1 /* $RCSfile: doio.c,v $$Revision: 4.0.1.2 $$Date: 91/06/07 10:53:39 $
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.2 91/06/07 10:53:39 lwall
10 * patch4: new copyright notice
11 * patch4: system fd's are now treated specially
12 * patch4: added $^F variable to specify maximum system fd, default 2
13 * patch4: character special files now opened with bidirectional stdio buffers
14 * patch4: taintchecks could improperly modify parent in vfork()
15 * patch4: many, many itty-bitty portability fixes
17 * Revision 4.0.1.1 91/04/11 17:41:06 lwall
18 * patch1: hopefully straightened out some of the Xenix mess
20 * Revision 4.0 91/03/20 01:07:06 lwall
29 #include <sys/socket.h>
36 #include <sys/select.h>
41 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
71 int laststype = O_STAT;
74 do_open(stab,name,len)
80 register STIO *stio = stab_io(stab);
81 char *myname = savestr(name);
85 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
86 FILE *saveifp = Nullfp;
87 FILE *saveofp = Nullfp;
91 forkprocess = 1; /* assume true if no fork */
92 while (len && isspace(name[len-1]))
95 stio = stab_io(stab) = stio_new();
97 fd = fileno(stio->ifp);
98 if (stio->type == '-')
100 else if (fd <= maxsysfd) {
103 savetype = stio->type;
106 else if (stio->type == '|')
107 result = mypclose(stio->ifp);
108 else if (stio->ifp != stio->ofp) {
110 result = fclose(stio->ofp);
111 fclose(stio->ifp); /* clear stdio, fd already closed */
114 result = fclose(stio->ifp);
117 result = fclose(stio->ifp);
118 if (result == EOF && fd > maxsysfd)
119 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
121 stio->ofp = stio->ifp = Nullfp;
123 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
134 for (name++; isspace(*name); name++) ;
137 taintproper("Insecure dependency in piped open");
139 fp = mypopen(name,"w");
142 else if (*name == '>') {
144 taintproper("Insecure dependency in open");
148 mode[0] = stio->type = 'a';
157 while (isspace(*name))
162 stab = stabent(name,FALSE);
163 if (!stab || !stab_io(stab)) {
169 if (stab_io(stab) && stab_io(stab)->ifp) {
170 fd = fileno(stab_io(stab)->ifp);
171 if (stab_io(stab)->type == 's')
177 if (!(fp = fdopen(fd = dup(fd),mode))) {
182 while (isspace(*name))
184 if (strEQ(name,"-")) {
189 fp = fopen(name,mode);
197 while (isspace(*name))
201 if (strEQ(name,"-")) {
206 fp = fopen(name,mode);
208 else if (name[len-1] == '|') {
211 taintproper("Insecure dependency in piped open");
214 while (len && isspace(name[len-1]))
216 for (; isspace(*name); name++) ;
217 fp = mypopen(name,"r");
222 for (; isspace(*name); name++) ;
223 if (strEQ(name,"-")) {
228 fp = fopen(name,"r");
235 stio->type != '|' && stio->type != '-') {
236 if (fstat(fileno(fp),&statbuf) < 0) {
240 if (S_ISSOCK(statbuf.st_mode) || (S_ISCHR(statbuf.st_mode) && writing))
241 stio->type = 's'; /* in case a socket was passed in to us */
243 else if (!(statbuf.st_mode & S_IFMT))
244 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
247 #if defined(HAS_FCNTL) && defined(F_SETFD)
249 fcntl(fd,F_SETFD,fd > maxsysfd);
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);
268 if (stio->type != 's')
271 if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
282 stio->type = savetype;
295 static int filemode = 0;
297 static char *oldname;
300 argvoutstab = stabent("ARGVOUT",TRUE);
301 if (filemode & (S_ISUID|S_ISGID)) {
302 fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */
304 (void)fchmod(lastfd,filemode);
306 (void)chmod(oldname,filemode);
310 while (alen(stab_xarray(stab)) >= 0) {
311 str = ashift(stab_xarray(stab));
312 str_sset(stab_val(stab),str);
313 STABSET(stab_val(stab));
314 oldname = str_get(stab_val(stab));
315 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
318 taintproper("Insecure dependency in inplace open");
320 if (strEQ(oldname,"-")) {
322 defoutstab = stabent("STDOUT",TRUE);
323 return stab_io(stab)->ifp;
325 filedev = statbuf.st_dev;
326 fileino = statbuf.st_ino;
327 filemode = statbuf.st_mode;
328 fileuid = statbuf.st_uid;
329 filegid = statbuf.st_gid;
330 if (!S_ISREG(filemode)) {
331 warn("Can't do inplace edit: %s is not a regular file",
333 do_close(stab,FALSE);
339 add_suffix(str,inplace);
341 str_cat(str,inplace);
343 #ifndef FLEXFILENAMES
344 if (stat(str->str_ptr,&statbuf) >= 0
345 && statbuf.st_dev == filedev
346 && statbuf.st_ino == fileino ) {
347 warn("Can't do inplace edit: %s > 14 characters",
349 do_close(stab,FALSE);
356 if (rename(oldname,str->str_ptr) < 0) {
357 warn("Can't rename %s to %s: %s, skipping file",
358 oldname, str->str_ptr, strerror(errno) );
359 do_close(stab,FALSE);
364 do_close(stab,FALSE);
365 (void)unlink(str->str_ptr);
366 (void)rename(oldname,str->str_ptr);
367 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
370 (void)UNLINK(str->str_ptr);
371 if (link(oldname,str->str_ptr) < 0) {
372 warn("Can't rename %s to %s: %s, skipping file",
373 oldname, str->str_ptr, strerror(errno) );
374 do_close(stab,FALSE);
378 (void)UNLINK(oldname);
383 if (UNLINK(oldname) < 0) {
384 warn("Can't rename %s to %s: %s, skipping file",
385 oldname, str->str_ptr, strerror(errno) );
386 do_close(stab,FALSE);
391 fatal("Can't do inplace edit without backup");
396 str_cat(str,oldname);
397 errno = 0; /* in case sprintf set errno */
398 if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
399 warn("Can't do inplace edit on %s: %s",
400 oldname, strerror(errno) );
401 do_close(stab,FALSE);
405 defoutstab = argvoutstab;
406 lastfd = fileno(stab_io(argvoutstab)->ifp);
407 (void)fstat(lastfd,&statbuf);
409 (void)fchmod(lastfd,filemode);
411 (void)chmod(oldname,filemode);
413 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
415 (void)fchown(lastfd,fileuid,filegid);
418 (void)chown(oldname,fileuid,filegid);
424 return stab_io(stab)->ifp;
427 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
431 (void)do_close(argvoutstab,FALSE);
432 defoutstab = stabent("STDOUT",TRUE);
439 do_pipe(str, rstab, wstab)
444 register STIO *rstio;
445 register STIO *wstio;
453 rstio = stab_io(rstab);
454 wstio = stab_io(wstab);
457 rstio = stab_io(rstab) = stio_new();
459 do_close(rstab,FALSE);
461 wstio = stab_io(wstab) = stio_new();
463 do_close(wstab,FALSE);
467 rstio->ifp = fdopen(fd[0], "r");
468 wstio->ofp = fdopen(fd[1], "w");
469 wstio->ifp = wstio->ofp;
472 if (!rstio->ifp || !wstio->ofp) {
473 if (rstio->ifp) fclose(rstio->ifp);
475 if (wstio->ofp) fclose(wstio->ofp);
480 str_sset(str,&str_yes);
484 str_sset(str,&str_undef);
490 do_close(stab,explicit)
502 stio = stab_io(stab);
503 if (!stio) { /* never opened */
504 if (dowarn && explicit)
505 warn("Close on unopened file <%s>",stab_name(stab));
509 if (stio->type == '|') {
510 status = mypclose(stio->ifp);
511 retval = (status == 0);
512 statusvalue = (unsigned short)status & 0xffff;
514 else if (stio->type == '-')
517 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
518 retval = (fclose(stio->ofp) != EOF);
519 fclose(stio->ifp); /* clear stdio, fd already closed */
522 retval = (fclose(stio->ifp) != EOF);
524 stio->ofp = stio->ifp = Nullfp;
539 if (!stab) { /* eof() */
541 stio = stab_io(argvstab);
546 stio = stab_io(stab);
553 #ifdef STDSTDIO /* (the code works without this) */
554 if (stio->ifp->_cnt > 0) /* cheat a little, since */
555 return FALSE; /* this is the most usual case */
558 ch = getc(stio->ifp);
560 (void)ungetc(ch, stio->ifp);
564 if (stio->ifp->_cnt < -1)
565 stio->ifp->_cnt = -1;
567 if (!stab) { /* not necessarily a real EOF yet? */
568 if (!nextargv(argvstab)) /* get another fp handy */
572 return TRUE; /* normal fp, definitely end of file */
586 stio = stab_io(stab);
587 if (!stio || !stio->ifp)
591 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
593 return ftell(stio->ifp);
597 warn("tell() on unopened file");
602 do_seek(stab, pos, whence)
612 stio = stab_io(stab);
613 if (!stio || !stio->ifp)
617 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
619 return fseek(stio->ifp, pos, whence) >= 0;
623 warn("seek() on unopened file");
628 do_ctl(optype,stab,func,argstr)
638 if (!stab || !argstr)
640 stio = stab_io(stab);
644 if (argstr->str_pok || !argstr->str_nok) {
645 if (!argstr->str_pok)
650 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
654 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
656 retval = 256; /* otherwise guess at what's safe */
658 if (argstr->str_cur < retval) {
659 Str_Grow(argstr,retval+1);
660 argstr->str_cur = retval;
664 s[argstr->str_cur] = 17; /* a little sanity check here */
667 retval = (int)str_gnum(argstr);
669 s = (char*)(long)retval; /* ouch */
671 s = (char*)retval; /* ouch */
676 if (optype == O_IOCTL)
677 retval = ioctl(fileno(stio->ifp), func, s);
680 fatal("fcntl is not implemented");
683 retval = fcntl(fileno(stio->ifp), func, s);
685 fatal("fcntl is not implemented");
692 if (argstr->str_pok) {
693 if (s[argstr->str_cur] != 17)
694 fatal("Return value overflowed string");
695 s[argstr->str_cur] = 0; /* put our null back */
701 do_stat(str,arg,gimme,arglast)
707 register ARRAY *ary = stack;
708 register int sp = arglast[0] + 1;
711 if ((arg[1].arg_type & A_MASK) == A_WORD) {
712 tmpstab = arg[1].arg_ptr.arg_stab;
713 if (tmpstab != defstab) {
716 str_set(statname,"");
717 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
718 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
723 else if (laststatval < 0)
727 str_set(statname,str_get(ary->ary_array[sp]));
730 laststype = arg->arg_type;
731 if (arg->arg_type == O_LSTAT)
732 laststatval = lstat(str_get(statname),&statcache);
735 laststatval = stat(str_get(statname),&statcache);
740 if (gimme != G_ARRAY) {
742 str_sset(str,&str_yes);
744 str_sset(str,&str_undef);
746 ary->ary_array[sp] = str;
752 (void)astore(ary,++sp,
753 str_2mortal(str_nmake((double)statcache.st_dev)));
754 (void)astore(ary,++sp,
755 str_2mortal(str_nmake((double)statcache.st_ino)));
756 (void)astore(ary,++sp,
757 str_2mortal(str_nmake((double)statcache.st_mode)));
758 (void)astore(ary,++sp,
759 str_2mortal(str_nmake((double)statcache.st_nlink)));
760 (void)astore(ary,++sp,
761 str_2mortal(str_nmake((double)statcache.st_uid)));
762 (void)astore(ary,++sp,
763 str_2mortal(str_nmake((double)statcache.st_gid)));
764 (void)astore(ary,++sp,
765 str_2mortal(str_nmake((double)statcache.st_rdev)));
766 (void)astore(ary,++sp,
767 str_2mortal(str_nmake((double)statcache.st_size)));
768 (void)astore(ary,++sp,
769 str_2mortal(str_nmake((double)statcache.st_atime)));
770 (void)astore(ary,++sp,
771 str_2mortal(str_nmake((double)statcache.st_mtime)));
772 (void)astore(ary,++sp,
773 str_2mortal(str_nmake((double)statcache.st_ctime)));
775 (void)astore(ary,++sp,
776 str_2mortal(str_nmake((double)statcache.st_blksize)));
777 (void)astore(ary,++sp,
778 str_2mortal(str_nmake((double)statcache.st_blocks)));
780 (void)astore(ary,++sp,
781 str_2mortal(str_make("",0)));
782 (void)astore(ary,++sp,
783 str_2mortal(str_make("",0)));
786 (void)astore(ary,++sp,str_nmake(0.0));
792 #if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
793 /* code courtesy of William Kucharski */
796 int chsize(fd, length)
797 int fd; /* file descriptor */
798 off_t length; /* length to set file to */
804 if (fstat(fd, &filebuf) < 0)
807 if (filebuf.st_size < length) {
809 /* extend file length */
811 if ((lseek(fd, (length - 1), 0)) < 0)
814 /* write a "0" byte */
816 if ((write(fd, "", 1)) != 1)
820 /* truncate length */
825 fl.l_type = F_WRLCK; /* write lock on file space */
828 * This relies on the UNDOCUMENTED F_FREESP argument to
829 * fcntl(2), which truncates the file so that it ends at the
830 * position indicated by fl.l_start.
832 * Will minor miracles never cease?
835 if (fcntl(fd, F_FREESP, &fl) < 0)
842 #endif /* F_FREESP */
845 do_truncate(str,arg,gimme,arglast)
851 register ARRAY *ary = stack;
852 register int sp = arglast[0] + 1;
853 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
857 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
859 if ((arg[1].arg_type & A_MASK) == A_WORD) {
860 tmpstab = arg[1].arg_ptr.arg_stab;
861 if (!stab_io(tmpstab) ||
862 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
865 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
868 if ((arg[1].arg_type & A_MASK) == A_WORD) {
869 tmpstab = arg[1].arg_ptr.arg_stab;
870 if (!stab_io(tmpstab) ||
871 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
877 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
880 if (chsize(tmpfd, len) < 0)
888 str_sset(str,&str_yes);
890 str_sset(str,&str_undef);
892 ary->ary_array[sp] = str;
895 fatal("truncate not implemented");
900 looks_like_number(str)
909 send = s + str->str_cur;
914 if (*s == '+' || *s == '-')
922 else if (s == str->str_ptr)
928 if (*s == 'e' || *s == 'E') {
930 if (*s == '+' || *s == '-')
951 warn("print to unopened file");
957 ((str->str_nok && str->str_u.str_nval != 0.0)
958 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
959 fprintf(fp, ofmt, str->str_u.str_nval);
964 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
965 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
966 STR *tmpstr = str_mortal(&str_undef);
967 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
972 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
979 do_aprint(arg,fp,arglast)
984 register STR **st = stack->ary_array;
985 register int sp = arglast[1];
987 register int items = arglast[2] - sp;
991 warn("print to unopened file");
995 if (arg->arg_type == O_PRTF) {
996 do_sprintf(arg->arg_ptr.arg_str,items,st);
997 retval = do_print(arg->arg_ptr.arg_str,fp);
1000 retval = (items <= 0);
1001 for (; items > 0; items--,st++) {
1002 if (retval && ofslen) {
1003 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
1008 if (!(retval = do_print(*st, fp)))
1011 if (retval && orslen)
1012 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
1026 if (arg[1].arg_type & A_DONT) {
1027 stio = stab_io(arg[1].arg_ptr.arg_stab);
1028 if (stio && stio->ifp) {
1029 statstab = arg[1].arg_ptr.arg_stab;
1030 str_set(statname,"");
1031 return (laststatval = fstat(fileno(stio->ifp), &statcache));
1034 if (arg[1].arg_ptr.arg_stab == defstab)
1037 warn("Stat on unopened file <%s>",
1038 stab_name(arg[1].arg_ptr.arg_stab));
1039 statstab = Nullstab;
1040 str_set(statname,"");
1041 return (laststatval = -1);
1045 statstab = Nullstab;
1046 str_set(statname,str_get(str));
1047 return (laststatval = stat(str_get(str),&statcache));
1056 if (arg[1].arg_type & A_DONT) {
1057 if (arg[1].arg_ptr.arg_stab == defstab) {
1058 if (laststype != O_LSTAT)
1059 fatal("The stat preceding -l _ wasn't an lstat");
1062 fatal("You can't use -l on a filehandle");
1065 laststype = O_LSTAT;
1066 statstab = Nullstab;
1067 str_set(statname,str_get(str));
1069 return (laststatval = lstat(str_get(str),&statcache));
1071 return (laststatval = stat(str_get(str),&statcache));
1084 register STDCHAR *s;
1085 register STIO *stio;
1087 if (arg[1].arg_type & A_DONT) {
1088 if (arg[1].arg_ptr.arg_stab == defstab) {
1090 stio = stab_io(statstab);
1093 goto really_filename;
1097 statstab = arg[1].arg_ptr.arg_stab;
1098 str_set(statname,"");
1099 stio = stab_io(statstab);
1101 if (stio && stio->ifp) {
1103 fstat(fileno(stio->ifp),&statcache);
1104 if (stio->ifp->_cnt <= 0) {
1105 i = getc(stio->ifp);
1107 (void)ungetc(i,stio->ifp);
1109 if (stio->ifp->_cnt <= 0) /* null file is anything */
1111 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1112 s = stio->ifp->_base;
1114 fatal("-T and -B not implemented on filehandles\n");
1119 warn("Test on unopened file <%s>",
1120 stab_name(arg[1].arg_ptr.arg_stab));
1125 statstab = Nullstab;
1126 str_set(statname,str_get(str));
1128 i = open(str_get(str),0);
1131 fstat(i,&statcache);
1132 len = read(i,tbuf,512);
1134 if (len <= 0) /* null file is anything */
1139 /* now scan s to look for textiness */
1141 for (i = 0; i < len; i++,s++) {
1142 if (!*s) { /* null never allowed in text */
1149 *s != '\n' && *s != '\r' && *s != '\b' &&
1150 *s != '\t' && *s != '\f' && *s != 27)
1154 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1161 do_aexec(really,arglast)
1165 register STR **st = stack->ary_array;
1166 register int sp = arglast[1];
1167 register int items = arglast[2] - sp;
1173 New(401,argv, items+1, char*);
1175 for (st += ++sp; items > 0; items--,st++) {
1177 *a++ = str_get(*st);
1183 if (*argv[0] != '/') /* will execvp use PATH? */
1184 taintenv(); /* testing IFS here is overkill, probably */
1186 if (really && *(tmps = str_get(really)))
1189 execvp(argv[0],argv);
1195 static char **Argv = Null(char **);
1196 static char *Cmd = Nullch;
1203 Argv = Null(char **);
1219 /* save an extra exec if possible */
1222 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1238 if (s[-1] == '\'') {
1240 execl(cshname,"csh", flags,ncmd,(char*)0);
1248 /* see if there are shell metacharacters in it */
1250 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1253 for (s = cmd; *s; s++) {
1254 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1255 if (*s == '\n' && !s[1]) {
1260 execl("/bin/sh","sh","-c",cmd,(char*)0);
1264 New(402,Argv, (s - cmd) / 2 + 2, char*);
1265 Cmd = nsavestr(cmd, s-cmd);
1267 for (s = Cmd; *s;) {
1268 while (*s && isspace(*s)) s++;
1271 while (*s && !isspace(*s)) s++;
1277 execvp(Argv[0],Argv);
1278 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1289 do_socket(stab, arglast)
1293 register STR **st = stack->ary_array;
1294 register int sp = arglast[1];
1295 register STIO *stio;
1296 int domain, type, protocol, fd;
1301 stio = stab_io(stab);
1303 stio = stab_io(stab) = stio_new();
1305 do_close(stab,FALSE);
1307 domain = (int)str_gnum(st[++sp]);
1308 type = (int)str_gnum(st[++sp]);
1309 protocol = (int)str_gnum(st[++sp]);
1311 taintproper("Insecure dependency in socket");
1313 fd = socket(domain,type,protocol);
1316 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1317 stio->ofp = fdopen(fd, "w");
1319 if (!stio->ifp || !stio->ofp) {
1320 if (stio->ifp) fclose(stio->ifp);
1321 if (stio->ofp) fclose(stio->ofp);
1322 if (!stio->ifp && !stio->ofp) close(fd);
1330 do_bind(stab, arglast)
1334 register STR **st = stack->ary_array;
1335 register int sp = arglast[1];
1336 register STIO *stio;
1342 stio = stab_io(stab);
1343 if (!stio || !stio->ifp)
1346 addr = str_get(st[++sp]);
1348 taintproper("Insecure dependency in bind");
1350 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1354 warn("bind() on closed fd");
1360 do_connect(stab, arglast)
1364 register STR **st = stack->ary_array;
1365 register int sp = arglast[1];
1366 register STIO *stio;
1372 stio = stab_io(stab);
1373 if (!stio || !stio->ifp)
1376 addr = str_get(st[++sp]);
1378 taintproper("Insecure dependency in connect");
1380 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1384 warn("connect() on closed fd");
1390 do_listen(stab, arglast)
1394 register STR **st = stack->ary_array;
1395 register int sp = arglast[1];
1396 register STIO *stio;
1402 stio = stab_io(stab);
1403 if (!stio || !stio->ifp)
1406 backlog = (int)str_gnum(st[++sp]);
1407 return listen(fileno(stio->ifp), backlog) >= 0;
1411 warn("listen() on closed fd");
1416 do_accept(str, nstab, gstab)
1421 register STIO *nstio;
1422 register STIO *gstio;
1423 int len = sizeof buf;
1431 gstio = stab_io(gstab);
1432 nstio = stab_io(nstab);
1434 if (!gstio || !gstio->ifp)
1437 nstio = stab_io(nstab) = stio_new();
1438 else if (nstio->ifp)
1439 do_close(nstab,FALSE);
1441 fd = accept(fileno(gstio->ifp),(struct sockaddr *)buf,&len);
1444 nstio->ifp = fdopen(fd, "r");
1445 nstio->ofp = fdopen(fd, "w");
1447 if (!nstio->ifp || !nstio->ofp) {
1448 if (nstio->ifp) fclose(nstio->ifp);
1449 if (nstio->ofp) fclose(nstio->ofp);
1450 if (!nstio->ifp && !nstio->ofp) close(fd);
1454 str_nset(str, buf, len);
1459 warn("accept() on closed fd");
1461 str_sset(str,&str_undef);
1466 do_shutdown(stab, arglast)
1470 register STR **st = stack->ary_array;
1471 register int sp = arglast[1];
1472 register STIO *stio;
1478 stio = stab_io(stab);
1479 if (!stio || !stio->ifp)
1482 how = (int)str_gnum(st[++sp]);
1483 return shutdown(fileno(stio->ifp), how) >= 0;
1487 warn("shutdown() on closed fd");
1493 do_sopt(optype, stab, arglast)
1498 register STR **st = stack->ary_array;
1499 register int sp = arglast[1];
1500 register STIO *stio;
1508 stio = stab_io(stab);
1509 if (!stio || !stio->ifp)
1512 fd = fileno(stio->ifp);
1513 lvl = (int)str_gnum(st[sp+1]);
1514 optname = (int)str_gnum(st[sp+2]);
1517 st[sp] = str_2mortal(str_new(257));
1518 st[sp]->str_cur = 256;
1519 st[sp]->str_pok = 1;
1520 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1525 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1535 warn("[gs]etsockopt() on closed fd");
1536 st[sp] = &str_undef;
1542 do_getsockname(optype, stab, arglast)
1547 register STR **st = stack->ary_array;
1548 register int sp = arglast[1];
1549 register STIO *stio;
1555 stio = stab_io(stab);
1556 if (!stio || !stio->ifp)
1559 st[sp] = str_2mortal(str_new(257));
1560 st[sp]->str_cur = 256;
1561 st[sp]->str_pok = 1;
1562 fd = fileno(stio->ifp);
1565 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1569 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1578 warn("get{sock,peer}name() on closed fd");
1580 st[sp] = &str_undef;
1586 do_ghent(which,gimme,arglast)
1591 register ARRAY *ary = stack;
1592 register int sp = arglast[0];
1593 register char **elem;
1595 struct hostent *gethostbyname();
1596 struct hostent *gethostbyaddr();
1597 #ifdef HAS_GETHOSTENT
1598 struct hostent *gethostent();
1600 struct hostent *hent;
1603 if (gimme != G_ARRAY) {
1604 astore(ary, ++sp, str_mortal(&str_undef));
1608 if (which == O_GHBYNAME) {
1609 char *name = str_get(ary->ary_array[sp+1]);
1611 hent = gethostbyname(name);
1613 else if (which == O_GHBYADDR) {
1614 STR *addrstr = ary->ary_array[sp+1];
1615 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1616 char *addr = str_get(addrstr);
1618 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1621 #ifdef HAS_GETHOSTENT
1622 hent = gethostent();
1624 fatal("gethostent not implemented");
1628 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1629 str_set(str, hent->h_name);
1630 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1631 for (elem = hent->h_aliases; *elem; elem++) {
1632 str_cat(str, *elem);
1634 str_ncat(str," ",1);
1636 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1637 str_numset(str, (double)hent->h_addrtype);
1638 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1639 len = hent->h_length;
1640 str_numset(str, (double)len);
1642 for (elem = hent->h_addr_list; *elem; elem++) {
1643 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1644 str_nset(str, *elem, len);
1647 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1648 str_nset(str, hent->h_addr, len);
1653 (void)astore(ary, ++sp, str_mortal(&str_no));
1661 do_gnent(which,gimme,arglast)
1666 register ARRAY *ary = stack;
1667 register int sp = arglast[0];
1668 register char **elem;
1670 struct netent *getnetbyname();
1671 struct netent *getnetbyaddr();
1672 struct netent *getnetent();
1673 struct netent *nent;
1675 if (gimme != G_ARRAY) {
1676 astore(ary, ++sp, str_mortal(&str_undef));
1680 if (which == O_GNBYNAME) {
1681 char *name = str_get(ary->ary_array[sp+1]);
1683 nent = getnetbyname(name);
1685 else if (which == O_GNBYADDR) {
1686 unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
1687 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1689 nent = getnetbyaddr((long)addr,addrtype);
1696 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1697 str_set(str, nent->n_name);
1698 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1699 for (elem = nent->n_aliases; *elem; elem++) {
1700 str_cat(str, *elem);
1702 str_ncat(str," ",1);
1704 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1705 str_numset(str, (double)nent->n_addrtype);
1706 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1707 str_numset(str, (double)nent->n_net);
1711 (void)astore(ary, ++sp, str_mortal(&str_no));
1719 do_gpent(which,gimme,arglast)
1724 register ARRAY *ary = stack;
1725 register int sp = arglast[0];
1726 register char **elem;
1728 struct protoent *getprotobyname();
1729 struct protoent *getprotobynumber();
1730 struct protoent *getprotoent();
1731 struct protoent *pent;
1733 if (gimme != G_ARRAY) {
1734 astore(ary, ++sp, str_mortal(&str_undef));
1738 if (which == O_GPBYNAME) {
1739 char *name = str_get(ary->ary_array[sp+1]);
1741 pent = getprotobyname(name);
1743 else if (which == O_GPBYNUMBER) {
1744 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1746 pent = getprotobynumber(proto);
1749 pent = getprotoent();
1753 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1754 str_set(str, pent->p_name);
1755 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1756 for (elem = pent->p_aliases; *elem; elem++) {
1757 str_cat(str, *elem);
1759 str_ncat(str," ",1);
1761 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1762 str_numset(str, (double)pent->p_proto);
1766 (void)astore(ary, ++sp, str_mortal(&str_no));
1774 do_gsent(which,gimme,arglast)
1779 register ARRAY *ary = stack;
1780 register int sp = arglast[0];
1781 register char **elem;
1783 struct servent *getservbyname();
1784 struct servent *getservbynumber();
1785 struct servent *getservent();
1786 struct servent *sent;
1788 if (gimme != G_ARRAY) {
1789 astore(ary, ++sp, str_mortal(&str_undef));
1793 if (which == O_GSBYNAME) {
1794 char *name = str_get(ary->ary_array[sp+1]);
1795 char *proto = str_get(ary->ary_array[sp+2]);
1797 if (proto && !*proto)
1800 sent = getservbyname(name,proto);
1802 else if (which == O_GSBYPORT) {
1803 int port = (int)str_gnum(ary->ary_array[sp+1]);
1804 char *proto = str_get(ary->ary_array[sp+2]);
1806 sent = getservbyport(port,proto);
1809 sent = getservent();
1812 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1813 str_set(str, sent->s_name);
1814 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1815 for (elem = sent->s_aliases; *elem; elem++) {
1816 str_cat(str, *elem);
1818 str_ncat(str," ",1);
1820 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1822 str_numset(str, (double)ntohs(sent->s_port));
1824 str_numset(str, (double)(sent->s_port));
1826 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1827 str_set(str, sent->s_proto);
1831 (void)astore(ary, ++sp, str_mortal(&str_no));
1838 #endif /* HAS_SOCKET */
1842 do_select(gimme,arglast)
1846 register STR **st = stack->ary_array;
1847 register int sp = arglast[0];
1855 struct timeval timebuf;
1856 struct timeval *tbuf = &timebuf;
1858 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1864 #if BYTEORDER & 0xf0000
1865 #define ORDERBYTE (0x88888888 - BYTEORDER)
1867 #define ORDERBYTE (0x4444 - BYTEORDER)
1872 for (i = 1; i <= 3; i++) {
1873 j = st[sp+i]->str_cur;
1878 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1879 growsize = maxlen; /* little endians can use vecs directly */
1887 masksize = NFDBITS / NBBY;
1889 masksize = sizeof(long); /* documented int, everyone seems to use long */
1891 growsize = maxlen + (masksize - (maxlen % masksize));
1892 Zero(&fd_sets[0], 4, char*);
1895 for (i = 1; i <= 3; i++) {
1900 Str_Grow(str,growsize);
1901 s = str_get(str) + j;
1902 while (++j <= growsize) {
1906 else if (str->str_ptr) {
1907 Safefree(str->str_ptr);
1908 str->str_ptr = Nullch;
1911 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1914 New(403, fd_sets[i], growsize, char);
1915 for (offset = 0; offset < growsize; offset += masksize) {
1916 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1917 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1923 if (str->str_nok || str->str_pok) {
1924 value = str_gnum(str);
1927 timebuf.tv_sec = (long)value;
1928 value -= (double)timebuf.tv_sec;
1929 timebuf.tv_usec = (long)(value * 1000000.0);
1932 tbuf = Null(struct timeval*);
1934 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1948 for (i = 1; i <= 3; i++) {
1952 for (offset = 0; offset < growsize; offset += masksize) {
1953 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1954 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1960 st[++sp] = str_mortal(&str_no);
1961 str_numset(st[sp], (double)nfound);
1962 if (gimme == G_ARRAY && tbuf) {
1963 value = (double)(timebuf.tv_sec) +
1964 (double)(timebuf.tv_usec) / 1000000.0;
1965 st[++sp] = str_mortal(&str_no);
1966 str_numset(st[sp], value);
1974 do_spair(stab1, stab2, arglast)
1979 register STR **st = stack->ary_array;
1980 register int sp = arglast[2];
1981 register STIO *stio1;
1982 register STIO *stio2;
1983 int domain, type, protocol, fd[2];
1985 if (!stab1 || !stab2)
1988 stio1 = stab_io(stab1);
1989 stio2 = stab_io(stab2);
1991 stio1 = stab_io(stab1) = stio_new();
1992 else if (stio1->ifp)
1993 do_close(stab1,FALSE);
1995 stio2 = stab_io(stab2) = stio_new();
1996 else if (stio2->ifp)
1997 do_close(stab2,FALSE);
1999 domain = (int)str_gnum(st[++sp]);
2000 type = (int)str_gnum(st[++sp]);
2001 protocol = (int)str_gnum(st[++sp]);
2003 taintproper("Insecure dependency in socketpair");
2005 #ifdef HAS_SOCKETPAIR
2006 if (socketpair(domain,type,protocol,fd) < 0)
2009 fatal("Socketpair unimplemented");
2011 stio1->ifp = fdopen(fd[0], "r");
2012 stio1->ofp = fdopen(fd[0], "w");
2014 stio2->ifp = fdopen(fd[1], "r");
2015 stio2->ofp = fdopen(fd[1], "w");
2017 if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
2018 if (stio1->ifp) fclose(stio1->ifp);
2019 if (stio1->ofp) fclose(stio1->ofp);
2020 if (!stio1->ifp && !stio1->ofp) close(fd[0]);
2021 if (stio2->ifp) fclose(stio2->ifp);
2022 if (stio2->ofp) fclose(stio2->ofp);
2023 if (!stio2->ifp && !stio2->ofp) close(fd[1]);
2030 #endif /* HAS_SOCKET */
2033 do_gpwent(which,gimme,arglast)
2039 register ARRAY *ary = stack;
2040 register int sp = arglast[0];
2042 struct passwd *getpwnam();
2043 struct passwd *getpwuid();
2044 struct passwd *getpwent();
2045 struct passwd *pwent;
2047 if (gimme != G_ARRAY) {
2048 astore(ary, ++sp, str_mortal(&str_undef));
2052 if (which == O_GPWNAM) {
2053 char *name = str_get(ary->ary_array[sp+1]);
2055 pwent = getpwnam(name);
2057 else if (which == O_GPWUID) {
2058 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2060 pwent = getpwuid(uid);
2066 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2067 str_set(str, pwent->pw_name);
2068 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2069 str_set(str, pwent->pw_passwd);
2070 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2071 str_numset(str, (double)pwent->pw_uid);
2072 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2073 str_numset(str, (double)pwent->pw_gid);
2074 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2076 str_numset(str, (double)pwent->pw_change);
2079 str_numset(str, (double)pwent->pw_quota);
2082 str_set(str, pwent->pw_age);
2086 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2088 str_set(str,pwent->pw_class);
2091 str_set(str, pwent->pw_comment);
2094 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2095 str_set(str, pwent->pw_gecos);
2096 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2097 str_set(str, pwent->pw_dir);
2098 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2099 str_set(str, pwent->pw_shell);
2101 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2102 str_numset(str, (double)pwent->pw_expire);
2108 fatal("password routines not implemented");
2113 do_ggrent(which,gimme,arglast)
2119 register ARRAY *ary = stack;
2120 register int sp = arglast[0];
2121 register char **elem;
2123 struct group *getgrnam();
2124 struct group *getgrgid();
2125 struct group *getgrent();
2126 struct group *grent;
2128 if (gimme != G_ARRAY) {
2129 astore(ary, ++sp, str_mortal(&str_undef));
2133 if (which == O_GGRNAM) {
2134 char *name = str_get(ary->ary_array[sp+1]);
2136 grent = getgrnam(name);
2138 else if (which == O_GGRGID) {
2139 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2141 grent = getgrgid(gid);
2147 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2148 str_set(str, grent->gr_name);
2149 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2150 str_set(str, grent->gr_passwd);
2151 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2152 str_numset(str, (double)grent->gr_gid);
2153 (void)astore(ary, ++sp, str = str_mortal(&str_no));
2154 for (elem = grent->gr_mem; *elem; elem++) {
2155 str_cat(str, *elem);
2157 str_ncat(str," ",1);
2163 fatal("group routines not implemented");
2168 do_dirop(optype,stab,gimme,arglast)
2174 #if defined(DIRENT) && defined(HAS_READDIR)
2175 register ARRAY *ary = stack;
2176 register STR **st = ary->ary_array;
2177 register int sp = arglast[1];
2178 register STIO *stio;
2184 struct DIRENT *readdir();
2186 register struct DIRENT *dp;
2190 if (!(stio = stab_io(stab)))
2191 stio = stab_io(stab) = stio_new();
2192 if (!stio->dirp && optype != O_OPEN_DIR)
2198 closedir(stio->dirp);
2199 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2203 if (gimme == G_ARRAY) {
2205 while (dp = readdir(stio->dirp)) {
2207 (void)astore(ary,++sp,
2208 str_2mortal(str_make(dp->d_name,dp->d_namlen)));
2210 (void)astore(ary,++sp,
2211 str_2mortal(str_make(dp->d_name,0)));
2216 if (!(dp = readdir(stio->dirp)))
2218 st[sp] = str_mortal(&str_undef);
2220 str_nset(st[sp], dp->d_name, dp->d_namlen);
2222 str_set(st[sp], dp->d_name);
2232 st[sp] = str_mortal(&str_undef);
2233 str_numset(st[sp], (double)telldir(stio->dirp));
2236 st[sp] = str_mortal(&str_undef);
2237 along = (long)str_gnum(st[sp+1]);
2238 (void)seekdir(stio->dirp,along);
2242 st[sp] = str_mortal(&str_undef);
2243 (void)rewinddir(stio->dirp);
2246 st[sp] = str_mortal(&str_undef);
2247 (void)closedir(stio->dirp);
2254 st[sp] = &str_undef;
2258 fatal("Unimplemented directory operation");
2266 register STR **st = stack->ary_array;
2267 register int sp = arglast[1];
2268 register int items = arglast[2] - sp;
2271 register int tot = 0;
2275 for (st += ++sp; items--; st++)
2276 tainted |= (*st)->str_tainted;
2277 st = stack->ary_array;
2279 items = arglast[2] - sp;
2284 taintproper("Insecure dependency in chmod");
2288 val = (int)str_gnum(st[++sp]);
2290 if (chmod(str_get(st[++sp]),val))
2298 taintproper("Insecure dependency in chown");
2303 val = (int)str_gnum(st[++sp]);
2304 val2 = (int)str_gnum(st[++sp]);
2306 if (chown(str_get(st[++sp]),val,val2))
2315 taintproper("Insecure dependency in kill");
2319 s = str_get(st[++sp]);
2321 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2323 if (!(val = whichsig(s)))
2324 fatal("Unrecognized signal name \"%s\"",s);
2327 val = (int)str_gnum(st[sp]);
2331 int proc = (int)str_gnum(st[++sp]);
2333 if (killpg(proc,val)) /* BSD */
2335 if (kill(-proc,val)) /* SYSV */
2342 if (kill((int)(str_gnum(st[++sp])),val))
2351 taintproper("Insecure dependency in unlink");
2355 s = str_get(st[++sp]);
2356 if (euid || unsafe) {
2360 else { /* don't let root wipe out directories without -U */
2362 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2364 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
2376 taintproper("Insecure dependency in utime");
2380 struct utimbuf utbuf;
2388 Zero(&utbuf, sizeof utbuf, char);
2389 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2390 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2395 if (utime(str_get(st[++sp]),&utbuf))
2407 /* Do the permissions allow some operation? Assumes statcache already set. */
2410 cando(bit, effective, statbufp)
2413 register struct stat *statbufp;
2416 /* [Comments and code from Len Reed]
2417 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2418 * to write-protected files. The execute permission bit is set
2419 * by the Miscrosoft C library stat() function for the following:
2424 * All files and directories are readable.
2425 * Directories and special files, e.g. "CON", cannot be
2427 * [Comment by Tom Dinger -- a directory can have the write-protect
2428 * bit set in the file system, but DOS permits changes to
2429 * the directory anyway. In addition, all bets are off
2430 * here for networked software, such as Novell and
2434 return (bit & statbufp->st_mode) ? TRUE : FALSE;
2437 if ((effective ? euid : uid) == 0) { /* root is special */
2438 if (bit == S_IXUSR) {
2439 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
2443 return TRUE; /* root reads and writes anything */
2446 if (statbufp->st_uid == (effective ? euid : uid) ) {
2447 if (statbufp->st_mode & bit)
2448 return TRUE; /* ok as "user" */
2450 else if (ingroup((int)statbufp->st_gid,effective)) {
2451 if (statbufp->st_mode & bit >> 3)
2452 return TRUE; /* ok as "group" */
2454 else if (statbufp->st_mode & bit >> 6)
2455 return TRUE; /* ok as "other" */
2457 #endif /* ! MSDOS */
2461 ingroup(testgid,effective)
2465 if (testgid == (effective ? egid : gid))
2467 #ifdef HAS_GETGROUPS
2472 GROUPSTYPE gary[NGROUPS];
2475 anum = getgroups(NGROUPS,gary);
2477 if (gary[anum] == testgid)
2484 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
2487 do_ipcget(optype, arglast)
2491 register STR **st = stack->ary_array;
2492 register int sp = arglast[0];
2496 key = (key_t)str_gnum(st[++sp]);
2497 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2498 flags = (int)str_gnum(st[++sp]);
2504 return msgget(key, flags);
2508 return semget(key, n, flags);
2512 return shmget(key, n, flags);
2514 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2516 fatal("%s not implemented", opname[optype]);
2519 return -1; /* should never happen */
2523 do_ipcctl(optype, arglast)
2527 register STR **st = stack->ary_array;
2528 register int sp = arglast[0];
2531 int id, n, cmd, infosize, getinfo, ret;
2533 id = (int)str_gnum(st[++sp]);
2534 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2535 cmd = (int)str_gnum(st[++sp]);
2539 getinfo = (cmd == IPC_STAT);
2545 if (cmd == IPC_STAT || cmd == IPC_SET)
2546 infosize = sizeof(struct msqid_ds);
2551 if (cmd == IPC_STAT || cmd == IPC_SET)
2552 infosize = sizeof(struct shmid_ds);
2557 if (cmd == IPC_STAT || cmd == IPC_SET)
2558 infosize = sizeof(struct semid_ds);
2559 else if (cmd == GETALL || cmd == SETALL)
2561 struct semid_ds semds;
2562 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2564 getinfo = (cmd == GETALL);
2565 infosize = semds.sem_nsems * sizeof(short);
2566 /* "short" is technically wrong but much more portable
2567 than guessing about u_?short(_t)? */
2571 #if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
2573 fatal("%s not implemented", opname[optype]);
2581 STR_GROW(astr, infosize+1);
2587 if (astr->str_cur != infosize)
2596 int i = (int)str_gnum(astr);
2597 a = (char *)i; /* ouch */
2604 ret = msgctl(id, cmd, a);
2609 ret = semctl(id, n, cmd, a);
2614 ret = shmctl(id, cmd, a);
2618 if (getinfo && ret >= 0) {
2619 astr->str_cur = infosize;
2620 astr->str_ptr[infosize] = '\0';
2630 register STR **st = stack->ary_array;
2631 register int sp = arglast[0];
2634 int id, msize, flags;
2636 id = (int)str_gnum(st[++sp]);
2638 flags = (int)str_gnum(st[++sp]);
2639 mbuf = str_get(mstr);
2640 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2645 return msgsnd(id, mbuf, msize, flags);
2647 fatal("msgsnd not implemented");
2656 register STR **st = stack->ary_array;
2657 register int sp = arglast[0];
2661 int id, msize, flags, ret;
2663 id = (int)str_gnum(st[++sp]);
2665 msize = (int)str_gnum(st[++sp]);
2666 mtype = (long)str_gnum(st[++sp]);
2667 flags = (int)str_gnum(st[++sp]);
2668 mbuf = str_get(mstr);
2669 if (mstr->str_cur < sizeof(long)+msize+1) {
2670 STR_GROW(mstr, sizeof(long)+msize+1);
2671 mbuf = str_get(mstr);
2674 ret = msgrcv(id, mbuf, msize, mtype, flags);
2676 mstr->str_cur = sizeof(long)+ret;
2677 mstr->str_ptr[sizeof(long)+ret] = '\0';
2681 fatal("msgrcv not implemented");
2690 register STR **st = stack->ary_array;
2691 register int sp = arglast[0];
2696 id = (int)str_gnum(st[++sp]);
2698 opbuf = str_get(opstr);
2699 opsize = opstr->str_cur;
2700 if (opsize < sizeof(struct sembuf)
2701 || (opsize % sizeof(struct sembuf)) != 0) {
2706 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
2708 fatal("semop not implemented");
2713 do_shmio(optype, arglast)
2718 register STR **st = stack->ary_array;
2719 register int sp = arglast[0];
2722 int id, mpos, msize;
2723 struct shmid_ds shmds;
2725 extern char *shmat();
2728 id = (int)str_gnum(st[++sp]);
2730 mpos = (int)str_gnum(st[++sp]);
2731 msize = (int)str_gnum(st[++sp]);
2733 if (shmctl(id, IPC_STAT, &shmds) == -1)
2735 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2736 errno = EFAULT; /* can't do as caller requested */
2739 shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
2740 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2742 mbuf = str_get(mstr);
2743 if (optype == O_SHMREAD) {
2744 if (mstr->str_cur < msize) {
2745 STR_GROW(mstr, msize+1);
2746 mbuf = str_get(mstr);
2748 bcopy(shm + mpos, mbuf, msize);
2749 mstr->str_cur = msize;
2750 mstr->str_ptr[msize] = '\0';
2755 if ((n = mstr->str_cur) > msize)
2757 bcopy(mbuf, shm + mpos, n);
2759 bzero(shm + mpos + n, msize - n);
2763 fatal("shm I/O not implemented");
2767 #endif /* SYSV IPC */