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