1 /* $RCSfile: doio.c,v $$Revision: 4.0.1.3 $$Date: 91/06/10 01:21:19 $
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.3 91/06/10 01:21:19 lwall
10 * patch10: read didn't work from character special files open for writing
11 * patch10: close-on-exec wrongly set on system file descriptors
13 * Revision 4.0.1.2 91/06/07 10:53:39 lwall
14 * patch4: new copyright notice
15 * patch4: system fd's are now treated specially
16 * patch4: added $^F variable to specify maximum system fd, default 2
17 * patch4: character special files now opened with bidirectional stdio buffers
18 * patch4: taintchecks could improperly modify parent in vfork()
19 * patch4: many, many itty-bitty portability fixes
21 * Revision 4.0.1.1 91/04/11 17:41:06 lwall
22 * patch1: hopefully straightened out some of the Xenix mess
24 * Revision 4.0 91/03/20 01:07:06 lwall
33 #include <sys/socket.h>
40 #include <sys/select.h>
45 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
75 int laststype = O_STAT;
78 do_open(stab,name,len)
84 register STIO *stio = stab_io(stab);
85 char *myname = savestr(name);
89 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
90 FILE *saveifp = Nullfp;
91 FILE *saveofp = Nullfp;
95 forkprocess = 1; /* assume true if no fork */
96 while (len && isspace(name[len-1]))
99 stio = stab_io(stab) = stio_new();
100 else if (stio->ifp) {
101 fd = fileno(stio->ifp);
102 if (stio->type == '-')
104 else if (fd <= maxsysfd) {
107 savetype = stio->type;
110 else if (stio->type == '|')
111 result = mypclose(stio->ifp);
112 else if (stio->ifp != stio->ofp) {
114 result = fclose(stio->ofp);
115 fclose(stio->ifp); /* clear stdio, fd already closed */
118 result = fclose(stio->ifp);
121 result = fclose(stio->ifp);
122 if (result == EOF && fd > maxsysfd)
123 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
125 stio->ofp = stio->ifp = Nullfp;
127 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
138 for (name++; isspace(*name); name++) ;
141 taintproper("Insecure dependency in piped open");
143 fp = mypopen(name,"w");
146 else if (*name == '>') {
148 taintproper("Insecure dependency in open");
152 mode[0] = stio->type = 'a';
161 while (isspace(*name))
166 stab = stabent(name,FALSE);
167 if (!stab || !stab_io(stab)) {
173 if (stab_io(stab) && stab_io(stab)->ifp) {
174 fd = fileno(stab_io(stab)->ifp);
175 if (stab_io(stab)->type == 's')
181 if (!(fp = fdopen(fd = dup(fd),mode))) {
186 while (isspace(*name))
188 if (strEQ(name,"-")) {
193 fp = fopen(name,mode);
201 while (isspace(*name))
205 if (strEQ(name,"-")) {
210 fp = fopen(name,mode);
212 else if (name[len-1] == '|') {
215 taintproper("Insecure dependency in piped open");
218 while (len && isspace(name[len-1]))
220 for (; isspace(*name); name++) ;
221 fp = mypopen(name,"r");
226 for (; isspace(*name); name++) ;
227 if (strEQ(name,"-")) {
232 fp = fopen(name,"r");
239 stio->type != '|' && stio->type != '-') {
240 if (fstat(fileno(fp),&statbuf) < 0) {
244 if (S_ISSOCK(statbuf.st_mode))
245 stio->type = 's'; /* in case a socket was passed in to us */
247 else if (!(statbuf.st_mode & S_IFMT))
248 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
251 if (saveifp) { /* must use old fp? */
252 fd = fileno(saveifp);
254 fflush(saveofp); /* emulate fclose() */
255 if (saveofp != saveifp) { /* was a socket? */
260 if (fd != fileno(fp)) {
261 dup2(fileno(fp), fd);
266 #if defined(HAS_FCNTL) && defined(F_SETFD)
268 fcntl(fd,F_SETFD,fd > maxsysfd);
272 if (stio->type == 's'
273 || (stio->type == '>' && S_ISCHR(statbuf.st_mode)) ) {
274 if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
288 stio->type = savetype;
301 static int filemode = 0;
303 static char *oldname;
306 argvoutstab = stabent("ARGVOUT",TRUE);
307 if (filemode & (S_ISUID|S_ISGID)) {
308 fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */
310 (void)fchmod(lastfd,filemode);
312 (void)chmod(oldname,filemode);
316 while (alen(stab_xarray(stab)) >= 0) {
317 str = ashift(stab_xarray(stab));
318 str_sset(stab_val(stab),str);
319 STABSET(stab_val(stab));
320 oldname = str_get(stab_val(stab));
321 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
324 taintproper("Insecure dependency in inplace open");
326 if (strEQ(oldname,"-")) {
328 defoutstab = stabent("STDOUT",TRUE);
329 return stab_io(stab)->ifp;
331 filedev = statbuf.st_dev;
332 fileino = statbuf.st_ino;
333 filemode = statbuf.st_mode;
334 fileuid = statbuf.st_uid;
335 filegid = statbuf.st_gid;
336 if (!S_ISREG(filemode)) {
337 warn("Can't do inplace edit: %s is not a regular file",
339 do_close(stab,FALSE);
345 add_suffix(str,inplace);
347 str_cat(str,inplace);
349 #ifndef FLEXFILENAMES
350 if (stat(str->str_ptr,&statbuf) >= 0
351 && statbuf.st_dev == filedev
352 && statbuf.st_ino == fileino ) {
353 warn("Can't do inplace edit: %s > 14 characters",
355 do_close(stab,FALSE);
362 if (rename(oldname,str->str_ptr) < 0) {
363 warn("Can't rename %s to %s: %s, skipping file",
364 oldname, str->str_ptr, strerror(errno) );
365 do_close(stab,FALSE);
370 do_close(stab,FALSE);
371 (void)unlink(str->str_ptr);
372 (void)rename(oldname,str->str_ptr);
373 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
376 (void)UNLINK(str->str_ptr);
377 if (link(oldname,str->str_ptr) < 0) {
378 warn("Can't rename %s to %s: %s, skipping file",
379 oldname, str->str_ptr, strerror(errno) );
380 do_close(stab,FALSE);
384 (void)UNLINK(oldname);
389 if (UNLINK(oldname) < 0) {
390 warn("Can't rename %s to %s: %s, skipping file",
391 oldname, str->str_ptr, strerror(errno) );
392 do_close(stab,FALSE);
397 fatal("Can't do inplace edit without backup");
402 str_cat(str,oldname);
403 errno = 0; /* in case sprintf set errno */
404 if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
405 warn("Can't do inplace edit on %s: %s",
406 oldname, strerror(errno) );
407 do_close(stab,FALSE);
411 defoutstab = argvoutstab;
412 lastfd = fileno(stab_io(argvoutstab)->ifp);
413 (void)fstat(lastfd,&statbuf);
415 (void)fchmod(lastfd,filemode);
417 (void)chmod(oldname,filemode);
419 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
421 (void)fchown(lastfd,fileuid,filegid);
424 (void)chown(oldname,fileuid,filegid);
430 return stab_io(stab)->ifp;
433 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
437 (void)do_close(argvoutstab,FALSE);
438 defoutstab = stabent("STDOUT",TRUE);
445 do_pipe(str, rstab, wstab)
450 register STIO *rstio;
451 register STIO *wstio;
459 rstio = stab_io(rstab);
460 wstio = stab_io(wstab);
463 rstio = stab_io(rstab) = stio_new();
465 do_close(rstab,FALSE);
467 wstio = stab_io(wstab) = stio_new();
469 do_close(wstab,FALSE);
473 rstio->ifp = fdopen(fd[0], "r");
474 wstio->ofp = fdopen(fd[1], "w");
475 wstio->ifp = wstio->ofp;
478 if (!rstio->ifp || !wstio->ofp) {
479 if (rstio->ifp) fclose(rstio->ifp);
481 if (wstio->ofp) fclose(wstio->ofp);
486 str_sset(str,&str_yes);
490 str_sset(str,&str_undef);
496 do_close(stab,explicit)
508 stio = stab_io(stab);
509 if (!stio) { /* never opened */
510 if (dowarn && explicit)
511 warn("Close on unopened file <%s>",stab_name(stab));
515 if (stio->type == '|') {
516 status = mypclose(stio->ifp);
517 retval = (status == 0);
518 statusvalue = (unsigned short)status & 0xffff;
520 else if (stio->type == '-')
523 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
524 retval = (fclose(stio->ofp) != EOF);
525 fclose(stio->ifp); /* clear stdio, fd already closed */
528 retval = (fclose(stio->ifp) != EOF);
530 stio->ofp = stio->ifp = Nullfp;
545 if (!stab) { /* eof() */
547 stio = stab_io(argvstab);
552 stio = stab_io(stab);
559 #ifdef STDSTDIO /* (the code works without this) */
560 if (stio->ifp->_cnt > 0) /* cheat a little, since */
561 return FALSE; /* this is the most usual case */
564 ch = getc(stio->ifp);
566 (void)ungetc(ch, stio->ifp);
570 if (stio->ifp->_cnt < -1)
571 stio->ifp->_cnt = -1;
573 if (!stab) { /* not necessarily a real EOF yet? */
574 if (!nextargv(argvstab)) /* get another fp handy */
578 return TRUE; /* normal fp, definitely end of file */
592 stio = stab_io(stab);
593 if (!stio || !stio->ifp)
597 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
599 return ftell(stio->ifp);
603 warn("tell() on unopened file");
608 do_seek(stab, pos, whence)
618 stio = stab_io(stab);
619 if (!stio || !stio->ifp)
623 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
625 return fseek(stio->ifp, pos, whence) >= 0;
629 warn("seek() on unopened file");
634 do_ctl(optype,stab,func,argstr)
644 if (!stab || !argstr)
646 stio = stab_io(stab);
650 if (argstr->str_pok || !argstr->str_nok) {
651 if (!argstr->str_pok)
656 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
660 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
662 retval = 256; /* otherwise guess at what's safe */
664 if (argstr->str_cur < retval) {
665 Str_Grow(argstr,retval+1);
666 argstr->str_cur = retval;
670 s[argstr->str_cur] = 17; /* a little sanity check here */
673 retval = (int)str_gnum(argstr);
675 s = (char*)(long)retval; /* ouch */
677 s = (char*)retval; /* ouch */
682 if (optype == O_IOCTL)
683 retval = ioctl(fileno(stio->ifp), func, s);
686 fatal("fcntl is not implemented");
689 retval = fcntl(fileno(stio->ifp), func, s);
691 fatal("fcntl is not implemented");
698 if (argstr->str_pok) {
699 if (s[argstr->str_cur] != 17)
700 fatal("Return value overflowed string");
701 s[argstr->str_cur] = 0; /* put our null back */
707 do_stat(str,arg,gimme,arglast)
713 register ARRAY *ary = stack;
714 register int sp = arglast[0] + 1;
717 if ((arg[1].arg_type & A_MASK) == A_WORD) {
718 tmpstab = arg[1].arg_ptr.arg_stab;
719 if (tmpstab != defstab) {
722 str_set(statname,"");
723 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
724 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
729 else if (laststatval < 0)
733 str_set(statname,str_get(ary->ary_array[sp]));
736 laststype = arg->arg_type;
737 if (arg->arg_type == O_LSTAT)
738 laststatval = lstat(str_get(statname),&statcache);
741 laststatval = stat(str_get(statname),&statcache);
746 if (gimme != G_ARRAY) {
748 str_sset(str,&str_yes);
750 str_sset(str,&str_undef);
752 ary->ary_array[sp] = str;
758 (void)astore(ary,++sp,
759 str_2mortal(str_nmake((double)statcache.st_dev)));
760 (void)astore(ary,++sp,
761 str_2mortal(str_nmake((double)statcache.st_ino)));
762 (void)astore(ary,++sp,
763 str_2mortal(str_nmake((double)statcache.st_mode)));
764 (void)astore(ary,++sp,
765 str_2mortal(str_nmake((double)statcache.st_nlink)));
766 (void)astore(ary,++sp,
767 str_2mortal(str_nmake((double)statcache.st_uid)));
768 (void)astore(ary,++sp,
769 str_2mortal(str_nmake((double)statcache.st_gid)));
770 (void)astore(ary,++sp,
771 str_2mortal(str_nmake((double)statcache.st_rdev)));
772 (void)astore(ary,++sp,
773 str_2mortal(str_nmake((double)statcache.st_size)));
774 (void)astore(ary,++sp,
775 str_2mortal(str_nmake((double)statcache.st_atime)));
776 (void)astore(ary,++sp,
777 str_2mortal(str_nmake((double)statcache.st_mtime)));
778 (void)astore(ary,++sp,
779 str_2mortal(str_nmake((double)statcache.st_ctime)));
781 (void)astore(ary,++sp,
782 str_2mortal(str_nmake((double)statcache.st_blksize)));
783 (void)astore(ary,++sp,
784 str_2mortal(str_nmake((double)statcache.st_blocks)));
786 (void)astore(ary,++sp,
787 str_2mortal(str_make("",0)));
788 (void)astore(ary,++sp,
789 str_2mortal(str_make("",0)));
792 (void)astore(ary,++sp,str_nmake(0.0));
798 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
799 /* code courtesy of William Kucharski */
802 int chsize(fd, length)
803 int fd; /* file descriptor */
804 off_t length; /* length to set file to */
810 if (fstat(fd, &filebuf) < 0)
813 if (filebuf.st_size < length) {
815 /* extend file length */
817 if ((lseek(fd, (length - 1), 0)) < 0)
820 /* write a "0" byte */
822 if ((write(fd, "", 1)) != 1)
826 /* truncate length */
831 fl.l_type = F_WRLCK; /* write lock on file space */
834 * This relies on the UNDOCUMENTED F_FREESP argument to
835 * fcntl(2), which truncates the file so that it ends at the
836 * position indicated by fl.l_start.
838 * Will minor miracles never cease?
841 if (fcntl(fd, F_FREESP, &fl) < 0)
848 #endif /* F_FREESP */
851 do_truncate(str,arg,gimme,arglast)
857 register ARRAY *ary = stack;
858 register int sp = arglast[0] + 1;
859 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
863 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
865 if ((arg[1].arg_type & A_MASK) == A_WORD) {
866 tmpstab = arg[1].arg_ptr.arg_stab;
867 if (!stab_io(tmpstab) ||
868 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
871 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
874 if ((arg[1].arg_type & A_MASK) == A_WORD) {
875 tmpstab = arg[1].arg_ptr.arg_stab;
876 if (!stab_io(tmpstab) ||
877 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
883 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
886 if (chsize(tmpfd, len) < 0)
894 str_sset(str,&str_yes);
896 str_sset(str,&str_undef);
898 ary->ary_array[sp] = str;
901 fatal("truncate not implemented");
906 looks_like_number(str)
915 send = s + str->str_cur;
920 if (*s == '+' || *s == '-')
928 else if (s == str->str_ptr)
934 if (*s == 'e' || *s == 'E') {
936 if (*s == '+' || *s == '-')
957 warn("print to unopened file");
963 ((str->str_nok && str->str_u.str_nval != 0.0)
964 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
965 fprintf(fp, ofmt, str->str_u.str_nval);
970 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
971 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
972 STR *tmpstr = str_mortal(&str_undef);
973 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
978 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
985 do_aprint(arg,fp,arglast)
990 register STR **st = stack->ary_array;
991 register int sp = arglast[1];
993 register int items = arglast[2] - sp;
997 warn("print to unopened file");
1001 if (arg->arg_type == O_PRTF) {
1002 do_sprintf(arg->arg_ptr.arg_str,items,st);
1003 retval = do_print(arg->arg_ptr.arg_str,fp);
1006 retval = (items <= 0);
1007 for (; items > 0; items--,st++) {
1008 if (retval && ofslen) {
1009 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
1014 if (!(retval = do_print(*st, fp)))
1017 if (retval && orslen)
1018 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
1032 if (arg[1].arg_type & A_DONT) {
1033 stio = stab_io(arg[1].arg_ptr.arg_stab);
1034 if (stio && stio->ifp) {
1035 statstab = arg[1].arg_ptr.arg_stab;
1036 str_set(statname,"");
1037 return (laststatval = fstat(fileno(stio->ifp), &statcache));
1040 if (arg[1].arg_ptr.arg_stab == defstab)
1043 warn("Stat on unopened file <%s>",
1044 stab_name(arg[1].arg_ptr.arg_stab));
1045 statstab = Nullstab;
1046 str_set(statname,"");
1047 return (laststatval = -1);
1051 statstab = Nullstab;
1052 str_set(statname,str_get(str));
1053 return (laststatval = stat(str_get(str),&statcache));
1062 if (arg[1].arg_type & A_DONT) {
1063 if (arg[1].arg_ptr.arg_stab == defstab) {
1064 if (laststype != O_LSTAT)
1065 fatal("The stat preceding -l _ wasn't an lstat");
1068 fatal("You can't use -l on a filehandle");
1071 laststype = O_LSTAT;
1072 statstab = Nullstab;
1073 str_set(statname,str_get(str));
1075 return (laststatval = lstat(str_get(str),&statcache));
1077 return (laststatval = stat(str_get(str),&statcache));
1090 register STDCHAR *s;
1091 register STIO *stio;
1093 if (arg[1].arg_type & A_DONT) {
1094 if (arg[1].arg_ptr.arg_stab == defstab) {
1096 stio = stab_io(statstab);
1099 goto really_filename;
1103 statstab = arg[1].arg_ptr.arg_stab;
1104 str_set(statname,"");
1105 stio = stab_io(statstab);
1107 if (stio && stio->ifp) {
1109 fstat(fileno(stio->ifp),&statcache);
1110 if (stio->ifp->_cnt <= 0) {
1111 i = getc(stio->ifp);
1113 (void)ungetc(i,stio->ifp);
1115 if (stio->ifp->_cnt <= 0) /* null file is anything */
1117 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1118 s = stio->ifp->_base;
1120 fatal("-T and -B not implemented on filehandles\n");
1125 warn("Test on unopened file <%s>",
1126 stab_name(arg[1].arg_ptr.arg_stab));
1131 statstab = Nullstab;
1132 str_set(statname,str_get(str));
1134 i = open(str_get(str),0);
1137 fstat(i,&statcache);
1138 len = read(i,tbuf,512);
1140 if (len <= 0) /* null file is anything */
1145 /* now scan s to look for textiness */
1147 for (i = 0; i < len; i++,s++) {
1148 if (!*s) { /* null never allowed in text */
1155 *s != '\n' && *s != '\r' && *s != '\b' &&
1156 *s != '\t' && *s != '\f' && *s != 27)
1160 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1167 do_aexec(really,arglast)
1171 register STR **st = stack->ary_array;
1172 register int sp = arglast[1];
1173 register int items = arglast[2] - sp;
1179 New(401,argv, items+1, char*);
1181 for (st += ++sp; items > 0; items--,st++) {
1183 *a++ = str_get(*st);
1189 if (*argv[0] != '/') /* will execvp use PATH? */
1190 taintenv(); /* testing IFS here is overkill, probably */
1192 if (really && *(tmps = str_get(really)))
1195 execvp(argv[0],argv);
1201 static char **Argv = Null(char **);
1202 static char *Cmd = Nullch;
1209 Argv = Null(char **);
1225 /* save an extra exec if possible */
1228 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1244 if (s[-1] == '\'') {
1246 execl(cshname,"csh", flags,ncmd,(char*)0);
1254 /* see if there are shell metacharacters in it */
1256 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1259 for (s = cmd; *s; s++) {
1260 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1261 if (*s == '\n' && !s[1]) {
1266 execl("/bin/sh","sh","-c",cmd,(char*)0);
1270 New(402,Argv, (s - cmd) / 2 + 2, char*);
1271 Cmd = nsavestr(cmd, s-cmd);
1273 for (s = Cmd; *s;) {
1274 while (*s && isspace(*s)) s++;
1277 while (*s && !isspace(*s)) s++;
1283 execvp(Argv[0],Argv);
1284 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1295 do_socket(stab, arglast)
1299 register STR **st = stack->ary_array;
1300 register int sp = arglast[1];
1301 register STIO *stio;
1302 int domain, type, protocol, fd;
1307 stio = stab_io(stab);
1309 stio = stab_io(stab) = stio_new();
1311 do_close(stab,FALSE);
1313 domain = (int)str_gnum(st[++sp]);
1314 type = (int)str_gnum(st[++sp]);
1315 protocol = (int)str_gnum(st[++sp]);
1317 taintproper("Insecure dependency in socket");
1319 fd = socket(domain,type,protocol);
1322 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1323 stio->ofp = fdopen(fd, "w");
1325 if (!stio->ifp || !stio->ofp) {
1326 if (stio->ifp) fclose(stio->ifp);
1327 if (stio->ofp) fclose(stio->ofp);
1328 if (!stio->ifp && !stio->ofp) close(fd);
1336 do_bind(stab, arglast)
1340 register STR **st = stack->ary_array;
1341 register int sp = arglast[1];
1342 register STIO *stio;
1348 stio = stab_io(stab);
1349 if (!stio || !stio->ifp)
1352 addr = str_get(st[++sp]);
1354 taintproper("Insecure dependency in bind");
1356 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1360 warn("bind() on closed fd");
1366 do_connect(stab, arglast)
1370 register STR **st = stack->ary_array;
1371 register int sp = arglast[1];
1372 register STIO *stio;
1378 stio = stab_io(stab);
1379 if (!stio || !stio->ifp)
1382 addr = str_get(st[++sp]);
1384 taintproper("Insecure dependency in connect");
1386 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1390 warn("connect() on closed fd");
1396 do_listen(stab, arglast)
1400 register STR **st = stack->ary_array;
1401 register int sp = arglast[1];
1402 register STIO *stio;
1408 stio = stab_io(stab);
1409 if (!stio || !stio->ifp)
1412 backlog = (int)str_gnum(st[++sp]);
1413 return listen(fileno(stio->ifp), backlog) >= 0;
1417 warn("listen() on closed fd");
1422 do_accept(str, nstab, gstab)
1427 register STIO *nstio;
1428 register STIO *gstio;
1429 int len = sizeof buf;
1437 gstio = stab_io(gstab);
1438 nstio = stab_io(nstab);
1440 if (!gstio || !gstio->ifp)
1443 nstio = stab_io(nstab) = stio_new();
1444 else if (nstio->ifp)
1445 do_close(nstab,FALSE);
1447 fd = accept(fileno(gstio->ifp),(struct sockaddr *)buf,&len);
1450 nstio->ifp = fdopen(fd, "r");
1451 nstio->ofp = fdopen(fd, "w");
1453 if (!nstio->ifp || !nstio->ofp) {
1454 if (nstio->ifp) fclose(nstio->ifp);
1455 if (nstio->ofp) fclose(nstio->ofp);
1456 if (!nstio->ifp && !nstio->ofp) close(fd);
1460 str_nset(str, buf, len);
1465 warn("accept() on closed fd");
1467 str_sset(str,&str_undef);
1472 do_shutdown(stab, arglast)
1476 register STR **st = stack->ary_array;
1477 register int sp = arglast[1];
1478 register STIO *stio;
1484 stio = stab_io(stab);
1485 if (!stio || !stio->ifp)
1488 how = (int)str_gnum(st[++sp]);
1489 return shutdown(fileno(stio->ifp), how) >= 0;
1493 warn("shutdown() on closed fd");
1499 do_sopt(optype, stab, arglast)
1504 register STR **st = stack->ary_array;
1505 register int sp = arglast[1];
1506 register STIO *stio;
1514 stio = stab_io(stab);
1515 if (!stio || !stio->ifp)
1518 fd = fileno(stio->ifp);
1519 lvl = (int)str_gnum(st[sp+1]);
1520 optname = (int)str_gnum(st[sp+2]);
1523 st[sp] = str_2mortal(str_new(257));
1524 st[sp]->str_cur = 256;
1525 st[sp]->str_pok = 1;
1526 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1531 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1541 warn("[gs]etsockopt() on closed fd");
1542 st[sp] = &str_undef;
1548 do_getsockname(optype, stab, arglast)
1553 register STR **st = stack->ary_array;
1554 register int sp = arglast[1];
1555 register STIO *stio;
1561 stio = stab_io(stab);
1562 if (!stio || !stio->ifp)
1565 st[sp] = str_2mortal(str_new(257));
1566 st[sp]->str_cur = 256;
1567 st[sp]->str_pok = 1;
1568 fd = fileno(stio->ifp);
1571 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1575 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1584 warn("get{sock,peer}name() on closed fd");
1586 st[sp] = &str_undef;
1592 do_ghent(which,gimme,arglast)
1597 register ARRAY *ary = stack;
1598 register int sp = arglast[0];
1599 register char **elem;
1601 struct hostent *gethostbyname();
1602 struct hostent *gethostbyaddr();
1603 #ifdef HAS_GETHOSTENT
1604 struct hostent *gethostent();
1606 struct hostent *hent;
1609 if (gimme != G_ARRAY) {
1610 astore(ary, ++sp, str_mortal(&str_undef));
1614 if (which == O_GHBYNAME) {
1615 char *name = str_get(ary->ary_array[sp+1]);
1617 hent = gethostbyname(name);
1619 else if (which == O_GHBYADDR) {
1620 STR *addrstr = ary->ary_array[sp+1];
1621 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1622 char *addr = str_get(addrstr);
1624 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1627 #ifdef HAS_GETHOSTENT
1628 hent = gethostent();
1630 fatal("gethostent not implemented");
1634 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1635 str_set(str, hent->h_name);
1636 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1637 for (elem = hent->h_aliases; *elem; elem++) {
1638 str_cat(str, *elem);
1640 str_ncat(str," ",1);
1642 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1643 str_numset(str, (double)hent->h_addrtype);
1644 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1645 len = hent->h_length;
1646 str_numset(str, (double)len);
1648 for (elem = hent->h_addr_list; *elem; elem++) {
1649 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1650 str_nset(str, *elem, len);
1653 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1654 str_nset(str, hent->h_addr, len);
1659 (void)astore(ary, ++sp, str_mortal(&str_no));
1667 do_gnent(which,gimme,arglast)
1672 register ARRAY *ary = stack;
1673 register int sp = arglast[0];
1674 register char **elem;
1676 struct netent *getnetbyname();
1677 struct netent *getnetbyaddr();
1678 struct netent *getnetent();
1679 struct netent *nent;
1681 if (gimme != G_ARRAY) {
1682 astore(ary, ++sp, str_mortal(&str_undef));
1686 if (which == O_GNBYNAME) {
1687 char *name = str_get(ary->ary_array[sp+1]);
1689 nent = getnetbyname(name);
1691 else if (which == O_GNBYADDR) {
1692 unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
1693 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1695 nent = getnetbyaddr((long)addr,addrtype);
1702 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1703 str_set(str, nent->n_name);
1704 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1705 for (elem = nent->n_aliases; *elem; elem++) {
1706 str_cat(str, *elem);
1708 str_ncat(str," ",1);
1710 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1711 str_numset(str, (double)nent->n_addrtype);
1712 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1713 str_numset(str, (double)nent->n_net);
1717 (void)astore(ary, ++sp, str_mortal(&str_no));
1725 do_gpent(which,gimme,arglast)
1730 register ARRAY *ary = stack;
1731 register int sp = arglast[0];
1732 register char **elem;
1734 struct protoent *getprotobyname();
1735 struct protoent *getprotobynumber();
1736 struct protoent *getprotoent();
1737 struct protoent *pent;
1739 if (gimme != G_ARRAY) {
1740 astore(ary, ++sp, str_mortal(&str_undef));
1744 if (which == O_GPBYNAME) {
1745 char *name = str_get(ary->ary_array[sp+1]);
1747 pent = getprotobyname(name);
1749 else if (which == O_GPBYNUMBER) {
1750 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1752 pent = getprotobynumber(proto);
1755 pent = getprotoent();
1759 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1760 str_set(str, pent->p_name);
1761 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1762 for (elem = pent->p_aliases; *elem; elem++) {
1763 str_cat(str, *elem);
1765 str_ncat(str," ",1);
1767 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1768 str_numset(str, (double)pent->p_proto);
1772 (void)astore(ary, ++sp, str_mortal(&str_no));
1780 do_gsent(which,gimme,arglast)
1785 register ARRAY *ary = stack;
1786 register int sp = arglast[0];
1787 register char **elem;
1789 struct servent *getservbyname();
1790 struct servent *getservbynumber();
1791 struct servent *getservent();
1792 struct servent *sent;
1794 if (gimme != G_ARRAY) {
1795 astore(ary, ++sp, str_mortal(&str_undef));
1799 if (which == O_GSBYNAME) {
1800 char *name = str_get(ary->ary_array[sp+1]);
1801 char *proto = str_get(ary->ary_array[sp+2]);
1803 if (proto && !*proto)
1806 sent = getservbyname(name,proto);
1808 else if (which == O_GSBYPORT) {
1809 int port = (int)str_gnum(ary->ary_array[sp+1]);
1810 char *proto = str_get(ary->ary_array[sp+2]);
1812 sent = getservbyport(port,proto);
1815 sent = getservent();
1818 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1819 str_set(str, sent->s_name);
1820 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1821 for (elem = sent->s_aliases; *elem; elem++) {
1822 str_cat(str, *elem);
1824 str_ncat(str," ",1);
1826 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1828 str_numset(str, (double)ntohs(sent->s_port));
1830 str_numset(str, (double)(sent->s_port));
1832 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1833 str_set(str, sent->s_proto);
1837 (void)astore(ary, ++sp, str_mortal(&str_no));
1844 #endif /* HAS_SOCKET */
1848 do_select(gimme,arglast)
1852 register STR **st = stack->ary_array;
1853 register int sp = arglast[0];
1861 struct timeval timebuf;
1862 struct timeval *tbuf = &timebuf;
1864 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1870 #if BYTEORDER & 0xf0000
1871 #define ORDERBYTE (0x88888888 - BYTEORDER)
1873 #define ORDERBYTE (0x4444 - BYTEORDER)
1878 for (i = 1; i <= 3; i++) {
1879 j = st[sp+i]->str_cur;
1884 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1885 growsize = maxlen; /* little endians can use vecs directly */
1893 masksize = NFDBITS / NBBY;
1895 masksize = sizeof(long); /* documented int, everyone seems to use long */
1897 growsize = maxlen + (masksize - (maxlen % masksize));
1898 Zero(&fd_sets[0], 4, char*);
1901 for (i = 1; i <= 3; i++) {
1906 Str_Grow(str,growsize);
1907 s = str_get(str) + j;
1908 while (++j <= growsize) {
1912 else if (str->str_ptr) {
1913 Safefree(str->str_ptr);
1914 str->str_ptr = Nullch;
1917 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1920 New(403, fd_sets[i], growsize, char);
1921 for (offset = 0; offset < growsize; offset += masksize) {
1922 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1923 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1929 if (str->str_nok || str->str_pok) {
1930 value = str_gnum(str);
1933 timebuf.tv_sec = (long)value;
1934 value -= (double)timebuf.tv_sec;
1935 timebuf.tv_usec = (long)(value * 1000000.0);
1938 tbuf = Null(struct timeval*);
1940 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1954 for (i = 1; i <= 3; i++) {
1958 for (offset = 0; offset < growsize; offset += masksize) {
1959 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1960 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1966 st[++sp] = str_mortal(&str_no);
1967 str_numset(st[sp], (double)nfound);
1968 if (gimme == G_ARRAY && tbuf) {
1969 value = (double)(timebuf.tv_sec) +
1970 (double)(timebuf.tv_usec) / 1000000.0;
1971 st[++sp] = str_mortal(&str_no);
1972 str_numset(st[sp], value);
1980 do_spair(stab1, stab2, arglast)
1985 register STR **st = stack->ary_array;
1986 register int sp = arglast[2];
1987 register STIO *stio1;
1988 register STIO *stio2;
1989 int domain, type, protocol, fd[2];
1991 if (!stab1 || !stab2)
1994 stio1 = stab_io(stab1);
1995 stio2 = stab_io(stab2);
1997 stio1 = stab_io(stab1) = stio_new();
1998 else if (stio1->ifp)
1999 do_close(stab1,FALSE);
2001 stio2 = stab_io(stab2) = stio_new();
2002 else if (stio2->ifp)
2003 do_close(stab2,FALSE);
2005 domain = (int)str_gnum(st[++sp]);
2006 type = (int)str_gnum(st[++sp]);
2007 protocol = (int)str_gnum(st[++sp]);
2009 taintproper("Insecure dependency in socketpair");
2011 #ifdef HAS_SOCKETPAIR
2012 if (socketpair(domain,type,protocol,fd) < 0)
2015 fatal("Socketpair unimplemented");
2017 stio1->ifp = fdopen(fd[0], "r");
2018 stio1->ofp = fdopen(fd[0], "w");
2020 stio2->ifp = fdopen(fd[1], "r");
2021 stio2->ofp = fdopen(fd[1], "w");
2023 if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
2024 if (stio1->ifp) fclose(stio1->ifp);
2025 if (stio1->ofp) fclose(stio1->ofp);
2026 if (!stio1->ifp && !stio1->ofp) close(fd[0]);
2027 if (stio2->ifp) fclose(stio2->ifp);
2028 if (stio2->ofp) fclose(stio2->ofp);
2029 if (!stio2->ifp && !stio2->ofp) close(fd[1]);
2036 #endif /* HAS_SOCKET */
2039 do_gpwent(which,gimme,arglast)
2045 register ARRAY *ary = stack;
2046 register int sp = arglast[0];
2048 struct passwd *getpwnam();
2049 struct passwd *getpwuid();
2050 struct passwd *getpwent();
2051 struct passwd *pwent;
2053 if (gimme != G_ARRAY) {
2054 astore(ary, ++sp, str_mortal(&str_undef));
2058 if (which == O_GPWNAM) {
2059 char *name = str_get(ary->ary_array[sp+1]);
2061 pwent = getpwnam(name);
2063 else if (which == O_GPWUID) {
2064 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2066 pwent = getpwuid(uid);
2072 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2073 str_set(str, pwent->pw_name);
2074 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2075 str_set(str, pwent->pw_passwd);
2076 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2077 str_numset(str, (double)pwent->pw_uid);
2078 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2079 str_numset(str, (double)pwent->pw_gid);
2080 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2082 str_numset(str, (double)pwent->pw_change);
2085 str_numset(str, (double)pwent->pw_quota);
2088 str_set(str, pwent->pw_age);
2092 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2094 str_set(str,pwent->pw_class);
2097 str_set(str, pwent->pw_comment);
2100 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2101 str_set(str, pwent->pw_gecos);
2102 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2103 str_set(str, pwent->pw_dir);
2104 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2105 str_set(str, pwent->pw_shell);
2107 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2108 str_numset(str, (double)pwent->pw_expire);
2114 fatal("password routines not implemented");
2119 do_ggrent(which,gimme,arglast)
2125 register ARRAY *ary = stack;
2126 register int sp = arglast[0];
2127 register char **elem;
2129 struct group *getgrnam();
2130 struct group *getgrgid();
2131 struct group *getgrent();
2132 struct group *grent;
2134 if (gimme != G_ARRAY) {
2135 astore(ary, ++sp, str_mortal(&str_undef));
2139 if (which == O_GGRNAM) {
2140 char *name = str_get(ary->ary_array[sp+1]);
2142 grent = getgrnam(name);
2144 else if (which == O_GGRGID) {
2145 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2147 grent = getgrgid(gid);
2153 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2154 str_set(str, grent->gr_name);
2155 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2156 str_set(str, grent->gr_passwd);
2157 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2158 str_numset(str, (double)grent->gr_gid);
2159 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2160 for (elem = grent->gr_mem; *elem; elem++) {
2161 str_cat(str, *elem);
2163 str_ncat(str," ",1);
2169 fatal("group routines not implemented");
2174 do_dirop(optype,stab,gimme,arglast)
2180 #if defined(DIRENT) && defined(HAS_READDIR)
2181 register ARRAY *ary = stack;
2182 register STR **st = ary->ary_array;
2183 register int sp = arglast[1];
2184 register STIO *stio;
2190 struct DIRENT *readdir();
2192 register struct DIRENT *dp;
2196 if (!(stio = stab_io(stab)))
2197 stio = stab_io(stab) = stio_new();
2198 if (!stio->dirp && optype != O_OPEN_DIR)
2204 closedir(stio->dirp);
2205 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2209 if (gimme == G_ARRAY) {
2211 while (dp = readdir(stio->dirp)) {
2213 (void)astore(ary,++sp,
2214 str_2mortal(str_make(dp->d_name,dp->d_namlen)));
2216 (void)astore(ary,++sp,
2217 str_2mortal(str_make(dp->d_name,0)));
2222 if (!(dp = readdir(stio->dirp)))
2224 st[sp] = str_mortal(&str_undef);
2226 str_nset(st[sp], dp->d_name, dp->d_namlen);
2228 str_set(st[sp], dp->d_name);
2238 st[sp] = str_mortal(&str_undef);
2239 str_numset(st[sp], (double)telldir(stio->dirp));
2242 st[sp] = str_mortal(&str_undef);
2243 along = (long)str_gnum(st[sp+1]);
2244 (void)seekdir(stio->dirp,along);
2248 st[sp] = str_mortal(&str_undef);
2249 (void)rewinddir(stio->dirp);
2252 st[sp] = str_mortal(&str_undef);
2253 (void)closedir(stio->dirp);
2260 st[sp] = &str_undef;
2264 fatal("Unimplemented directory operation");
2272 register STR **st = stack->ary_array;
2273 register int sp = arglast[1];
2274 register int items = arglast[2] - sp;
2277 register int tot = 0;
2281 for (st += ++sp; items--; st++)
2282 tainted |= (*st)->str_tainted;
2283 st = stack->ary_array;
2285 items = arglast[2] - sp;
2290 taintproper("Insecure dependency in chmod");
2294 val = (int)str_gnum(st[++sp]);
2296 if (chmod(str_get(st[++sp]),val))
2304 taintproper("Insecure dependency in chown");
2309 val = (int)str_gnum(st[++sp]);
2310 val2 = (int)str_gnum(st[++sp]);
2312 if (chown(str_get(st[++sp]),val,val2))
2321 taintproper("Insecure dependency in kill");
2325 s = str_get(st[++sp]);
2327 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2329 if (!(val = whichsig(s)))
2330 fatal("Unrecognized signal name \"%s\"",s);
2333 val = (int)str_gnum(st[sp]);
2337 int proc = (int)str_gnum(st[++sp]);
2339 if (killpg(proc,val)) /* BSD */
2341 if (kill(-proc,val)) /* SYSV */
2348 if (kill((int)(str_gnum(st[++sp])),val))
2357 taintproper("Insecure dependency in unlink");
2361 s = str_get(st[++sp]);
2362 if (euid || unsafe) {
2366 else { /* don't let root wipe out directories without -U */
2368 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2370 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2382 taintproper("Insecure dependency in utime");
2386 struct utimbuf utbuf;
2394 Zero(&utbuf, sizeof utbuf, char);
2395 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2396 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2401 if (utime(str_get(st[++sp]),&utbuf))
2413 /* Do the permissions allow some operation? Assumes statcache already set. */
2416 cando(bit, effective, statbufp)
2419 register struct stat *statbufp;
2422 /* [Comments and code from Len Reed]
2423 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2424 * to write-protected files. The execute permission bit is set
2425 * by the Miscrosoft C library stat() function for the following:
2430 * All files and directories are readable.
2431 * Directories and special files, e.g. "CON", cannot be
2433 * [Comment by Tom Dinger -- a directory can have the write-protect
2434 * bit set in the file system, but DOS permits changes to
2435 * the directory anyway. In addition, all bets are off
2436 * here for networked software, such as Novell and
2440 return (bit & statbufp->st_mode) ? TRUE : FALSE;
2443 if ((effective ? euid : uid) == 0) { /* root is special */
2444 if (bit == S_IXUSR) {
2445 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
2449 return TRUE; /* root reads and writes anything */
2452 if (statbufp->st_uid == (effective ? euid : uid) ) {
2453 if (statbufp->st_mode & bit)
2454 return TRUE; /* ok as "user" */
2456 else if (ingroup((int)statbufp->st_gid,effective)) {
2457 if (statbufp->st_mode & bit >> 3)
2458 return TRUE; /* ok as "group" */
2460 else if (statbufp->st_mode & bit >> 6)
2461 return TRUE; /* ok as "other" */
2463 #endif /* ! MSDOS */
2467 ingroup(testgid,effective)
2471 if (testgid == (effective ? egid : gid))
2473 #ifdef HAS_GETGROUPS
2478 GROUPSTYPE gary[NGROUPS];
2481 anum = getgroups(NGROUPS,gary);
2483 if (gary[anum] == testgid)
2490 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2493 do_ipcget(optype, arglast)
2497 register STR **st = stack->ary_array;
2498 register int sp = arglast[0];
2502 key = (key_t)str_gnum(st[++sp]);
2503 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2504 flags = (int)str_gnum(st[++sp]);
2510 return msgget(key, flags);
2514 return semget(key, n, flags);
2518 return shmget(key, n, flags);
2520 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2522 fatal("%s not implemented", opname[optype]);
2525 return -1; /* should never happen */
2529 do_ipcctl(optype, arglast)
2533 register STR **st = stack->ary_array;
2534 register int sp = arglast[0];
2537 int id, n, cmd, infosize, getinfo, ret;
2539 id = (int)str_gnum(st[++sp]);
2540 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2541 cmd = (int)str_gnum(st[++sp]);
2545 getinfo = (cmd == IPC_STAT);
2551 if (cmd == IPC_STAT || cmd == IPC_SET)
2552 infosize = sizeof(struct msqid_ds);
2557 if (cmd == IPC_STAT || cmd == IPC_SET)
2558 infosize = sizeof(struct shmid_ds);
2563 if (cmd == IPC_STAT || cmd == IPC_SET)
2564 infosize = sizeof(struct semid_ds);
2565 else if (cmd == GETALL || cmd == SETALL)
2567 struct semid_ds semds;
2568 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2570 getinfo = (cmd == GETALL);
2571 infosize = semds.sem_nsems * sizeof(short);
2572 /* "short" is technically wrong but much more portable
2573 than guessing about u_?short(_t)? */
2577 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2579 fatal("%s not implemented", opname[optype]);
2587 STR_GROW(astr, infosize+1);
2593 if (astr->str_cur != infosize)
2602 int i = (int)str_gnum(astr);
2603 a = (char *)i; /* ouch */
2610 ret = msgctl(id, cmd, a);
2615 ret = semctl(id, n, cmd, a);
2620 ret = shmctl(id, cmd, a);
2624 if (getinfo && ret >= 0) {
2625 astr->str_cur = infosize;
2626 astr->str_ptr[infosize] = '\0';
2636 register STR **st = stack->ary_array;
2637 register int sp = arglast[0];
2640 int id, msize, flags;
2642 id = (int)str_gnum(st[++sp]);
2644 flags = (int)str_gnum(st[++sp]);
2645 mbuf = str_get(mstr);
2646 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2651 return msgsnd(id, mbuf, msize, flags);
2653 fatal("msgsnd not implemented");
2662 register STR **st = stack->ary_array;
2663 register int sp = arglast[0];
2667 int id, msize, flags, ret;
2669 id = (int)str_gnum(st[++sp]);
2671 msize = (int)str_gnum(st[++sp]);
2672 mtype = (long)str_gnum(st[++sp]);
2673 flags = (int)str_gnum(st[++sp]);
2674 mbuf = str_get(mstr);
2675 if (mstr->str_cur < sizeof(long)+msize+1) {
2676 STR_GROW(mstr, sizeof(long)+msize+1);
2677 mbuf = str_get(mstr);
2680 ret = msgrcv(id, mbuf, msize, mtype, flags);
2682 mstr->str_cur = sizeof(long)+ret;
2683 mstr->str_ptr[sizeof(long)+ret] = '\0';
2687 fatal("msgrcv not implemented");
2696 register STR **st = stack->ary_array;
2697 register int sp = arglast[0];
2702 id = (int)str_gnum(st[++sp]);
2704 opbuf = str_get(opstr);
2705 opsize = opstr->str_cur;
2706 if (opsize < sizeof(struct sembuf)
2707 || (opsize % sizeof(struct sembuf)) != 0) {
2712 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
2714 fatal("semop not implemented");
2719 do_shmio(optype, arglast)
2724 register STR **st = stack->ary_array;
2725 register int sp = arglast[0];
2728 int id, mpos, msize;
2729 struct shmid_ds shmds;
2731 extern char *shmat();
2734 id = (int)str_gnum(st[++sp]);
2736 mpos = (int)str_gnum(st[++sp]);
2737 msize = (int)str_gnum(st[++sp]);
2739 if (shmctl(id, IPC_STAT, &shmds) == -1)
2741 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2742 errno = EFAULT; /* can't do as caller requested */
2745 shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2746 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2748 mbuf = str_get(mstr);
2749 if (optype == O_SHMREAD) {
2750 if (mstr->str_cur < msize) {
2751 STR_GROW(mstr, msize+1);
2752 mbuf = str_get(mstr);
2754 bcopy(shm + mpos, mbuf, msize);
2755 mstr->str_cur = msize;
2756 mstr->str_ptr[msize] = '\0';
2761 if ((n = mstr->str_cur) > msize)
2763 bcopy(mbuf, shm + mpos, n);
2765 bzero(shm + mpos + n, msize - n);
2769 fatal("shm I/O not implemented");
2773 #endif /* SYSV IPC */