This commit was manufactured by cvs2svn to create tag 'mac102'.
[python/dscho.git] / Modules / posixmodule.c
blobba0a0a62fd7f54e6e8bd1d5feacc952ab4249ba3
1 /***********************************************************
2 Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3 Amsterdam, 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 #ifdef _M_IX86
28 #define NT
29 #endif
31 #include "allobjects.h"
32 #include "modsupport.h"
33 #include "ceval.h"
35 #include <signal.h>
36 #include <string.h>
37 #include <setjmp.h>
38 #include <errno.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
42 #include "mytime.h" /* For clock_t on some systems */
44 #ifdef HAVE_FCNTL_H
45 #include <fcntl.h>
46 #endif
48 #ifdef HAVE_UNISTD_H
49 #include <unistd.h>
50 #else /* !HAVE_UNISTD_H */
51 extern int mkdir PROTO((const char *, mode_t));
52 extern int chdir PROTO((const char *));
53 extern int rmdir PROTO((const char *));
54 extern int chmod PROTO((const char *, mode_t));
55 extern int chown PROTO((const char *, uid_t, gid_t));
56 extern char *getcwd PROTO((char *, int));
57 extern char *strerror PROTO((int));
58 extern int link PROTO((const char *, const char *));
59 extern int rename PROTO((const char *, const char *));
60 extern int stat PROTO((const char *, struct stat *));
61 extern int unlink PROTO((const char *));
62 extern int pclose PROTO((FILE *));
63 #ifdef HAVE_SYMLINK
64 extern int symlink PROTO((const char *, const char *));
65 #endif
66 #ifdef HAVE_LSTAT
67 extern int lstat PROTO((const char *, struct stat *));
68 #endif
69 #endif /* !HAVE_UNISTD_H */
71 #if 1
72 /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
73 extern int rename();
74 extern int pclose();
75 extern int lstat();
76 extern int symlink();
77 #endif
79 #ifdef HAVE_UTIME_H
80 #include <utime.h>
81 #endif
83 #ifdef HAVE_SYS_TIMES_H
84 #include <sys/times.h>
85 #endif
87 #ifdef HAVE_SYS_PARAM_H
88 #include <sys/param.h>
89 #endif
91 #ifdef HAVE_SYS_UTSNAME_H
92 #include <sys/utsname.h>
93 #endif
95 #ifndef MAXPATHLEN
96 #define MAXPATHLEN 1024
97 #endif
99 /* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
100 #if defined(DIRENT) || defined(_POSIX_VERSION)
101 #include <dirent.h>
102 #define NLENGTH(dirent) (strlen((dirent)->d_name))
103 #else /* not (DIRENT or _POSIX_VERSION) */
104 #define dirent direct
105 #define NLENGTH(dirent) ((dirent)->d_namlen)
106 #ifdef SYSNDIR
107 #include <sys/ndir.h>
108 #endif /* SYSNDIR */
109 #ifdef SYSDIR
110 #include <sys/dir.h>
111 #endif /* SYSDIR */
112 #ifdef NDIR
113 #include <ndir.h>
114 #endif /* NDIR */
115 #endif /* not (DIRENT or _POSIX_VERSION) */
117 #ifdef NT
118 #include <direct.h>
119 #include <io.h>
120 #include <process.h>
121 #include <windows.h>
122 #define popen _popen
123 #endif /* NT */
126 /* Return a dictionary corresponding to the POSIX environment table */
128 extern char **environ;
130 static object *
131 convertenviron()
133 object *d;
134 char **e;
135 d = newdictobject();
136 if (d == NULL)
137 return NULL;
138 if (environ == NULL)
139 return d;
140 /* XXX This part ignores errors */
141 for (e = environ; *e != NULL; e++) {
142 object *v;
143 char *p = strchr(*e, '=');
144 if (p == NULL)
145 continue;
146 v = newstringobject(p+1);
147 if (v == NULL)
148 continue;
149 *p = '\0';
150 (void) dictinsert(d, *e, v);
151 *p = '=';
152 DECREF(v);
154 return d;
158 static object *PosixError; /* Exception posix.error */
160 /* Set a POSIX-specific error from errno, and return NULL */
162 static object * posix_error() { return err_errno(PosixError);
166 /* POSIX generic methods */
168 static object *
169 posix_1str(args, func)
170 object *args;
171 int (*func) FPROTO((const char *));
173 char *path1;
174 int res;
175 if (!getargs(args, "s", &path1))
176 return NULL;
177 BGN_SAVE
178 res = (*func)(path1);
179 END_SAVE
180 if (res < 0)
181 return posix_error();
182 INCREF(None);
183 return None;
186 static object *
187 posix_2str(args, func)
188 object *args;
189 int (*func) FPROTO((const char *, const char *));
191 char *path1, *path2;
192 int res;
193 if (!getargs(args, "(ss)", &path1, &path2))
194 return NULL;
195 BGN_SAVE
196 res = (*func)(path1, path2);
197 END_SAVE
198 if (res < 0)
199 return posix_error();
200 INCREF(None);
201 return None;
204 static object *
205 posix_strint(args, func)
206 object *args;
207 int (*func) FPROTO((const char *, int));
209 char *path;
210 int i;
211 int res;
212 if (!getargs(args, "(si)", &path, &i))
213 return NULL;
214 BGN_SAVE
215 res = (*func)(path, i);
216 END_SAVE
217 if (res < 0)
218 return posix_error();
219 INCREF(None);
220 return None;
223 static object *
224 posix_strintint(args, func)
225 object *args;
226 int (*func) FPROTO((const char *, int, int));
228 char *path;
229 int i,i2;
230 int res;
231 if (!getargs(args, "(sii)", &path, &i, &i2))
232 return NULL;
233 BGN_SAVE
234 res = (*func)(path, i, i2);
235 END_SAVE
236 if (res < 0)
237 return posix_error();
238 INCREF(None);
239 return None;
242 static object *
243 posix_do_stat(self, args, statfunc)
244 object *self;
245 object *args;
246 int (*statfunc) FPROTO((const char *, struct stat *));
248 struct stat st;
249 char *path;
250 int res;
251 if (!getargs(args, "s", &path))
252 return NULL;
253 BGN_SAVE
254 res = (*statfunc)(path, &st);
255 END_SAVE
256 if (res != 0)
257 return posix_error();
258 return mkvalue("(llllllllll)",
259 (long)st.st_mode,
260 (long)st.st_ino,
261 (long)st.st_dev,
262 (long)st.st_nlink,
263 (long)st.st_uid,
264 (long)st.st_gid,
265 (long)st.st_size,
266 (long)st.st_atime,
267 (long)st.st_mtime,
268 (long)st.st_ctime);
272 /* POSIX methods */
274 static object *
275 posix_chdir(self, args)
276 object *self;
277 object *args;
279 return posix_1str(args, chdir);
282 static object *
283 posix_chmod(self, args)
284 object *self;
285 object *args;
287 return posix_strint(args, chmod);
290 static object *
291 posix_chown(self, args)
292 object *self;
293 object *args;
295 return posix_strintint(args, chown);
298 static object *
299 posix_getcwd(self, args)
300 object *self;
301 object *args;
303 char buf[1026];
304 char *res;
305 if (!getnoarg(args))
306 return NULL;
307 BGN_SAVE
308 res = getcwd(buf, sizeof buf);
309 END_SAVE
310 if (res == NULL)
311 return posix_error();
312 return newstringobject(buf);
315 static object *
316 posix_link(self, args)
317 object *self;
318 object *args;
320 return posix_2str(args, link);
323 #ifdef NT
324 static object *
325 posix_listdir(self, args)
326 object *self;
327 object *args;
329 char *name;
330 int len;
331 object *d, *v;
332 HANDLE hFindFile;
333 WIN32_FIND_DATA FileData;
334 char namebuf[MAX_PATH+5];
336 if (!getargs(args, "s#", &name, &len))
337 return NULL;
338 if (len >= MAX_PATH) {
339 err_setstr(ValueError, "path too long");
340 return NULL;
342 strcpy(namebuf, name);
343 if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
344 namebuf[len++] = '/';
345 strcpy(namebuf + len, "*.*");
347 if ((d = newlistobject(0)) == NULL)
348 return NULL;
350 hFindFile = FindFirstFile(namebuf, &FileData);
351 if (hFindFile == INVALID_HANDLE_VALUE) {
352 errno = GetLastError();
353 return posix_error();
355 do {
356 v = newstringobject(FileData.cFileName);
357 if (v == NULL) {
358 DECREF(d);
359 d = NULL;
360 break;
362 if (addlistitem(d, v) != 0) {
363 DECREF(v);
364 DECREF(d);
365 d = NULL;
366 break;
368 DECREF(v);
369 } while (FindNextFile(hFindFile, &FileData) == TRUE);
371 if (FindClose(hFindFile) == FALSE) {
372 errno = GetLastError();
373 return posix_error();
376 return d;
378 #else /* ! NT */
379 static object *
380 posix_listdir(self, args)
381 object *self;
382 object *args;
384 char *name;
385 object *d, *v;
386 DIR *dirp;
387 struct dirent *ep;
388 if (!getargs(args, "s", &name))
389 return NULL;
390 BGN_SAVE
391 if ((dirp = opendir(name)) == NULL) {
392 RET_SAVE
393 return posix_error();
395 if ((d = newlistobject(0)) == NULL) {
396 closedir(dirp);
397 RET_SAVE
398 return NULL;
400 while ((ep = readdir(dirp)) != NULL) {
401 v = newstringobject(ep->d_name);
402 if (v == NULL) {
403 DECREF(d);
404 d = NULL;
405 break;
407 if (addlistitem(d, v) != 0) {
408 DECREF(v);
409 DECREF(d);
410 d = NULL;
411 break;
413 DECREF(v);
415 closedir(dirp);
416 END_SAVE
418 return d;
420 #endif /* ! NT */
422 static object *
423 posix_mkdir(self, args)
424 object *self;
425 object *args;
427 return posix_strint(args, mkdir);
430 #ifdef HAVE_NICE
431 static object *
432 posix_nice(self, args)
433 object *self;
434 object *args;
436 int increment, value;
438 if (!getargs(args, "i", &increment))
439 return NULL;
440 value = nice(increment);
441 if (value == -1)
442 return posix_error();
443 return newintobject((long) value);
445 #endif /* HAVE_NICE */
447 static object *
448 posix_rename(self, args)
449 object *self;
450 object *args;
452 return posix_2str(args, rename);
455 static object *
456 posix_rmdir(self, args)
457 object *self;
458 object *args;
460 return posix_1str(args, rmdir);
463 static object *
464 posix_stat(self, args)
465 object *self;
466 object *args;
468 return posix_do_stat(self, args, stat);
471 static object *
472 posix_system(self, args)
473 object *self;
474 object *args;
476 char *command;
477 long sts;
478 if (!getargs(args, "s", &command))
479 return NULL;
480 BGN_SAVE
481 sts = system(command);
482 END_SAVE
483 return newintobject(sts);
486 static object *
487 posix_umask(self, args)
488 object *self;
489 object *args;
491 int i;
492 if (!getintarg(args, &i))
493 return NULL;
494 i = umask(i);
495 if (i < 0)
496 return posix_error();
497 return newintobject((long)i);
500 static object *
501 posix_unlink(self, args)
502 object *self;
503 object *args;
505 return posix_1str(args, unlink);
508 #ifdef HAVE_UNAME
509 static object *
510 posix_uname(self, args)
511 object *self;
512 object *args;
514 struct utsname u;
515 object *v;
516 int res;
517 if (!getnoarg(args))
518 return NULL;
519 BGN_SAVE
520 res = uname(&u);
521 END_SAVE
522 if (res < 0)
523 return posix_error();
524 return mkvalue("(sssss)",
525 u.sysname,
526 u.nodename,
527 u.release,
528 u.version,
529 u.machine);
531 #endif /* HAVE_UNAME */
533 static object *
534 posix_utime(self, args)
535 object *self;
536 object *args;
538 char *path;
539 int res;
541 #ifdef HAVE_UTIME_H
542 struct utimbuf buf;
543 #define ATIME buf.actime
544 #define MTIME buf.modtime
545 #define UTIME_ARG &buf
546 #else
547 time_t buf[2];
548 #define ATIME buf[0]
549 #define MTIME buf[1]
550 #define UTIME_ARG buf
551 #endif
553 if (!getargs(args, "(s(ll))", &path, &ATIME, &MTIME))
554 return NULL;
555 BGN_SAVE
556 res = utime(path, UTIME_ARG);
557 END_SAVE
558 if (res < 0)
559 return posix_error();
560 INCREF(None);
561 return None;
562 #undef UTIME_ARG
563 #undef ATIME
564 #undef MTIME
568 /* Process operations */
570 static object *
571 posix__exit(self, args)
572 object *self;
573 object *args;
575 int sts;
576 if (!getintarg(args, &sts))
577 return NULL;
578 _exit(sts);
579 /* NOTREACHED */
582 static object *
583 posix_execv(self, args)
584 object *self;
585 object *args;
587 char *path;
588 object *argv;
589 char **argvlist;
590 int i, argc;
591 object *(*getitem) PROTO((object *, int));
593 /* execv has two arguments: (path, argv), where
594 argv is a list or tuple of strings. */
596 if (!getargs(args, "(sO)", &path, &argv))
597 return NULL;
598 if (is_listobject(argv)) {
599 argc = getlistsize(argv);
600 getitem = getlistitem;
602 else if (is_tupleobject(argv)) {
603 argc = gettuplesize(argv);
604 getitem = gettupleitem;
606 else {
607 badarg:
608 err_badarg();
609 return NULL;
612 argvlist = NEW(char *, argc+1);
613 if (argvlist == NULL)
614 return NULL;
615 for (i = 0; i < argc; i++) {
616 if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
617 DEL(argvlist);
618 goto badarg;
621 argvlist[argc] = NULL;
623 #ifdef BAD_EXEC_PROTOTYPES
624 execv(path, (const char **) argvlist);
625 #else
626 execv(path, argvlist);
627 #endif
629 /* If we get here it's definitely an error */
631 DEL(argvlist);
632 return posix_error();
635 static object *
636 posix_execve(self, args)
637 object *self;
638 object *args;
640 char *path;
641 object *argv, *env;
642 char **argvlist;
643 char **envlist;
644 object *key, *val;
645 int i, pos, argc, envc;
646 object *(*getitem) PROTO((object *, int));
648 /* execve has three arguments: (path, argv, env), where
649 argv is a list or tuple of strings and env is a dictionary
650 like posix.environ. */
652 if (!getargs(args, "(sOO)", &path, &argv, &env))
653 return NULL;
654 if (is_listobject(argv)) {
655 argc = getlistsize(argv);
656 getitem = getlistitem;
658 else if (is_tupleobject(argv)) {
659 argc = gettuplesize(argv);
660 getitem = gettupleitem;
662 else {
663 err_setstr(TypeError, "argv must be tuple or list");
664 return NULL;
666 if (!is_dictobject(env)) {
667 err_setstr(TypeError, "env must be dictionary");
668 return NULL;
671 argvlist = NEW(char *, argc+1);
672 if (argvlist == NULL) {
673 err_nomem();
674 return NULL;
676 for (i = 0; i < argc; i++) {
677 if (!getargs((*getitem)(argv, i),
678 "s;argv must be list of strings",
679 &argvlist[i])) {
680 goto fail_1;
683 argvlist[argc] = NULL;
685 i = getmappingsize(env);
686 envlist = NEW(char *, i + 1);
687 if (envlist == NULL) {
688 err_nomem();
689 goto fail_1;
691 pos = 0;
692 envc = 0;
693 while (mappinggetnext(env, &pos, &key, &val)) {
694 char *p, *k, *v;
695 if (!getargs(key, "s;non-string key in env", &k) ||
696 !getargs(val, "s;non-string value in env", &v)) {
697 goto fail_2;
699 p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
700 if (p == NULL) {
701 err_nomem();
702 goto fail_2;
704 sprintf(p, "%s=%s", k, v);
705 envlist[envc++] = p;
707 envlist[envc] = 0;
710 #ifdef BAD_EXEC_PROTOTYPES
711 execve(path, (const char **)argvlist, envlist);
712 #else
713 execve(path, argvlist, envlist);
714 #endif
716 /* If we get here it's definitely an error */
718 (void) posix_error();
720 fail_2:
721 while (--envc >= 0)
722 DEL(envlist[envc]);
723 DEL(envlist);
724 fail_1:
725 DEL(argvlist);
727 return NULL;
730 static object *
731 posix_fork(self, args)
732 object *self;
733 object *args;
735 int pid;
736 if (!getnoarg(args))
737 return NULL;
738 pid = fork();
739 if (pid == -1)
740 return posix_error();
741 return newintobject((long)pid);
744 static object *
745 posix_getegid(self, args)
746 object *self;
747 object *args;
749 if (!getnoarg(args))
750 return NULL;
751 return newintobject((long)getegid());
754 static object *
755 posix_geteuid(self, args)
756 object *self;
757 object *args;
759 if (!getnoarg(args))
760 return NULL;
761 return newintobject((long)geteuid());
764 static object *
765 posix_getgid(self, args)
766 object *self;
767 object *args;
769 if (!getnoarg(args))
770 return NULL;
771 return newintobject((long)getgid());
774 static object *
775 posix_getpid(self, args)
776 object *self;
777 object *args;
779 if (!getnoarg(args))
780 return NULL;
781 return newintobject((long)getpid());
784 #ifdef HAVE_GETPGRP
785 static object *
786 posix_getpgrp(self, args)
787 object *self;
788 object *args;
790 if (!getnoarg(args))
791 return NULL;
792 #ifdef GETPGRP_HAVE_ARG
793 return newintobject((long)getpgrp(0));
794 #else
795 return newintobject((long)getpgrp());
796 #endif
798 #endif /* HAVE_GETPGRP */
800 #ifdef HAVE_SETPGRP
801 static object *
802 posix_setpgrp(self, args)
803 object *self;
804 object *args;
806 if (!getnoarg(args))
807 return NULL;
808 #ifdef GETPGRP_HAVE_ARG
809 if (setpgrp(0, 0) < 0)
810 #else
811 if (setpgrp() < 0)
812 #endif
813 return posix_error();
814 INCREF(None);
815 return None;
818 #endif /* HAVE_SETPGRP */
820 static object *
821 posix_getppid(self, args)
822 object *self;
823 object *args;
825 if (!getnoarg(args))
826 return NULL;
827 return newintobject((long)getppid());
830 static object *
831 posix_getuid(self, args)
832 object *self;
833 object *args;
835 if (!getnoarg(args))
836 return NULL;
837 return newintobject((long)getuid());
840 static object *
841 posix_kill(self, args)
842 object *self;
843 object *args;
845 int pid, sig;
846 if (!getargs(args, "(ii)", &pid, &sig))
847 return NULL;
848 if (kill(pid, sig) == -1)
849 return posix_error();
850 INCREF(None);
851 return None;
854 static object *
855 posix_popen(self, args)
856 object *self;
857 object *args;
859 char *name, *mode;
860 FILE *fp;
861 if (!getargs(args, "(ss)", &name, &mode))
862 return NULL;
863 BGN_SAVE
864 fp = popen(name, mode);
865 END_SAVE
866 if (fp == NULL)
867 return posix_error();
868 /* From now on, ignore SIGPIPE and let the error checking
869 do the work. */
870 #ifdef NT
871 return newopenfileobject(fp, name, mode, fclose);
872 #else /* ! NT */
873 (void) signal(SIGPIPE, SIG_IGN);
874 return newopenfileobject(fp, name, mode, pclose);
875 #endif /* ! NT */
878 static object *
879 posix_setuid(self, args)
880 object *self;
881 object *args;
883 int uid;
884 if (!getargs(args, "i", &uid))
885 return NULL;
886 if (setuid(uid) < 0)
887 return posix_error();
888 INCREF(None);
889 return None;
892 static object *
893 posix_setgid(self, args)
894 object *self;
895 object *args;
897 int gid;
898 if (!getargs(args, "i", &gid))
899 return NULL;
900 if (setgid(gid) < 0)
901 return posix_error();
902 INCREF(None);
903 return None;
906 #ifdef HAVE_WAITPID
907 static object *
908 posix_waitpid(self, args)
909 object *self;
910 object *args;
912 int pid, options, sts;
913 if (!getargs(args, "(ii)", &pid, &options))
914 return NULL;
915 BGN_SAVE
916 pid = waitpid(pid, &sts, options);
917 END_SAVE
918 if (pid == -1)
919 return posix_error();
920 else
921 return mkvalue("ii", pid, sts);
923 #endif /* HAVE_WAITPID */
925 static object *
926 posix_wait(self, args)
927 object *self;
928 object *args;
930 int pid, sts;
931 BGN_SAVE
932 pid = wait(&sts);
933 END_SAVE
934 if (pid == -1)
935 return posix_error();
936 else
937 return mkvalue("ii", pid, sts);
940 static object *
941 posix_lstat(self, args)
942 object *self;
943 object *args;
945 #ifdef HAVE_LSTAT
946 return posix_do_stat(self, args, lstat);
947 #else /* !HAVE_LSTAT */
948 return posix_do_stat(self, args, stat);
949 #endif /* !HAVE_LSTAT */
952 #ifdef HAVE_READLINK
953 static object *
954 posix_readlink(self, args)
955 object *self;
956 object *args;
958 char buf[MAXPATHLEN];
959 char *path;
960 int n;
961 if (!getargs(args, "s", &path))
962 return NULL;
963 BGN_SAVE
964 n = readlink(path, buf, (int) sizeof buf);
965 END_SAVE
966 if (n < 0)
967 return posix_error();
968 return newsizedstringobject(buf, n);
970 #endif /* HAVE_READLINK */
972 #ifdef HAVE_SYMLINK
973 static object *
974 posix_symlink(self, args)
975 object *self;
976 object *args;
978 return posix_2str(args, symlink);
980 #endif /* HAVE_SYMLINK */
982 #ifdef HAVE_TIMES
983 #ifndef HZ
984 #define HZ 60 /* Universal constant :-) */
985 #endif
986 static object *
987 posix_times(self, args)
988 object *self;
989 object *args;
991 struct tms t;
992 clock_t c;
993 if (!getnoarg(args))
994 return NULL;
995 errno = 0;
996 c = times(&t);
997 if (c == (clock_t) -1)
998 return posix_error();
999 return mkvalue("dddd",
1000 (double)t.tms_utime / HZ,
1001 (double)t.tms_stime / HZ,
1002 (double)t.tms_cutime / HZ,
1003 (double)t.tms_cstime / HZ);
1005 #endif /* HAVE_TIMES */
1007 #ifdef HAVE_SETSID
1008 static object *
1009 posix_setsid(self, args)
1010 object *self;
1011 object *args;
1013 if (!getnoarg(args))
1014 return NULL;
1015 if (setsid() < 0)
1016 return posix_error();
1017 INCREF(None);
1018 return None;
1020 #endif /* HAVE_SETSID */
1022 #ifdef HAVE_SETPGID
1023 static object *
1024 posix_setpgid(self, args)
1025 object *self;
1026 object *args;
1028 int pid, pgrp;
1029 if (!getargs(args, "(ii)", &pid, &pgrp))
1030 return NULL;
1031 if (setpgid(pid, pgrp) < 0)
1032 return posix_error();
1033 INCREF(None);
1034 return None;
1036 #endif /* HAVE_SETPGID */
1038 #ifdef HAVE_TCGETPGRP
1039 static object *
1040 posix_tcgetpgrp(self, args)
1041 object *self;
1042 object *args;
1044 int fd, pgid;
1045 if (!getargs(args, "i", &fd))
1046 return NULL;
1047 pgid = tcgetpgrp(fd);
1048 if (pgid < 0)
1049 return posix_error();
1050 return newintobject((long)pgid);
1052 #endif /* HAVE_TCGETPGRP */
1054 #ifdef HAVE_TCSETPGRP
1055 static object *
1056 posix_tcsetpgrp(self, args)
1057 object *self;
1058 object *args;
1060 int fd, pgid;
1061 if (!getargs(args, "(ii)", &fd, &pgid))
1062 return NULL;
1063 if (tcsetpgrp(fd, pgid) < 0)
1064 return posix_error();
1065 INCREF(None);
1066 return None;
1068 #endif /* HAVE_TCSETPGRP */
1070 /* Functions acting on file descriptors */
1072 static object *
1073 posix_open(self, args)
1074 object *self;
1075 object *args;
1077 char *file;
1078 int flag;
1079 int mode = 0777;
1080 int fd;
1081 if (!getargs(args, "(si)", &file, &flag)) {
1082 err_clear();
1083 if (!getargs(args, "(sii)", &file, &flag, &mode))
1084 return NULL;
1086 BGN_SAVE
1087 fd = open(file, flag, mode);
1088 END_SAVE
1089 if (fd < 0)
1090 return posix_error();
1091 return newintobject((long)fd);
1094 static object *
1095 posix_close(self, args)
1096 object *self;
1097 object *args;
1099 int fd, res;
1100 if (!getargs(args, "i", &fd))
1101 return NULL;
1102 BGN_SAVE
1103 res = close(fd);
1104 END_SAVE
1105 if (res < 0)
1106 return posix_error();
1107 INCREF(None);
1108 return None;
1111 static object *
1112 posix_dup(self, args)
1113 object *self;
1114 object *args;
1116 int fd;
1117 if (!getargs(args, "i", &fd))
1118 return NULL;
1119 BGN_SAVE
1120 fd = dup(fd);
1121 END_SAVE
1122 if (fd < 0)
1123 return posix_error();
1124 return newintobject((long)fd);
1127 static object *
1128 posix_dup2(self, args)
1129 object *self;
1130 object *args;
1132 int fd, fd2, res;
1133 if (!getargs(args, "(ii)", &fd, &fd2))
1134 return NULL;
1135 BGN_SAVE
1136 res = dup2(fd, fd2);
1137 END_SAVE
1138 if (res < 0)
1139 return posix_error();
1140 INCREF(None);
1141 return None;
1144 static object *
1145 posix_lseek(self, args)
1146 object *self;
1147 object *args;
1149 int fd, how;
1150 long pos, res;
1151 if (!getargs(args, "(ili)", &fd, &pos, &how))
1152 return NULL;
1153 #ifdef SEEK_SET
1154 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
1155 switch (how) {
1156 case 0: how = SEEK_SET; break;
1157 case 1: how = SEEK_CUR; break;
1158 case 2: how = SEEK_END; break;
1160 #endif
1161 BGN_SAVE
1162 res = lseek(fd, pos, how);
1163 END_SAVE
1164 if (res < 0)
1165 return posix_error();
1166 return newintobject(res);
1169 static object *
1170 posix_read(self, args)
1171 object *self;
1172 object *args;
1174 int fd, size;
1175 object *buffer;
1176 if (!getargs(args, "(ii)", &fd, &size))
1177 return NULL;
1178 buffer = newsizedstringobject((char *)NULL, size);
1179 if (buffer == NULL)
1180 return NULL;
1181 BGN_SAVE
1182 size = read(fd, getstringvalue(buffer), size);
1183 END_SAVE
1184 if (size < 0) {
1185 DECREF(buffer);
1186 return posix_error();
1188 resizestring(&buffer, size);
1189 return buffer;
1192 static object *
1193 posix_write(self, args)
1194 object *self;
1195 object *args;
1197 int fd, size;
1198 char *buffer;
1199 if (!getargs(args, "(is#)", &fd, &buffer, &size))
1200 return NULL;
1201 BGN_SAVE
1202 size = write(fd, buffer, size);
1203 END_SAVE
1204 if (size < 0)
1205 return posix_error();
1206 return newintobject((long)size);
1209 static object *
1210 posix_fstat(self, args)
1211 object *self;
1212 object *args;
1214 int fd;
1215 struct stat st;
1216 int res;
1217 if (!getargs(args, "i", &fd))
1218 return NULL;
1219 BGN_SAVE
1220 res = fstat(fd, &st);
1221 END_SAVE
1222 if (res != 0)
1223 return posix_error();
1224 return mkvalue("(llllllllll)",
1225 (long)st.st_mode,
1226 (long)st.st_ino,
1227 (long)st.st_dev,
1228 (long)st.st_nlink,
1229 (long)st.st_uid,
1230 (long)st.st_gid,
1231 (long)st.st_size,
1232 (long)st.st_atime,
1233 (long)st.st_mtime,
1234 (long)st.st_ctime);
1237 static object *
1238 posix_fdopen(self, args)
1239 object *self;
1240 object *args;
1242 extern int fclose PROTO((FILE *));
1243 int fd;
1244 char *mode;
1245 FILE *fp;
1246 if (!getargs(args, "(is)", &fd, &mode))
1247 return NULL;
1248 BGN_SAVE
1249 fp = fdopen(fd, mode);
1250 END_SAVE
1251 if (fp == NULL)
1252 return posix_error();
1253 /* From now on, ignore SIGPIPE and let the error checking
1254 do the work. */
1255 #ifndef NT
1256 (void) signal(SIGPIPE, SIG_IGN);
1257 #endif /* ! NT */
1258 return newopenfileobject(fp, "(fdopen)", mode, fclose);
1261 static object *
1262 posix_pipe(self, args)
1263 object *self;
1264 object *args;
1266 int fds[2];
1267 int res;
1268 if (!getargs(args, ""))
1269 return NULL;
1270 BGN_SAVE
1271 res = pipe(fds);
1272 END_SAVE
1273 if (res != 0)
1274 return posix_error();
1275 return mkvalue("(ii)", fds[0], fds[1]);
1278 static struct methodlist posix_methods[] = {
1279 {"chdir", posix_chdir},
1280 {"chmod", posix_chmod},
1281 {"chown", posix_chown},
1282 {"getcwd", posix_getcwd},
1283 #ifndef NT
1284 {"link", posix_link},
1285 #endif /* ! NT */
1286 {"listdir", posix_listdir},
1287 {"lstat", posix_lstat},
1288 {"mkdir", posix_mkdir},
1289 #ifdef HAVE_NICE
1290 {"nice", posix_nice},
1291 #endif
1292 #ifdef HAVE_READLINK
1293 {"readlink", posix_readlink},
1294 #endif
1295 {"rename", posix_rename},
1296 {"rmdir", posix_rmdir},
1297 {"stat", posix_stat},
1298 #ifdef HAVE_SYMLINK
1299 {"symlink", posix_symlink},
1300 #endif
1301 {"system", posix_system},
1302 {"umask", posix_umask},
1303 #ifdef HAVE_UNAME
1304 {"uname", posix_uname},
1305 #endif
1306 {"unlink", posix_unlink},
1307 #ifndef NT
1308 {"utime", posix_utime},
1309 #endif /* ! NT */
1310 #ifdef HAVE_TIMES
1311 {"times", posix_times},
1312 #endif
1313 {"_exit", posix__exit},
1314 {"execv", posix_execv},
1315 {"execve", posix_execve},
1316 #ifndef NT
1317 {"fork", posix_fork},
1318 {"getegid", posix_getegid},
1319 {"geteuid", posix_geteuid},
1320 {"getgid", posix_getgid},
1321 #endif /* ! NT */
1322 {"getpid", posix_getpid},
1323 #ifdef HAVE_GETPGRP
1324 {"getpgrp", posix_getpgrp},
1325 #endif
1326 #ifndef NT
1327 {"getppid", posix_getppid},
1328 {"getuid", posix_getuid},
1329 {"kill", posix_kill},
1330 #endif /* ! NT */
1331 {"popen", posix_popen},
1332 #ifndef NT
1333 {"setuid", posix_setuid},
1334 {"setgid", posix_setgid},
1335 #ifdef HAVE_SETPGRP
1336 {"setpgrp", posix_setpgrp},
1337 #endif
1338 {"wait", posix_wait},
1339 #endif /* ! NT */
1340 #ifdef HAVE_WAITPID
1341 {"waitpid", posix_waitpid},
1342 #endif
1343 #ifdef HAVE_SETSID
1344 {"setsid", posix_setsid},
1345 #endif
1346 #ifdef HAVE_SETPGID
1347 {"setpgid", posix_setpgid},
1348 #endif
1349 #ifdef HAVE_TCGETPGRP
1350 {"tcgetpgrp", posix_tcgetpgrp},
1351 #endif
1352 #ifdef HAVE_TCSETPGRP
1353 {"tcsetpgrp", posix_tcsetpgrp},
1354 #endif
1355 {"open", posix_open},
1356 {"close", posix_close},
1357 {"dup", posix_dup},
1358 {"dup2", posix_dup2},
1359 {"lseek", posix_lseek},
1360 {"read", posix_read},
1361 {"write", posix_write},
1362 {"fstat", posix_fstat},
1363 {"fdopen", posix_fdopen},
1364 #ifndef NT
1365 {"pipe", posix_pipe},
1366 #endif /* ! NT */
1368 {NULL, NULL} /* Sentinel */
1372 #ifdef NT
1373 void
1374 initnt()
1376 object *m, *d, *v;
1378 m = initmodule("nt", posix_methods);
1379 d = getmoduledict(m);
1381 /* Initialize nt.environ dictionary */
1382 v = convertenviron();
1383 if (v == NULL || dictinsert(d, "environ", v) != 0)
1384 fatal("can't define nt.environ");
1385 DECREF(v);
1387 /* Initialize nt.error exception */
1388 PosixError = newstringobject("nt.error");
1389 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1390 fatal("can't define nt.error");
1392 #else /* ! NT */
1393 void
1394 initposix()
1396 object *m, *d, *v;
1398 m = initmodule("posix", posix_methods);
1399 d = getmoduledict(m);
1401 /* Initialize posix.environ dictionary */
1402 v = convertenviron();
1403 if (v == NULL || dictinsert(d, "environ", v) != 0)
1404 fatal("can't define posix.environ");
1405 DECREF(v);
1407 /* Initialize posix.error exception */
1408 PosixError = newstringobject("posix.error");
1409 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1410 fatal("can't define posix.error");
1412 #endif /* ! NT */