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