1 /* $RCSfile: doio.c,v $$Revision: 4.0.1.4 $$Date: 91/11/05 16:51:43 $
3 * Copyright (c) 1991, Larry Wall
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
9 * Revision 4.0.1.4 91/11/05 16:51:43 lwall
10 * patch11: prepared for ctype implementations that don't define isascii()
11 * patch11: perl mistook some streams for sockets because they return mode 0 too
12 * patch11: reopening STDIN, STDOUT and STDERR failed on some machines
13 * patch11: certain perl errors should set EBADF so that $! looks better
14 * patch11: truncate on a closed filehandle could dump
15 * patch11: stats of _ forgot whether prior stat was actually lstat
16 * patch11: -T returned true on NFS directory
18 * Revision 4.0.1.3 91/06/10 01:21:19 lwall
19 * patch10: read didn't work from character special files open for writing
20 * patch10: close-on-exec wrongly set on system file descriptors
22 * Revision 4.0.1.2 91/06/07 10:53:39 lwall
23 * patch4: new copyright notice
24 * patch4: system fd's are now treated specially
25 * patch4: added $^F variable to specify maximum system fd, default 2
26 * patch4: character special files now opened with bidirectional stdio buffers
27 * patch4: taintchecks could improperly modify parent in vfork()
28 * patch4: many, many itty-bitty portability fixes
30 * Revision 4.0.1.1 91/04/11 17:41:06 lwall
31 * patch1: hopefully straightened out some of the Xenix mess
33 * Revision 4.0 91/03/20 01:07:06 lwall
42 #include <sys/socket.h>
49 #include <sys/select.h>
54 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
84 int laststype = O_STAT;
87 do_open(stab,name,len)
93 register STIO *stio = stab_io(stab);
94 char *myname = savestr(name);
98 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
99 FILE *saveifp = Nullfp;
100 FILE *saveofp = Nullfp;
104 forkprocess = 1; /* assume true if no fork */
105 while (len && isSPACE(name[len-1]))
108 stio = stab_io(stab) = stio_new();
109 else if (stio->ifp) {
110 fd = fileno(stio->ifp);
111 if (stio->type == '-')
113 else if (fd <= maxsysfd) {
116 savetype = stio->type;
119 else if (stio->type == '|')
120 result = mypclose(stio->ifp);
121 else if (stio->ifp != stio->ofp) {
123 result = fclose(stio->ofp);
124 fclose(stio->ifp); /* clear stdio, fd already closed */
127 result = fclose(stio->ifp);
130 result = fclose(stio->ifp);
131 if (result == EOF && fd > maxsysfd)
132 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
134 stio->ofp = stio->ifp = Nullfp;
136 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
148 for (name++; isSPACE(*name); name++) ;
151 taintproper("Insecure dependency in piped open");
153 fp = mypopen(name,"w");
156 else if (*name == '>') {
158 taintproper("Insecure dependency in open");
162 mode[0] = stio->type = 'a';
171 while (isSPACE(*name))
176 stab = stabent(name,FALSE);
177 if (!stab || !stab_io(stab)) {
183 if (stab_io(stab) && stab_io(stab)->ifp) {
184 fd = fileno(stab_io(stab)->ifp);
185 if (stab_io(stab)->type == 's')
191 if (!(fp = fdopen(fd = dup(fd),mode))) {
196 while (isSPACE(*name))
198 if (strEQ(name,"-")) {
203 fp = fopen(name,mode);
211 while (isSPACE(*name))
215 if (strEQ(name,"-")) {
220 fp = fopen(name,mode);
222 else if (name[len-1] == '|') {
225 taintproper("Insecure dependency in piped open");
228 while (len && isSPACE(name[len-1]))
231 for (; isSPACE(*name); name++) ;
232 fp = mypopen(name,"r");
238 for (; isSPACE(*name); name++) ;
239 if (strEQ(name,"-")) {
244 fp = fopen(name,"r");
251 stio->type != '|' && stio->type != '-') {
252 if (fstat(fileno(fp),&statbuf) < 0) {
256 if (S_ISSOCK(statbuf.st_mode))
257 stio->type = 's'; /* in case a socket was passed in to us */
261 !(statbuf.st_mode & S_IFMT)
266 if (getsockname(fileno(fp), tokenbuf, 0) >= 0 || errno != ENOTSOCK)
267 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
268 /* but some return 0 for streams too, sigh */
272 if (saveifp) { /* must use old fp? */
273 fd = fileno(saveifp);
275 fflush(saveofp); /* emulate fclose() */
276 if (saveofp != saveifp) { /* was a socket? */
282 if (fd != fileno(fp)) {
283 dup2(fileno(fp), fd);
288 #if defined(HAS_FCNTL) && defined(F_SETFD)
290 fcntl(fd,F_SETFD,fd > maxsysfd);
294 if (stio->type == 's'
295 || (stio->type == '>' && S_ISCHR(statbuf.st_mode)) ) {
296 if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
310 stio->type = savetype;
319 #ifndef FLEXFILENAMES
325 static int filemode = 0;
327 static char *oldname;
330 argvoutstab = stabent("ARGVOUT",TRUE);
331 if (filemode & (S_ISUID|S_ISGID)) {
332 fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */
334 (void)fchmod(lastfd,filemode);
336 (void)chmod(oldname,filemode);
340 while (alen(stab_xarray(stab)) >= 0) {
341 str = ashift(stab_xarray(stab));
342 str_sset(stab_val(stab),str);
343 STABSET(stab_val(stab));
344 oldname = str_get(stab_val(stab));
345 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
348 taintproper("Insecure dependency in inplace open");
350 if (strEQ(oldname,"-")) {
352 defoutstab = stabent("STDOUT",TRUE);
353 return stab_io(stab)->ifp;
355 #ifndef FLEXFILENAMES
356 filedev = statbuf.st_dev;
357 fileino = statbuf.st_ino;
359 filemode = statbuf.st_mode;
360 fileuid = statbuf.st_uid;
361 filegid = statbuf.st_gid;
362 if (!S_ISREG(filemode)) {
363 warn("Can't do inplace edit: %s is not a regular file",
365 do_close(stab,FALSE);
371 add_suffix(str,inplace);
373 str_cat(str,inplace);
375 #ifndef FLEXFILENAMES
376 if (stat(str->str_ptr,&statbuf) >= 0
377 && statbuf.st_dev == filedev
378 && statbuf.st_ino == fileino ) {
379 warn("Can't do inplace edit: %s > 14 characters",
381 do_close(stab,FALSE);
388 if (rename(oldname,str->str_ptr) < 0) {
389 warn("Can't rename %s to %s: %s, skipping file",
390 oldname, str->str_ptr, strerror(errno) );
391 do_close(stab,FALSE);
396 do_close(stab,FALSE);
397 (void)unlink(str->str_ptr);
398 (void)rename(oldname,str->str_ptr);
399 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
402 (void)UNLINK(str->str_ptr);
403 if (link(oldname,str->str_ptr) < 0) {
404 warn("Can't rename %s to %s: %s, skipping file",
405 oldname, str->str_ptr, strerror(errno) );
406 do_close(stab,FALSE);
410 (void)UNLINK(oldname);
415 if (UNLINK(oldname) < 0) {
416 warn("Can't rename %s to %s: %s, skipping file",
417 oldname, str->str_ptr, strerror(errno) );
418 do_close(stab,FALSE);
423 fatal("Can't do inplace edit without backup");
428 str_cat(str,oldname);
429 errno = 0; /* in case sprintf set errno */
430 if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
431 warn("Can't do inplace edit on %s: %s",
432 oldname, strerror(errno) );
433 do_close(stab,FALSE);
437 defoutstab = argvoutstab;
438 lastfd = fileno(stab_io(argvoutstab)->ifp);
439 (void)fstat(lastfd,&statbuf);
441 (void)fchmod(lastfd,filemode);
443 (void)chmod(oldname,filemode);
445 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
447 (void)fchown(lastfd,fileuid,filegid);
450 (void)chown(oldname,fileuid,filegid);
456 return stab_io(stab)->ifp;
459 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
463 (void)do_close(argvoutstab,FALSE);
464 defoutstab = stabent("STDOUT",TRUE);
471 do_pipe(str, rstab, wstab)
476 register STIO *rstio;
477 register STIO *wstio;
485 rstio = stab_io(rstab);
486 wstio = stab_io(wstab);
489 rstio = stab_io(rstab) = stio_new();
491 do_close(rstab,FALSE);
493 wstio = stab_io(wstab) = stio_new();
495 do_close(wstab,FALSE);
499 rstio->ifp = fdopen(fd[0], "r");
500 wstio->ofp = fdopen(fd[1], "w");
501 wstio->ifp = wstio->ofp;
504 if (!rstio->ifp || !wstio->ofp) {
505 if (rstio->ifp) fclose(rstio->ifp);
507 if (wstio->ofp) fclose(wstio->ofp);
512 str_sset(str,&str_yes);
516 str_sset(str,&str_undef);
522 do_close(stab,explicit)
536 stio = stab_io(stab);
537 if (!stio) { /* never opened */
538 if (dowarn && explicit)
539 warn("Close on unopened file <%s>",stab_name(stab));
543 if (stio->type == '|') {
544 status = mypclose(stio->ifp);
545 retval = (status == 0);
546 statusvalue = (unsigned short)status & 0xffff;
548 else if (stio->type == '-')
551 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
552 retval = (fclose(stio->ofp) != EOF);
553 fclose(stio->ifp); /* clear stdio, fd already closed */
556 retval = (fclose(stio->ifp) != EOF);
558 stio->ofp = stio->ifp = Nullfp;
573 if (!stab) { /* eof() */
575 stio = stab_io(argvstab);
580 stio = stab_io(stab);
587 #ifdef STDSTDIO /* (the code works without this) */
588 if (stio->ifp->_cnt > 0) /* cheat a little, since */
589 return FALSE; /* this is the most usual case */
592 ch = getc(stio->ifp);
594 (void)ungetc(ch, stio->ifp);
598 if (stio->ifp->_cnt < -1)
599 stio->ifp->_cnt = -1;
601 if (!stab) { /* not necessarily a real EOF yet? */
602 if (!nextargv(argvstab)) /* get another fp handy */
606 return TRUE; /* normal fp, definitely end of file */
620 stio = stab_io(stab);
621 if (!stio || !stio->ifp)
625 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
627 return ftell(stio->ifp);
631 warn("tell() on unopened file");
637 do_seek(stab, pos, whence)
647 stio = stab_io(stab);
648 if (!stio || !stio->ifp)
652 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
654 return fseek(stio->ifp, pos, whence) >= 0;
658 warn("seek() on unopened file");
664 do_ctl(optype,stab,func,argstr)
674 if (!stab || !argstr || !(stio = stab_io(stab)) || !stio->ifp) {
675 errno = EBADF; /* well, sort of... */
679 if (argstr->str_pok || !argstr->str_nok) {
680 if (!argstr->str_pok)
685 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
689 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
691 retval = 256; /* otherwise guess at what's safe */
693 if (argstr->str_cur < retval) {
694 Str_Grow(argstr,retval+1);
695 argstr->str_cur = retval;
699 s[argstr->str_cur] = 17; /* a little sanity check here */
702 retval = (int)str_gnum(argstr);
704 s = (char*)(long)retval; /* ouch */
706 s = (char*)retval; /* ouch */
711 if (optype == O_IOCTL)
712 retval = ioctl(fileno(stio->ifp), func, s);
715 fatal("fcntl is not implemented");
718 retval = fcntl(fileno(stio->ifp), func, s);
720 fatal("fcntl is not implemented");
727 if (argstr->str_pok) {
728 if (s[argstr->str_cur] != 17)
729 fatal("Return value overflowed string");
730 s[argstr->str_cur] = 0; /* put our null back */
736 do_stat(str,arg,gimme,arglast)
742 register ARRAY *ary = stack;
743 register int sp = arglast[0] + 1;
746 if ((arg[1].arg_type & A_MASK) == A_WORD) {
747 tmpstab = arg[1].arg_ptr.arg_stab;
748 if (tmpstab != defstab) {
751 str_set(statname,"");
752 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
753 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
758 else if (laststatval < 0)
762 str_set(statname,str_get(ary->ary_array[sp]));
765 laststype = arg->arg_type;
766 if (arg->arg_type == O_LSTAT)
767 laststatval = lstat(str_get(statname),&statcache);
770 laststatval = stat(str_get(statname),&statcache);
775 if (gimme != G_ARRAY) {
777 str_sset(str,&str_yes);
779 str_sset(str,&str_undef);
781 ary->ary_array[sp] = str;
787 (void)astore(ary,++sp,
788 str_2mortal(str_nmake((double)statcache.st_dev)));
789 (void)astore(ary,++sp,
790 str_2mortal(str_nmake((double)statcache.st_ino)));
791 (void)astore(ary,++sp,
792 str_2mortal(str_nmake((double)statcache.st_mode)));
793 (void)astore(ary,++sp,
794 str_2mortal(str_nmake((double)statcache.st_nlink)));
795 (void)astore(ary,++sp,
796 str_2mortal(str_nmake((double)statcache.st_uid)));
797 (void)astore(ary,++sp,
798 str_2mortal(str_nmake((double)statcache.st_gid)));
799 (void)astore(ary,++sp,
800 str_2mortal(str_nmake((double)statcache.st_rdev)));
801 (void)astore(ary,++sp,
802 str_2mortal(str_nmake((double)statcache.st_size)));
803 (void)astore(ary,++sp,
804 str_2mortal(str_nmake((double)statcache.st_atime)));
805 (void)astore(ary,++sp,
806 str_2mortal(str_nmake((double)statcache.st_mtime)));
807 (void)astore(ary,++sp,
808 str_2mortal(str_nmake((double)statcache.st_ctime)));
810 (void)astore(ary,++sp,
811 str_2mortal(str_nmake((double)statcache.st_blksize)));
812 (void)astore(ary,++sp,
813 str_2mortal(str_nmake((double)statcache.st_blocks)));
815 (void)astore(ary,++sp,
816 str_2mortal(str_make("",0)));
817 (void)astore(ary,++sp,
818 str_2mortal(str_make("",0)));
821 (void)astore(ary,++sp,str_nmake(0.0));
827 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
828 /* code courtesy of William Kucharski */
831 int chsize(fd, length)
832 int fd; /* file descriptor */
833 off_t length; /* length to set file to */
839 if (fstat(fd, &filebuf) < 0)
842 if (filebuf.st_size < length) {
844 /* extend file length */
846 if ((lseek(fd, (length - 1), 0)) < 0)
849 /* write a "0" byte */
851 if ((write(fd, "", 1)) != 1)
855 /* truncate length */
860 fl.l_type = F_WRLCK; /* write lock on file space */
863 * This relies on the UNDOCUMENTED F_FREESP argument to
864 * fcntl(2), which truncates the file so that it ends at the
865 * position indicated by fl.l_start.
867 * Will minor miracles never cease?
870 if (fcntl(fd, F_FREESP, &fl) < 0)
877 #endif /* F_FREESP */
880 do_truncate(str,arg,gimme,arglast)
886 register ARRAY *ary = stack;
887 register int sp = arglast[0] + 1;
888 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
892 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
894 if ((arg[1].arg_type & A_MASK) == A_WORD) {
895 tmpstab = arg[1].arg_ptr.arg_stab;
896 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
897 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
900 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
903 if ((arg[1].arg_type & A_MASK) == A_WORD) {
904 tmpstab = arg[1].arg_ptr.arg_stab;
905 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
906 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
912 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
915 if (chsize(tmpfd, len) < 0)
923 str_sset(str,&str_yes);
925 str_sset(str,&str_undef);
927 ary->ary_array[sp] = str;
930 fatal("truncate not implemented");
935 looks_like_number(str)
944 send = s + str->str_cur;
949 if (*s == '+' || *s == '-')
957 else if (s == str->str_ptr)
963 if (*s == 'e' || *s == 'E') {
965 if (*s == '+' || *s == '-')
986 warn("print to unopened file");
993 ((str->str_nok && str->str_u.str_nval != 0.0)
994 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
995 fprintf(fp, ofmt, str->str_u.str_nval);
1000 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
1001 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
1002 STR *tmpstr = str_mortal(&str_undef);
1003 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
1005 tmps = str->str_ptr;
1008 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
1015 do_aprint(arg,fp,arglast)
1020 register STR **st = stack->ary_array;
1021 register int sp = arglast[1];
1022 register int retval;
1023 register int items = arglast[2] - sp;
1027 warn("print to unopened file");
1032 if (arg->arg_type == O_PRTF) {
1033 do_sprintf(arg->arg_ptr.arg_str,items,st);
1034 retval = do_print(arg->arg_ptr.arg_str,fp);
1037 retval = (items <= 0);
1038 for (; items > 0; items--,st++) {
1039 if (retval && ofslen) {
1040 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
1045 if (!(retval = do_print(*st, fp)))
1048 if (retval && orslen)
1049 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
1062 if (arg[1].arg_type & A_DONT) {
1063 stio = stab_io(arg[1].arg_ptr.arg_stab);
1064 if (stio && stio->ifp) {
1065 statstab = arg[1].arg_ptr.arg_stab;
1066 str_set(statname,"");
1068 return (laststatval = fstat(fileno(stio->ifp), &statcache));
1071 if (arg[1].arg_ptr.arg_stab == defstab)
1074 warn("Stat on unopened file <%s>",
1075 stab_name(arg[1].arg_ptr.arg_stab));
1076 statstab = Nullstab;
1077 str_set(statname,"");
1078 return (laststatval = -1);
1082 statstab = Nullstab;
1083 str_set(statname,str_get(str));
1085 return (laststatval = stat(str_get(str),&statcache));
1094 if (arg[1].arg_type & A_DONT) {
1095 if (arg[1].arg_ptr.arg_stab == defstab) {
1096 if (laststype != O_LSTAT)
1097 fatal("The stat preceding -l _ wasn't an lstat");
1100 fatal("You can't use -l on a filehandle");
1103 laststype = O_LSTAT;
1104 statstab = Nullstab;
1105 str_set(statname,str_get(str));
1107 return (laststatval = lstat(str_get(str),&statcache));
1109 return (laststatval = stat(str_get(str),&statcache));
1122 register STDCHAR *s;
1123 register STIO *stio;
1125 if (arg[1].arg_type & A_DONT) {
1126 if (arg[1].arg_ptr.arg_stab == defstab) {
1128 stio = stab_io(statstab);
1131 goto really_filename;
1135 statstab = arg[1].arg_ptr.arg_stab;
1136 str_set(statname,"");
1137 stio = stab_io(statstab);
1139 if (stio && stio->ifp) {
1141 fstat(fileno(stio->ifp),&statcache);
1142 if (S_ISDIR(statcache.st_mode)) /* handle NFS glitch */
1143 return arg->arg_type == O_FTTEXT ? &str_no : &str_yes;
1144 if (stio->ifp->_cnt <= 0) {
1145 i = getc(stio->ifp);
1147 (void)ungetc(i,stio->ifp);
1149 if (stio->ifp->_cnt <= 0) /* null file is anything */
1151 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1152 s = stio->ifp->_base;
1154 fatal("-T and -B not implemented on filehandles");
1159 warn("Test on unopened file <%s>",
1160 stab_name(arg[1].arg_ptr.arg_stab));
1166 statstab = Nullstab;
1167 str_set(statname,str_get(str));
1169 i = open(str_get(str),0);
1172 fstat(i,&statcache);
1173 len = read(i,tbuf,512);
1176 if (S_ISDIR(statcache.st_mode) && arg->arg_type == O_FTTEXT)
1177 return &str_no; /* special case NFS directories */
1178 return &str_yes; /* null file is anything */
1183 /* now scan s to look for textiness */
1185 for (i = 0; i < len; i++,s++) {
1186 if (!*s) { /* null never allowed in text */
1193 *s != '\n' && *s != '\r' && *s != '\b' &&
1194 *s != '\t' && *s != '\f' && *s != 27)
1198 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1205 do_aexec(really,arglast)
1209 register STR **st = stack->ary_array;
1210 register int sp = arglast[1];
1211 register int items = arglast[2] - sp;
1217 New(401,argv, items+1, char*);
1219 for (st += ++sp; items > 0; items--,st++) {
1221 *a++ = str_get(*st);
1227 if (*argv[0] != '/') /* will execvp use PATH? */
1228 taintenv(); /* testing IFS here is overkill, probably */
1230 if (really && *(tmps = str_get(really)))
1233 execvp(argv[0],argv);
1239 static char **Argv = Null(char **);
1240 static char *Cmd = Nullch;
1247 Argv = Null(char **);
1263 /* save an extra exec if possible */
1266 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1282 if (s[-1] == '\'') {
1284 execl(cshname,"csh", flags,ncmd,(char*)0);
1292 /* see if there are shell metacharacters in it */
1295 for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */
1298 for (s = cmd; *s; s++) {
1299 if (*s != ' ' && !isALPHA(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1300 if (*s == '\n' && !s[1]) {
1305 execl("/bin/sh","sh","-c",cmd,(char*)0);
1309 New(402,Argv, (s - cmd) / 2 + 2, char*);
1310 Cmd = nsavestr(cmd, s-cmd);
1312 for (s = Cmd; *s;) {
1313 while (*s && isSPACE(*s)) s++;
1316 while (*s && !isSPACE(*s)) s++;
1322 execvp(Argv[0],Argv);
1323 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1334 do_socket(stab, arglast)
1338 register STR **st = stack->ary_array;
1339 register int sp = arglast[1];
1340 register STIO *stio;
1341 int domain, type, protocol, fd;
1348 stio = stab_io(stab);
1350 stio = stab_io(stab) = stio_new();
1352 do_close(stab,FALSE);
1354 domain = (int)str_gnum(st[++sp]);
1355 type = (int)str_gnum(st[++sp]);
1356 protocol = (int)str_gnum(st[++sp]);
1358 taintproper("Insecure dependency in socket");
1360 fd = socket(domain,type,protocol);
1363 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1364 stio->ofp = fdopen(fd, "w");
1366 if (!stio->ifp || !stio->ofp) {
1367 if (stio->ifp) fclose(stio->ifp);
1368 if (stio->ofp) fclose(stio->ofp);
1369 if (!stio->ifp && !stio->ofp) close(fd);
1377 do_bind(stab, arglast)
1381 register STR **st = stack->ary_array;
1382 register int sp = arglast[1];
1383 register STIO *stio;
1389 stio = stab_io(stab);
1390 if (!stio || !stio->ifp)
1393 addr = str_get(st[++sp]);
1395 taintproper("Insecure dependency in bind");
1397 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1401 warn("bind() on closed fd");
1408 do_connect(stab, arglast)
1412 register STR **st = stack->ary_array;
1413 register int sp = arglast[1];
1414 register STIO *stio;
1420 stio = stab_io(stab);
1421 if (!stio || !stio->ifp)
1424 addr = str_get(st[++sp]);
1426 taintproper("Insecure dependency in connect");
1428 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1432 warn("connect() on closed fd");
1439 do_listen(stab, arglast)
1443 register STR **st = stack->ary_array;
1444 register int sp = arglast[1];
1445 register STIO *stio;
1451 stio = stab_io(stab);
1452 if (!stio || !stio->ifp)
1455 backlog = (int)str_gnum(st[++sp]);
1456 return listen(fileno(stio->ifp), backlog) >= 0;
1460 warn("listen() on closed fd");
1466 do_accept(str, nstab, gstab)
1471 register STIO *nstio;
1472 register STIO *gstio;
1473 int len = sizeof buf;
1481 gstio = stab_io(gstab);
1482 nstio = stab_io(nstab);
1484 if (!gstio || !gstio->ifp)
1487 nstio = stab_io(nstab) = stio_new();
1488 else if (nstio->ifp)
1489 do_close(nstab,FALSE);
1491 fd = accept(fileno(gstio->ifp),(struct sockaddr *)buf,&len);
1494 nstio->ifp = fdopen(fd, "r");
1495 nstio->ofp = fdopen(fd, "w");
1497 if (!nstio->ifp || !nstio->ofp) {
1498 if (nstio->ifp) fclose(nstio->ifp);
1499 if (nstio->ofp) fclose(nstio->ofp);
1500 if (!nstio->ifp && !nstio->ofp) close(fd);
1504 str_nset(str, buf, len);
1509 warn("accept() on closed fd");
1512 str_sset(str,&str_undef);
1517 do_shutdown(stab, arglast)
1521 register STR **st = stack->ary_array;
1522 register int sp = arglast[1];
1523 register STIO *stio;
1529 stio = stab_io(stab);
1530 if (!stio || !stio->ifp)
1533 how = (int)str_gnum(st[++sp]);
1534 return shutdown(fileno(stio->ifp), how) >= 0;
1538 warn("shutdown() on closed fd");
1545 do_sopt(optype, stab, arglast)
1550 register STR **st = stack->ary_array;
1551 register int sp = arglast[1];
1552 register STIO *stio;
1560 stio = stab_io(stab);
1561 if (!stio || !stio->ifp)
1564 fd = fileno(stio->ifp);
1565 lvl = (int)str_gnum(st[sp+1]);
1566 optname = (int)str_gnum(st[sp+2]);
1569 st[sp] = str_2mortal(Str_new(22,257));
1570 st[sp]->str_cur = 256;
1571 st[sp]->str_pok = 1;
1572 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1577 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1587 warn("[gs]etsockopt() on closed fd");
1588 st[sp] = &str_undef;
1595 do_getsockname(optype, stab, arglast)
1600 register STR **st = stack->ary_array;
1601 register int sp = arglast[1];
1602 register STIO *stio;
1608 stio = stab_io(stab);
1609 if (!stio || !stio->ifp)
1612 st[sp] = str_2mortal(Str_new(22,257));
1613 st[sp]->str_cur = 256;
1614 st[sp]->str_pok = 1;
1615 fd = fileno(stio->ifp);
1618 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1622 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1631 warn("get{sock,peer}name() on closed fd");
1634 st[sp] = &str_undef;
1640 do_ghent(which,gimme,arglast)
1645 register ARRAY *ary = stack;
1646 register int sp = arglast[0];
1647 register char **elem;
1649 struct hostent *gethostbyname();
1650 struct hostent *gethostbyaddr();
1651 #ifdef HAS_GETHOSTENT
1652 struct hostent *gethostent();
1654 struct hostent *hent;
1657 if (gimme != G_ARRAY) {
1658 astore(ary, ++sp, str_mortal(&str_undef));
1662 if (which == O_GHBYNAME) {
1663 char *name = str_get(ary->ary_array[sp+1]);
1665 hent = gethostbyname(name);
1667 else if (which == O_GHBYADDR) {
1668 STR *addrstr = ary->ary_array[sp+1];
1669 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1670 char *addr = str_get(addrstr);
1672 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1675 #ifdef HAS_GETHOSTENT
1676 hent = gethostent();
1678 fatal("gethostent not implemented");
1682 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1683 str_set(str, hent->h_name);
1684 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1685 for (elem = hent->h_aliases; *elem; elem++) {
1686 str_cat(str, *elem);
1688 str_ncat(str," ",1);
1690 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1691 str_numset(str, (double)hent->h_addrtype);
1692 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1693 len = hent->h_length;
1694 str_numset(str, (double)len);
1696 for (elem = hent->h_addr_list; *elem; elem++) {
1697 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1698 str_nset(str, *elem, len);
1701 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1702 str_nset(str, hent->h_addr, len);
1707 (void)astore(ary, ++sp, str_mortal(&str_no));
1715 do_gnent(which,gimme,arglast)
1720 register ARRAY *ary = stack;
1721 register int sp = arglast[0];
1722 register char **elem;
1724 struct netent *getnetbyname();
1725 struct netent *getnetbyaddr();
1726 struct netent *getnetent();
1727 struct netent *nent;
1729 if (gimme != G_ARRAY) {
1730 astore(ary, ++sp, str_mortal(&str_undef));
1734 if (which == O_GNBYNAME) {
1735 char *name = str_get(ary->ary_array[sp+1]);
1737 nent = getnetbyname(name);
1739 else if (which == O_GNBYADDR) {
1740 unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
1741 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1743 nent = getnetbyaddr((long)addr,addrtype);
1750 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1751 str_set(str, nent->n_name);
1752 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1753 for (elem = nent->n_aliases; *elem; elem++) {
1754 str_cat(str, *elem);
1756 str_ncat(str," ",1);
1758 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1759 str_numset(str, (double)nent->n_addrtype);
1760 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1761 str_numset(str, (double)nent->n_net);
1765 (void)astore(ary, ++sp, str_mortal(&str_no));
1773 do_gpent(which,gimme,arglast)
1778 register ARRAY *ary = stack;
1779 register int sp = arglast[0];
1780 register char **elem;
1782 struct protoent *getprotobyname();
1783 struct protoent *getprotobynumber();
1784 struct protoent *getprotoent();
1785 struct protoent *pent;
1787 if (gimme != G_ARRAY) {
1788 astore(ary, ++sp, str_mortal(&str_undef));
1792 if (which == O_GPBYNAME) {
1793 char *name = str_get(ary->ary_array[sp+1]);
1795 pent = getprotobyname(name);
1797 else if (which == O_GPBYNUMBER) {
1798 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1800 pent = getprotobynumber(proto);
1803 pent = getprotoent();
1807 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1808 str_set(str, pent->p_name);
1809 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1810 for (elem = pent->p_aliases; *elem; elem++) {
1811 str_cat(str, *elem);
1813 str_ncat(str," ",1);
1815 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1816 str_numset(str, (double)pent->p_proto);
1820 (void)astore(ary, ++sp, str_mortal(&str_no));
1828 do_gsent(which,gimme,arglast)
1833 register ARRAY *ary = stack;
1834 register int sp = arglast[0];
1835 register char **elem;
1837 struct servent *getservbyname();
1838 struct servent *getservbynumber();
1839 struct servent *getservent();
1840 struct servent *sent;
1842 if (gimme != G_ARRAY) {
1843 astore(ary, ++sp, str_mortal(&str_undef));
1847 if (which == O_GSBYNAME) {
1848 char *name = str_get(ary->ary_array[sp+1]);
1849 char *proto = str_get(ary->ary_array[sp+2]);
1851 if (proto && !*proto)
1854 sent = getservbyname(name,proto);
1856 else if (which == O_GSBYPORT) {
1857 int port = (int)str_gnum(ary->ary_array[sp+1]);
1858 char *proto = str_get(ary->ary_array[sp+2]);
1860 sent = getservbyport(port,proto);
1863 sent = getservent();
1866 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1867 str_set(str, sent->s_name);
1868 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1869 for (elem = sent->s_aliases; *elem; elem++) {
1870 str_cat(str, *elem);
1872 str_ncat(str," ",1);
1874 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1876 str_numset(str, (double)ntohs(sent->s_port));
1878 str_numset(str, (double)(sent->s_port));
1880 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1881 str_set(str, sent->s_proto);
1885 (void)astore(ary, ++sp, str_mortal(&str_no));
1892 #endif /* HAS_SOCKET */
1896 do_select(gimme,arglast)
1900 register STR **st = stack->ary_array;
1901 register int sp = arglast[0];
1909 struct timeval timebuf;
1910 struct timeval *tbuf = &timebuf;
1912 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1918 #if BYTEORDER & 0xf0000
1919 #define ORDERBYTE (0x88888888 - BYTEORDER)
1921 #define ORDERBYTE (0x4444 - BYTEORDER)
1926 for (i = 1; i <= 3; i++) {
1927 j = st[sp+i]->str_cur;
1932 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1933 growsize = maxlen; /* little endians can use vecs directly */
1941 masksize = NFDBITS / NBBY;
1943 masksize = sizeof(long); /* documented int, everyone seems to use long */
1945 growsize = maxlen + (masksize - (maxlen % masksize));
1946 Zero(&fd_sets[0], 4, char*);
1949 for (i = 1; i <= 3; i++) {
1954 Str_Grow(str,growsize);
1955 s = str_get(str) + j;
1956 while (++j <= growsize) {
1960 else if (str->str_ptr) {
1961 Safefree(str->str_ptr);
1962 str->str_ptr = Nullch;
1965 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1968 New(403, fd_sets[i], growsize, char);
1969 for (offset = 0; offset < growsize; offset += masksize) {
1970 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1971 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1977 if (str->str_nok || str->str_pok) {
1978 value = str_gnum(str);
1981 timebuf.tv_sec = (long)value;
1982 value -= (double)timebuf.tv_sec;
1983 timebuf.tv_usec = (long)(value * 1000000.0);
1986 tbuf = Null(struct timeval*);
1988 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
2002 for (i = 1; i <= 3; i++) {
2006 for (offset = 0; offset < growsize; offset += masksize) {
2007 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
2008 s[(k % masksize) + offset] = fd_sets[i][j+offset];
2014 st[++sp] = str_mortal(&str_no);
2015 str_numset(st[sp], (double)nfound);
2016 if (gimme == G_ARRAY && tbuf) {
2017 value = (double)(timebuf.tv_sec) +
2018 (double)(timebuf.tv_usec) / 1000000.0;
2019 st[++sp] = str_mortal(&str_no);
2020 str_numset(st[sp], value);
2028 do_spair(stab1, stab2, arglast)
2033 register STR **st = stack->ary_array;
2034 register int sp = arglast[2];
2035 register STIO *stio1;
2036 register STIO *stio2;
2037 int domain, type, protocol, fd[2];
2039 if (!stab1 || !stab2)
2042 stio1 = stab_io(stab1);
2043 stio2 = stab_io(stab2);
2045 stio1 = stab_io(stab1) = stio_new();
2046 else if (stio1->ifp)
2047 do_close(stab1,FALSE);
2049 stio2 = stab_io(stab2) = stio_new();
2050 else if (stio2->ifp)
2051 do_close(stab2,FALSE);
2053 domain = (int)str_gnum(st[++sp]);
2054 type = (int)str_gnum(st[++sp]);
2055 protocol = (int)str_gnum(st[++sp]);
2057 taintproper("Insecure dependency in socketpair");
2059 #ifdef HAS_SOCKETPAIR
2060 if (socketpair(domain,type,protocol,fd) < 0)
2063 fatal("Socketpair unimplemented");
2065 stio1->ifp = fdopen(fd[0], "r");
2066 stio1->ofp = fdopen(fd[0], "w");
2068 stio2->ifp = fdopen(fd[1], "r");
2069 stio2->ofp = fdopen(fd[1], "w");
2071 if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
2072 if (stio1->ifp) fclose(stio1->ifp);
2073 if (stio1->ofp) fclose(stio1->ofp);
2074 if (!stio1->ifp && !stio1->ofp) close(fd[0]);
2075 if (stio2->ifp) fclose(stio2->ifp);
2076 if (stio2->ofp) fclose(stio2->ofp);
2077 if (!stio2->ifp && !stio2->ofp) close(fd[1]);
2084 #endif /* HAS_SOCKET */
2087 do_gpwent(which,gimme,arglast)
2093 register ARRAY *ary = stack;
2094 register int sp = arglast[0];
2096 struct passwd *getpwnam();
2097 struct passwd *getpwuid();
2098 struct passwd *getpwent();
2099 struct passwd *pwent;
2101 if (gimme != G_ARRAY) {
2102 astore(ary, ++sp, str_mortal(&str_undef));
2106 if (which == O_GPWNAM) {
2107 char *name = str_get(ary->ary_array[sp+1]);
2109 pwent = getpwnam(name);
2111 else if (which == O_GPWUID) {
2112 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2114 pwent = getpwuid(uid);
2120 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2121 str_set(str, pwent->pw_name);
2122 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2123 str_set(str, pwent->pw_passwd);
2124 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2125 str_numset(str, (double)pwent->pw_uid);
2126 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2127 str_numset(str, (double)pwent->pw_gid);
2128 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2130 str_numset(str, (double)pwent->pw_change);
2133 str_numset(str, (double)pwent->pw_quota);
2136 str_set(str, pwent->pw_age);
2140 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2142 str_set(str,pwent->pw_class);
2145 str_set(str, pwent->pw_comment);
2148 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2149 str_set(str, pwent->pw_gecos);
2150 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2151 str_set(str, pwent->pw_dir);
2152 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2153 str_set(str, pwent->pw_shell);
2155 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2156 str_numset(str, (double)pwent->pw_expire);
2162 fatal("password routines not implemented");
2167 do_ggrent(which,gimme,arglast)
2173 register ARRAY *ary = stack;
2174 register int sp = arglast[0];
2175 register char **elem;
2177 struct group *getgrnam();
2178 struct group *getgrgid();
2179 struct group *getgrent();
2180 struct group *grent;
2182 if (gimme != G_ARRAY) {
2183 astore(ary, ++sp, str_mortal(&str_undef));
2187 if (which == O_GGRNAM) {
2188 char *name = str_get(ary->ary_array[sp+1]);
2190 grent = getgrnam(name);
2192 else if (which == O_GGRGID) {
2193 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2195 grent = getgrgid(gid);
2201 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2202 str_set(str, grent->gr_name);
2203 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2204 str_set(str, grent->gr_passwd);
2205 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2206 str_numset(str, (double)grent->gr_gid);
2207 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2208 for (elem = grent->gr_mem; *elem; elem++) {
2209 str_cat(str, *elem);
2211 str_ncat(str," ",1);
2217 fatal("group routines not implemented");
2222 do_dirop(optype,stab,gimme,arglast)
2228 #if defined(DIRENT) && defined(HAS_READDIR)
2229 register ARRAY *ary = stack;
2230 register STR **st = ary->ary_array;
2231 register int sp = arglast[1];
2232 register STIO *stio;
2238 struct DIRENT *readdir();
2240 register struct DIRENT *dp;
2244 if (!(stio = stab_io(stab)))
2245 stio = stab_io(stab) = stio_new();
2246 if (!stio->dirp && optype != O_OPEN_DIR)
2252 closedir(stio->dirp);
2253 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2257 if (gimme == G_ARRAY) {
2260 while (dp = readdir(stio->dirp)) {
2262 (void)astore(ary,++sp,
2263 str_2mortal(str_make(dp->d_name,dp->d_namlen)));
2265 (void)astore(ary,++sp,
2266 str_2mortal(str_make(dp->d_name,0)));
2271 if (!(dp = readdir(stio->dirp)))
2273 st[sp] = str_mortal(&str_undef);
2275 str_nset(st[sp], dp->d_name, dp->d_namlen);
2277 str_set(st[sp], dp->d_name);
2287 st[sp] = str_mortal(&str_undef);
2288 str_numset(st[sp], (double)telldir(stio->dirp));
2291 st[sp] = str_mortal(&str_undef);
2292 along = (long)str_gnum(st[sp+1]);
2293 (void)seekdir(stio->dirp,along);
2297 st[sp] = str_mortal(&str_undef);
2298 (void)rewinddir(stio->dirp);
2301 st[sp] = str_mortal(&str_undef);
2302 (void)closedir(stio->dirp);
2309 st[sp] = &str_undef;
2315 fatal("Unimplemented directory operation");
2323 register STR **st = stack->ary_array;
2324 register int sp = arglast[1];
2325 register int items = arglast[2] - sp;
2328 register int tot = 0;
2332 for (st += ++sp; items--; st++)
2333 tainted |= (*st)->str_tainted;
2334 st = stack->ary_array;
2336 items = arglast[2] - sp;
2341 taintproper("Insecure dependency in chmod");
2345 val = (int)str_gnum(st[++sp]);
2347 if (chmod(str_get(st[++sp]),val))
2355 taintproper("Insecure dependency in chown");
2360 val = (int)str_gnum(st[++sp]);
2361 val2 = (int)str_gnum(st[++sp]);
2363 if (chown(str_get(st[++sp]),val,val2))
2372 taintproper("Insecure dependency in kill");
2376 s = str_get(st[++sp]);
2378 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2380 if (!(val = whichsig(s)))
2381 fatal("Unrecognized signal name \"%s\"",s);
2384 val = (int)str_gnum(st[sp]);
2388 int proc = (int)str_gnum(st[++sp]);
2390 if (killpg(proc,val)) /* BSD */
2392 if (kill(-proc,val)) /* SYSV */
2399 if (kill((int)(str_gnum(st[++sp])),val))
2408 taintproper("Insecure dependency in unlink");
2412 s = str_get(st[++sp]);
2413 if (euid || unsafe) {
2417 else { /* don't let root wipe out directories without -U */
2419 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2421 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2433 taintproper("Insecure dependency in utime");
2437 struct utimbuf utbuf;
2445 Zero(&utbuf, sizeof utbuf, char);
2446 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2447 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2452 if (utime(str_get(st[++sp]),&utbuf))
2464 /* Do the permissions allow some operation? Assumes statcache already set. */
2467 cando(bit, effective, statbufp)
2470 register struct stat *statbufp;
2473 /* [Comments and code from Len Reed]
2474 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2475 * to write-protected files. The execute permission bit is set
2476 * by the Miscrosoft C library stat() function for the following:
2481 * All files and directories are readable.
2482 * Directories and special files, e.g. "CON", cannot be
2484 * [Comment by Tom Dinger -- a directory can have the write-protect
2485 * bit set in the file system, but DOS permits changes to
2486 * the directory anyway. In addition, all bets are off
2487 * here for networked software, such as Novell and
2491 return (bit & statbufp->st_mode) ? TRUE : FALSE;
2494 if ((effective ? euid : uid) == 0) { /* root is special */
2495 if (bit == S_IXUSR) {
2496 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
2500 return TRUE; /* root reads and writes anything */
2503 if (statbufp->st_uid == (effective ? euid : uid) ) {
2504 if (statbufp->st_mode & bit)
2505 return TRUE; /* ok as "user" */
2507 else if (ingroup((int)statbufp->st_gid,effective)) {
2508 if (statbufp->st_mode & bit >> 3)
2509 return TRUE; /* ok as "group" */
2511 else if (statbufp->st_mode & bit >> 6)
2512 return TRUE; /* ok as "other" */
2514 #endif /* ! MSDOS */
2518 ingroup(testgid,effective)
2522 if (testgid == (effective ? egid : gid))
2524 #ifdef HAS_GETGROUPS
2529 GROUPSTYPE gary[NGROUPS];
2532 anum = getgroups(NGROUPS,gary);
2534 if (gary[anum] == testgid)
2541 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2544 do_ipcget(optype, arglast)
2548 register STR **st = stack->ary_array;
2549 register int sp = arglast[0];
2553 key = (key_t)str_gnum(st[++sp]);
2554 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2555 flags = (int)str_gnum(st[++sp]);
2561 return msgget(key, flags);
2565 return semget(key, n, flags);
2569 return shmget(key, n, flags);
2571 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2573 fatal("%s not implemented", opname[optype]);
2576 return -1; /* should never happen */
2580 do_ipcctl(optype, arglast)
2584 register STR **st = stack->ary_array;
2585 register int sp = arglast[0];
2588 int id, n, cmd, infosize, getinfo, ret;
2590 id = (int)str_gnum(st[++sp]);
2591 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2592 cmd = (int)str_gnum(st[++sp]);
2596 getinfo = (cmd == IPC_STAT);
2602 if (cmd == IPC_STAT || cmd == IPC_SET)
2603 infosize = sizeof(struct msqid_ds);
2608 if (cmd == IPC_STAT || cmd == IPC_SET)
2609 infosize = sizeof(struct shmid_ds);
2614 if (cmd == IPC_STAT || cmd == IPC_SET)
2615 infosize = sizeof(struct semid_ds);
2616 else if (cmd == GETALL || cmd == SETALL)
2618 struct semid_ds semds;
2619 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2621 getinfo = (cmd == GETALL);
2622 infosize = semds.sem_nsems * sizeof(short);
2623 /* "short" is technically wrong but much more portable
2624 than guessing about u_?short(_t)? */
2628 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2630 fatal("%s not implemented", opname[optype]);
2638 STR_GROW(astr, infosize+1);
2644 if (astr->str_cur != infosize)
2653 int i = (int)str_gnum(astr);
2654 a = (char *)i; /* ouch */
2661 ret = msgctl(id, cmd, a);
2666 ret = semctl(id, n, cmd, a);
2671 ret = shmctl(id, cmd, a);
2675 if (getinfo && ret >= 0) {
2676 astr->str_cur = infosize;
2677 astr->str_ptr[infosize] = '\0';
2687 register STR **st = stack->ary_array;
2688 register int sp = arglast[0];
2691 int id, msize, flags;
2693 id = (int)str_gnum(st[++sp]);
2695 flags = (int)str_gnum(st[++sp]);
2696 mbuf = str_get(mstr);
2697 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2702 return msgsnd(id, mbuf, msize, flags);
2704 fatal("msgsnd not implemented");
2713 register STR **st = stack->ary_array;
2714 register int sp = arglast[0];
2718 int id, msize, flags, ret;
2720 id = (int)str_gnum(st[++sp]);
2722 msize = (int)str_gnum(st[++sp]);
2723 mtype = (long)str_gnum(st[++sp]);
2724 flags = (int)str_gnum(st[++sp]);
2725 mbuf = str_get(mstr);
2726 if (mstr->str_cur < sizeof(long)+msize+1) {
2727 STR_GROW(mstr, sizeof(long)+msize+1);
2728 mbuf = str_get(mstr);
2731 ret = msgrcv(id, mbuf, msize, mtype, flags);
2733 mstr->str_cur = sizeof(long)+ret;
2734 mstr->str_ptr[sizeof(long)+ret] = '\0';
2738 fatal("msgrcv not implemented");
2747 register STR **st = stack->ary_array;
2748 register int sp = arglast[0];
2753 id = (int)str_gnum(st[++sp]);
2755 opbuf = str_get(opstr);
2756 opsize = opstr->str_cur;
2757 if (opsize < sizeof(struct sembuf)
2758 || (opsize % sizeof(struct sembuf)) != 0) {
2763 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
2765 fatal("semop not implemented");
2770 do_shmio(optype, arglast)
2775 register STR **st = stack->ary_array;
2776 register int sp = arglast[0];
2779 int id, mpos, msize;
2780 struct shmid_ds shmds;
2782 extern char *shmat();
2785 id = (int)str_gnum(st[++sp]);
2787 mpos = (int)str_gnum(st[++sp]);
2788 msize = (int)str_gnum(st[++sp]);
2790 if (shmctl(id, IPC_STAT, &shmds) == -1)
2792 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2793 errno = EFAULT; /* can't do as caller requested */
2796 shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2797 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2799 mbuf = str_get(mstr);
2800 if (optype == O_SHMREAD) {
2801 if (mstr->str_cur < msize) {
2802 STR_GROW(mstr, msize+1);
2803 mbuf = str_get(mstr);
2805 bcopy(shm + mpos, mbuf, msize);
2806 mstr->str_cur = msize;
2807 mstr->str_ptr[msize] = '\0';
2812 if ((n = mstr->str_cur) > msize)
2814 bcopy(mbuf, shm + mpos, n);
2816 bzero(shm + mpos + n, msize - n);
2820 fatal("shm I/O not implemented");
2824 #endif /* SYSV IPC */