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