1 /* $RCSfile: doio.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 13:00:21 $
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.5 92/06/08 13:00:21 lwall
10 * patch20: some machines don't define ENOTSOCK in errno.h
11 * patch20: new warnings for failed use of stat operators on filenames with \n
12 * patch20: wait failed when STDOUT or STDERR reopened to a pipe
13 * patch20: end of file latch not reset on reopen of STDIN
14 * patch20: seek(HANDLE, 0, 1) went to eof because of ancient Ultrix workaround
15 * patch20: fixed memory leak on system() for vfork() machines
16 * patch20: get*by* routines now return something useful in a scalar context
17 * patch20: h_errno now accessible via $?
19 * Revision 4.0.1.4 91/11/05 16:51:43 lwall
20 * patch11: prepared for ctype implementations that don't define isascii()
21 * patch11: perl mistook some streams for sockets because they return mode 0 too
22 * patch11: reopening STDIN, STDOUT and STDERR failed on some machines
23 * patch11: certain perl errors should set EBADF so that $! looks better
24 * patch11: truncate on a closed filehandle could dump
25 * patch11: stats of _ forgot whether prior stat was actually lstat
26 * patch11: -T returned true on NFS directory
28 * Revision 4.0.1.3 91/06/10 01:21:19 lwall
29 * patch10: read didn't work from character special files open for writing
30 * patch10: close-on-exec wrongly set on system file descriptors
32 * Revision 4.0.1.2 91/06/07 10:53:39 lwall
33 * patch4: new copyright notice
34 * patch4: system fd's are now treated specially
35 * patch4: added $^F variable to specify maximum system fd, default 2
36 * patch4: character special files now opened with bidirectional stdio buffers
37 * patch4: taintchecks could improperly modify parent in vfork()
38 * patch4: many, many itty-bitty portability fixes
40 * Revision 4.0.1.1 91/04/11 17:41:06 lwall
41 * patch1: hopefully straightened out some of the Xenix mess
43 * Revision 4.0 91/03/20 01:07:06 lwall
52 #include <sys/socket.h>
55 #include <net/errno.h>
62 #include <sys/select.h>
67 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
97 int laststype = O_STAT;
99 static char* warn_nl = "Unsuccessful %s on filename containing newline";
102 do_open(stab,name,len)
108 register STIO *stio = stab_io(stab);
109 char *myname = savestr(name);
113 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
114 FILE *saveifp = Nullfp;
115 FILE *saveofp = Nullfp;
118 mode[0] = mode[1] = mode[2] = '\0';
120 forkprocess = 1; /* assume true if no fork */
121 while (len && isSPACE(name[len-1]))
124 stio = stab_io(stab) = stio_new();
125 else if (stio->ifp) {
126 fd = fileno(stio->ifp);
127 if (stio->type == '-')
129 else if (fd <= maxsysfd) {
132 savetype = stio->type;
135 else if (stio->type == '|')
136 result = mypclose(stio->ifp);
137 else if (stio->ifp != stio->ofp) {
139 result = fclose(stio->ofp);
140 fclose(stio->ifp); /* clear stdio, fd already closed */
143 result = fclose(stio->ifp);
146 result = fclose(stio->ifp);
147 if (result == EOF && fd > maxsysfd)
148 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
150 stio->ofp = stio->ifp = Nullfp;
152 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
164 for (name++; isSPACE(*name); name++) ;
167 taintproper("Insecure dependency in piped open");
169 fp = mypopen(name,"w");
172 else if (*name == '>') {
174 taintproper("Insecure dependency in open");
178 mode[0] = stio->type = 'a';
187 while (isSPACE(*name))
192 stab = stabent(name,FALSE);
193 if (!stab || !stab_io(stab)) {
199 if (stab_io(stab) && stab_io(stab)->ifp) {
200 fd = fileno(stab_io(stab)->ifp);
201 if (stab_io(stab)->type == 's')
207 if (!(fp = fdopen(fd = dup(fd),mode))) {
212 while (isSPACE(*name))
214 if (strEQ(name,"-")) {
219 fp = fopen(name,mode);
227 while (isSPACE(*name))
231 if (strEQ(name,"-")) {
236 fp = fopen(name,mode);
238 else if (name[len-1] == '|') {
241 taintproper("Insecure dependency in piped open");
244 while (len && isSPACE(name[len-1]))
247 for (; isSPACE(*name); name++) ;
248 fp = mypopen(name,"r");
254 for (; isSPACE(*name); name++) ;
255 if (strEQ(name,"-")) {
260 fp = fopen(name,"r");
264 if (dowarn && stio->type == '<' && index(name, '\n'))
265 warn(warn_nl, "open");
271 stio->type != '|' && stio->type != '-') {
272 if (fstat(fileno(fp),&statbuf) < 0) {
276 if (S_ISSOCK(statbuf.st_mode))
277 stio->type = 's'; /* in case a socket was passed in to us */
281 !(statbuf.st_mode & S_IFMT)
286 int buflen = sizeof tokenbuf;
287 if (getsockname(fileno(fp), tokenbuf, &buflen) >= 0
288 || errno != ENOTSOCK)
289 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
290 /* but some return 0 for streams too, sigh */
294 if (saveifp) { /* must use old fp? */
295 fd = fileno(saveifp);
297 fflush(saveofp); /* emulate fclose() */
298 if (saveofp != saveifp) { /* was a socket? */
304 if (fd != fileno(fp)) {
308 dup2(fileno(fp), fd);
309 str = afetch(fdpid,fileno(fp),TRUE);
310 pid = str->str_u.str_useful;
311 str->str_u.str_useful = 0;
312 str = afetch(fdpid,fd,TRUE);
313 str->str_u.str_useful = pid;
320 #if defined(HAS_FCNTL) && defined(F_SETFD)
322 fcntl(fd,F_SETFD,fd > maxsysfd);
326 if (stio->type == 's'
327 || (stio->type == '>' && S_ISCHR(statbuf.st_mode)) ) {
328 if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
342 stio->type = savetype;
351 #ifndef FLEXFILENAMES
357 static int filemode = 0;
359 static char *oldname;
362 argvoutstab = stabent("ARGVOUT",TRUE);
363 if (filemode & (S_ISUID|S_ISGID)) {
364 fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */
366 (void)fchmod(lastfd,filemode);
368 (void)chmod(oldname,filemode);
372 while (alen(stab_xarray(stab)) >= 0) {
373 str = ashift(stab_xarray(stab));
374 str_sset(stab_val(stab),str);
375 STABSET(stab_val(stab));
376 oldname = str_get(stab_val(stab));
377 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
380 taintproper("Insecure dependency in inplace open");
382 if (strEQ(oldname,"-")) {
384 defoutstab = stabent("STDOUT",TRUE);
385 return stab_io(stab)->ifp;
387 #ifndef FLEXFILENAMES
388 filedev = statbuf.st_dev;
389 fileino = statbuf.st_ino;
391 filemode = statbuf.st_mode;
392 fileuid = statbuf.st_uid;
393 filegid = statbuf.st_gid;
394 if (!S_ISREG(filemode)) {
395 warn("Can't do inplace edit: %s is not a regular file",
397 do_close(stab,FALSE);
403 add_suffix(str,inplace);
405 str_cat(str,inplace);
407 #ifndef FLEXFILENAMES
408 if (stat(str->str_ptr,&statbuf) >= 0
409 && statbuf.st_dev == filedev
410 && statbuf.st_ino == fileino ) {
411 warn("Can't do inplace edit: %s > 14 characters",
413 do_close(stab,FALSE);
420 if (rename(oldname,str->str_ptr) < 0) {
421 warn("Can't rename %s to %s: %s, skipping file",
422 oldname, str->str_ptr, strerror(errno) );
423 do_close(stab,FALSE);
428 do_close(stab,FALSE);
429 (void)unlink(str->str_ptr);
430 (void)rename(oldname,str->str_ptr);
431 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
434 (void)UNLINK(str->str_ptr);
435 if (link(oldname,str->str_ptr) < 0) {
436 warn("Can't rename %s to %s: %s, skipping file",
437 oldname, str->str_ptr, strerror(errno) );
438 do_close(stab,FALSE);
442 (void)UNLINK(oldname);
447 if (UNLINK(oldname) < 0) {
448 warn("Can't rename %s to %s: %s, skipping file",
449 oldname, str->str_ptr, strerror(errno) );
450 do_close(stab,FALSE);
455 fatal("Can't do inplace edit without backup");
460 str_cat(str,oldname);
461 errno = 0; /* in case sprintf set errno */
462 if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
463 warn("Can't do inplace edit on %s: %s",
464 oldname, strerror(errno) );
465 do_close(stab,FALSE);
469 defoutstab = argvoutstab;
470 lastfd = fileno(stab_io(argvoutstab)->ifp);
471 (void)fstat(lastfd,&statbuf);
473 (void)fchmod(lastfd,filemode);
475 (void)chmod(oldname,filemode);
477 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
479 (void)fchown(lastfd,fileuid,filegid);
482 (void)chown(oldname,fileuid,filegid);
488 return stab_io(stab)->ifp;
491 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
495 (void)do_close(argvoutstab,FALSE);
496 defoutstab = stabent("STDOUT",TRUE);
503 do_pipe(str, rstab, wstab)
508 register STIO *rstio;
509 register STIO *wstio;
517 rstio = stab_io(rstab);
518 wstio = stab_io(wstab);
521 rstio = stab_io(rstab) = stio_new();
523 do_close(rstab,FALSE);
525 wstio = stab_io(wstab) = stio_new();
527 do_close(wstab,FALSE);
531 rstio->ifp = fdopen(fd[0], "r");
532 wstio->ofp = fdopen(fd[1], "w");
533 wstio->ifp = wstio->ofp;
536 if (!rstio->ifp || !wstio->ofp) {
537 if (rstio->ifp) fclose(rstio->ifp);
539 if (wstio->ofp) fclose(wstio->ofp);
544 str_sset(str,&str_yes);
548 str_sset(str,&str_undef);
554 do_close(stab,explicit)
568 stio = stab_io(stab);
569 if (!stio) { /* never opened */
570 if (dowarn && explicit)
571 warn("Close on unopened file <%s>",stab_ename(stab));
575 if (stio->type == '|') {
576 status = mypclose(stio->ifp);
577 retval = (status == 0);
578 statusvalue = (unsigned short)status & 0xffff;
580 else if (stio->type == '-')
583 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
584 retval = (fclose(stio->ofp) != EOF);
585 fclose(stio->ifp); /* clear stdio, fd already closed */
588 retval = (fclose(stio->ifp) != EOF);
590 stio->ofp = stio->ifp = Nullfp;
605 if (!stab) { /* eof() */
607 stio = stab_io(argvstab);
612 stio = stab_io(stab);
619 #ifdef STDSTDIO /* (the code works without this) */
620 if (stio->ifp->_cnt > 0) /* cheat a little, since */
621 return FALSE; /* this is the most usual case */
624 ch = getc(stio->ifp);
626 (void)ungetc(ch, stio->ifp);
630 if (stio->ifp->_cnt < -1)
631 stio->ifp->_cnt = -1;
633 if (!stab) { /* not necessarily a real EOF yet? */
634 if (!nextargv(argvstab)) /* get another fp handy */
638 return TRUE; /* normal fp, definitely end of file */
652 stio = stab_io(stab);
653 if (!stio || !stio->ifp)
656 #ifdef ULTRIX_STDIO_BOTCH
658 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
661 return ftell(stio->ifp);
665 warn("tell() on unopened file");
671 do_seek(stab, pos, whence)
681 stio = stab_io(stab);
682 if (!stio || !stio->ifp)
685 #ifdef ULTRIX_STDIO_BOTCH
687 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
690 return fseek(stio->ifp, pos, whence) >= 0;
694 warn("seek() on unopened file");
700 do_ctl(optype,stab,func,argstr)
710 if (!stab || !argstr || !(stio = stab_io(stab)) || !stio->ifp) {
711 errno = EBADF; /* well, sort of... */
715 if (argstr->str_pok || !argstr->str_nok) {
716 if (!argstr->str_pok)
721 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
725 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
727 retval = 256; /* otherwise guess at what's safe */
729 if (argstr->str_cur < retval) {
730 Str_Grow(argstr,retval+1);
731 argstr->str_cur = retval;
735 s[argstr->str_cur] = 17; /* a little sanity check here */
738 retval = (int)str_gnum(argstr);
740 s = (char*)(long)retval; /* ouch */
742 s = (char*)retval; /* ouch */
747 if (optype == O_IOCTL)
748 retval = ioctl(fileno(stio->ifp), func, s);
751 fatal("fcntl is not implemented");
754 retval = fcntl(fileno(stio->ifp), func, s);
756 fatal("fcntl is not implemented");
763 if (argstr->str_pok) {
764 if (s[argstr->str_cur] != 17)
765 fatal("Return value overflowed string");
766 s[argstr->str_cur] = 0; /* put our null back */
772 do_stat(str,arg,gimme,arglast)
778 register ARRAY *ary = stack;
779 register int sp = arglast[0] + 1;
782 if ((arg[1].arg_type & A_MASK) == A_WORD) {
783 tmpstab = arg[1].arg_ptr.arg_stab;
784 if (tmpstab != defstab) {
787 str_set(statname,"");
788 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
789 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
794 else if (laststatval < 0)
798 str_set(statname,str_get(ary->ary_array[sp]));
801 laststype = arg->arg_type;
802 if (arg->arg_type == O_LSTAT)
803 laststatval = lstat(str_get(statname),&statcache);
806 laststatval = stat(str_get(statname),&statcache);
807 if (laststatval < 0) {
808 if (dowarn && index(str_get(statname), '\n'))
809 warn(warn_nl, "stat");
814 if (gimme != G_ARRAY) {
816 str_sset(str,&str_yes);
818 str_sset(str,&str_undef);
820 ary->ary_array[sp] = str;
826 (void)astore(ary,++sp,
827 str_2mortal(str_nmake((double)statcache.st_dev)));
828 (void)astore(ary,++sp,
829 str_2mortal(str_nmake((double)statcache.st_ino)));
830 (void)astore(ary,++sp,
831 str_2mortal(str_nmake((double)statcache.st_mode)));
832 (void)astore(ary,++sp,
833 str_2mortal(str_nmake((double)statcache.st_nlink)));
834 (void)astore(ary,++sp,
835 str_2mortal(str_nmake((double)statcache.st_uid)));
836 (void)astore(ary,++sp,
837 str_2mortal(str_nmake((double)statcache.st_gid)));
838 (void)astore(ary,++sp,
839 str_2mortal(str_nmake((double)statcache.st_rdev)));
840 (void)astore(ary,++sp,
841 str_2mortal(str_nmake((double)statcache.st_size)));
842 (void)astore(ary,++sp,
843 str_2mortal(str_nmake((double)statcache.st_atime)));
844 (void)astore(ary,++sp,
845 str_2mortal(str_nmake((double)statcache.st_mtime)));
846 (void)astore(ary,++sp,
847 str_2mortal(str_nmake((double)statcache.st_ctime)));
849 (void)astore(ary,++sp,
850 str_2mortal(str_nmake((double)statcache.st_blksize)));
851 (void)astore(ary,++sp,
852 str_2mortal(str_nmake((double)statcache.st_blocks)));
854 (void)astore(ary,++sp,
855 str_2mortal(str_make("",0)));
856 (void)astore(ary,++sp,
857 str_2mortal(str_make("",0)));
860 (void)astore(ary,++sp,str_nmake(0.0));
866 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
867 /* code courtesy of William Kucharski */
870 int chsize(fd, length)
871 int fd; /* file descriptor */
872 off_t length; /* length to set file to */
878 if (fstat(fd, &filebuf) < 0)
881 if (filebuf.st_size < length) {
883 /* extend file length */
885 if ((lseek(fd, (length - 1), 0)) < 0)
888 /* write a "0" byte */
890 if ((write(fd, "", 1)) != 1)
894 /* truncate length */
899 fl.l_type = F_WRLCK; /* write lock on file space */
902 * This relies on the UNDOCUMENTED F_FREESP argument to
903 * fcntl(2), which truncates the file so that it ends at the
904 * position indicated by fl.l_start.
906 * Will minor miracles never cease?
909 if (fcntl(fd, F_FREESP, &fl) < 0)
916 #endif /* F_FREESP */
919 do_truncate(str,arg,gimme,arglast)
925 register ARRAY *ary = stack;
926 register int sp = arglast[0] + 1;
927 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
931 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
933 if ((arg[1].arg_type & A_MASK) == A_WORD) {
934 tmpstab = arg[1].arg_ptr.arg_stab;
935 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
936 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
939 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
942 if ((arg[1].arg_type & A_MASK) == A_WORD) {
943 tmpstab = arg[1].arg_ptr.arg_stab;
944 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
945 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
951 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
954 if (chsize(tmpfd, len) < 0)
962 str_sset(str,&str_yes);
964 str_sset(str,&str_undef);
966 ary->ary_array[sp] = str;
969 fatal("truncate not implemented");
974 looks_like_number(str)
983 send = s + str->str_cur;
988 if (*s == '+' || *s == '-')
996 else if (s == str->str_ptr)
1002 if (*s == 'e' || *s == 'E') {
1004 if (*s == '+' || *s == '-')
1021 register char *tmps;
1025 warn("print to unopened file");
1032 ((str->str_nok && str->str_u.str_nval != 0.0)
1033 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
1034 fprintf(fp, ofmt, str->str_u.str_nval);
1038 tmps = str_get(str);
1039 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
1040 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
1041 STR *tmpstr = str_mortal(&str_undef);
1042 stab_efullname(tmpstr,((STAB*)str));/* a stab value, be nice */
1044 tmps = str->str_ptr;
1047 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
1054 do_aprint(arg,fp,arglast)
1059 register STR **st = stack->ary_array;
1060 register int sp = arglast[1];
1061 register int retval;
1062 register int items = arglast[2] - sp;
1066 warn("print to unopened file");
1071 if (arg->arg_type == O_PRTF) {
1072 do_sprintf(arg->arg_ptr.arg_str,items,st);
1073 retval = do_print(arg->arg_ptr.arg_str,fp);
1076 retval = (items <= 0);
1077 for (; items > 0; items--,st++) {
1078 if (retval && ofslen) {
1079 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
1084 if (!(retval = do_print(*st, fp)))
1087 if (retval && orslen)
1088 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
1101 if (arg[1].arg_type & A_DONT) {
1102 stio = stab_io(arg[1].arg_ptr.arg_stab);
1103 if (stio && stio->ifp) {
1104 statstab = arg[1].arg_ptr.arg_stab;
1105 str_set(statname,"");
1107 return (laststatval = fstat(fileno(stio->ifp), &statcache));
1110 if (arg[1].arg_ptr.arg_stab == defstab)
1113 warn("Stat on unopened file <%s>",
1114 stab_ename(arg[1].arg_ptr.arg_stab));
1115 statstab = Nullstab;
1116 str_set(statname,"");
1117 return (laststatval = -1);
1121 statstab = Nullstab;
1122 str_set(statname,str_get(str));
1124 laststatval = stat(str_get(str),&statcache);
1125 if (laststatval < 0 && dowarn && index(str_get(str), '\n'))
1126 warn(warn_nl, "stat");
1136 if (arg[1].arg_type & A_DONT) {
1137 if (arg[1].arg_ptr.arg_stab == defstab) {
1138 if (laststype != O_LSTAT)
1139 fatal("The stat preceding -l _ wasn't an lstat");
1142 fatal("You can't use -l on a filehandle");
1145 laststype = O_LSTAT;
1146 statstab = Nullstab;
1147 str_set(statname,str_get(str));
1149 laststatval = lstat(str_get(str),&statcache);
1151 laststatval = stat(str_get(str),&statcache);
1153 if (laststatval < 0 && dowarn && index(str_get(str), '\n'))
1154 warn(warn_nl, "lstat");
1167 register STDCHAR *s;
1168 register STIO *stio;
1170 if (arg[1].arg_type & A_DONT) {
1171 if (arg[1].arg_ptr.arg_stab == defstab) {
1173 stio = stab_io(statstab);
1176 goto really_filename;
1180 statstab = arg[1].arg_ptr.arg_stab;
1181 str_set(statname,"");
1182 stio = stab_io(statstab);
1184 if (stio && stio->ifp) {
1185 #if defined(STDSTDIO) || defined(atarist) /* this will work with atariST */
1186 fstat(fileno(stio->ifp),&statcache);
1187 if (S_ISDIR(statcache.st_mode)) /* handle NFS glitch */
1188 return arg->arg_type == O_FTTEXT ? &str_no : &str_yes;
1189 if (stio->ifp->_cnt <= 0) {
1190 i = getc(stio->ifp);
1192 (void)ungetc(i,stio->ifp);
1194 if (stio->ifp->_cnt <= 0) /* null file is anything */
1196 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1197 s = stio->ifp->_base;
1199 fatal("-T and -B not implemented on filehandles");
1204 warn("Test on unopened file <%s>",
1205 stab_ename(arg[1].arg_ptr.arg_stab));
1211 statstab = Nullstab;
1212 str_set(statname,str_get(str));
1214 i = open(str_get(str),0);
1216 if (dowarn && index(str_get(str), '\n'))
1217 warn(warn_nl, "open");
1220 fstat(i,&statcache);
1221 len = read(i,tbuf,512);
1224 if (S_ISDIR(statcache.st_mode) && arg->arg_type == O_FTTEXT)
1225 return &str_no; /* special case NFS directories */
1226 return &str_yes; /* null file is anything */
1231 /* now scan s to look for textiness */
1233 for (i = 0; i < len; i++,s++) {
1234 if (!*s) { /* null never allowed in text */
1241 *s != '\n' && *s != '\r' && *s != '\b' &&
1242 *s != '\t' && *s != '\f' && *s != 27)
1246 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1252 static char **Argv = Null(char **);
1253 static char *Cmd = Nullch;
1256 do_aexec(really,arglast)
1260 register STR **st = stack->ary_array;
1261 register int sp = arglast[1];
1262 register int items = arglast[2] - sp;
1267 New(401,Argv, items+1, char*);
1269 for (st += ++sp; items > 0; items--,st++) {
1271 *a++ = str_get(*st);
1277 if (*Argv[0] != '/') /* will execvp use PATH? */
1278 taintenv(); /* testing IFS here is overkill, probably */
1280 if (really && *(tmps = str_get(really)))
1283 execvp(Argv[0],Argv);
1294 Argv = Null(char **);
1310 /* save an extra exec if possible */
1313 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1329 if (s[-1] == '\'') {
1331 execl(cshname,"csh", flags,ncmd,(char*)0);
1339 /* see if there are shell metacharacters in it */
1342 for (s = cmd; *s && isALPHA(*s); s++) ; /* catch VAR=val gizmo */
1345 for (s = cmd; *s; s++) {
1346 if (*s != ' ' && !isALPHA(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1347 if (*s == '\n' && !s[1]) {
1352 execl("/bin/sh","sh","-c",cmd,(char*)0);
1356 New(402,Argv, (s - cmd) / 2 + 2, char*);
1357 Cmd = nsavestr(cmd, s-cmd);
1359 for (s = Cmd; *s;) {
1360 while (*s && isSPACE(*s)) s++;
1363 while (*s && !isSPACE(*s)) s++;
1369 execvp(Argv[0],Argv);
1370 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1381 do_socket(stab, arglast)
1385 register STR **st = stack->ary_array;
1386 register int sp = arglast[1];
1387 register STIO *stio;
1388 int domain, type, protocol, fd;
1395 stio = stab_io(stab);
1397 stio = stab_io(stab) = stio_new();
1399 do_close(stab,FALSE);
1401 domain = (int)str_gnum(st[++sp]);
1402 type = (int)str_gnum(st[++sp]);
1403 protocol = (int)str_gnum(st[++sp]);
1405 taintproper("Insecure dependency in socket");
1407 fd = socket(domain,type,protocol);
1410 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1411 stio->ofp = fdopen(fd, "w");
1413 if (!stio->ifp || !stio->ofp) {
1414 if (stio->ifp) fclose(stio->ifp);
1415 if (stio->ofp) fclose(stio->ofp);
1416 if (!stio->ifp && !stio->ofp) close(fd);
1424 do_bind(stab, arglast)
1428 register STR **st = stack->ary_array;
1429 register int sp = arglast[1];
1430 register STIO *stio;
1436 stio = stab_io(stab);
1437 if (!stio || !stio->ifp)
1440 addr = str_get(st[++sp]);
1442 taintproper("Insecure dependency in bind");
1444 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1448 warn("bind() on closed fd");
1455 do_connect(stab, arglast)
1459 register STR **st = stack->ary_array;
1460 register int sp = arglast[1];
1461 register STIO *stio;
1467 stio = stab_io(stab);
1468 if (!stio || !stio->ifp)
1471 addr = str_get(st[++sp]);
1473 taintproper("Insecure dependency in connect");
1475 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1479 warn("connect() on closed fd");
1486 do_listen(stab, arglast)
1490 register STR **st = stack->ary_array;
1491 register int sp = arglast[1];
1492 register STIO *stio;
1498 stio = stab_io(stab);
1499 if (!stio || !stio->ifp)
1502 backlog = (int)str_gnum(st[++sp]);
1503 return listen(fileno(stio->ifp), backlog) >= 0;
1507 warn("listen() on closed fd");
1513 do_accept(str, nstab, gstab)
1518 register STIO *nstio;
1519 register STIO *gstio;
1520 int len = sizeof buf;
1528 gstio = stab_io(gstab);
1529 nstio = stab_io(nstab);
1531 if (!gstio || !gstio->ifp)
1534 nstio = stab_io(nstab) = stio_new();
1535 else if (nstio->ifp)
1536 do_close(nstab,FALSE);
1538 fd = accept(fileno(gstio->ifp),(struct sockaddr *)buf,&len);
1541 nstio->ifp = fdopen(fd, "r");
1542 nstio->ofp = fdopen(fd, "w");
1544 if (!nstio->ifp || !nstio->ofp) {
1545 if (nstio->ifp) fclose(nstio->ifp);
1546 if (nstio->ofp) fclose(nstio->ofp);
1547 if (!nstio->ifp && !nstio->ofp) close(fd);
1551 str_nset(str, buf, len);
1556 warn("accept() on closed fd");
1559 str_sset(str,&str_undef);
1564 do_shutdown(stab, arglast)
1568 register STR **st = stack->ary_array;
1569 register int sp = arglast[1];
1570 register STIO *stio;
1576 stio = stab_io(stab);
1577 if (!stio || !stio->ifp)
1580 how = (int)str_gnum(st[++sp]);
1581 return shutdown(fileno(stio->ifp), how) >= 0;
1585 warn("shutdown() on closed fd");
1592 do_sopt(optype, stab, arglast)
1597 register STR **st = stack->ary_array;
1598 register int sp = arglast[1];
1599 register STIO *stio;
1602 unsigned int optname;
1607 stio = stab_io(stab);
1608 if (!stio || !stio->ifp)
1611 fd = fileno(stio->ifp);
1612 lvl = (unsigned int)str_gnum(st[sp+1]);
1613 optname = (unsigned int)str_gnum(st[sp+2]);
1616 st[sp] = str_2mortal(Str_new(22,257));
1617 st[sp]->str_cur = 256;
1618 st[sp]->str_pok = 1;
1619 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr,
1620 (int*)&st[sp]->str_cur) < 0)
1625 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1635 warn("[gs]etsockopt() on closed fd");
1636 st[sp] = &str_undef;
1643 do_getsockname(optype, stab, arglast)
1648 register STR **st = stack->ary_array;
1649 register int sp = arglast[1];
1650 register STIO *stio;
1656 stio = stab_io(stab);
1657 if (!stio || !stio->ifp)
1660 st[sp] = str_2mortal(Str_new(22,257));
1661 st[sp]->str_cur = 256;
1662 st[sp]->str_pok = 1;
1663 fd = fileno(stio->ifp);
1666 if (getsockname(fd, st[sp]->str_ptr, (int*)&st[sp]->str_cur) < 0)
1670 if (getpeername(fd, st[sp]->str_ptr, (int*)&st[sp]->str_cur) < 0)
1679 warn("get{sock,peer}name() on closed fd");
1682 st[sp] = &str_undef;
1688 do_ghent(which,gimme,arglast)
1693 register ARRAY *ary = stack;
1694 register int sp = arglast[0];
1695 register char **elem;
1697 struct hostent *gethostbyname();
1698 struct hostent *gethostbyaddr();
1699 #ifdef HAS_GETHOSTENT
1700 struct hostent *gethostent();
1702 struct hostent *hent;
1705 if (which == O_GHBYNAME) {
1706 char *name = str_get(ary->ary_array[sp+1]);
1708 hent = gethostbyname(name);
1710 else if (which == O_GHBYADDR) {
1711 STR *addrstr = ary->ary_array[sp+1];
1712 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1713 char *addr = str_get(addrstr);
1715 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1718 #ifdef HAS_GETHOSTENT
1719 hent = gethostent();
1721 fatal("gethostent not implemented");
1724 #ifdef HOST_NOT_FOUND
1726 statusvalue = (unsigned short)h_errno & 0xffff;
1729 if (gimme != G_ARRAY) {
1730 astore(ary, ++sp, str = str_mortal(&str_undef));
1732 if (which == O_GHBYNAME) {
1734 str_nset(str, *hent->h_addr, hent->h_length);
1736 str_nset(str, hent->h_addr, hent->h_length);
1740 str_set(str, hent->h_name);
1747 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1748 str_set(str, hent->h_name);
1749 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1750 for (elem = hent->h_aliases; *elem; elem++) {
1751 str_cat(str, *elem);
1753 str_ncat(str," ",1);
1755 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1756 str_numset(str, (double)hent->h_addrtype);
1757 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1758 len = hent->h_length;
1759 str_numset(str, (double)len);
1761 for (elem = hent->h_addr_list; *elem; elem++) {
1762 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1763 str_nset(str, *elem, len);
1766 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1767 str_nset(str, hent->h_addr, len);
1772 (void)astore(ary, ++sp, str_mortal(&str_no));
1780 do_gnent(which,gimme,arglast)
1785 register ARRAY *ary = stack;
1786 register int sp = arglast[0];
1787 register char **elem;
1789 struct netent *getnetbyname();
1790 struct netent *getnetbyaddr();
1791 struct netent *getnetent();
1792 struct netent *nent;
1794 if (which == O_GNBYNAME) {
1795 char *name = str_get(ary->ary_array[sp+1]);
1797 nent = getnetbyname(name);
1799 else if (which == O_GNBYADDR) {
1800 unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
1801 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1803 nent = getnetbyaddr((long)addr,addrtype);
1808 if (gimme != G_ARRAY) {
1809 astore(ary, ++sp, str = str_mortal(&str_undef));
1811 if (which == O_GNBYNAME)
1812 str_numset(str, (double)nent->n_net);
1814 str_set(str, nent->n_name);
1821 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1822 str_set(str, nent->n_name);
1823 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1824 for (elem = nent->n_aliases; *elem; elem++) {
1825 str_cat(str, *elem);
1827 str_ncat(str," ",1);
1829 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1830 str_numset(str, (double)nent->n_addrtype);
1831 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1832 str_numset(str, (double)nent->n_net);
1836 (void)astore(ary, ++sp, str_mortal(&str_no));
1844 do_gpent(which,gimme,arglast)
1849 register ARRAY *ary = stack;
1850 register int sp = arglast[0];
1851 register char **elem;
1853 struct protoent *getprotobyname();
1854 struct protoent *getprotobynumber();
1855 struct protoent *getprotoent();
1856 struct protoent *pent;
1858 if (which == O_GPBYNAME) {
1859 char *name = str_get(ary->ary_array[sp+1]);
1861 pent = getprotobyname(name);
1863 else if (which == O_GPBYNUMBER) {
1864 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1866 pent = getprotobynumber(proto);
1869 pent = getprotoent();
1871 if (gimme != G_ARRAY) {
1872 astore(ary, ++sp, str = str_mortal(&str_undef));
1874 if (which == O_GPBYNAME)
1875 str_numset(str, (double)pent->p_proto);
1877 str_set(str, pent->p_name);
1884 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1885 str_set(str, pent->p_name);
1886 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1887 for (elem = pent->p_aliases; *elem; elem++) {
1888 str_cat(str, *elem);
1890 str_ncat(str," ",1);
1892 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1893 str_numset(str, (double)pent->p_proto);
1897 (void)astore(ary, ++sp, str_mortal(&str_no));
1905 do_gsent(which,gimme,arglast)
1910 register ARRAY *ary = stack;
1911 register int sp = arglast[0];
1912 register char **elem;
1914 struct servent *getservbyname();
1915 struct servent *getservbynumber();
1916 struct servent *getservent();
1917 struct servent *sent;
1919 if (which == O_GSBYNAME) {
1920 char *name = str_get(ary->ary_array[sp+1]);
1921 char *proto = str_get(ary->ary_array[sp+2]);
1923 if (proto && !*proto)
1926 sent = getservbyname(name,proto);
1928 else if (which == O_GSBYPORT) {
1929 int port = (int)str_gnum(ary->ary_array[sp+1]);
1930 char *proto = str_get(ary->ary_array[sp+2]);
1932 sent = getservbyport(port,proto);
1935 sent = getservent();
1937 if (gimme != G_ARRAY) {
1938 astore(ary, ++sp, str = str_mortal(&str_undef));
1940 if (which == O_GSBYNAME) {
1942 str_numset(str, (double)ntohs(sent->s_port));
1944 str_numset(str, (double)(sent->s_port));
1948 str_set(str, sent->s_name);
1955 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1956 str_set(str, sent->s_name);
1957 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1958 for (elem = sent->s_aliases; *elem; elem++) {
1959 str_cat(str, *elem);
1961 str_ncat(str," ",1);
1963 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1965 str_numset(str, (double)ntohs(sent->s_port));
1967 str_numset(str, (double)(sent->s_port));
1969 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1970 str_set(str, sent->s_proto);
1974 (void)astore(ary, ++sp, str_mortal(&str_no));
1981 #endif /* HAS_SOCKET */
1985 do_select(gimme,arglast)
1989 register STR **st = stack->ary_array;
1990 register int sp = arglast[0];
1998 struct timeval timebuf;
1999 struct timeval *tbuf = &timebuf;
2001 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
2007 #if BYTEORDER & 0xf0000
2008 #define ORDERBYTE (0x88888888 - BYTEORDER)
2010 #define ORDERBYTE (0x4444 - BYTEORDER)
2015 for (i = 1; i <= 3; i++) {
2016 j = st[sp+i]->str_cur;
2021 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
2022 growsize = maxlen; /* little endians can use vecs directly */
2030 masksize = NFDBITS / NBBY;
2032 masksize = sizeof(long); /* documented int, everyone seems to use long */
2034 growsize = maxlen + (masksize - (maxlen % masksize));
2035 Zero(&fd_sets[0], 4, char*);
2038 for (i = 1; i <= 3; i++) {
2043 Str_Grow(str,growsize);
2044 s = str_get(str) + j;
2045 while (++j <= growsize) {
2049 else if (str->str_ptr) {
2050 Safefree(str->str_ptr);
2051 str->str_ptr = Nullch;
2054 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
2057 New(403, fd_sets[i], growsize, char);
2058 for (offset = 0; offset < growsize; offset += masksize) {
2059 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
2060 fd_sets[i][j+offset] = s[(k % masksize) + offset];
2066 if (str->str_nok || str->str_pok) {
2067 value = str_gnum(str);
2070 timebuf.tv_sec = (long)value;
2071 value -= (double)timebuf.tv_sec;
2072 timebuf.tv_usec = (long)(value * 1000000.0);
2075 tbuf = Null(struct timeval*);
2077 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
2091 for (i = 1; i <= 3; i++) {
2095 for (offset = 0; offset < growsize; offset += masksize) {
2096 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
2097 s[(k % masksize) + offset] = fd_sets[i][j+offset];
2099 Safefree(fd_sets[i]);
2104 st[++sp] = str_mortal(&str_no);
2105 str_numset(st[sp], (double)nfound);
2106 if (gimme == G_ARRAY && tbuf) {
2107 value = (double)(timebuf.tv_sec) +
2108 (double)(timebuf.tv_usec) / 1000000.0;
2109 st[++sp] = str_mortal(&str_no);
2110 str_numset(st[sp], value);
2118 do_spair(stab1, stab2, arglast)
2123 register STR **st = stack->ary_array;
2124 register int sp = arglast[2];
2125 register STIO *stio1;
2126 register STIO *stio2;
2127 int domain, type, protocol, fd[2];
2129 if (!stab1 || !stab2)
2132 stio1 = stab_io(stab1);
2133 stio2 = stab_io(stab2);
2135 stio1 = stab_io(stab1) = stio_new();
2136 else if (stio1->ifp)
2137 do_close(stab1,FALSE);
2139 stio2 = stab_io(stab2) = stio_new();
2140 else if (stio2->ifp)
2141 do_close(stab2,FALSE);
2143 domain = (int)str_gnum(st[++sp]);
2144 type = (int)str_gnum(st[++sp]);
2145 protocol = (int)str_gnum(st[++sp]);
2147 taintproper("Insecure dependency in socketpair");
2149 #ifdef HAS_SOCKETPAIR
2150 if (socketpair(domain,type,protocol,fd) < 0)
2153 fatal("Socketpair unimplemented");
2155 stio1->ifp = fdopen(fd[0], "r");
2156 stio1->ofp = fdopen(fd[0], "w");
2158 stio2->ifp = fdopen(fd[1], "r");
2159 stio2->ofp = fdopen(fd[1], "w");
2161 if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
2162 if (stio1->ifp) fclose(stio1->ifp);
2163 if (stio1->ofp) fclose(stio1->ofp);
2164 if (!stio1->ifp && !stio1->ofp) close(fd[0]);
2165 if (stio2->ifp) fclose(stio2->ifp);
2166 if (stio2->ofp) fclose(stio2->ofp);
2167 if (!stio2->ifp && !stio2->ofp) close(fd[1]);
2174 #endif /* HAS_SOCKET */
2177 do_gpwent(which,gimme,arglast)
2183 register ARRAY *ary = stack;
2184 register int sp = arglast[0];
2186 struct passwd *getpwnam();
2187 struct passwd *getpwuid();
2188 struct passwd *getpwent();
2189 struct passwd *pwent;
2191 if (which == O_GPWNAM) {
2192 char *name = str_get(ary->ary_array[sp+1]);
2194 pwent = getpwnam(name);
2196 else if (which == O_GPWUID) {
2197 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2199 pwent = getpwuid(uid);
2204 if (gimme != G_ARRAY) {
2205 astore(ary, ++sp, str = str_mortal(&str_undef));
2207 if (which == O_GPWNAM)
2208 str_numset(str, (double)pwent->pw_uid);
2210 str_set(str, pwent->pw_name);
2216 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2217 str_set(str, pwent->pw_name);
2218 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2219 str_set(str, pwent->pw_passwd);
2220 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2221 str_numset(str, (double)pwent->pw_uid);
2222 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2223 str_numset(str, (double)pwent->pw_gid);
2224 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2226 str_numset(str, (double)pwent->pw_change);
2229 str_numset(str, (double)pwent->pw_quota);
2232 str_set(str, pwent->pw_age);
2236 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2238 str_set(str,pwent->pw_class);
2241 str_set(str, pwent->pw_comment);
2244 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2245 str_set(str, pwent->pw_gecos);
2246 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2247 str_set(str, pwent->pw_dir);
2248 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2249 str_set(str, pwent->pw_shell);
2251 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2252 str_numset(str, (double)pwent->pw_expire);
2258 fatal("password routines not implemented");
2263 do_ggrent(which,gimme,arglast)
2269 register ARRAY *ary = stack;
2270 register int sp = arglast[0];
2271 register char **elem;
2273 struct group *getgrnam();
2274 struct group *getgrgid();
2275 struct group *getgrent();
2276 struct group *grent;
2278 if (which == O_GGRNAM) {
2279 char *name = str_get(ary->ary_array[sp+1]);
2281 grent = getgrnam(name);
2283 else if (which == O_GGRGID) {
2284 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2286 grent = getgrgid(gid);
2291 if (gimme != G_ARRAY) {
2292 astore(ary, ++sp, str = str_mortal(&str_undef));
2294 if (which == O_GGRNAM)
2295 str_numset(str, (double)grent->gr_gid);
2297 str_set(str, grent->gr_name);
2303 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2304 str_set(str, grent->gr_name);
2305 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2306 str_set(str, grent->gr_passwd);
2307 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2308 str_numset(str, (double)grent->gr_gid);
2309 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2310 for (elem = grent->gr_mem; *elem; elem++) {
2311 str_cat(str, *elem);
2313 str_ncat(str," ",1);
2319 fatal("group routines not implemented");
2324 do_dirop(optype,stab,gimme,arglast)
2330 #if defined(DIRENT) && defined(HAS_READDIR)
2331 register ARRAY *ary = stack;
2332 register STR **st = ary->ary_array;
2333 register int sp = arglast[1];
2334 register STIO *stio;
2337 struct DIRENT *readdir();
2339 register struct DIRENT *dp;
2343 if (!(stio = stab_io(stab)))
2344 stio = stab_io(stab) = stio_new();
2345 if (!stio->dirp && optype != O_OPEN_DIR)
2351 closedir(stio->dirp);
2352 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2356 if (gimme == G_ARRAY) {
2359 while (dp = readdir(stio->dirp)) {
2361 (void)astore(ary,++sp,
2362 str_2mortal(str_make(dp->d_name,dp->d_namlen)));
2364 (void)astore(ary,++sp,
2365 str_2mortal(str_make(dp->d_name,0)));
2370 if (!(dp = readdir(stio->dirp)))
2372 st[sp] = str_mortal(&str_undef);
2374 str_nset(st[sp], dp->d_name, dp->d_namlen);
2376 str_set(st[sp], dp->d_name);
2380 #if defined(HAS_TELLDIR) || defined(telldir)
2385 st[sp] = str_mortal(&str_undef);
2386 str_numset(st[sp], (double)telldir(stio->dirp));
2390 #if defined(HAS_SEEKDIR) || defined(seekdir)
2392 st[sp] = str_mortal(&str_undef);
2393 along = (long)str_gnum(st[sp+1]);
2394 (void)seekdir(stio->dirp,along);
2397 #if defined(HAS_REWINDDIR) || defined(rewinddir)
2399 st[sp] = str_mortal(&str_undef);
2400 (void)rewinddir(stio->dirp);
2404 st[sp] = str_mortal(&str_undef);
2405 (void)closedir(stio->dirp);
2414 st[sp] = &str_undef;
2421 fatal("Unimplemented directory operation");
2429 register STR **st = stack->ary_array;
2430 register int sp = arglast[1];
2431 register int items = arglast[2] - sp;
2434 register int tot = 0;
2438 for (st += ++sp; items--; st++)
2439 tainted |= (*st)->str_tainted;
2440 st = stack->ary_array;
2442 items = arglast[2] - sp;
2447 taintproper("Insecure dependency in chmod");
2451 val = (int)str_gnum(st[++sp]);
2453 if (chmod(str_get(st[++sp]),val))
2461 taintproper("Insecure dependency in chown");
2466 val = (int)str_gnum(st[++sp]);
2467 val2 = (int)str_gnum(st[++sp]);
2469 if (chown(str_get(st[++sp]),val,val2))
2478 taintproper("Insecure dependency in kill");
2482 s = str_get(st[++sp]);
2484 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2486 if (!(val = whichsig(s)))
2487 fatal("Unrecognized signal name \"%s\"",s);
2490 val = (int)str_gnum(st[sp]);
2494 int proc = (int)str_gnum(st[++sp]);
2496 if (killpg(proc,val)) /* BSD */
2498 if (kill(-proc,val)) /* SYSV */
2505 if (kill((int)(str_gnum(st[++sp])),val))
2514 taintproper("Insecure dependency in unlink");
2518 s = str_get(st[++sp]);
2519 if (euid || unsafe) {
2523 else { /* don't let root wipe out directories without -U */
2525 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2527 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2539 taintproper("Insecure dependency in utime");
2543 struct utimbuf utbuf;
2551 Zero(&utbuf, sizeof utbuf, char);
2552 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2553 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2558 if (utime(str_get(st[++sp]),&utbuf))
2570 /* Do the permissions allow some operation? Assumes statcache already set. */
2573 cando(bit, effective, statbufp)
2576 register struct stat *statbufp;
2579 /* [Comments and code from Len Reed]
2580 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2581 * to write-protected files. The execute permission bit is set
2582 * by the Miscrosoft C library stat() function for the following:
2587 * All files and directories are readable.
2588 * Directories and special files, e.g. "CON", cannot be
2590 * [Comment by Tom Dinger -- a directory can have the write-protect
2591 * bit set in the file system, but DOS permits changes to
2592 * the directory anyway. In addition, all bets are off
2593 * here for networked software, such as Novell and
2597 /* Atari stat() does pretty much the same thing. we set x_bit_set_in_stat
2598 * too so it will actually look into the files for magic numbers
2600 return (bit & statbufp->st_mode) ? TRUE : FALSE;
2603 if ((effective ? euid : uid) == 0) { /* root is special */
2604 if (bit == S_IXUSR) {
2605 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
2609 return TRUE; /* root reads and writes anything */
2612 if (statbufp->st_uid == (effective ? euid : uid) ) {
2613 if (statbufp->st_mode & bit)
2614 return TRUE; /* ok as "user" */
2616 else if (ingroup((int)statbufp->st_gid,effective)) {
2617 if (statbufp->st_mode & bit >> 3)
2618 return TRUE; /* ok as "group" */
2620 else if (statbufp->st_mode & bit >> 6)
2621 return TRUE; /* ok as "other" */
2623 #endif /* ! MSDOS */
2627 ingroup(testgid,effective)
2631 if (testgid == (effective ? egid : gid))
2633 #ifdef HAS_GETGROUPS
2638 GROUPSTYPE gary[NGROUPS];
2641 anum = getgroups(NGROUPS,gary);
2643 if (gary[anum] == testgid)
2650 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2653 do_ipcget(optype, arglast)
2657 register STR **st = stack->ary_array;
2658 register int sp = arglast[0];
2662 key = (key_t)str_gnum(st[++sp]);
2663 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2664 flags = (int)str_gnum(st[++sp]);
2670 return msgget(key, flags);
2674 return semget(key, n, flags);
2678 return shmget(key, n, flags);
2680 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2682 fatal("%s not implemented", opname[optype]);
2685 return -1; /* should never happen */
2689 do_ipcctl(optype, arglast)
2693 register STR **st = stack->ary_array;
2694 register int sp = arglast[0];
2697 int id, n, cmd, infosize, getinfo, ret;
2699 id = (int)str_gnum(st[++sp]);
2700 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2701 cmd = (int)str_gnum(st[++sp]);
2705 getinfo = (cmd == IPC_STAT);
2711 if (cmd == IPC_STAT || cmd == IPC_SET)
2712 infosize = sizeof(struct msqid_ds);
2717 if (cmd == IPC_STAT || cmd == IPC_SET)
2718 infosize = sizeof(struct shmid_ds);
2723 if (cmd == IPC_STAT || cmd == IPC_SET)
2724 infosize = sizeof(struct semid_ds);
2725 else if (cmd == GETALL || cmd == SETALL)
2727 struct semid_ds semds;
2728 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2730 getinfo = (cmd == GETALL);
2731 infosize = semds.sem_nsems * sizeof(short);
2732 /* "short" is technically wrong but much more portable
2733 than guessing about u_?short(_t)? */
2737 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2739 fatal("%s not implemented", opname[optype]);
2747 STR_GROW(astr, infosize+1);
2753 if (astr->str_cur != infosize)
2762 int i = (int)str_gnum(astr);
2763 a = (char *)i; /* ouch */
2770 ret = msgctl(id, cmd, (struct msqid_ds *)a);
2775 ret = semctl(id, n, cmd, a);
2780 ret = shmctl(id, cmd, (struct shmid_ds *)a);
2784 if (getinfo && ret >= 0) {
2785 astr->str_cur = infosize;
2786 astr->str_ptr[infosize] = '\0';
2796 register STR **st = stack->ary_array;
2797 register int sp = arglast[0];
2800 int id, msize, flags;
2802 id = (int)str_gnum(st[++sp]);
2804 flags = (int)str_gnum(st[++sp]);
2805 mbuf = str_get(mstr);
2806 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2811 return msgsnd(id, (struct msgbuf *)mbuf, msize, flags);
2813 fatal("msgsnd not implemented");
2822 register STR **st = stack->ary_array;
2823 register int sp = arglast[0];
2827 int id, msize, flags, ret;
2829 id = (int)str_gnum(st[++sp]);
2831 msize = (int)str_gnum(st[++sp]);
2832 mtype = (long)str_gnum(st[++sp]);
2833 flags = (int)str_gnum(st[++sp]);
2834 mbuf = str_get(mstr);
2835 if (mstr->str_cur < sizeof(long)+msize+1) {
2836 STR_GROW(mstr, sizeof(long)+msize+1);
2837 mbuf = str_get(mstr);
2840 ret = msgrcv(id, (struct msgbuf *)mbuf, msize, mtype, flags);
2842 mstr->str_cur = sizeof(long)+ret;
2843 mstr->str_ptr[sizeof(long)+ret] = '\0';
2847 fatal("msgrcv not implemented");
2856 register STR **st = stack->ary_array;
2857 register int sp = arglast[0];
2862 id = (int)str_gnum(st[++sp]);
2864 opbuf = str_get(opstr);
2865 opsize = opstr->str_cur;
2866 if (opsize < sizeof(struct sembuf)
2867 || (opsize % sizeof(struct sembuf)) != 0) {
2872 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
2874 fatal("semop not implemented");
2879 do_shmio(optype, arglast)
2884 register STR **st = stack->ary_array;
2885 register int sp = arglast[0];
2888 int id, mpos, msize;
2889 struct shmid_ds shmds;
2891 extern char *shmat();
2894 id = (int)str_gnum(st[++sp]);
2896 mpos = (int)str_gnum(st[++sp]);
2897 msize = (int)str_gnum(st[++sp]);
2899 if (shmctl(id, IPC_STAT, &shmds) == -1)
2901 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2902 errno = EFAULT; /* can't do as caller requested */
2905 shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2906 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2908 mbuf = str_get(mstr);
2909 if (optype == O_SHMREAD) {
2910 if (mstr->str_cur < msize) {
2911 STR_GROW(mstr, msize+1);
2912 mbuf = str_get(mstr);
2914 Copy(shm + mpos, mbuf, msize, char);
2915 mstr->str_cur = msize;
2916 mstr->str_ptr[msize] = '\0';
2921 if ((n = mstr->str_cur) > msize)
2923 Copy(mbuf, shm + mpos, n, char);
2925 memzero(shm + mpos + n, msize - n);
2929 fatal("shm I/O not implemented");
2933 #endif /* SYSV IPC */