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