#changed all email address to go through python.org
[python/dscho.git] / Modules / posixmodule.c
blob3d4bdcf9eae65db935a292cb746c9dc1e53dd1b5
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* POSIX module implementation */
27 /* This file is also used for Windows NT. In that case the module
28 actually calls itself 'nt', not 'posix', and a few functions are
29 either unimplemented or implemented differently. The source
30 assumes that for Windows NT, the macro 'NT' is defined independent
31 of the compiler used. Different compilers define their own feature
32 test macro, e.g. '__BORLANDC__' or '_MSCVER'. */
34 /* For MS-DOS and Windows 3.x, use ../Dos/dosmodule.c */
36 #include "allobjects.h"
37 #include "modsupport.h"
38 #include "ceval.h"
40 #include <string.h>
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #ifdef HAVE_SYS_WAIT_H
45 #include <sys/wait.h> /* For WNOHANG */
46 #endif
48 #include "mytime.h" /* For clock_t on some systems */
50 #ifdef HAVE_FCNTL_H
51 #include <fcntl.h>
52 #endif /* HAVE_FCNTL_H */
54 #ifndef NT
55 #define HAVE_FORK 1
56 #endif
58 #if !defined(NT) || defined(__BORLANDC__)
59 /* Unix functions that the configure script doesn't check for
60 and that aren't easily available under NT except with Borland C */
61 #define HAVE_GETEGID 1
62 #define HAVE_GETEUID 1
63 #define HAVE_GETGID 1
64 #define HAVE_GETPPID 1
65 #define HAVE_GETUID 1
66 #define HAVE_KILL 1
67 #define HAVE_WAIT 1
68 #define HAVE_OPENDIR 1
69 #define HAVE_PIPE 1
70 #define HAVE_GETCWD 1
71 #endif
73 #ifndef NT
75 #ifdef HAVE_UNISTD_H
76 #include <unistd.h>
77 #endif
79 #ifdef NeXT
80 /* NeXT's <unistd.h> and <utime.h> aren't worth much */
81 #undef HAVE_UNISTD_H
82 #undef HAVE_UTIME_H
83 /* #undef HAVE_GETCWD */
84 #endif
86 #ifdef HAVE_UNISTD_H
87 /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
88 extern int rename();
89 extern int pclose();
90 extern int lstat();
91 extern int symlink();
92 #else /* !HAVE_UNISTD_H */
93 extern int mkdir PROTO((const char *, mode_t));
94 extern int chdir PROTO((const char *));
95 extern int rmdir PROTO((const char *));
96 extern int chmod PROTO((const char *, mode_t));
97 extern int chown PROTO((const char *, uid_t, gid_t));
98 extern char *getcwd PROTO((char *, int));
99 extern char *strerror PROTO((int));
100 extern int link PROTO((const char *, const char *));
101 extern int rename PROTO((const char *, const char *));
102 extern int stat PROTO((const char *, struct stat *));
103 extern int unlink PROTO((const char *));
104 extern int pclose PROTO((FILE *));
105 #ifdef HAVE_SYMLINK
106 extern int symlink PROTO((const char *, const char *));
107 #endif /* HAVE_SYMLINK */
108 #ifdef HAVE_LSTAT
109 extern int lstat PROTO((const char *, struct stat *));
110 #endif /* HAVE_LSTAT */
111 #endif /* !HAVE_UNISTD_H */
113 #endif /* !NT */
115 #ifdef HAVE_UTIME_H
116 #include <utime.h>
117 #endif /* HAVE_UTIME_H */
119 #ifdef HAVE_SYS_UTIME_H
120 #include <sys/utime.h>
121 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
122 #endif /* HAVE_SYS_UTIME_H */
124 #ifdef HAVE_SYS_TIMES_H
125 #include <sys/times.h>
126 #endif /* HAVE_SYS_TIMES_H */
128 #ifdef HAVE_SYS_PARAM_H
129 #include <sys/param.h>
130 #endif /* HAVE_SYS_PARAM_H */
132 #ifdef HAVE_SYS_UTSNAME_H
133 #include <sys/utsname.h>
134 #endif /* HAVE_SYS_UTSNAME_H */
136 #ifndef MAXPATHLEN
137 #define MAXPATHLEN 1024
138 #endif /* MAXPATHLEN */
140 #ifdef HAVE_DIRENT_H
141 #include <dirent.h>
142 #define NAMLEN(dirent) strlen((dirent)->d_name)
143 #else
144 #define dirent direct
145 #define NAMLEN(dirent) (dirent)->d_namlen
146 #ifdef HAVE_SYS_NDIR_H
147 #include <sys/ndir.h>
148 #endif
149 #ifdef HAVE_SYS_DIR_H
150 #include <sys/dir.h>
151 #endif
152 #ifdef HAVE_NDIR_H
153 #include <ndir.h>
154 #endif
155 #endif
157 #ifdef NT
158 #include <direct.h>
159 #include <io.h>
160 #include <process.h>
161 #include <windows.h>
162 #define popen _popen
163 #define pclose _pclose
164 #endif /* NT */
166 #ifdef OS2
167 #include <io.h>
168 #endif /* OS2 */
170 /* Return a dictionary corresponding to the POSIX environment table */
172 #ifndef NT
173 extern char **environ;
174 #endif /* !NT */
176 static object *
177 convertenviron()
179 object *d;
180 char **e;
181 d = newdictobject();
182 if (d == NULL)
183 return NULL;
184 if (environ == NULL)
185 return d;
186 /* XXX This part ignores errors */
187 for (e = environ; *e != NULL; e++) {
188 object *v;
189 char *p = strchr(*e, '=');
190 if (p == NULL)
191 continue;
192 v = newstringobject(p+1);
193 if (v == NULL)
194 continue;
195 *p = '\0';
196 (void) dictinsert(d, *e, v);
197 *p = '=';
198 DECREF(v);
200 return d;
204 static object *PosixError; /* Exception posix.error */
206 /* Set a POSIX-specific error from errno, and return NULL */
208 static object * posix_error()
210 return err_errno(PosixError);
214 /* POSIX generic methods */
216 static object *
217 posix_1str(args, func)
218 object *args;
219 int (*func) FPROTO((const char *));
221 char *path1;
222 int res;
223 if (!getargs(args, "s", &path1))
224 return NULL;
225 BGN_SAVE
226 res = (*func)(path1);
227 END_SAVE
228 if (res < 0)
229 return posix_error();
230 INCREF(None);
231 return None;
234 static object *
235 posix_2str(args, func)
236 object *args;
237 int (*func) FPROTO((const char *, const char *));
239 char *path1, *path2;
240 int res;
241 if (!getargs(args, "(ss)", &path1, &path2))
242 return NULL;
243 BGN_SAVE
244 res = (*func)(path1, path2);
245 END_SAVE
246 if (res < 0)
247 return posix_error();
248 INCREF(None);
249 return None;
252 static object *
253 posix_strint(args, func)
254 object *args;
255 int (*func) FPROTO((const char *, int));
257 char *path;
258 int i;
259 int res;
260 if (!getargs(args, "(si)", &path, &i))
261 return NULL;
262 BGN_SAVE
263 res = (*func)(path, i);
264 END_SAVE
265 if (res < 0)
266 return posix_error();
267 INCREF(None);
268 return None;
271 static object *
272 posix_strintint(args, func)
273 object *args;
274 int (*func) FPROTO((const char *, int, int));
276 char *path;
277 int i,i2;
278 int res;
279 if (!getargs(args, "(sii)", &path, &i, &i2))
280 return NULL;
281 BGN_SAVE
282 res = (*func)(path, i, i2);
283 END_SAVE
284 if (res < 0)
285 return posix_error();
286 INCREF(None);
287 return None;
290 static object *
291 posix_do_stat(self, args, statfunc)
292 object *self;
293 object *args;
294 int (*statfunc) FPROTO((const char *, struct stat *));
296 struct stat st;
297 char *path;
298 int res;
299 if (!getargs(args, "s", &path))
300 return NULL;
301 BGN_SAVE
302 res = (*statfunc)(path, &st);
303 END_SAVE
304 if (res != 0)
305 return posix_error();
306 return mkvalue("(llllllllll)",
307 (long)st.st_mode,
308 (long)st.st_ino,
309 (long)st.st_dev,
310 (long)st.st_nlink,
311 (long)st.st_uid,
312 (long)st.st_gid,
313 (long)st.st_size,
314 (long)st.st_atime,
315 (long)st.st_mtime,
316 (long)st.st_ctime);
320 /* POSIX methods */
322 static object *
323 posix_chdir(self, args)
324 object *self;
325 object *args;
327 return posix_1str(args, chdir);
330 static object *
331 posix_chmod(self, args)
332 object *self;
333 object *args;
335 return posix_strint(args, chmod);
338 #ifdef HAVE_CHOWN
339 static object *
340 posix_chown(self, args)
341 object *self;
342 object *args;
344 return posix_strintint(args, chown);
346 #endif /* HAVE_CHOWN */
348 #ifdef HAVE_GETCWD
349 static object *
350 posix_getcwd(self, args)
351 object *self;
352 object *args;
354 char buf[1026];
355 char *res;
356 if (!getnoarg(args))
357 return NULL;
358 BGN_SAVE
359 res = getcwd(buf, sizeof buf);
360 END_SAVE
361 if (res == NULL)
362 return posix_error();
363 return newstringobject(buf);
365 #endif
367 #ifdef HAVE_LINK
368 static object *
369 posix_link(self, args)
370 object *self;
371 object *args;
373 return posix_2str(args, link);
375 #endif /* HAVE_LINK */
377 static object *
378 posix_listdir(self, args)
379 object *self;
380 object *args;
382 #if defined(NT) && !defined(HAVE_OPENDIR)
384 char *name;
385 int len;
386 object *d, *v;
387 HANDLE hFindFile;
388 WIN32_FIND_DATA FileData;
389 char namebuf[MAX_PATH+5];
391 if (!getargs(args, "s#", &name, &len))
392 return NULL;
393 if (len >= MAX_PATH) {
394 err_setstr(ValueError, "path too long");
395 return NULL;
397 strcpy(namebuf, name);
398 if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
399 namebuf[len++] = '/';
400 strcpy(namebuf + len, "*.*");
402 if ((d = newlistobject(0)) == NULL)
403 return NULL;
405 hFindFile = FindFirstFile(namebuf, &FileData);
406 if (hFindFile == INVALID_HANDLE_VALUE) {
407 errno = GetLastError();
408 return posix_error();
410 do {
411 v = newstringobject(FileData.cFileName);
412 if (v == NULL) {
413 DECREF(d);
414 d = NULL;
415 break;
417 if (addlistitem(d, v) != 0) {
418 DECREF(v);
419 DECREF(d);
420 d = NULL;
421 break;
423 DECREF(v);
424 } while (FindNextFile(hFindFile, &FileData) == TRUE);
426 if (FindClose(hFindFile) == FALSE) {
427 errno = GetLastError();
428 return posix_error();
431 return d;
433 #else /* !NT */
435 char *name;
436 object *d, *v;
437 DIR *dirp;
438 struct dirent *ep;
439 if (!getargs(args, "s", &name))
440 return NULL;
441 BGN_SAVE
442 if ((dirp = opendir(name)) == NULL) {
443 RET_SAVE
444 return posix_error();
446 if ((d = newlistobject(0)) == NULL) {
447 closedir(dirp);
448 RET_SAVE
449 return NULL;
451 while ((ep = readdir(dirp)) != NULL) {
452 v = newsizedstringobject(ep->d_name, NAMLEN(ep));
453 if (v == NULL) {
454 DECREF(d);
455 d = NULL;
456 break;
458 if (addlistitem(d, v) != 0) {
459 DECREF(v);
460 DECREF(d);
461 d = NULL;
462 break;
464 DECREF(v);
466 closedir(dirp);
467 END_SAVE
469 return d;
471 #endif /* !NT */
474 static object *
475 posix_mkdir(self, args)
476 object *self;
477 object *args;
479 return posix_strint(args, mkdir);
482 #ifdef HAVE_NICE
483 static object *
484 posix_nice(self, args)
485 object *self;
486 object *args;
488 int increment, value;
490 if (!getargs(args, "i", &increment))
491 return NULL;
492 value = nice(increment);
493 if (value == -1)
494 return posix_error();
495 return newintobject((long) value);
497 #endif /* HAVE_NICE */
499 static object *
500 posix_rename(self, args)
501 object *self;
502 object *args;
504 return posix_2str(args, rename);
507 static object *
508 posix_rmdir(self, args)
509 object *self;
510 object *args;
512 return posix_1str(args, rmdir);
515 static object *
516 posix_stat(self, args)
517 object *self;
518 object *args;
520 return posix_do_stat(self, args, stat);
523 static object *
524 posix_system(self, args)
525 object *self;
526 object *args;
528 char *command;
529 long sts;
530 if (!getargs(args, "s", &command))
531 return NULL;
532 BGN_SAVE
533 sts = system(command);
534 END_SAVE
535 return newintobject(sts);
538 static object *
539 posix_umask(self, args)
540 object *self;
541 object *args;
543 int i;
544 if (!getintarg(args, &i))
545 return NULL;
546 i = umask(i);
547 if (i < 0)
548 return posix_error();
549 return newintobject((long)i);
552 static object *
553 posix_unlink(self, args)
554 object *self;
555 object *args;
557 return posix_1str(args, unlink);
560 #ifdef HAVE_UNAME
561 static object *
562 posix_uname(self, args)
563 object *self;
564 object *args;
566 struct utsname u;
567 object *v;
568 int res;
569 if (!getnoarg(args))
570 return NULL;
571 BGN_SAVE
572 res = uname(&u);
573 END_SAVE
574 if (res < 0)
575 return posix_error();
576 return mkvalue("(sssss)",
577 u.sysname,
578 u.nodename,
579 u.release,
580 u.version,
581 u.machine);
583 #endif /* HAVE_UNAME */
585 static object *
586 posix_utime(self, args)
587 object *self;
588 object *args;
590 char *path;
591 long atime, mtime;
592 int res;
594 #ifdef HAVE_UTIME_H
595 struct utimbuf buf;
596 #define ATIME buf.actime
597 #define MTIME buf.modtime
598 #define UTIME_ARG &buf
599 #else /* HAVE_UTIME_H */
600 time_t buf[2];
601 #define ATIME buf[0]
602 #define MTIME buf[1]
603 #define UTIME_ARG buf
604 #endif /* HAVE_UTIME_H */
606 if (!getargs(args, "(s(ll))", &path, &atime, &mtime))
607 return NULL;
608 ATIME = atime;
609 MTIME = mtime;
610 BGN_SAVE
611 res = utime(path, UTIME_ARG);
612 END_SAVE
613 if (res < 0)
614 return posix_error();
615 INCREF(None);
616 return None;
617 #undef UTIME_ARG
618 #undef ATIME
619 #undef MTIME
623 /* Process operations */
625 static object *
626 posix__exit(self, args)
627 object *self;
628 object *args;
630 int sts;
631 if (!getintarg(args, &sts))
632 return NULL;
633 _exit(sts);
634 /* NOTREACHED */
637 static object *
638 posix_execv(self, args)
639 object *self;
640 object *args;
642 char *path;
643 object *argv;
644 char **argvlist;
645 int i, argc;
646 object *(*getitem) PROTO((object *, int));
648 /* execv has two arguments: (path, argv), where
649 argv is a list or tuple of strings. */
651 if (!getargs(args, "(sO)", &path, &argv))
652 return NULL;
653 if (is_listobject(argv)) {
654 argc = getlistsize(argv);
655 getitem = getlistitem;
657 else if (is_tupleobject(argv)) {
658 argc = gettuplesize(argv);
659 getitem = gettupleitem;
661 else {
662 badarg:
663 err_badarg();
664 return NULL;
667 argvlist = NEW(char *, argc+1);
668 if (argvlist == NULL)
669 return NULL;
670 for (i = 0; i < argc; i++) {
671 if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
672 DEL(argvlist);
673 goto badarg;
676 argvlist[argc] = NULL;
678 #ifdef BAD_EXEC_PROTOTYPES
679 execv(path, (const char **) argvlist);
680 #else /* BAD_EXEC_PROTOTYPES */
681 execv(path, argvlist);
682 #endif /* BAD_EXEC_PROTOTYPES */
684 /* If we get here it's definitely an error */
686 DEL(argvlist);
687 return posix_error();
690 static object *
691 posix_execve(self, args)
692 object *self;
693 object *args;
695 char *path;
696 object *argv, *env;
697 char **argvlist;
698 char **envlist;
699 object *key, *val;
700 int i, pos, argc, envc;
701 object *(*getitem) PROTO((object *, int));
703 /* execve has three arguments: (path, argv, env), where
704 argv is a list or tuple of strings and env is a dictionary
705 like posix.environ. */
707 if (!getargs(args, "(sOO)", &path, &argv, &env))
708 return NULL;
709 if (is_listobject(argv)) {
710 argc = getlistsize(argv);
711 getitem = getlistitem;
713 else if (is_tupleobject(argv)) {
714 argc = gettuplesize(argv);
715 getitem = gettupleitem;
717 else {
718 err_setstr(TypeError, "argv must be tuple or list");
719 return NULL;
721 if (!is_dictobject(env)) {
722 err_setstr(TypeError, "env must be dictionary");
723 return NULL;
726 argvlist = NEW(char *, argc+1);
727 if (argvlist == NULL) {
728 err_nomem();
729 return NULL;
731 for (i = 0; i < argc; i++) {
732 if (!getargs((*getitem)(argv, i),
733 "s;argv must be list of strings",
734 &argvlist[i])) {
735 goto fail_1;
738 argvlist[argc] = NULL;
740 i = getmappingsize(env);
741 envlist = NEW(char *, i + 1);
742 if (envlist == NULL) {
743 err_nomem();
744 goto fail_1;
746 pos = 0;
747 envc = 0;
748 while (mappinggetnext(env, &pos, &key, &val)) {
749 char *p, *k, *v;
750 if (!getargs(key, "s;non-string key in env", &k) ||
751 !getargs(val, "s;non-string value in env", &v)) {
752 goto fail_2;
754 p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
755 if (p == NULL) {
756 err_nomem();
757 goto fail_2;
759 sprintf(p, "%s=%s", k, v);
760 envlist[envc++] = p;
762 envlist[envc] = 0;
765 #ifdef BAD_EXEC_PROTOTYPES
766 execve(path, (const char **)argvlist, envlist);
767 #else /* BAD_EXEC_PROTOTYPES */
768 execve(path, argvlist, envlist);
769 #endif /* BAD_EXEC_PROTOTYPES */
771 /* If we get here it's definitely an error */
773 (void) posix_error();
775 fail_2:
776 while (--envc >= 0)
777 DEL(envlist[envc]);
778 DEL(envlist);
779 fail_1:
780 DEL(argvlist);
782 return NULL;
785 #ifdef HAVE_FORK
786 static object *
787 posix_fork(self, args)
788 object *self;
789 object *args;
791 int pid;
792 if (!getnoarg(args))
793 return NULL;
794 pid = fork();
795 if (pid == -1)
796 return posix_error();
797 return newintobject((long)pid);
799 #endif
801 #ifdef HAVE_GETEGID
802 static object *
803 posix_getegid(self, args)
804 object *self;
805 object *args;
807 if (!getnoarg(args))
808 return NULL;
809 return newintobject((long)getegid());
811 #endif
813 #ifdef HAVE_GETEUID
814 static object *
815 posix_geteuid(self, args)
816 object *self;
817 object *args;
819 if (!getnoarg(args))
820 return NULL;
821 return newintobject((long)geteuid());
823 #endif
825 #ifdef HAVE_GETGID
826 static object *
827 posix_getgid(self, args)
828 object *self;
829 object *args;
831 if (!getnoarg(args))
832 return NULL;
833 return newintobject((long)getgid());
835 #endif
837 static object *
838 posix_getpid(self, args)
839 object *self;
840 object *args;
842 if (!getnoarg(args))
843 return NULL;
844 return newintobject((long)getpid());
847 #ifdef HAVE_GETPGRP
848 static object *
849 posix_getpgrp(self, args)
850 object *self;
851 object *args;
853 if (!getnoarg(args))
854 return NULL;
855 #ifdef GETPGRP_HAVE_ARG
856 return newintobject((long)getpgrp(0));
857 #else /* GETPGRP_HAVE_ARG */
858 return newintobject((long)getpgrp());
859 #endif /* GETPGRP_HAVE_ARG */
861 #endif /* HAVE_GETPGRP */
863 #ifdef HAVE_SETPGRP
864 static object *
865 posix_setpgrp(self, args)
866 object *self;
867 object *args;
869 if (!getnoarg(args))
870 return NULL;
871 #ifdef SETPGRP_HAVE_ARG
872 if (setpgrp(0, 0) < 0)
873 #else /* SETPGRP_HAVE_ARG */
874 if (setpgrp() < 0)
875 #endif /* SETPGRP_HAVE_ARG */
876 return posix_error();
877 INCREF(None);
878 return None;
881 #endif /* HAVE_SETPGRP */
883 #ifdef HAVE_GETPPID
884 static object *
885 posix_getppid(self, args)
886 object *self;
887 object *args;
889 if (!getnoarg(args))
890 return NULL;
891 return newintobject((long)getppid());
893 #endif
895 #ifdef HAVE_GETUID
896 static object *
897 posix_getuid(self, args)
898 object *self;
899 object *args;
901 if (!getnoarg(args))
902 return NULL;
903 return newintobject((long)getuid());
905 #endif
907 #ifdef HAVE_KILL
908 static object *
909 posix_kill(self, args)
910 object *self;
911 object *args;
913 int pid, sig;
914 if (!getargs(args, "(ii)", &pid, &sig))
915 return NULL;
916 if (kill(pid, sig) == -1)
917 return posix_error();
918 INCREF(None);
919 return None;
921 #endif
923 static object *
924 posix_popen(self, args)
925 object *self;
926 object *args;
928 char *name;
929 char *mode = "r";
930 int bufsize = -1;
931 FILE *fp;
932 object *f;
933 if (!newgetargs(args, "s|si", &name, &mode, &bufsize))
934 return NULL;
935 BGN_SAVE
936 fp = popen(name, mode);
937 END_SAVE
938 if (fp == NULL)
939 return posix_error();
940 f = newopenfileobject(fp, name, mode, pclose);
941 if (f != NULL)
942 setfilebufsize(f, bufsize);
943 return f;
946 #ifdef HAVE_SETUID
947 static object *
948 posix_setuid(self, args)
949 object *self;
950 object *args;
952 int uid;
953 if (!getargs(args, "i", &uid))
954 return NULL;
955 if (setuid(uid) < 0)
956 return posix_error();
957 INCREF(None);
958 return None;
960 #endif /* HAVE_SETUID */
962 #ifdef HAVE_SETGID
963 static object *
964 posix_setgid(self, args)
965 object *self;
966 object *args;
968 int gid;
969 if (!getargs(args, "i", &gid))
970 return NULL;
971 if (setgid(gid) < 0)
972 return posix_error();
973 INCREF(None);
974 return None;
976 #endif /* HAVE_SETGID */
978 #ifdef HAVE_WAITPID
979 static object *
980 posix_waitpid(self, args)
981 object *self;
982 object *args;
984 int pid, options, sts;
985 if (!getargs(args, "(ii)", &pid, &options))
986 return NULL;
987 BGN_SAVE
988 pid = waitpid(pid, &sts, options);
989 END_SAVE
990 if (pid == -1)
991 return posix_error();
992 else
993 return mkvalue("ii", pid, sts);
995 #endif /* HAVE_WAITPID */
997 #ifdef HAVE_WAIT
998 static object *
999 posix_wait(self, args)
1000 object *self;
1001 object *args;
1003 int pid, sts;
1004 BGN_SAVE
1005 pid = wait(&sts);
1006 END_SAVE
1007 if (pid == -1)
1008 return posix_error();
1009 else
1010 return mkvalue("ii", pid, sts);
1012 #endif
1014 static object *
1015 posix_lstat(self, args)
1016 object *self;
1017 object *args;
1019 #ifdef HAVE_LSTAT
1020 return posix_do_stat(self, args, lstat);
1021 #else /* !HAVE_LSTAT */
1022 return posix_do_stat(self, args, stat);
1023 #endif /* !HAVE_LSTAT */
1026 #ifdef HAVE_READLINK
1027 static object *
1028 posix_readlink(self, args)
1029 object *self;
1030 object *args;
1032 char buf[MAXPATHLEN];
1033 char *path;
1034 int n;
1035 if (!getargs(args, "s", &path))
1036 return NULL;
1037 BGN_SAVE
1038 n = readlink(path, buf, (int) sizeof buf);
1039 END_SAVE
1040 if (n < 0)
1041 return posix_error();
1042 return newsizedstringobject(buf, n);
1044 #endif /* HAVE_READLINK */
1046 #ifdef HAVE_SYMLINK
1047 static object *
1048 posix_symlink(self, args)
1049 object *self;
1050 object *args;
1052 return posix_2str(args, symlink);
1054 #endif /* HAVE_SYMLINK */
1056 #ifdef HAVE_TIMES
1057 #ifndef HZ
1058 #define HZ 60 /* Universal constant :-) */
1059 #endif /* HZ */
1060 static object *
1061 posix_times(self, args)
1062 object *self;
1063 object *args;
1065 struct tms t;
1066 clock_t c;
1067 if (!getnoarg(args))
1068 return NULL;
1069 errno = 0;
1070 c = times(&t);
1071 if (c == (clock_t) -1)
1072 return posix_error();
1073 return mkvalue("dddd",
1074 (double)t.tms_utime / HZ,
1075 (double)t.tms_stime / HZ,
1076 (double)t.tms_cutime / HZ,
1077 (double)t.tms_cstime / HZ);
1079 #endif /* HAVE_TIMES */
1080 #if defined(NT) && !defined(HAVE_TIMES)
1081 #define HAVE_TIMES /* so the method table will pick it up */
1082 static object *
1083 posix_times(self, args)
1084 object *self;
1085 object *args;
1087 FILETIME create, exit, kernel, user;
1088 HANDLE hProc;
1089 if (!getnoarg(args))
1090 return NULL;
1091 hProc = GetCurrentProcess();
1092 GetProcessTimes(hProc,&create, &exit, &kernel, &user);
1093 return mkvalue("dddd",
1094 (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6,
1095 (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
1096 (double)0,
1097 (double)0);
1099 #endif /* NT */
1101 #ifdef HAVE_SETSID
1102 static object *
1103 posix_setsid(self, args)
1104 object *self;
1105 object *args;
1107 if (!getnoarg(args))
1108 return NULL;
1109 if (setsid() < 0)
1110 return posix_error();
1111 INCREF(None);
1112 return None;
1114 #endif /* HAVE_SETSID */
1116 #ifdef HAVE_SETPGID
1117 static object *
1118 posix_setpgid(self, args)
1119 object *self;
1120 object *args;
1122 int pid, pgrp;
1123 if (!getargs(args, "(ii)", &pid, &pgrp))
1124 return NULL;
1125 if (setpgid(pid, pgrp) < 0)
1126 return posix_error();
1127 INCREF(None);
1128 return None;
1130 #endif /* HAVE_SETPGID */
1132 #ifdef HAVE_TCGETPGRP
1133 static object *
1134 posix_tcgetpgrp(self, args)
1135 object *self;
1136 object *args;
1138 int fd, pgid;
1139 if (!getargs(args, "i", &fd))
1140 return NULL;
1141 pgid = tcgetpgrp(fd);
1142 if (pgid < 0)
1143 return posix_error();
1144 return newintobject((long)pgid);
1146 #endif /* HAVE_TCGETPGRP */
1148 #ifdef HAVE_TCSETPGRP
1149 static object *
1150 posix_tcsetpgrp(self, args)
1151 object *self;
1152 object *args;
1154 int fd, pgid;
1155 if (!getargs(args, "(ii)", &fd, &pgid))
1156 return NULL;
1157 if (tcsetpgrp(fd, pgid) < 0)
1158 return posix_error();
1159 INCREF(None);
1160 return None;
1162 #endif /* HAVE_TCSETPGRP */
1164 /* Functions acting on file descriptors */
1166 static object *
1167 posix_open(self, args)
1168 object *self;
1169 object *args;
1171 char *file;
1172 int flag;
1173 int mode = 0777;
1174 int fd;
1175 if (!getargs(args, "(si)", &file, &flag)) {
1176 err_clear();
1177 if (!getargs(args, "(sii)", &file, &flag, &mode))
1178 return NULL;
1180 BGN_SAVE
1181 fd = open(file, flag, mode);
1182 END_SAVE
1183 if (fd < 0)
1184 return posix_error();
1185 return newintobject((long)fd);
1188 static object *
1189 posix_close(self, args)
1190 object *self;
1191 object *args;
1193 int fd, res;
1194 if (!getargs(args, "i", &fd))
1195 return NULL;
1196 BGN_SAVE
1197 res = close(fd);
1198 END_SAVE
1199 if (res < 0)
1200 return posix_error();
1201 INCREF(None);
1202 return None;
1205 static object *
1206 posix_dup(self, args)
1207 object *self;
1208 object *args;
1210 int fd;
1211 if (!getargs(args, "i", &fd))
1212 return NULL;
1213 BGN_SAVE
1214 fd = dup(fd);
1215 END_SAVE
1216 if (fd < 0)
1217 return posix_error();
1218 return newintobject((long)fd);
1221 static object *
1222 posix_dup2(self, args)
1223 object *self;
1224 object *args;
1226 int fd, fd2, res;
1227 if (!getargs(args, "(ii)", &fd, &fd2))
1228 return NULL;
1229 BGN_SAVE
1230 res = dup2(fd, fd2);
1231 END_SAVE
1232 if (res < 0)
1233 return posix_error();
1234 INCREF(None);
1235 return None;
1238 static object *
1239 posix_lseek(self, args)
1240 object *self;
1241 object *args;
1243 int fd, how;
1244 long pos, res;
1245 if (!getargs(args, "(ili)", &fd, &pos, &how))
1246 return NULL;
1247 #ifdef SEEK_SET
1248 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
1249 switch (how) {
1250 case 0: how = SEEK_SET; break;
1251 case 1: how = SEEK_CUR; break;
1252 case 2: how = SEEK_END; break;
1254 #endif /* SEEK_END */
1255 BGN_SAVE
1256 res = lseek(fd, pos, how);
1257 END_SAVE
1258 if (res < 0)
1259 return posix_error();
1260 return newintobject(res);
1263 static object *
1264 posix_read(self, args)
1265 object *self;
1266 object *args;
1268 int fd, size;
1269 object *buffer;
1270 if (!getargs(args, "(ii)", &fd, &size))
1271 return NULL;
1272 buffer = newsizedstringobject((char *)NULL, size);
1273 if (buffer == NULL)
1274 return NULL;
1275 BGN_SAVE
1276 size = read(fd, getstringvalue(buffer), size);
1277 END_SAVE
1278 if (size < 0) {
1279 DECREF(buffer);
1280 return posix_error();
1282 resizestring(&buffer, size);
1283 return buffer;
1286 static object *
1287 posix_write(self, args)
1288 object *self;
1289 object *args;
1291 int fd, size;
1292 char *buffer;
1293 if (!getargs(args, "(is#)", &fd, &buffer, &size))
1294 return NULL;
1295 BGN_SAVE
1296 size = write(fd, buffer, size);
1297 END_SAVE
1298 if (size < 0)
1299 return posix_error();
1300 return newintobject((long)size);
1303 static object *
1304 posix_fstat(self, args)
1305 object *self;
1306 object *args;
1308 int fd;
1309 struct stat st;
1310 int res;
1311 if (!getargs(args, "i", &fd))
1312 return NULL;
1313 BGN_SAVE
1314 res = fstat(fd, &st);
1315 END_SAVE
1316 if (res != 0)
1317 return posix_error();
1318 return mkvalue("(llllllllll)",
1319 (long)st.st_mode,
1320 (long)st.st_ino,
1321 (long)st.st_dev,
1322 (long)st.st_nlink,
1323 (long)st.st_uid,
1324 (long)st.st_gid,
1325 (long)st.st_size,
1326 (long)st.st_atime,
1327 (long)st.st_mtime,
1328 (long)st.st_ctime);
1331 static object *
1332 posix_fdopen(self, args)
1333 object *self;
1334 object *args;
1336 extern int fclose PROTO((FILE *));
1337 int fd;
1338 char *mode = "r";
1339 int bufsize = -1;
1340 FILE *fp;
1341 object *f;
1342 if (!newgetargs(args, "i|si", &fd, &mode, &bufsize))
1343 return NULL;
1344 BGN_SAVE
1345 fp = fdopen(fd, mode);
1346 END_SAVE
1347 if (fp == NULL)
1348 return posix_error();
1349 f = newopenfileobject(fp, "(fdopen)", mode, fclose);
1350 if (f != NULL)
1351 setfilebufsize(f, bufsize);
1352 return f;
1355 static object *
1356 posix_pipe(self, args)
1357 object *self;
1358 object *args;
1360 #if !defined(NT) || defined(HAVE_PIPE)
1361 int fds[2];
1362 int res;
1363 if (!getargs(args, ""))
1364 return NULL;
1365 BGN_SAVE
1366 res = pipe(fds);
1367 END_SAVE
1368 if (res != 0)
1369 return posix_error();
1370 return mkvalue("(ii)", fds[0], fds[1]);
1371 #else /* NT */
1372 HANDLE read, write;
1373 BOOL ok;
1374 if (!getargs(args, ""))
1375 return NULL;
1376 BGN_SAVE
1377 ok = CreatePipe( &read, &write, NULL, 0);
1378 END_SAVE
1379 if (!ok)
1380 return posix_error();
1381 return mkvalue("(ii)", read, write);
1382 #endif /* NT */
1385 static struct methodlist posix_methods[] = {
1386 {"chdir", posix_chdir},
1387 {"chmod", posix_chmod},
1388 #ifdef HAVE_CHOWN
1389 {"chown", posix_chown},
1390 #endif /* HAVE_CHOWN */
1391 #ifdef HAVE_GETCWD
1392 {"getcwd", posix_getcwd},
1393 #endif
1394 #ifdef HAVE_LINK
1395 {"link", posix_link},
1396 #endif /* HAVE_LINK */
1397 {"listdir", posix_listdir},
1398 {"lstat", posix_lstat},
1399 {"mkdir", posix_mkdir},
1400 #ifdef HAVE_NICE
1401 {"nice", posix_nice},
1402 #endif /* HAVE_NICE */
1403 #ifdef HAVE_READLINK
1404 {"readlink", posix_readlink},
1405 #endif /* HAVE_READLINK */
1406 {"rename", posix_rename},
1407 {"rmdir", posix_rmdir},
1408 {"stat", posix_stat},
1409 #ifdef HAVE_SYMLINK
1410 {"symlink", posix_symlink},
1411 #endif /* HAVE_SYMLINK */
1412 {"system", posix_system},
1413 {"umask", posix_umask},
1414 #ifdef HAVE_UNAME
1415 {"uname", posix_uname},
1416 #endif /* HAVE_UNAME */
1417 {"unlink", posix_unlink},
1418 {"utime", posix_utime},
1419 #ifdef HAVE_TIMES
1420 {"times", posix_times},
1421 #endif /* HAVE_TIMES */
1422 {"_exit", posix__exit},
1423 {"execv", posix_execv},
1424 {"execve", posix_execve},
1425 #ifdef HAVE_FORK
1426 {"fork", posix_fork},
1427 #endif /* HAVE_FORK */
1428 #ifdef HAVE_GETEGID
1429 {"getegid", posix_getegid},
1430 #endif /* HAVE_GETEGID */
1431 #ifdef HAVE_GETEUID
1432 {"geteuid", posix_geteuid},
1433 #endif /* HAVE_GETEUID */
1434 #ifdef HAVE_GETGID
1435 {"getgid", posix_getgid},
1436 #endif /* HAVE_GETGID */
1437 {"getpid", posix_getpid},
1438 #ifdef HAVE_GETPGRP
1439 {"getpgrp", posix_getpgrp},
1440 #endif /* HAVE_GETPGRP */
1441 #ifdef HAVE_GETPPID
1442 {"getppid", posix_getppid},
1443 #endif /* HAVE_GETPPID */
1444 #ifdef HAVE_GETUID
1445 {"getuid", posix_getuid},
1446 #endif /* HAVE_GETUID */
1447 #ifdef HAVE_KILL
1448 {"kill", posix_kill},
1449 #endif /* HAVE_KILL */
1450 {"popen", posix_popen, 1},
1451 #ifdef HAVE_SETUID
1452 {"setuid", posix_setuid},
1453 #endif /* HAVE_SETUID */
1454 #ifdef HAVE_SETGID
1455 {"setgid", posix_setgid},
1456 #endif /* HAVE_SETGID */
1457 #ifdef HAVE_SETPGRP
1458 {"setpgrp", posix_setpgrp},
1459 #endif /* HAVE_SETPGRP */
1460 #ifdef HAVE_WAIT
1461 {"wait", posix_wait},
1462 #endif /* HAVE_WAIT */
1463 #ifdef HAVE_WAITPID
1464 {"waitpid", posix_waitpid},
1465 #endif /* HAVE_WAITPID */
1466 #ifdef HAVE_SETSID
1467 {"setsid", posix_setsid},
1468 #endif /* HAVE_SETSID */
1469 #ifdef HAVE_SETPGID
1470 {"setpgid", posix_setpgid},
1471 #endif /* HAVE_SETPGID */
1472 #ifdef HAVE_TCGETPGRP
1473 {"tcgetpgrp", posix_tcgetpgrp},
1474 #endif /* HAVE_TCGETPGRP */
1475 #ifdef HAVE_TCSETPGRP
1476 {"tcsetpgrp", posix_tcsetpgrp},
1477 #endif /* HAVE_TCSETPGRP */
1478 {"open", posix_open},
1479 {"close", posix_close},
1480 {"dup", posix_dup},
1481 {"dup2", posix_dup2},
1482 {"lseek", posix_lseek},
1483 {"read", posix_read},
1484 {"write", posix_write},
1485 {"fstat", posix_fstat},
1486 {"fdopen", posix_fdopen, 1},
1487 {"pipe", posix_pipe},
1488 {NULL, NULL} /* Sentinel */
1492 #ifdef NT
1493 void
1494 initnt()
1496 object *m, *d, *v;
1498 m = initmodule("nt", posix_methods);
1499 d = getmoduledict(m);
1501 /* Initialize nt.environ dictionary */
1502 v = convertenviron();
1503 if (v == NULL || dictinsert(d, "environ", v) != 0)
1504 fatal("can't define nt.environ");
1505 DECREF(v);
1507 /* Initialize nt.error exception */
1508 PosixError = newstringobject("nt.error");
1509 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1510 fatal("can't define nt.error");
1512 #else /* !NT */
1513 void
1514 initposix()
1516 object *m, *d, *v;
1518 m = initmodule("posix", posix_methods);
1519 d = getmoduledict(m);
1521 /* Initialize posix.environ dictionary */
1522 v = convertenviron();
1523 if (v == NULL || dictinsert(d, "environ", v) != 0)
1524 fatal("can't define posix.environ");
1525 DECREF(v);
1527 #ifdef WNOHANG
1528 /* Export WNOHANG symbol */
1529 v = newintobject((long)WNOHANG);
1530 if (v == NULL || dictinsert(d, "WNOHANG", v) != 0)
1531 fatal("can't define posix.WNOHANG");
1532 DECREF(v);
1533 #endif
1535 /* Initialize posix.error exception */
1536 PosixError = newstringobject("posix.error");
1537 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1538 fatal("can't define posix.error");
1540 #endif /* !NT */