1 /* $Header: doio.c,v 3.0.1.9 90/08/09 02:56:19 lwall Locked $
3 * Copyright (c) 1989, Larry Wall
5 * You may distribute under the terms of the GNU General Public License
6 * as specified in the README file that comes with the perl 3.0 kit.
9 * Revision 3.0.1.9 90/08/09 02:56:19 lwall
10 * patch19: various MSDOS and OS/2 patches folded in
11 * patch19: prints now check error status better
12 * patch19: printing a list with null elements only printed front of list
13 * patch19: on machines with vfork child would allocate memory in parent
14 * patch19: getsockname and getpeername gave bogus warning on error
15 * patch19: MACH doesn't have seekdir or telldir
17 * Revision 3.0.1.8 90/03/27 15:44:02 lwall
18 * patch16: MSDOS support
19 * patch16: support for machines that can't cast negative floats to unsigned ints
20 * patch16: system() can lose arguments passed to shell scripts on SysV machines
22 * Revision 3.0.1.7 90/03/14 12:26:24 lwall
23 * patch15: commands involving execs could cause malloc arena corruption
25 * Revision 3.0.1.6 90/03/12 16:30:07 lwall
26 * patch13: system 'FOO=bar command' didn't invoke sh as it should
28 * Revision 3.0.1.5 90/02/28 17:01:36 lwall
29 * patch9: open(FOO,"$filename\0") will now protect trailing spaces in filename
30 * patch9: removed obsolete checks to avoid opening block devices
31 * patch9: removed references to acusec and modusec that some utime.h's have
32 * patch9: added pipe function
34 * Revision 3.0.1.4 89/12/21 19:55:10 lwall
35 * patch7: select now works on big-endian machines
36 * patch7: errno may now be a macro with an lvalue
37 * patch7: ANSI strerror() is now supported
38 * patch7: Configure now detects DG/UX thingies like [sg]etpgrp2 and utime.h
40 * Revision 3.0.1.3 89/11/17 15:13:06 lwall
41 * patch5: some systems have symlink() but not lstat()
42 * patch5: some systems have dirent.h but not readdir()
44 * Revision 3.0.1.2 89/11/11 04:25:51 lwall
45 * patch2: orthogonalized the file modes some so we can have <& +<& etc.
46 * patch2: do_open() now detects sockets passed to process from parent
47 * patch2: fd's above 2 are now closed on exec
48 * patch2: csh code can now use csh from other than /bin
49 * patch2: getsockopt, get{sock,peer}name didn't define result properly
50 * patch2: warn("shutdown") was replicated
51 * patch2: gethostbyname was misdeclared
52 * patch2: telldir() is sometimes a macro
54 * Revision 3.0.1.1 89/10/26 23:10:05 lwall
55 * patch1: Configure now checks for BSD shadow passwords
57 * Revision 3.0 89/10/18 15:10:54 lwall
66 #include <sys/socket.h>
84 do_open(stab,name,len)
90 register STIO *stio = stab_io(stab);
91 char *myname = savestr(name);
95 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
98 forkprocess = 1; /* assume true if no fork */
99 while (len && isspace(name[len-1]))
102 stio = stab_io(stab) = stio_new();
103 else if (stio->ifp) {
104 fd = fileno(stio->ifp);
105 if (stio->type == '|')
106 result = mypclose(stio->ifp);
107 else if (stio->ifp != stio->ofp) {
110 result = fclose(stio->ifp);
112 else if (stio->type != '-')
113 result = fclose(stio->ifp);
116 if (result == EOF && fd > 2)
117 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
119 stio->ofp = stio->ifp = Nullfp;
121 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
132 for (name++; isspace(*name); name++) ;
135 taintproper("Insecure dependency in piped open");
137 fp = mypopen(name,"w");
140 else if (*name == '>') {
142 taintproper("Insecure dependency in open");
146 mode[0] = stio->type = 'a';
155 while (isspace(*name))
160 stab = stabent(name,FALSE);
161 if (!stab || !stab_io(stab))
163 if (stab_io(stab) && stab_io(stab)->ifp) {
164 fd = fileno(stab_io(stab)->ifp);
165 if (stab_io(stab)->type == 's')
171 fp = fdopen(dup(fd),mode);
174 while (isspace(*name))
176 if (strEQ(name,"-")) {
181 fp = fopen(name,mode);
189 while (isspace(*name))
193 if (strEQ(name,"-")) {
198 fp = fopen(name,mode);
200 else if (name[len-1] == '|') {
203 taintproper("Insecure dependency in piped open");
206 while (len && isspace(name[len-1]))
208 for (; isspace(*name); name++) ;
209 fp = mypopen(name,"r");
214 for (; isspace(*name); name++) ;
215 if (strEQ(name,"-")) {
220 fp = fopen(name,"r");
227 stio->type != '|' && stio->type != '-') {
228 if (fstat(fileno(fp),&statbuf) < 0) {
232 result = (statbuf.st_mode & S_IFMT);
234 if (result == S_IFSOCK || result == 0)
235 stio->type = 's'; /* in case a socket was passed in to us */
238 #if defined(FCNTL) && defined(F_SETFD)
245 if (stio->type != 's')
248 stio->ofp = fdopen(fileno(fp),"w");
259 int filemode,fileuid,filegid;
261 while (alen(stab_xarray(stab)) >= 0) {
262 str = ashift(stab_xarray(stab));
263 str_sset(stab_val(stab),str);
264 STABSET(stab_val(stab));
265 oldname = str_get(stab_val(stab));
266 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
269 taintproper("Insecure dependency in inplace open");
271 filemode = statbuf.st_mode;
272 fileuid = statbuf.st_uid;
273 filegid = statbuf.st_gid;
276 add_suffix(str,inplace);
278 str_cat(str,inplace);
282 (void)rename(oldname,str->str_ptr);
284 do_close(stab,FALSE);
285 (void)unlink(str->str_ptr);
286 (void)rename(oldname,str->str_ptr);
287 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
290 (void)UNLINK(str->str_ptr);
291 (void)link(oldname,str->str_ptr);
292 (void)UNLINK(oldname);
297 (void)UNLINK(oldname);
299 fatal("Can't do inplace edit without backup");
304 str_cat(str,oldname);
305 errno = 0; /* in case sprintf set errno */
306 if (!do_open(argvoutstab,str->str_ptr,str->str_cur))
307 fatal("Can't do inplace edit");
308 defoutstab = argvoutstab;
310 (void)fchmod(fileno(stab_io(argvoutstab)->ifp),filemode);
312 (void)chmod(oldname,filemode);
315 (void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
318 (void)chown(oldname,fileuid,filegid);
323 return stab_io(stab)->ifp;
326 fprintf(stderr,"Can't open %s\n",str_get(str));
330 (void)do_close(argvoutstab,FALSE);
331 defoutstab = stabent("STDOUT",TRUE);
338 do_pipe(str, rstab, wstab)
343 register STIO *rstio;
344 register STIO *wstio;
352 rstio = stab_io(rstab);
353 wstio = stab_io(wstab);
356 rstio = stab_io(rstab) = stio_new();
358 do_close(rstab,FALSE);
360 wstio = stab_io(wstab) = stio_new();
362 do_close(wstab,FALSE);
366 rstio->ifp = fdopen(fd[0], "r");
367 wstio->ofp = fdopen(fd[1], "w");
368 wstio->ifp = wstio->ofp;
372 str_sset(str,&str_yes);
376 str_sset(str,&str_undef);
382 do_close(stab,explicit)
387 register STIO *stio = stab_io(stab);
390 if (!stio) { /* never opened */
391 if (dowarn && explicit)
392 warn("Close on unopened file <%s>",stab_name(stab));
396 if (stio->type == '|') {
397 status = mypclose(stio->ifp);
398 retval = (status >= 0);
399 statusvalue = (unsigned short)status & 0xffff;
401 else if (stio->type == '-')
404 if (stio->ofp && stio->ofp != stio->ifp) /* a socket */
406 retval = (fclose(stio->ifp) != EOF);
408 stio->ofp = stio->ifp = Nullfp;
423 if (!stab) { /* eof() */
425 stio = stab_io(argvstab);
430 stio = stab_io(stab);
437 #ifdef STDSTDIO /* (the code works without this) */
438 if (stio->ifp->_cnt > 0) /* cheat a little, since */
439 return FALSE; /* this is the most usual case */
442 ch = getc(stio->ifp);
444 (void)ungetc(ch, stio->ifp);
447 if (!stab) { /* not necessarily a real EOF yet? */
448 if (!nextargv(argvstab)) /* get another fp handy */
452 return TRUE; /* normal fp, definitely end of file */
466 stio = stab_io(stab);
467 if (!stio || !stio->ifp)
471 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
473 return ftell(stio->ifp);
477 warn("tell() on unopened file");
482 do_seek(stab, pos, whence)
492 stio = stab_io(stab);
493 if (!stio || !stio->ifp)
497 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
499 return fseek(stio->ifp, pos, whence) >= 0;
503 warn("seek() on unopened file");
508 do_ctl(optype,stab,func,argstr)
518 if (!stab || !argstr)
520 stio = stab_io(stab);
524 if (argstr->str_pok || !argstr->str_nok) {
525 if (!argstr->str_pok)
530 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
534 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
536 retval = 256; /* otherwise guess at what's safe */
538 if (argstr->str_cur < retval) {
539 Str_Grow(argstr,retval+1);
540 argstr->str_cur = retval;
544 s[argstr->str_cur] = 17; /* a little sanity check here */
547 retval = (int)str_gnum(argstr);
548 s = (char*)retval; /* ouch */
552 if (optype == O_IOCTL)
553 retval = ioctl(fileno(stio->ifp), func, s);
556 retval = fcntl(fileno(stio->ifp), func, s);
558 fatal("fcntl is not implemented");
564 if (argstr->str_pok) {
565 if (s[argstr->str_cur] != 17)
566 fatal("Return value overflowed string");
567 s[argstr->str_cur] = 0; /* put our null back */
573 do_stat(str,arg,gimme,arglast)
579 register ARRAY *ary = stack;
580 register int sp = arglast[0] + 1;
584 if ((arg[1].arg_type & A_MASK) == A_WORD) {
585 tmpstab = arg[1].arg_ptr.arg_stab;
586 if (tmpstab != defstab) {
588 str_set(statname,"");
589 if (!stab_io(tmpstab) ||
590 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
596 str_sset(statname,ary->ary_array[sp]);
599 if (arg->arg_type == O_LSTAT)
600 i = lstat(str_get(statname),&statcache);
603 i = stat(str_get(statname),&statcache);
608 if (gimme != G_ARRAY) {
610 str_sset(str,&str_yes);
612 str_sset(str,&str_undef);
614 ary->ary_array[sp] = str;
620 (void)astore(ary,++sp,
621 str_2static(str_nmake((double)statcache.st_dev)));
622 (void)astore(ary,++sp,
623 str_2static(str_nmake((double)statcache.st_ino)));
624 (void)astore(ary,++sp,
625 str_2static(str_nmake((double)statcache.st_mode)));
626 (void)astore(ary,++sp,
627 str_2static(str_nmake((double)statcache.st_nlink)));
628 (void)astore(ary,++sp,
629 str_2static(str_nmake((double)statcache.st_uid)));
630 (void)astore(ary,++sp,
631 str_2static(str_nmake((double)statcache.st_gid)));
632 (void)astore(ary,++sp,
633 str_2static(str_nmake((double)statcache.st_rdev)));
634 (void)astore(ary,++sp,
635 str_2static(str_nmake((double)statcache.st_size)));
636 (void)astore(ary,++sp,
637 str_2static(str_nmake((double)statcache.st_atime)));
638 (void)astore(ary,++sp,
639 str_2static(str_nmake((double)statcache.st_mtime)));
640 (void)astore(ary,++sp,
641 str_2static(str_nmake((double)statcache.st_ctime)));
643 (void)astore(ary,++sp,
644 str_2static(str_nmake((double)statcache.st_blksize)));
645 (void)astore(ary,++sp,
646 str_2static(str_nmake((double)statcache.st_blocks)));
648 (void)astore(ary,++sp,
649 str_2static(str_make("",0)));
650 (void)astore(ary,++sp,
651 str_2static(str_make("",0)));
654 (void)astore(ary,++sp,str_nmake(0.0));
661 do_truncate(str,arg,gimme,arglast)
667 register ARRAY *ary = stack;
668 register int sp = arglast[0] + 1;
669 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
673 #if defined(TRUNCATE) || defined(CHSIZE) || defined(F_FREESP)
675 if ((arg[1].arg_type & A_MASK) == A_WORD) {
676 tmpstab = arg[1].arg_ptr.arg_stab;
677 if (!stab_io(tmpstab) ||
678 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
681 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
685 #define chsize(f,l) fcntl(f,F_FREESP,l)
687 if ((arg[1].arg_type & A_MASK) == A_WORD) {
688 tmpstab = arg[1].arg_ptr.arg_stab;
689 if (!stab_io(tmpstab) ||
690 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
696 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
699 if (chsize(tmpfd, len) < 0)
707 str_sset(str,&str_yes);
709 str_sset(str,&str_undef);
711 ary->ary_array[sp] = str;
714 fatal("truncate not implemented");
719 looks_like_number(str)
728 send = s + str->str_cur;
733 if (*s == '+' || *s == '-')
741 else if (s == str->str_ptr)
747 if (*s == 'e' || *s == 'E') {
749 if (*s == '+' || *s == '-')
770 warn("print to unopened file");
776 ((str->str_nok && str->str_u.str_nval != 0.0)
777 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
778 fprintf(fp, ofmt, str->str_u.str_nval);
783 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'a' && tmps[3] == 'b'
784 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
785 tmps = stab_name(((STAB*)str)); /* a stab value, be nice */
786 str = ((STAB*)str)->str_magic;
789 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
796 do_aprint(arg,fp,arglast)
801 register STR **st = stack->ary_array;
802 register int sp = arglast[1];
804 register int items = arglast[2] - sp;
808 warn("print to unopened file");
812 if (arg->arg_type == O_PRTF) {
813 do_sprintf(arg->arg_ptr.arg_str,items,st);
814 retval = do_print(arg->arg_ptr.arg_str,fp);
817 retval = (items <= 0);
818 for (; items > 0; items--,st++) {
819 if (retval && ofslen) {
820 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
825 if (!(retval = do_print(*st, fp)))
828 if (retval && orslen)
829 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
842 if (arg[1].arg_type & A_DONT) {
843 stio = stab_io(arg[1].arg_ptr.arg_stab);
844 if (stio && stio->ifp) {
845 statstab = arg[1].arg_ptr.arg_stab;
846 str_set(statname,"");
847 return fstat(fileno(stio->ifp), &statcache);
850 if (arg[1].arg_ptr.arg_stab == defstab)
853 warn("Stat on unopened file <%s>",
854 stab_name(arg[1].arg_ptr.arg_stab));
856 str_set(statname,"");
862 str_sset(statname,str);
863 return stat(str_get(str),&statcache);
879 if (arg[1].arg_type & A_DONT) {
880 if (arg[1].arg_ptr.arg_stab == defstab) {
882 stio = stab_io(statstab);
885 goto really_filename;
889 statstab = arg[1].arg_ptr.arg_stab;
890 str_set(statname,"");
891 stio = stab_io(statstab);
893 if (stio && stio->ifp) {
895 fstat(fileno(stio->ifp),&statcache);
896 if (stio->ifp->_cnt <= 0) {
899 (void)ungetc(i,stio->ifp);
901 if (stio->ifp->_cnt <= 0) /* null file is anything */
903 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
904 s = stio->ifp->_base;
906 fatal("-T and -B not implemented on filehandles\n");
911 warn("Test on unopened file <%s>",
912 stab_name(arg[1].arg_ptr.arg_stab));
918 str_sset(statname,str);
920 i = open(str_get(str),0);
924 len = read(i,tbuf,512);
925 if (len <= 0) /* null file is anything */
931 /* now scan s to look for textiness */
933 for (i = 0; i < len; i++,s++) {
934 if (!*s) { /* null never allowed in text */
941 *s != '\n' && *s != '\r' && *s != '\b' &&
942 *s != '\t' && *s != '\f' && *s != 27)
946 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
953 do_aexec(really,arglast)
957 register STR **st = stack->ary_array;
958 register int sp = arglast[1];
959 register int items = arglast[2] - sp;
965 New(401,argv, items+1, char*);
967 for (st += ++sp; items > 0; items--,st++) {
975 if (*argv[0] != '/') /* will execvp use PATH? */
976 taintenv(); /* testing IFS here is overkill, probably */
978 if (really && *(tmps = str_get(really)))
981 execvp(argv[0],argv);
987 static char **Argv = Null(char **);
988 static char *Cmd = Nullch;
995 Argv = Null(char **);
1013 taintproper("Insecure dependency in exec");
1016 /* save an extra exec if possible */
1019 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
1035 if (s[-1] == '\'') {
1037 execl(cshname,"csh", flags,ncmd,(char*)0);
1045 /* see if there are shell metacharacters in it */
1047 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1050 for (s = cmd; *s; s++) {
1051 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1052 if (*s == '\n' && !s[1]) {
1057 execl("/bin/sh","sh","-c",cmd,(char*)0);
1061 New(402,Argv, (s - cmd) / 2 + 2, char*);
1062 Cmd = nsavestr(cmd, s-cmd);
1064 for (s = Cmd; *s;) {
1065 while (*s && isspace(*s)) s++;
1068 while (*s && !isspace(*s)) s++;
1074 execvp(Argv[0],Argv);
1075 if (errno == ENOEXEC) { /* for system V NIH syndrome */
1086 do_socket(stab, arglast)
1090 register STR **st = stack->ary_array;
1091 register int sp = arglast[1];
1092 register STIO *stio;
1093 int domain, type, protocol, fd;
1098 stio = stab_io(stab);
1100 stio = stab_io(stab) = stio_new();
1102 do_close(stab,FALSE);
1104 domain = (int)str_gnum(st[++sp]);
1105 type = (int)str_gnum(st[++sp]);
1106 protocol = (int)str_gnum(st[++sp]);
1108 taintproper("Insecure dependency in socket");
1110 fd = socket(domain,type,protocol);
1113 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1114 stio->ofp = fdopen(fd, "w");
1121 do_bind(stab, arglast)
1125 register STR **st = stack->ary_array;
1126 register int sp = arglast[1];
1127 register STIO *stio;
1133 stio = stab_io(stab);
1134 if (!stio || !stio->ifp)
1137 addr = str_get(st[++sp]);
1139 taintproper("Insecure dependency in bind");
1141 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1145 warn("bind() on closed fd");
1151 do_connect(stab, arglast)
1155 register STR **st = stack->ary_array;
1156 register int sp = arglast[1];
1157 register STIO *stio;
1163 stio = stab_io(stab);
1164 if (!stio || !stio->ifp)
1167 addr = str_get(st[++sp]);
1169 taintproper("Insecure dependency in connect");
1171 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1175 warn("connect() on closed fd");
1181 do_listen(stab, arglast)
1185 register STR **st = stack->ary_array;
1186 register int sp = arglast[1];
1187 register STIO *stio;
1193 stio = stab_io(stab);
1194 if (!stio || !stio->ifp)
1197 backlog = (int)str_gnum(st[++sp]);
1198 return listen(fileno(stio->ifp), backlog) >= 0;
1202 warn("listen() on closed fd");
1207 do_accept(str, nstab, gstab)
1212 register STIO *nstio;
1213 register STIO *gstio;
1214 int len = sizeof buf;
1222 gstio = stab_io(gstab);
1223 nstio = stab_io(nstab);
1225 if (!gstio || !gstio->ifp)
1228 nstio = stab_io(nstab) = stio_new();
1229 else if (nstio->ifp)
1230 do_close(nstab,FALSE);
1232 fd = accept(fileno(gstio->ifp),buf,&len);
1235 nstio->ifp = fdopen(fd, "r");
1236 nstio->ofp = fdopen(fd, "w");
1239 str_nset(str, buf, len);
1244 warn("accept() on closed fd");
1246 str_sset(str,&str_undef);
1251 do_shutdown(stab, arglast)
1255 register STR **st = stack->ary_array;
1256 register int sp = arglast[1];
1257 register STIO *stio;
1263 stio = stab_io(stab);
1264 if (!stio || !stio->ifp)
1267 how = (int)str_gnum(st[++sp]);
1268 return shutdown(fileno(stio->ifp), how) >= 0;
1272 warn("shutdown() on closed fd");
1278 do_sopt(optype, stab, arglast)
1283 register STR **st = stack->ary_array;
1284 register int sp = arglast[1];
1285 register STIO *stio;
1293 stio = stab_io(stab);
1294 if (!stio || !stio->ifp)
1297 fd = fileno(stio->ifp);
1298 lvl = (int)str_gnum(st[sp+1]);
1299 optname = (int)str_gnum(st[sp+2]);
1302 st[sp] = str_2static(str_new(257));
1303 st[sp]->str_cur = 256;
1304 st[sp]->str_pok = 1;
1305 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1310 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1320 warn("[gs]etsockopt() on closed fd");
1321 st[sp] = &str_undef;
1327 do_getsockname(optype, stab, arglast)
1332 register STR **st = stack->ary_array;
1333 register int sp = arglast[1];
1334 register STIO *stio;
1340 stio = stab_io(stab);
1341 if (!stio || !stio->ifp)
1344 st[sp] = str_2static(str_new(257));
1345 st[sp]->str_cur = 256;
1346 st[sp]->str_pok = 1;
1347 fd = fileno(stio->ifp);
1350 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1354 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1363 warn("get{sock,peer}name() on closed fd");
1365 st[sp] = &str_undef;
1371 do_ghent(which,gimme,arglast)
1376 register ARRAY *ary = stack;
1377 register int sp = arglast[0];
1378 register char **elem;
1380 struct hostent *gethostbyname();
1381 struct hostent *gethostbyaddr();
1383 struct hostent *gethostent();
1385 struct hostent *hent;
1388 if (gimme != G_ARRAY) {
1389 astore(ary, ++sp, str_static(&str_undef));
1393 if (which == O_GHBYNAME) {
1394 char *name = str_get(ary->ary_array[sp+1]);
1396 hent = gethostbyname(name);
1398 else if (which == O_GHBYADDR) {
1399 STR *addrstr = ary->ary_array[sp+1];
1400 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1401 char *addr = str_get(addrstr);
1403 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1407 hent = gethostent();
1409 fatal("gethostent not implemented");
1413 (void)astore(ary, ++sp, str = str_static(&str_no));
1414 str_set(str, hent->h_name);
1415 (void)astore(ary, ++sp, str = str_static(&str_no));
1416 for (elem = hent->h_aliases; *elem; elem++) {
1417 str_cat(str, *elem);
1419 str_ncat(str," ",1);
1421 (void)astore(ary, ++sp, str = str_static(&str_no));
1422 str_numset(str, (double)hent->h_addrtype);
1423 (void)astore(ary, ++sp, str = str_static(&str_no));
1424 len = hent->h_length;
1425 str_numset(str, (double)len);
1427 for (elem = hent->h_addr_list; *elem; elem++) {
1428 (void)astore(ary, ++sp, str = str_static(&str_no));
1429 str_nset(str, *elem, len);
1432 (void)astore(ary, ++sp, str = str_static(&str_no));
1433 str_nset(str, hent->h_addr, len);
1438 (void)astore(ary, ++sp, str_static(&str_no));
1446 do_gnent(which,gimme,arglast)
1451 register ARRAY *ary = stack;
1452 register int sp = arglast[0];
1453 register char **elem;
1455 struct netent *getnetbyname();
1456 struct netent *getnetbyaddr();
1457 struct netent *getnetent();
1458 struct netent *nent;
1460 if (gimme != G_ARRAY) {
1461 astore(ary, ++sp, str_static(&str_undef));
1465 if (which == O_GNBYNAME) {
1466 char *name = str_get(ary->ary_array[sp+1]);
1468 nent = getnetbyname(name);
1470 else if (which == O_GNBYADDR) {
1471 STR *addrstr = ary->ary_array[sp+1];
1472 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1473 char *addr = str_get(addrstr);
1475 nent = getnetbyaddr(addr,addrtype);
1482 (void)astore(ary, ++sp, str = str_static(&str_no));
1483 str_set(str, nent->n_name);
1484 (void)astore(ary, ++sp, str = str_static(&str_no));
1485 for (elem = nent->n_aliases; *elem; elem++) {
1486 str_cat(str, *elem);
1488 str_ncat(str," ",1);
1490 (void)astore(ary, ++sp, str = str_static(&str_no));
1491 str_numset(str, (double)nent->n_addrtype);
1492 (void)astore(ary, ++sp, str = str_static(&str_no));
1493 str_numset(str, (double)nent->n_net);
1497 (void)astore(ary, ++sp, str_static(&str_no));
1505 do_gpent(which,gimme,arglast)
1510 register ARRAY *ary = stack;
1511 register int sp = arglast[0];
1512 register char **elem;
1514 struct protoent *getprotobyname();
1515 struct protoent *getprotobynumber();
1516 struct protoent *getprotoent();
1517 struct protoent *pent;
1519 if (gimme != G_ARRAY) {
1520 astore(ary, ++sp, str_static(&str_undef));
1524 if (which == O_GPBYNAME) {
1525 char *name = str_get(ary->ary_array[sp+1]);
1527 pent = getprotobyname(name);
1529 else if (which == O_GPBYNUMBER) {
1530 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1532 pent = getprotobynumber(proto);
1535 pent = getprotoent();
1539 (void)astore(ary, ++sp, str = str_static(&str_no));
1540 str_set(str, pent->p_name);
1541 (void)astore(ary, ++sp, str = str_static(&str_no));
1542 for (elem = pent->p_aliases; *elem; elem++) {
1543 str_cat(str, *elem);
1545 str_ncat(str," ",1);
1547 (void)astore(ary, ++sp, str = str_static(&str_no));
1548 str_numset(str, (double)pent->p_proto);
1552 (void)astore(ary, ++sp, str_static(&str_no));
1560 do_gsent(which,gimme,arglast)
1565 register ARRAY *ary = stack;
1566 register int sp = arglast[0];
1567 register char **elem;
1569 struct servent *getservbyname();
1570 struct servent *getservbynumber();
1571 struct servent *getservent();
1572 struct servent *sent;
1574 if (gimme != G_ARRAY) {
1575 astore(ary, ++sp, str_static(&str_undef));
1579 if (which == O_GSBYNAME) {
1580 char *name = str_get(ary->ary_array[sp+1]);
1581 char *proto = str_get(ary->ary_array[sp+2]);
1583 if (proto && !*proto)
1586 sent = getservbyname(name,proto);
1588 else if (which == O_GSBYPORT) {
1589 int port = (int)str_gnum(ary->ary_array[sp+1]);
1590 char *proto = str_get(ary->ary_array[sp+2]);
1592 sent = getservbyport(port,proto);
1595 sent = getservent();
1598 (void)astore(ary, ++sp, str = str_static(&str_no));
1599 str_set(str, sent->s_name);
1600 (void)astore(ary, ++sp, str = str_static(&str_no));
1601 for (elem = sent->s_aliases; *elem; elem++) {
1602 str_cat(str, *elem);
1604 str_ncat(str," ",1);
1606 (void)astore(ary, ++sp, str = str_static(&str_no));
1608 str_numset(str, (double)ntohs(sent->s_port));
1610 str_numset(str, (double)(sent->s_port));
1612 (void)astore(ary, ++sp, str = str_static(&str_no));
1613 str_set(str, sent->s_proto);
1617 (void)astore(ary, ++sp, str_static(&str_no));
1628 do_select(gimme,arglast)
1632 register STR **st = stack->ary_array;
1633 register int sp = arglast[0];
1641 struct timeval timebuf;
1642 struct timeval *tbuf = &timebuf;
1644 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1650 #if BYTEORDER & 0xf0000
1651 #define ORDERBYTE (0x88888888 - BYTEORDER)
1653 #define ORDERBYTE (0x4444 - BYTEORDER)
1658 for (i = 1; i <= 3; i++) {
1659 j = st[sp+i]->str_cur;
1664 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1665 growsize = maxlen; /* little endians can use vecs directly */
1673 masksize = NFDBITS / NBBY;
1675 masksize = sizeof(long); /* documented int, everyone seems to use long */
1677 growsize = maxlen + (masksize - (maxlen % masksize));
1678 Zero(&fd_sets[0], 4, char*);
1681 for (i = 1; i <= 3; i++) {
1686 Str_Grow(str,growsize);
1687 s = str_get(str) + j;
1688 while (++j <= growsize) {
1692 else if (str->str_ptr) {
1693 Safefree(str->str_ptr);
1694 str->str_ptr = Nullch;
1697 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1700 New(403, fd_sets[i], growsize, char);
1701 for (offset = 0; offset < growsize; offset += masksize) {
1702 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1703 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1709 if (str->str_nok || str->str_pok) {
1710 value = str_gnum(str);
1713 timebuf.tv_sec = (long)value;
1714 value -= (double)timebuf.tv_sec;
1715 timebuf.tv_usec = (long)(value * 1000000.0);
1718 tbuf = Null(struct timeval*);
1720 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1734 for (i = 1; i <= 3; i++) {
1738 for (offset = 0; offset < growsize; offset += masksize) {
1739 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1740 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1746 st[++sp] = str_static(&str_no);
1747 str_numset(st[sp], (double)nfound);
1748 if (gimme == G_ARRAY && tbuf) {
1749 value = (double)(timebuf.tv_sec) +
1750 (double)(timebuf.tv_usec) / 1000000.0;
1751 st[++sp] = str_static(&str_no);
1752 str_numset(st[sp], value);
1760 do_spair(stab1, stab2, arglast)
1765 register STR **st = stack->ary_array;
1766 register int sp = arglast[2];
1767 register STIO *stio1;
1768 register STIO *stio2;
1769 int domain, type, protocol, fd[2];
1771 if (!stab1 || !stab2)
1774 stio1 = stab_io(stab1);
1775 stio2 = stab_io(stab2);
1777 stio1 = stab_io(stab1) = stio_new();
1778 else if (stio1->ifp)
1779 do_close(stab1,FALSE);
1781 stio2 = stab_io(stab2) = stio_new();
1782 else if (stio2->ifp)
1783 do_close(stab2,FALSE);
1785 domain = (int)str_gnum(st[++sp]);
1786 type = (int)str_gnum(st[++sp]);
1787 protocol = (int)str_gnum(st[++sp]);
1789 taintproper("Insecure dependency in socketpair");
1792 if (socketpair(domain,type,protocol,fd) < 0)
1795 fatal("Socketpair unimplemented");
1797 stio1->ifp = fdopen(fd[0], "r");
1798 stio1->ofp = fdopen(fd[0], "w");
1800 stio2->ifp = fdopen(fd[1], "r");
1801 stio2->ofp = fdopen(fd[1], "w");
1810 do_gpwent(which,gimme,arglast)
1816 register ARRAY *ary = stack;
1817 register int sp = arglast[0];
1819 struct passwd *getpwnam();
1820 struct passwd *getpwuid();
1821 struct passwd *getpwent();
1822 struct passwd *pwent;
1824 if (gimme != G_ARRAY) {
1825 astore(ary, ++sp, str_static(&str_undef));
1829 if (which == O_GPWNAM) {
1830 char *name = str_get(ary->ary_array[sp+1]);
1832 pwent = getpwnam(name);
1834 else if (which == O_GPWUID) {
1835 int uid = (int)str_gnum(ary->ary_array[sp+1]);
1837 pwent = getpwuid(uid);
1843 (void)astore(ary, ++sp, str = str_static(&str_no));
1844 str_set(str, pwent->pw_name);
1845 (void)astore(ary, ++sp, str = str_static(&str_no));
1846 str_set(str, pwent->pw_passwd);
1847 (void)astore(ary, ++sp, str = str_static(&str_no));
1848 str_numset(str, (double)pwent->pw_uid);
1849 (void)astore(ary, ++sp, str = str_static(&str_no));
1850 str_numset(str, (double)pwent->pw_gid);
1851 (void)astore(ary, ++sp, str = str_static(&str_no));
1853 str_numset(str, (double)pwent->pw_change);
1856 str_numset(str, (double)pwent->pw_quota);
1859 str_set(str, pwent->pw_age);
1863 (void)astore(ary, ++sp, str = str_static(&str_no));
1865 str_set(str,pwent->pw_class);
1867 str_set(str, pwent->pw_comment);
1869 (void)astore(ary, ++sp, str = str_static(&str_no));
1870 str_set(str, pwent->pw_gecos);
1871 (void)astore(ary, ++sp, str = str_static(&str_no));
1872 str_set(str, pwent->pw_dir);
1873 (void)astore(ary, ++sp, str = str_static(&str_no));
1874 str_set(str, pwent->pw_shell);
1876 (void)astore(ary, ++sp, str = str_static(&str_no));
1877 str_numset(str, (double)pwent->pw_expire);
1883 fatal("password routines not implemented");
1888 do_ggrent(which,gimme,arglast)
1894 register ARRAY *ary = stack;
1895 register int sp = arglast[0];
1896 register char **elem;
1898 struct group *getgrnam();
1899 struct group *getgrgid();
1900 struct group *getgrent();
1901 struct group *grent;
1903 if (gimme != G_ARRAY) {
1904 astore(ary, ++sp, str_static(&str_undef));
1908 if (which == O_GGRNAM) {
1909 char *name = str_get(ary->ary_array[sp+1]);
1911 grent = getgrnam(name);
1913 else if (which == O_GGRGID) {
1914 int gid = (int)str_gnum(ary->ary_array[sp+1]);
1916 grent = getgrgid(gid);
1922 (void)astore(ary, ++sp, str = str_static(&str_no));
1923 str_set(str, grent->gr_name);
1924 (void)astore(ary, ++sp, str = str_static(&str_no));
1925 str_set(str, grent->gr_passwd);
1926 (void)astore(ary, ++sp, str = str_static(&str_no));
1927 str_numset(str, (double)grent->gr_gid);
1928 (void)astore(ary, ++sp, str = str_static(&str_no));
1929 for (elem = grent->gr_mem; *elem; elem++) {
1930 str_cat(str, *elem);
1932 str_ncat(str," ",1);
1938 fatal("group routines not implemented");
1943 do_dirop(optype,stab,gimme,arglast)
1949 #if defined(DIRENT) && defined(READDIR)
1950 register ARRAY *ary = stack;
1951 register STR **st = ary->ary_array;
1952 register int sp = arglast[1];
1953 register STIO *stio;
1958 struct DIRENT *readdir();
1959 register struct DIRENT *dp;
1963 if (!(stio = stab_io(stab)))
1964 stio = stab_io(stab) = stio_new();
1965 if (!stio->dirp && optype != O_OPENDIR)
1971 closedir(stio->dirp);
1972 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
1976 if (gimme == G_ARRAY) {
1978 while (dp = readdir(stio->dirp)) {
1980 (void)astore(ary,++sp,
1981 str_2static(str_make(dp->d_name,dp->d_namlen)));
1983 (void)astore(ary,++sp,
1984 str_2static(str_make(dp->d_name,0)));
1989 if (!(dp = readdir(stio->dirp)))
1991 st[sp] = str_static(&str_undef);
1993 str_nset(st[sp], dp->d_name, dp->d_namlen);
1995 str_set(st[sp], dp->d_name);
2005 st[sp] = str_static(&str_undef);
2006 str_numset(st[sp], (double)telldir(stio->dirp));
2009 st[sp] = str_static(&str_undef);
2010 along = (long)str_gnum(st[sp+1]);
2011 (void)seekdir(stio->dirp,along);
2015 st[sp] = str_static(&str_undef);
2016 (void)rewinddir(stio->dirp);
2019 st[sp] = str_static(&str_undef);
2020 (void)closedir(stio->dirp);
2027 st[sp] = &str_undef;
2031 fatal("Unimplemented directory operation");
2039 register STR **st = stack->ary_array;
2040 register int sp = arglast[1];
2041 register int items = arglast[2] - sp;
2044 register int tot = 0;
2048 for (st += ++sp; items--; st++)
2049 tainted |= (*st)->str_tainted;
2050 st = stack->ary_array;
2052 items = arglast[2] - sp;
2057 taintproper("Insecure dependency in chmod");
2061 val = (int)str_gnum(st[++sp]);
2063 if (chmod(str_get(st[++sp]),val))
2071 taintproper("Insecure dependency in chown");
2076 val = (int)str_gnum(st[++sp]);
2077 val2 = (int)str_gnum(st[++sp]);
2079 if (chown(str_get(st[++sp]),val,val2))
2088 taintproper("Insecure dependency in kill");
2092 s = str_get(st[++sp]);
2094 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2096 if (!(val = whichsig(s)))
2097 fatal("Unrecognized signal name \"%s\"",s);
2100 val = (int)str_gnum(st[sp]);
2104 int proc = (int)str_gnum(st[++sp]);
2106 if (killpg(proc,val)) /* BSD */
2108 if (kill(-proc,val)) /* SYSV */
2115 if (kill((int)(str_gnum(st[++sp])),val))
2124 taintproper("Insecure dependency in unlink");
2128 s = str_get(st[++sp]);
2129 if (euid || unsafe) {
2133 else { /* don't let root wipe out directories without -U */
2135 if (lstat(s,&statbuf) < 0 ||
2137 if (stat(s,&statbuf) < 0 ||
2139 (statbuf.st_mode & S_IFMT) == S_IFDIR )
2150 taintproper("Insecure dependency in utime");
2154 struct utimbuf utbuf;
2162 Zero(&utbuf, sizeof utbuf, char);
2163 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2164 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
2169 if (utime(str_get(st[++sp]),&utbuf))
2181 /* Do the permissions allow some operation? Assumes statcache already set. */
2184 cando(bit, effective, statbufp)
2187 register struct stat *statbufp;
2189 if ((effective ? euid : uid) == 0) { /* root is special */
2190 if (bit == S_IEXEC) {
2191 if (statbufp->st_mode & 0111 ||
2192 (statbufp->st_mode & S_IFMT) == S_IFDIR )
2196 return TRUE; /* root reads and writes anything */
2199 if (statbufp->st_uid == (effective ? euid : uid) ) {
2200 if (statbufp->st_mode & bit)
2201 return TRUE; /* ok as "user" */
2203 else if (ingroup((int)statbufp->st_gid,effective)) {
2204 if (statbufp->st_mode & bit >> 3)
2205 return TRUE; /* ok as "group" */
2207 else if (statbufp->st_mode & bit >> 6)
2208 return TRUE; /* ok as "other" */
2213 ingroup(testgid,effective)
2217 if (testgid == (effective ? egid : gid))
2224 GIDTYPE gary[NGROUPS];
2227 anum = getgroups(NGROUPS,gary);
2229 if (gary[anum] == testgid)