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