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