This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 4.0 patch 13: patch #11, continued
[perl5.git] / doio.c
CommitLineData
1462b684 1/* $RCSfile: doio.c,v $$Revision: 4.0.1.3 $$Date: 91/06/10 01:21:19 $
a687059c 2 *
6e21c824 3 * Copyright (c) 1991, Larry Wall
a687059c 4 *
6e21c824
LW
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
a687059c
LW
7 *
8 * $Log: doio.c,v $
1462b684
LW
9 * Revision 4.0.1.3 91/06/10 01:21:19 lwall
10 * patch10: read didn't work from character special files open for writing
11 * patch10: close-on-exec wrongly set on system file descriptors
12 *
6e21c824
LW
13 * Revision 4.0.1.2 91/06/07 10:53:39 lwall
14 * patch4: new copyright notice
15 * patch4: system fd's are now treated specially
16 * patch4: added $^F variable to specify maximum system fd, default 2
17 * patch4: character special files now opened with bidirectional stdio buffers
18 * patch4: taintchecks could improperly modify parent in vfork()
19 * patch4: many, many itty-bitty portability fixes
20 *
1c3d792e
LW
21 * Revision 4.0.1.1 91/04/11 17:41:06 lwall
22 * patch1: hopefully straightened out some of the Xenix mess
23 *
fe14fcc3
LW
24 * Revision 4.0 91/03/20 01:07:06 lwall
25 * 4.0 baseline.
a687059c
LW
26 *
27 */
28
29#include "EXTERN.h"
30#include "perl.h"
31
fe14fcc3 32#ifdef HAS_SOCKET
a687059c
LW
33#include <sys/socket.h>
34#include <netdb.h>
35#endif
36
fe14fcc3 37#ifdef HAS_SELECT
1c3d792e
LW
38#ifdef I_SYS_SELECT
39#ifndef I_SYS_TIME
fe14fcc3
LW
40#include <sys/select.h>
41#endif
42#endif
1c3d792e 43#endif
fe14fcc3
LW
44
45#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
c2ab57d4 46#include <sys/ipc.h>
fe14fcc3 47#ifdef HAS_MSG
c2ab57d4 48#include <sys/msg.h>
e5d73d77 49#endif
fe14fcc3 50#ifdef HAS_SEM
c2ab57d4 51#include <sys/sem.h>
e5d73d77 52#endif
fe14fcc3 53#ifdef HAS_SHM
c2ab57d4
LW
54#include <sys/shm.h>
55#endif
e5d73d77 56#endif
c2ab57d4 57
a687059c
LW
58#ifdef I_PWD
59#include <pwd.h>
60#endif
61#ifdef I_GRP
62#include <grp.h>
63#endif
663a0e37
LW
64#ifdef I_UTIME
65#include <utime.h>
66#endif
ff8e2863
LW
67#ifdef I_FCNTL
68#include <fcntl.h>
69#endif
fe14fcc3
LW
70#ifdef I_SYS_FILE
71#include <sys/file.h>
72#endif
a687059c 73
57ebbfd0 74int laststatval = -1;
fe14fcc3 75int laststype = O_STAT;
57ebbfd0 76
a687059c 77bool
afd9f252 78do_open(stab,name,len)
a687059c
LW
79STAB *stab;
80register char *name;
afd9f252 81int len;
a687059c
LW
82{
83 FILE *fp;
a687059c
LW
84 register STIO *stio = stab_io(stab);
85 char *myname = savestr(name);
86 int result;
87 int fd;
88 int writing = 0;
89 char mode[3]; /* stdio file mode ("r\0" or "r+\0") */
6e21c824
LW
90 FILE *saveifp = Nullfp;
91 FILE *saveofp = Nullfp;
92 char savetype = ' ';
a687059c
LW
93
94 name = myname;
95 forkprocess = 1; /* assume true if no fork */
96 while (len && isspace(name[len-1]))
97 name[--len] = '\0';
98 if (!stio)
99 stio = stab_io(stab) = stio_new();
100 else if (stio->ifp) {
101 fd = fileno(stio->ifp);
6e21c824 102 if (stio->type == '-')
c2ab57d4 103 result = 0;
6e21c824
LW
104 else if (fd <= maxsysfd) {
105 saveifp = stio->ifp;
106 saveofp = stio->ofp;
107 savetype = stio->type;
108 result = 0;
109 }
110 else if (stio->type == '|')
111 result = mypclose(stio->ifp);
a687059c 112 else if (stio->ifp != stio->ofp) {
c2ab57d4
LW
113 if (stio->ofp) {
114 result = fclose(stio->ofp);
115 fclose(stio->ifp); /* clear stdio, fd already closed */
116 }
117 else
118 result = fclose(stio->ifp);
a687059c 119 }
a687059c 120 else
c2ab57d4 121 result = fclose(stio->ifp);
6e21c824 122 if (result == EOF && fd > maxsysfd)
a687059c
LW
123 fprintf(stderr,"Warning: unable to close filehandle %s properly.\n",
124 stab_name(stab));
125 stio->ofp = stio->ifp = Nullfp;
126 }
127 if (*name == '+' && len > 1 && name[len-1] != '|') { /* scary */
128 mode[1] = *name++;
129 mode[2] = '\0';
130 --len;
131 writing = 1;
132 }
133 else {
134 mode[1] = '\0';
135 }
136 stio->type = *name;
137 if (*name == '|') {
138 for (name++; isspace(*name); name++) ;
139#ifdef TAINT
140 taintenv();
141 taintproper("Insecure dependency in piped open");
142#endif
143 fp = mypopen(name,"w");
144 writing = 1;
145 }
a687059c
LW
146 else if (*name == '>') {
147#ifdef TAINT
148 taintproper("Insecure dependency in open");
149#endif
bf38876a
LW
150 name++;
151 if (*name == '>') {
152 mode[0] = stio->type = 'a';
153 name++;
a687059c 154 }
bf38876a 155 else
a687059c 156 mode[0] = 'w';
a687059c 157 writing = 1;
bf38876a
LW
158 if (*name == '&') {
159 duplicity:
160 name++;
161 while (isspace(*name))
162 name++;
163 if (isdigit(*name))
164 fd = atoi(name);
165 else {
166 stab = stabent(name,FALSE);
6e21c824
LW
167 if (!stab || !stab_io(stab)) {
168#ifdef EINVAL
169 errno = EINVAL;
170#endif
171 goto say_false;
172 }
bf38876a
LW
173 if (stab_io(stab) && stab_io(stab)->ifp) {
174 fd = fileno(stab_io(stab)->ifp);
175 if (stab_io(stab)->type == 's')
176 stio->type = 's';
177 }
178 else
179 fd = -1;
180 }
fe14fcc3
LW
181 if (!(fp = fdopen(fd = dup(fd),mode))) {
182 close(fd);
183 }
bf38876a
LW
184 }
185 else {
186 while (isspace(*name))
187 name++;
188 if (strEQ(name,"-")) {
189 fp = stdout;
190 stio->type = '-';
191 }
192 else {
193 fp = fopen(name,mode);
194 }
195 }
a687059c
LW
196 }
197 else {
198 if (*name == '<') {
bf38876a
LW
199 mode[0] = 'r';
200 name++;
201 while (isspace(*name))
202 name++;
203 if (*name == '&')
204 goto duplicity;
a687059c
LW
205 if (strEQ(name,"-")) {
206 fp = stdin;
207 stio->type = '-';
208 }
bf38876a 209 else
a687059c 210 fp = fopen(name,mode);
a687059c
LW
211 }
212 else if (name[len-1] == '|') {
213#ifdef TAINT
214 taintenv();
215 taintproper("Insecure dependency in piped open");
216#endif
217 name[--len] = '\0';
218 while (len && isspace(name[len-1]))
219 name[--len] = '\0';
220 for (; isspace(*name); name++) ;
221 fp = mypopen(name,"r");
222 stio->type = '|';
223 }
224 else {
225 stio->type = '<';
226 for (; isspace(*name); name++) ;
227 if (strEQ(name,"-")) {
228 fp = stdin;
229 stio->type = '-';
230 }
231 else
232 fp = fopen(name,"r");
233 }
234 }
235 Safefree(myname);
236 if (!fp)
6e21c824 237 goto say_false;
a687059c
LW
238 if (stio->type &&
239 stio->type != '|' && stio->type != '-') {
240 if (fstat(fileno(fp),&statbuf) < 0) {
241 (void)fclose(fp);
6e21c824 242 goto say_false;
a687059c 243 }
1462b684 244 if (S_ISSOCK(statbuf.st_mode))
bf38876a 245 stio->type = 's'; /* in case a socket was passed in to us */
c623bd54
LW
246#ifdef S_IFMT
247 else if (!(statbuf.st_mode & S_IFMT))
248 stio->type = 's'; /* some OS's return 0 on fstat()ed socket */
bf38876a 249#endif
a687059c 250 }
6e21c824
LW
251 if (saveifp) { /* must use old fp? */
252 fd = fileno(saveifp);
253 if (saveofp) {
254 fflush(saveofp); /* emulate fclose() */
255 if (saveofp != saveifp) { /* was a socket? */
256 fclose(saveofp);
257 Safefree(saveofp);
258 }
259 }
260 if (fd != fileno(fp)) {
261 dup2(fileno(fp), fd);
262 fclose(fp);
263 }
264 fp = saveifp;
265 }
1462b684
LW
266#if defined(HAS_FCNTL) && defined(F_SETFD)
267 fd = fileno(fp);
268 fcntl(fd,F_SETFD,fd > maxsysfd);
269#endif
a687059c 270 stio->ifp = fp;
bf38876a 271 if (writing) {
1462b684
LW
272 if (stio->type == 's'
273 || (stio->type == '>' && S_ISCHR(statbuf.st_mode)) ) {
fe14fcc3
LW
274 if (!(stio->ofp = fdopen(fileno(fp),"w"))) {
275 fclose(fp);
276 stio->ifp = Nullfp;
6e21c824 277 goto say_false;
fe14fcc3 278 }
1462b684
LW
279 }
280 else
281 stio->ofp = fp;
bf38876a 282 }
a687059c 283 return TRUE;
6e21c824
LW
284
285say_false:
286 stio->ifp = saveifp;
287 stio->ofp = saveofp;
288 stio->type = savetype;
289 return FALSE;
a687059c
LW
290}
291
292FILE *
293nextargv(stab)
294register STAB *stab;
295{
296 register STR *str;
c623bd54
LW
297 int filedev;
298 int fileino;
c623bd54
LW
299 int fileuid;
300 int filegid;
fe14fcc3
LW
301 static int filemode = 0;
302 static int lastfd;
303 static char *oldname;
304
305 if (!argvoutstab)
306 argvoutstab = stabent("ARGVOUT",TRUE);
307 if (filemode & (S_ISUID|S_ISGID)) {
308 fflush(stab_io(argvoutstab)->ifp); /* chmod must follow last write */
309#ifdef HAS_FCHMOD
310 (void)fchmod(lastfd,filemode);
311#else
312 (void)chmod(oldname,filemode);
313#endif
314 }
315 filemode = 0;
a687059c
LW
316 while (alen(stab_xarray(stab)) >= 0) {
317 str = ashift(stab_xarray(stab));
318 str_sset(stab_val(stab),str);
319 STABSET(stab_val(stab));
320 oldname = str_get(stab_val(stab));
afd9f252 321 if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
a687059c
LW
322 if (inplace) {
323#ifdef TAINT
324 taintproper("Insecure dependency in inplace open");
325#endif
c623bd54
LW
326 if (strEQ(oldname,"-")) {
327 str_free(str);
328 defoutstab = stabent("STDOUT",TRUE);
329 return stab_io(stab)->ifp;
330 }
331 filedev = statbuf.st_dev;
332 fileino = statbuf.st_ino;
a687059c
LW
333 filemode = statbuf.st_mode;
334 fileuid = statbuf.st_uid;
335 filegid = statbuf.st_gid;
c623bd54
LW
336 if (!S_ISREG(filemode)) {
337 warn("Can't do inplace edit: %s is not a regular file",
338 oldname );
339 do_close(stab,FALSE);
340 str_free(str);
341 continue;
342 }
a687059c 343 if (*inplace) {
ff8e2863
LW
344#ifdef SUFFIX
345 add_suffix(str,inplace);
346#else
a687059c 347 str_cat(str,inplace);
ff8e2863 348#endif
c623bd54
LW
349#ifndef FLEXFILENAMES
350 if (stat(str->str_ptr,&statbuf) >= 0
351 && statbuf.st_dev == filedev
352 && statbuf.st_ino == fileino ) {
353 warn("Can't do inplace edit: %s > 14 characters",
354 str->str_ptr );
355 do_close(stab,FALSE);
356 str_free(str);
357 continue;
358 }
359#endif
fe14fcc3 360#ifdef HAS_RENAME
ff8e2863 361#ifndef MSDOS
c623bd54
LW
362 if (rename(oldname,str->str_ptr) < 0) {
363 warn("Can't rename %s to %s: %s, skipping file",
364 oldname, str->str_ptr, strerror(errno) );
365 do_close(stab,FALSE);
366 str_free(str);
367 continue;
368 }
a687059c 369#else
ff8e2863
LW
370 do_close(stab,FALSE);
371 (void)unlink(str->str_ptr);
372 (void)rename(oldname,str->str_ptr);
373 do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
374#endif /* MSDOS */
375#else
a687059c 376 (void)UNLINK(str->str_ptr);
c623bd54
LW
377 if (link(oldname,str->str_ptr) < 0) {
378 warn("Can't rename %s to %s: %s, skipping file",
379 oldname, str->str_ptr, strerror(errno) );
380 do_close(stab,FALSE);
381 str_free(str);
382 continue;
383 }
a687059c
LW
384 (void)UNLINK(oldname);
385#endif
386 }
387 else {
ff8e2863 388#ifndef MSDOS
fe14fcc3
LW
389 if (UNLINK(oldname) < 0) {
390 warn("Can't rename %s to %s: %s, skipping file",
391 oldname, str->str_ptr, strerror(errno) );
392 do_close(stab,FALSE);
393 str_free(str);
394 continue;
395 }
ff8e2863
LW
396#else
397 fatal("Can't do inplace edit without backup");
398#endif
a687059c
LW
399 }
400
401 str_nset(str,">",1);
402 str_cat(str,oldname);
403 errno = 0; /* in case sprintf set errno */
fe14fcc3 404 if (!do_open(argvoutstab,str->str_ptr,str->str_cur)) {
c623bd54
LW
405 warn("Can't do inplace edit on %s: %s",
406 oldname, strerror(errno) );
fe14fcc3
LW
407 do_close(stab,FALSE);
408 str_free(str);
409 continue;
410 }
a687059c 411 defoutstab = argvoutstab;
fe14fcc3
LW
412 lastfd = fileno(stab_io(argvoutstab)->ifp);
413 (void)fstat(lastfd,&statbuf);
414#ifdef HAS_FCHMOD
415 (void)fchmod(lastfd,filemode);
a687059c
LW
416#else
417 (void)chmod(oldname,filemode);
418#endif
fe14fcc3
LW
419 if (fileuid != statbuf.st_uid || filegid != statbuf.st_gid) {
420#ifdef HAS_FCHOWN
421 (void)fchown(lastfd,fileuid,filegid);
a687059c 422#else
fe14fcc3
LW
423#ifdef HAS_CHOWN
424 (void)chown(oldname,fileuid,filegid);
a687059c 425#endif
b1248f16 426#endif
fe14fcc3 427 }
a687059c
LW
428 }
429 str_free(str);
430 return stab_io(stab)->ifp;
431 }
432 else
c623bd54 433 fprintf(stderr,"Can't open %s: %s\n",str_get(str), strerror(errno));
a687059c
LW
434 str_free(str);
435 }
436 if (inplace) {
437 (void)do_close(argvoutstab,FALSE);
438 defoutstab = stabent("STDOUT",TRUE);
439 }
440 return Nullfp;
441}
442
fe14fcc3 443#ifdef HAS_PIPE
afd9f252
LW
444void
445do_pipe(str, rstab, wstab)
446STR *str;
447STAB *rstab;
448STAB *wstab;
449{
450 register STIO *rstio;
451 register STIO *wstio;
452 int fd[2];
453
454 if (!rstab)
455 goto badexit;
456 if (!wstab)
457 goto badexit;
458
459 rstio = stab_io(rstab);
460 wstio = stab_io(wstab);
461
462 if (!rstio)
463 rstio = stab_io(rstab) = stio_new();
464 else if (rstio->ifp)
465 do_close(rstab,FALSE);
466 if (!wstio)
467 wstio = stab_io(wstab) = stio_new();
468 else if (wstio->ifp)
469 do_close(wstab,FALSE);
470
471 if (pipe(fd) < 0)
472 goto badexit;
473 rstio->ifp = fdopen(fd[0], "r");
474 wstio->ofp = fdopen(fd[1], "w");
475 wstio->ifp = wstio->ofp;
476 rstio->type = '<';
477 wstio->type = '>';
fe14fcc3
LW
478 if (!rstio->ifp || !wstio->ofp) {
479 if (rstio->ifp) fclose(rstio->ifp);
480 else close(fd[0]);
481 if (wstio->ofp) fclose(wstio->ofp);
482 else close(fd[1]);
483 goto badexit;
484 }
afd9f252
LW
485
486 str_sset(str,&str_yes);
487 return;
488
489badexit:
490 str_sset(str,&str_undef);
491 return;
492}
b1248f16 493#endif
afd9f252 494
a687059c
LW
495bool
496do_close(stab,explicit)
497STAB *stab;
498bool explicit;
499{
500 bool retval = FALSE;
c2ab57d4 501 register STIO *stio;
a687059c
LW
502 int status;
503
c2ab57d4
LW
504 if (!stab)
505 stab = argvstab;
506 if (!stab)
507 return FALSE;
508 stio = stab_io(stab);
a687059c
LW
509 if (!stio) { /* never opened */
510 if (dowarn && explicit)
511 warn("Close on unopened file <%s>",stab_name(stab));
512 return FALSE;
513 }
514 if (stio->ifp) {
515 if (stio->type == '|') {
516 status = mypclose(stio->ifp);
c623bd54 517 retval = (status == 0);
b1248f16 518 statusvalue = (unsigned short)status & 0xffff;
a687059c
LW
519 }
520 else if (stio->type == '-')
521 retval = TRUE;
522 else {
c2ab57d4
LW
523 if (stio->ofp && stio->ofp != stio->ifp) { /* a socket */
524 retval = (fclose(stio->ofp) != EOF);
525 fclose(stio->ifp); /* clear stdio, fd already closed */
526 }
527 else
528 retval = (fclose(stio->ifp) != EOF);
a687059c
LW
529 }
530 stio->ofp = stio->ifp = Nullfp;
531 }
532 if (explicit)
533 stio->lines = 0;
534 stio->type = ' ';
535 return retval;
536}
537
538bool
539do_eof(stab)
540STAB *stab;
541{
542 register STIO *stio;
543 int ch;
544
545 if (!stab) { /* eof() */
546 if (argvstab)
547 stio = stab_io(argvstab);
548 else
549 return TRUE;
550 }
551 else
552 stio = stab_io(stab);
553
554 if (!stio)
555 return TRUE;
556
557 while (stio->ifp) {
558
559#ifdef STDSTDIO /* (the code works without this) */
560 if (stio->ifp->_cnt > 0) /* cheat a little, since */
561 return FALSE; /* this is the most usual case */
562#endif
563
564 ch = getc(stio->ifp);
565 if (ch != EOF) {
566 (void)ungetc(ch, stio->ifp);
567 return FALSE;
568 }
fe14fcc3
LW
569#ifdef STDSTDIO
570 if (stio->ifp->_cnt < -1)
571 stio->ifp->_cnt = -1;
572#endif
a687059c
LW
573 if (!stab) { /* not necessarily a real EOF yet? */
574 if (!nextargv(argvstab)) /* get another fp handy */
575 return TRUE;
576 }
577 else
578 return TRUE; /* normal fp, definitely end of file */
579 }
580 return TRUE;
581}
582
583long
584do_tell(stab)
585STAB *stab;
586{
587 register STIO *stio;
588
589 if (!stab)
590 goto phooey;
591
592 stio = stab_io(stab);
593 if (!stio || !stio->ifp)
594 goto phooey;
595
596 if (feof(stio->ifp))
597 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
598
599 return ftell(stio->ifp);
600
601phooey:
602 if (dowarn)
603 warn("tell() on unopened file");
604 return -1L;
605}
606
607bool
608do_seek(stab, pos, whence)
609STAB *stab;
610long pos;
611int whence;
612{
613 register STIO *stio;
614
615 if (!stab)
616 goto nuts;
617
618 stio = stab_io(stab);
619 if (!stio || !stio->ifp)
620 goto nuts;
621
622 if (feof(stio->ifp))
623 (void)fseek (stio->ifp, 0L, 2); /* ultrix 1.2 workaround */
624
625 return fseek(stio->ifp, pos, whence) >= 0;
626
627nuts:
628 if (dowarn)
629 warn("seek() on unopened file");
630 return FALSE;
631}
632
633int
634do_ctl(optype,stab,func,argstr)
635int optype;
636STAB *stab;
637int func;
638STR *argstr;
639{
640 register STIO *stio;
641 register char *s;
642 int retval;
643
644 if (!stab || !argstr)
645 return -1;
646 stio = stab_io(stab);
647 if (!stio)
648 return -1;
649
650 if (argstr->str_pok || !argstr->str_nok) {
651 if (!argstr->str_pok)
652 s = str_get(argstr);
653
654#ifdef IOCPARM_MASK
655#ifndef IOCPARM_LEN
656#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
657#endif
658#endif
659#ifdef IOCPARM_LEN
660 retval = IOCPARM_LEN(func); /* on BSDish systes we're safe */
661#else
662 retval = 256; /* otherwise guess at what's safe */
663#endif
664 if (argstr->str_cur < retval) {
ff8e2863 665 Str_Grow(argstr,retval+1);
a687059c
LW
666 argstr->str_cur = retval;
667 }
668
669 s = argstr->str_ptr;
670 s[argstr->str_cur] = 17; /* a little sanity check here */
671 }
672 else {
673 retval = (int)str_gnum(argstr);
c2ab57d4
LW
674#ifdef MSDOS
675 s = (char*)(long)retval; /* ouch */
676#else
a687059c 677 s = (char*)retval; /* ouch */
c2ab57d4 678#endif
a687059c
LW
679 }
680
681#ifndef lint
682 if (optype == O_IOCTL)
683 retval = ioctl(fileno(stio->ifp), func, s);
684 else
57ebbfd0
LW
685#ifdef MSDOS
686 fatal("fcntl is not implemented");
687#else
fe14fcc3 688#ifdef HAS_FCNTL
a687059c
LW
689 retval = fcntl(fileno(stio->ifp), func, s);
690#else
691 fatal("fcntl is not implemented");
692#endif
57ebbfd0 693#endif
a687059c
LW
694#else /* lint */
695 retval = 0;
696#endif /* lint */
697
698 if (argstr->str_pok) {
699 if (s[argstr->str_cur] != 17)
700 fatal("Return value overflowed string");
701 s[argstr->str_cur] = 0; /* put our null back */
702 }
703 return retval;
704}
705
706int
707do_stat(str,arg,gimme,arglast)
708STR *str;
709register ARG *arg;
710int gimme;
711int *arglast;
712{
713 register ARRAY *ary = stack;
714 register int sp = arglast[0] + 1;
715 int max = 13;
a687059c
LW
716
717 if ((arg[1].arg_type & A_MASK) == A_WORD) {
718 tmpstab = arg[1].arg_ptr.arg_stab;
719 if (tmpstab != defstab) {
fe14fcc3 720 laststype = O_STAT;
a687059c
LW
721 statstab = tmpstab;
722 str_set(statname,"");
c2ab57d4 723 if (!stab_io(tmpstab) || !stab_io(tmpstab)->ifp ||
a687059c
LW
724 fstat(fileno(stab_io(tmpstab)->ifp),&statcache) < 0) {
725 max = 0;
57ebbfd0 726 laststatval = -1;
a687059c
LW
727 }
728 }
57ebbfd0
LW
729 else if (laststatval < 0)
730 max = 0;
a687059c
LW
731 }
732 else {
c623bd54 733 str_set(statname,str_get(ary->ary_array[sp]));
a687059c 734 statstab = Nullstab;
fe14fcc3
LW
735#ifdef HAS_LSTAT
736 laststype = arg->arg_type;
a687059c 737 if (arg->arg_type == O_LSTAT)
57ebbfd0 738 laststatval = lstat(str_get(statname),&statcache);
a687059c
LW
739 else
740#endif
57ebbfd0
LW
741 laststatval = stat(str_get(statname),&statcache);
742 if (laststatval < 0)
a687059c
LW
743 max = 0;
744 }
745
746 if (gimme != G_ARRAY) {
747 if (max)
748 str_sset(str,&str_yes);
749 else
750 str_sset(str,&str_undef);
751 STABSET(str);
752 ary->ary_array[sp] = str;
753 return sp;
754 }
755 sp--;
756 if (max) {
757#ifndef lint
758 (void)astore(ary,++sp,
fe14fcc3 759 str_2mortal(str_nmake((double)statcache.st_dev)));
a687059c 760 (void)astore(ary,++sp,
fe14fcc3 761 str_2mortal(str_nmake((double)statcache.st_ino)));
a687059c 762 (void)astore(ary,++sp,
fe14fcc3 763 str_2mortal(str_nmake((double)statcache.st_mode)));
a687059c 764 (void)astore(ary,++sp,
fe14fcc3 765 str_2mortal(str_nmake((double)statcache.st_nlink)));
a687059c 766 (void)astore(ary,++sp,
fe14fcc3 767 str_2mortal(str_nmake((double)statcache.st_uid)));
a687059c 768 (void)astore(ary,++sp,
fe14fcc3 769 str_2mortal(str_nmake((double)statcache.st_gid)));
a687059c 770 (void)astore(ary,++sp,
fe14fcc3 771 str_2mortal(str_nmake((double)statcache.st_rdev)));
a687059c 772 (void)astore(ary,++sp,
fe14fcc3 773 str_2mortal(str_nmake((double)statcache.st_size)));
a687059c 774 (void)astore(ary,++sp,
fe14fcc3 775 str_2mortal(str_nmake((double)statcache.st_atime)));
a687059c 776 (void)astore(ary,++sp,
fe14fcc3 777 str_2mortal(str_nmake((double)statcache.st_mtime)));
a687059c 778 (void)astore(ary,++sp,
fe14fcc3 779 str_2mortal(str_nmake((double)statcache.st_ctime)));
a687059c
LW
780#ifdef STATBLOCKS
781 (void)astore(ary,++sp,
fe14fcc3 782 str_2mortal(str_nmake((double)statcache.st_blksize)));
a687059c 783 (void)astore(ary,++sp,
fe14fcc3 784 str_2mortal(str_nmake((double)statcache.st_blocks)));
a687059c
LW
785#else
786 (void)astore(ary,++sp,
fe14fcc3 787 str_2mortal(str_make("",0)));
a687059c 788 (void)astore(ary,++sp,
fe14fcc3 789 str_2mortal(str_make("",0)));
a687059c
LW
790#endif
791#else /* lint */
792 (void)astore(ary,++sp,str_nmake(0.0));
793#endif /* lint */
794 }
795 return sp;
796}
797
fe14fcc3 798#if !defined(HAS_TRUNCATE) && !defined(HAS_CHSIZE) && defined(F_FREESP)
c2ab57d4 799 /* code courtesy of William Kucharski */
fe14fcc3 800#define HAS_CHSIZE
6eb13c3b
LW
801
802int chsize(fd, length)
803int fd; /* file descriptor */
804off_t length; /* length to set file to */
805{
806 extern long lseek();
807 struct flock fl;
808 struct stat filebuf;
809
810 if (fstat(fd, &filebuf) < 0)
811 return -1;
812
813 if (filebuf.st_size < length) {
814
815 /* extend file length */
816
817 if ((lseek(fd, (length - 1), 0)) < 0)
818 return -1;
819
820 /* write a "0" byte */
821
822 if ((write(fd, "", 1)) != 1)
823 return -1;
824 }
825 else {
826 /* truncate length */
827
828 fl.l_whence = 0;
829 fl.l_len = 0;
830 fl.l_start = length;
831 fl.l_type = F_WRLCK; /* write lock on file space */
832
833 /*
834 * This relies on the UNDOCUMENTED F_FREESP argument to
835 * fcntl(2), which truncates the file so that it ends at the
836 * position indicated by fl.l_start.
837 *
838 * Will minor miracles never cease?
839 */
840
841 if (fcntl(fd, F_FREESP, &fl) < 0)
842 return -1;
843
844 }
845
846 return 0;
847}
848#endif /* F_FREESP */
849
a687059c 850int
ff8e2863
LW
851do_truncate(str,arg,gimme,arglast)
852STR *str;
853register ARG *arg;
854int gimme;
855int *arglast;
856{
857 register ARRAY *ary = stack;
858 register int sp = arglast[0] + 1;
859 off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
860 int result = 1;
861 STAB *tmpstab;
862
fe14fcc3
LW
863#if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE)
864#ifdef HAS_TRUNCATE
ff8e2863
LW
865 if ((arg[1].arg_type & A_MASK) == A_WORD) {
866 tmpstab = arg[1].arg_ptr.arg_stab;
867 if (!stab_io(tmpstab) ||
868 ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
869 result = 0;
870 }
871 else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
872 result = 0;
873#else
ff8e2863
LW
874 if ((arg[1].arg_type & A_MASK) == A_WORD) {
875 tmpstab = arg[1].arg_ptr.arg_stab;
876 if (!stab_io(tmpstab) ||
877 chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
878 result = 0;
879 }
880 else {
881 int tmpfd;
882
883 if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
884 result = 0;
885 else {
886 if (chsize(tmpfd, len) < 0)
887 result = 0;
888 close(tmpfd);
889 }
890 }
891#endif
892
893 if (result)
894 str_sset(str,&str_yes);
895 else
896 str_sset(str,&str_undef);
897 STABSET(str);
898 ary->ary_array[sp] = str;
899 return sp;
900#else
901 fatal("truncate not implemented");
902#endif
903}
904
905int
a687059c
LW
906looks_like_number(str)
907STR *str;
908{
909 register char *s;
910 register char *send;
911
912 if (!str->str_pok)
913 return TRUE;
914 s = str->str_ptr;
915 send = s + str->str_cur;
916 while (isspace(*s))
917 s++;
918 if (s >= send)
919 return FALSE;
920 if (*s == '+' || *s == '-')
921 s++;
922 while (isdigit(*s))
923 s++;
924 if (s == send)
925 return TRUE;
926 if (*s == '.')
927 s++;
928 else if (s == str->str_ptr)
929 return FALSE;
930 while (isdigit(*s))
931 s++;
932 if (s == send)
933 return TRUE;
934 if (*s == 'e' || *s == 'E') {
935 s++;
936 if (*s == '+' || *s == '-')
937 s++;
938 while (isdigit(*s))
939 s++;
940 }
941 while (isspace(*s))
942 s++;
943 if (s >= send)
944 return TRUE;
945 return FALSE;
946}
947
948bool
949do_print(str,fp)
950register STR *str;
951FILE *fp;
952{
953 register char *tmps;
954
955 if (!fp) {
956 if (dowarn)
957 warn("print to unopened file");
958 return FALSE;
959 }
960 if (!str)
ff8e2863 961 return TRUE;
a687059c
LW
962 if (ofmt &&
963 ((str->str_nok && str->str_u.str_nval != 0.0)
ff8e2863 964 || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
a687059c 965 fprintf(fp, ofmt, str->str_u.str_nval);
ff8e2863
LW
966 return !ferror(fp);
967 }
a687059c
LW
968 else {
969 tmps = str_get(str);
c2ab57d4 970 if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'B' && tmps[3] == '\0'
a687059c 971 && str->str_cur == sizeof(STBP) && strlen(tmps) < str->str_cur) {
fe14fcc3 972 STR *tmpstr = str_mortal(&str_undef);
c2ab57d4
LW
973 stab_fullname(tmpstr,((STAB*)str));/* a stab value, be nice */
974 str = tmpstr;
975 tmps = str->str_ptr;
a687059c
LW
976 putc('*',fp);
977 }
ff8e2863 978 if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
a687059c
LW
979 return FALSE;
980 }
981 return TRUE;
982}
983
984bool
985do_aprint(arg,fp,arglast)
986register ARG *arg;
987register FILE *fp;
988int *arglast;
989{
990 register STR **st = stack->ary_array;
991 register int sp = arglast[1];
992 register int retval;
993 register int items = arglast[2] - sp;
994
995 if (!fp) {
996 if (dowarn)
997 warn("print to unopened file");
998 return FALSE;
999 }
1000 st += ++sp;
1001 if (arg->arg_type == O_PRTF) {
1002 do_sprintf(arg->arg_ptr.arg_str,items,st);
1003 retval = do_print(arg->arg_ptr.arg_str,fp);
1004 }
1005 else {
1006 retval = (items <= 0);
1007 for (; items > 0; items--,st++) {
1008 if (retval && ofslen) {
ff8e2863 1009 if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
a687059c
LW
1010 retval = FALSE;
1011 break;
1012 }
1013 }
1014 if (!(retval = do_print(*st, fp)))
1015 break;
1016 }
1017 if (retval && orslen)
ff8e2863 1018 if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
a687059c
LW
1019 retval = FALSE;
1020 }
1021 return retval;
1022}
1023
1024int
1025mystat(arg,str)
1026ARG *arg;
1027STR *str;
1028{
1029 STIO *stio;
1030
fe14fcc3 1031 laststype = O_STAT;
a687059c
LW
1032 if (arg[1].arg_type & A_DONT) {
1033 stio = stab_io(arg[1].arg_ptr.arg_stab);
1034 if (stio && stio->ifp) {
1035 statstab = arg[1].arg_ptr.arg_stab;
1036 str_set(statname,"");
57ebbfd0 1037 return (laststatval = fstat(fileno(stio->ifp), &statcache));
a687059c
LW
1038 }
1039 else {
1040 if (arg[1].arg_ptr.arg_stab == defstab)
57ebbfd0 1041 return laststatval;
a687059c
LW
1042 if (dowarn)
1043 warn("Stat on unopened file <%s>",
1044 stab_name(arg[1].arg_ptr.arg_stab));
1045 statstab = Nullstab;
1046 str_set(statname,"");
57ebbfd0 1047 return (laststatval = -1);
a687059c
LW
1048 }
1049 }
1050 else {
1051 statstab = Nullstab;
c623bd54 1052 str_set(statname,str_get(str));
57ebbfd0 1053 return (laststatval = stat(str_get(str),&statcache));
a687059c
LW
1054 }
1055}
1056
c623bd54
LW
1057int
1058mylstat(arg,str)
1059ARG *arg;
1060STR *str;
1061{
fe14fcc3
LW
1062 if (arg[1].arg_type & A_DONT) {
1063 if (arg[1].arg_ptr.arg_stab == defstab) {
1064 if (laststype != O_LSTAT)
1065 fatal("The stat preceding -l _ wasn't an lstat");
1066 return laststatval;
1067 }
1068 fatal("You can't use -l on a filehandle");
1069 }
c623bd54 1070
fe14fcc3 1071 laststype = O_LSTAT;
c623bd54
LW
1072 statstab = Nullstab;
1073 str_set(statname,str_get(str));
fe14fcc3 1074#ifdef HAS_LSTAT
c623bd54
LW
1075 return (laststatval = lstat(str_get(str),&statcache));
1076#else
1077 return (laststatval = stat(str_get(str),&statcache));
1078#endif
1079}
1080
a687059c
LW
1081STR *
1082do_fttext(arg,str)
1083register ARG *arg;
1084STR *str;
1085{
1086 int i;
1087 int len;
1088 int odd = 0;
1089 STDCHAR tbuf[512];
1090 register STDCHAR *s;
1091 register STIO *stio;
1092
1093 if (arg[1].arg_type & A_DONT) {
1094 if (arg[1].arg_ptr.arg_stab == defstab) {
1095 if (statstab)
1096 stio = stab_io(statstab);
1097 else {
1098 str = statname;
1099 goto really_filename;
1100 }
1101 }
1102 else {
1103 statstab = arg[1].arg_ptr.arg_stab;
1104 str_set(statname,"");
1105 stio = stab_io(statstab);
1106 }
1107 if (stio && stio->ifp) {
1108#ifdef STDSTDIO
1109 fstat(fileno(stio->ifp),&statcache);
1110 if (stio->ifp->_cnt <= 0) {
1111 i = getc(stio->ifp);
1112 if (i != EOF)
1113 (void)ungetc(i,stio->ifp);
1114 }
1115 if (stio->ifp->_cnt <= 0) /* null file is anything */
1116 return &str_yes;
1117 len = stio->ifp->_cnt + (stio->ifp->_ptr - stio->ifp->_base);
1118 s = stio->ifp->_base;
1119#else
1120 fatal("-T and -B not implemented on filehandles\n");
1121#endif
1122 }
1123 else {
1124 if (dowarn)
1125 warn("Test on unopened file <%s>",
1126 stab_name(arg[1].arg_ptr.arg_stab));
1127 return &str_undef;
1128 }
1129 }
1130 else {
1131 statstab = Nullstab;
c623bd54 1132 str_set(statname,str_get(str));
a687059c
LW
1133 really_filename:
1134 i = open(str_get(str),0);
1135 if (i < 0)
1136 return &str_undef;
1137 fstat(i,&statcache);
1138 len = read(i,tbuf,512);
fe14fcc3 1139 (void)close(i);
a687059c
LW
1140 if (len <= 0) /* null file is anything */
1141 return &str_yes;
a687059c
LW
1142 s = tbuf;
1143 }
1144
1145 /* now scan s to look for textiness */
1146
1147 for (i = 0; i < len; i++,s++) {
1148 if (!*s) { /* null never allowed in text */
1149 odd += len;
1150 break;
1151 }
1152 else if (*s & 128)
1153 odd++;
1154 else if (*s < 32 &&
1155 *s != '\n' && *s != '\r' && *s != '\b' &&
1156 *s != '\t' && *s != '\f' && *s != 27)
1157 odd++;
1158 }
1159
1160 if ((odd * 10 > len) == (arg->arg_type == O_FTTEXT)) /* allow 10% odd */
1161 return &str_no;
1162 else
1163 return &str_yes;
1164}
1165
1166bool
1167do_aexec(really,arglast)
1168STR *really;
1169int *arglast;
1170{
1171 register STR **st = stack->ary_array;
1172 register int sp = arglast[1];
1173 register int items = arglast[2] - sp;
1174 register char **a;
1175 char **argv;
1176 char *tmps;
1177
1178 if (items) {
1179 New(401,argv, items+1, char*);
1180 a = argv;
1181 for (st += ++sp; items > 0; items--,st++) {
1182 if (*st)
1183 *a++ = str_get(*st);
1184 else
1185 *a++ = "";
1186 }
1187 *a = Nullch;
1188#ifdef TAINT
1189 if (*argv[0] != '/') /* will execvp use PATH? */
1190 taintenv(); /* testing IFS here is overkill, probably */
1191#endif
1192 if (really && *(tmps = str_get(really)))
1193 execvp(tmps,argv);
1194 else
1195 execvp(argv[0],argv);
1196 Safefree(argv);
1197 }
1198 return FALSE;
1199}
1200
ff8e2863
LW
1201static char **Argv = Null(char **);
1202static char *Cmd = Nullch;
1203
fe14fcc3 1204void
ff8e2863
LW
1205do_execfree()
1206{
1207 if (Argv) {
1208 Safefree(Argv);
1209 Argv = Null(char **);
1210 }
1211 if (Cmd) {
1212 Safefree(Cmd);
1213 Cmd = Nullch;
1214 }
1215}
1216
a687059c
LW
1217bool
1218do_exec(cmd)
1219char *cmd;
1220{
1221 register char **a;
1222 register char *s;
a687059c
LW
1223 char flags[10];
1224
a687059c
LW
1225 /* save an extra exec if possible */
1226
bf38876a
LW
1227#ifdef CSH
1228 if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
a687059c 1229 strcpy(flags,"-c");
bf38876a 1230 s = cmd+cshlen+3;
a687059c
LW
1231 if (*s == 'f') {
1232 s++;
1233 strcat(flags,"f");
1234 }
1235 if (*s == ' ')
1236 s++;
1237 if (*s++ == '\'') {
1238 char *ncmd = s;
1239
1240 while (*s)
1241 s++;
1242 if (s[-1] == '\n')
1243 *--s = '\0';
1244 if (s[-1] == '\'') {
1245 *--s = '\0';
bf38876a 1246 execl(cshname,"csh", flags,ncmd,(char*)0);
a687059c
LW
1247 *s = '\'';
1248 return FALSE;
1249 }
1250 }
1251 }
bf38876a 1252#endif /* CSH */
a687059c
LW
1253
1254 /* see if there are shell metacharacters in it */
1255
63f2c1e1
LW
1256 for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
1257 if (*s == '=')
1258 goto doshell;
a687059c
LW
1259 for (s = cmd; *s; s++) {
1260 if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
1261 if (*s == '\n' && !s[1]) {
1262 *s = '\0';
1263 break;
1264 }
1265 doshell:
1266 execl("/bin/sh","sh","-c",cmd,(char*)0);
1267 return FALSE;
1268 }
1269 }
ff8e2863
LW
1270 New(402,Argv, (s - cmd) / 2 + 2, char*);
1271 Cmd = nsavestr(cmd, s-cmd);
1272 a = Argv;
1273 for (s = Cmd; *s;) {
a687059c
LW
1274 while (*s && isspace(*s)) s++;
1275 if (*s)
1276 *(a++) = s;
1277 while (*s && !isspace(*s)) s++;
1278 if (*s)
1279 *s++ = '\0';
1280 }
1281 *a = Nullch;
ff8e2863
LW
1282 if (Argv[0]) {
1283 execvp(Argv[0],Argv);
b1248f16 1284 if (errno == ENOEXEC) { /* for system V NIH syndrome */
ff8e2863 1285 do_execfree();
a687059c 1286 goto doshell;
b1248f16 1287 }
a687059c 1288 }
ff8e2863 1289 do_execfree();
a687059c
LW
1290 return FALSE;
1291}
1292
fe14fcc3 1293#ifdef HAS_SOCKET
a687059c
LW
1294int
1295do_socket(stab, arglast)
1296STAB *stab;
1297int *arglast;
1298{
1299 register STR **st = stack->ary_array;
1300 register int sp = arglast[1];
1301 register STIO *stio;
1302 int domain, type, protocol, fd;
1303
1304 if (!stab)
1305 return FALSE;
1306
1307 stio = stab_io(stab);
1308 if (!stio)
1309 stio = stab_io(stab) = stio_new();
1310 else if (stio->ifp)
1311 do_close(stab,FALSE);
1312
1313 domain = (int)str_gnum(st[++sp]);
1314 type = (int)str_gnum(st[++sp]);
1315 protocol = (int)str_gnum(st[++sp]);
1316#ifdef TAINT
1317 taintproper("Insecure dependency in socket");
1318#endif
1319 fd = socket(domain,type,protocol);
1320 if (fd < 0)
1321 return FALSE;
1322 stio->ifp = fdopen(fd, "r"); /* stdio gets confused about sockets */
1323 stio->ofp = fdopen(fd, "w");
1324 stio->type = 's';
fe14fcc3
LW
1325 if (!stio->ifp || !stio->ofp) {
1326 if (stio->ifp) fclose(stio->ifp);
1327 if (stio->ofp) fclose(stio->ofp);
1328 if (!stio->ifp && !stio->ofp) close(fd);
1329 return FALSE;
1330 }
a687059c
LW
1331
1332 return TRUE;
1333}
1334
1335int
1336do_bind(stab, arglast)
1337STAB *stab;
1338int *arglast;
1339{
1340 register STR **st = stack->ary_array;
1341 register int sp = arglast[1];
1342 register STIO *stio;
1343 char *addr;
1344
1345 if (!stab)
1346 goto nuts;
1347
1348 stio = stab_io(stab);
1349 if (!stio || !stio->ifp)
1350 goto nuts;
1351
1352 addr = str_get(st[++sp]);
1353#ifdef TAINT
1354 taintproper("Insecure dependency in bind");
1355#endif
1356 return bind(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1357
1358nuts:
1359 if (dowarn)
1360 warn("bind() on closed fd");
1361 return FALSE;
1362
1363}
1364
1365int
1366do_connect(stab, arglast)
1367STAB *stab;
1368int *arglast;
1369{
1370 register STR **st = stack->ary_array;
1371 register int sp = arglast[1];
1372 register STIO *stio;
1373 char *addr;
1374
1375 if (!stab)
1376 goto nuts;
1377
1378 stio = stab_io(stab);
1379 if (!stio || !stio->ifp)
1380 goto nuts;
1381
1382 addr = str_get(st[++sp]);
1383#ifdef TAINT
1384 taintproper("Insecure dependency in connect");
1385#endif
1386 return connect(fileno(stio->ifp), addr, st[sp]->str_cur) >= 0;
1387
1388nuts:
1389 if (dowarn)
1390 warn("connect() on closed fd");
1391 return FALSE;
1392
1393}
1394
1395int
1396do_listen(stab, arglast)
1397STAB *stab;
1398int *arglast;
1399{
1400 register STR **st = stack->ary_array;
1401 register int sp = arglast[1];
1402 register STIO *stio;
1403 int backlog;
1404
1405 if (!stab)
1406 goto nuts;
1407
1408 stio = stab_io(stab);
1409 if (!stio || !stio->ifp)
1410 goto nuts;
1411
1412 backlog = (int)str_gnum(st[++sp]);
1413 return listen(fileno(stio->ifp), backlog) >= 0;
1414
1415nuts:
1416 if (dowarn)
1417 warn("listen() on closed fd");
1418 return FALSE;
1419}
1420
1421void
1422do_accept(str, nstab, gstab)
1423STR *str;
1424STAB *nstab;
1425STAB *gstab;
1426{
1427 register STIO *nstio;
1428 register STIO *gstio;
1429 int len = sizeof buf;
1430 int fd;
1431
1432 if (!nstab)
1433 goto badexit;
1434 if (!gstab)
1435 goto nuts;
1436
1437 gstio = stab_io(gstab);
1438 nstio = stab_io(nstab);
1439
1440 if (!gstio || !gstio->ifp)
1441 goto nuts;
1442 if (!nstio)
1443 nstio = stab_io(nstab) = stio_new();
1444 else if (nstio->ifp)
1445 do_close(nstab,FALSE);
1446
6e21c824 1447 fd = accept(fileno(gstio->ifp),(struct sockaddr *)buf,&len);
a687059c
LW
1448 if (fd < 0)
1449 goto badexit;
1450 nstio->ifp = fdopen(fd, "r");
1451 nstio->ofp = fdopen(fd, "w");
1452 nstio->type = 's';
fe14fcc3
LW
1453 if (!nstio->ifp || !nstio->ofp) {
1454 if (nstio->ifp) fclose(nstio->ifp);
1455 if (nstio->ofp) fclose(nstio->ofp);
1456 if (!nstio->ifp && !nstio->ofp) close(fd);
1457 goto badexit;
1458 }
a687059c
LW
1459
1460 str_nset(str, buf, len);
1461 return;
1462
1463nuts:
1464 if (dowarn)
1465 warn("accept() on closed fd");
1466badexit:
1467 str_sset(str,&str_undef);
1468 return;
1469}
1470
1471int
1472do_shutdown(stab, arglast)
1473STAB *stab;
1474int *arglast;
1475{
1476 register STR **st = stack->ary_array;
1477 register int sp = arglast[1];
1478 register STIO *stio;
1479 int how;
1480
1481 if (!stab)
1482 goto nuts;
1483
1484 stio = stab_io(stab);
1485 if (!stio || !stio->ifp)
1486 goto nuts;
1487
1488 how = (int)str_gnum(st[++sp]);
1489 return shutdown(fileno(stio->ifp), how) >= 0;
1490
1491nuts:
1492 if (dowarn)
1493 warn("shutdown() on closed fd");
1494 return FALSE;
1495
1496}
1497
1498int
1499do_sopt(optype, stab, arglast)
1500int optype;
1501STAB *stab;
1502int *arglast;
1503{
1504 register STR **st = stack->ary_array;
1505 register int sp = arglast[1];
1506 register STIO *stio;
1507 int fd;
1508 int lvl;
1509 int optname;
1510
1511 if (!stab)
1512 goto nuts;
1513
1514 stio = stab_io(stab);
1515 if (!stio || !stio->ifp)
1516 goto nuts;
1517
1518 fd = fileno(stio->ifp);
1519 lvl = (int)str_gnum(st[sp+1]);
1520 optname = (int)str_gnum(st[sp+2]);
1521 switch (optype) {
1522 case O_GSOCKOPT:
fe14fcc3 1523 st[sp] = str_2mortal(str_new(257));
a687059c 1524 st[sp]->str_cur = 256;
bf38876a 1525 st[sp]->str_pok = 1;
a687059c
LW
1526 if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
1527 goto nuts;
1528 break;
1529 case O_SSOCKOPT:
1530 st[sp] = st[sp+3];
1531 if (setsockopt(fd, lvl, optname, st[sp]->str_ptr, st[sp]->str_cur) < 0)
1532 goto nuts;
1533 st[sp] = &str_yes;
1534 break;
1535 }
1536
1537 return sp;
1538
1539nuts:
1540 if (dowarn)
bf38876a 1541 warn("[gs]etsockopt() on closed fd");
a687059c
LW
1542 st[sp] = &str_undef;
1543 return sp;
1544
1545}
1546
1547int
1548do_getsockname(optype, stab, arglast)
1549int optype;
1550STAB *stab;
1551int *arglast;
1552{
1553 register STR **st = stack->ary_array;
1554 register int sp = arglast[1];
1555 register STIO *stio;
1556 int fd;
1557
1558 if (!stab)
1559 goto nuts;
1560
1561 stio = stab_io(stab);
1562 if (!stio || !stio->ifp)
1563 goto nuts;
1564
fe14fcc3 1565 st[sp] = str_2mortal(str_new(257));
a687059c 1566 st[sp]->str_cur = 256;
bf38876a 1567 st[sp]->str_pok = 1;
a687059c
LW
1568 fd = fileno(stio->ifp);
1569 switch (optype) {
1570 case O_GETSOCKNAME:
1571 if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
ff8e2863 1572 goto nuts2;
a687059c
LW
1573 break;
1574 case O_GETPEERNAME:
1575 if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
ff8e2863 1576 goto nuts2;
a687059c
LW
1577 break;
1578 }
1579
1580 return sp;
1581
1582nuts:
1583 if (dowarn)
bf38876a 1584 warn("get{sock,peer}name() on closed fd");
ff8e2863 1585nuts2:
a687059c
LW
1586 st[sp] = &str_undef;
1587 return sp;
1588
1589}
1590
1591int
1592do_ghent(which,gimme,arglast)
1593int which;
1594int gimme;
1595int *arglast;
1596{
1597 register ARRAY *ary = stack;
1598 register int sp = arglast[0];
1599 register char **elem;
1600 register STR *str;
bf38876a 1601 struct hostent *gethostbyname();
a687059c 1602 struct hostent *gethostbyaddr();
fe14fcc3 1603#ifdef HAS_GETHOSTENT
a687059c
LW
1604 struct hostent *gethostent();
1605#endif
1606 struct hostent *hent;
1607 unsigned long len;
1608
1609 if (gimme != G_ARRAY) {
fe14fcc3 1610 astore(ary, ++sp, str_mortal(&str_undef));
a687059c
LW
1611 return sp;
1612 }
1613
1614 if (which == O_GHBYNAME) {
1615 char *name = str_get(ary->ary_array[sp+1]);
1616
1617 hent = gethostbyname(name);
1618 }
1619 else if (which == O_GHBYADDR) {
1620 STR *addrstr = ary->ary_array[sp+1];
1621 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
1622 char *addr = str_get(addrstr);
1623
1624 hent = gethostbyaddr(addr,addrstr->str_cur,addrtype);
1625 }
1626 else
fe14fcc3 1627#ifdef HAS_GETHOSTENT
a687059c
LW
1628 hent = gethostent();
1629#else
1630 fatal("gethostent not implemented");
1631#endif
1632 if (hent) {
1633#ifndef lint
fe14fcc3 1634 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 1635 str_set(str, hent->h_name);
fe14fcc3 1636 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1637 for (elem = hent->h_aliases; *elem; elem++) {
1638 str_cat(str, *elem);
1639 if (elem[1])
1640 str_ncat(str," ",1);
1641 }
fe14fcc3 1642 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 1643 str_numset(str, (double)hent->h_addrtype);
fe14fcc3 1644 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1645 len = hent->h_length;
1646 str_numset(str, (double)len);
1647#ifdef h_addr
1648 for (elem = hent->h_addr_list; *elem; elem++) {
fe14fcc3 1649 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1650 str_nset(str, *elem, len);
1651 }
1652#else
fe14fcc3 1653 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1654 str_nset(str, hent->h_addr, len);
1655#endif /* h_addr */
1656#else /* lint */
1657 elem = Nullch;
1658 elem = elem;
fe14fcc3 1659 (void)astore(ary, ++sp, str_mortal(&str_no));
a687059c
LW
1660#endif /* lint */
1661 }
1662
1663 return sp;
1664}
1665
1666int
1667do_gnent(which,gimme,arglast)
1668int which;
1669int gimme;
1670int *arglast;
1671{
1672 register ARRAY *ary = stack;
1673 register int sp = arglast[0];
1674 register char **elem;
1675 register STR *str;
1676 struct netent *getnetbyname();
1677 struct netent *getnetbyaddr();
1678 struct netent *getnetent();
1679 struct netent *nent;
1680
1681 if (gimme != G_ARRAY) {
fe14fcc3 1682 astore(ary, ++sp, str_mortal(&str_undef));
a687059c
LW
1683 return sp;
1684 }
1685
1686 if (which == O_GNBYNAME) {
1687 char *name = str_get(ary->ary_array[sp+1]);
1688
1689 nent = getnetbyname(name);
1690 }
1691 else if (which == O_GNBYADDR) {
fe14fcc3 1692 unsigned long addr = U_L(str_gnum(ary->ary_array[sp+1]));
a687059c 1693 int addrtype = (int)str_gnum(ary->ary_array[sp+2]);
a687059c 1694
fe14fcc3 1695 nent = getnetbyaddr((long)addr,addrtype);
a687059c
LW
1696 }
1697 else
1698 nent = getnetent();
1699
1700 if (nent) {
1701#ifndef lint
fe14fcc3 1702 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 1703 str_set(str, nent->n_name);
fe14fcc3 1704 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1705 for (elem = nent->n_aliases; *elem; elem++) {
1706 str_cat(str, *elem);
1707 if (elem[1])
1708 str_ncat(str," ",1);
1709 }
fe14fcc3 1710 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 1711 str_numset(str, (double)nent->n_addrtype);
fe14fcc3 1712 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1713 str_numset(str, (double)nent->n_net);
1714#else /* lint */
1715 elem = Nullch;
1716 elem = elem;
fe14fcc3 1717 (void)astore(ary, ++sp, str_mortal(&str_no));
a687059c
LW
1718#endif /* lint */
1719 }
1720
1721 return sp;
1722}
1723
1724int
1725do_gpent(which,gimme,arglast)
1726int which;
1727int gimme;
1728int *arglast;
1729{
1730 register ARRAY *ary = stack;
1731 register int sp = arglast[0];
1732 register char **elem;
1733 register STR *str;
1734 struct protoent *getprotobyname();
1735 struct protoent *getprotobynumber();
1736 struct protoent *getprotoent();
1737 struct protoent *pent;
1738
1739 if (gimme != G_ARRAY) {
fe14fcc3 1740 astore(ary, ++sp, str_mortal(&str_undef));
a687059c
LW
1741 return sp;
1742 }
1743
1744 if (which == O_GPBYNAME) {
1745 char *name = str_get(ary->ary_array[sp+1]);
1746
1747 pent = getprotobyname(name);
1748 }
1749 else if (which == O_GPBYNUMBER) {
1750 int proto = (int)str_gnum(ary->ary_array[sp+1]);
1751
1752 pent = getprotobynumber(proto);
1753 }
1754 else
1755 pent = getprotoent();
1756
1757 if (pent) {
1758#ifndef lint
fe14fcc3 1759 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 1760 str_set(str, pent->p_name);
fe14fcc3 1761 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1762 for (elem = pent->p_aliases; *elem; elem++) {
1763 str_cat(str, *elem);
1764 if (elem[1])
1765 str_ncat(str," ",1);
1766 }
fe14fcc3 1767 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1768 str_numset(str, (double)pent->p_proto);
1769#else /* lint */
1770 elem = Nullch;
1771 elem = elem;
fe14fcc3 1772 (void)astore(ary, ++sp, str_mortal(&str_no));
a687059c
LW
1773#endif /* lint */
1774 }
1775
1776 return sp;
1777}
1778
1779int
1780do_gsent(which,gimme,arglast)
1781int which;
1782int gimme;
1783int *arglast;
1784{
1785 register ARRAY *ary = stack;
1786 register int sp = arglast[0];
1787 register char **elem;
1788 register STR *str;
1789 struct servent *getservbyname();
1790 struct servent *getservbynumber();
1791 struct servent *getservent();
1792 struct servent *sent;
1793
1794 if (gimme != G_ARRAY) {
fe14fcc3 1795 astore(ary, ++sp, str_mortal(&str_undef));
a687059c
LW
1796 return sp;
1797 }
1798
1799 if (which == O_GSBYNAME) {
1800 char *name = str_get(ary->ary_array[sp+1]);
1801 char *proto = str_get(ary->ary_array[sp+2]);
1802
1803 if (proto && !*proto)
1804 proto = Nullch;
1805
1806 sent = getservbyname(name,proto);
1807 }
1808 else if (which == O_GSBYPORT) {
1809 int port = (int)str_gnum(ary->ary_array[sp+1]);
1810 char *proto = str_get(ary->ary_array[sp+2]);
1811
1812 sent = getservbyport(port,proto);
1813 }
1814 else
1815 sent = getservent();
1816 if (sent) {
1817#ifndef lint
fe14fcc3 1818 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 1819 str_set(str, sent->s_name);
fe14fcc3 1820 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1821 for (elem = sent->s_aliases; *elem; elem++) {
1822 str_cat(str, *elem);
1823 if (elem[1])
1824 str_ncat(str," ",1);
1825 }
fe14fcc3
LW
1826 (void)astore(ary, ++sp, str = str_mortal(&str_no));
1827#ifdef HAS_NTOHS
a687059c
LW
1828 str_numset(str, (double)ntohs(sent->s_port));
1829#else
1830 str_numset(str, (double)(sent->s_port));
1831#endif
fe14fcc3 1832 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
1833 str_set(str, sent->s_proto);
1834#else /* lint */
1835 elem = Nullch;
1836 elem = elem;
fe14fcc3 1837 (void)astore(ary, ++sp, str_mortal(&str_no));
a687059c
LW
1838#endif /* lint */
1839 }
1840
1841 return sp;
1842}
1843
fe14fcc3 1844#endif /* HAS_SOCKET */
ff8e2863 1845
fe14fcc3 1846#ifdef HAS_SELECT
a687059c
LW
1847int
1848do_select(gimme,arglast)
1849int gimme;
1850int *arglast;
1851{
1852 register STR **st = stack->ary_array;
1853 register int sp = arglast[0];
1854 register int i;
1855 register int j;
1856 register char *s;
1857 register STR *str;
1858 double value;
1859 int maxlen = 0;
1860 int nfound;
1861 struct timeval timebuf;
1862 struct timeval *tbuf = &timebuf;
663a0e37
LW
1863 int growsize;
1864#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1865 int masksize;
1866 int offset;
1867 char *fd_sets[4];
1868 int k;
1869
1870#if BYTEORDER & 0xf0000
1871#define ORDERBYTE (0x88888888 - BYTEORDER)
1872#else
1873#define ORDERBYTE (0x4444 - BYTEORDER)
1874#endif
1875
1876#endif
a687059c
LW
1877
1878 for (i = 1; i <= 3; i++) {
663a0e37 1879 j = st[sp+i]->str_cur;
a687059c
LW
1880 if (maxlen < j)
1881 maxlen = j;
1882 }
663a0e37
LW
1883
1884#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
1885 growsize = maxlen; /* little endians can use vecs directly */
1886#else
1887#ifdef NFDBITS
1888
1889#ifndef NBBY
1890#define NBBY 8
1891#endif
1892
1893 masksize = NFDBITS / NBBY;
1894#else
1895 masksize = sizeof(long); /* documented int, everyone seems to use long */
1896#endif
1897 growsize = maxlen + (masksize - (maxlen % masksize));
1898 Zero(&fd_sets[0], 4, char*);
1899#endif
1900
a687059c
LW
1901 for (i = 1; i <= 3; i++) {
1902 str = st[sp+i];
1903 j = str->str_len;
663a0e37 1904 if (j < growsize) {
a687059c 1905 if (str->str_pok) {
ff8e2863 1906 Str_Grow(str,growsize);
a687059c 1907 s = str_get(str) + j;
663a0e37 1908 while (++j <= growsize) {
a687059c
LW
1909 *s++ = '\0';
1910 }
1911 }
1912 else if (str->str_ptr) {
1913 Safefree(str->str_ptr);
1914 str->str_ptr = Nullch;
1915 }
1916 }
663a0e37
LW
1917#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
1918 s = str->str_ptr;
1919 if (s) {
1920 New(403, fd_sets[i], growsize, char);
1921 for (offset = 0; offset < growsize; offset += masksize) {
1922 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1923 fd_sets[i][j+offset] = s[(k % masksize) + offset];
1924 }
1925 }
1926#endif
a687059c
LW
1927 }
1928 str = st[sp+4];
1929 if (str->str_nok || str->str_pok) {
1930 value = str_gnum(str);
1931 if (value < 0.0)
1932 value = 0.0;
1933 timebuf.tv_sec = (long)value;
1934 value -= (double)timebuf.tv_sec;
1935 timebuf.tv_usec = (long)(value * 1000000.0);
1936 }
1937 else
1938 tbuf = Null(struct timeval*);
1939
663a0e37 1940#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
a687059c
LW
1941 nfound = select(
1942 maxlen * 8,
1943 st[sp+1]->str_ptr,
1944 st[sp+2]->str_ptr,
1945 st[sp+3]->str_ptr,
1946 tbuf);
663a0e37
LW
1947#else
1948 nfound = select(
1949 maxlen * 8,
1950 fd_sets[1],
1951 fd_sets[2],
1952 fd_sets[3],
1953 tbuf);
1954 for (i = 1; i <= 3; i++) {
1955 if (fd_sets[i]) {
1956 str = st[sp+i];
1957 s = str->str_ptr;
1958 for (offset = 0; offset < growsize; offset += masksize) {
1959 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
1960 s[(k % masksize) + offset] = fd_sets[i][j+offset];
1961 }
1962 }
1963 }
1964#endif
a687059c 1965
fe14fcc3 1966 st[++sp] = str_mortal(&str_no);
a687059c
LW
1967 str_numset(st[sp], (double)nfound);
1968 if (gimme == G_ARRAY && tbuf) {
1969 value = (double)(timebuf.tv_sec) +
1970 (double)(timebuf.tv_usec) / 1000000.0;
fe14fcc3 1971 st[++sp] = str_mortal(&str_no);
a687059c
LW
1972 str_numset(st[sp], value);
1973 }
1974 return sp;
1975}
ff8e2863 1976#endif /* SELECT */
a687059c 1977
fe14fcc3 1978#ifdef HAS_SOCKET
a687059c
LW
1979int
1980do_spair(stab1, stab2, arglast)
1981STAB *stab1;
1982STAB *stab2;
1983int *arglast;
1984{
1985 register STR **st = stack->ary_array;
1986 register int sp = arglast[2];
1987 register STIO *stio1;
1988 register STIO *stio2;
1989 int domain, type, protocol, fd[2];
1990
1991 if (!stab1 || !stab2)
1992 return FALSE;
1993
1994 stio1 = stab_io(stab1);
1995 stio2 = stab_io(stab2);
1996 if (!stio1)
1997 stio1 = stab_io(stab1) = stio_new();
1998 else if (stio1->ifp)
1999 do_close(stab1,FALSE);
2000 if (!stio2)
2001 stio2 = stab_io(stab2) = stio_new();
2002 else if (stio2->ifp)
2003 do_close(stab2,FALSE);
2004
2005 domain = (int)str_gnum(st[++sp]);
2006 type = (int)str_gnum(st[++sp]);
2007 protocol = (int)str_gnum(st[++sp]);
2008#ifdef TAINT
2009 taintproper("Insecure dependency in socketpair");
2010#endif
fe14fcc3 2011#ifdef HAS_SOCKETPAIR
a687059c
LW
2012 if (socketpair(domain,type,protocol,fd) < 0)
2013 return FALSE;
2014#else
2015 fatal("Socketpair unimplemented");
2016#endif
2017 stio1->ifp = fdopen(fd[0], "r");
2018 stio1->ofp = fdopen(fd[0], "w");
2019 stio1->type = 's';
2020 stio2->ifp = fdopen(fd[1], "r");
2021 stio2->ofp = fdopen(fd[1], "w");
2022 stio2->type = 's';
fe14fcc3
LW
2023 if (!stio1->ifp || !stio1->ofp || !stio2->ifp || !stio2->ofp) {
2024 if (stio1->ifp) fclose(stio1->ifp);
2025 if (stio1->ofp) fclose(stio1->ofp);
2026 if (!stio1->ifp && !stio1->ofp) close(fd[0]);
2027 if (stio2->ifp) fclose(stio2->ifp);
2028 if (stio2->ofp) fclose(stio2->ofp);
2029 if (!stio2->ifp && !stio2->ofp) close(fd[1]);
2030 return FALSE;
2031 }
a687059c
LW
2032
2033 return TRUE;
2034}
2035
fe14fcc3 2036#endif /* HAS_SOCKET */
a687059c
LW
2037
2038int
2039do_gpwent(which,gimme,arglast)
2040int which;
2041int gimme;
2042int *arglast;
2043{
2044#ifdef I_PWD
2045 register ARRAY *ary = stack;
2046 register int sp = arglast[0];
a687059c
LW
2047 register STR *str;
2048 struct passwd *getpwnam();
2049 struct passwd *getpwuid();
2050 struct passwd *getpwent();
2051 struct passwd *pwent;
a687059c
LW
2052
2053 if (gimme != G_ARRAY) {
fe14fcc3 2054 astore(ary, ++sp, str_mortal(&str_undef));
a687059c
LW
2055 return sp;
2056 }
2057
2058 if (which == O_GPWNAM) {
2059 char *name = str_get(ary->ary_array[sp+1]);
2060
2061 pwent = getpwnam(name);
2062 }
2063 else if (which == O_GPWUID) {
2064 int uid = (int)str_gnum(ary->ary_array[sp+1]);
2065
2066 pwent = getpwuid(uid);
2067 }
2068 else
2069 pwent = getpwent();
2070
2071 if (pwent) {
fe14fcc3 2072 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2073 str_set(str, pwent->pw_name);
fe14fcc3 2074 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2075 str_set(str, pwent->pw_passwd);
fe14fcc3 2076 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2077 str_numset(str, (double)pwent->pw_uid);
fe14fcc3 2078 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2079 str_numset(str, (double)pwent->pw_gid);
fe14fcc3 2080 (void)astore(ary, ++sp, str = str_mortal(&str_no));
03a14243
LW
2081#ifdef PWCHANGE
2082 str_numset(str, (double)pwent->pw_change);
2083#else
a687059c
LW
2084#ifdef PWQUOTA
2085 str_numset(str, (double)pwent->pw_quota);
2086#else
2087#ifdef PWAGE
2088 str_set(str, pwent->pw_age);
2089#endif
2090#endif
03a14243 2091#endif
fe14fcc3 2092 (void)astore(ary, ++sp, str = str_mortal(&str_no));
03a14243
LW
2093#ifdef PWCLASS
2094 str_set(str,pwent->pw_class);
2095#else
c2ab57d4 2096#ifdef PWCOMMENT
a687059c 2097 str_set(str, pwent->pw_comment);
03a14243 2098#endif
c2ab57d4 2099#endif
fe14fcc3 2100 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2101 str_set(str, pwent->pw_gecos);
fe14fcc3 2102 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2103 str_set(str, pwent->pw_dir);
fe14fcc3 2104 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2105 str_set(str, pwent->pw_shell);
03a14243 2106#ifdef PWEXPIRE
fe14fcc3 2107 (void)astore(ary, ++sp, str = str_mortal(&str_no));
03a14243
LW
2108 str_numset(str, (double)pwent->pw_expire);
2109#endif
a687059c
LW
2110 }
2111
2112 return sp;
2113#else
2114 fatal("password routines not implemented");
2115#endif
2116}
2117
2118int
2119do_ggrent(which,gimme,arglast)
2120int which;
2121int gimme;
2122int *arglast;
2123{
2124#ifdef I_GRP
2125 register ARRAY *ary = stack;
2126 register int sp = arglast[0];
2127 register char **elem;
2128 register STR *str;
2129 struct group *getgrnam();
2130 struct group *getgrgid();
2131 struct group *getgrent();
2132 struct group *grent;
a687059c
LW
2133
2134 if (gimme != G_ARRAY) {
fe14fcc3 2135 astore(ary, ++sp, str_mortal(&str_undef));
a687059c
LW
2136 return sp;
2137 }
2138
2139 if (which == O_GGRNAM) {
2140 char *name = str_get(ary->ary_array[sp+1]);
2141
2142 grent = getgrnam(name);
2143 }
2144 else if (which == O_GGRGID) {
2145 int gid = (int)str_gnum(ary->ary_array[sp+1]);
2146
2147 grent = getgrgid(gid);
2148 }
2149 else
2150 grent = getgrent();
2151
2152 if (grent) {
fe14fcc3 2153 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2154 str_set(str, grent->gr_name);
fe14fcc3 2155 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2156 str_set(str, grent->gr_passwd);
fe14fcc3 2157 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c 2158 str_numset(str, (double)grent->gr_gid);
fe14fcc3 2159 (void)astore(ary, ++sp, str = str_mortal(&str_no));
a687059c
LW
2160 for (elem = grent->gr_mem; *elem; elem++) {
2161 str_cat(str, *elem);
2162 if (elem[1])
2163 str_ncat(str," ",1);
2164 }
2165 }
2166
2167 return sp;
2168#else
2169 fatal("group routines not implemented");
2170#endif
2171}
2172
2173int
2174do_dirop(optype,stab,gimme,arglast)
2175int optype;
2176STAB *stab;
2177int gimme;
2178int *arglast;
2179{
fe14fcc3 2180#if defined(DIRENT) && defined(HAS_READDIR)
a687059c
LW
2181 register ARRAY *ary = stack;
2182 register STR **st = ary->ary_array;
2183 register int sp = arglast[1];
2184 register STIO *stio;
2185 long along;
bf38876a 2186#ifndef telldir
a687059c 2187 long telldir();
bf38876a 2188#endif
6e21c824 2189#ifndef apollo
a687059c 2190 struct DIRENT *readdir();
6e21c824 2191#endif
a687059c
LW
2192 register struct DIRENT *dp;
2193
2194 if (!stab)
2195 goto nope;
2196 if (!(stio = stab_io(stab)))
2197 stio = stab_io(stab) = stio_new();
6e21c824 2198 if (!stio->dirp && optype != O_OPEN_DIR)
a687059c
LW
2199 goto nope;
2200 st[sp] = &str_yes;
2201 switch (optype) {
6e21c824 2202 case O_OPEN_DIR:
a687059c
LW
2203 if (stio->dirp)
2204 closedir(stio->dirp);
2205 if (!(stio->dirp = opendir(str_get(st[sp+1]))))
2206 goto nope;
2207 break;
2208 case O_READDIR:
2209 if (gimme == G_ARRAY) {
2210 --sp;
2211 while (dp = readdir(stio->dirp)) {
2212#ifdef DIRNAMLEN
2213 (void)astore(ary,++sp,
fe14fcc3 2214 str_2mortal(str_make(dp->d_name,dp->d_namlen)));
a687059c
LW
2215#else
2216 (void)astore(ary,++sp,
fe14fcc3 2217 str_2mortal(str_make(dp->d_name,0)));
a687059c
LW
2218#endif
2219 }
2220 }
2221 else {
2222 if (!(dp = readdir(stio->dirp)))
2223 goto nope;
fe14fcc3 2224 st[sp] = str_mortal(&str_undef);
a687059c
LW
2225#ifdef DIRNAMLEN
2226 str_nset(st[sp], dp->d_name, dp->d_namlen);
2227#else
2228 str_set(st[sp], dp->d_name);
2229#endif
2230 }
2231 break;
ff8e2863
LW
2232#if MACH
2233 case O_TELLDIR:
2234 case O_SEEKDIR:
2235 goto nope;
2236#else
a687059c 2237 case O_TELLDIR:
fe14fcc3 2238 st[sp] = str_mortal(&str_undef);
a687059c
LW
2239 str_numset(st[sp], (double)telldir(stio->dirp));
2240 break;
2241 case O_SEEKDIR:
fe14fcc3 2242 st[sp] = str_mortal(&str_undef);
a687059c
LW
2243 along = (long)str_gnum(st[sp+1]);
2244 (void)seekdir(stio->dirp,along);
2245 break;
ff8e2863 2246#endif
a687059c 2247 case O_REWINDDIR:
fe14fcc3 2248 st[sp] = str_mortal(&str_undef);
a687059c
LW
2249 (void)rewinddir(stio->dirp);
2250 break;
2251 case O_CLOSEDIR:
fe14fcc3 2252 st[sp] = str_mortal(&str_undef);
a687059c
LW
2253 (void)closedir(stio->dirp);
2254 stio->dirp = 0;
2255 break;
2256 }
2257 return sp;
2258
2259nope:
2260 st[sp] = &str_undef;
2261 return sp;
2262
2263#else
2264 fatal("Unimplemented directory operation");
2265#endif
2266}
2267
2268apply(type,arglast)
2269int type;
2270int *arglast;
2271{
2272 register STR **st = stack->ary_array;
2273 register int sp = arglast[1];
2274 register int items = arglast[2] - sp;
2275 register int val;
2276 register int val2;
2277 register int tot = 0;
2278 char *s;
2279
2280#ifdef TAINT
2281 for (st += ++sp; items--; st++)
2282 tainted |= (*st)->str_tainted;
2283 st = stack->ary_array;
2284 sp = arglast[1];
2285 items = arglast[2] - sp;
2286#endif
2287 switch (type) {
2288 case O_CHMOD:
2289#ifdef TAINT
2290 taintproper("Insecure dependency in chmod");
2291#endif
2292 if (--items > 0) {
2293 tot = items;
2294 val = (int)str_gnum(st[++sp]);
2295 while (items--) {
2296 if (chmod(str_get(st[++sp]),val))
2297 tot--;
2298 }
2299 }
2300 break;
fe14fcc3 2301#ifdef HAS_CHOWN
a687059c
LW
2302 case O_CHOWN:
2303#ifdef TAINT
2304 taintproper("Insecure dependency in chown");
2305#endif
2306 if (items > 2) {
2307 items -= 2;
2308 tot = items;
2309 val = (int)str_gnum(st[++sp]);
2310 val2 = (int)str_gnum(st[++sp]);
2311 while (items--) {
2312 if (chown(str_get(st[++sp]),val,val2))
2313 tot--;
2314 }
2315 }
2316 break;
b1248f16 2317#endif
fe14fcc3 2318#ifdef HAS_KILL
a687059c
LW
2319 case O_KILL:
2320#ifdef TAINT
2321 taintproper("Insecure dependency in kill");
2322#endif
2323 if (--items > 0) {
2324 tot = items;
2325 s = str_get(st[++sp]);
2326 if (isupper(*s)) {
2327 if (*s == 'S' && s[1] == 'I' && s[2] == 'G')
2328 s += 3;
2329 if (!(val = whichsig(s)))
2330 fatal("Unrecognized signal name \"%s\"",s);
2331 }
2332 else
2333 val = (int)str_gnum(st[sp]);
2334 if (val < 0) {
2335 val = -val;
2336 while (items--) {
2337 int proc = (int)str_gnum(st[++sp]);
fe14fcc3 2338#ifdef HAS_KILLPG
a687059c
LW
2339 if (killpg(proc,val)) /* BSD */
2340#else
2341 if (kill(-proc,val)) /* SYSV */
2342#endif
2343 tot--;
2344 }
2345 }
2346 else {
2347 while (items--) {
2348 if (kill((int)(str_gnum(st[++sp])),val))
2349 tot--;
2350 }
2351 }
2352 }
2353 break;
b1248f16 2354#endif
a687059c
LW
2355 case O_UNLINK:
2356#ifdef TAINT
2357 taintproper("Insecure dependency in unlink");
2358#endif
2359 tot = items;
2360 while (items--) {
2361 s = str_get(st[++sp]);
2362 if (euid || unsafe) {
2363 if (UNLINK(s))
2364 tot--;
2365 }
2366 else { /* don't let root wipe out directories without -U */
fe14fcc3 2367#ifdef HAS_LSTAT
c623bd54 2368 if (lstat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
a687059c 2369#else
c623bd54 2370 if (stat(s,&statbuf) < 0 || S_ISDIR(statbuf.st_mode))
a687059c 2371#endif
a687059c
LW
2372 tot--;
2373 else {
2374 if (UNLINK(s))
2375 tot--;
2376 }
2377 }
2378 }
2379 break;
2380 case O_UTIME:
2381#ifdef TAINT
2382 taintproper("Insecure dependency in utime");
2383#endif
2384 if (items > 2) {
663a0e37
LW
2385#ifdef I_UTIME
2386 struct utimbuf utbuf;
2387#else
a687059c 2388 struct {
663a0e37
LW
2389 long actime;
2390 long modtime;
a687059c 2391 } utbuf;
663a0e37 2392#endif
a687059c 2393
afd9f252 2394 Zero(&utbuf, sizeof utbuf, char);
663a0e37
LW
2395 utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
2396 utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
a687059c
LW
2397 items -= 2;
2398#ifndef lint
2399 tot = items;
2400 while (items--) {
2401 if (utime(str_get(st[++sp]),&utbuf))
2402 tot--;
2403 }
2404#endif
2405 }
2406 else
2407 items = 0;
2408 break;
2409 }
2410 return tot;
2411}
2412
2413/* Do the permissions allow some operation? Assumes statcache already set. */
2414
2415int
2416cando(bit, effective, statbufp)
2417int bit;
2418int effective;
2419register struct stat *statbufp;
2420{
fe14fcc3
LW
2421#ifdef MSDOS
2422 /* [Comments and code from Len Reed]
2423 * MS-DOS "user" is similar to UNIX's "superuser," but can't write
2424 * to write-protected files. The execute permission bit is set
2425 * by the Miscrosoft C library stat() function for the following:
2426 * .exe files
2427 * .com files
2428 * .bat files
2429 * directories
2430 * All files and directories are readable.
2431 * Directories and special files, e.g. "CON", cannot be
2432 * write-protected.
2433 * [Comment by Tom Dinger -- a directory can have the write-protect
2434 * bit set in the file system, but DOS permits changes to
2435 * the directory anyway. In addition, all bets are off
2436 * here for networked software, such as Novell and
2437 * Sun's PC-NFS.]
2438 */
2439
2440 return (bit & statbufp->st_mode) ? TRUE : FALSE;
2441
2442#else /* ! MSDOS */
a687059c 2443 if ((effective ? euid : uid) == 0) { /* root is special */
c623bd54
LW
2444 if (bit == S_IXUSR) {
2445 if (statbufp->st_mode & 0111 || S_ISDIR(statbufp->st_mode))
a687059c
LW
2446 return TRUE;
2447 }
2448 else
2449 return TRUE; /* root reads and writes anything */
2450 return FALSE;
2451 }
2452 if (statbufp->st_uid == (effective ? euid : uid) ) {
2453 if (statbufp->st_mode & bit)
2454 return TRUE; /* ok as "user" */
2455 }
2456 else if (ingroup((int)statbufp->st_gid,effective)) {
2457 if (statbufp->st_mode & bit >> 3)
2458 return TRUE; /* ok as "group" */
2459 }
2460 else if (statbufp->st_mode & bit >> 6)
2461 return TRUE; /* ok as "other" */
2462 return FALSE;
fe14fcc3 2463#endif /* ! MSDOS */
a687059c
LW
2464}
2465
2466int
2467ingroup(testgid,effective)
2468int testgid;
2469int effective;
2470{
2471 if (testgid == (effective ? egid : gid))
2472 return TRUE;
fe14fcc3 2473#ifdef HAS_GETGROUPS
a687059c
LW
2474#ifndef NGROUPS
2475#define NGROUPS 32
2476#endif
2477 {
1c3d792e 2478 GROUPSTYPE gary[NGROUPS];
a687059c
LW
2479 int anum;
2480
2481 anum = getgroups(NGROUPS,gary);
2482 while (--anum >= 0)
2483 if (gary[anum] == testgid)
2484 return TRUE;
2485 }
2486#endif
2487 return FALSE;
2488}
c2ab57d4 2489
fe14fcc3 2490#if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
c2ab57d4
LW
2491
2492int
2493do_ipcget(optype, arglast)
2494int optype;
2495int *arglast;
2496{
2497 register STR **st = stack->ary_array;
2498 register int sp = arglast[0];
2499 key_t key;
2500 int n, flags;
2501
2502 key = (key_t)str_gnum(st[++sp]);
2503 n = (optype == O_MSGGET) ? 0 : (int)str_gnum(st[++sp]);
2504 flags = (int)str_gnum(st[++sp]);
2505 errno = 0;
2506 switch (optype)
2507 {
fe14fcc3 2508#ifdef HAS_MSG
c2ab57d4
LW
2509 case O_MSGGET:
2510 return msgget(key, flags);
e5d73d77 2511#endif
fe14fcc3 2512#ifdef HAS_SEM
c2ab57d4
LW
2513 case O_SEMGET:
2514 return semget(key, n, flags);
e5d73d77 2515#endif
fe14fcc3 2516#ifdef HAS_SHM
c2ab57d4
LW
2517 case O_SHMGET:
2518 return shmget(key, n, flags);
e5d73d77 2519#endif
fe14fcc3 2520#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
e5d73d77
LW
2521 default:
2522 fatal("%s not implemented", opname[optype]);
2523#endif
c2ab57d4
LW
2524 }
2525 return -1; /* should never happen */
2526}
2527
2528int
2529do_ipcctl(optype, arglast)
2530int optype;
2531int *arglast;
2532{
2533 register STR **st = stack->ary_array;
2534 register int sp = arglast[0];
2535 STR *astr;
2536 char *a;
2537 int id, n, cmd, infosize, getinfo, ret;
2538
2539 id = (int)str_gnum(st[++sp]);
2540 n = (optype == O_SEMCTL) ? (int)str_gnum(st[++sp]) : 0;
2541 cmd = (int)str_gnum(st[++sp]);
2542 astr = st[++sp];
2543
2544 infosize = 0;
2545 getinfo = (cmd == IPC_STAT);
2546
2547 switch (optype)
2548 {
fe14fcc3 2549#ifdef HAS_MSG
c2ab57d4
LW
2550 case O_MSGCTL:
2551 if (cmd == IPC_STAT || cmd == IPC_SET)
2552 infosize = sizeof(struct msqid_ds);
2553 break;
e5d73d77 2554#endif
fe14fcc3 2555#ifdef HAS_SHM
c2ab57d4
LW
2556 case O_SHMCTL:
2557 if (cmd == IPC_STAT || cmd == IPC_SET)
2558 infosize = sizeof(struct shmid_ds);
2559 break;
e5d73d77 2560#endif
fe14fcc3 2561#ifdef HAS_SEM
c2ab57d4
LW
2562 case O_SEMCTL:
2563 if (cmd == IPC_STAT || cmd == IPC_SET)
2564 infosize = sizeof(struct semid_ds);
2565 else if (cmd == GETALL || cmd == SETALL)
2566 {
2567 struct semid_ds semds;
2568 if (semctl(id, 0, IPC_STAT, &semds) == -1)
2569 return -1;
2570 getinfo = (cmd == GETALL);
6e21c824
LW
2571 infosize = semds.sem_nsems * sizeof(short);
2572 /* "short" is technically wrong but much more portable
2573 than guessing about u_?short(_t)? */
c2ab57d4
LW
2574 }
2575 break;
e5d73d77 2576#endif
fe14fcc3 2577#if !defined(HAS_MSG) || !defined(HAS_SEM) || !defined(HAS_SHM)
e5d73d77
LW
2578 default:
2579 fatal("%s not implemented", opname[optype]);
2580#endif
c2ab57d4
LW
2581 }
2582
2583 if (infosize)
2584 {
2585 if (getinfo)
2586 {
2587 STR_GROW(astr, infosize+1);
2588 a = str_get(astr);
2589 }
2590 else
2591 {
2592 a = str_get(astr);
2593 if (astr->str_cur != infosize)
2594 {
2595 errno = EINVAL;
2596 return -1;
2597 }
2598 }
2599 }
2600 else
2601 {
2602 int i = (int)str_gnum(astr);
2603 a = (char *)i; /* ouch */
2604 }
2605 errno = 0;
2606 switch (optype)
2607 {
fe14fcc3 2608#ifdef HAS_MSG
c2ab57d4
LW
2609 case O_MSGCTL:
2610 ret = msgctl(id, cmd, a);
2611 break;
e5d73d77 2612#endif
fe14fcc3 2613#ifdef HAS_SEM
c2ab57d4
LW
2614 case O_SEMCTL:
2615 ret = semctl(id, n, cmd, a);
2616 break;
e5d73d77 2617#endif
fe14fcc3 2618#ifdef HAS_SHM
c2ab57d4
LW
2619 case O_SHMCTL:
2620 ret = shmctl(id, cmd, a);
2621 break;
e5d73d77 2622#endif
c2ab57d4
LW
2623 }
2624 if (getinfo && ret >= 0) {
2625 astr->str_cur = infosize;
2626 astr->str_ptr[infosize] = '\0';
2627 }
2628 return ret;
2629}
2630
2631int
2632do_msgsnd(arglast)
2633int *arglast;
2634{
fe14fcc3 2635#ifdef HAS_MSG
c2ab57d4
LW
2636 register STR **st = stack->ary_array;
2637 register int sp = arglast[0];
2638 STR *mstr;
2639 char *mbuf;
2640 int id, msize, flags;
2641
2642 id = (int)str_gnum(st[++sp]);
2643 mstr = st[++sp];
2644 flags = (int)str_gnum(st[++sp]);
2645 mbuf = str_get(mstr);
2646 if ((msize = mstr->str_cur - sizeof(long)) < 0) {
2647 errno = EINVAL;
2648 return -1;
2649 }
2650 errno = 0;
2651 return msgsnd(id, mbuf, msize, flags);
e5d73d77
LW
2652#else
2653 fatal("msgsnd not implemented");
2654#endif
c2ab57d4
LW
2655}
2656
2657int
2658do_msgrcv(arglast)
2659int *arglast;
2660{
fe14fcc3 2661#ifdef HAS_MSG
c2ab57d4
LW
2662 register STR **st = stack->ary_array;
2663 register int sp = arglast[0];
2664 STR *mstr;
2665 char *mbuf;
2666 long mtype;
2667 int id, msize, flags, ret;
2668
2669 id = (int)str_gnum(st[++sp]);
2670 mstr = st[++sp];
2671 msize = (int)str_gnum(st[++sp]);
2672 mtype = (long)str_gnum(st[++sp]);
2673 flags = (int)str_gnum(st[++sp]);
2674 mbuf = str_get(mstr);
2675 if (mstr->str_cur < sizeof(long)+msize+1) {
2676 STR_GROW(mstr, sizeof(long)+msize+1);
2677 mbuf = str_get(mstr);
2678 }
2679 errno = 0;
2680 ret = msgrcv(id, mbuf, msize, mtype, flags);
2681 if (ret >= 0) {
2682 mstr->str_cur = sizeof(long)+ret;
2683 mstr->str_ptr[sizeof(long)+ret] = '\0';
2684 }
2685 return ret;
e5d73d77
LW
2686#else
2687 fatal("msgrcv not implemented");
2688#endif
c2ab57d4
LW
2689}
2690
2691int
2692do_semop(arglast)
2693int *arglast;
2694{
fe14fcc3 2695#ifdef HAS_SEM
c2ab57d4
LW
2696 register STR **st = stack->ary_array;
2697 register int sp = arglast[0];
2698 STR *opstr;
2699 char *opbuf;
2700 int id, opsize;
2701
2702 id = (int)str_gnum(st[++sp]);
2703 opstr = st[++sp];
2704 opbuf = str_get(opstr);
2705 opsize = opstr->str_cur;
2706 if (opsize < sizeof(struct sembuf)
2707 || (opsize % sizeof(struct sembuf)) != 0) {
2708 errno = EINVAL;
2709 return -1;
2710 }
2711 errno = 0;
6e21c824 2712 return semop(id, (struct sembuf *)opbuf, opsize/sizeof(struct sembuf));
e5d73d77
LW
2713#else
2714 fatal("semop not implemented");
2715#endif
c2ab57d4
LW
2716}
2717
2718int
2719do_shmio(optype, arglast)
2720int optype;
2721int *arglast;
2722{
fe14fcc3 2723#ifdef HAS_SHM
c2ab57d4
LW
2724 register STR **st = stack->ary_array;
2725 register int sp = arglast[0];
2726 STR *mstr;
2727 char *mbuf, *shm;
2728 int id, mpos, msize;
2729 struct shmid_ds shmds;
6e21c824 2730#ifndef VOIDSHMAT
c2ab57d4 2731 extern char *shmat();
6e21c824 2732#endif
c2ab57d4
LW
2733
2734 id = (int)str_gnum(st[++sp]);
2735 mstr = st[++sp];
2736 mpos = (int)str_gnum(st[++sp]);
2737 msize = (int)str_gnum(st[++sp]);
2738 errno = 0;
2739 if (shmctl(id, IPC_STAT, &shmds) == -1)
2740 return -1;
2741 if (mpos < 0 || msize < 0 || mpos + msize > shmds.shm_segsz) {
2742 errno = EFAULT; /* can't do as caller requested */
2743 return -1;
2744 }
6e21c824 2745 shm = (char*)shmat(id, (char*)NULL, (optype == O_SHMREAD) ? SHM_RDONLY : 0);
c2ab57d4
LW
2746 if (shm == (char *)-1) /* I hate System V IPC, I really do */
2747 return -1;
2748 mbuf = str_get(mstr);
2749 if (optype == O_SHMREAD) {
2750 if (mstr->str_cur < msize) {
2751 STR_GROW(mstr, msize+1);
2752 mbuf = str_get(mstr);
2753 }
2754 bcopy(shm + mpos, mbuf, msize);
2755 mstr->str_cur = msize;
2756 mstr->str_ptr[msize] = '\0';
2757 }
2758 else {
2759 int n;
2760
2761 if ((n = mstr->str_cur) > msize)
2762 n = msize;
2763 bcopy(mbuf, shm + mpos, n);
2764 if (n < msize)
2765 bzero(shm + mpos + n, msize - n);
2766 }
2767 return shmdt(shm);
e5d73d77
LW
2768#else
2769 fatal("shm I/O not implemented");
2770#endif
c2ab57d4
LW
2771}
2772
fe14fcc3 2773#endif /* SYSV IPC */