perl 4.0 patch 29: patch #20, continued
[p5sagit/p5-mst-13.2.git] / perl.c
CommitLineData
83025b21 1char rcsid[] = "$RCSfile: perl.c,v $$Revision: 4.0.1.7 $$Date: 92/06/08 14:50:39 $\nPatch level: ###\n";
8d063cd8 2/*
352d5a3a 3 * Copyright (c) 1991, Larry Wall
a687059c 4 *
352d5a3a 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 *
fe14fcc3 8 * $Log: perl.c,v $
83025b21 9 * Revision 4.0.1.7 92/06/08 14:50:39 lwall
10 * patch20: PERLLIB now supports multiple directories
11 * patch20: running taintperl explicitly now does checks even if $< == $>
12 * patch20: -e 'cmd' no longer fails silently if /tmp runs out of space
13 * patch20: perl -P now uses location of sed determined by Configure
14 * patch20: form feed for formats is now specifiable via $^L
15 * patch20: paragraph mode now skips extra newlines automatically
16 * patch20: eval "1 #comment" didn't work
17 * patch20: couldn't require . files
18 * patch20: semantic compilation errors didn't abort execution
19 *
988174c1 20 * Revision 4.0.1.6 91/11/11 16:38:45 lwall
21 * patch19: default arg for shift was wrong after first subroutine definition
22 * patch19: op/regexp.t failed from missing arg to bcmp()
23 *
45d8adaa 24 * Revision 4.0.1.5 91/11/05 18:03:32 lwall
25 * patch11: random cleanup
26 * patch11: $0 was being truncated at times
27 * patch11: cppstdin now installed outside of source directory
28 * patch11: -P didn't allow use of #elif or #undef
29 * patch11: prepared for ctype implementations that don't define isascii()
30 * patch11: added eval {}
31 * patch11: eval confused by string containing null
32 *
1462b684 33 * Revision 4.0.1.4 91/06/10 01:23:07 lwall
34 * patch10: perl -v printed incorrect copyright notice
35 *
352d5a3a 36 * Revision 4.0.1.3 91/06/07 11:40:18 lwall
37 * patch4: changed old $^P to $^X
38 *
39 * Revision 4.0.1.2 91/06/07 11:26:16 lwall
40 * patch4: new copyright notice
41 * patch4: added $^P variable to control calling of perldb routines
42 * patch4: added $^F variable to specify maximum system fd, default 2
43 * patch4: debugger lost track of lines in eval
44 *
35c8bce7 45 * Revision 4.0.1.1 91/04/11 17:49:05 lwall
46 * patch1: fixed undefined environ problem
47 *
fe14fcc3 48 * Revision 4.0 91/03/20 01:37:44 lwall
49 * 4.0 baseline.
8d063cd8 50 *
51 */
52
45d8adaa 53/*SUPPRESS 560*/
54
378cc40b 55#include "EXTERN.h"
56#include "perl.h"
57#include "perly.h"
a687059c 58#include "patchlevel.h"
378cc40b 59
352d5a3a 60char *getenv();
61
a687059c 62#ifdef IAMSUID
63#ifndef DOSUID
64#define DOSUID
65#endif
66#endif
378cc40b 67
a687059c 68#ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
69#ifdef DOSUID
70#undef DOSUID
71#endif
72#endif
8d063cd8 73
33b78306 74static char* moreswitches();
83025b21 75static void incpush();
33b78306 76static char* cddir;
33b78306 77static bool minus_c;
27e2fb84 78static char patchlevel[6];
fe14fcc3 79static char *nrs = "\n";
80static int nrschar = '\n'; /* final char of rs, or 0777 if none */
81static int nrslen = 1;
33b78306 82
8d063cd8 83main(argc,argv,env)
84register int argc;
85register char **argv;
86register char **env;
87{
88 register STR *str;
89 register char *s;
45d8adaa 90 char *scriptname;
352d5a3a 91 char *getenv();
378cc40b 92 bool dosearch = FALSE;
a687059c 93#ifdef DOSUID
13281fa4 94 char *validarg = "";
95#endif
8d063cd8 96
a687059c 97#ifdef SETUID_SCRIPTS_ARE_SECURE_NOW
98#ifdef IAMSUID
99#undef IAMSUID
100 fatal("suidperl is no longer needed since the kernel can now execute\n\
101setuid perl scripts securely.\n");
102#endif
103#endif
104
ac58e20f 105 origargv = argv;
106 origargc = argc;
fe14fcc3 107 origenviron = environ;
378cc40b 108 uid = (int)getuid();
109 euid = (int)geteuid();
a687059c 110 gid = (int)getgid();
111 egid = (int)getegid();
fe14fcc3 112 sprintf(patchlevel,"%3.3s%2.2d", index(rcsid,'4'), PATCHLEVEL);
0f85fab0 113#ifdef MSDOS
114 /*
115 * There is no way we can refer to them from Perl so close them to save
116 * space. The other alternative would be to provide STDAUX and STDPRN
117 * filehandles.
118 */
119 (void)fclose(stdaux);
120 (void)fclose(stdprn);
121#endif
a687059c 122 if (do_undump) {
33b78306 123 origfilename = savestr(argv[0]);
a687059c 124 do_undump = 0;
ac58e20f 125 loop_ptr = -1; /* start label stack again */
a687059c 126 goto just_doit;
127 }
83025b21 128#ifdef TAINT
129#ifndef DOSUID
130 if (uid == euid && gid == egid)
131 taintanyway == TRUE; /* running taintperl explicitly */
132#endif
133#endif
a687059c 134 (void)sprintf(index(rcsid,'#'), "%d\n", PATCHLEVEL);
135 linestr = Str_new(65,80);
378cc40b 136 str_nset(linestr,"",0);
a687059c 137 str = str_make("",0); /* first used for -I flags */
138 curstash = defstash = hnew(0);
139 curstname = str_make("main",4);
140 stab_xhash(stabent("_main",TRUE)) = defstash;
20188a90 141 defstash->tbl_name = "main";
33b78306 142 incstab = hadd(aadd(stabent("INC",TRUE)));
a687059c 143 incstab->str_pok |= SP_MULTI;
33b78306 144 for (argc--,argv++; argc > 0; argc--,argv++) {
8d063cd8 145 if (argv[0][0] != '-' || !argv[0][1])
146 break;
13281fa4 147#ifdef DOSUID
148 if (*validarg)
149 validarg = " PHOOEY ";
150 else
151 validarg = argv[0];
152#endif
153 s = argv[0]+1;
8d063cd8 154 reswitch:
13281fa4 155 switch (*s) {
27e2fb84 156 case '0':
378cc40b 157 case 'a':
33b78306 158 case 'c':
a687059c 159 case 'd':
8d063cd8 160 case 'D':
33b78306 161 case 'i':
fe14fcc3 162 case 'l':
33b78306 163 case 'n':
164 case 'p':
165 case 'u':
166 case 'U':
167 case 'v':
168 case 'w':
169 if (s = moreswitches(s))
170 goto reswitch;
8d063cd8 171 break;
33b78306 172
8d063cd8 173 case 'e':
a687059c 174#ifdef TAINT
175 if (euid != uid || egid != gid)
176 fatal("No -e allowed in setuid scripts");
177#endif
8d063cd8 178 if (!e_fp) {
a687059c 179 e_tmpname = savestr(TMPPATH);
180 (void)mktemp(e_tmpname);
83025b21 181 if (!*e_tmpname)
182 fatal("Can't mktemp()");
8d063cd8 183 e_fp = fopen(e_tmpname,"w");
33b78306 184 if (!e_fp)
185 fatal("Cannot open temporary file");
8d063cd8 186 }
33b78306 187 if (argv[1]) {
8d063cd8 188 fputs(argv[1],e_fp);
33b78306 189 argc--,argv++;
190 }
a687059c 191 (void)putc('\n', e_fp);
8d063cd8 192 break;
193 case 'I':
a687059c 194#ifdef TAINT
195 if (euid != uid || egid != gid)
196 fatal("No -I allowed in setuid scripts");
197#endif
13281fa4 198 str_cat(str,"-");
199 str_cat(str,s);
8d063cd8 200 str_cat(str," ");
a687059c 201 if (*++s) {
202 (void)apush(stab_array(incstab),str_make(s,0));
378cc40b 203 }
33b78306 204 else if (argv[1]) {
a687059c 205 (void)apush(stab_array(incstab),str_make(argv[1],0));
8d063cd8 206 str_cat(str,argv[1]);
207 argc--,argv++;
208 str_cat(str," ");
209 }
210 break;
8d063cd8 211 case 'P':
a687059c 212#ifdef TAINT
213 if (euid != uid || egid != gid)
214 fatal("No -P allowed in setuid scripts");
215#endif
8d063cd8 216 preprocess = TRUE;
13281fa4 217 s++;
8d063cd8 218 goto reswitch;
219 case 's':
a687059c 220#ifdef TAINT
221 if (euid != uid || egid != gid)
222 fatal("No -s allowed in setuid scripts");
223#endif
8d063cd8 224 doswitches = TRUE;
13281fa4 225 s++;
8d063cd8 226 goto reswitch;
378cc40b 227 case 'S':
45d8adaa 228#ifdef TAINT
229 if (euid != uid || egid != gid)
230 fatal("No -S allowed in setuid scripts");
231#endif
378cc40b 232 dosearch = TRUE;
13281fa4 233 s++;
378cc40b 234 goto reswitch;
33b78306 235 case 'x':
236 doextract = TRUE;
13281fa4 237 s++;
33b78306 238 if (*s)
239 cddir = savestr(s);
240 break;
8d063cd8 241 case '-':
242 argc--,argv++;
243 goto switch_end;
244 case 0:
245 break;
246 default:
13281fa4 247 fatal("Unrecognized switch: -%s",s);
8d063cd8 248 }
249 }
250 switch_end:
45d8adaa 251 scriptname = argv[0];
8d063cd8 252 if (e_fp) {
83025b21 253 if (fflush(e_fp) || ferror(e_fp) || fclose(e_fp))
254 fatal("Can't write to temp file for -e: %s", strerror(errno));
8d063cd8 255 argc++,argv--;
45d8adaa 256 scriptname = e_tmpname;
8d063cd8 257 }
fe14fcc3 258
83025b21 259#ifdef DOSISH
fe14fcc3 260#define PERLLIB_SEP ';'
261#else
262#define PERLLIB_SEP ':'
263#endif
264#ifndef TAINT /* Can't allow arbitrary PERLLIB in setuid script */
83025b21 265 incpush(getenv("PERLLIB"));
fe14fcc3 266#endif /* TAINT */
267
378cc40b 268#ifndef PRIVLIB
269#define PRIVLIB "/usr/local/lib/perl"
270#endif
83025b21 271 incpush(PRIVLIB);
33b78306 272 (void)apush(stab_array(incstab),str_make(".",1));
8d063cd8 273
274 str_set(&str_no,No);
275 str_set(&str_yes,Yes);
8d063cd8 276
277 /* open script */
278
45d8adaa 279 if (scriptname == Nullch)
34de22dd 280#ifdef MSDOS
281 {
282 if ( isatty(fileno(stdin)) )
283 moreswitches("v");
45d8adaa 284 scriptname = "-";
34de22dd 285 }
286#else
45d8adaa 287 scriptname = "-";
34de22dd 288#endif
45d8adaa 289 if (dosearch && !index(scriptname, '/') && (s = getenv("PATH"))) {
378cc40b 290 char *xfound = Nullch, *xfailed = Nullch;
a687059c 291 int len;
378cc40b 292
a687059c 293 bufend = s + strlen(s);
378cc40b 294 while (*s) {
83025b21 295#ifndef DOSISH
a687059c 296 s = cpytill(tokenbuf,s,bufend,':',&len);
33b78306 297#else
83025b21 298#ifdef atarist
299 for (len = 0; *s && *s != ',' && *s != ';'; tokenbuf[len++] = *s++);
300 tokenbuf[len] = '\0';
301#else
33b78306 302 for (len = 0; *s && *s != ';'; tokenbuf[len++] = *s++);
303 tokenbuf[len] = '\0';
304#endif
83025b21 305#endif
378cc40b 306 if (*s)
307 s++;
83025b21 308#ifndef DOSISH
33b78306 309 if (len && tokenbuf[len-1] != '/')
310#else
83025b21 311#ifdef atarist
312 if (len && ((tokenbuf[len-1] != '\\') && (tokenbuf[len-1] != '/')))
313#else
33b78306 314 if (len && tokenbuf[len-1] != '\\')
315#endif
83025b21 316#endif
a687059c 317 (void)strcat(tokenbuf+len,"/");
45d8adaa 318 (void)strcat(tokenbuf+len,scriptname);
378cc40b 319#ifdef DEBUGGING
320 if (debug & 1)
321 fprintf(stderr,"Looking for %s\n",tokenbuf);
322#endif
323 if (stat(tokenbuf,&statbuf) < 0) /* not there? */
324 continue;
27e2fb84 325 if (S_ISREG(statbuf.st_mode)
326 && cando(S_IRUSR,TRUE,&statbuf) && cando(S_IXUSR,TRUE,&statbuf)) {
378cc40b 327 xfound = tokenbuf; /* bingo! */
328 break;
329 }
330 if (!xfailed)
331 xfailed = savestr(tokenbuf);
332 }
333 if (!xfound)
45d8adaa 334 fatal("Can't execute %s", xfailed ? xfailed : scriptname );
378cc40b 335 if (xfailed)
a687059c 336 Safefree(xfailed);
45d8adaa 337 scriptname = savestr(xfound);
378cc40b 338 }
a687059c 339
20188a90 340 fdpid = anew(Nullstab); /* for remembering popen pids by fd */
27e2fb84 341 pidstatus = hnew(COEFFSIZE);/* for remembering status of dead pids */
a687059c 342
45d8adaa 343 origfilename = savestr(scriptname);
20188a90 344 curcmd->c_filestab = fstab(origfilename);
345 if (strEQ(origfilename,"-"))
45d8adaa 346 scriptname = "";
8d063cd8 347 if (preprocess) {
45d8adaa 348 char *cpp = CPPSTDIN;
349
350 if (strEQ(cpp,"cppstdin"))
351 sprintf(tokenbuf, "%s/%s", SCRIPTDIR, cpp);
352 else
353 sprintf(tokenbuf, "%s", cpp);
378cc40b 354 str_cat(str,"-I");
355 str_cat(str,PRIVLIB);
83025b21 356#ifdef MSDOS
a687059c 357 (void)sprintf(buf, "\
83025b21 358sed %s -e \"/^[^#]/b\" \
359 -e \"/^#[ ]*include[ ]/b\" \
360 -e \"/^#[ ]*define[ ]/b\" \
361 -e \"/^#[ ]*if[ ]/b\" \
362 -e \"/^#[ ]*ifdef[ ]/b\" \
363 -e \"/^#[ ]*ifndef[ ]/b\" \
364 -e \"/^#[ ]*else/b\" \
365 -e \"/^#[ ]*elif[ ]/b\" \
366 -e \"/^#[ ]*undef[ ]/b\" \
367 -e \"/^#[ ]*endif/b\" \
368 -e \"s/^#.*//\" \
369 %s | %s -C %s %s",
370 (doextract ? "-e \"1,/^#/d\n\"" : ""),
371#else
372 (void)sprintf(buf, "\
373%s %s -e '/^[^#]/b' \
8d063cd8 374 -e '/^#[ ]*include[ ]/b' \
375 -e '/^#[ ]*define[ ]/b' \
376 -e '/^#[ ]*if[ ]/b' \
377 -e '/^#[ ]*ifdef[ ]/b' \
378cc40b 378 -e '/^#[ ]*ifndef[ ]/b' \
8d063cd8 379 -e '/^#[ ]*else/b' \
45d8adaa 380 -e '/^#[ ]*elif[ ]/b' \
381 -e '/^#[ ]*undef[ ]/b' \
8d063cd8 382 -e '/^#[ ]*endif/b' \
45d8adaa 383 -e 's/^[ ]*#.*//' \
378cc40b 384 %s | %s -C %s %s",
83025b21 385#ifdef LOC_SED
386 LOC_SED,
20188a90 387#else
83025b21 388 "sed",
20188a90 389#endif
33b78306 390 (doextract ? "-e '1,/^#/d\n'" : ""),
83025b21 391#endif
45d8adaa 392 scriptname, tokenbuf, str_get(str), CPPMINUS);
34de22dd 393#ifdef DEBUGGING
394 if (debug & 64) {
395 fputs(buf,stderr);
396 fputs("\n",stderr);
397 }
398#endif
399 doextract = FALSE;
a687059c 400#ifdef IAMSUID /* actually, this is caught earlier */
83025b21 401 if (euid != uid && !euid) { /* if running suidperl */
fe14fcc3 402#ifdef HAS_SETEUID
a687059c 403 (void)seteuid(uid); /* musn't stay setuid root */
404#else
fe14fcc3 405#ifdef HAS_SETREUID
a687059c 406 (void)setreuid(-1, uid);
407#else
408 setuid(uid);
409#endif
13281fa4 410#endif
83025b21 411 if (geteuid() != uid)
412 fatal("Can't do seteuid!\n");
413 }
a687059c 414#endif /* IAMSUID */
415 rsfp = mypopen(buf,"r");
8d063cd8 416 }
45d8adaa 417 else if (!*scriptname) {
418#ifdef TAINT
419 if (euid != uid || egid != gid)
420 fatal("Can't take set-id script from stdin");
421#endif
8d063cd8 422 rsfp = stdin;
45d8adaa 423 }
8d063cd8 424 else
45d8adaa 425 rsfp = fopen(scriptname,"r");
426 if ((FILE*)rsfp == Nullfp) {
13281fa4 427#ifdef DOSUID
a687059c 428#ifndef IAMSUID /* in case script is not readable before setuid */
20188a90 429 if (euid && stat(stab_val(curcmd->c_filestab)->str_ptr,&statbuf) >= 0 &&
13281fa4 430 statbuf.st_mode & (S_ISUID|S_ISGID)) {
27e2fb84 431 (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
a687059c 432 execv(buf, origargv); /* try again */
13281fa4 433 fatal("Can't do setuid\n");
434 }
435#endif
436#endif
a687059c 437 fatal("Can't open perl script \"%s\": %s\n",
20188a90 438 stab_val(curcmd->c_filestab)->str_ptr, strerror(errno));
13281fa4 439 }
8d063cd8 440 str_free(str); /* free -I directories */
fe14fcc3 441 str = Nullstr;
8d063cd8 442
13281fa4 443 /* do we need to emulate setuid on scripts? */
444
445 /* This code is for those BSD systems that have setuid #! scripts disabled
446 * in the kernel because of a security problem. Merely defining DOSUID
447 * in perl will not fix that problem, but if you have disabled setuid
448 * scripts in the kernel, this will attempt to emulate setuid and setgid
449 * on scripts that have those now-otherwise-useless bits set. The setuid
27e2fb84 450 * root version must be called suidperl or sperlN.NNN. If regular perl
451 * discovers that it has opened a setuid script, it calls suidperl with
452 * the same argv that it had. If suidperl finds that the script it has
453 * just opened is NOT setuid root, it sets the effective uid back to the
454 * uid. We don't just make perl setuid root because that loses the
455 * effective uid we had before invoking perl, if it was different from the
456 * uid.
13281fa4 457 *
458 * DOSUID must be defined in both perl and suidperl, and IAMSUID must
459 * be defined in suidperl only. suidperl must be setuid root. The
460 * Configure script will set this up for you if you want it.
a687059c 461 *
462 * There is also the possibility of have a script which is running
463 * set-id due to a C wrapper. We want to do the TAINT checks
464 * on these set-id scripts, but don't want to have the overhead of
465 * them in normal perl, and can't use suidperl because it will lose
466 * the effective uid info, so we have an additional non-setuid root
27e2fb84 467 * version called taintperl or tperlN.NNN that just does the TAINT checks.
13281fa4 468 */
a687059c 469
13281fa4 470#ifdef DOSUID
471 if (fstat(fileno(rsfp),&statbuf) < 0) /* normal stat is insecure */
20188a90 472 fatal("Can't stat script \"%s\"",origfilename);
13281fa4 473 if (statbuf.st_mode & (S_ISUID|S_ISGID)) {
474 int len;
475
a687059c 476#ifdef IAMSUID
fe14fcc3 477#ifndef HAS_SETREUID
a687059c 478 /* On this access check to make sure the directories are readable,
479 * there is actually a small window that the user could use to make
480 * filename point to an accessible directory. So there is a faint
481 * chance that someone could execute a setuid script down in a
482 * non-accessible directory. I don't know what to do about that.
483 * But I don't think it's too important. The manual lies when
484 * it says access() is useful in setuid programs.
485 */
20188a90 486 if (access(stab_val(curcmd->c_filestab)->str_ptr,1)) /*double check*/
13281fa4 487 fatal("Permission denied");
a687059c 488#else
489 /* If we can swap euid and uid, then we can determine access rights
490 * with a simple stat of the file, and then compare device and
491 * inode to make sure we did stat() on the same file we opened.
492 * Then we just have to make sure he or she can execute it.
493 */
494 {
495 struct stat tmpstatbuf;
496
497 if (setreuid(euid,uid) < 0 || getuid() != euid || geteuid() != uid)
498 fatal("Can't swap uid and euid"); /* really paranoid */
20188a90 499 if (stat(stab_val(curcmd->c_filestab)->str_ptr,&tmpstatbuf) < 0)
500 fatal("Permission denied"); /* testing full pathname here */
a687059c 501 if (tmpstatbuf.st_dev != statbuf.st_dev ||
502 tmpstatbuf.st_ino != statbuf.st_ino) {
503 (void)fclose(rsfp);
504 if (rsfp = mypopen("/bin/mail root","w")) { /* heh, heh */
505 fprintf(rsfp,
506"User %d tried to run dev %d ino %d in place of dev %d ino %d!\n\
507(Filename of set-id script was %s, uid %d gid %d.)\n\nSincerely,\nperl\n",
508 uid,tmpstatbuf.st_dev, tmpstatbuf.st_ino,
509 statbuf.st_dev, statbuf.st_ino,
20188a90 510 stab_val(curcmd->c_filestab)->str_ptr,
511 statbuf.st_uid, statbuf.st_gid);
a687059c 512 (void)mypclose(rsfp);
513 }
514 fatal("Permission denied\n");
515 }
516 if (setreuid(uid,euid) < 0 || getuid() != uid || geteuid() != euid)
517 fatal("Can't reswap uid and euid");
27e2fb84 518 if (!cando(S_IXUSR,FALSE,&statbuf)) /* can real uid exec? */
a687059c 519 fatal("Permission denied\n");
520 }
fe14fcc3 521#endif /* HAS_SETREUID */
a687059c 522#endif /* IAMSUID */
523
27e2fb84 524 if (!S_ISREG(statbuf.st_mode))
13281fa4 525 fatal("Permission denied");
27e2fb84 526 if (statbuf.st_mode & S_IWOTH)
a687059c 527 fatal("Setuid/gid script is writable by world");
13281fa4 528 doswitches = FALSE; /* -s is insecure in suid */
33b78306 529 curcmd->c_line++;
13281fa4 530 if (fgets(tokenbuf,sizeof tokenbuf, rsfp) == Nullch ||
531 strnNE(tokenbuf,"#!",2) ) /* required even on Sys V */
532 fatal("No #! line");
663a0e37 533 s = tokenbuf+2;
534 if (*s == ' ') s++;
45d8adaa 535 while (!isSPACE(*s)) s++;
27e2fb84 536 if (strnNE(s-4,"perl",4) && strnNE(s-9,"perl",4)) /* sanity check */
13281fa4 537 fatal("Not a perl script");
a687059c 538 while (*s == ' ' || *s == '\t') s++;
13281fa4 539 /*
540 * #! arg must be what we saw above. They can invoke it by
541 * mentioning suidperl explicitly, but they may not add any strange
542 * arguments beyond what #! says if they do invoke suidperl that way.
543 */
544 len = strlen(validarg);
545 if (strEQ(validarg," PHOOEY ") ||
45d8adaa 546 strnNE(s,validarg,len) || !isSPACE(s[len]))
a687059c 547 fatal("Args must match #! line");
548
549#ifndef IAMSUID
550 if (euid != uid && (statbuf.st_mode & S_ISUID) &&
551 euid == statbuf.st_uid)
552 if (!do_undump)
553 fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
554FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
555#endif /* IAMSUID */
13281fa4 556
557 if (euid) { /* oops, we're not the setuid root perl */
a687059c 558 (void)fclose(rsfp);
13281fa4 559#ifndef IAMSUID
27e2fb84 560 (void)sprintf(buf, "%s/sperl%s", BIN, patchlevel);
a687059c 561 execv(buf, origargv); /* try again */
13281fa4 562#endif
563 fatal("Can't do setuid\n");
564 }
565
83025b21 566 if (statbuf.st_mode & S_ISGID && statbuf.st_gid != egid) {
fe14fcc3 567#ifdef HAS_SETEGID
a687059c 568 (void)setegid(statbuf.st_gid);
569#else
fe14fcc3 570#ifdef HAS_SETREGID
a687059c 571 (void)setregid((GIDTYPE)-1,statbuf.st_gid);
572#else
573 setgid(statbuf.st_gid);
574#endif
575#endif
83025b21 576 if (getegid() != statbuf.st_gid)
577 fatal("Can't do setegid!\n");
578 }
a687059c 579 if (statbuf.st_mode & S_ISUID) {
580 if (statbuf.st_uid != euid)
fe14fcc3 581#ifdef HAS_SETEUID
a687059c 582 (void)seteuid(statbuf.st_uid); /* all that for this */
583#else
fe14fcc3 584#ifdef HAS_SETREUID
a687059c 585 (void)setreuid((UIDTYPE)-1,statbuf.st_uid);
586#else
587 setuid(statbuf.st_uid);
588#endif
589#endif
83025b21 590 if (geteuid() != statbuf.st_uid)
591 fatal("Can't do seteuid!\n");
a687059c 592 }
83025b21 593 else if (uid) { /* oops, mustn't run as root */
fe14fcc3 594#ifdef HAS_SETEUID
a687059c 595 (void)seteuid((UIDTYPE)uid);
596#else
fe14fcc3 597#ifdef HAS_SETREUID
a687059c 598 (void)setreuid((UIDTYPE)-1,(UIDTYPE)uid);
599#else
600 setuid((UIDTYPE)uid);
601#endif
602#endif
83025b21 603 if (geteuid() != uid)
604 fatal("Can't do seteuid!\n");
605 }
ffed7fef 606 uid = (int)getuid();
13281fa4 607 euid = (int)geteuid();
ffed7fef 608 gid = (int)getgid();
609 egid = (int)getegid();
27e2fb84 610 if (!cando(S_IXUSR,TRUE,&statbuf))
13281fa4 611 fatal("Permission denied\n"); /* they can't do this */
612 }
613#ifdef IAMSUID
614 else if (preprocess)
615 fatal("-P not allowed for setuid/setgid script\n");
616 else
617 fatal("Script is not setuid/setgid in suidperl\n");
a687059c 618#else
619#ifndef TAINT /* we aren't taintperl or suidperl */
620 /* script has a wrapper--can't run suidperl or we lose euid */
621 else if (euid != uid || egid != gid) {
622 (void)fclose(rsfp);
27e2fb84 623 (void)sprintf(buf, "%s/tperl%s", BIN, patchlevel);
a687059c 624 execv(buf, origargv); /* try again */
625 fatal("Can't run setuid script with taint checks");
626 }
627#endif /* TAINT */
13281fa4 628#endif /* IAMSUID */
a687059c 629#else /* !DOSUID */
630#ifndef TAINT /* we aren't taintperl or suidperl */
631 if (euid != uid || egid != gid) { /* (suidperl doesn't exist, in fact) */
632#ifndef SETUID_SCRIPTS_ARE_SECURE_NOW
633 fstat(fileno(rsfp),&statbuf); /* may be either wrapped or real suid */
634 if ((euid != uid && euid == statbuf.st_uid && statbuf.st_mode & S_ISUID)
635 ||
636 (egid != gid && egid == statbuf.st_gid && statbuf.st_mode & S_ISGID)
637 )
638 if (!do_undump)
639 fatal("YOU HAVEN'T DISABLED SET-ID SCRIPTS IN THE KERNEL YET!\n\
640FIX YOUR KERNEL, PUT A C WRAPPER AROUND THIS SCRIPT, OR USE -u AND UNDUMP!\n");
641#endif /* SETUID_SCRIPTS_ARE_SECURE_NOW */
642 /* not set-id, must be wrapped */
643 (void)fclose(rsfp);
27e2fb84 644 (void)sprintf(buf, "%s/tperl%s", BIN, patchlevel);
a687059c 645 execv(buf, origargv); /* try again */
646 fatal("Can't run setuid script with taint checks");
647 }
648#endif /* TAINT */
13281fa4 649#endif /* DOSUID */
650
33b78306 651#if !defined(IAMSUID) && !defined(TAINT)
652
653 /* skip forward in input to the real script? */
654
655 while (doextract) {
656 if ((s = str_gets(linestr, rsfp, 0)) == Nullch)
657 fatal("No Perl script found in input\n");
658 if (*s == '#' && s[1] == '!' && instr(s,"perl")) {
659 ungetc('\n',rsfp); /* to keep line count right */
660 doextract = FALSE;
661 if (s = instr(s,"perl -")) {
662 s += 6;
45d8adaa 663 /*SUPPRESS 530*/
33b78306 664 while (s = moreswitches(s)) ;
665 }
666 if (cddir && chdir(cddir) < 0)
667 fatal("Can't chdir to %s",cddir);
668 }
669 }
670#endif /* !defined(IAMSUID) && !defined(TAINT) */
671
8d063cd8 672 defstab = stabent("_",TRUE);
673
988174c1 674 subname = str_make("main",4);
a687059c 675 if (perldb) {
676 debstash = hnew(0);
677 stab_xhash(stabent("_DB",TRUE)) = debstash;
678 curstash = debstash;
20188a90 679 dbargs = stab_xarray(aadd((tmpstab = stabent("args",TRUE))));
a687059c 680 tmpstab->str_pok |= SP_MULTI;
20188a90 681 dbargs->ary_flags = 0;
a687059c 682 DBstab = stabent("DB",TRUE);
683 DBstab->str_pok |= SP_MULTI;
20188a90 684 DBline = stabent("dbline",TRUE);
685 DBline->str_pok |= SP_MULTI;
a687059c 686 DBsub = hadd(tmpstab = stabent("sub",TRUE));
687 tmpstab->str_pok |= SP_MULTI;
688 DBsingle = stab_val((tmpstab = stabent("single",TRUE)));
689 tmpstab->str_pok |= SP_MULTI;
20188a90 690 DBtrace = stab_val((tmpstab = stabent("trace",TRUE)));
691 tmpstab->str_pok |= SP_MULTI;
692 DBsignal = stab_val((tmpstab = stabent("signal",TRUE)));
693 tmpstab->str_pok |= SP_MULTI;
a687059c 694 curstash = defstash;
695 }
696
8d063cd8 697 /* init tokener */
698
a687059c 699 bufend = bufptr = str_get(linestr);
700
701 savestack = anew(Nullstab); /* for saving non-local values */
702 stack = anew(Nullstab); /* for saving non-local values */
703 stack->ary_flags = 0; /* not a real array */
6eb13c3b 704 afill(stack,63); afill(stack,-1); /* preextend stack */
705 afill(savestack,63); afill(savestack,-1);
8d063cd8 706
a687059c 707 /* now parse the script */
8d063cd8 708
a687059c 709 error_count = 0;
33b78306 710 if (yyparse() || error_count) {
711 if (minus_c)
712 fatal("%s had compilation errors.\n", origfilename);
713 else {
714 fatal("Execution of %s aborted due to compilation errors.\n",
715 origfilename);
716 }
717 }
8d063cd8 718
a687059c 719 New(50,loop_stack,128,struct loop);
ae986130 720#ifdef DEBUGGING
721 if (debug) {
722 New(51,debname,128,char);
723 New(52,debdelim,128,char);
724 }
725#endif
a687059c 726 curstash = defstash;
378cc40b 727
728 preprocess = FALSE;
8d063cd8 729 if (e_fp) {
730 e_fp = Nullfp;
a687059c 731 (void)UNLINK(e_tmpname);
732 }
733
734 /* initialize everything that won't change if we undump */
735
736 if (sigstab = stabent("SIG",allstabs)) {
737 sigstab->str_pok |= SP_MULTI;
738 (void)hadd(sigstab);
739 }
740
352d5a3a 741 magicalize("!#?^~=-%.+&*()<>,\\/[|`':\004\t\020\024\027\006");
33b78306 742 userinit(); /* in case linked C routines want magical variables */
a687059c 743
744 amperstab = stabent("&",allstabs);
745 leftstab = stabent("`",allstabs);
746 rightstab = stabent("'",allstabs);
747 sawampersand = (amperstab || leftstab || rightstab);
748 if (tmpstab = stabent(":",allstabs))
83025b21 749 str_set(stab_val(tmpstab),chopset);
20188a90 750 if (tmpstab = stabent("\024",allstabs))
751 time(&basetime);
a687059c 752
753 /* these aren't necessarily magical */
83025b21 754 if (tmpstab = stabent("\014",allstabs)) {
755 str_set(stab_val(tmpstab),"\f");
756 formfeed = stab_val(tmpstab);
757 }
a687059c 758 if (tmpstab = stabent(";",allstabs))
759 str_set(STAB_STR(tmpstab),"\034");
33b78306 760 if (tmpstab = stabent("]",allstabs)) {
761 str = STAB_STR(tmpstab);
762 str_set(str,rcsid);
27e2fb84 763 str->str_u.str_nval = atof(patchlevel);
33b78306 764 str->str_nok = 1;
765 }
a687059c 766 str_nset(stab_val(stabent("\"", TRUE)), " ", 1);
767
768 stdinstab = stabent("STDIN",TRUE);
769 stdinstab->str_pok |= SP_MULTI;
83025b21 770 if (!stab_io(stdinstab))
771 stab_io(stdinstab) = stio_new();
a687059c 772 stab_io(stdinstab)->ifp = stdin;
773 tmpstab = stabent("stdin",TRUE);
774 stab_io(tmpstab) = stab_io(stdinstab);
775 tmpstab->str_pok |= SP_MULTI;
776
777 tmpstab = stabent("STDOUT",TRUE);
778 tmpstab->str_pok |= SP_MULTI;
83025b21 779 if (!stab_io(tmpstab))
780 stab_io(tmpstab) = stio_new();
a687059c 781 stab_io(tmpstab)->ofp = stab_io(tmpstab)->ifp = stdout;
782 defoutstab = tmpstab;
783 tmpstab = stabent("stdout",TRUE);
784 stab_io(tmpstab) = stab_io(defoutstab);
785 tmpstab->str_pok |= SP_MULTI;
786
787 curoutstab = stabent("STDERR",TRUE);
788 curoutstab->str_pok |= SP_MULTI;
83025b21 789 if (!stab_io(curoutstab))
790 stab_io(curoutstab) = stio_new();
a687059c 791 stab_io(curoutstab)->ofp = stab_io(curoutstab)->ifp = stderr;
792 tmpstab = stabent("stderr",TRUE);
793 stab_io(tmpstab) = stab_io(curoutstab);
794 tmpstab->str_pok |= SP_MULTI;
795 curoutstab = defoutstab; /* switch back to STDOUT */
796
797 statname = Str_new(66,0); /* last filename we did stat on */
798
fe14fcc3 799 /* now that script is parsed, we can modify record separator */
800
801 rs = nrs;
802 rslen = nrslen;
803 rschar = nrschar;
83025b21 804 rspara = (nrslen == 2);
fe14fcc3 805 str_nset(stab_val(stabent("/", TRUE)), rs, rslen);
806
a687059c 807 if (do_undump)
34de22dd 808 my_unexec();
a687059c 809
810 just_doit: /* come here if running an undumped a.out */
8d063cd8 811 argc--,argv++; /* skip name of script */
812 if (doswitches) {
813 for (; argc > 0 && **argv == '-'; argc--,argv++) {
814 if (argv[0][1] == '-') {
815 argc--,argv++;
816 break;
817 }
fe14fcc3 818 if (s = index(argv[0], '=')) {
819 *s++ = '\0';
820 str_set(stab_val(stabent(argv[0]+1,TRUE)),s);
821 }
822 else
823 str_numset(stab_val(stabent(argv[0]+1,TRUE)),(double)1.0);
8d063cd8 824 }
825 }
a687059c 826#ifdef TAINT
827 tainted = 1;
828#endif
fe14fcc3 829 if (tmpstab = stabent("0",allstabs)) {
34de22dd 830 str_set(stab_val(tmpstab),origfilename);
fe14fcc3 831 magicname("0", Nullch, 0);
832 }
352d5a3a 833 if (tmpstab = stabent("\030",allstabs))
fe14fcc3 834 str_set(stab_val(tmpstab),origargv[0]);
a559c259 835 if (argvstab = stabent("ARGV",allstabs)) {
a687059c 836 argvstab->str_pok |= SP_MULTI;
837 (void)aadd(argvstab);
33b78306 838 aclear(stab_array(argvstab));
8d063cd8 839 for (; argc > 0; argc--,argv++) {
a687059c 840 (void)apush(stab_array(argvstab),str_make(argv[0],0));
8d063cd8 841 }
842 }
a687059c 843#ifdef TAINT
844 (void) stabent("ENV",TRUE); /* must test PATH and IFS */
845#endif
a559c259 846 if (envstab = stabent("ENV",allstabs)) {
a687059c 847 envstab->str_pok |= SP_MULTI;
848 (void)hadd(envstab);
20188a90 849 hclear(stab_hash(envstab), FALSE);
33b78306 850 if (env != environ)
851 environ[0] = Nullch;
8d063cd8 852 for (; *env; env++) {
853 if (!(s = index(*env,'=')))
854 continue;
855 *s++ = '\0';
a687059c 856 str = str_make(s--,0);
857 str_magic(str, envstab, 'E', *env, s - *env);
858 (void)hstore(stab_hash(envstab), *env, s - *env, str, 0);
859 *s = '=';
8d063cd8 860 }
861 }
a687059c 862#ifdef TAINT
863 tainted = 0;
864#endif
378cc40b 865 if (tmpstab = stabent("$",allstabs))
8d063cd8 866 str_numset(STAB_STR(tmpstab),(double)getpid());
867
20188a90 868 if (dowarn) {
869 stab_check('A','Z');
870 stab_check('a','z');
871 }
872
a687059c 873 if (setjmp(top_env)) /* sets goto_targ on longjump */
ac58e20f 874 loop_ptr = -1; /* start label stack again */
8d063cd8 875
876#ifdef DEBUGGING
877 if (debug & 1024)
a687059c 878 dump_all();
8d063cd8 879 if (debug)
880 fprintf(stderr,"\nEXECUTING...\n\n");
881#endif
882
33b78306 883 if (minus_c) {
884 fprintf(stderr,"%s syntax OK\n", origfilename);
885 exit(0);
886 }
887
8d063cd8 888 /* do it */
889
a687059c 890 (void) cmd_exec(main_root,G_SCALAR,-1);
8d063cd8 891
892 if (goto_targ)
378cc40b 893 fatal("Can't find label \"%s\"--aborting",goto_targ);
8d063cd8 894 exit(0);
378cc40b 895 /* NOTREACHED */
8d063cd8 896}
897
fe14fcc3 898void
8d063cd8 899magicalize(list)
900register char *list;
901{
8d063cd8 902 char sym[2];
903
904 sym[1] = '\0';
33b78306 905 while (*sym = *list++)
906 magicname(sym, Nullch, 0);
907}
908
fe14fcc3 909void
33b78306 910magicname(sym,name,namlen)
911char *sym;
912char *name;
913int namlen;
914{
915 register STAB *stab;
916
917 if (stab = stabent(sym,allstabs)) {
918 stab_flags(stab) = SF_VMAGIC;
919 str_magic(stab_val(stab), stab, 0, name, namlen);
378cc40b 920 }
8d063cd8 921}
922
83025b21 923static void
924incpush(p)
925char *p;
926{
927 char *s;
928
929 if (!p)
930 return;
931
932 /* Break at all separators */
933 while (*p) {
934 /* First, skip any consecutive separators */
935 while ( *p == PERLLIB_SEP ) {
936 /* Uncomment the next line for PATH semantics */
937 /* (void)apush(stab_array(incstab), str_make(".", 1)); */
938 p++;
939 }
940 if ( (s = index(p, PERLLIB_SEP)) != Nullch ) {
941 (void)apush(stab_array(incstab), str_make(p, (int)(s - p)));
942 p = s + 1;
943 } else {
944 (void)apush(stab_array(incstab), str_make(p, 0));
945 break;
946 }
947 }
948}
949
352d5a3a 950void
951savelines(array, str)
952ARRAY *array;
953STR *str;
954{
955 register char *s = str->str_ptr;
956 register char *send = str->str_ptr + str->str_cur;
957 register char *t;
958 register int line = 1;
959
960 while (s && s < send) {
961 STR *tmpstr = Str_new(85,0);
962
963 t = index(s, '\n');
964 if (t)
965 t++;
966 else
967 t = send;
968
969 str_nset(tmpstr, s, t - s);
970 astore(array, line++, tmpstr);
971 s = t;
972 }
973}
974
fe14fcc3 975/* this routine is in perl.c by virtue of being sort of an alternate main() */
8d063cd8 976
a687059c 977int
45d8adaa 978do_eval(str,optype,stash,savecmd,gimme,arglast)
a687059c 979STR *str;
980int optype;
981HASH *stash;
45d8adaa 982int savecmd;
a687059c 983int gimme;
984int *arglast;
8d063cd8 985{
a687059c 986 STR **st = stack->ary_array;
987 int retval;
fe14fcc3 988 CMD *myroot = Nullcmd;
a687059c 989 ARRAY *ar;
990 int i;
33b78306 991 CMD * VOLATILE oldcurcmd = curcmd;
ac58e20f 992 VOLATILE int oldtmps_base = tmps_base;
993 VOLATILE int oldsave = savestack->ary_fill;
20188a90 994 VOLATILE int oldperldb = perldb;
ac58e20f 995 SPAT * VOLATILE oldspat = curspat;
fe14fcc3 996 SPAT * VOLATILE oldlspat = lastspat;
a687059c 997 static char *last_eval = Nullch;
45d8adaa 998 static long last_elen = 0;
a687059c 999 static CMD *last_root = Nullcmd;
663a0e37 1000 VOLATILE int sp = arglast[0];
33b78306 1001 char *specfilename;
20188a90 1002 char *tmpfilename;
fe14fcc3 1003 int parsing = 1;
8d063cd8 1004
a687059c 1005 tmps_base = tmps_max;
1006 if (curstash != stash) {
1007 (void)savehptr(&curstash);
1008 curstash = stash;
8d063cd8 1009 }
a687059c 1010 str_set(stab_val(stabent("@",TRUE)),"");
20188a90 1011 if (curcmd->c_line == 0) /* don't debug debugger... */
1012 perldb = FALSE;
33b78306 1013 curcmd = &compiling;
1014 if (optype == O_EVAL) { /* normal eval */
20188a90 1015 curcmd->c_filestab = fstab("(eval)");
33b78306 1016 curcmd->c_line = 1;
a687059c 1017 str_sset(linestr,str);
83025b21 1018 str_cat(linestr,";\n;\n"); /* be kind to them */
352d5a3a 1019 if (perldb)
1020 savelines(stab_xarray(curcmd->c_filestab), linestr);
8d063cd8 1021 }
a687059c 1022 else {
0f85fab0 1023 if (last_root && !in_eval) {
a687059c 1024 Safefree(last_eval);
fe14fcc3 1025 last_eval = Nullch;
a687059c 1026 cmd_free(last_root);
1027 last_root = Nullcmd;
8d063cd8 1028 }
33b78306 1029 specfilename = str_get(str);
a687059c 1030 str_set(linestr,"");
20188a90 1031 if (optype == O_REQUIRE && &str_undef !=
33b78306 1032 hfetch(stab_hash(incstab), specfilename, strlen(specfilename), 0)) {
20188a90 1033 curcmd = oldcurcmd;
33b78306 1034 tmps_base = oldtmps_base;
1035 st[++sp] = &str_yes;
20188a90 1036 perldb = oldperldb;
33b78306 1037 return sp;
1038 }
20188a90 1039 tmpfilename = savestr(specfilename);
83025b21 1040 if (*tmpfilename == '/' ||
1041 (*tmpfilename == '.' &&
1042 (tmpfilename[1] == '/' ||
1043 (tmpfilename[1] == '.' && tmpfilename[2] == '/'))))
1044 {
20188a90 1045 rsfp = fopen(tmpfilename,"r");
83025b21 1046 }
33b78306 1047 else {
1048 ar = stab_array(incstab);
a687059c 1049 for (i = 0; i <= ar->ary_fill; i++) {
20188a90 1050 (void)sprintf(buf, "%s/%s",
1051 str_get(afetch(ar,i,TRUE)), specfilename);
a687059c 1052 rsfp = fopen(buf,"r");
1053 if (rsfp) {
33b78306 1054 char *s = buf;
1055
1056 if (*s == '.' && s[1] == '/')
1057 s += 2;
20188a90 1058 Safefree(tmpfilename);
1059 tmpfilename = savestr(s);
8d063cd8 1060 break;
1061 }
378cc40b 1062 }
1063 }
20188a90 1064 curcmd->c_filestab = fstab(tmpfilename);
1065 Safefree(tmpfilename);
fe14fcc3 1066 tmpfilename = Nullch;
a687059c 1067 if (!rsfp) {
20188a90 1068 curcmd = oldcurcmd;
a687059c 1069 tmps_base = oldtmps_base;
33b78306 1070 if (optype == O_REQUIRE) {
1071 sprintf(tokenbuf,"Can't locate %s in @INC", specfilename);
1072 if (instr(tokenbuf,".h "))
1073 strcat(tokenbuf," (change .h to .ph maybe?)");
1074 if (instr(tokenbuf,".ph "))
6eb13c3b 1075 strcat(tokenbuf," (did you run h2ph?)");
33b78306 1076 fatal("%s",tokenbuf);
1077 }
a687059c 1078 if (gimme != G_ARRAY)
1079 st[++sp] = &str_undef;
20188a90 1080 perldb = oldperldb;
a687059c 1081 return sp;
8d063cd8 1082 }
33b78306 1083 curcmd->c_line = 0;
8d063cd8 1084 }
a687059c 1085 in_eval++;
1086 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
1087 bufend = bufptr + linestr->str_cur;
ac58e20f 1088 if (++loop_ptr >= loop_max) {
1089 loop_max += 128;
1090 Renew(loop_stack, loop_max, struct loop);
1091 }
1092 loop_stack[loop_ptr].loop_label = "_EVAL_";
1093 loop_stack[loop_ptr].loop_sp = sp;
1094#ifdef DEBUGGING
1095 if (debug & 4) {
1096 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
1097 }
1098#endif
fe14fcc3 1099 eval_root = Nullcmd;
ac58e20f 1100 if (setjmp(loop_stack[loop_ptr].loop_env)) {
a687059c 1101 retval = 1;
8d063cd8 1102 }
a687059c 1103 else {
1104 error_count = 0;
20188a90 1105 if (rsfp) {
a687059c 1106 retval = yyparse();
20188a90 1107 retval |= error_count;
1108 }
45d8adaa 1109 else if (last_root && last_elen == bufend - bufptr
988174c1 1110 && *bufptr == *last_eval && !bcmp(bufptr,last_eval,last_elen)){
a687059c 1111 retval = 0;
1112 eval_root = last_root; /* no point in reparsing */
1113 }
45d8adaa 1114 else if (in_eval == 1 && !savecmd) {
a687059c 1115 if (last_root) {
1116 Safefree(last_eval);
fe14fcc3 1117 last_eval = Nullch;
a687059c 1118 cmd_free(last_root);
8d063cd8 1119 }
a687059c 1120 last_root = Nullcmd;
45d8adaa 1121 last_elen = bufend - bufptr;
1122 last_eval = nsavestr(bufptr, last_elen);
a687059c 1123 retval = yyparse();
20188a90 1124 retval |= error_count;
a687059c 1125 if (!retval)
1126 last_root = eval_root;
fe14fcc3 1127 if (!last_root) {
1128 Safefree(last_eval);
1129 last_eval = Nullch;
1130 }
8d063cd8 1131 }
a687059c 1132 else
1133 retval = yyparse();
8d063cd8 1134 }
a687059c 1135 myroot = eval_root; /* in case cmd_exec does another eval! */
20188a90 1136
83025b21 1137 if (retval || error_count) {
ac58e20f 1138 st = stack->ary_array;
1139 sp = arglast[0];
1140 if (gimme != G_ARRAY)
1141 st[++sp] = &str_undef;
fe14fcc3 1142 if (parsing) {
1143#ifndef MANGLEDPARSE
1144#ifdef DEBUGGING
1145 if (debug & 128)
1146 fprintf(stderr,"Freeing eval_root %lx\n",(long)eval_root);
1147#endif
1148 cmd_free(eval_root);
1149#endif
83025b21 1150 /*SUPPRESS 29*/ /*SUPPRESS 30*/
45d8adaa 1151 if ((CMD*)eval_root == last_root)
fe14fcc3 1152 last_root = Nullcmd;
1153 eval_root = myroot = Nullcmd;
1154 }
a687059c 1155 if (rsfp) {
1156 fclose(rsfp);
1157 rsfp = 0;
1158 }
8d063cd8 1159 }
8d063cd8 1160 else {
fe14fcc3 1161 parsing = 0;
a687059c 1162 sp = cmd_exec(eval_root,gimme,sp);
1163 st = stack->ary_array;
1164 for (i = arglast[0] + 1; i <= sp; i++)
fe14fcc3 1165 st[i] = str_mortal(st[i]);
a687059c 1166 /* if we don't save result, free zaps it */
45d8adaa 1167 if (savecmd)
1168 eval_root = myroot;
1169 else if (in_eval != 1 && myroot != last_root)
a687059c 1170 cmd_free(myroot);
a559c259 1171 }
20188a90 1172
1173 perldb = oldperldb;
a559c259 1174 in_eval--;
ac58e20f 1175#ifdef DEBUGGING
20188a90 1176 if (debug & 4) {
1177 char *tmps = loop_stack[loop_ptr].loop_label;
1178 deb("(Popping label #%d %s)\n",loop_ptr,
1179 tmps ? tmps : "" );
1180 }
ac58e20f 1181#endif
1182 loop_ptr--;
378cc40b 1183 tmps_base = oldtmps_base;
a687059c 1184 curspat = oldspat;
fe14fcc3 1185 lastspat = oldlspat;
378cc40b 1186 if (savestack->ary_fill > oldsave) /* let them use local() */
1187 restorelist(oldsave);
20188a90 1188
1189 if (optype != O_EVAL) {
1190 if (retval) {
1191 if (optype == O_REQUIRE)
1192 fatal("%s", str_get(stab_val(stabent("@",TRUE))));
1193 }
1194 else {
1195 curcmd = oldcurcmd;
1196 if (gimme == G_SCALAR ? str_true(st[sp]) : sp > arglast[0]) {
1197 (void)hstore(stab_hash(incstab), specfilename,
1198 strlen(specfilename), str_smake(stab_val(curcmd->c_filestab)),
1199 0 );
1200 }
1201 else if (optype == O_REQUIRE)
1202 fatal("%s did not return a true value", specfilename);
1203 }
1204 }
1205 curcmd = oldcurcmd;
a687059c 1206 return sp;
378cc40b 1207}
33b78306 1208
45d8adaa 1209int
1210do_try(cmd,gimme,arglast)
1211CMD *cmd;
1212int gimme;
1213int *arglast;
1214{
1215 STR **st = stack->ary_array;
1216
1217 CMD * VOLATILE oldcurcmd = curcmd;
1218 VOLATILE int oldtmps_base = tmps_base;
1219 VOLATILE int oldsave = savestack->ary_fill;
1220 SPAT * VOLATILE oldspat = curspat;
1221 SPAT * VOLATILE oldlspat = lastspat;
1222 VOLATILE int sp = arglast[0];
1223
1224 tmps_base = tmps_max;
1225 str_set(stab_val(stabent("@",TRUE)),"");
1226 in_eval++;
1227 if (++loop_ptr >= loop_max) {
1228 loop_max += 128;
1229 Renew(loop_stack, loop_max, struct loop);
1230 }
1231 loop_stack[loop_ptr].loop_label = "_EVAL_";
1232 loop_stack[loop_ptr].loop_sp = sp;
1233#ifdef DEBUGGING
1234 if (debug & 4) {
1235 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
1236 }
1237#endif
1238 if (setjmp(loop_stack[loop_ptr].loop_env)) {
1239 st = stack->ary_array;
1240 sp = arglast[0];
1241 if (gimme != G_ARRAY)
1242 st[++sp] = &str_undef;
1243 }
1244 else {
1245 sp = cmd_exec(cmd,gimme,sp);
1246 st = stack->ary_array;
1247/* for (i = arglast[0] + 1; i <= sp; i++)
1248 st[i] = str_mortal(st[i]); not needed, I think */
1249 /* if we don't save result, free zaps it */
1250 }
1251
1252 in_eval--;
1253#ifdef DEBUGGING
1254 if (debug & 4) {
1255 char *tmps = loop_stack[loop_ptr].loop_label;
1256 deb("(Popping label #%d %s)\n",loop_ptr,
1257 tmps ? tmps : "" );
1258 }
1259#endif
1260 loop_ptr--;
1261 tmps_base = oldtmps_base;
1262 curspat = oldspat;
1263 lastspat = oldlspat;
1264 curcmd = oldcurcmd;
1265 if (savestack->ary_fill > oldsave) /* let them use local() */
1266 restorelist(oldsave);
1267
1268 return sp;
1269}
1270
33b78306 1271/* This routine handles any switches that can be given during run */
1272
1273static char *
1274moreswitches(s)
1275char *s;
1276{
fe14fcc3 1277 int numlen;
1278
33b78306 1279 switch (*s) {
27e2fb84 1280 case '0':
fe14fcc3 1281 nrschar = scanoct(s, 4, &numlen);
1282 nrs = nsavestr("\n",1);
1283 *nrs = nrschar;
1284 if (nrschar > 0377) {
1285 nrslen = 0;
1286 nrs = "";
27e2fb84 1287 }
fe14fcc3 1288 else if (!nrschar && numlen >= 2) {
1289 nrslen = 2;
1290 nrs = "\n\n";
1291 nrschar = '\n';
1292 }
1293 return s + numlen;
33b78306 1294 case 'a':
1295 minus_a = TRUE;
1296 s++;
1297 return s;
1298 case 'c':
1299 minus_c = TRUE;
1300 s++;
1301 return s;
1302 case 'd':
1303#ifdef TAINT
1304 if (euid != uid || egid != gid)
1305 fatal("No -d allowed in setuid scripts");
1306#endif
1307 perldb = TRUE;
1308 s++;
1309 return s;
1310 case 'D':
1311#ifdef DEBUGGING
1312#ifdef TAINT
1313 if (euid != uid || egid != gid)
1314 fatal("No -D allowed in setuid scripts");
1315#endif
fe14fcc3 1316 debug = atoi(s+1) | 32768;
33b78306 1317#else
1318 warn("Recompile perl with -DDEBUGGING to use -D switch\n");
1319#endif
45d8adaa 1320 /*SUPPRESS 530*/
1321 for (s++; isDIGIT(*s); s++) ;
fe14fcc3 1322 return s;
33b78306 1323 case 'i':
1324 inplace = savestr(s+1);
45d8adaa 1325 /*SUPPRESS 530*/
1326 for (s = inplace; *s && !isSPACE(*s); s++) ;
33b78306 1327 *s = '\0';
33b78306 1328 break;
1329 case 'I':
1330#ifdef TAINT
1331 if (euid != uid || egid != gid)
1332 fatal("No -I allowed in setuid scripts");
1333#endif
1334 if (*++s) {
1335 (void)apush(stab_array(incstab),str_make(s,0));
1336 }
1337 else
1338 fatal("No space allowed after -I");
1339 break;
fe14fcc3 1340 case 'l':
1341 minus_l = TRUE;
1342 s++;
45d8adaa 1343 if (isDIGIT(*s)) {
fe14fcc3 1344 ors = savestr("\n");
1345 orslen = 1;
1346 *ors = scanoct(s, 3 + (*s == '0'), &numlen);
1347 s += numlen;
1348 }
1349 else {
1350 ors = nsavestr(nrs,nrslen);
1351 orslen = nrslen;
1352 }
1353 return s;
33b78306 1354 case 'n':
1355 minus_n = TRUE;
1356 s++;
1357 return s;
1358 case 'p':
1359 minus_p = TRUE;
1360 s++;
1361 return s;
1362 case 'u':
1363 do_undump = TRUE;
1364 s++;
1365 return s;
1366 case 'U':
1367 unsafe = TRUE;
1368 s++;
1369 return s;
1370 case 'v':
fe14fcc3 1371 fputs("\nThis is perl, version 4.0\n\n",stdout);
33b78306 1372 fputs(rcsid,stdout);
fe14fcc3 1373 fputs("\nCopyright (c) 1989, 1990, 1991, Larry Wall\n",stdout);
33b78306 1374#ifdef MSDOS
1375 fputs("MS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n",
1376 stdout);
20188a90 1377#ifdef OS2
83025b21 1378 fputs("OS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n",
20188a90 1379 stdout);
1380#endif
33b78306 1381#endif
83025b21 1382#ifdef atarist
1383 fputs("atariST series port, ++jrb bammi@cadence.com\n", stdout);
1384#endif
33b78306 1385 fputs("\n\
1462b684 1386Perl may be copied only under the terms of either the Artistic License or the\n\
1387GNU General Public License, which may be found in the Perl 4.0 source kit.\n",stdout);
20188a90 1388#ifdef MSDOS
1389 usage(origargv[0]);
1390#endif
33b78306 1391 exit(0);
1392 case 'w':
1393 dowarn = TRUE;
1394 s++;
1395 return s;
1396 case ' ':
1397 case '\n':
1398 case '\t':
1399 break;
1400 default:
1401 fatal("Switch meaningless after -x: -%s",s);
1402 }
1403 return Nullch;
1404}
34de22dd 1405
1406/* compliments of Tom Christiansen */
1407
1408/* unexec() can be found in the Gnu emacs distribution */
1409
83025b21 1410void
34de22dd 1411my_unexec()
1412{
1413#ifdef UNEXEC
1414 int status;
1415 extern int etext;
1416 static char dumpname[BUFSIZ];
1417 static char perlpath[256];
1418
1419 sprintf (dumpname, "%s.perldump", origfilename);
1420 sprintf (perlpath, "%s/perl", BIN);
1421
1422 status = unexec(dumpname, perlpath, &etext, sbrk(0), 0);
1423 if (status)
1424 fprintf(stderr, "unexec of %s into %s failed!\n", perlpath, dumpname);
1425 exit(status);
1426#else
83025b21 1427#ifdef DOSISH
352d5a3a 1428 abort(); /* nothing else to do */
1429#else /* ! MSDOS */
fe14fcc3 1430# ifndef SIGABRT
1431# define SIGABRT SIGILL
1432# endif
1433# ifndef SIGILL
1434# define SIGILL 6 /* blech */
1435# endif
1436 kill(getpid(),SIGABRT); /* for use with undump */
352d5a3a 1437#endif /* ! MSDOS */
34de22dd 1438#endif
1439}
1440