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