improve treatment of multi-line replies, ignore empty lines
[python/dscho.git] / Modules / posixmodule.c
blob8631e649a75bd173a3c252fa574d46f459cab082
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 #include "allobjects.h"
28 #include "modsupport.h"
29 #include "ceval.h"
31 #include <string.h>
32 #include <errno.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
36 #include "mytime.h" /* For clock_t on some systems */
38 #ifdef HAVE_FCNTL_H
39 #include <fcntl.h>
40 #endif /* HAVE_FCNTL_H */
42 #ifndef NT
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #else /* !HAVE_UNISTD_H */
46 extern int mkdir PROTO((const char *, mode_t));
47 extern int chdir PROTO((const char *));
48 extern int rmdir PROTO((const char *));
49 extern int chmod PROTO((const char *, mode_t));
50 extern int chown PROTO((const char *, uid_t, gid_t));
51 extern char *getcwd PROTO((char *, int));
52 extern char *strerror PROTO((int));
53 extern int link PROTO((const char *, const char *));
54 extern int rename PROTO((const char *, const char *));
55 extern int stat PROTO((const char *, struct stat *));
56 extern int unlink PROTO((const char *));
57 extern int pclose PROTO((FILE *));
58 #ifdef HAVE_SYMLINK
59 extern int symlink PROTO((const char *, const char *));
60 #endif /_ HAVE_SYMLINK */
61 #ifdef HAVE_LSTAT
62 extern int lstat PROTO((const char *, struct stat *));
63 #endif /* HAVE_LSTAT */
64 #endif /* !HAVE_UNISTD_H */
65 #endif /* !NT */
67 #ifndef NT
68 /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
69 extern int rename();
70 extern int pclose();
71 extern int lstat();
72 extern int symlink();
73 #endif /* !NT */
75 #ifdef HAVE_UTIME_H
76 #include <utime.h>
77 #endif /* HAVE_UTIME_H */
79 #ifdef HAVE_SYS_UTIME_H
80 #include <sys/utime.h>
81 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
82 #endif /* HAVE_SYS_UTIME_H */
84 #ifdef HAVE_SYS_TIMES_H
85 #include <sys/times.h>
86 #endif /* HAVE_SYS_TIMES_H */
88 #ifdef HAVE_SYS_PARAM_H
89 #include <sys/param.h>
90 #endif /* HAVE_SYS_PARAM_H */
92 #ifdef HAVE_SYS_UTSNAME_H
93 #include <sys/utsname.h>
94 #endif /* HAVE_SYS_UTSNAME_H */
96 #ifndef MAXPATHLEN
97 #define MAXPATHLEN 1024
98 #endif /* MAXPATHLEN */
100 #ifdef HAVE_DIRENT_H
101 #include <dirent.h>
102 #define NAMLEN(dirent) strlen((dirent)->d_name)
103 #else
104 #define dirent direct
105 #define NAMLEN(dirent) (dirent)->d_namlen
106 #ifdef HAVE_SYS_NDIR_H
107 #include <sys/ndir.h>
108 #endif
109 #ifdef HAVE_SYS_DIR_H
110 #include <sys/dir.h>
111 #endif
112 #ifdef HAVE_NDIR_H
113 #include <ndir.h>
114 #endif
115 #endif
117 #ifdef NT
118 #include <direct.h>
119 #include <io.h>
120 #include <process.h>
121 #include <windows.h>
122 #define popen _popen
123 #define pclose _pclose
124 #endif /* NT */
126 #ifdef OS2
127 #include <io.h>
128 #endif /* OS2 */
130 /* Return a dictionary corresponding to the POSIX environment table */
132 #ifndef NT
133 extern char **environ;
134 #endif /* !NT */
136 static object *
137 convertenviron()
139 object *d;
140 char **e;
141 d = newdictobject();
142 if (d == NULL)
143 return NULL;
144 if (environ == NULL)
145 return d;
146 /* XXX This part ignores errors */
147 for (e = environ; *e != NULL; e++) {
148 object *v;
149 char *p = strchr(*e, '=');
150 if (p == NULL)
151 continue;
152 v = newstringobject(p+1);
153 if (v == NULL)
154 continue;
155 *p = '\0';
156 (void) dictinsert(d, *e, v);
157 *p = '=';
158 DECREF(v);
160 return d;
164 static object *PosixError; /* Exception posix.error */
166 /* Set a POSIX-specific error from errno, and return NULL */
168 static object * posix_error() { return err_errno(PosixError);
172 /* POSIX generic methods */
174 static object *
175 posix_1str(args, func)
176 object *args;
177 int (*func) FPROTO((const char *));
179 char *path1;
180 int res;
181 if (!getargs(args, "s", &path1))
182 return NULL;
183 BGN_SAVE
184 res = (*func)(path1);
185 END_SAVE
186 if (res < 0)
187 return posix_error();
188 INCREF(None);
189 return None;
192 static object *
193 posix_2str(args, func)
194 object *args;
195 int (*func) FPROTO((const char *, const char *));
197 char *path1, *path2;
198 int res;
199 if (!getargs(args, "(ss)", &path1, &path2))
200 return NULL;
201 BGN_SAVE
202 res = (*func)(path1, path2);
203 END_SAVE
204 if (res < 0)
205 return posix_error();
206 INCREF(None);
207 return None;
210 static object *
211 posix_strint(args, func)
212 object *args;
213 int (*func) FPROTO((const char *, int));
215 char *path;
216 int i;
217 int res;
218 if (!getargs(args, "(si)", &path, &i))
219 return NULL;
220 BGN_SAVE
221 res = (*func)(path, i);
222 END_SAVE
223 if (res < 0)
224 return posix_error();
225 INCREF(None);
226 return None;
229 static object *
230 posix_strintint(args, func)
231 object *args;
232 int (*func) FPROTO((const char *, int, int));
234 char *path;
235 int i,i2;
236 int res;
237 if (!getargs(args, "(sii)", &path, &i, &i2))
238 return NULL;
239 BGN_SAVE
240 res = (*func)(path, i, i2);
241 END_SAVE
242 if (res < 0)
243 return posix_error();
244 INCREF(None);
245 return None;
248 static object *
249 posix_do_stat(self, args, statfunc)
250 object *self;
251 object *args;
252 int (*statfunc) FPROTO((const char *, struct stat *));
254 struct stat st;
255 char *path;
256 int res;
257 if (!getargs(args, "s", &path))
258 return NULL;
259 BGN_SAVE
260 res = (*statfunc)(path, &st);
261 END_SAVE
262 if (res != 0)
263 return posix_error();
264 return mkvalue("(llllllllll)",
265 (long)st.st_mode,
266 (long)st.st_ino,
267 (long)st.st_dev,
268 (long)st.st_nlink,
269 (long)st.st_uid,
270 (long)st.st_gid,
271 (long)st.st_size,
272 (long)st.st_atime,
273 (long)st.st_mtime,
274 (long)st.st_ctime);
278 /* POSIX methods */
280 static object *
281 posix_chdir(self, args)
282 object *self;
283 object *args;
285 return posix_1str(args, chdir);
288 static object *
289 posix_chmod(self, args)
290 object *self;
291 object *args;
293 return posix_strint(args, chmod);
296 #ifdef HAVE_CHOWN
297 static object *
298 posix_chown(self, args)
299 object *self;
300 object *args;
302 return posix_strintint(args, chown);
304 #endif /* HAVE_CHOWN */
306 static object *
307 posix_getcwd(self, args)
308 object *self;
309 object *args;
311 char buf[1026];
312 char *res;
313 if (!getnoarg(args))
314 return NULL;
315 BGN_SAVE
316 res = getcwd(buf, sizeof buf);
317 END_SAVE
318 if (res == NULL)
319 return posix_error();
320 return newstringobject(buf);
323 #ifdef HAVE_LINK
324 static object *
325 posix_link(self, args)
326 object *self;
327 object *args;
329 return posix_2str(args, link);
331 #endif /* HAVE_LINK */
333 static object *
334 posix_listdir(self, args)
335 object *self;
336 object *args;
338 #ifdef NT
340 char *name;
341 int len;
342 object *d, *v;
343 HANDLE hFindFile;
344 WIN32_FIND_DATA FileData;
345 char namebuf[MAX_PATH+5];
347 if (!getargs(args, "s#", &name, &len))
348 return NULL;
349 if (len >= MAX_PATH) {
350 err_setstr(ValueError, "path too long");
351 return NULL;
353 strcpy(namebuf, name);
354 if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
355 namebuf[len++] = '/';
356 strcpy(namebuf + len, "*.*");
358 if ((d = newlistobject(0)) == NULL)
359 return NULL;
361 hFindFile = FindFirstFile(namebuf, &FileData);
362 if (hFindFile == INVALID_HANDLE_VALUE) {
363 errno = GetLastError();
364 return posix_error();
366 do {
367 v = newstringobject(FileData.cFileName);
368 if (v == NULL) {
369 DECREF(d);
370 d = NULL;
371 break;
373 if (addlistitem(d, v) != 0) {
374 DECREF(v);
375 DECREF(d);
376 d = NULL;
377 break;
379 DECREF(v);
380 } while (FindNextFile(hFindFile, &FileData) == TRUE);
382 if (FindClose(hFindFile) == FALSE) {
383 errno = GetLastError();
384 return posix_error();
387 return d;
389 #else /* !NT */
391 char *name;
392 object *d, *v;
393 DIR *dirp;
394 struct dirent *ep;
395 if (!getargs(args, "s", &name))
396 return NULL;
397 BGN_SAVE
398 if ((dirp = opendir(name)) == NULL) {
399 RET_SAVE
400 return posix_error();
402 if ((d = newlistobject(0)) == NULL) {
403 closedir(dirp);
404 RET_SAVE
405 return NULL;
407 while ((ep = readdir(dirp)) != NULL) {
408 v = newsizedstringobject(ep->d_name, NAMLEN(ep));
409 if (v == NULL) {
410 DECREF(d);
411 d = NULL;
412 break;
414 if (addlistitem(d, v) != 0) {
415 DECREF(v);
416 DECREF(d);
417 d = NULL;
418 break;
420 DECREF(v);
422 closedir(dirp);
423 END_SAVE
425 return d;
427 #endif /* !NT */
430 static object *
431 posix_mkdir(self, args)
432 object *self;
433 object *args;
435 return posix_strint(args, mkdir);
438 #ifdef HAVE_NICE
439 static object *
440 posix_nice(self, args)
441 object *self;
442 object *args;
444 int increment, value;
446 if (!getargs(args, "i", &increment))
447 return NULL;
448 value = nice(increment);
449 if (value == -1)
450 return posix_error();
451 return newintobject((long) value);
453 #endif /* HAVE_NICE */
455 static object *
456 posix_rename(self, args)
457 object *self;
458 object *args;
460 return posix_2str(args, rename);
463 static object *
464 posix_rmdir(self, args)
465 object *self;
466 object *args;
468 return posix_1str(args, rmdir);
471 static object *
472 posix_stat(self, args)
473 object *self;
474 object *args;
476 return posix_do_stat(self, args, stat);
479 static object *
480 posix_system(self, args)
481 object *self;
482 object *args;
484 char *command;
485 long sts;
486 if (!getargs(args, "s", &command))
487 return NULL;
488 BGN_SAVE
489 sts = system(command);
490 END_SAVE
491 return newintobject(sts);
494 static object *
495 posix_umask(self, args)
496 object *self;
497 object *args;
499 int i;
500 if (!getintarg(args, &i))
501 return NULL;
502 i = umask(i);
503 if (i < 0)
504 return posix_error();
505 return newintobject((long)i);
508 static object *
509 posix_unlink(self, args)
510 object *self;
511 object *args;
513 return posix_1str(args, unlink);
516 #ifdef HAVE_UNAME
517 static object *
518 posix_uname(self, args)
519 object *self;
520 object *args;
522 struct utsname u;
523 object *v;
524 int res;
525 if (!getnoarg(args))
526 return NULL;
527 BGN_SAVE
528 res = uname(&u);
529 END_SAVE
530 if (res < 0)
531 return posix_error();
532 return mkvalue("(sssss)",
533 u.sysname,
534 u.nodename,
535 u.release,
536 u.version,
537 u.machine);
539 #endif /* HAVE_UNAME */
541 static object *
542 posix_utime(self, args)
543 object *self;
544 object *args;
546 char *path;
547 int res;
549 #ifdef HAVE_UTIME_H
550 struct utimbuf buf;
551 #define ATIME buf.actime
552 #define MTIME buf.modtime
553 #define UTIME_ARG &buf
554 #else /* HAVE_UTIME_H */
555 time_t buf[2];
556 #define ATIME buf[0]
557 #define MTIME buf[1]
558 #define UTIME_ARG buf
559 #endif /* HAVE_UTIME_H */
561 if (!getargs(args, "(s(ll))", &path, &ATIME, &MTIME))
562 return NULL;
563 BGN_SAVE
564 res = utime(path, UTIME_ARG);
565 END_SAVE
566 if (res < 0)
567 return posix_error();
568 INCREF(None);
569 return None;
570 #undef UTIME_ARG
571 #undef ATIME
572 #undef MTIME
576 /* Process operations */
578 static object *
579 posix__exit(self, args)
580 object *self;
581 object *args;
583 int sts;
584 if (!getintarg(args, &sts))
585 return NULL;
586 _exit(sts);
587 /* NOTREACHED */
590 static object *
591 posix_execv(self, args)
592 object *self;
593 object *args;
595 char *path;
596 object *argv;
597 char **argvlist;
598 int i, argc;
599 object *(*getitem) PROTO((object *, int));
601 /* execv has two arguments: (path, argv), where
602 argv is a list or tuple of strings. */
604 if (!getargs(args, "(sO)", &path, &argv))
605 return NULL;
606 if (is_listobject(argv)) {
607 argc = getlistsize(argv);
608 getitem = getlistitem;
610 else if (is_tupleobject(argv)) {
611 argc = gettuplesize(argv);
612 getitem = gettupleitem;
614 else {
615 badarg:
616 err_badarg();
617 return NULL;
620 argvlist = NEW(char *, argc+1);
621 if (argvlist == NULL)
622 return NULL;
623 for (i = 0; i < argc; i++) {
624 if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
625 DEL(argvlist);
626 goto badarg;
629 argvlist[argc] = NULL;
631 #ifdef BAD_EXEC_PROTOTYPES
632 execv(path, (const char **) argvlist);
633 #else /* BAD_EXEC_PROTOTYPES */
634 execv(path, argvlist);
635 #endif /* BAD_EXEC_PROTOTYPES */
637 /* If we get here it's definitely an error */
639 DEL(argvlist);
640 return posix_error();
643 static object *
644 posix_execve(self, args)
645 object *self;
646 object *args;
648 char *path;
649 object *argv, *env;
650 char **argvlist;
651 char **envlist;
652 object *key, *val;
653 int i, pos, argc, envc;
654 object *(*getitem) PROTO((object *, int));
656 /* execve has three arguments: (path, argv, env), where
657 argv is a list or tuple of strings and env is a dictionary
658 like posix.environ. */
660 if (!getargs(args, "(sOO)", &path, &argv, &env))
661 return NULL;
662 if (is_listobject(argv)) {
663 argc = getlistsize(argv);
664 getitem = getlistitem;
666 else if (is_tupleobject(argv)) {
667 argc = gettuplesize(argv);
668 getitem = gettupleitem;
670 else {
671 err_setstr(TypeError, "argv must be tuple or list");
672 return NULL;
674 if (!is_dictobject(env)) {
675 err_setstr(TypeError, "env must be dictionary");
676 return NULL;
679 argvlist = NEW(char *, argc+1);
680 if (argvlist == NULL) {
681 err_nomem();
682 return NULL;
684 for (i = 0; i < argc; i++) {
685 if (!getargs((*getitem)(argv, i),
686 "s;argv must be list of strings",
687 &argvlist[i])) {
688 goto fail_1;
691 argvlist[argc] = NULL;
693 i = getmappingsize(env);
694 envlist = NEW(char *, i + 1);
695 if (envlist == NULL) {
696 err_nomem();
697 goto fail_1;
699 pos = 0;
700 envc = 0;
701 while (mappinggetnext(env, &pos, &key, &val)) {
702 char *p, *k, *v;
703 if (!getargs(key, "s;non-string key in env", &k) ||
704 !getargs(val, "s;non-string value in env", &v)) {
705 goto fail_2;
707 p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
708 if (p == NULL) {
709 err_nomem();
710 goto fail_2;
712 sprintf(p, "%s=%s", k, v);
713 envlist[envc++] = p;
715 envlist[envc] = 0;
718 #ifdef BAD_EXEC_PROTOTYPES
719 execve(path, (const char **)argvlist, envlist);
720 #else /* BAD_EXEC_PROTOTYPES */
721 execve(path, argvlist, envlist);
722 #endif /* BAD_EXEC_PROTOTYPES */
724 /* If we get here it's definitely an error */
726 (void) posix_error();
728 fail_2:
729 while (--envc >= 0)
730 DEL(envlist[envc]);
731 DEL(envlist);
732 fail_1:
733 DEL(argvlist);
735 return NULL;
738 #ifndef NT
739 static object *
740 posix_fork(self, args)
741 object *self;
742 object *args;
744 int pid;
745 if (!getnoarg(args))
746 return NULL;
747 pid = fork();
748 if (pid == -1)
749 return posix_error();
750 return newintobject((long)pid);
753 static object *
754 posix_getegid(self, args)
755 object *self;
756 object *args;
758 if (!getnoarg(args))
759 return NULL;
760 return newintobject((long)getegid());
763 static object *
764 posix_geteuid(self, args)
765 object *self;
766 object *args;
768 if (!getnoarg(args))
769 return NULL;
770 return newintobject((long)geteuid());
773 static object *
774 posix_getgid(self, args)
775 object *self;
776 object *args;
778 if (!getnoarg(args))
779 return NULL;
780 return newintobject((long)getgid());
782 #endif /* !NT */
784 static object *
785 posix_getpid(self, args)
786 object *self;
787 object *args;
789 if (!getnoarg(args))
790 return NULL;
791 return newintobject((long)getpid());
794 #ifdef HAVE_GETPGRP
795 static object *
796 posix_getpgrp(self, args)
797 object *self;
798 object *args;
800 if (!getnoarg(args))
801 return NULL;
802 #ifdef GETPGRP_HAVE_ARG
803 return newintobject((long)getpgrp(0));
804 #else /* GETPGRP_HAVE_ARG */
805 return newintobject((long)getpgrp());
806 #endif /* GETPGRP_HAVE_ARG */
808 #endif /* HAVE_GETPGRP */
810 #ifdef HAVE_SETPGRP
811 static object *
812 posix_setpgrp(self, args)
813 object *self;
814 object *args;
816 if (!getnoarg(args))
817 return NULL;
818 #ifdef SETPGRP_HAVE_ARG
819 if (setpgrp(0, 0) < 0)
820 #else /* SETPGRP_HAVE_ARG */
821 if (setpgrp() < 0)
822 #endif /* SETPGRP_HAVE_ARG */
823 return posix_error();
824 INCREF(None);
825 return None;
828 #endif /* HAVE_SETPGRP */
830 #ifndef NT
831 static object *
832 posix_getppid(self, args)
833 object *self;
834 object *args;
836 if (!getnoarg(args))
837 return NULL;
838 return newintobject((long)getppid());
841 static object *
842 posix_getuid(self, args)
843 object *self;
844 object *args;
846 if (!getnoarg(args))
847 return NULL;
848 return newintobject((long)getuid());
851 static object *
852 posix_kill(self, args)
853 object *self;
854 object *args;
856 int pid, sig;
857 if (!getargs(args, "(ii)", &pid, &sig))
858 return NULL;
859 if (kill(pid, sig) == -1)
860 return posix_error();
861 INCREF(None);
862 return None;
864 #endif /* !NT */
866 static object *
867 posix_popen(self, args)
868 object *self;
869 object *args;
871 char *name;
872 char *mode = "r";
873 int bufsize = -1;
874 FILE *fp;
875 object *f;
876 if (!newgetargs(args, "s|si", &name, &mode, &bufsize))
877 return NULL;
878 BGN_SAVE
879 fp = popen(name, mode);
880 END_SAVE
881 if (fp == NULL)
882 return posix_error();
883 f = newopenfileobject(fp, name, mode, pclose);
884 if (f != NULL)
885 setfilebufsize(f, bufsize);
886 return f;
889 #ifdef HAVE_SETUID
890 static object *
891 posix_setuid(self, args)
892 object *self;
893 object *args;
895 int uid;
896 if (!getargs(args, "i", &uid))
897 return NULL;
898 if (setuid(uid) < 0)
899 return posix_error();
900 INCREF(None);
901 return None;
903 #endif /* HAVE_SETUID */
905 #ifdef HAVE_SETGID
906 static object *
907 posix_setgid(self, args)
908 object *self;
909 object *args;
911 int gid;
912 if (!getargs(args, "i", &gid))
913 return NULL;
914 if (setgid(gid) < 0)
915 return posix_error();
916 INCREF(None);
917 return None;
919 #endif /* HAVE_SETGID */
921 #ifdef HAVE_WAITPID
922 static object *
923 posix_waitpid(self, args)
924 object *self;
925 object *args;
927 int pid, options, sts;
928 if (!getargs(args, "(ii)", &pid, &options))
929 return NULL;
930 BGN_SAVE
931 pid = waitpid(pid, &sts, options);
932 END_SAVE
933 if (pid == -1)
934 return posix_error();
935 else
936 return mkvalue("ii", pid, sts);
938 #endif /* HAVE_WAITPID */
940 #ifndef NT
941 static object *
942 posix_wait(self, args)
943 object *self;
944 object *args;
946 int pid, sts;
947 BGN_SAVE
948 pid = wait(&sts);
949 END_SAVE
950 if (pid == -1)
951 return posix_error();
952 else
953 return mkvalue("ii", pid, sts);
955 #endif /* !NT */
957 static object *
958 posix_lstat(self, args)
959 object *self;
960 object *args;
962 #ifdef HAVE_LSTAT
963 return posix_do_stat(self, args, lstat);
964 #else /* !HAVE_LSTAT */
965 return posix_do_stat(self, args, stat);
966 #endif /* !HAVE_LSTAT */
969 #ifdef HAVE_READLINK
970 static object *
971 posix_readlink(self, args)
972 object *self;
973 object *args;
975 char buf[MAXPATHLEN];
976 char *path;
977 int n;
978 if (!getargs(args, "s", &path))
979 return NULL;
980 BGN_SAVE
981 n = readlink(path, buf, (int) sizeof buf);
982 END_SAVE
983 if (n < 0)
984 return posix_error();
985 return newsizedstringobject(buf, n);
987 #endif /* HAVE_READLINK */
989 #ifdef HAVE_SYMLINK
990 static object *
991 posix_symlink(self, args)
992 object *self;
993 object *args;
995 return posix_2str(args, symlink);
997 #endif /* HAVE_SYMLINK */
999 #ifdef HAVE_TIMES
1000 #ifndef HZ
1001 #define HZ 60 /* Universal constant :-) */
1002 #endif /* HZ */
1003 static object *
1004 posix_times(self, args)
1005 object *self;
1006 object *args;
1008 struct tms t;
1009 clock_t c;
1010 if (!getnoarg(args))
1011 return NULL;
1012 errno = 0;
1013 c = times(&t);
1014 if (c == (clock_t) -1)
1015 return posix_error();
1016 return mkvalue("dddd",
1017 (double)t.tms_utime / HZ,
1018 (double)t.tms_stime / HZ,
1019 (double)t.tms_cutime / HZ,
1020 (double)t.tms_cstime / HZ);
1022 #endif /* HAVE_TIMES */
1023 #ifdef NT
1024 #define HAVE_TIMES /* so the method table will pick it up */
1025 static object *
1026 posix_times(self, args)
1027 object *self;
1028 object *args;
1030 FILETIME create, exit, kernel, user;
1031 HANDLE hProc;
1032 if (!getnoarg(args))
1033 return NULL;
1034 hProc = GetCurrentProcess();
1035 GetProcessTimes(hProc,&create, &exit, &kernel, &user);
1036 return mkvalue("dddd",
1037 (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6,
1038 (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
1039 (double)0,
1040 (double)0);
1042 #endif /* NT */
1044 #ifdef HAVE_SETSID
1045 static object *
1046 posix_setsid(self, args)
1047 object *self;
1048 object *args;
1050 if (!getnoarg(args))
1051 return NULL;
1052 if (setsid() < 0)
1053 return posix_error();
1054 INCREF(None);
1055 return None;
1057 #endif /* HAVE_SETSID */
1059 #ifdef HAVE_SETPGID
1060 static object *
1061 posix_setpgid(self, args)
1062 object *self;
1063 object *args;
1065 int pid, pgrp;
1066 if (!getargs(args, "(ii)", &pid, &pgrp))
1067 return NULL;
1068 if (setpgid(pid, pgrp) < 0)
1069 return posix_error();
1070 INCREF(None);
1071 return None;
1073 #endif /* HAVE_SETPGID */
1075 #ifdef HAVE_TCGETPGRP
1076 static object *
1077 posix_tcgetpgrp(self, args)
1078 object *self;
1079 object *args;
1081 int fd, pgid;
1082 if (!getargs(args, "i", &fd))
1083 return NULL;
1084 pgid = tcgetpgrp(fd);
1085 if (pgid < 0)
1086 return posix_error();
1087 return newintobject((long)pgid);
1089 #endif /* HAVE_TCGETPGRP */
1091 #ifdef HAVE_TCSETPGRP
1092 static object *
1093 posix_tcsetpgrp(self, args)
1094 object *self;
1095 object *args;
1097 int fd, pgid;
1098 if (!getargs(args, "(ii)", &fd, &pgid))
1099 return NULL;
1100 if (tcsetpgrp(fd, pgid) < 0)
1101 return posix_error();
1102 INCREF(None);
1103 return None;
1105 #endif /* HAVE_TCSETPGRP */
1107 /* Functions acting on file descriptors */
1109 static object *
1110 posix_open(self, args)
1111 object *self;
1112 object *args;
1114 char *file;
1115 int flag;
1116 int mode = 0777;
1117 int fd;
1118 if (!getargs(args, "(si)", &file, &flag)) {
1119 err_clear();
1120 if (!getargs(args, "(sii)", &file, &flag, &mode))
1121 return NULL;
1123 BGN_SAVE
1124 fd = open(file, flag, mode);
1125 END_SAVE
1126 if (fd < 0)
1127 return posix_error();
1128 return newintobject((long)fd);
1131 static object *
1132 posix_close(self, args)
1133 object *self;
1134 object *args;
1136 int fd, res;
1137 if (!getargs(args, "i", &fd))
1138 return NULL;
1139 BGN_SAVE
1140 res = close(fd);
1141 END_SAVE
1142 if (res < 0)
1143 return posix_error();
1144 INCREF(None);
1145 return None;
1148 static object *
1149 posix_dup(self, args)
1150 object *self;
1151 object *args;
1153 int fd;
1154 if (!getargs(args, "i", &fd))
1155 return NULL;
1156 BGN_SAVE
1157 fd = dup(fd);
1158 END_SAVE
1159 if (fd < 0)
1160 return posix_error();
1161 return newintobject((long)fd);
1164 static object *
1165 posix_dup2(self, args)
1166 object *self;
1167 object *args;
1169 int fd, fd2, res;
1170 if (!getargs(args, "(ii)", &fd, &fd2))
1171 return NULL;
1172 BGN_SAVE
1173 res = dup2(fd, fd2);
1174 END_SAVE
1175 if (res < 0)
1176 return posix_error();
1177 INCREF(None);
1178 return None;
1181 static object *
1182 posix_lseek(self, args)
1183 object *self;
1184 object *args;
1186 int fd, how;
1187 long pos, res;
1188 if (!getargs(args, "(ili)", &fd, &pos, &how))
1189 return NULL;
1190 #ifdef SEEK_SET
1191 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
1192 switch (how) {
1193 case 0: how = SEEK_SET; break;
1194 case 1: how = SEEK_CUR; break;
1195 case 2: how = SEEK_END; break;
1197 #endif /* SEEK_END */
1198 BGN_SAVE
1199 res = lseek(fd, pos, how);
1200 END_SAVE
1201 if (res < 0)
1202 return posix_error();
1203 return newintobject(res);
1206 static object *
1207 posix_read(self, args)
1208 object *self;
1209 object *args;
1211 int fd, size;
1212 object *buffer;
1213 if (!getargs(args, "(ii)", &fd, &size))
1214 return NULL;
1215 buffer = newsizedstringobject((char *)NULL, size);
1216 if (buffer == NULL)
1217 return NULL;
1218 BGN_SAVE
1219 size = read(fd, getstringvalue(buffer), size);
1220 END_SAVE
1221 if (size < 0) {
1222 DECREF(buffer);
1223 return posix_error();
1225 resizestring(&buffer, size);
1226 return buffer;
1229 static object *
1230 posix_write(self, args)
1231 object *self;
1232 object *args;
1234 int fd, size;
1235 char *buffer;
1236 if (!getargs(args, "(is#)", &fd, &buffer, &size))
1237 return NULL;
1238 BGN_SAVE
1239 size = write(fd, buffer, size);
1240 END_SAVE
1241 if (size < 0)
1242 return posix_error();
1243 return newintobject((long)size);
1246 static object *
1247 posix_fstat(self, args)
1248 object *self;
1249 object *args;
1251 int fd;
1252 struct stat st;
1253 int res;
1254 if (!getargs(args, "i", &fd))
1255 return NULL;
1256 BGN_SAVE
1257 res = fstat(fd, &st);
1258 END_SAVE
1259 if (res != 0)
1260 return posix_error();
1261 return mkvalue("(llllllllll)",
1262 (long)st.st_mode,
1263 (long)st.st_ino,
1264 (long)st.st_dev,
1265 (long)st.st_nlink,
1266 (long)st.st_uid,
1267 (long)st.st_gid,
1268 (long)st.st_size,
1269 (long)st.st_atime,
1270 (long)st.st_mtime,
1271 (long)st.st_ctime);
1274 static object *
1275 posix_fdopen(self, args)
1276 object *self;
1277 object *args;
1279 extern int fclose PROTO((FILE *));
1280 int fd;
1281 char *mode = "r";
1282 int bufsize = -1;
1283 FILE *fp;
1284 object *f;
1285 if (!newgetargs(args, "i|si", &fd, &mode, &bufsize))
1286 return NULL;
1287 BGN_SAVE
1288 fp = fdopen(fd, mode);
1289 END_SAVE
1290 if (fp == NULL)
1291 return posix_error();
1292 f = newopenfileobject(fp, "(fdopen)", mode, fclose);
1293 if (f != NULL)
1294 setfilebufsize(f, bufsize);
1295 return f;
1298 static object *
1299 posix_pipe(self, args)
1300 object *self;
1301 object *args;
1303 #ifndef NT
1304 int fds[2];
1305 int res;
1306 if (!getargs(args, ""))
1307 return NULL;
1308 BGN_SAVE
1309 res = pipe(fds);
1310 END_SAVE
1311 if (res != 0)
1312 return posix_error();
1313 return mkvalue("(ii)", fds[0], fds[1]);
1314 #else /* NT */
1315 HANDLE read, write;
1316 BOOL ok;
1317 if (!getargs(args, ""))
1318 return NULL;
1319 BGN_SAVE
1320 ok = CreatePipe( &read, &write, NULL, 0);
1321 END_SAVE
1322 if (!ok)
1323 return posix_error();
1324 return mkvalue("(ii)", read, write);
1325 #endif /* NT */
1328 static struct methodlist posix_methods[] = {
1329 {"chdir", posix_chdir},
1330 {"chmod", posix_chmod},
1331 #ifdef HAVE_CHOWN
1332 {"chown", posix_chown},
1333 #endif /* HAVE_CHOWN */
1334 {"getcwd", posix_getcwd},
1335 #ifdef HAVE_LINK
1336 {"link", posix_link},
1337 #endif /* HAVE_LINK */
1338 {"listdir", posix_listdir},
1339 {"lstat", posix_lstat},
1340 {"mkdir", posix_mkdir},
1341 #ifdef HAVE_NICE
1342 {"nice", posix_nice},
1343 #endif /* HAVE_NICE */
1344 #ifdef HAVE_READLINK
1345 {"readlink", posix_readlink},
1346 #endif /* HAVE_READLINK */
1347 {"rename", posix_rename},
1348 {"rmdir", posix_rmdir},
1349 {"stat", posix_stat},
1350 #ifdef HAVE_SYMLINK
1351 {"symlink", posix_symlink},
1352 #endif /* HAVE_SYMLINK */
1353 {"system", posix_system},
1354 {"umask", posix_umask},
1355 #ifdef HAVE_UNAME
1356 {"uname", posix_uname},
1357 #endif /* HAVE_UNAME */
1358 {"unlink", posix_unlink},
1359 {"utime", posix_utime},
1360 #ifdef HAVE_TIMES
1361 {"times", posix_times},
1362 #endif /* HAVE_TIMES */
1363 {"_exit", posix__exit},
1364 {"execv", posix_execv},
1365 {"execve", posix_execve},
1366 #ifndef NT
1367 {"fork", posix_fork},
1368 {"getegid", posix_getegid},
1369 {"geteuid", posix_geteuid},
1370 {"getgid", posix_getgid},
1371 #endif /* !NT */
1372 {"getpid", posix_getpid},
1373 #ifdef HAVE_GETPGRP
1374 {"getpgrp", posix_getpgrp},
1375 #endif /* HAVE_GETPGRP */
1376 #ifndef NT
1377 {"getppid", posix_getppid},
1378 {"getuid", posix_getuid},
1379 {"kill", posix_kill},
1380 #endif /* !NT */
1381 {"popen", posix_popen, 1},
1382 #ifdef HAVE_SETUID
1383 {"setuid", posix_setuid},
1384 #endif /* HAVE_SETUID */
1385 #ifdef HAVE_SETGID
1386 {"setgid", posix_setgid},
1387 #endif /* HAVE_SETGID */
1388 #ifdef HAVE_SETPGRP
1389 {"setpgrp", posix_setpgrp},
1390 #endif /* HAVE_SETPGRP */
1391 #ifndef NT
1392 {"wait", posix_wait},
1393 #endif /* !NT */
1394 #ifdef HAVE_WAITPID
1395 {"waitpid", posix_waitpid},
1396 #endif /* HAVE_WAITPID */
1397 #ifdef HAVE_SETSID
1398 {"setsid", posix_setsid},
1399 #endif /* HAVE_SETSID */
1400 #ifdef HAVE_SETPGID
1401 {"setpgid", posix_setpgid},
1402 #endif /* HAVE_SETPGID */
1403 #ifdef HAVE_TCGETPGRP
1404 {"tcgetpgrp", posix_tcgetpgrp},
1405 #endif /* HAVE_TCGETPGRP */
1406 #ifdef HAVE_TCSETPGRP
1407 {"tcsetpgrp", posix_tcsetpgrp},
1408 #endif /* HAVE_TCSETPGRP */
1409 {"open", posix_open},
1410 {"close", posix_close},
1411 {"dup", posix_dup},
1412 {"dup2", posix_dup2},
1413 {"lseek", posix_lseek},
1414 {"read", posix_read},
1415 {"write", posix_write},
1416 {"fstat", posix_fstat},
1417 {"fdopen", posix_fdopen, 1},
1418 {"pipe", posix_pipe},
1419 {NULL, NULL} /* Sentinel */
1423 #ifdef NT
1424 void
1425 initnt()
1427 object *m, *d, *v;
1429 m = initmodule("nt", posix_methods);
1430 d = getmoduledict(m);
1432 /* Initialize nt.environ dictionary */
1433 v = convertenviron();
1434 if (v == NULL || dictinsert(d, "environ", v) != 0)
1435 fatal("can't define nt.environ");
1436 DECREF(v);
1438 /* Initialize nt.error exception */
1439 PosixError = newstringobject("nt.error");
1440 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1441 fatal("can't define nt.error");
1443 #else /* !NT */
1444 void
1445 initposix()
1447 object *m, *d, *v;
1449 m = initmodule("posix", posix_methods);
1450 d = getmoduledict(m);
1452 /* Initialize posix.environ dictionary */
1453 v = convertenviron();
1454 if (v == NULL || dictinsert(d, "environ", v) != 0)
1455 fatal("can't define posix.environ");
1456 DECREF(v);
1458 /* Initialize posix.error exception */
1459 PosixError = newstringobject("posix.error");
1460 if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
1461 fatal("can't define posix.error");
1463 #endif /* !NT */