At the release of 1.0.1.
[python/dscho.git] / Modules / posixmodule.c
blob07d12e74e6d893acedb33e3c7d59d54a188740d2
1 /***********************************************************
2 Copyright 1991, 1992, 1993 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 AMOEBA
28 #define NO_LSTAT
29 #define SYSV
30 #endif
32 #ifdef __sgi
33 #define DO_PG
34 #endif
36 #ifdef _NEXT_SOURCE
37 #define mode_t int
38 #define NO_UNAME
39 #endif
41 #include <signal.h>
42 #include <string.h>
43 #include <setjmp.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
47 #ifdef DO_TIMES
48 #include <sys/times.h>
49 #include <sys/param.h>
50 #include <errno.h>
51 #endif
53 #ifdef SYSV
55 #define UTIME_STRUCT 1
56 #include <dirent.h>
57 #define direct dirent
58 #ifdef i386
59 #define mode_t int
60 #endif
62 #else /* !SYSV */
64 #include <sys/dir.h>
66 #endif /* !SYSV */
68 #ifndef NO_UNISTD
69 #include <unistd.h> /* Take this out and hope the best if it doesn't exist */
70 #endif
72 #include "allobjects.h"
73 #include "modsupport.h"
74 #include "ceval.h"
76 #ifdef _SEQUENT_
77 #include <unistd.h>
78 #else /* _SEQUENT_ */
79 /* XXX Aren't these always declared in unistd.h? */
80 extern int mkdir PROTO((const char *, mode_t));
81 extern int chdir PROTO((const char *));
82 extern int rmdir PROTO((const char *));
83 extern int chmod PROTO((const char *, mode_t));
84 extern char *getcwd(); /* No PROTO((char *, int)) -- non portable */
85 extern char *strerror PROTO((int));
86 extern int link PROTO((const char *, const char *));
87 extern int rename PROTO((const char *, const char *));
88 extern int stat PROTO((const char *, struct stat *));
89 extern int unlink PROTO((const char *));
90 extern int pclose PROTO((FILE *));
91 #endif /* !_SEQUENT_ */
92 #ifdef NO_LSTAT
93 #define lstat stat
94 #else
95 extern int lstat PROTO((const char *, struct stat *));
96 extern int symlink PROTO((const char *, const char *));
97 #endif
100 /* Return a dictionary corresponding to the POSIX environment table */
102 extern char **environ;
104 static object *
105 convertenviron()
107 object *d;
108 char **e;
109 d = newdictobject();
110 if (d == NULL)
111 return NULL;
112 if (environ == NULL)
113 return d;
114 /* XXX This part ignores errors */
115 for (e = environ; *e != NULL; e++) {
116 object *v;
117 char *p = strchr(*e, '=');
118 if (p == NULL)
119 continue;
120 v = newstringobject(p+1);
121 if (v == NULL)
122 continue;
123 *p = '\0';
124 (void) dictinsert(d, *e, v);
125 *p = '=';
126 DECREF(v);
128 return d;
132 static object *PosixError; /* Exception posix.error */
134 /* Set a POSIX-specific error from errno, and return NULL */
136 static object * posix_error() { return err_errno(PosixError);
140 /* POSIX generic methods */
142 static object *
143 posix_1str(args, func)
144 object *args;
145 int (*func) FPROTO((const char *));
147 char *path1;
148 int res;
149 if (!getargs(args, "s", &path1))
150 return NULL;
151 BGN_SAVE
152 res = (*func)(path1);
153 END_SAVE
154 if (res < 0)
155 return posix_error();
156 INCREF(None);
157 return None;
160 static object *
161 posix_2str(args, func)
162 object *args;
163 int (*func) FPROTO((const char *, const char *));
165 char *path1, *path2;
166 int res;
167 if (!getargs(args, "(ss)", &path1, &path2))
168 return NULL;
169 BGN_SAVE
170 res = (*func)(path1, path2);
171 END_SAVE
172 if (res < 0)
173 return posix_error();
174 INCREF(None);
175 return None;
178 static object *
179 posix_strint(args, func)
180 object *args;
181 int (*func) FPROTO((const char *, int));
183 char *path;
184 int i;
185 int res;
186 if (!getargs(args, "(si)", &path, &i))
187 return NULL;
188 BGN_SAVE
189 res = (*func)(path, i);
190 END_SAVE
191 if (res < 0)
192 return posix_error();
193 INCREF(None);
194 return None;
197 static object *
198 posix_do_stat(self, args, statfunc)
199 object *self;
200 object *args;
201 int (*statfunc) FPROTO((const char *, struct stat *));
203 struct stat st;
204 char *path;
205 int res;
206 if (!getargs(args, "s", &path))
207 return NULL;
208 BGN_SAVE
209 res = (*statfunc)(path, &st);
210 END_SAVE
211 if (res != 0)
212 return posix_error();
213 return mkvalue("(llllllllll)",
214 (long)st.st_mode,
215 (long)st.st_ino,
216 (long)st.st_dev,
217 (long)st.st_nlink,
218 (long)st.st_uid,
219 (long)st.st_gid,
220 (long)st.st_size,
221 (long)st.st_atime,
222 (long)st.st_mtime,
223 (long)st.st_ctime);
227 /* POSIX methods */
229 static object *
230 posix_chdir(self, args)
231 object *self;
232 object *args;
234 return posix_1str(args, chdir);
237 static object *
238 posix_chmod(self, args)
239 object *self;
240 object *args;
242 return posix_strint(args, chmod);
245 static object *
246 posix_getcwd(self, args)
247 object *self;
248 object *args;
250 char buf[1026];
251 char *res;
252 if (!getnoarg(args))
253 return NULL;
254 BGN_SAVE
255 res = getcwd(buf, sizeof buf);
256 END_SAVE
257 if (res == NULL)
258 return posix_error();
259 return newstringobject(buf);
262 static object *
263 posix_link(self, args)
264 object *self;
265 object *args;
267 return posix_2str(args, link);
270 static object *
271 posix_listdir(self, args)
272 object *self;
273 object *args;
275 char *name;
276 object *d, *v;
277 DIR *dirp;
278 struct direct *ep;
279 if (!getargs(args, "s", &name))
280 return NULL;
281 BGN_SAVE
282 if ((dirp = opendir(name)) == NULL) {
283 RET_SAVE
284 return posix_error();
286 if ((d = newlistobject(0)) == NULL) {
287 closedir(dirp);
288 RET_SAVE
289 return NULL;
291 while ((ep = readdir(dirp)) != NULL) {
292 v = newstringobject(ep->d_name);
293 if (v == NULL) {
294 DECREF(d);
295 d = NULL;
296 break;
298 if (addlistitem(d, v) != 0) {
299 DECREF(v);
300 DECREF(d);
301 d = NULL;
302 break;
304 DECREF(v);
306 closedir(dirp);
307 END_SAVE
309 return d;
312 static object *
313 posix_mkdir(self, args)
314 object *self;
315 object *args;
317 return posix_strint(args, mkdir);
320 static object *
321 posix_nice(self, args)
322 object *self;
323 object *args;
325 int increment, value;
327 if (!getargs(args, "i", &increment))
328 return NULL;
329 value = nice(increment);
330 if (value == -1)
331 return posix_error();
332 return newintobject((long) value);
335 #if i386 && ! _SEQUENT_
337 rename(from, to)
338 char *from;
339 char *to;
341 int status;
342 /* XXX Shouldn't this unlink the destination first? */
343 status = link(from, to);
344 if (status != 0)
345 return status;
346 return unlink(from);
348 #endif /* i386 && ! _SEQUENT_ */
350 static object *
351 posix_rename(self, args)
352 object *self;
353 object *args;
355 return posix_2str(args, rename);
358 static object *
359 posix_rmdir(self, args)
360 object *self;
361 object *args;
363 return posix_1str(args, rmdir);
366 static object *
367 posix_stat(self, args)
368 object *self;
369 object *args;
371 return posix_do_stat(self, args, stat);
374 static object *
375 posix_system(self, args)
376 object *self;
377 object *args;
379 char *command;
380 long sts;
381 if (!getargs(args, "s", &command))
382 return NULL;
383 BGN_SAVE
384 sts = system(command);
385 END_SAVE
386 return newintobject(sts);
389 static object *
390 posix_umask(self, args)
391 object *self;
392 object *args;
394 int i;
395 if (!getintarg(args, &i))
396 return NULL;
397 i = umask(i);
398 if (i < 0)
399 return posix_error();
400 return newintobject((long)i);
403 static object *
404 posix_unlink(self, args)
405 object *self;
406 object *args;
408 return posix_1str(args, unlink);
411 #ifndef NO_UNAME
412 #include <sys/utsname.h>
414 extern int uname PROTO((struct utsname *));
416 static object *
417 posix_uname(self, args)
418 object *self;
419 object *args;
421 struct utsname u;
422 object *v;
423 int res;
424 if (!getnoarg(args))
425 return NULL;
426 BGN_SAVE
427 res = uname(&u);
428 END_SAVE
429 if (res < 0)
430 return posix_error();
431 return mkvalue("(sssss)",
432 u.sysname,
433 u.nodename,
434 u.release,
435 u.version,
436 u.machine);
438 #endif /* NO_UNAME */
440 #ifdef UTIME_STRUCT
441 #include <utime.h>
442 #endif
444 static object *
445 posix_utime(self, args)
446 object *self;
447 object *args;
449 char *path;
450 int res;
452 #ifdef UTIME_STRUCT
453 struct utimbuf buf;
454 #define ATIME buf.actime
455 #define MTIME buf.modtime
456 #define UTIME_ARG &buf
458 #else
459 time_t buf[2];
460 #define ATIME buf[0]
461 #define MTIME buf[1]
462 #define UTIME_ARG buf
463 #endif
465 if (!getargs(args, "(s(ll))", &path, &ATIME, &MTIME))
466 return NULL;
467 BGN_SAVE
468 res = utime(path, UTIME_ARG);
469 END_SAVE
470 if (res < 0)
471 return posix_error();
472 INCREF(None);
473 return None;
474 #undef UTIME_ARG
475 #undef ATIME
476 #undef MTIME
480 /* Process operations */
482 static object *
483 posix__exit(self, args)
484 object *self;
485 object *args;
487 int sts;
488 if (!getintarg(args, &sts))
489 return NULL;
490 _exit(sts);
491 /* NOTREACHED */
494 static object *
495 posix_execv(self, args)
496 object *self;
497 object *args;
499 char *path;
500 object *argv;
501 char **argvlist;
502 int i, argc;
503 object *(*getitem) PROTO((object *, int));
505 /* execv has two arguments: (path, argv), where
506 argv is a list or tuple of strings. */
508 if (!getargs(args, "(sO)", &path, &argv))
509 return NULL;
510 if (is_listobject(argv)) {
511 argc = getlistsize(argv);
512 getitem = getlistitem;
514 else if (is_tupleobject(argv)) {
515 argc = gettuplesize(argv);
516 getitem = gettupleitem;
518 else {
519 badarg:
520 err_badarg();
521 return NULL;
524 argvlist = NEW(char *, argc+1);
525 if (argvlist == NULL)
526 return NULL;
527 for (i = 0; i < argc; i++) {
528 if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
529 DEL(argvlist);
530 goto badarg;
533 argvlist[argc] = NULL;
535 execv(path, argvlist);
537 /* If we get here it's definitely an error */
539 DEL(argvlist);
540 return posix_error();
543 static object *
544 posix_execve(self, args)
545 object *self;
546 object *args;
548 char *path;
549 object *argv, *env;
550 char **argvlist;
551 char **envlist;
552 object *key, *val;
553 int i, pos, argc, envc;
554 object *(*getitem) PROTO((object *, int));
556 /* execve has three arguments: (path, argv, env), where
557 argv is a list or tuple of strings and env is a dictionary
558 like posix.environ. */
560 if (!getargs(args, "(sOO)", &path, &argv, &env))
561 return NULL;
562 if (is_listobject(argv)) {
563 argc = getlistsize(argv);
564 getitem = getlistitem;
566 else if (is_tupleobject(argv)) {
567 argc = gettuplesize(argv);
568 getitem = gettupleitem;
570 else {
571 err_setstr(TypeError, "argv must be tuple or list");
572 return NULL;
574 if (!is_dictobject(env)) {
575 err_setstr(TypeError, "env must be dictionary");
576 return NULL;
579 argvlist = NEW(char *, argc+1);
580 if (argvlist == NULL) {
581 err_nomem();
582 return NULL;
584 for (i = 0; i < argc; i++) {
585 if (!getargs((*getitem)(argv, i),
586 "s;argv must be list of strings",
587 &argvlist[i])) {
588 goto fail_1;
591 argvlist[argc] = NULL;
593 i = getmappingsize(env);
594 envlist = NEW(char *, i + 1);
595 if (envlist == NULL) {
596 err_nomem();
597 goto fail_1;
599 pos = 0;
600 envc = 0;
601 while (mappinggetnext(env, &pos, &key, &val)) {
602 char *p, *k, *v;
603 if (!getargs(key, "s;non-string key in env", &k) ||
604 !getargs(val, "s;non-string value in env", &v)) {
605 goto fail_2;
607 p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
608 if (p == NULL) {
609 err_nomem();
610 goto fail_2;
612 sprintf(p, "%s=%s", k, v);
613 envlist[envc++] = p;
615 envlist[envc] = 0;
617 execve(path, argvlist, envlist);
619 /* If we get here it's definitely an error */
621 (void) posix_error();
623 fail_2:
624 while (--envc >= 0)
625 DEL(envlist[envc]);
626 DEL(envlist);
627 fail_1:
628 DEL(argvlist);
630 return NULL;
633 static object *
634 posix_fork(self, args)
635 object *self;
636 object *args;
638 int pid;
639 if (!getnoarg(args))
640 return NULL;
641 pid = fork();
642 if (pid == -1)
643 return posix_error();
644 return newintobject((long)pid);
647 static object *
648 posix_getegid(self, args)
649 object *self;
650 object *args;
652 if (!getnoarg(args))
653 return NULL;
654 return newintobject((long)getegid());
657 static object *
658 posix_geteuid(self, args)
659 object *self;
660 object *args;
662 if (!getnoarg(args))
663 return NULL;
664 return newintobject((long)geteuid());
667 static object *
668 posix_getgid(self, args)
669 object *self;
670 object *args;
672 if (!getnoarg(args))
673 return NULL;
674 return newintobject((long)getgid());
677 static object *
678 posix_getpid(self, args)
679 object *self;
680 object *args;
682 if (!getnoarg(args))
683 return NULL;
684 return newintobject((long)getpid());
687 static object *
688 posix_getpgrp(self, args)
689 object *self;
690 object *args;
692 if (!getnoarg(args))
693 return NULL;
694 #ifdef SYSV
695 return newintobject((long)getpgrp());
696 #else
697 return newintobject((long)getpgrp(0));
698 #endif
701 static object *
702 posix_setpgrp(self, args)
703 object *self;
704 object *args;
706 if (!getnoarg(args))
707 return NULL;
708 #ifdef SYSV
709 if (setpgrp() < 0)
710 #else
711 if (setpgrp(0, 0) < 0)
712 #endif
713 return posix_error();
714 INCREF(None);
715 return None;
718 static object *
719 posix_getppid(self, args)
720 object *self;
721 object *args;
723 if (!getnoarg(args))
724 return NULL;
725 return newintobject((long)getppid());
728 static object *
729 posix_getuid(self, args)
730 object *self;
731 object *args;
733 if (!getnoarg(args))
734 return NULL;
735 return newintobject((long)getuid());
738 static object *
739 posix_kill(self, args)
740 object *self;
741 object *args;
743 int pid, sig;
744 if (!getargs(args, "(ii)", &pid, &sig))
745 return NULL;
746 if (kill(pid, sig) == -1)
747 return posix_error();
748 INCREF(None);
749 return None;
752 static object *
753 posix_popen(self, args)
754 object *self;
755 object *args;
757 char *name, *mode;
758 FILE *fp;
759 if (!getargs(args, "(ss)", &name, &mode))
760 return NULL;
761 BGN_SAVE
762 fp = popen(name, mode);
763 END_SAVE
764 if (fp == NULL)
765 return posix_error();
766 /* From now on, ignore SIGPIPE and let the error checking
767 do the work. */
768 (void) signal(SIGPIPE, SIG_IGN);
769 return newopenfileobject(fp, name, mode, pclose);
772 static object *
773 posix_setuid(self, args)
774 object *self;
775 object *args;
777 int uid;
778 if (!getargs(args, "i", &uid))
779 return NULL;
780 if (setuid(uid) < 0)
781 return posix_error();
782 INCREF(None);
783 return None;
786 static object *
787 posix_setgid(self, args)
788 object *self;
789 object *args;
791 int gid;
792 if (!getargs(args, "i", &gid))
793 return NULL;
794 if (setgid(gid) < 0)
795 return posix_error();
796 INCREF(None);
797 return None;
800 static object *
801 posix_waitpid(self, args)
802 object *self;
803 object *args;
805 #ifdef NO_WAITPID
806 err_setstr(PosixError,
807 "posix.waitpid() not supported on this system");
808 return NULL;
809 #else
810 int pid, options, sts;
811 if (!getargs(args, "(ii)", &pid, &options))
812 return NULL;
813 BGN_SAVE
814 pid = waitpid(pid, &sts, options);
815 END_SAVE
816 if (pid == -1)
817 return posix_error();
818 else
819 return mkvalue("ii", pid, sts);
820 #endif
823 static object *
824 posix_wait(self, args)
825 object *self;
826 object *args;
828 int pid, sts;
829 if (args != NULL)
830 return posix_waitpid(self, args); /* BW compat */
831 BGN_SAVE
832 pid = wait(&sts);
833 END_SAVE
834 if (pid == -1)
835 return posix_error();
836 else
837 return mkvalue("ii", pid, sts);
840 static object *
841 posix_lstat(self, args)
842 object *self;
843 object *args;
845 return posix_do_stat(self, args, lstat);
848 static object *
849 posix_readlink(self, args)
850 object *self;
851 object *args;
853 #ifdef NO_LSTAT
854 err_setstr(PosixError, "readlink not implemented on this system");
855 return NULL;
856 #else
857 char buf[1024]; /* XXX Should use MAXPATHLEN */
858 char *path;
859 int n;
860 if (!getargs(args, "s", &path))
861 return NULL;
862 BGN_SAVE
863 n = readlink(path, buf, (int) sizeof buf);
864 END_SAVE
865 if (n < 0)
866 return posix_error();
867 return newsizedstringobject(buf, n);
868 #endif
871 static object *
872 posix_symlink(self, args)
873 object *self;
874 object *args;
876 #ifdef NO_LSTAT
877 err_setstr(PosixError, "symlink not implemented on this system");
878 return NULL;
879 #else
880 return posix_2str(args, symlink);
881 #endif
885 #ifdef DO_TIMES
887 static object *
888 posix_times(self, args)
889 object *self;
890 object *args;
892 struct tms t;
893 clock_t c;
894 if (!getnoarg(args))
895 return NULL;
896 errno = 0;
897 c = times(&t);
898 if (c == (clock_t) -1)
899 return posix_error();
900 return mkvalue("dddd",
901 (double)t.tms_utime / HZ,
902 (double)t.tms_stime / HZ,
903 (double)t.tms_cutime / HZ,
904 (double)t.tms_cstime / HZ);
907 #endif /* DO_TIMES */
909 #ifdef DO_PG
911 static object *
912 posix_setsid(self, args)
913 object *self;
914 object *args;
916 if (!getnoarg(args))
917 return NULL;
918 if (setsid() < 0)
919 return posix_error();
920 INCREF(None);
921 return None;
924 static object *
925 posix_setpgid(self, args)
926 object *self;
927 object *args;
929 int pid, pgrp;
930 if (!getargs(args, "(ii)", &pid, &pgrp))
931 return NULL;
932 if (setpgid(pid, pgrp) < 0)
933 return posix_error();
934 INCREF(None);
935 return None;
938 static object *
939 posix_tcgetpgrp(self, args)
940 object *self;
941 object *args;
943 int fd, pgid;
944 if (!getargs(args, "i", &fd))
945 return NULL;
946 pgid = tcgetpgrp(fd);
947 if (pgid < 0)
948 return posix_error();
949 return newintobject((long)pgid);
952 static object *
953 posix_tcsetpgrp(self, args)
954 object *self;
955 object *args;
957 int fd, pgid;
958 if (!getargs(args, "(ii)", &fd, &pgid))
959 return NULL;
960 if (tcsetpgrp(fd, pgid) < 0)
961 return posix_error();
962 INCREF(None);
963 return None;
966 #endif /* DO_PG */
968 /* Functions acting on file descriptors */
970 static object *
971 posix_open(self, args)
972 object *self;
973 object *args;
975 char *file;
976 int flag;
977 int mode = 0777;
978 int fd;
979 if (!getargs(args, "(si)", &file, &flag)) {
980 err_clear();
981 if (!getargs(args, "(sii)", &file, &flag, &mode))
982 return NULL;
984 BGN_SAVE
985 fd = open(file, flag, mode);
986 END_SAVE
987 if (fd < 0)
988 return posix_error();
989 return newintobject((long)fd);
992 static object *
993 posix_close(self, args)
994 object *self;
995 object *args;
997 int fd, res;
998 if (!getargs(args, "i", &fd))
999 return NULL;
1000 BGN_SAVE
1001 res = close(fd);
1002 END_SAVE
1003 if (res < 0)
1004 return posix_error();
1005 INCREF(None);
1006 return None;
1009 static object *
1010 posix_dup(self, args)
1011 object *self;
1012 object *args;
1014 int fd;
1015 if (!getargs(args, "i", &fd))
1016 return NULL;
1017 BGN_SAVE
1018 fd = dup(fd);
1019 END_SAVE
1020 if (fd < 0)
1021 return posix_error();
1022 return newintobject((long)fd);
1025 static object *
1026 posix_dup2(self, args)
1027 object *self;
1028 object *args;
1030 int fd, fd2, res;
1031 if (!getargs(args, "(ii)", &fd, &fd2))
1032 return NULL;
1033 BGN_SAVE
1034 res = dup2(fd, fd2);
1035 END_SAVE
1036 if (res < 0)
1037 return posix_error();
1038 INCREF(None);
1039 return None;
1042 static object *
1043 posix_lseek(self, args)
1044 object *self;
1045 object *args;
1047 int fd, how;
1048 long pos, res;
1049 if (!getargs(args, "(ili)", &fd, &pos, &how))
1050 return NULL;
1051 #ifdef SEEK_SET
1052 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
1053 switch (how) {
1054 case 0: how = SEEK_SET; break;
1055 case 1: how = SEEK_CUR; break;
1056 case 2: how = SEEK_END; break;
1058 #endif
1059 BGN_SAVE
1060 res = lseek(fd, pos, how);
1061 END_SAVE
1062 if (res < 0)
1063 return posix_error();
1064 return newintobject(res);
1067 static object *
1068 posix_read(self, args)
1069 object *self;
1070 object *args;
1072 int fd, size;
1073 object *buffer;
1074 if (!getargs(args, "(ii)", &fd, &size))
1075 return NULL;
1076 buffer = newsizedstringobject((char *)NULL, size);
1077 if (buffer == NULL)
1078 return NULL;
1079 BGN_SAVE
1080 size = read(fd, getstringvalue(buffer), size);
1081 END_SAVE
1082 if (size < 0) {
1083 DECREF(buffer);
1084 return posix_error();
1086 resizestring(&buffer, size);
1087 return buffer;
1090 static object *
1091 posix_write(self, args)
1092 object *self;
1093 object *args;
1095 int fd, size;
1096 char *buffer;
1097 if (!getargs(args, "(is#)", &fd, &buffer, &size))
1098 return NULL;
1099 BGN_SAVE
1100 size = write(fd, buffer, size);
1101 END_SAVE
1102 if (size < 0)
1103 return posix_error();
1104 return newintobject((long)size);
1107 static object *
1108 posix_fstat(self, args)
1109 object *self;
1110 object *args;
1112 int fd;
1113 struct stat st;
1114 int res;
1115 if (!getargs(args, "i", &fd))
1116 return NULL;
1117 BGN_SAVE
1118 res = fstat(fd, &st);
1119 END_SAVE
1120 if (res != 0)
1121 return posix_error();
1122 return mkvalue("(llllllllll)",
1123 (long)st.st_mode,
1124 (long)st.st_ino,
1125 (long)st.st_dev,
1126 (long)st.st_nlink,
1127 (long)st.st_uid,
1128 (long)st.st_gid,
1129 (long)st.st_size,
1130 (long)st.st_atime,
1131 (long)st.st_mtime,
1132 (long)st.st_ctime);
1135 static object *
1136 posix_fdopen(self, args)
1137 object *self;
1138 object *args;
1140 extern int fclose PROTO((FILE *));
1141 int fd;
1142 char *mode;
1143 FILE *fp;
1144 if (!getargs(args, "(is)", &fd, &mode))
1145 return NULL;
1146 BGN_SAVE
1147 fp = fdopen(fd, mode);
1148 END_SAVE
1149 if (fp == NULL)
1150 return posix_error();
1151 /* From now on, ignore SIGPIPE and let the error checking
1152 do the work. */
1153 (void) signal(SIGPIPE, SIG_IGN);
1154 return newopenfileobject(fp, "(fdopen)", mode, fclose);
1157 static object *
1158 posix_pipe(self, args)
1159 object *self;
1160 object *args;
1162 int fds[2];
1163 int res;
1164 if (!getargs(args, ""))
1165 return NULL;
1166 BGN_SAVE
1167 res = pipe(fds);
1168 END_SAVE
1169 if (res != 0)
1170 return posix_error();
1171 return mkvalue("(ii)", fds[0], fds[1]);
1174 static struct methodlist posix_methods[] = {
1175 {"chdir", posix_chdir},
1176 {"chmod", posix_chmod},
1177 {"getcwd", posix_getcwd},
1178 {"link", posix_link},
1179 {"listdir", posix_listdir},
1180 {"lstat", posix_lstat},
1181 {"mkdir", posix_mkdir},
1182 {"nice", posix_nice},
1183 {"readlink", posix_readlink},
1184 {"rename", posix_rename},
1185 {"rmdir", posix_rmdir},
1186 {"stat", posix_stat},
1187 {"symlink", posix_symlink},
1188 {"system", posix_system},
1189 {"umask", posix_umask},
1190 #ifndef NO_UNAME
1191 {"uname", posix_uname},
1192 #endif
1193 {"unlink", posix_unlink},
1194 {"utime", posix_utime},
1195 #ifdef DO_TIMES
1196 {"times", posix_times},
1197 #endif
1198 {"_exit", posix__exit},
1199 {"execv", posix_execv},
1200 {"execve", posix_execve},
1201 {"fork", posix_fork},
1202 {"getegid", posix_getegid},
1203 {"geteuid", posix_geteuid},
1204 {"getgid", posix_getgid},
1205 {"getpid", posix_getpid},
1206 {"getpgrp", posix_getpgrp},
1207 {"getppid", posix_getppid},
1208 {"getuid", posix_getuid},
1209 {"kill", posix_kill},
1210 {"popen", posix_popen},
1211 {"setuid", posix_setuid},
1212 {"setgid", posix_setgid},
1213 {"setpgrp", posix_setpgrp},
1214 {"wait", posix_wait},
1215 {"waitpid", posix_waitpid},
1216 #ifdef DO_PG
1217 {"setsid", posix_setsid},
1218 {"setpgid", posix_setpgid},
1219 {"tcgetpgrp", posix_tcgetpgrp},
1220 {"tcsetpgrp", posix_tcsetpgrp},
1221 #endif
1222 {"open", posix_open},
1223 {"close", posix_close},
1224 {"dup", posix_dup},
1225 {"dup2", posix_dup2},
1226 {"lseek", posix_lseek},
1227 {"read", posix_read},
1228 {"write", posix_write},
1229 {"fstat", posix_fstat},
1230 {"fdopen", posix_fdopen},
1231 {"pipe", posix_pipe},
1233 {NULL, NULL} /* Sentinel */
1237 void
1238 initposix()
1240 object *m, *d, *v;
1242 m = initmodule("posix", posix_methods);
1243 d = getmoduledict(m);
1245 /* Initialize posix.environ dictionary */
1246 v = convertenviron();
1247 if (v == NULL || dictinsert(d, "environ", v) != 0)
1248 fatal("can't define posix.environ");
1249 DECREF(v);
1251 /* Initialize posix.error exception */
1252 PosixError = newstringobject("posix.error");
1253 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1254 fatal("can't define posix.error");
1258 /* Function used elsewhere to get a file's modification time */
1260 long
1261 getmtime(path)
1262 char *path;
1264 struct stat st;
1265 if (stat(path, &st) != 0)
1266 return -1;
1267 else
1268 return st.st_mtime;