Use py_resource module
[python/dscho.git] / Modules / posixmodule.c
blob338a40c0d2504297de72b059f4e8a853a6492324
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 and MS-Win. 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 '_MSC_VER'. */
34 /* See also ../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 /* Various compilers have only certain posix functions */
55 #ifdef __WATCOMC__ /* Watcom compiler */
56 #define HAVE_GETCWD 1
57 #define HAVE_OPENDIR 1
58 #define HAVE_SYSTEM 1
59 #if defined(__OS2__)
60 #define HAVE_EXECV 1
61 #define HAVE_WAIT 1
62 #endif
63 #include <process.h>
64 #else
65 #ifdef __BORLANDC__ /* Borland compiler */
66 #define HAVE_EXECV 1
67 #define HAVE_GETCWD 1
68 #define HAVE_GETEGID 1
69 #define HAVE_GETEUID 1
70 #define HAVE_GETGID 1
71 #define HAVE_GETPPID 1
72 #define HAVE_GETUID 1
73 #define HAVE_KILL 1
74 #define HAVE_OPENDIR 1
75 #define HAVE_PIPE 1
76 #define HAVE_POPEN 1
77 #define HAVE_SYSTEM 1
78 #define HAVE_WAIT 1
79 #else
80 #ifdef _MSC_VER /* Microsoft compiler */
81 #ifdef NT
82 #define HAVE_EXECV 1
83 #define HAVE_PIPE 1
84 #define HAVE_POPEN 1
85 #define HAVE_SYSTEM 1
86 #else /* 16-bit Windows */
87 #endif /* NT */
88 #else /* all other compilers */
89 /* Unix functions that the configure script doesn't check for */
90 #define HAVE_EXECV 1
91 #define HAVE_FORK 1
92 #define HAVE_GETCWD 1
93 #define HAVE_GETEGID 1
94 #define HAVE_GETEUID 1
95 #define HAVE_GETGID 1
96 #define HAVE_GETPPID 1
97 #define HAVE_GETUID 1
98 #define HAVE_KILL 1
99 #define HAVE_OPENDIR 1
100 #define HAVE_PIPE 1
101 #define HAVE_POPEN 1
102 #define HAVE_SYSTEM 1
103 #define HAVE_WAIT 1
104 #endif /* _MSC_VER */
105 #endif /* __BORLANDC__ */
106 #endif /* ! __WATCOMC__ */
108 #ifndef _MSC_VER
110 #ifdef HAVE_UNISTD_H
111 #include <unistd.h>
112 #endif
114 #ifdef NeXT
115 /* NeXT's <unistd.h> and <utime.h> aren't worth much */
116 #undef HAVE_UNISTD_H
117 #undef HAVE_UTIME_H
118 /* #undef HAVE_GETCWD */
119 #endif
121 #ifdef HAVE_UNISTD_H
122 /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
123 extern int rename();
124 extern int pclose();
125 extern int lstat();
126 extern int symlink();
127 #else /* !HAVE_UNISTD_H */
128 #if defined(__WATCOMC__)
129 extern int mkdir PROTO((const char *));
130 #else
131 extern int mkdir PROTO((const char *, mode_t));
132 #endif
133 extern int chdir PROTO((const char *));
134 extern int rmdir PROTO((const char *));
135 extern int chmod PROTO((const char *, mode_t));
136 extern int chown PROTO((const char *, uid_t, gid_t));
137 extern char *getcwd PROTO((char *, int));
138 extern char *strerror PROTO((int));
139 extern int link PROTO((const char *, const char *));
140 extern int rename PROTO((const char *, const char *));
141 extern int stat PROTO((const char *, struct stat *));
142 extern int unlink PROTO((const char *));
143 extern int pclose PROTO((FILE *));
144 #ifdef HAVE_SYMLINK
145 extern int symlink PROTO((const char *, const char *));
146 #endif /* HAVE_SYMLINK */
147 #ifdef HAVE_LSTAT
148 extern int lstat PROTO((const char *, struct stat *));
149 #endif /* HAVE_LSTAT */
150 #endif /* !HAVE_UNISTD_H */
152 #endif /* !_MSC_VER */
154 #ifdef HAVE_UTIME_H
155 #include <utime.h>
156 #endif /* HAVE_UTIME_H */
158 #ifdef HAVE_SYS_UTIME_H
159 #include <sys/utime.h>
160 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
161 #endif /* HAVE_SYS_UTIME_H */
163 #ifdef HAVE_SYS_TIMES_H
164 #include <sys/times.h>
165 #endif /* HAVE_SYS_TIMES_H */
167 #ifdef HAVE_SYS_PARAM_H
168 #include <sys/param.h>
169 #endif /* HAVE_SYS_PARAM_H */
171 #ifdef HAVE_SYS_UTSNAME_H
172 #include <sys/utsname.h>
173 #endif /* HAVE_SYS_UTSNAME_H */
175 #ifndef MAXPATHLEN
176 #define MAXPATHLEN 1024
177 #endif /* MAXPATHLEN */
179 #ifdef HAVE_DIRENT_H
180 #include <dirent.h>
181 #define NAMLEN(dirent) strlen((dirent)->d_name)
182 #else
183 #ifdef __WATCOMC__
184 #include <direct.h>
185 #define NAMLEN(dirent) strlen((dirent)->d_name)
186 #else
187 #define dirent direct
188 #define NAMLEN(dirent) (dirent)->d_namlen
189 #endif
190 #ifdef HAVE_SYS_NDIR_H
191 #include <sys/ndir.h>
192 #endif
193 #ifdef HAVE_SYS_DIR_H
194 #include <sys/dir.h>
195 #endif
196 #ifdef HAVE_NDIR_H
197 #include <ndir.h>
198 #endif
199 #endif
201 #ifdef _MSC_VER
202 #include <direct.h>
203 #include <io.h>
204 #include <process.h>
205 #include <windows.h>
206 #ifdef NT
207 #define popen _popen
208 #define pclose _pclose
209 #else /* 16-bit Windows */
210 #include <dos.h>
211 #include <ctype.h>
212 #endif /* NT */
213 #endif /* _MSC_VER */
215 #ifdef OS2
216 #include <io.h>
217 #endif /* OS2 */
219 /* Return a dictionary corresponding to the POSIX environment table */
221 #if !defined(_MSC_VER) && !defined(__WATCOMC__)
222 extern char **environ;
223 #endif /* !_MSC_VER */
225 static object *
226 convertenviron()
228 object *d;
229 char **e;
230 d = newdictobject();
231 if (d == NULL)
232 return NULL;
233 if (environ == NULL)
234 return d;
235 /* XXX This part ignores errors */
236 for (e = environ; *e != NULL; e++) {
237 object *v;
238 char *p = strchr(*e, '=');
239 if (p == NULL)
240 continue;
241 v = newstringobject(p+1);
242 if (v == NULL)
243 continue;
244 *p = '\0';
245 (void) dictinsert(d, *e, v);
246 *p = '=';
247 DECREF(v);
249 return d;
253 static object *PosixError; /* Exception posix.error */
255 /* Set a POSIX-specific error from errno, and return NULL */
257 static object * posix_error()
259 return err_errno(PosixError);
263 /* POSIX generic methods */
265 static object *
266 posix_1str(args, func)
267 object *args;
268 int (*func) FPROTO((const char *));
270 char *path1;
271 int res;
272 if (!getargs(args, "s", &path1))
273 return NULL;
274 BGN_SAVE
275 res = (*func)(path1);
276 END_SAVE
277 if (res < 0)
278 return posix_error();
279 INCREF(None);
280 return None;
283 static object *
284 posix_2str(args, func)
285 object *args;
286 int (*func) FPROTO((const char *, const char *));
288 char *path1, *path2;
289 int res;
290 if (!getargs(args, "(ss)", &path1, &path2))
291 return NULL;
292 BGN_SAVE
293 res = (*func)(path1, path2);
294 END_SAVE
295 if (res < 0)
296 return posix_error();
297 INCREF(None);
298 return None;
301 static object *
302 posix_strint(args, func)
303 object *args;
304 int (*func) FPROTO((const char *, int));
306 char *path;
307 int i;
308 int res;
309 if (!getargs(args, "(si)", &path, &i))
310 return NULL;
311 BGN_SAVE
312 res = (*func)(path, i);
313 END_SAVE
314 if (res < 0)
315 return posix_error();
316 INCREF(None);
317 return None;
320 static object *
321 posix_strintint(args, func)
322 object *args;
323 int (*func) FPROTO((const char *, int, int));
325 char *path;
326 int i,i2;
327 int res;
328 if (!getargs(args, "(sii)", &path, &i, &i2))
329 return NULL;
330 BGN_SAVE
331 res = (*func)(path, i, i2);
332 END_SAVE
333 if (res < 0)
334 return posix_error();
335 INCREF(None);
336 return None;
339 static object *
340 posix_do_stat(self, args, statfunc)
341 object *self;
342 object *args;
343 int (*statfunc) FPROTO((const char *, struct stat *));
345 struct stat st;
346 char *path;
347 int res;
348 if (!getargs(args, "s", &path))
349 return NULL;
350 BGN_SAVE
351 res = (*statfunc)(path, &st);
352 END_SAVE
353 if (res != 0)
354 return posix_error();
355 return mkvalue("(llllllllll)",
356 (long)st.st_mode,
357 (long)st.st_ino,
358 (long)st.st_dev,
359 (long)st.st_nlink,
360 (long)st.st_uid,
361 (long)st.st_gid,
362 (long)st.st_size,
363 (long)st.st_atime,
364 (long)st.st_mtime,
365 (long)st.st_ctime);
369 /* POSIX methods */
371 static object *
372 posix_chdir(self, args)
373 object *self;
374 object *args;
376 return posix_1str(args, chdir);
379 static object *
380 posix_chmod(self, args)
381 object *self;
382 object *args;
384 return posix_strint(args, chmod);
387 #ifdef HAVE_CHOWN
388 static object *
389 posix_chown(self, args)
390 object *self;
391 object *args;
393 return posix_strintint(args, chown);
395 #endif /* HAVE_CHOWN */
397 #ifdef HAVE_GETCWD
398 static object *
399 posix_getcwd(self, args)
400 object *self;
401 object *args;
403 char buf[1026];
404 char *res;
405 if (!getnoarg(args))
406 return NULL;
407 BGN_SAVE
408 res = getcwd(buf, sizeof buf);
409 END_SAVE
410 if (res == NULL)
411 return posix_error();
412 return newstringobject(buf);
414 #endif
416 #ifdef HAVE_LINK
417 static object *
418 posix_link(self, args)
419 object *self;
420 object *args;
422 return posix_2str(args, link);
424 #endif /* HAVE_LINK */
426 static object *
427 posix_listdir(self, args)
428 object *self;
429 object *args;
431 #if defined(NT) && !defined(HAVE_OPENDIR)
433 char *name;
434 int len;
435 object *d, *v;
436 HANDLE hFindFile;
437 WIN32_FIND_DATA FileData;
438 char namebuf[MAX_PATH+5];
440 if (!getargs(args, "s#", &name, &len))
441 return NULL;
442 if (len >= MAX_PATH) {
443 err_setstr(ValueError, "path too long");
444 return NULL;
446 strcpy(namebuf, name);
447 if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
448 namebuf[len++] = '/';
449 strcpy(namebuf + len, "*.*");
451 if ((d = newlistobject(0)) == NULL)
452 return NULL;
454 hFindFile = FindFirstFile(namebuf, &FileData);
455 if (hFindFile == INVALID_HANDLE_VALUE) {
456 errno = GetLastError();
457 return posix_error();
459 do {
460 if (FileData.cFileName[0] == '.' &&
461 (FileData.cFileName[1] == '\0' ||
462 FileData.cFileName[1] == '.' &&
463 FileData.cFileName[2] == '\0'))
464 continue;
465 v = newstringobject(FileData.cFileName);
466 if (v == NULL) {
467 DECREF(d);
468 d = NULL;
469 break;
471 if (addlistitem(d, v) != 0) {
472 DECREF(v);
473 DECREF(d);
474 d = NULL;
475 break;
477 DECREF(v);
478 } while (FindNextFile(hFindFile, &FileData) == TRUE);
480 if (FindClose(hFindFile) == FALSE) {
481 errno = GetLastError();
482 return posix_error();
485 return d;
487 #else /* !NT */
488 #ifdef _MSC_VER /* 16-bit Windows */
490 #ifndef MAX_PATH
491 #define MAX_PATH 250
492 #endif
493 char *name, *pt;
494 int len;
495 object *d, *v;
496 char namebuf[MAX_PATH+5];
497 struct _find_t ep;
499 if (!getargs(args, "s#", &name, &len))
500 return NULL;
501 if (len >= MAX_PATH) {
502 err_setstr(ValueError, "path too long");
503 return NULL;
505 strcpy(namebuf, name);
506 for (pt = namebuf; *pt; pt++)
507 if (*pt == '/')
508 *pt = '\\';
509 if (namebuf[len-1] != '\\')
510 namebuf[len++] = '\\';
511 strcpy(namebuf + len, "*.*");
513 if ((d = newlistobject(0)) == NULL)
514 return NULL;
516 if (_dos_findfirst(namebuf, _A_RDONLY |
517 _A_HIDDEN | _A_SYSTEM | _A_SUBDIR, &ep) != 0){
518 errno = ENOENT;
519 return posix_error();
521 do {
522 if (ep.name[0] == '.' &&
523 (ep.name[1] == '\0' ||
524 ep.name[1] == '.' &&
525 ep.name[2] == '\0'))
526 continue;
527 strcpy(namebuf, ep.name);
528 for (pt = namebuf; *pt; pt++)
529 if (isupper(*pt))
530 *pt = tolower(*pt);
531 v = newstringobject(namebuf);
532 if (v == NULL) {
533 DECREF(d);
534 d = NULL;
535 break;
537 if (addlistitem(d, v) != 0) {
538 DECREF(v);
539 DECREF(d);
540 d = NULL;
541 break;
543 DECREF(v);
544 } while (_dos_findnext(&ep) == 0);
546 return d;
548 #else
550 char *name;
551 object *d, *v;
552 DIR *dirp;
553 struct dirent *ep;
554 if (!getargs(args, "s", &name))
555 return NULL;
556 BGN_SAVE
557 if ((dirp = opendir(name)) == NULL) {
558 RET_SAVE
559 return posix_error();
561 if ((d = newlistobject(0)) == NULL) {
562 closedir(dirp);
563 RET_SAVE
564 return NULL;
566 while ((ep = readdir(dirp)) != NULL) {
567 if (ep->d_name[0] == '.' &&
568 (NAMLEN(ep) == 1 ||
569 ep->d_name[1] == '.' && NAMLEN(ep) == 2))
570 continue;
571 v = newsizedstringobject(ep->d_name, NAMLEN(ep));
572 if (v == NULL) {
573 DECREF(d);
574 d = NULL;
575 break;
577 if (addlistitem(d, v) != 0) {
578 DECREF(v);
579 DECREF(d);
580 d = NULL;
581 break;
583 DECREF(v);
585 closedir(dirp);
586 END_SAVE
588 return d;
590 #endif /* !_MSC_VER */
591 #endif /* !NT */
594 static object *
595 posix_mkdir(self, args)
596 object *self;
597 object *args;
599 int res;
600 char *path;
601 int mode = 0777;
602 if (!newgetargs(args, "s|i", &path, &mode))
603 return NULL;
604 BGN_SAVE
605 #if defined(__WATCOMC__)
606 res = mkdir(path);
607 #else
608 res = mkdir(path, mode);
609 #endif
610 END_SAVE
611 if (res < 0)
612 return posix_error();
613 INCREF(None);
614 return None;
617 #ifdef HAVE_NICE
618 static object *
619 posix_nice(self, args)
620 object *self;
621 object *args;
623 int increment, value;
625 if (!getargs(args, "i", &increment))
626 return NULL;
627 value = nice(increment);
628 if (value == -1)
629 return posix_error();
630 return newintobject((long) value);
632 #endif /* HAVE_NICE */
634 static object *
635 posix_rename(self, args)
636 object *self;
637 object *args;
639 return posix_2str(args, rename);
642 static object *
643 posix_rmdir(self, args)
644 object *self;
645 object *args;
647 return posix_1str(args, rmdir);
650 static object *
651 posix_stat(self, args)
652 object *self;
653 object *args;
655 return posix_do_stat(self, args, stat);
658 #ifdef HAVE_SYSTEM
659 static object *
660 posix_system(self, args)
661 object *self;
662 object *args;
664 char *command;
665 long sts;
666 if (!getargs(args, "s", &command))
667 return NULL;
668 BGN_SAVE
669 sts = system(command);
670 END_SAVE
671 return newintobject(sts);
673 #endif
675 static object *
676 posix_umask(self, args)
677 object *self;
678 object *args;
680 int i;
681 if (!getintarg(args, &i))
682 return NULL;
683 i = umask(i);
684 if (i < 0)
685 return posix_error();
686 return newintobject((long)i);
689 static object *
690 posix_unlink(self, args)
691 object *self;
692 object *args;
694 return posix_1str(args, unlink);
697 #ifdef HAVE_UNAME
698 static object *
699 posix_uname(self, args)
700 object *self;
701 object *args;
703 struct utsname u;
704 object *v;
705 int res;
706 if (!getnoarg(args))
707 return NULL;
708 BGN_SAVE
709 res = uname(&u);
710 END_SAVE
711 if (res < 0)
712 return posix_error();
713 return mkvalue("(sssss)",
714 u.sysname,
715 u.nodename,
716 u.release,
717 u.version,
718 u.machine);
720 #endif /* HAVE_UNAME */
722 static object *
723 posix_utime(self, args)
724 object *self;
725 object *args;
727 char *path;
728 long atime, mtime;
729 int res;
731 #ifdef HAVE_UTIME_H
732 struct utimbuf buf;
733 #define ATIME buf.actime
734 #define MTIME buf.modtime
735 #define UTIME_ARG &buf
736 #else /* HAVE_UTIME_H */
737 time_t buf[2];
738 #define ATIME buf[0]
739 #define MTIME buf[1]
740 #define UTIME_ARG buf
741 #endif /* HAVE_UTIME_H */
743 if (!getargs(args, "(s(ll))", &path, &atime, &mtime))
744 return NULL;
745 ATIME = atime;
746 MTIME = mtime;
747 BGN_SAVE
748 res = utime(path, UTIME_ARG);
749 END_SAVE
750 if (res < 0)
751 return posix_error();
752 INCREF(None);
753 return None;
754 #undef UTIME_ARG
755 #undef ATIME
756 #undef MTIME
760 /* Process operations */
762 static object *
763 posix__exit(self, args)
764 object *self;
765 object *args;
767 int sts;
768 if (!getintarg(args, &sts))
769 return NULL;
770 _exit(sts);
771 /* NOTREACHED */
774 #ifdef HAVE_EXECV
775 static object *
776 posix_execv(self, args)
777 object *self;
778 object *args;
780 char *path;
781 object *argv;
782 char **argvlist;
783 int i, argc;
784 object *(*getitem) PROTO((object *, int));
786 /* execv has two arguments: (path, argv), where
787 argv is a list or tuple of strings. */
789 if (!getargs(args, "(sO)", &path, &argv))
790 return NULL;
791 if (is_listobject(argv)) {
792 argc = getlistsize(argv);
793 getitem = getlistitem;
795 else if (is_tupleobject(argv)) {
796 argc = gettuplesize(argv);
797 getitem = gettupleitem;
799 else {
800 badarg:
801 err_badarg();
802 return NULL;
805 argvlist = NEW(char *, argc+1);
806 if (argvlist == NULL)
807 return NULL;
808 for (i = 0; i < argc; i++) {
809 if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
810 DEL(argvlist);
811 goto badarg;
814 argvlist[argc] = NULL;
816 #ifdef BAD_EXEC_PROTOTYPES
817 execv(path, (const char **) argvlist);
818 #else /* BAD_EXEC_PROTOTYPES */
819 execv(path, argvlist);
820 #endif /* BAD_EXEC_PROTOTYPES */
822 /* If we get here it's definitely an error */
824 DEL(argvlist);
825 return posix_error();
828 static object *
829 posix_execve(self, args)
830 object *self;
831 object *args;
833 char *path;
834 object *argv, *env;
835 char **argvlist;
836 char **envlist;
837 object *key, *val;
838 int i, pos, argc, envc;
839 object *(*getitem) PROTO((object *, int));
841 /* execve has three arguments: (path, argv, env), where
842 argv is a list or tuple of strings and env is a dictionary
843 like posix.environ. */
845 if (!getargs(args, "(sOO)", &path, &argv, &env))
846 return NULL;
847 if (is_listobject(argv)) {
848 argc = getlistsize(argv);
849 getitem = getlistitem;
851 else if (is_tupleobject(argv)) {
852 argc = gettuplesize(argv);
853 getitem = gettupleitem;
855 else {
856 err_setstr(TypeError, "argv must be tuple or list");
857 return NULL;
859 if (!is_dictobject(env)) {
860 err_setstr(TypeError, "env must be dictionary");
861 return NULL;
864 argvlist = NEW(char *, argc+1);
865 if (argvlist == NULL) {
866 err_nomem();
867 return NULL;
869 for (i = 0; i < argc; i++) {
870 if (!getargs((*getitem)(argv, i),
871 "s;argv must be list of strings",
872 &argvlist[i])) {
873 goto fail_1;
876 argvlist[argc] = NULL;
878 i = getmappingsize(env);
879 envlist = NEW(char *, i + 1);
880 if (envlist == NULL) {
881 err_nomem();
882 goto fail_1;
884 pos = 0;
885 envc = 0;
886 while (mappinggetnext(env, &pos, &key, &val)) {
887 char *p, *k, *v;
888 if (!getargs(key, "s;non-string key in env", &k) ||
889 !getargs(val, "s;non-string value in env", &v)) {
890 goto fail_2;
892 p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
893 if (p == NULL) {
894 err_nomem();
895 goto fail_2;
897 sprintf(p, "%s=%s", k, v);
898 envlist[envc++] = p;
900 envlist[envc] = 0;
903 #ifdef BAD_EXEC_PROTOTYPES
904 execve(path, (const char **)argvlist, envlist);
905 #else /* BAD_EXEC_PROTOTYPES */
906 execve(path, argvlist, envlist);
907 #endif /* BAD_EXEC_PROTOTYPES */
909 /* If we get here it's definitely an error */
911 (void) posix_error();
913 fail_2:
914 while (--envc >= 0)
915 DEL(envlist[envc]);
916 DEL(envlist);
917 fail_1:
918 DEL(argvlist);
920 return NULL;
922 #endif /* HAVE_EXECV */
924 #ifdef HAVE_FORK
925 static object *
926 posix_fork(self, args)
927 object *self;
928 object *args;
930 int pid;
931 if (!getnoarg(args))
932 return NULL;
933 pid = fork();
934 if (pid == -1)
935 return posix_error();
936 return newintobject((long)pid);
938 #endif
940 #ifdef HAVE_GETEGID
941 static object *
942 posix_getegid(self, args)
943 object *self;
944 object *args;
946 if (!getnoarg(args))
947 return NULL;
948 return newintobject((long)getegid());
950 #endif
952 #ifdef HAVE_GETEUID
953 static object *
954 posix_geteuid(self, args)
955 object *self;
956 object *args;
958 if (!getnoarg(args))
959 return NULL;
960 return newintobject((long)geteuid());
962 #endif
964 #ifdef HAVE_GETGID
965 static object *
966 posix_getgid(self, args)
967 object *self;
968 object *args;
970 if (!getnoarg(args))
971 return NULL;
972 return newintobject((long)getgid());
974 #endif
976 static object *
977 posix_getpid(self, args)
978 object *self;
979 object *args;
981 if (!getnoarg(args))
982 return NULL;
983 return newintobject((long)getpid());
986 #ifdef HAVE_GETPGRP
987 static object *
988 posix_getpgrp(self, args)
989 object *self;
990 object *args;
992 if (!getnoarg(args))
993 return NULL;
994 #ifdef GETPGRP_HAVE_ARG
995 return newintobject((long)getpgrp(0));
996 #else /* GETPGRP_HAVE_ARG */
997 return newintobject((long)getpgrp());
998 #endif /* GETPGRP_HAVE_ARG */
1000 #endif /* HAVE_GETPGRP */
1002 #ifdef HAVE_SETPGRP
1003 static object *
1004 posix_setpgrp(self, args)
1005 object *self;
1006 object *args;
1008 if (!getnoarg(args))
1009 return NULL;
1010 #ifdef SETPGRP_HAVE_ARG
1011 if (setpgrp(0, 0) < 0)
1012 #else /* SETPGRP_HAVE_ARG */
1013 if (setpgrp() < 0)
1014 #endif /* SETPGRP_HAVE_ARG */
1015 return posix_error();
1016 INCREF(None);
1017 return None;
1020 #endif /* HAVE_SETPGRP */
1022 #ifdef HAVE_GETPPID
1023 static object *
1024 posix_getppid(self, args)
1025 object *self;
1026 object *args;
1028 if (!getnoarg(args))
1029 return NULL;
1030 return newintobject((long)getppid());
1032 #endif
1034 #ifdef HAVE_GETUID
1035 static object *
1036 posix_getuid(self, args)
1037 object *self;
1038 object *args;
1040 if (!getnoarg(args))
1041 return NULL;
1042 return newintobject((long)getuid());
1044 #endif
1046 #ifdef HAVE_KILL
1047 static object *
1048 posix_kill(self, args)
1049 object *self;
1050 object *args;
1052 int pid, sig;
1053 if (!getargs(args, "(ii)", &pid, &sig))
1054 return NULL;
1055 if (kill(pid, sig) == -1)
1056 return posix_error();
1057 INCREF(None);
1058 return None;
1060 #endif
1062 #ifdef HAVE_POPEN
1063 static object *
1064 posix_popen(self, args)
1065 object *self;
1066 object *args;
1068 char *name;
1069 char *mode = "r";
1070 int bufsize = -1;
1071 FILE *fp;
1072 object *f;
1073 if (!newgetargs(args, "s|si", &name, &mode, &bufsize))
1074 return NULL;
1075 BGN_SAVE
1076 fp = popen(name, mode);
1077 END_SAVE
1078 if (fp == NULL)
1079 return posix_error();
1080 f = newopenfileobject(fp, name, mode, pclose);
1081 if (f != NULL)
1082 setfilebufsize(f, bufsize);
1083 return f;
1085 #endif /* HAVE_POPEN */
1087 #ifdef HAVE_SETUID
1088 static object *
1089 posix_setuid(self, args)
1090 object *self;
1091 object *args;
1093 int uid;
1094 if (!getargs(args, "i", &uid))
1095 return NULL;
1096 if (setuid(uid) < 0)
1097 return posix_error();
1098 INCREF(None);
1099 return None;
1101 #endif /* HAVE_SETUID */
1103 #ifdef HAVE_SETGID
1104 static object *
1105 posix_setgid(self, args)
1106 object *self;
1107 object *args;
1109 int gid;
1110 if (!getargs(args, "i", &gid))
1111 return NULL;
1112 if (setgid(gid) < 0)
1113 return posix_error();
1114 INCREF(None);
1115 return None;
1117 #endif /* HAVE_SETGID */
1119 #ifdef HAVE_WAITPID
1120 static object *
1121 posix_waitpid(self, args)
1122 object *self;
1123 object *args;
1125 int pid, options, sts;
1126 if (!getargs(args, "(ii)", &pid, &options))
1127 return NULL;
1128 BGN_SAVE
1129 pid = waitpid(pid, &sts, options);
1130 END_SAVE
1131 if (pid == -1)
1132 return posix_error();
1133 else
1134 return mkvalue("ii", pid, sts);
1136 #endif /* HAVE_WAITPID */
1138 #ifdef HAVE_WAIT
1139 static object *
1140 posix_wait(self, args)
1141 object *self;
1142 object *args;
1144 int pid, sts;
1145 BGN_SAVE
1146 pid = wait(&sts);
1147 END_SAVE
1148 if (pid == -1)
1149 return posix_error();
1150 else
1151 return mkvalue("ii", pid, sts);
1153 #endif
1155 static object *
1156 posix_lstat(self, args)
1157 object *self;
1158 object *args;
1160 #ifdef HAVE_LSTAT
1161 return posix_do_stat(self, args, lstat);
1162 #else /* !HAVE_LSTAT */
1163 return posix_do_stat(self, args, stat);
1164 #endif /* !HAVE_LSTAT */
1167 #ifdef HAVE_READLINK
1168 static object *
1169 posix_readlink(self, args)
1170 object *self;
1171 object *args;
1173 char buf[MAXPATHLEN];
1174 char *path;
1175 int n;
1176 if (!getargs(args, "s", &path))
1177 return NULL;
1178 BGN_SAVE
1179 n = readlink(path, buf, (int) sizeof buf);
1180 END_SAVE
1181 if (n < 0)
1182 return posix_error();
1183 return newsizedstringobject(buf, n);
1185 #endif /* HAVE_READLINK */
1187 #ifdef HAVE_SYMLINK
1188 static object *
1189 posix_symlink(self, args)
1190 object *self;
1191 object *args;
1193 return posix_2str(args, symlink);
1195 #endif /* HAVE_SYMLINK */
1197 #ifdef HAVE_TIMES
1198 #ifndef HZ
1199 #define HZ 60 /* Universal constant :-) */
1200 #endif /* HZ */
1201 static object *
1202 posix_times(self, args)
1203 object *self;
1204 object *args;
1206 struct tms t;
1207 clock_t c;
1208 if (!getnoarg(args))
1209 return NULL;
1210 errno = 0;
1211 c = times(&t);
1212 if (c == (clock_t) -1)
1213 return posix_error();
1214 return mkvalue("ddddd",
1215 (double)t.tms_utime / HZ,
1216 (double)t.tms_stime / HZ,
1217 (double)t.tms_cutime / HZ,
1218 (double)t.tms_cstime / HZ,
1219 (double)c / HZ);
1221 #endif /* HAVE_TIMES */
1222 #if defined(NT) && !defined(HAVE_TIMES)
1223 #define HAVE_TIMES /* so the method table will pick it up */
1224 static object *
1225 posix_times(self, args)
1226 object *self;
1227 object *args;
1229 FILETIME create, exit, kernel, user;
1230 HANDLE hProc;
1231 if (!getnoarg(args))
1232 return NULL;
1233 hProc = GetCurrentProcess();
1234 GetProcessTimes(hProc,&create, &exit, &kernel, &user);
1235 return mkvalue("ddddd",
1236 (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6,
1237 (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
1238 (double)0,
1239 (double)0,
1240 (double)0);
1242 #endif /* NT */
1244 #ifdef HAVE_SETSID
1245 static object *
1246 posix_setsid(self, args)
1247 object *self;
1248 object *args;
1250 if (!getnoarg(args))
1251 return NULL;
1252 if (setsid() < 0)
1253 return posix_error();
1254 INCREF(None);
1255 return None;
1257 #endif /* HAVE_SETSID */
1259 #ifdef HAVE_SETPGID
1260 static object *
1261 posix_setpgid(self, args)
1262 object *self;
1263 object *args;
1265 int pid, pgrp;
1266 if (!getargs(args, "(ii)", &pid, &pgrp))
1267 return NULL;
1268 if (setpgid(pid, pgrp) < 0)
1269 return posix_error();
1270 INCREF(None);
1271 return None;
1273 #endif /* HAVE_SETPGID */
1275 #ifdef HAVE_TCGETPGRP
1276 static object *
1277 posix_tcgetpgrp(self, args)
1278 object *self;
1279 object *args;
1281 int fd, pgid;
1282 if (!getargs(args, "i", &fd))
1283 return NULL;
1284 pgid = tcgetpgrp(fd);
1285 if (pgid < 0)
1286 return posix_error();
1287 return newintobject((long)pgid);
1289 #endif /* HAVE_TCGETPGRP */
1291 #ifdef HAVE_TCSETPGRP
1292 static object *
1293 posix_tcsetpgrp(self, args)
1294 object *self;
1295 object *args;
1297 int fd, pgid;
1298 if (!getargs(args, "(ii)", &fd, &pgid))
1299 return NULL;
1300 if (tcsetpgrp(fd, pgid) < 0)
1301 return posix_error();
1302 INCREF(None);
1303 return None;
1305 #endif /* HAVE_TCSETPGRP */
1307 /* Functions acting on file descriptors */
1309 static object *
1310 posix_open(self, args)
1311 object *self;
1312 object *args;
1314 char *file;
1315 int flag;
1316 int mode = 0777;
1317 int fd;
1318 if (!getargs(args, "(si)", &file, &flag)) {
1319 err_clear();
1320 if (!getargs(args, "(sii)", &file, &flag, &mode))
1321 return NULL;
1323 BGN_SAVE
1324 fd = open(file, flag, mode);
1325 END_SAVE
1326 if (fd < 0)
1327 return posix_error();
1328 return newintobject((long)fd);
1331 static object *
1332 posix_close(self, args)
1333 object *self;
1334 object *args;
1336 int fd, res;
1337 if (!getargs(args, "i", &fd))
1338 return NULL;
1339 BGN_SAVE
1340 res = close(fd);
1341 END_SAVE
1342 if (res < 0)
1343 return posix_error();
1344 INCREF(None);
1345 return None;
1348 static object *
1349 posix_dup(self, args)
1350 object *self;
1351 object *args;
1353 int fd;
1354 if (!getargs(args, "i", &fd))
1355 return NULL;
1356 BGN_SAVE
1357 fd = dup(fd);
1358 END_SAVE
1359 if (fd < 0)
1360 return posix_error();
1361 return newintobject((long)fd);
1364 static object *
1365 posix_dup2(self, args)
1366 object *self;
1367 object *args;
1369 int fd, fd2, res;
1370 if (!getargs(args, "(ii)", &fd, &fd2))
1371 return NULL;
1372 BGN_SAVE
1373 res = dup2(fd, fd2);
1374 END_SAVE
1375 if (res < 0)
1376 return posix_error();
1377 INCREF(None);
1378 return None;
1381 static object *
1382 posix_lseek(self, args)
1383 object *self;
1384 object *args;
1386 int fd, how;
1387 long pos, res;
1388 if (!getargs(args, "(ili)", &fd, &pos, &how))
1389 return NULL;
1390 #ifdef SEEK_SET
1391 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
1392 switch (how) {
1393 case 0: how = SEEK_SET; break;
1394 case 1: how = SEEK_CUR; break;
1395 case 2: how = SEEK_END; break;
1397 #endif /* SEEK_END */
1398 BGN_SAVE
1399 res = lseek(fd, pos, how);
1400 END_SAVE
1401 if (res < 0)
1402 return posix_error();
1403 return newintobject(res);
1406 static object *
1407 posix_read(self, args)
1408 object *self;
1409 object *args;
1411 int fd, size;
1412 object *buffer;
1413 if (!getargs(args, "(ii)", &fd, &size))
1414 return NULL;
1415 buffer = newsizedstringobject((char *)NULL, size);
1416 if (buffer == NULL)
1417 return NULL;
1418 BGN_SAVE
1419 size = read(fd, getstringvalue(buffer), size);
1420 END_SAVE
1421 if (size < 0) {
1422 DECREF(buffer);
1423 return posix_error();
1425 resizestring(&buffer, size);
1426 return buffer;
1429 static object *
1430 posix_write(self, args)
1431 object *self;
1432 object *args;
1434 int fd, size;
1435 char *buffer;
1436 if (!getargs(args, "(is#)", &fd, &buffer, &size))
1437 return NULL;
1438 BGN_SAVE
1439 size = write(fd, buffer, size);
1440 END_SAVE
1441 if (size < 0)
1442 return posix_error();
1443 return newintobject((long)size);
1446 static object *
1447 posix_fstat(self, args)
1448 object *self;
1449 object *args;
1451 int fd;
1452 struct stat st;
1453 int res;
1454 if (!getargs(args, "i", &fd))
1455 return NULL;
1456 BGN_SAVE
1457 res = fstat(fd, &st);
1458 END_SAVE
1459 if (res != 0)
1460 return posix_error();
1461 return mkvalue("(llllllllll)",
1462 (long)st.st_mode,
1463 (long)st.st_ino,
1464 (long)st.st_dev,
1465 (long)st.st_nlink,
1466 (long)st.st_uid,
1467 (long)st.st_gid,
1468 (long)st.st_size,
1469 (long)st.st_atime,
1470 (long)st.st_mtime,
1471 (long)st.st_ctime);
1474 static object *
1475 posix_fdopen(self, args)
1476 object *self;
1477 object *args;
1479 extern int fclose PROTO((FILE *));
1480 int fd;
1481 char *mode = "r";
1482 int bufsize = -1;
1483 FILE *fp;
1484 object *f;
1485 if (!newgetargs(args, "i|si", &fd, &mode, &bufsize))
1486 return NULL;
1487 BGN_SAVE
1488 fp = fdopen(fd, mode);
1489 END_SAVE
1490 if (fp == NULL)
1491 return posix_error();
1492 f = newopenfileobject(fp, "(fdopen)", mode, fclose);
1493 if (f != NULL)
1494 setfilebufsize(f, bufsize);
1495 return f;
1498 #ifdef HAVE_PIPE
1499 static object *
1500 posix_pipe(self, args)
1501 object *self;
1502 object *args;
1504 #if !defined(NT)
1505 int fds[2];
1506 int res;
1507 if (!getargs(args, ""))
1508 return NULL;
1509 BGN_SAVE
1510 res = pipe(fds);
1511 END_SAVE
1512 if (res != 0)
1513 return posix_error();
1514 return mkvalue("(ii)", fds[0], fds[1]);
1515 #else /* NT */
1516 HANDLE read, write;
1517 BOOL ok;
1518 if (!getargs(args, ""))
1519 return NULL;
1520 BGN_SAVE
1521 ok = CreatePipe( &read, &write, NULL, 0);
1522 END_SAVE
1523 if (!ok)
1524 return posix_error();
1525 return mkvalue("(ii)", read, write);
1526 #endif /* NT */
1528 #endif /* HAVE_PIPE */
1530 #ifdef HAVE_MKFIFO
1531 static object *
1532 posix_mkfifo(self, args)
1533 object *self;
1534 object *args;
1536 char *file;
1537 int mode = 0666;
1538 int res;
1539 if (!newgetargs(args, "s|i", &file, &mode))
1540 return NULL;
1541 BGN_SAVE
1542 res = mkfifo(file, mode);
1543 END_SAVE
1544 if (res < 0)
1545 return posix_error();
1546 INCREF(None);
1547 return None;
1549 #endif
1551 #ifdef HAVE_FTRUNCATE
1552 static object *
1553 posix_ftruncate(self, args)
1554 object *self; /* Not used */
1555 object *args;
1557 int fd;
1558 long length;
1559 int res;
1561 if (!getargs(args, "(il)", &fd, &length))
1562 return NULL;
1564 BGN_SAVE
1565 res = ftruncate(fd, length);
1566 END_SAVE
1567 if (res < 0) {
1568 err_errno(IOError);
1569 return NULL;
1571 INCREF(None);
1572 return None;
1574 #endif
1576 static struct methodlist posix_methods[] = {
1577 {"chdir", posix_chdir},
1578 {"chmod", posix_chmod},
1579 #ifdef HAVE_CHOWN
1580 {"chown", posix_chown},
1581 #endif /* HAVE_CHOWN */
1582 #ifdef HAVE_GETCWD
1583 {"getcwd", posix_getcwd},
1584 #endif
1585 #ifdef HAVE_LINK
1586 {"link", posix_link},
1587 #endif /* HAVE_LINK */
1588 {"listdir", posix_listdir},
1589 {"lstat", posix_lstat},
1590 {"mkdir", posix_mkdir, 1},
1591 #ifdef HAVE_NICE
1592 {"nice", posix_nice},
1593 #endif /* HAVE_NICE */
1594 #ifdef HAVE_READLINK
1595 {"readlink", posix_readlink},
1596 #endif /* HAVE_READLINK */
1597 {"rename", posix_rename},
1598 {"rmdir", posix_rmdir},
1599 {"stat", posix_stat},
1600 #ifdef HAVE_SYMLINK
1601 {"symlink", posix_symlink},
1602 #endif /* HAVE_SYMLINK */
1603 #ifdef HAVE_SYSTEM
1604 {"system", posix_system},
1605 #endif
1606 {"umask", posix_umask},
1607 #ifdef HAVE_UNAME
1608 {"uname", posix_uname},
1609 #endif /* HAVE_UNAME */
1610 {"unlink", posix_unlink},
1611 {"remove", posix_unlink},
1612 {"utime", posix_utime},
1613 #ifdef HAVE_TIMES
1614 {"times", posix_times},
1615 #endif /* HAVE_TIMES */
1616 {"_exit", posix__exit},
1617 #ifdef HAVE_EXECV
1618 {"execv", posix_execv},
1619 {"execve", posix_execve},
1620 #endif /* HAVE_EXECV */
1621 #ifdef HAVE_FORK
1622 {"fork", posix_fork},
1623 #endif /* HAVE_FORK */
1624 #ifdef HAVE_GETEGID
1625 {"getegid", posix_getegid},
1626 #endif /* HAVE_GETEGID */
1627 #ifdef HAVE_GETEUID
1628 {"geteuid", posix_geteuid},
1629 #endif /* HAVE_GETEUID */
1630 #ifdef HAVE_GETGID
1631 {"getgid", posix_getgid},
1632 #endif /* HAVE_GETGID */
1633 {"getpid", posix_getpid},
1634 #ifdef HAVE_GETPGRP
1635 {"getpgrp", posix_getpgrp},
1636 #endif /* HAVE_GETPGRP */
1637 #ifdef HAVE_GETPPID
1638 {"getppid", posix_getppid},
1639 #endif /* HAVE_GETPPID */
1640 #ifdef HAVE_GETUID
1641 {"getuid", posix_getuid},
1642 #endif /* HAVE_GETUID */
1643 #ifdef HAVE_KILL
1644 {"kill", posix_kill},
1645 #endif /* HAVE_KILL */
1646 #ifdef HAVE_POPEN
1647 {"popen", posix_popen, 1},
1648 #endif /* HAVE_POPEN */
1649 #ifdef HAVE_SETUID
1650 {"setuid", posix_setuid},
1651 #endif /* HAVE_SETUID */
1652 #ifdef HAVE_SETGID
1653 {"setgid", posix_setgid},
1654 #endif /* HAVE_SETGID */
1655 #ifdef HAVE_SETPGRP
1656 {"setpgrp", posix_setpgrp},
1657 #endif /* HAVE_SETPGRP */
1658 #ifdef HAVE_WAIT
1659 {"wait", posix_wait},
1660 #endif /* HAVE_WAIT */
1661 #ifdef HAVE_WAITPID
1662 {"waitpid", posix_waitpid},
1663 #endif /* HAVE_WAITPID */
1664 #ifdef HAVE_SETSID
1665 {"setsid", posix_setsid},
1666 #endif /* HAVE_SETSID */
1667 #ifdef HAVE_SETPGID
1668 {"setpgid", posix_setpgid},
1669 #endif /* HAVE_SETPGID */
1670 #ifdef HAVE_TCGETPGRP
1671 {"tcgetpgrp", posix_tcgetpgrp},
1672 #endif /* HAVE_TCGETPGRP */
1673 #ifdef HAVE_TCSETPGRP
1674 {"tcsetpgrp", posix_tcsetpgrp},
1675 #endif /* HAVE_TCSETPGRP */
1676 {"open", posix_open},
1677 {"close", posix_close},
1678 {"dup", posix_dup},
1679 {"dup2", posix_dup2},
1680 {"lseek", posix_lseek},
1681 {"read", posix_read},
1682 {"write", posix_write},
1683 {"fstat", posix_fstat},
1684 {"fdopen", posix_fdopen, 1},
1685 #ifdef HAVE_PIPE
1686 {"pipe", posix_pipe},
1687 #endif
1688 #ifdef HAVE_MKFIFO
1689 {"mkfifo", posix_mkfifo, 1},
1690 #endif
1691 #ifdef HAVE_FTRUNCATE
1692 {"ftruncate", posix_ftruncate, 1},
1693 #endif
1694 {NULL, NULL} /* Sentinel */
1698 #if defined(_MSC_VER) || defined(__WATCOMC__)
1699 void
1700 initnt()
1702 object *m, *d, *v;
1704 m = initmodule("nt", posix_methods);
1705 d = getmoduledict(m);
1707 /* Initialize nt.environ dictionary */
1708 v = convertenviron();
1709 if (v == NULL || dictinsert(d, "environ", v) != 0)
1710 fatal("can't define nt.environ");
1711 DECREF(v);
1713 /* Initialize nt.error exception */
1714 PosixError = newstringobject("nt.error");
1715 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1716 fatal("can't define nt.error");
1718 #else /* !_MSC_VER */
1719 void
1720 initposix()
1722 object *m, *d, *v;
1724 m = initmodule("posix", posix_methods);
1725 d = getmoduledict(m);
1727 /* Initialize posix.environ dictionary */
1728 v = convertenviron();
1729 if (v == NULL || dictinsert(d, "environ", v) != 0)
1730 fatal("can't define posix.environ");
1731 DECREF(v);
1733 #ifdef WNOHANG
1734 /* Export WNOHANG symbol */
1735 v = newintobject((long)WNOHANG);
1736 if (v == NULL || dictinsert(d, "WNOHANG", v) != 0)
1737 fatal("can't define posix.WNOHANG");
1738 DECREF(v);
1739 #endif
1741 /* Initialize posix.error exception */
1742 PosixError = newstringobject("posix.error");
1743 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1744 fatal("can't define posix.error");
1746 #endif /* !_MSC_VER */