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