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