This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 3.0: (no announcement message available)
[perl5.git] / doio.c
CommitLineData
a687059c
LW
1/* $Header: doio.c,v 3.0 89/10/18 15:10:54 lwall Locked $
2 *
3 * Copyright (c) 1989, Larry Wall
4 *
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.
7 *
8 * $Log: doio.c,v $
9 * Revision 3.0 89/10/18 15:10:54 lwall
10 * 3.0 baseline
11 *
12 */
13
14#include "EXTERN.h"
15#include "perl.h"
16
17#ifdef SOCKET
18#include <sys/socket.h>
19#include <netdb.h>
20#endif
21
22#include <errno.h>
23#ifdef I_PWD
24#include <pwd.h>
25#endif
26#ifdef I_GRP
27#include <grp.h>
28#endif
29
30extern int errno;
31
32bool
33do_open(stab,name)
34STAB *stab;
35register char *name;
36{
37 FILE *fp;
38 int len = strlen(name);
39 register STIO *stio = stab_io(stab);
40 char *myname = savestr(name);
41 int result;
42 int fd;
43 int writing = 0;
44 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
45
46 name = myname;
47 forkprocess = 1; /* assume true if no fork */
48 while (len && isspace(name[len-1]))
49 name[--len] = '\0';
50 if (!stio)
51 stio = stab_io(stab) = stio_new();
52 else if (stio->ifp) {
53 fd = fileno(stio->ifp);
54 if (stio->type == '|')
55 result = mypclose(stio->ifp);
56 else if (stio->ifp != stio->ofp) {
57 if (stio->ofp)
58 fclose(stio->ofp);
59 result = fclose(stio->ifp);
60 }
61 else if (stio->type != '-')
62 result = fclose(stio->ifp);
63 else
64 result = 0;
65 if (result == EOF && fd > 2)
66 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
67 stab_name(stab));
68 stio->ofp = stio->ifp = Nullfp;
69 }
70 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
71 mode[1] = *name++;
72 mode[2] = '\0';
73 --len;
74 writing = 1;
75 }
76 else {
77 mode[1] = '\0';
78 }
79 stio->type = *name;
80 if (*name == '|') {
81 for (name++; isspace(*name); name++) ;
82#ifdef TAINT
83 taintenv();
84 taintproper("Insecure dependency in piped open");
85#endif
86 fp = mypopen(name,"w");
87 writing = 1;
88 }
89 else if (*name == '>' && name[1] == '>') {
90#ifdef TAINT
91 taintproper("Insecure dependency in open");
92#endif
93 mode[0] = stio->type = 'a';
94 for (name += 2; isspace(*name); name++) ;
95 fp = fopen(name, mode);
96 writing = 1;
97 }
98 else if (*name == '>' && name[1] == '&') {
99#ifdef TAINT
100 taintproper("Insecure dependency in open");
101#endif
102 for (name += 2; isspace(*name); name++) ;
103 if (isdigit(*name))
104 fd = atoi(name);
105 else {
106 stab = stabent(name,FALSE);
107 if (stab_io(stab) && stab_io(stab)->ifp) {
108 fd = fileno(stab_io(stab)->ifp);
109 stio->type = stab_io(stab)->type;
110 }
111 else
112 fd = -1;
113 }
114 fp = fdopen(dup(fd),stio->type == 'a' ? "a" :
115 (stio->type == '<' ? "r" : "w") );
116 writing = 1;
117 }
118 else if (*name == '>') {
119#ifdef TAINT
120 taintproper("Insecure dependency in open");
121#endif
122 for (name++; isspace(*name); name++) ;
123 if (strEQ(name,"-")) {
124 fp = stdout;
125 stio->type = '-';
126 }
127 else {
128 mode[0] = 'w';
129 fp = fopen(name,mode);
130 }
131 writing = 1;
132 }
133 else {
134 if (*name == '<') {
135 for (name++; isspace(*name); name++) ;
136 if (strEQ(name,"-")) {
137 fp = stdin;
138 stio->type = '-';
139 }
140 else {
141 mode[0] = 'r';
142 fp = fopen(name,mode);
143 }
144 }
145 else if (name[len-1] == '|') {
146#ifdef TAINT
147 taintenv();
148 taintproper("Insecure dependency in piped open");
149#endif
150 name[--len] = '\0';
151 while (len && isspace(name[len-1]))
152 name[--len] = '\0';
153 for (; isspace(*name); name++) ;
154 fp = mypopen(name,"r");
155 stio->type = '|';
156 }
157 else {
158 stio->type = '<';
159 for (; isspace(*name); name++) ;
160 if (strEQ(name,"-")) {
161 fp = stdin;
162 stio->type = '-';
163 }
164 else
165 fp = fopen(name,"r");
166 }
167 }
168 Safefree(myname);
169 if (!fp)
170 return FALSE;
171 if (stio->type &&
172 stio->type != '|' && stio->type != '-') {
173 if (fstat(fileno(fp),&statbuf) < 0) {
174 (void)fclose(fp);
175 return FALSE;
176 }
177 if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
178#ifdef S_IFSOCK
179 (statbuf.st_mode & S_IFMT) != S_IFSOCK &&
180#endif
181#ifdef S_IFFIFO
182 (statbuf.st_mode & S_IFMT) != S_IFFIFO &&
183#endif
184 (statbuf.st_mode & S_IFMT) != S_IFCHR) {
185 (void)fclose(fp);
186 return FALSE;
187 }
188 }
189 stio->ifp = fp;
190 if (writing)
191 stio->ofp = fp;
192 return TRUE;
193}
194
195FILE *
196nextargv(stab)
197register STAB *stab;
198{
199 register STR *str;
200 char *oldname;
201 int filemode,fileuid,filegid;
202
203 while (alen(stab_xarray(stab)) >= 0) {
204 str = ashift(stab_xarray(stab));
205 str_sset(stab_val(stab),str);
206 STABSET(stab_val(stab));
207 oldname = str_get(stab_val(stab));
208 if (do_open(stab,oldname)) {
209 if (inplace) {
210#ifdef TAINT
211 taintproper("Insecure dependency in inplace open");
212#endif
213 filemode = statbuf.st_mode;
214 fileuid = statbuf.st_uid;
215 filegid = statbuf.st_gid;
216 if (*inplace) {
217 str_cat(str,inplace);
218#ifdef RENAME
219 (void)rename(oldname,str->str_ptr);
220#else
221 (void)UNLINK(str->str_ptr);
222 (void)link(oldname,str->str_ptr);
223 (void)UNLINK(oldname);
224#endif
225 }
226 else {
227 (void)UNLINK(oldname);
228 }
229
230 str_nset(str,">",1);
231 str_cat(str,oldname);
232 errno = 0; /* in case sprintf set errno */
233 if (!do_open(argvoutstab,str->str_ptr))
234 fatal("Can't do inplace edit");
235 defoutstab = argvoutstab;
236#ifdef FCHMOD
237 (void)fchmod(fileno(stab_io(argvoutstab)->ifp),filemode);
238#else
239 (void)chmod(oldname,filemode);
240#endif
241#ifdef FCHOWN
242 (void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
243#else
244 (void)chown(oldname,fileuid,filegid);
245#endif
246 }
247 str_free(str);
248 return stab_io(stab)->ifp;
249 }
250 else
251 fprintf(stderr,"Can't open %s\n",str_get(str));
252 str_free(str);
253 }
254 if (inplace) {
255 (void)do_close(argvoutstab,FALSE);
256 defoutstab = stabent("STDOUT",TRUE);
257 }
258 return Nullfp;
259}
260
261bool
262do_close(stab,explicit)
263STAB *stab;
264bool explicit;
265{
266 bool retval = FALSE;
267 register STIO *stio = stab_io(stab);
268 int status;
269
270 if (!stio) { /* never opened */
271 if (dowarn && explicit)
272 warn("Close on unopened file <%s>",stab_name(stab));
273 return FALSE;
274 }
275 if (stio->ifp) {
276 if (stio->type == '|') {
277 status = mypclose(stio->ifp);
278 retval = (status >= 0);
279 statusvalue = (unsigned)status & 0xffff;
280 }
281 else if (stio->type == '-')
282 retval = TRUE;
283 else {
284 if (stio->ofp && stio->ofp != stio->ifp) /* a socket */
285 fclose(stio->ofp);
286 retval = (fclose(stio->ifp) != EOF);
287 }
288 stio->ofp = stio->ifp = Nullfp;
289 }
290 if (explicit)
291 stio->lines = 0;
292 stio->type = ' ';
293 return retval;
294}
295
296bool
297do_eof(stab)
298STAB *stab;
299{
300 register STIO *stio;
301 int ch;
302
303 if (!stab) { /* eof() */
304 if (argvstab)
305 stio = stab_io(argvstab);
306 else
307 return TRUE;
308 }
309 else
310 stio = stab_io(stab);
311
312 if (!stio)
313 return TRUE;
314
315 while (stio->ifp) {
316
317#ifdef STDSTDIO /* (the code works without this) */
318 if (stio->ifp->_cnt > 0) /* cheat a little, since */
319 return FALSE; /* this is the most usual case */
320#endif
321
322 ch = getc(stio->ifp);
323 if (ch != EOF) {
324 (void)ungetc(ch, stio->ifp);
325 return FALSE;
326 }
327 if (!stab) { /* not necessarily a real EOF yet? */
328 if (!nextargv(argvstab)) /* get another fp handy */
329 return TRUE;
330 }
331 else
332 return TRUE; /* normal fp, definitely end of file */
333 }
334 return TRUE;
335}
336
337long
338do_tell(stab)
339STAB *stab;
340{
341 register STIO *stio;
342
343 if (!stab)
344 goto phooey;
345
346 stio = stab_io(stab);
347 if (!stio || !stio->ifp)
348 goto phooey;
349
350 if (feof(stio->ifp))
351 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
352
353 return ftell(stio->ifp);
354
355phooey:
356 if (dowarn)
357 warn("tell() on unopened file");
358 return -1L;
359}
360
361bool
362do_seek(stab, pos, whence)
363STAB *stab;
364long pos;
365int whence;
366{
367 register STIO *stio;
368
369 if (!stab)
370 goto nuts;
371
372 stio = stab_io(stab);
373 if (!stio || !stio->ifp)
374 goto nuts;
375
376 if (feof(stio->ifp))
377 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
378
379 return fseek(stio->ifp, pos, whence) >= 0;
380
381nuts:
382 if (dowarn)
383 warn("seek() on unopened file");
384 return FALSE;
385}
386
387int
388do_ctl(optype,stab,func,argstr)
389int optype;
390STAB *stab;
391int func;
392STR *argstr;
393{
394 register STIO *stio;
395 register char *s;
396 int retval;
397
398 if (!stab || !argstr)
399 return -1;
400 stio = stab_io(stab);
401 if (!stio)
402 return -1;
403
404 if (argstr->str_pok || !argstr->str_nok) {
405 if (!argstr->str_pok)
406 s = str_get(argstr);
407
408#ifdef IOCPARM_MASK
409#ifndef IOCPARM_LEN
410#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
411#endif
412#endif
413#ifdef IOCPARM_LEN
414 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
415#else
416 retval = 256; /* otherwise guess at what's safe */
417#endif
418 if (argstr->str_cur < retval) {
419 str_grow(argstr,retval+1);
420 argstr->str_cur = retval;
421 }
422
423 s = argstr->str_ptr;
424 s[argstr->str_cur] = 17; /* a little sanity check here */
425 }
426 else {
427 retval = (int)str_gnum(argstr);
428 s = (char*)retval; /* ouch */
429 }
430
431#ifndef lint
432 if (optype == O_IOCTL)
433 retval = ioctl(fileno(stio->ifp), func, s);
434 else
435#ifdef I_FCNTL
436 retval = fcntl(fileno(stio->ifp), func, s);
437#else
438 fatal("fcntl is not implemented");
439#endif
440#else /* lint */
441 retval = 0;
442#endif /* lint */
443
444 if (argstr->str_pok) {
445 if (s[argstr->str_cur] != 17)
446 fatal("Return value overflowed string");
447 s[argstr->str_cur] = 0; /* put our null back */
448 }
449 return retval;
450}
451
452int
453do_stat(str,arg,gimme,arglast)
454STR *str;
455register ARG *arg;
456int gimme;
457int *arglast;
458{
459 register ARRAY *ary = stack;
460 register int sp = arglast[0] + 1;
461 int max = 13;
462 register int i;
463
464 if ((arg[1].arg_type & A_MASK) == A_WORD) {
465 tmpstab = arg[1].arg_ptr.arg_stab;
466 if (tmpstab != defstab) {
467 statstab = tmpstab;
468 str_set(statname,"");
469 if (!stab_io(tmpstab) ||
470 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
471 max = 0;
472 }
473 }
474 }
475 else {
476 str_sset(statname,ary->ary_array[sp]);
477 statstab = Nullstab;
478#ifdef SYMLINK
479 if (arg->arg_type == O_LSTAT)
480 i = lstat(str_get(statname),&statcache);
481 else
482#endif
483 i = stat(str_get(statname),&statcache);
484 if (i < 0)
485 max = 0;
486 }
487
488 if (gimme != G_ARRAY) {
489 if (max)
490 str_sset(str,&str_yes);
491 else
492 str_sset(str,&str_undef);
493 STABSET(str);
494 ary->ary_array[sp] = str;
495 return sp;
496 }
497 sp--;
498 if (max) {
499#ifndef lint
500 (void)astore(ary,++sp,
501 str_2static(str_nmake((double)statcache.st_dev)));
502 (void)astore(ary,++sp,
503 str_2static(str_nmake((double)statcache.st_ino)));
504 (void)astore(ary,++sp,
505 str_2static(str_nmake((double)statcache.st_mode)));
506 (void)astore(ary,++sp,
507 str_2static(str_nmake((double)statcache.st_nlink)));
508 (void)astore(ary,++sp,
509 str_2static(str_nmake((double)statcache.st_uid)));
510 (void)astore(ary,++sp,
511 str_2static(str_nmake((double)statcache.st_gid)));
512 (void)astore(ary,++sp,
513 str_2static(str_nmake((double)statcache.st_rdev)));
514 (void)astore(ary,++sp,
515 str_2static(str_nmake((double)statcache.st_size)));
516 (void)astore(ary,++sp,
517 str_2static(str_nmake((double)statcache.st_atime)));
518 (void)astore(ary,++sp,
519 str_2static(str_nmake((double)statcache.st_mtime)));
520 (void)astore(ary,++sp,
521 str_2static(str_nmake((double)statcache.st_ctime)));
522#ifdef STATBLOCKS
523 (void)astore(ary,++sp,
524 str_2static(str_nmake((double)statcache.st_blksize)));
525 (void)astore(ary,++sp,
526 str_2static(str_nmake((double)statcache.st_blocks)));
527#else
528 (void)astore(ary,++sp,
529 str_2static(str_make("",0)));
530 (void)astore(ary,++sp,
531 str_2static(str_make("",0)));
532#endif
533#else /* lint */
534 (void)astore(ary,++sp,str_nmake(0.0));
535#endif /* lint */
536 }
537 return sp;
538}
539
540int
541looks_like_number(str)
542STR *str;
543{
544 register char *s;
545 register char *send;
546
547 if (!str->str_pok)
548 return TRUE;
549 s = str->str_ptr;
550 send = s + str->str_cur;
551 while (isspace(*s))
552 s++;
553 if (s >= send)
554 return FALSE;
555 if (*s == '+' || *s == '-')
556 s++;
557 while (isdigit(*s))
558 s++;
559 if (s == send)
560 return TRUE;
561 if (*s == '.')
562 s++;
563 else if (s == str->str_ptr)
564 return FALSE;
565 while (isdigit(*s))
566 s++;
567 if (s == send)
568 return TRUE;
569 if (*s == 'e' || *s == 'E') {
570 s++;
571 if (*s == '+' || *s == '-')
572 s++;
573 while (isdigit(*s))
574 s++;
575 }
576 while (isspace(*s))
577 s++;
578 if (s >= send)
579 return TRUE;
580 return FALSE;
581}
582
583bool
584do_print(str,fp)
585register STR *str;
586FILE *fp;
587{
588 register char *tmps;
589
590 if (!fp) {
591 if (dowarn)
592 warn("print to unopened file");
593 return FALSE;
594 }
595 if (!str)
596 return FALSE;
597 if (ofmt &&
598 ((str->str_nok && str->str_u.str_nval != 0.0)
599 || (looks_like_number(str) && str_gnum(str) != 0.0) ) )
600 fprintf(fp, ofmt, str->str_u.str_nval);
601 else {
602 tmps = str_get(str);
603 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'a' && tmps[3] == 'b'
604 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
605 tmps = stab_name(((STAB*)str)); /* a stab value, be nice */
606 str = ((STAB*)str)->str_magic;
607 putc('*',fp);
608 }
609 if (str->str_cur && fwrite(tmps,1,str->str_cur,fp) == 0)
610 return FALSE;
611 }
612 return TRUE;
613}
614
615bool
616do_aprint(arg,fp,arglast)
617register ARG *arg;
618register FILE *fp;
619int *arglast;
620{
621 register STR **st = stack->ary_array;
622 register int sp = arglast[1];
623 register int retval;
624 register int items = arglast[2] - sp;
625
626 if (!fp) {
627 if (dowarn)
628 warn("print to unopened file");
629 return FALSE;
630 }
631 st += ++sp;
632 if (arg->arg_type == O_PRTF) {
633 do_sprintf(arg->arg_ptr.arg_str,items,st);
634 retval = do_print(arg->arg_ptr.arg_str,fp);
635 }
636 else {
637 retval = (items <= 0);
638 for (; items > 0; items--,st++) {
639 if (retval && ofslen) {
640 if (fwrite(ofs, 1, ofslen, fp) == 0) {
641 retval = FALSE;
642 break;
643 }
644 }
645 if (!(retval = do_print(*st, fp)))
646 break;
647 }
648 if (retval && orslen)
649 if (fwrite(ors, 1, orslen, fp) == 0)
650 retval = FALSE;
651 }
652 return retval;
653}
654
655int
656mystat(arg,str)
657ARG *arg;
658STR *str;
659{
660 STIO *stio;
661
662 if (arg[1].arg_type & A_DONT) {
663 stio = stab_io(arg[1].arg_ptr.arg_stab);
664 if (stio && stio->ifp) {
665 statstab = arg[1].arg_ptr.arg_stab;
666 str_set(statname,"");
667 return fstat(fileno(stio->ifp), &statcache);
668 }
669 else {
670 if (arg[1].arg_ptr.arg_stab == defstab)
671 return 0;
672 if (dowarn)
673 warn("Stat on unopened file <%s>",
674 stab_name(arg[1].arg_ptr.arg_stab));
675 statstab = Nullstab;
676 str_set(statname,"");
677 return -1;
678 }
679 }
680 else {
681 statstab = Nullstab;
682 str_sset(statname,str);
683 return stat(str_get(str),&statcache);
684 }
685}
686
687STR *
688do_fttext(arg,str)
689register ARG *arg;
690STR *str;
691{
692 int i;
693 int len;
694 int odd = 0;
695 STDCHAR tbuf[512];
696 register STDCHAR *s;
697 register STIO *stio;
698
699 if (arg[1].arg_type & A_DONT) {
700 if (arg[1].arg_ptr.arg_stab == defstab) {
701 if (statstab)
702 stio = stab_io(statstab);
703 else {
704 str = statname;
705 goto really_filename;
706 }
707 }
708 else {
709 statstab = arg[1].arg_ptr.arg_stab;
710 str_set(statname,"");
711 stio = stab_io(statstab);
712 }
713 if (stio && stio->ifp) {
714#ifdef STDSTDIO
715 fstat(fileno(stio->ifp),&statcache);
716 if (stio->ifp->_cnt <= 0) {
717 i = getc(stio->ifp);
718 if (i != EOF)
719 (void)ungetc(i,stio->ifp);
720 }
721 if (stio->ifp->_cnt <= 0) /* null file is anything */
722 return &str_yes;
723 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
724 s = stio->ifp->_base;
725#else
726 fatal("-T and -B not implemented on filehandles\n");
727#endif
728 }
729 else {
730 if (dowarn)
731 warn("Test on unopened file <%s>",
732 stab_name(arg[1].arg_ptr.arg_stab));
733 return &str_undef;
734 }
735 }
736 else {
737 statstab = Nullstab;
738 str_sset(statname,str);
739 really_filename:
740 i = open(str_get(str),0);
741 if (i < 0)
742 return &str_undef;
743 fstat(i,&statcache);
744 len = read(i,tbuf,512);
745 if (len <= 0) /* null file is anything */
746 return &str_yes;
747 (void)close(i);
748 s = tbuf;
749 }
750
751 /* now scan s to look for textiness */
752
753 for (i = 0; i < len; i++,s++) {
754 if (!*s) { /* null never allowed in text */
755 odd += len;
756 break;
757 }
758 else if (*s & 128)
759 odd++;
760 else if (*s < 32 &&
761 *s != '\n' && *s != '\r' && *s != '\b' &&
762 *s != '\t' && *s != '\f' && *s != 27)
763 odd++;
764 }
765
766 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
767 return &str_no;
768 else
769 return &str_yes;
770}
771
772bool
773do_aexec(really,arglast)
774STR *really;
775int *arglast;
776{
777 register STR **st = stack->ary_array;
778 register int sp = arglast[1];
779 register int items = arglast[2] - sp;
780 register char **a;
781 char **argv;
782 char *tmps;
783
784 if (items) {
785 New(401,argv, items+1, char*);
786 a = argv;
787 for (st += ++sp; items > 0; items--,st++) {
788 if (*st)
789 *a++ = str_get(*st);
790 else
791 *a++ = "";
792 }
793 *a = Nullch;
794#ifdef TAINT
795 if (*argv[0] != '/') /* will execvp use PATH? */
796 taintenv(); /* testing IFS here is overkill, probably */
797#endif
798 if (really && *(tmps = str_get(really)))
799 execvp(tmps,argv);
800 else
801 execvp(argv[0],argv);
802 Safefree(argv);
803 }
804 return FALSE;
805}
806
807bool
808do_exec(cmd)
809char *cmd;
810{
811 register char **a;
812 register char *s;
813 char **argv;
814 char flags[10];
815
816#ifdef TAINT
817 taintenv();
818 taintproper("Insecure dependency in exec");
819#endif
820
821 /* save an extra exec if possible */
822
823 if (csh > 0 && strnEQ(cmd,"/bin/csh -c",11)) {
824 strcpy(flags,"-c");
825 s = cmd+11;
826 if (*s == 'f') {
827 s++;
828 strcat(flags,"f");
829 }
830 if (*s == ' ')
831 s++;
832 if (*s++ == '\'') {
833 char *ncmd = s;
834
835 while (*s)
836 s++;
837 if (s[-1] == '\n')
838 *--s = '\0';
839 if (s[-1] == '\'') {
840 *--s = '\0';
841 execl("/bin/csh","csh", flags,ncmd,(char*)0);
842 *s = '\'';
843 return FALSE;
844 }
845 }
846 }
847
848 /* see if there are shell metacharacters in it */
849
850 for (s = cmd; *s; s++) {
851 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
852 if (*s == '\n' && !s[1]) {
853 *s = '\0';
854 break;
855 }
856 doshell:
857 execl("/bin/sh","sh","-c",cmd,(char*)0);
858 return FALSE;
859 }
860 }
861 New(402,argv, (s - cmd) / 2 + 2, char*);
862
863 a = argv;
864 for (s = cmd; *s;) {
865 while (*s && isspace(*s)) s++;
866 if (*s)
867 *(a++) = s;
868 while (*s && !isspace(*s)) s++;
869 if (*s)
870 *s++ = '\0';
871 }
872 *a = Nullch;
873 if (argv[0]) {
874 execvp(argv[0],argv);
875 if (errno == ENOEXEC) /* for system V NIH syndrome */
876 goto doshell;
877 }
878 Safefree(argv);
879 return FALSE;
880}
881
882#ifdef SOCKET
883int
884do_socket(stab, arglast)
885STAB *stab;
886int *arglast;
887{
888 register STR **st = stack->ary_array;
889 register int sp = arglast[1];
890 register STIO *stio;
891 int domain, type, protocol, fd;
892
893 if (!stab)
894 return FALSE;
895
896 stio = stab_io(stab);
897 if (!stio)
898 stio = stab_io(stab) = stio_new();
899 else if (stio->ifp)
900 do_close(stab,FALSE);
901
902 domain = (int)str_gnum(st[++sp]);
903 type = (int)str_gnum(st[++sp]);
904 protocol = (int)str_gnum(st[++sp]);
905#ifdef TAINT
906 taintproper("Insecure dependency in socket");
907#endif
908 fd = socket(domain,type,protocol);
909 if (fd < 0)
910 return FALSE;
911 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
912 stio->ofp = fdopen(fd, "w");
913 stio->type = 's';
914
915 return TRUE;
916}
917
918int
919do_bind(stab, arglast)
920STAB *stab;
921int *arglast;
922{
923 register STR **st = stack->ary_array;
924 register int sp = arglast[1];
925 register STIO *stio;
926 char *addr;
927
928 if (!stab)
929 goto nuts;
930
931 stio = stab_io(stab);
932 if (!stio || !stio->ifp)
933 goto nuts;
934
935 addr = str_get(st[++sp]);
936#ifdef TAINT
937 taintproper("Insecure dependency in bind");
938#endif
939 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
940
941nuts:
942 if (dowarn)
943 warn("bind() on closed fd");
944 return FALSE;
945
946}
947
948int
949do_connect(stab, arglast)
950STAB *stab;
951int *arglast;
952{
953 register STR **st = stack->ary_array;
954 register int sp = arglast[1];
955 register STIO *stio;
956 char *addr;
957
958 if (!stab)
959 goto nuts;
960
961 stio = stab_io(stab);
962 if (!stio || !stio->ifp)
963 goto nuts;
964
965 addr = str_get(st[++sp]);
966#ifdef TAINT
967 taintproper("Insecure dependency in connect");
968#endif
969 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
970
971nuts:
972 if (dowarn)
973 warn("connect() on closed fd");
974 return FALSE;
975
976}
977
978int
979do_listen(stab, arglast)
980STAB *stab;
981int *arglast;
982{
983 register STR **st = stack->ary_array;
984 register int sp = arglast[1];
985 register STIO *stio;
986 int backlog;
987
988 if (!stab)
989 goto nuts;
990
991 stio = stab_io(stab);
992 if (!stio || !stio->ifp)
993 goto nuts;
994
995 backlog = (int)str_gnum(st[++sp]);
996 return listen(fileno(stio->ifp), backlog) >= 0;
997
998nuts:
999 if (dowarn)
1000 warn("listen() on closed fd");
1001 return FALSE;
1002}
1003
1004void
1005do_accept(str, nstab, gstab)
1006STR *str;
1007STAB *nstab;
1008STAB *gstab;
1009{
1010 register STIO *nstio;
1011 register STIO *gstio;
1012 int len = sizeof buf;
1013 int fd;
1014
1015 if (!nstab)
1016 goto badexit;
1017 if (!gstab)
1018 goto nuts;
1019
1020 gstio = stab_io(gstab);
1021 nstio = stab_io(nstab);
1022
1023 if (!gstio || !gstio->ifp)
1024 goto nuts;
1025 if (!nstio)
1026 nstio = stab_io(nstab) = stio_new();
1027 else if (nstio->ifp)
1028 do_close(nstab,FALSE);
1029
1030 fd = accept(fileno(gstio->ifp),buf,&len);
1031 if (fd < 0)
1032 goto badexit;
1033 nstio->ifp = fdopen(fd, "r");
1034 nstio->ofp = fdopen(fd, "w");
1035 nstio->type = 's';
1036
1037 str_nset(str, buf, len);
1038 return;
1039
1040nuts:
1041 if (dowarn)
1042 warn("accept() on closed fd");
1043badexit:
1044 str_sset(str,&str_undef);
1045 return;
1046}
1047
1048int
1049do_shutdown(stab, arglast)
1050STAB *stab;
1051int *arglast;
1052{
1053 register STR **st = stack->ary_array;
1054 register int sp = arglast[1];
1055 register STIO *stio;
1056 int how;
1057
1058 if (!stab)
1059 goto nuts;
1060
1061 stio = stab_io(stab);
1062 if (!stio || !stio->ifp)
1063 goto nuts;
1064
1065 how = (int)str_gnum(st[++sp]);
1066 return shutdown(fileno(stio->ifp), how) >= 0;
1067
1068nuts:
1069 if (dowarn)
1070 warn("shutdown() on closed fd");
1071 return FALSE;
1072
1073}
1074
1075int
1076do_sopt(optype, stab, arglast)
1077int optype;
1078STAB *stab;
1079int *arglast;
1080{
1081 register STR **st = stack->ary_array;
1082 register int sp = arglast[1];
1083 register STIO *stio;
1084 int fd;
1085 int lvl;
1086 int optname;
1087
1088 if (!stab)
1089 goto nuts;
1090
1091 stio = stab_io(stab);
1092 if (!stio || !stio->ifp)
1093 goto nuts;
1094
1095 fd = fileno(stio->ifp);
1096 lvl = (int)str_gnum(st[sp+1]);
1097 optname = (int)str_gnum(st[sp+2]);
1098 switch (optype) {
1099 case O_GSOCKOPT:
1100 st[sp] = str_2static(str_new(257));
1101 st[sp]->str_cur = 256;
1102 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1103 goto nuts;
1104 break;
1105 case O_SSOCKOPT:
1106 st[sp] = st[sp+3];
1107 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1108 goto nuts;
1109 st[sp] = &str_yes;
1110 break;
1111 }
1112
1113 return sp;
1114
1115nuts:
1116 if (dowarn)
1117 warn("shutdown() on closed fd");
1118 st[sp] = &str_undef;
1119 return sp;
1120
1121}
1122
1123int
1124do_getsockname(optype, stab, arglast)
1125int optype;
1126STAB *stab;
1127int *arglast;
1128{
1129 register STR **st = stack->ary_array;
1130 register int sp = arglast[1];
1131 register STIO *stio;
1132 int fd;
1133
1134 if (!stab)
1135 goto nuts;
1136
1137 stio = stab_io(stab);
1138 if (!stio || !stio->ifp)
1139 goto nuts;
1140
1141 st[sp] = str_2static(str_new(257));
1142 st[sp]->str_cur = 256;
1143 fd = fileno(stio->ifp);
1144 switch (optype) {
1145 case O_GETSOCKNAME:
1146 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1147 goto nuts;
1148 break;
1149 case O_GETPEERNAME:
1150 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1151 goto nuts;
1152 break;
1153 }
1154
1155 return sp;
1156
1157nuts:
1158 if (dowarn)
1159 warn("shutdown() on closed fd");
1160 st[sp] = &str_undef;
1161 return sp;
1162
1163}
1164
1165int
1166do_ghent(which,gimme,arglast)
1167int which;
1168int gimme;
1169int *arglast;
1170{
1171 register ARRAY *ary = stack;
1172 register int sp = arglast[0];
1173 register char **elem;
1174 register STR *str;
1175 struct hostent *gethostbynam();
1176 struct hostent *gethostbyaddr();
1177#ifdef GETHOSTENT
1178 struct hostent *gethostent();
1179#endif
1180 struct hostent *hent;
1181 unsigned long len;
1182
1183 if (gimme != G_ARRAY) {
1184 astore(ary, ++sp, str_static(&str_undef));
1185 return sp;
1186 }
1187
1188 if (which == O_GHBYNAME) {
1189 char *name = str_get(ary->ary_array[sp+1]);
1190
1191 hent = gethostbyname(name);
1192 }
1193 else if (which == O_GHBYADDR) {
1194 STR *addrstr = ary->ary_array[sp+1];
1195 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1196 char *addr = str_get(addrstr);
1197
1198 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1199 }
1200 else
1201#ifdef GETHOSTENT
1202 hent = gethostent();
1203#else
1204 fatal("gethostent not implemented");
1205#endif
1206 if (hent) {
1207#ifndef lint
1208 (void)astore(ary, ++sp, str = str_static(&str_no));
1209 str_set(str, hent->h_name);
1210 (void)astore(ary, ++sp, str = str_static(&str_no));
1211 for (elem = hent->h_aliases; *elem; elem++) {
1212 str_cat(str, *elem);
1213 if (elem[1])
1214 str_ncat(str," ",1);
1215 }
1216 (void)astore(ary, ++sp, str = str_static(&str_no));
1217 str_numset(str, (double)hent->h_addrtype);
1218 (void)astore(ary, ++sp, str = str_static(&str_no));
1219 len = hent->h_length;
1220 str_numset(str, (double)len);
1221#ifdef h_addr
1222 for (elem = hent->h_addr_list; *elem; elem++) {
1223 (void)astore(ary, ++sp, str = str_static(&str_no));
1224 str_nset(str, *elem, len);
1225 }
1226#else
1227 (void)astore(ary, ++sp, str = str_static(&str_no));
1228 str_nset(str, hent->h_addr, len);
1229#endif /* h_addr */
1230#else /* lint */
1231 elem = Nullch;
1232 elem = elem;
1233 (void)astore(ary, ++sp, str_static(&str_no));
1234#endif /* lint */
1235 }
1236
1237 return sp;
1238}
1239
1240int
1241do_gnent(which,gimme,arglast)
1242int which;
1243int gimme;
1244int *arglast;
1245{
1246 register ARRAY *ary = stack;
1247 register int sp = arglast[0];
1248 register char **elem;
1249 register STR *str;
1250 struct netent *getnetbyname();
1251 struct netent *getnetbyaddr();
1252 struct netent *getnetent();
1253 struct netent *nent;
1254
1255 if (gimme != G_ARRAY) {
1256 astore(ary, ++sp, str_static(&str_undef));
1257 return sp;
1258 }
1259
1260 if (which == O_GNBYNAME) {
1261 char *name = str_get(ary->ary_array[sp+1]);
1262
1263 nent = getnetbyname(name);
1264 }
1265 else if (which == O_GNBYADDR) {
1266 STR *addrstr = ary->ary_array[sp+1];
1267 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1268 char *addr = str_get(addrstr);
1269
1270 nent = getnetbyaddr(addr,addrtype);
1271 }
1272 else
1273 nent = getnetent();
1274
1275 if (nent) {
1276#ifndef lint
1277 (void)astore(ary, ++sp, str = str_static(&str_no));
1278 str_set(str, nent->n_name);
1279 (void)astore(ary, ++sp, str = str_static(&str_no));
1280 for (elem = nent->n_aliases; *elem; elem++) {
1281 str_cat(str, *elem);
1282 if (elem[1])
1283 str_ncat(str," ",1);
1284 }
1285 (void)astore(ary, ++sp, str = str_static(&str_no));
1286 str_numset(str, (double)nent->n_addrtype);
1287 (void)astore(ary, ++sp, str = str_static(&str_no));
1288 str_numset(str, (double)nent->n_net);
1289#else /* lint */
1290 elem = Nullch;
1291 elem = elem;
1292 (void)astore(ary, ++sp, str_static(&str_no));
1293#endif /* lint */
1294 }
1295
1296 return sp;
1297}
1298
1299int
1300do_gpent(which,gimme,arglast)
1301int which;
1302int gimme;
1303int *arglast;
1304{
1305 register ARRAY *ary = stack;
1306 register int sp = arglast[0];
1307 register char **elem;
1308 register STR *str;
1309 struct protoent *getprotobyname();
1310 struct protoent *getprotobynumber();
1311 struct protoent *getprotoent();
1312 struct protoent *pent;
1313
1314 if (gimme != G_ARRAY) {
1315 astore(ary, ++sp, str_static(&str_undef));
1316 return sp;
1317 }
1318
1319 if (which == O_GPBYNAME) {
1320 char *name = str_get(ary->ary_array[sp+1]);
1321
1322 pent = getprotobyname(name);
1323 }
1324 else if (which == O_GPBYNUMBER) {
1325 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1326
1327 pent = getprotobynumber(proto);
1328 }
1329 else
1330 pent = getprotoent();
1331
1332 if (pent) {
1333#ifndef lint
1334 (void)astore(ary, ++sp, str = str_static(&str_no));
1335 str_set(str, pent->p_name);
1336 (void)astore(ary, ++sp, str = str_static(&str_no));
1337 for (elem = pent->p_aliases; *elem; elem++) {
1338 str_cat(str, *elem);
1339 if (elem[1])
1340 str_ncat(str," ",1);
1341 }
1342 (void)astore(ary, ++sp, str = str_static(&str_no));
1343 str_numset(str, (double)pent->p_proto);
1344#else /* lint */
1345 elem = Nullch;
1346 elem = elem;
1347 (void)astore(ary, ++sp, str_static(&str_no));
1348#endif /* lint */
1349 }
1350
1351 return sp;
1352}
1353
1354int
1355do_gsent(which,gimme,arglast)
1356int which;
1357int gimme;
1358int *arglast;
1359{
1360 register ARRAY *ary = stack;
1361 register int sp = arglast[0];
1362 register char **elem;
1363 register STR *str;
1364 struct servent *getservbyname();
1365 struct servent *getservbynumber();
1366 struct servent *getservent();
1367 struct servent *sent;
1368
1369 if (gimme != G_ARRAY) {
1370 astore(ary, ++sp, str_static(&str_undef));
1371 return sp;
1372 }
1373
1374 if (which == O_GSBYNAME) {
1375 char *name = str_get(ary->ary_array[sp+1]);
1376 char *proto = str_get(ary->ary_array[sp+2]);
1377
1378 if (proto && !*proto)
1379 proto = Nullch;
1380
1381 sent = getservbyname(name,proto);
1382 }
1383 else if (which == O_GSBYPORT) {
1384 int port = (int)str_gnum(ary->ary_array[sp+1]);
1385 char *proto = str_get(ary->ary_array[sp+2]);
1386
1387 sent = getservbyport(port,proto);
1388 }
1389 else
1390 sent = getservent();
1391 if (sent) {
1392#ifndef lint
1393 (void)astore(ary, ++sp, str = str_static(&str_no));
1394 str_set(str, sent->s_name);
1395 (void)astore(ary, ++sp, str = str_static(&str_no));
1396 for (elem = sent->s_aliases; *elem; elem++) {
1397 str_cat(str, *elem);
1398 if (elem[1])
1399 str_ncat(str," ",1);
1400 }
1401 (void)astore(ary, ++sp, str = str_static(&str_no));
1402#ifdef NTOHS
1403 str_numset(str, (double)ntohs(sent->s_port));
1404#else
1405 str_numset(str, (double)(sent->s_port));
1406#endif
1407 (void)astore(ary, ++sp, str = str_static(&str_no));
1408 str_set(str, sent->s_proto);
1409#else /* lint */
1410 elem = Nullch;
1411 elem = elem;
1412 (void)astore(ary, ++sp, str_static(&str_no));
1413#endif /* lint */
1414 }
1415
1416 return sp;
1417}
1418
1419int
1420do_select(gimme,arglast)
1421int gimme;
1422int *arglast;
1423{
1424 register STR **st = stack->ary_array;
1425 register int sp = arglast[0];
1426 register int i;
1427 register int j;
1428 register char *s;
1429 register STR *str;
1430 double value;
1431 int maxlen = 0;
1432 int nfound;
1433 struct timeval timebuf;
1434 struct timeval *tbuf = &timebuf;
1435
1436 for (i = 1; i <= 3; i++) {
1437 j = st[sp+i]->str_len;
1438 if (maxlen < j)
1439 maxlen = j;
1440 }
1441 for (i = 1; i <= 3; i++) {
1442 str = st[sp+i];
1443 j = str->str_len;
1444 if (j < maxlen) {
1445 if (str->str_pok) {
1446 str_grow(str,maxlen);
1447 s = str_get(str) + j;
1448 while (++j <= maxlen) {
1449 *s++ = '\0';
1450 }
1451 }
1452 else if (str->str_ptr) {
1453 Safefree(str->str_ptr);
1454 str->str_ptr = Nullch;
1455 }
1456 }
1457 }
1458 str = st[sp+4];
1459 if (str->str_nok || str->str_pok) {
1460 value = str_gnum(str);
1461 if (value < 0.0)
1462 value = 0.0;
1463 timebuf.tv_sec = (long)value;
1464 value -= (double)timebuf.tv_sec;
1465 timebuf.tv_usec = (long)(value * 1000000.0);
1466 }
1467 else
1468 tbuf = Null(struct timeval*);
1469
1470 nfound = select(
1471 maxlen * 8,
1472 st[sp+1]->str_ptr,
1473 st[sp+2]->str_ptr,
1474 st[sp+3]->str_ptr,
1475 tbuf);
1476
1477 st[++sp] = str_static(&str_no);
1478 str_numset(st[sp], (double)nfound);
1479 if (gimme == G_ARRAY && tbuf) {
1480 value = (double)(timebuf.tv_sec) +
1481 (double)(timebuf.tv_usec) / 1000000.0;
1482 st[++sp] = str_static(&str_no);
1483 str_numset(st[sp], value);
1484 }
1485 return sp;
1486}
1487
1488int
1489do_spair(stab1, stab2, arglast)
1490STAB *stab1;
1491STAB *stab2;
1492int *arglast;
1493{
1494 register STR **st = stack->ary_array;
1495 register int sp = arglast[2];
1496 register STIO *stio1;
1497 register STIO *stio2;
1498 int domain, type, protocol, fd[2];
1499
1500 if (!stab1 || !stab2)
1501 return FALSE;
1502
1503 stio1 = stab_io(stab1);
1504 stio2 = stab_io(stab2);
1505 if (!stio1)
1506 stio1 = stab_io(stab1) = stio_new();
1507 else if (stio1->ifp)
1508 do_close(stab1,FALSE);
1509 if (!stio2)
1510 stio2 = stab_io(stab2) = stio_new();
1511 else if (stio2->ifp)
1512 do_close(stab2,FALSE);
1513
1514 domain = (int)str_gnum(st[++sp]);
1515 type = (int)str_gnum(st[++sp]);
1516 protocol = (int)str_gnum(st[++sp]);
1517#ifdef TAINT
1518 taintproper("Insecure dependency in socketpair");
1519#endif
1520#ifdef SOCKETPAIR
1521 if (socketpair(domain,type,protocol,fd) < 0)
1522 return FALSE;
1523#else
1524 fatal("Socketpair unimplemented");
1525#endif
1526 stio1->ifp = fdopen(fd[0], "r");
1527 stio1->ofp = fdopen(fd[0], "w");
1528 stio1->type = 's';
1529 stio2->ifp = fdopen(fd[1], "r");
1530 stio2->ofp = fdopen(fd[1], "w");
1531 stio2->type = 's';
1532
1533 return TRUE;
1534}
1535
1536#endif /* SOCKET */
1537
1538int
1539do_gpwent(which,gimme,arglast)
1540int which;
1541int gimme;
1542int *arglast;
1543{
1544#ifdef I_PWD
1545 register ARRAY *ary = stack;
1546 register int sp = arglast[0];
1547 register char **elem;
1548 register STR *str;
1549 struct passwd *getpwnam();
1550 struct passwd *getpwuid();
1551 struct passwd *getpwent();
1552 struct passwd *pwent;
1553 unsigned long len;
1554
1555 if (gimme != G_ARRAY) {
1556 astore(ary, ++sp, str_static(&str_undef));
1557 return sp;
1558 }
1559
1560 if (which == O_GPWNAM) {
1561 char *name = str_get(ary->ary_array[sp+1]);
1562
1563 pwent = getpwnam(name);
1564 }
1565 else if (which == O_GPWUID) {
1566 int uid = (int)str_gnum(ary->ary_array[sp+1]);
1567
1568 pwent = getpwuid(uid);
1569 }
1570 else
1571 pwent = getpwent();
1572
1573 if (pwent) {
1574 (void)astore(ary, ++sp, str = str_static(&str_no));
1575 str_set(str, pwent->pw_name);
1576 (void)astore(ary, ++sp, str = str_static(&str_no));
1577 str_set(str, pwent->pw_passwd);
1578 (void)astore(ary, ++sp, str = str_static(&str_no));
1579 str_numset(str, (double)pwent->pw_uid);
1580 (void)astore(ary, ++sp, str = str_static(&str_no));
1581 str_numset(str, (double)pwent->pw_gid);
1582 (void)astore(ary, ++sp, str = str_static(&str_no));
1583#ifdef PWQUOTA
1584 str_numset(str, (double)pwent->pw_quota);
1585#else
1586#ifdef PWAGE
1587 str_set(str, pwent->pw_age);
1588#endif
1589#endif
1590 (void)astore(ary, ++sp, str = str_static(&str_no));
1591 str_set(str, pwent->pw_comment);
1592 (void)astore(ary, ++sp, str = str_static(&str_no));
1593 str_set(str, pwent->pw_gecos);
1594 (void)astore(ary, ++sp, str = str_static(&str_no));
1595 str_set(str, pwent->pw_dir);
1596 (void)astore(ary, ++sp, str = str_static(&str_no));
1597 str_set(str, pwent->pw_shell);
1598 }
1599
1600 return sp;
1601#else
1602 fatal("password routines not implemented");
1603#endif
1604}
1605
1606int
1607do_ggrent(which,gimme,arglast)
1608int which;
1609int gimme;
1610int *arglast;
1611{
1612#ifdef I_GRP
1613 register ARRAY *ary = stack;
1614 register int sp = arglast[0];
1615 register char **elem;
1616 register STR *str;
1617 struct group *getgrnam();
1618 struct group *getgrgid();
1619 struct group *getgrent();
1620 struct group *grent;
1621 unsigned long len;
1622
1623 if (gimme != G_ARRAY) {
1624 astore(ary, ++sp, str_static(&str_undef));
1625 return sp;
1626 }
1627
1628 if (which == O_GGRNAM) {
1629 char *name = str_get(ary->ary_array[sp+1]);
1630
1631 grent = getgrnam(name);
1632 }
1633 else if (which == O_GGRGID) {
1634 int gid = (int)str_gnum(ary->ary_array[sp+1]);
1635
1636 grent = getgrgid(gid);
1637 }
1638 else
1639 grent = getgrent();
1640
1641 if (grent) {
1642 (void)astore(ary, ++sp, str = str_static(&str_no));
1643 str_set(str, grent->gr_name);
1644 (void)astore(ary, ++sp, str = str_static(&str_no));
1645 str_set(str, grent->gr_passwd);
1646 (void)astore(ary, ++sp, str = str_static(&str_no));
1647 str_numset(str, (double)grent->gr_gid);
1648 (void)astore(ary, ++sp, str = str_static(&str_no));
1649 for (elem = grent->gr_mem; *elem; elem++) {
1650 str_cat(str, *elem);
1651 if (elem[1])
1652 str_ncat(str," ",1);
1653 }
1654 }
1655
1656 return sp;
1657#else
1658 fatal("group routines not implemented");
1659#endif
1660}
1661
1662int
1663do_dirop(optype,stab,gimme,arglast)
1664int optype;
1665STAB *stab;
1666int gimme;
1667int *arglast;
1668{
1669#ifdef DIRENT
1670 register ARRAY *ary = stack;
1671 register STR **st = ary->ary_array;
1672 register int sp = arglast[1];
1673 register STIO *stio;
1674 long along;
1675 long telldir();
1676 struct DIRENT *readdir();
1677 register struct DIRENT *dp;
1678
1679 if (!stab)
1680 goto nope;
1681 if (!(stio = stab_io(stab)))
1682 stio = stab_io(stab) = stio_new();
1683 if (!stio->dirp && optype != O_OPENDIR)
1684 goto nope;
1685 st[sp] = &str_yes;
1686 switch (optype) {
1687 case O_OPENDIR:
1688 if (stio->dirp)
1689 closedir(stio->dirp);
1690 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
1691 goto nope;
1692 break;
1693 case O_READDIR:
1694 if (gimme == G_ARRAY) {
1695 --sp;
1696 while (dp = readdir(stio->dirp)) {
1697#ifdef DIRNAMLEN
1698 (void)astore(ary,++sp,
1699 str_2static(str_make(dp->d_name,dp->d_namlen)));
1700#else
1701 (void)astore(ary,++sp,
1702 str_2static(str_make(dp->d_name,0)));
1703#endif
1704 }
1705 }
1706 else {
1707 if (!(dp = readdir(stio->dirp)))
1708 goto nope;
1709 st[sp] = str_static(&str_undef);
1710#ifdef DIRNAMLEN
1711 str_nset(st[sp], dp->d_name, dp->d_namlen);
1712#else
1713 str_set(st[sp], dp->d_name);
1714#endif
1715 }
1716 break;
1717 case O_TELLDIR:
1718 st[sp] = str_static(&str_undef);
1719 str_numset(st[sp], (double)telldir(stio->dirp));
1720 break;
1721 case O_SEEKDIR:
1722 st[sp] = str_static(&str_undef);
1723 along = (long)str_gnum(st[sp+1]);
1724 (void)seekdir(stio->dirp,along);
1725 break;
1726 case O_REWINDDIR:
1727 st[sp] = str_static(&str_undef);
1728 (void)rewinddir(stio->dirp);
1729 break;
1730 case O_CLOSEDIR:
1731 st[sp] = str_static(&str_undef);
1732 (void)closedir(stio->dirp);
1733 stio->dirp = 0;
1734 break;
1735 }
1736 return sp;
1737
1738nope:
1739 st[sp] = &str_undef;
1740 return sp;
1741
1742#else
1743 fatal("Unimplemented directory operation");
1744#endif
1745}
1746
1747apply(type,arglast)
1748int type;
1749int *arglast;
1750{
1751 register STR **st = stack->ary_array;
1752 register int sp = arglast[1];
1753 register int items = arglast[2] - sp;
1754 register int val;
1755 register int val2;
1756 register int tot = 0;
1757 char *s;
1758
1759#ifdef TAINT
1760 for (st += ++sp; items--; st++)
1761 tainted |= (*st)->str_tainted;
1762 st = stack->ary_array;
1763 sp = arglast[1];
1764 items = arglast[2] - sp;
1765#endif
1766 switch (type) {
1767 case O_CHMOD:
1768#ifdef TAINT
1769 taintproper("Insecure dependency in chmod");
1770#endif
1771 if (--items > 0) {
1772 tot = items;
1773 val = (int)str_gnum(st[++sp]);
1774 while (items--) {
1775 if (chmod(str_get(st[++sp]),val))
1776 tot--;
1777 }
1778 }
1779 break;
1780 case O_CHOWN:
1781#ifdef TAINT
1782 taintproper("Insecure dependency in chown");
1783#endif
1784 if (items > 2) {
1785 items -= 2;
1786 tot = items;
1787 val = (int)str_gnum(st[++sp]);
1788 val2 = (int)str_gnum(st[++sp]);
1789 while (items--) {
1790 if (chown(str_get(st[++sp]),val,val2))
1791 tot--;
1792 }
1793 }
1794 break;
1795 case O_KILL:
1796#ifdef TAINT
1797 taintproper("Insecure dependency in kill");
1798#endif
1799 if (--items > 0) {
1800 tot = items;
1801 s = str_get(st[++sp]);
1802 if (isupper(*s)) {
1803 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
1804 s += 3;
1805 if (!(val = whichsig(s)))
1806 fatal("Unrecognized signal name \"%s\"",s);
1807 }
1808 else
1809 val = (int)str_gnum(st[sp]);
1810 if (val < 0) {
1811 val = -val;
1812 while (items--) {
1813 int proc = (int)str_gnum(st[++sp]);
1814#ifdef KILLPG
1815 if (killpg(proc,val)) /* BSD */
1816#else
1817 if (kill(-proc,val)) /* SYSV */
1818#endif
1819 tot--;
1820 }
1821 }
1822 else {
1823 while (items--) {
1824 if (kill((int)(str_gnum(st[++sp])),val))
1825 tot--;
1826 }
1827 }
1828 }
1829 break;
1830 case O_UNLINK:
1831#ifdef TAINT
1832 taintproper("Insecure dependency in unlink");
1833#endif
1834 tot = items;
1835 while (items--) {
1836 s = str_get(st[++sp]);
1837 if (euid || unsafe) {
1838 if (UNLINK(s))
1839 tot--;
1840 }
1841 else { /* don't let root wipe out directories without -U */
1842#ifdef SYMLINK
1843 if (lstat(s,&statbuf) < 0 ||
1844#else
1845 if (stat(s,&statbuf) < 0 ||
1846#endif
1847 (statbuf.st_mode & S_IFMT) == S_IFDIR )
1848 tot--;
1849 else {
1850 if (UNLINK(s))
1851 tot--;
1852 }
1853 }
1854 }
1855 break;
1856 case O_UTIME:
1857#ifdef TAINT
1858 taintproper("Insecure dependency in utime");
1859#endif
1860 if (items > 2) {
1861 struct {
1862 long atime,
1863 mtime;
1864 } utbuf;
1865
1866 utbuf.atime = (long)str_gnum(st[++sp]); /* time accessed */
1867 utbuf.mtime = (long)str_gnum(st[++sp]); /* time modified */
1868 items -= 2;
1869#ifndef lint
1870 tot = items;
1871 while (items--) {
1872 if (utime(str_get(st[++sp]),&utbuf))
1873 tot--;
1874 }
1875#endif
1876 }
1877 else
1878 items = 0;
1879 break;
1880 }
1881 return tot;
1882}
1883
1884/* Do the permissions allow some operation? Assumes statcache already set. */
1885
1886int
1887cando(bit, effective, statbufp)
1888int bit;
1889int effective;
1890register struct stat *statbufp;
1891{
1892 if ((effective ? euid : uid) == 0) { /* root is special */
1893 if (bit == S_IEXEC) {
1894 if (statbufp->st_mode & 0111 ||
1895 (statbufp->st_mode & S_IFMT) == S_IFDIR )
1896 return TRUE;
1897 }
1898 else
1899 return TRUE; /* root reads and writes anything */
1900 return FALSE;
1901 }
1902 if (statbufp->st_uid == (effective ? euid : uid) ) {
1903 if (statbufp->st_mode & bit)
1904 return TRUE; /* ok as "user" */
1905 }
1906 else if (ingroup((int)statbufp->st_gid,effective)) {
1907 if (statbufp->st_mode & bit >> 3)
1908 return TRUE; /* ok as "group" */
1909 }
1910 else if (statbufp->st_mode & bit >> 6)
1911 return TRUE; /* ok as "other" */
1912 return FALSE;
1913}
1914
1915int
1916ingroup(testgid,effective)
1917int testgid;
1918int effective;
1919{
1920 if (testgid == (effective ? egid : gid))
1921 return TRUE;
1922#ifdef GETGROUPS
1923#ifndef NGROUPS
1924#define NGROUPS 32
1925#endif
1926 {
1927 GIDTYPE gary[NGROUPS];
1928 int anum;
1929
1930 anum = getgroups(NGROUPS,gary);
1931 while (--anum >= 0)
1932 if (gary[anum] == testgid)
1933 return TRUE;
1934 }
1935#endif
1936 return FALSE;
1937}