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