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