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