This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl 4.0 patch 36: (combined patch)
[perl5.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
LW
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
a687059c 7 *
fe14fcc3 8 * $Log: perl.c,v $
83025b21
LW
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
LW
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
LW
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
LW
33 * Revision 4.0.1.4 91/06/10 01:23:07 lwall
34 * patch10: perl -v printed incorrect copyright notice
35 *
352d5a3a
LW
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
LW
45 * Revision 4.0.1.1 91/04/11 17:49:05 lwall
46 * patch1: fixed undefined environ problem
47 *
fe14fcc3
LW
48 * Revision 4.0 91/03/20 01:37:44 lwall
49 * 4.0 baseline.
8d063cd8
LW
50 *
51 */
52
45d8adaa
LW
53/*SUPPRESS 560*/
54
378cc40b
LW
55#include "EXTERN.h"
56#include "perl.h"
57#include "perly.h"
a687059c 58#include "patchlevel.h"
378cc40b 59
352d5a3a
LW
60char *getenv();
61
a687059c
LW
62#ifdef IAMSUID
63#ifndef DOSUID
64#define DOSUID
65#endif
66#endif
378cc40b 67
a687059c
LW
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
LW
79static char *nrs = "\n";
80static int nrschar = '\n'; /* final char of rs, or 0777 if none */
81static int nrslen = 1;
33b78306 82
8d063cd8
LW
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
LW
94 char *validarg = "";
95#endif
8d063cd8 96
a687059c
LW
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
LW
105 origargv = argv;
106 origargc = argc;
fe14fcc3 107 origenviron = environ;
378cc40b
LW
108 uid = (int)getuid();
109 euid = (int)geteuid();
a687059c
LW
110 gid = (int)getgid();
111 egid = (int)getegid();
fe14fcc3 112 sprintf(patchlevel,"%3.3s%2.2d", index(rcsid,'4'), PATCHLEVEL);
0f85fab0
LW
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
LW
126 goto just_doit;
127 }
83025b21
LW
128#ifdef TAINT
129#ifndef DOSUID
130 if (uid == euid && gid == egid)
e334a159 131 taintanyway = TRUE; /* running taintperl explicitly */
83025b21
LW
132#endif
133#endif
a687059c
LW
134 (void)sprintf(index(rcsid,'#'), "%d\n", PATCHLEVEL);
135 linestr = Str_new(65,80);
378cc40b 136 str_nset(linestr,"",0);
a687059c
LW
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
LW
145 if (argv[0][0] != '-' || !argv[0][1])
146 break;
13281fa4
LW
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
LW
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
LW
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
LW
179 e_tmpname = savestr(TMPPATH);
180 (void)mktemp(e_tmpname);
83025b21
LW
181 if (!*e_tmpname)
182 fatal("Can't mktemp()");
8d063cd8 183 e_fp = fopen(e_tmpname,"w");
33b78306
LW
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
LW
189 argc--,argv++;
190 }
a687059c 191 (void)putc('\n', e_fp);
8d063cd8
LW
192 break;
193 case 'I':
a687059c
LW
194#ifdef TAINT
195 if (euid != uid || egid != gid)
196 fatal("No -I allowed in setuid scripts");
197#endif
13281fa4
LW
198 str_cat(str,"-");
199 str_cat(str,s);
8d063cd8 200 str_cat(str," ");
a687059c
LW
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
LW
206 str_cat(str,argv[1]);
207 argc--,argv++;
208 str_cat(str," ");
209 }
210 break;
8d063cd8 211 case 'P':
a687059c
LW
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
LW
218 goto reswitch;
219 case 's':
a687059c
LW
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
LW
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
LW
235 case 'x':
236 doextract = TRUE;
13281fa4 237 s++;
33b78306
LW
238 if (*s)
239 cddir = savestr(s);
240 break;
8d063cd8
LW
241 case '-':
242 argc--,argv++;
243 goto switch_end;
244 case 0:
245 break;
246 default:
13281fa4 247 fatal("Unrecognized switch: -%s",s);
8d063cd8
LW
248 }
249 }
250 switch_end:
45d8adaa 251 scriptname = argv[0];
8d063cd8 252 if (e_fp) {
83025b21
LW
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
LW
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
LW
266#endif /* TAINT */
267
378cc40b
LW
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
LW
273
274 str_set(&str_no,No);
275 str_set(&str_yes,Yes);
8d063cd8
LW
276
277 /* open script */
278
45d8adaa 279 if (scriptname == Nullch)
34de22dd
LW
280#ifdef MSDOS
281 {
282 if ( isatty(fileno(stdin)) )
283 moreswitches("v");
45d8adaa 284 scriptname = "-";
34de22dd
LW
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
LW
298#ifdef atarist
299 for (len = 0; *s && *s != ',' && *s != ';'; tokenbuf[len++] = *s++);
300 tokenbuf[len] = '\0';
301#else
33b78306
LW
302 for (len = 0; *s && *s != ';'; tokenbuf[len++] = *s++);
303 tokenbuf[len] = '\0';
304#endif
83025b21 305#endif
378cc40b
LW
306 if (*s)
307 s++;
83025b21 308#ifndef DOSISH
33b78306
LW
309 if (len && tokenbuf[len-1] != '/')
310#else
83025b21
LW
311#ifdef atarist
312 if (len && ((tokenbuf[len-1] != '\\') && (tokenbuf[len-1] != '/')))
313#else
33b78306
LW
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
LW
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
LW
325 if (S_ISREG(statbuf.st_mode)
326 && cando(S_IRUSR,TRUE,&statbuf) && cando(S_IXUSR,TRUE,&statbuf)) {
378cc40b
LW
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
LW
344 curcmd->c_filestab = fstab(origfilename);
345 if (strEQ(origfilename,"-"))
45d8adaa 346 scriptname = "";
8d063cd8 347 if (preprocess) {
45d8adaa
LW
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
LW
354 str_cat(str,"-I");
355 str_cat(str,PRIVLIB);
83025b21 356#ifdef MSDOS
a687059c 357 (void)sprintf(buf, "\
83025b21
LW
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
LW
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
LW
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
LW
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
LW
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
LW
403 (void)seteuid(uid); /* musn't stay setuid root */
404#else
fe14fcc3 405#ifdef HAS_SETREUID
a687059c
LW
406 (void)setreuid(-1, uid);
407#else
408 setuid(uid);
409#endif
13281fa4 410#endif
83025b21
LW
411 if (geteuid() != uid)
412 fatal("Can't do seteuid!\n");
413 }
a687059c
LW
414#endif /* IAMSUID */
415 rsfp = mypopen(buf,"r");
8d063cd8 416 }
45d8adaa
LW
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
LW
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
LW
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
LW
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
LW
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
LW
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
LW
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
LW
470#ifdef DOSUID
471 if (fstat(fileno(rsfp),&statbuf) < 0) /* normal stat is insecure */
20188a90 472 fatal("Can't stat script \"%s\"",origfilename);
13281fa4
LW
473 if (statbuf.st_mode & (S_ISUID|S_ISGID)) {
474 int len;
475
a687059c 476#ifdef IAMSUID
fe14fcc3 477#ifndef HAS_SETREUID
a687059c
LW
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
LW
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
LW
499 if (stat(stab_val(curcmd->c_filestab)->str_ptr,&tmpstatbuf) < 0)
500 fatal("Permission denied"); /* testing full pathname here */
a687059c
LW
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
LW
510 stab_val(curcmd->c_filestab)->str_ptr,
511 statbuf.st_uid, statbuf.st_gid);
a687059c
LW
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
LW
519 fatal("Permission denied\n");
520 }
fe14fcc3 521#endif /* HAS_SETREUID */
a687059c
LW
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
LW
530 if (fgets(tokenbuf,sizeof tokenbuf, rsfp) == Nullch ||
531 strnNE(tokenbuf,"#!",2) ) /* required even on Sys V */
532 fatal("No #! line");
663a0e37
LW
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
LW
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
LW
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
LW
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
LW
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
LW
568 (void)setegid(statbuf.st_gid);
569#else
fe14fcc3 570#ifdef HAS_SETREGID
a687059c
LW
571 (void)setregid((GIDTYPE)-1,statbuf.st_gid);
572#else
573 setgid(statbuf.st_gid);
574#endif
575#endif
83025b21
LW
576 if (getegid() != statbuf.st_gid)
577 fatal("Can't do setegid!\n");
578 }
a687059c
LW
579 if (statbuf.st_mode & S_ISUID) {
580 if (statbuf.st_uid != euid)
fe14fcc3 581#ifdef HAS_SETEUID
a687059c
LW
582 (void)seteuid(statbuf.st_uid); /* all that for this */
583#else
fe14fcc3 584#ifdef HAS_SETREUID
a687059c
LW
585 (void)setreuid((UIDTYPE)-1,statbuf.st_uid);
586#else
587 setuid(statbuf.st_uid);
588#endif
589#endif
83025b21
LW
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
LW
595 (void)seteuid((UIDTYPE)uid);
596#else
fe14fcc3 597#ifdef HAS_SETREUID
a687059c
LW
598 (void)setreuid((UIDTYPE)-1,(UIDTYPE)uid);
599#else
600 setuid((UIDTYPE)uid);
601#endif
602#endif
83025b21
LW
603 if (geteuid() != uid)
604 fatal("Can't do seteuid!\n");
605 }
ffed7fef 606 uid = (int)getuid();
13281fa4 607 euid = (int)geteuid();
ffed7fef
LW
608 gid = (int)getgid();
609 egid = (int)getegid();
27e2fb84 610 if (!cando(S_IXUSR,TRUE,&statbuf))
13281fa4
LW
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
LW
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
LW
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
LW
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
LW
645 execv(buf, origargv); /* try again */
646 fatal("Can't run setuid script with taint checks");
647 }
648#endif /* TAINT */
13281fa4
LW
649#endif /* DOSUID */
650
33b78306
LW
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
LW
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
LW
672 defstab = stabent("_",TRUE);
673
988174c1 674 subname = str_make("main",4);
a687059c
LW
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
LW
682 DBstab = stabent("DB",TRUE);
683 DBstab->str_pok |= SP_MULTI;
20188a90
LW
684 DBline = stabent("dbline",TRUE);
685 DBline->str_pok |= SP_MULTI;
a687059c
LW
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
LW
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
LW
694 curstash = defstash;
695 }
696
8d063cd8
LW
697 /* init tokener */
698
a687059c
LW
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
LW
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
LW
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
LW
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
LW
727
728 preprocess = FALSE;
8d063cd8
LW
729 if (e_fp) {
730 e_fp = Nullfp;
a687059c
LW
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
LW
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
LW
750 if (tmpstab = stabent("\024",allstabs))
751 time(&basetime);
a687059c
LW
752
753 /* these aren't necessarily magical */
83025b21
LW
754 if (tmpstab = stabent("\014",allstabs)) {
755 str_set(stab_val(tmpstab),"\f");
756 formfeed = stab_val(tmpstab);
757 }
a687059c
LW
758 if (tmpstab = stabent(";",allstabs))
759 str_set(STAB_STR(tmpstab),"\034");
33b78306
LW
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
LW
764 str->str_nok = 1;
765 }
a687059c
LW
766 str_nset(stab_val(stabent("\"", TRUE)), " ", 1);
767
768 stdinstab = stabent("STDIN",TRUE);
769 stdinstab->str_pok |= SP_MULTI;
83025b21
LW
770 if (!stab_io(stdinstab))
771 stab_io(stdinstab) = stio_new();
a687059c
LW
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
LW
779 if (!stab_io(tmpstab))
780 stab_io(tmpstab) = stio_new();
a687059c
LW
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
LW
789 if (!stab_io(curoutstab))
790 stab_io(curoutstab) = stio_new();
a687059c
LW
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
LW
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
LW
805 str_nset(stab_val(stabent("/", TRUE)), rs, rslen);
806
a687059c 807 if (do_undump)
34de22dd 808 my_unexec();
a687059c
LW
809
810 just_doit: /* come here if running an undumped a.out */
8d063cd8
LW
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
LW
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
LW
824 }
825 }
a687059c
LW
826#ifdef TAINT
827 tainted = 1;
828#endif
fe14fcc3 829 if (tmpstab = stabent("0",allstabs)) {
34de22dd 830 str_set(stab_val(tmpstab),origfilename);
fe14fcc3
LW
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
LW
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
LW
841 }
842 }
a687059c
LW
843#ifdef TAINT
844 (void) stabent("ENV",TRUE); /* must test PATH and IFS */
845#endif
a559c259 846 if (envstab = stabent("ENV",allstabs)) {
a687059c
LW
847 envstab->str_pok |= SP_MULTI;
848 (void)hadd(envstab);
20188a90 849 hclear(stab_hash(envstab), FALSE);
33b78306
LW
850 if (env != environ)
851 environ[0] = Nullch;
8d063cd8
LW
852 for (; *env; env++) {
853 if (!(s = index(*env,'=')))
854 continue;
855 *s++ = '\0';
a687059c
LW
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
LW
860 }
861 }
a687059c
LW
862#ifdef TAINT
863 tainted = 0;
864#endif
378cc40b 865 if (tmpstab = stabent("$",allstabs))
8d063cd8
LW
866 str_numset(STAB_STR(tmpstab),(double)getpid());
867
20188a90
LW
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
LW
875
876#ifdef DEBUGGING
877 if (debug & 1024)
a687059c 878 dump_all();
8d063cd8
LW
879 if (debug)
880 fprintf(stderr,"\nEXECUTING...\n\n");
881#endif
882
33b78306
LW
883 if (minus_c) {
884 fprintf(stderr,"%s syntax OK\n", origfilename);
885 exit(0);
886 }
887
8d063cd8
LW
888 /* do it */
889
a687059c 890 (void) cmd_exec(main_root,G_SCALAR,-1);
8d063cd8
LW
891
892 if (goto_targ)
378cc40b 893 fatal("Can't find label \"%s\"--aborting",goto_targ);
8d063cd8 894 exit(0);
378cc40b 895 /* NOTREACHED */
8d063cd8
LW
896}
897
fe14fcc3 898void
8d063cd8
LW
899magicalize(list)
900register char *list;
901{
8d063cd8
LW
902 char sym[2];
903
904 sym[1] = '\0';
33b78306
LW
905 while (*sym = *list++)
906 magicname(sym, Nullch, 0);
907}
908
fe14fcc3 909void
33b78306
LW
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
LW
921}
922
83025b21
LW
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
LW
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
LW
979STR *str;
980int optype;
981HASH *stash;
45d8adaa 982int savecmd;
a687059c
LW
983int gimme;
984int *arglast;
8d063cd8 985{
a687059c
LW
986 STR **st = stack->ary_array;
987 int retval;
fe14fcc3 988 CMD *myroot = Nullcmd;
a687059c
LW
989 ARRAY *ar;
990 int i;
33b78306 991 CMD * VOLATILE oldcurcmd = curcmd;
ac58e20f
LW
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
LW
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
LW
1011 if (curcmd->c_line == 0) /* don't debug debugger... */
1012 perldb = FALSE;
33b78306
LW
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
LW
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
LW
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
LW
1034 tmps_base = oldtmps_base;
1035 st[++sp] = &str_yes;
20188a90 1036 perldb = oldperldb;
33b78306
LW
1037 return sp;
1038 }
20188a90 1039 tmpfilename = savestr(specfilename);
83025b21
LW
1040 if (*tmpfilename == '/' ||
1041 (*tmpfilename == '.' &&
1042 (tmpfilename[1] == '/' ||
1043 (tmpfilename[1] == '.' && tmpfilename[2] == '/'))))
1044 {
20188a90 1045 rsfp = fopen(tmpfilename,"r");
83025b21 1046 }
33b78306
LW
1047 else {
1048 ar = stab_array(incstab);
a687059c 1049 for (i = 0; i <= ar->ary_fill; i++) {
20188a90
LW
1050 (void)sprintf(buf, "%s/%s",
1051 str_get(afetch(ar,i,TRUE)), specfilename);
a687059c
LW
1052 rsfp = fopen(buf,"r");
1053 if (rsfp) {
33b78306
LW
1054 char *s = buf;
1055
1056 if (*s == '.' && s[1] == '/')
1057 s += 2;
20188a90
LW
1058 Safefree(tmpfilename);
1059 tmpfilename = savestr(s);
8d063cd8
LW
1060 break;
1061 }
378cc40b
LW
1062 }
1063 }
20188a90
LW
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
LW
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
LW
1076 fatal("%s",tokenbuf);
1077 }
a687059c
LW
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
LW
1085 in_eval++;
1086 oldoldbufptr = oldbufptr = bufptr = str_get(linestr);
1087 bufend = bufptr + linestr->str_cur;
ac58e20f
LW
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
LW
1103 else {
1104 error_count = 0;
20188a90 1105 if (rsfp) {
a687059c 1106 retval = yyparse();
20188a90
LW
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
LW
1111 retval = 0;
1112 eval_root = last_root; /* no point in reparsing */
1113 }
45d8adaa 1114 else if (in_eval == 1 && !savecmd) {
a687059c
LW
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
LW
1121 last_elen = bufend - bufptr;
1122 last_eval = nsavestr(bufptr, last_elen);
a687059c 1123 retval = yyparse();
20188a90 1124 retval |= error_count;
a687059c
LW
1125 if (!retval)
1126 last_root = eval_root;
fe14fcc3
LW
1127 if (!last_root) {
1128 Safefree(last_eval);
1129 last_eval = Nullch;
1130 }
8d063cd8 1131 }
a687059c
LW
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
LW
1138 st = stack->ary_array;
1139 sp = arglast[0];
1140 if (gimme != G_ARRAY)
1141 st[++sp] = &str_undef;
fe14fcc3
LW
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
LW
1152 last_root = Nullcmd;
1153 eval_root = myroot = Nullcmd;
1154 }
a687059c
LW
1155 if (rsfp) {
1156 fclose(rsfp);
1157 rsfp = 0;
1158 }
8d063cd8 1159 }
8d063cd8 1160 else {
fe14fcc3 1161 parsing = 0;
a687059c
LW
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
LW
1167 if (savecmd)
1168 eval_root = myroot;
1169 else if (in_eval != 1 && myroot != last_root)
a687059c 1170 cmd_free(myroot);
e334a159
LW
1171 if (eval_root == myroot)
1172 eval_root = Nullcmd;
a559c259 1173 }
20188a90
LW
1174
1175 perldb = oldperldb;
a559c259 1176 in_eval--;
ac58e20f 1177#ifdef DEBUGGING
20188a90
LW
1178 if (debug & 4) {
1179 char *tmps = loop_stack[loop_ptr].loop_label;
1180 deb("(Popping label #%d %s)\n",loop_ptr,
1181 tmps ? tmps : "" );
1182 }
ac58e20f
LW
1183#endif
1184 loop_ptr--;
378cc40b 1185 tmps_base = oldtmps_base;
a687059c 1186 curspat = oldspat;
fe14fcc3 1187 lastspat = oldlspat;
378cc40b
LW
1188 if (savestack->ary_fill > oldsave) /* let them use local() */
1189 restorelist(oldsave);
20188a90
LW
1190
1191 if (optype != O_EVAL) {
1192 if (retval) {
1193 if (optype == O_REQUIRE)
1194 fatal("%s", str_get(stab_val(stabent("@",TRUE))));
1195 }
1196 else {
1197 curcmd = oldcurcmd;
1198 if (gimme == G_SCALAR ? str_true(st[sp]) : sp > arglast[0]) {
1199 (void)hstore(stab_hash(incstab), specfilename,
1200 strlen(specfilename), str_smake(stab_val(curcmd->c_filestab)),
1201 0 );
1202 }
1203 else if (optype == O_REQUIRE)
1204 fatal("%s did not return a true value", specfilename);
1205 }
1206 }
1207 curcmd = oldcurcmd;
a687059c 1208 return sp;
378cc40b 1209}
33b78306 1210
45d8adaa
LW
1211int
1212do_try(cmd,gimme,arglast)
1213CMD *cmd;
1214int gimme;
1215int *arglast;
1216{
1217 STR **st = stack->ary_array;
1218
1219 CMD * VOLATILE oldcurcmd = curcmd;
1220 VOLATILE int oldtmps_base = tmps_base;
1221 VOLATILE int oldsave = savestack->ary_fill;
1222 SPAT * VOLATILE oldspat = curspat;
1223 SPAT * VOLATILE oldlspat = lastspat;
1224 VOLATILE int sp = arglast[0];
1225
1226 tmps_base = tmps_max;
1227 str_set(stab_val(stabent("@",TRUE)),"");
1228 in_eval++;
1229 if (++loop_ptr >= loop_max) {
1230 loop_max += 128;
1231 Renew(loop_stack, loop_max, struct loop);
1232 }
1233 loop_stack[loop_ptr].loop_label = "_EVAL_";
1234 loop_stack[loop_ptr].loop_sp = sp;
1235#ifdef DEBUGGING
1236 if (debug & 4) {
1237 deb("(Pushing label #%d _EVAL_)\n", loop_ptr);
1238 }
1239#endif
1240 if (setjmp(loop_stack[loop_ptr].loop_env)) {
1241 st = stack->ary_array;
1242 sp = arglast[0];
1243 if (gimme != G_ARRAY)
1244 st[++sp] = &str_undef;
1245 }
1246 else {
1247 sp = cmd_exec(cmd,gimme,sp);
1248 st = stack->ary_array;
1249/* for (i = arglast[0] + 1; i <= sp; i++)
1250 st[i] = str_mortal(st[i]); not needed, I think */
1251 /* if we don't save result, free zaps it */
1252 }
1253
1254 in_eval--;
1255#ifdef DEBUGGING
1256 if (debug & 4) {
1257 char *tmps = loop_stack[loop_ptr].loop_label;
1258 deb("(Popping label #%d %s)\n",loop_ptr,
1259 tmps ? tmps : "" );
1260 }
1261#endif
1262 loop_ptr--;
1263 tmps_base = oldtmps_base;
1264 curspat = oldspat;
1265 lastspat = oldlspat;
1266 curcmd = oldcurcmd;
1267 if (savestack->ary_fill > oldsave) /* let them use local() */
1268 restorelist(oldsave);
1269
1270 return sp;
1271}
1272
33b78306
LW
1273/* This routine handles any switches that can be given during run */
1274
1275static char *
1276moreswitches(s)
1277char *s;
1278{
fe14fcc3
LW
1279 int numlen;
1280
33b78306 1281 switch (*s) {
27e2fb84 1282 case '0':
fe14fcc3
LW
1283 nrschar = scanoct(s, 4, &numlen);
1284 nrs = nsavestr("\n",1);
1285 *nrs = nrschar;
1286 if (nrschar > 0377) {
1287 nrslen = 0;
1288 nrs = "";
27e2fb84 1289 }
fe14fcc3
LW
1290 else if (!nrschar && numlen >= 2) {
1291 nrslen = 2;
1292 nrs = "\n\n";
1293 nrschar = '\n';
1294 }
1295 return s + numlen;
33b78306
LW
1296 case 'a':
1297 minus_a = TRUE;
1298 s++;
1299 return s;
1300 case 'c':
1301 minus_c = TRUE;
1302 s++;
1303 return s;
1304 case 'd':
1305#ifdef TAINT
1306 if (euid != uid || egid != gid)
1307 fatal("No -d allowed in setuid scripts");
1308#endif
1309 perldb = TRUE;
1310 s++;
1311 return s;
1312 case 'D':
1313#ifdef DEBUGGING
1314#ifdef TAINT
1315 if (euid != uid || egid != gid)
1316 fatal("No -D allowed in setuid scripts");
1317#endif
fe14fcc3 1318 debug = atoi(s+1) | 32768;
33b78306
LW
1319#else
1320 warn("Recompile perl with -DDEBUGGING to use -D switch\n");
1321#endif
45d8adaa
LW
1322 /*SUPPRESS 530*/
1323 for (s++; isDIGIT(*s); s++) ;
fe14fcc3 1324 return s;
33b78306
LW
1325 case 'i':
1326 inplace = savestr(s+1);
45d8adaa
LW
1327 /*SUPPRESS 530*/
1328 for (s = inplace; *s && !isSPACE(*s); s++) ;
33b78306 1329 *s = '\0';
33b78306
LW
1330 break;
1331 case 'I':
1332#ifdef TAINT
1333 if (euid != uid || egid != gid)
1334 fatal("No -I allowed in setuid scripts");
1335#endif
1336 if (*++s) {
1337 (void)apush(stab_array(incstab),str_make(s,0));
1338 }
1339 else
1340 fatal("No space allowed after -I");
1341 break;
fe14fcc3
LW
1342 case 'l':
1343 minus_l = TRUE;
1344 s++;
45d8adaa 1345 if (isDIGIT(*s)) {
fe14fcc3
LW
1346 ors = savestr("\n");
1347 orslen = 1;
1348 *ors = scanoct(s, 3 + (*s == '0'), &numlen);
1349 s += numlen;
1350 }
1351 else {
1352 ors = nsavestr(nrs,nrslen);
1353 orslen = nrslen;
1354 }
1355 return s;
33b78306
LW
1356 case 'n':
1357 minus_n = TRUE;
1358 s++;
1359 return s;
1360 case 'p':
1361 minus_p = TRUE;
1362 s++;
1363 return s;
1364 case 'u':
1365 do_undump = TRUE;
1366 s++;
1367 return s;
1368 case 'U':
1369 unsafe = TRUE;
1370 s++;
1371 return s;
1372 case 'v':
fe14fcc3 1373 fputs("\nThis is perl, version 4.0\n\n",stdout);
33b78306 1374 fputs(rcsid,stdout);
fe14fcc3 1375 fputs("\nCopyright (c) 1989, 1990, 1991, Larry Wall\n",stdout);
33b78306
LW
1376#ifdef MSDOS
1377 fputs("MS-DOS port Copyright (c) 1989, 1990, Diomidis Spinellis\n",
1378 stdout);
20188a90 1379#ifdef OS2
83025b21 1380 fputs("OS/2 port Copyright (c) 1990, 1991, Raymond Chen, Kai Uwe Rommel\n",
20188a90
LW
1381 stdout);
1382#endif
33b78306 1383#endif
83025b21
LW
1384#ifdef atarist
1385 fputs("atariST series port, ++jrb bammi@cadence.com\n", stdout);
1386#endif
33b78306 1387 fputs("\n\
1462b684
LW
1388Perl may be copied only under the terms of either the Artistic License or the\n\
1389GNU General Public License, which may be found in the Perl 4.0 source kit.\n",stdout);
20188a90
LW
1390#ifdef MSDOS
1391 usage(origargv[0]);
1392#endif
33b78306
LW
1393 exit(0);
1394 case 'w':
1395 dowarn = TRUE;
1396 s++;
1397 return s;
1398 case ' ':
1399 case '\n':
1400 case '\t':
1401 break;
1402 default:
1403 fatal("Switch meaningless after -x: -%s",s);
1404 }
1405 return Nullch;
1406}
34de22dd
LW
1407
1408/* compliments of Tom Christiansen */
1409
1410/* unexec() can be found in the Gnu emacs distribution */
1411
83025b21 1412void
34de22dd
LW
1413my_unexec()
1414{
1415#ifdef UNEXEC
1416 int status;
1417 extern int etext;
1418 static char dumpname[BUFSIZ];
1419 static char perlpath[256];
1420
1421 sprintf (dumpname, "%s.perldump", origfilename);
1422 sprintf (perlpath, "%s/perl", BIN);
1423
1424 status = unexec(dumpname, perlpath, &etext, sbrk(0), 0);
1425 if (status)
1426 fprintf(stderr, "unexec of %s into %s failed!\n", perlpath, dumpname);
1427 exit(status);
1428#else
83025b21 1429#ifdef DOSISH
352d5a3a
LW
1430 abort(); /* nothing else to do */
1431#else /* ! MSDOS */
fe14fcc3
LW
1432# ifndef SIGABRT
1433# define SIGABRT SIGILL
1434# endif
1435# ifndef SIGILL
1436# define SIGILL 6 /* blech */
1437# endif
1438 kill(getpid(),SIGABRT); /* for use with undump */
352d5a3a 1439#endif /* ! MSDOS */
34de22dd
LW
1440#endif
1441}
1442