Remove last traces of "tokenbuf as temp buffer" and removed it
[p5sagit/p5-mst-13.2.git] / mg.c
1 /*    mg.c
2  *
3  *    Copyright (c) 1991-1997, Larry Wall
4  *
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.
7  *
8  */
9
10 /*
11  * "Sam sat on the ground and put his head in his hands.  'I wish I had never
12  * come here, and I don't want to see no more magic,' he said, and fell silent."
13  */
14
15 #include "EXTERN.h"
16 #include "perl.h"
17
18 /* XXX If this causes problems, set i_unistd=undef in the hint file.  */
19 #ifdef I_UNISTD
20 # include <unistd.h>
21 #endif
22
23 #if defined(HAS_GETGROUPS) || defined(HAS_SETGROUPS)
24 #  ifndef NGROUPS
25 #    define NGROUPS 32
26 #  endif
27 #endif
28
29 /*
30  * Use the "DESTRUCTOR" scope cleanup to reinstate magic.
31  */
32
33 struct magic_state {
34     SV* mgs_sv;
35     U32 mgs_flags;
36 };
37 typedef struct magic_state MGS;
38
39 static void restore_magic _((void *p));
40
41 static void
42 save_magic(mgs, sv)
43 MGS* mgs;
44 SV* sv;
45 {
46     assert(SvMAGICAL(sv));
47
48     mgs->mgs_sv = sv;
49     mgs->mgs_flags = SvMAGICAL(sv) | SvREADONLY(sv);
50     SAVEDESTRUCTOR(restore_magic, mgs);
51
52     SvMAGICAL_off(sv);
53     SvREADONLY_off(sv);
54     SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
55 }
56
57 static void
58 restore_magic(p)
59 void* p;
60 {
61     MGS* mgs = (MGS*)p;
62     SV* sv = mgs->mgs_sv;
63
64     if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
65     {
66         if (mgs->mgs_flags)
67             SvFLAGS(sv) |= mgs->mgs_flags;
68         else
69             mg_magical(sv);
70         if (SvGMAGICAL(sv))
71             SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK);
72     }
73 }
74
75
76 void
77 mg_magical(sv)
78 SV* sv;
79 {
80     MAGIC* mg;
81     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
82         MGVTBL* vtbl = mg->mg_virtual;
83         if (vtbl) {
84             if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
85                 SvGMAGICAL_on(sv);
86             if (vtbl->svt_set)
87                 SvSMAGICAL_on(sv);
88             if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)) || vtbl->svt_clear)
89                 SvRMAGICAL_on(sv);
90         }
91     }
92 }
93
94 int
95 mg_get(sv)
96 SV* sv;
97 {
98     MGS mgs;
99     MAGIC* mg;
100     MAGIC** mgp;
101     int mgp_valid = 0;
102
103     ENTER;
104     save_magic(&mgs, sv);
105
106     mgp = &SvMAGIC(sv);
107     while ((mg = *mgp) != 0) {
108         MGVTBL* vtbl = mg->mg_virtual;
109         if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
110             (*vtbl->svt_get)(sv, mg);
111             /* Ignore this magic if it's been deleted */
112             if ((mg == (mgp_valid ? *mgp : SvMAGIC(sv))) &&
113                   (mg->mg_flags & MGf_GSKIP))
114                 mgs.mgs_flags = 0;
115         }
116         /* Advance to next magic (complicated by possible deletion) */
117         if (mg == (mgp_valid ? *mgp : SvMAGIC(sv))) {
118             mgp = &mg->mg_moremagic;
119             mgp_valid = 1;
120         }
121         else
122             mgp = &SvMAGIC(sv); /* Re-establish pointer after sv_upgrade */
123     }
124
125     LEAVE;
126     return 0;
127 }
128
129 int
130 mg_set(sv)
131 SV* sv;
132 {
133     MGS mgs;
134     MAGIC* mg;
135     MAGIC* nextmg;
136
137     ENTER;
138     save_magic(&mgs, sv);
139
140     for (mg = SvMAGIC(sv); mg; mg = nextmg) {
141         MGVTBL* vtbl = mg->mg_virtual;
142         nextmg = mg->mg_moremagic;      /* it may delete itself */
143         if (mg->mg_flags & MGf_GSKIP) {
144             mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
145             mgs.mgs_flags = 0;
146         }
147         if (vtbl && vtbl->svt_set)
148             (*vtbl->svt_set)(sv, mg);
149     }
150
151     LEAVE;
152     return 0;
153 }
154
155 U32
156 mg_len(sv)
157 SV* sv;
158 {
159     MAGIC* mg;
160     char *junk;
161     STRLEN len;
162
163     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
164         MGVTBL* vtbl = mg->mg_virtual;
165         if (vtbl && vtbl->svt_len) {
166             MGS mgs;
167
168             ENTER;
169             save_magic(&mgs, sv);
170             /* omit MGf_GSKIP -- not changed here */
171             len = (*vtbl->svt_len)(sv, mg);
172             LEAVE;
173             return len;
174         }
175     }
176
177     junk = SvPV(sv, len);
178     return len;
179 }
180
181 int
182 mg_clear(sv)
183 SV* sv;
184 {
185     MGS mgs;
186     MAGIC* mg;
187
188     ENTER;
189     save_magic(&mgs, sv);
190
191     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
192         MGVTBL* vtbl = mg->mg_virtual;
193         /* omit GSKIP -- never set here */
194         
195         if (vtbl && vtbl->svt_clear)
196             (*vtbl->svt_clear)(sv, mg);
197     }
198
199     LEAVE;
200     return 0;
201 }
202
203 MAGIC*
204 mg_find(sv, type)
205 SV* sv;
206 int type;
207 {
208     MAGIC* mg;
209     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
210         if (mg->mg_type == type)
211             return mg;
212     }
213     return 0;
214 }
215
216 int
217 mg_copy(sv, nsv, key, klen)
218 SV* sv;
219 SV* nsv;
220 char *key;
221 I32 klen;
222 {
223     int count = 0;
224     MAGIC* mg;
225     for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
226         if (isUPPER(mg->mg_type)) {
227             sv_magic(nsv, mg->mg_obj, toLOWER(mg->mg_type), key, klen);
228             count++;
229         }
230     }
231     return count;
232 }
233
234 int
235 mg_free(sv)
236 SV* sv;
237 {
238     MAGIC* mg;
239     MAGIC* moremagic;
240     for (mg = SvMAGIC(sv); mg; mg = moremagic) {
241         MGVTBL* vtbl = mg->mg_virtual;
242         moremagic = mg->mg_moremagic;
243         if (vtbl && vtbl->svt_free)
244             (*vtbl->svt_free)(sv, mg);
245         if (mg->mg_ptr && mg->mg_type != 'g')
246             if (mg->mg_len >= 0)
247                 Safefree(mg->mg_ptr);
248             else if (mg->mg_len == HEf_SVKEY)
249                 SvREFCNT_dec((SV*)mg->mg_ptr);
250         if (mg->mg_flags & MGf_REFCOUNTED)
251             SvREFCNT_dec(mg->mg_obj);
252         Safefree(mg);
253     }
254     SvMAGIC(sv) = 0;
255     return 0;
256 }
257
258 #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
259 #include <signal.h>
260 #endif
261
262 U32
263 magic_len(sv, mg)
264 SV *sv;
265 MAGIC *mg;
266 {
267     register I32 paren;
268     register char *s;
269     register I32 i;
270     register REGEXP *rx;
271     char *t;
272
273     switch (*mg->mg_ptr) {
274     case '1': case '2': case '3': case '4':
275     case '5': case '6': case '7': case '8': case '9': case '&':
276         if (curpm && (rx = curpm->op_pmregexp)) {
277             paren = atoi(mg->mg_ptr);
278           getparen:
279             if (paren <= rx->nparens &&
280                 (s = rx->startp[paren]) &&
281                 (t = rx->endp[paren]))
282             {
283                 i = t - s;
284                 if (i >= 0)
285                     return i;
286             }
287         }
288         return 0;
289     case '+':
290         if (curpm && (rx = curpm->op_pmregexp)) {
291             paren = rx->lastparen;
292             if (paren)
293                 goto getparen;
294         }
295         return 0;
296     case '`':
297         if (curpm && (rx = curpm->op_pmregexp)) {
298             if ((s = rx->subbeg) && rx->startp[0]) {
299                 i = rx->startp[0] - s;
300                 if (i >= 0)
301                     return i;
302             }
303         }
304         return 0;
305     case '\'':
306         if (curpm && (rx = curpm->op_pmregexp)) {
307             if (rx->subend && (s = rx->endp[0])) {
308                 i = rx->subend - s;
309                 if (i >= 0)
310                     return i;
311             }
312         }
313         return 0;
314     case ',':
315         return (STRLEN)ofslen;
316     case '\\':
317         return (STRLEN)orslen;
318     }
319     magic_get(sv,mg);
320     if (!SvPOK(sv) && SvNIOK(sv))
321         sv_2pv(sv, &na);
322     if (SvPOK(sv))
323         return SvCUR(sv);
324     return 0;
325 }
326
327 int
328 magic_get(sv, mg)
329 SV *sv;
330 MAGIC *mg;
331 {
332     register I32 paren;
333     register char *s;
334     register I32 i;
335     register REGEXP *rx;
336     char *t;
337
338     switch (*mg->mg_ptr) {
339     case '\001':                /* ^A */
340         sv_setsv(sv, bodytarget);
341         break;
342     case '\004':                /* ^D */
343         sv_setiv(sv, (IV)(debug & 32767));
344         break;
345     case '\005':  /* ^E */
346 #ifdef VMS
347         {
348 #           include <descrip.h>
349 #           include <starlet.h>
350             char msg[255];
351             $DESCRIPTOR(msgdsc,msg);
352             sv_setnv(sv,(double) vaxc$errno);
353             if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1)
354                 sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length);
355             else
356                 sv_setpv(sv,"");
357         }
358 #else
359 #ifdef OS2
360         sv_setnv(sv, (double)Perl_rc);
361         sv_setpv(sv, os2error(Perl_rc));
362 #else
363         sv_setnv(sv, (double)errno);
364         sv_setpv(sv, errno ? Strerror(errno) : "");
365 #endif
366 #endif
367         SvNOK_on(sv);   /* what a wonderful hack! */
368         break;
369     case '\006':                /* ^F */
370         sv_setiv(sv, (IV)maxsysfd);
371         break;
372     case '\010':                /* ^H */
373         sv_setiv(sv, (IV)hints);
374         break;
375     case '\t':                  /* ^I */
376         if (inplace)
377             sv_setpv(sv, inplace);
378         else
379             sv_setsv(sv, &sv_undef);
380         break;
381     case '\017':                /* ^O */
382         sv_setpv(sv, osname);
383         break;
384     case '\020':                /* ^P */
385         sv_setiv(sv, (IV)perldb);
386         break;
387     case '\024':                /* ^T */
388 #ifdef BIG_TIME
389         sv_setnv(sv, basetime);
390 #else
391         sv_setiv(sv, (IV)basetime);
392 #endif
393         break;
394     case '\027':                /* ^W */
395         sv_setiv(sv, (IV)dowarn);
396         break;
397     case '1': case '2': case '3': case '4':
398     case '5': case '6': case '7': case '8': case '9': case '&':
399         if (curpm && (rx = curpm->op_pmregexp)) {
400             paren = atoi(GvENAME((GV*)mg->mg_obj));
401           getparen:
402             if (paren <= rx->nparens &&
403                 (s = rx->startp[paren]) &&
404                 (t = rx->endp[paren]))
405             {
406                 i = t - s;
407               getrx:
408                 if (i >= 0) {
409                     bool was_tainted;
410                     if (tainting) {
411                         was_tainted = tainted;
412                         tainted = FALSE;
413                     }
414                     sv_setpvn(sv,s,i);
415                     if (tainting)
416                         tainted = was_tainted || rx->exec_tainted;
417                     break;
418                 }
419             }
420         }
421         sv_setsv(sv,&sv_undef);
422         break;
423     case '+':
424         if (curpm && (rx = curpm->op_pmregexp)) {
425             paren = rx->lastparen;
426             if (paren)
427                 goto getparen;
428         }
429         sv_setsv(sv,&sv_undef);
430         break;
431     case '`':
432         if (curpm && (rx = curpm->op_pmregexp)) {
433             if ((s = rx->subbeg) && rx->startp[0]) {
434                 i = rx->startp[0] - s;
435                 goto getrx;
436             }
437         }
438         sv_setsv(sv,&sv_undef);
439         break;
440     case '\'':
441         if (curpm && (rx = curpm->op_pmregexp)) {
442             if (rx->subend && (s = rx->endp[0])) {
443                 i = rx->subend - s;
444                 goto getrx;
445             }
446         }
447         sv_setsv(sv,&sv_undef);
448         break;
449     case '.':
450 #ifndef lint
451         if (GvIO(last_in_gv)) {
452             sv_setiv(sv, (IV)IoLINES(GvIO(last_in_gv)));
453         }
454 #endif
455         break;
456     case '?':
457         {
458             dTHR;
459             sv_setiv(sv, (IV)STATUS_CURRENT);
460 #ifdef COMPLEX_STATUS
461             LvTARGOFF(sv) = statusvalue;
462             LvTARGLEN(sv) = statusvalue_vms;
463 #endif
464         }
465         break;
466     case '^':
467         s = IoTOP_NAME(GvIOp(defoutgv));
468         if (s)
469             sv_setpv(sv,s);
470         else {
471             sv_setpv(sv,GvENAME(defoutgv));
472             sv_catpv(sv,"_TOP");
473         }
474         break;
475     case '~':
476         s = IoFMT_NAME(GvIOp(defoutgv));
477         if (!s)
478             s = GvENAME(defoutgv);
479         sv_setpv(sv,s);
480         break;
481 #ifndef lint
482     case '=':
483         sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(defoutgv)));
484         break;
485     case '-':
486         sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(defoutgv)));
487         break;
488     case '%':
489         sv_setiv(sv, (IV)IoPAGE(GvIOp(defoutgv)));
490         break;
491 #endif
492     case ':':
493         break;
494     case '/':
495         break;
496     case '[':
497         WITH_THR(sv_setiv(sv, (IV)curcop->cop_arybase));
498         break;
499     case '|':
500         sv_setiv(sv, (IV)(IoFLAGS(GvIOp(defoutgv)) & IOf_FLUSH) != 0 );
501         break;
502     case ',':
503         sv_setpvn(sv,ofs,ofslen);
504         break;
505     case '\\':
506         sv_setpvn(sv,ors,orslen);
507         break;
508     case '#':
509         sv_setpv(sv,ofmt);
510         break;
511     case '!':
512 #ifdef VMS
513         sv_setnv(sv, (double)((errno == EVMSERR) ? vaxc$errno : errno));
514         sv_setpv(sv, errno ? Strerror(errno) : "");
515 #else
516         {
517         int saveerrno = errno;
518         sv_setnv(sv, (double)errno);
519 #ifdef OS2
520         if (errno == errno_isOS2) sv_setpv(sv, os2error(Perl_rc));
521         else
522 #endif
523         sv_setpv(sv, errno ? Strerror(errno) : "");
524         errno = saveerrno;
525         }
526 #endif
527         SvNOK_on(sv);   /* what a wonderful hack! */
528         break;
529     case '<':
530         sv_setiv(sv, (IV)uid);
531         break;
532     case '>':
533         sv_setiv(sv, (IV)euid);
534         break;
535     case '(':
536         sv_setiv(sv, (IV)gid);
537         sv_setpvf(sv, "%Vd", (IV)gid);
538         goto add_groups;
539     case ')':
540         sv_setiv(sv, (IV)egid);
541         sv_setpvf(sv, "%Vd", (IV)egid);
542       add_groups:
543 #ifdef HAS_GETGROUPS
544         {
545             Groups_t gary[NGROUPS];
546             i = getgroups(NGROUPS,gary);
547             while (--i >= 0)
548                 sv_catpvf(sv, " %Vd", (IV)gary[i]);
549         }
550 #endif
551         SvIOK_on(sv);   /* what a wonderful hack! */
552         break;
553     case '*':
554         break;
555     case '0':
556         break;
557     }
558     return 0;
559 }
560
561 int
562 magic_getuvar(sv, mg)
563 SV *sv;
564 MAGIC *mg;
565 {
566     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
567
568     if (uf && uf->uf_val)
569         (*uf->uf_val)(uf->uf_index, sv);
570     return 0;
571 }
572
573 int
574 magic_setenv(sv,mg)
575 SV* sv;
576 MAGIC* mg;
577 {
578     register char *s;
579     char *ptr;
580     STRLEN len, klen;
581     I32 i;
582
583     s = SvPV(sv,len);
584     ptr = MgPV(mg,klen);
585     my_setenv(ptr, s);
586
587 #ifdef DYNAMIC_ENV_FETCH
588      /* We just undefd an environment var.  Is a replacement */
589      /* waiting in the wings? */
590     if (!len) {
591         SV **valp;
592         if ((valp = hv_fetch(GvHVn(envgv), ptr, klen, FALSE)))
593             s = SvPV(*valp, len);
594     }
595 #endif
596
597 #if !defined(OS2) && !defined(AMIGAOS) && !defined(WIN32)
598                             /* And you'll never guess what the dog had */
599                             /*   in its mouth... */
600     if (tainting) {
601         MgTAINTEDDIR_off(mg);
602 #ifdef VMS
603         if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) {
604             char pathbuf[256], eltbuf[256], *cp, *elt = s;
605             struct stat sbuf;
606             int i = 0, j = 0;
607
608             do {          /* DCL$PATH may be a search list */
609                 while (1) {   /* as may dev portion of any element */
610                     if ( ((cp = strchr(elt,'[')) || (cp = strchr(elt,'<'))) ) {
611                         if ( *(cp+1) == '.' || *(cp+1) == '-' ||
612                              cando_by_name(S_IWUSR,0,elt) ) {
613                             MgTAINTEDDIR_on(mg);
614                             return 0;
615                         }
616                     }
617                     if ((cp = strchr(elt, ':')) != Nullch)
618                         *cp = '\0';
619                     if (my_trnlnm(elt, eltbuf, j++))
620                         elt = eltbuf;
621                     else
622                         break;
623                 }
624                 j = 0;
625             } while (my_trnlnm(s, pathbuf, i++) && (elt = pathbuf));
626         }
627 #endif /* VMS */
628         if (s && klen == 4 && strEQ(ptr,"PATH")) {
629             char *strend = s + len;
630
631             while (s < strend) {
632                 char tmpbuf[256];
633                 struct stat st;
634                 s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
635                              s, strend, ':', &i);
636                 s++;
637                 if (i >= sizeof tmpbuf   /* too long -- assume the worst */
638                       || *tmpbuf != '/'
639                       || (Stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) {
640                     MgTAINTEDDIR_on(mg);
641                     return 0;
642                 }
643             }
644         }
645     }
646 #endif /* neither OS2 nor AMIGAOS nor WIN32 */
647
648     return 0;
649 }
650
651 int
652 magic_clearenv(sv,mg)
653 SV* sv;
654 MAGIC* mg;
655 {
656     my_setenv(MgPV(mg,na),Nullch);
657     return 0;
658 }
659
660 int
661 magic_clear_all_env(sv,mg)
662 SV* sv;
663 MAGIC* mg;
664 {
665 #if defined(VMS)
666     die("Can't make list assignment to %%ENV on this system");
667 #else
668 #ifdef WIN32
669     char *envv = GetEnvironmentStrings();
670     char *cur = envv;
671     STRLEN len;
672     while (*cur) {
673         char *end = strchr(cur,'=');
674         if (end && end != cur) {
675             *end = '\0';
676             my_setenv(cur,Nullch);
677             *end = '=';
678             cur += strlen(end+1)+1;
679         }
680         else if ((len = strlen(cur)))
681             cur += len+1;
682     }
683     FreeEnvironmentStrings(envv);
684 #else
685     I32 i;
686
687     if (environ == origenviron)
688         New(901, environ, 1, char*);
689     else
690         for (i = 0; environ[i]; i++)
691             Safefree(environ[i]);
692     environ[0] = Nullch;
693
694 #endif
695 #endif
696     return 0;
697 }
698
699 int
700 magic_getsig(sv,mg)
701 SV* sv;
702 MAGIC* mg;
703 {
704     I32 i;
705     /* Are we fetching a signal entry? */
706     i = whichsig(MgPV(mg,na));
707     if (i) {
708         if(psig_ptr[i])
709             sv_setsv(sv,psig_ptr[i]);
710         else {
711             dTHR;               /* just for SvREFCNT_inc */
712             Sighandler_t sigstate = rsignal_state(i);
713
714             /* cache state so we don't fetch it again */
715             if(sigstate == SIG_IGN)
716                 sv_setpv(sv,"IGNORE");
717             else
718                 sv_setsv(sv,&sv_undef);
719             psig_ptr[i] = SvREFCNT_inc(sv);
720             SvTEMP_off(sv);
721         }
722     }
723     return 0;
724 }
725 int
726 magic_clearsig(sv,mg)
727 SV* sv;
728 MAGIC* mg;
729 {
730     I32 i;
731     /* Are we clearing a signal entry? */
732     i = whichsig(MgPV(mg,na));
733     if (i) {
734         if(psig_ptr[i]) {
735             SvREFCNT_dec(psig_ptr[i]);
736             psig_ptr[i]=0;
737         }
738         if(psig_name[i]) {
739             SvREFCNT_dec(psig_name[i]);
740             psig_name[i]=0;
741         }
742     }
743     return 0;
744 }
745
746 int
747 magic_setsig(sv,mg)
748 SV* sv;
749 MAGIC* mg;
750 {
751     dTHR;
752     register char *s;
753     I32 i;
754     SV** svp;
755
756     s = MgPV(mg,na);
757     if (*s == '_') {
758         if (strEQ(s,"__DIE__"))
759             svp = &diehook;
760         else if (strEQ(s,"__WARN__"))
761             svp = &warnhook;
762         else if (strEQ(s,"__PARSE__"))
763             svp = &parsehook;
764         else
765             croak("No such hook: %s", s);
766         i = 0;
767         if (*svp) {
768             SvREFCNT_dec(*svp);
769             *svp = 0;
770         }
771     }
772     else {
773         i = whichsig(s);        /* ...no, a brick */
774         if (!i) {
775             if (dowarn || strEQ(s,"ALARM"))
776                 warn("No such signal: SIG%s", s);
777             return 0;
778         }
779         SvREFCNT_dec(psig_name[i]);
780         SvREFCNT_dec(psig_ptr[i]);
781         psig_ptr[i] = SvREFCNT_inc(sv);
782         SvTEMP_off(sv); /* Make sure it doesn't go away on us */
783         psig_name[i] = newSVpv(s, strlen(s));
784         SvREADONLY_on(psig_name[i]);
785     }
786     if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
787         if (i)
788             (void)rsignal(i, sighandlerp);
789         else
790             *svp = SvREFCNT_inc(sv);
791         return 0;
792     }
793     s = SvPV_force(sv,na);
794     if (strEQ(s,"IGNORE")) {
795         if (i)
796             (void)rsignal(i, SIG_IGN);
797         else
798             *svp = 0;
799     }
800     else if (strEQ(s,"DEFAULT") || !*s) {
801         if (i)
802             (void)rsignal(i, SIG_DFL);
803         else
804             *svp = 0;
805     }
806     else {
807         /*
808          * We should warn if HINT_STRICT_REFS, but without
809          * access to a known hint bit in a known OP, we can't
810          * tell whether HINT_STRICT_REFS is in force or not.
811          */
812         if (!strchr(s,':') && !strchr(s,'\''))
813             sv_setpv(sv, form("main::%s", s));
814         if (i)
815             (void)rsignal(i, sighandlerp);
816         else
817             *svp = SvREFCNT_inc(sv);
818     }
819     return 0;
820 }
821
822 int
823 magic_setisa(sv,mg)
824 SV* sv;
825 MAGIC* mg;
826 {
827     sub_generation++;
828     return 0;
829 }
830
831 #ifdef OVERLOAD
832
833 int
834 magic_setamagic(sv,mg)
835 SV* sv;
836 MAGIC* mg;
837 {
838     /* HV_badAMAGIC_on(Sv_STASH(sv)); */
839     amagic_generation++;
840
841     return 0;
842 }
843 #endif /* OVERLOAD */
844
845 int
846 magic_setnkeys(sv,mg)
847 SV* sv;
848 MAGIC* mg;
849 {
850     if (LvTARG(sv)) {
851         hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
852         LvTARG(sv) = Nullsv;    /* Don't allow a ref to reassign this. */
853     }
854     return 0;
855 }
856
857 static int
858 magic_methpack(sv,mg,meth)
859 SV* sv;
860 MAGIC* mg;
861 char *meth;
862 {
863     dTHR;
864     dSP;
865
866     ENTER;
867     SAVETMPS;
868     PUSHMARK(sp);
869     EXTEND(sp, 2);
870     PUSHs(mg->mg_obj);
871     if (mg->mg_ptr) {
872         if (mg->mg_len >= 0)
873             PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
874         else if (mg->mg_len == HEf_SVKEY)
875             PUSHs((SV*)mg->mg_ptr);
876     }
877     else if (mg->mg_type == 'p')
878         PUSHs(sv_2mortal(newSViv(mg->mg_len)));
879     PUTBACK;
880
881     if (perl_call_method(meth, G_SCALAR))
882         sv_setsv(sv, *stack_sp--);
883
884     FREETMPS;
885     LEAVE;
886     return 0;
887 }
888
889 int
890 magic_getpack(sv,mg)
891 SV* sv;
892 MAGIC* mg;
893 {
894     magic_methpack(sv,mg,"FETCH");
895     if (mg->mg_ptr)
896         mg->mg_flags |= MGf_GSKIP;
897     return 0;
898 }
899
900 int
901 magic_setpack(sv,mg)
902 SV* sv;
903 MAGIC* mg;
904 {
905     dTHR;
906     dSP;
907
908     PUSHMARK(sp);
909     EXTEND(sp, 3);
910     PUSHs(mg->mg_obj);
911     if (mg->mg_ptr) {
912         if (mg->mg_len >= 0)
913             PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
914         else if (mg->mg_len == HEf_SVKEY)
915             PUSHs((SV*)mg->mg_ptr);
916     }
917     else if (mg->mg_type == 'p')
918         PUSHs(sv_2mortal(newSViv(mg->mg_len)));
919     PUSHs(sv);
920     PUTBACK;
921
922     perl_call_method("STORE", G_SCALAR|G_DISCARD);
923
924     return 0;
925 }
926
927 int
928 magic_clearpack(sv,mg)
929 SV* sv;
930 MAGIC* mg;
931 {
932     return magic_methpack(sv,mg,"DELETE");
933 }
934
935 int magic_wipepack(sv,mg)
936 SV* sv;
937 MAGIC* mg;
938 {
939     dTHR;
940     dSP;
941
942     PUSHMARK(sp);
943     XPUSHs(mg->mg_obj);
944     PUTBACK;
945
946     perl_call_method("CLEAR", G_SCALAR|G_DISCARD);
947
948     return 0;
949 }
950
951 int
952 magic_nextpack(sv,mg,key)
953 SV* sv;
954 MAGIC* mg;
955 SV* key;
956 {
957     dTHR;
958     dSP;
959     char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
960
961     ENTER;
962     SAVETMPS;
963     PUSHMARK(sp);
964     EXTEND(sp, 2);
965     PUSHs(mg->mg_obj);
966     if (SvOK(key))
967         PUSHs(key);
968     PUTBACK;
969
970     if (perl_call_method(meth, G_SCALAR))
971         sv_setsv(key, *stack_sp--);
972
973     FREETMPS;
974     LEAVE;
975     return 0;
976 }
977
978 int
979 magic_existspack(sv,mg)
980 SV* sv;
981 MAGIC* mg;
982 {
983     return magic_methpack(sv,mg,"EXISTS");
984
985
986 int
987 magic_setdbline(sv,mg)
988 SV* sv;
989 MAGIC* mg;
990 {
991     dTHR;
992     OP *o;
993     I32 i;
994     GV* gv;
995     SV** svp;
996
997     gv = DBline;
998     i = SvTRUE(sv);
999     svp = av_fetch(GvAV(gv),
1000                      atoi(MgPV(mg,na)), FALSE);
1001     if (svp && SvIOKp(*svp) && (o = (OP*)SvSTASH(*svp)))
1002         o->op_private = i;
1003     else
1004         warn("Can't break at that line\n");
1005     return 0;
1006 }
1007
1008 int
1009 magic_getarylen(sv,mg)
1010 SV* sv;
1011 MAGIC* mg;
1012 {
1013     dTHR;
1014     sv_setiv(sv, AvFILL((AV*)mg->mg_obj) + curcop->cop_arybase);
1015     return 0;
1016 }
1017
1018 int
1019 magic_setarylen(sv,mg)
1020 SV* sv;
1021 MAGIC* mg;
1022 {
1023     dTHR;
1024     av_fill((AV*)mg->mg_obj, SvIV(sv) - curcop->cop_arybase);
1025     return 0;
1026 }
1027
1028 int
1029 magic_getpos(sv,mg)
1030 SV* sv;
1031 MAGIC* mg;
1032 {
1033     SV* lsv = LvTARG(sv);
1034     
1035     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) {
1036         mg = mg_find(lsv, 'g');
1037         if (mg && mg->mg_len >= 0) {
1038             dTHR;
1039             sv_setiv(sv, mg->mg_len + curcop->cop_arybase);
1040             return 0;
1041         }
1042     }
1043     (void)SvOK_off(sv);
1044     return 0;
1045 }
1046
1047 int
1048 magic_setpos(sv,mg)
1049 SV* sv;
1050 MAGIC* mg;
1051 {
1052     SV* lsv = LvTARG(sv);
1053     SSize_t pos;
1054     STRLEN len;
1055
1056     mg = 0;
1057     
1058     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv))
1059         mg = mg_find(lsv, 'g');
1060     if (!mg) {
1061         if (!SvOK(sv))
1062             return 0;
1063         sv_magic(lsv, (SV*)0, 'g', Nullch, 0);
1064         mg = mg_find(lsv, 'g');
1065     }
1066     else if (!SvOK(sv)) {
1067         mg->mg_len = -1;
1068         return 0;
1069     }
1070     len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv);
1071
1072     WITH_THR(pos = SvIV(sv) - curcop->cop_arybase);
1073     if (pos < 0) {
1074         pos += len;
1075         if (pos < 0)
1076             pos = 0;
1077     }
1078     else if (pos > len)
1079         pos = len;
1080     mg->mg_len = pos;
1081     mg->mg_flags &= ~MGf_MINMATCH;
1082
1083     return 0;
1084 }
1085
1086 int
1087 magic_getglob(sv,mg)
1088 SV* sv;
1089 MAGIC* mg;
1090 {
1091     if (SvFAKE(sv)) {                   /* FAKE globs can get coerced */
1092         SvFAKE_off(sv);
1093         gv_efullname3(sv,((GV*)sv), "*");
1094         SvFAKE_on(sv);
1095     }
1096     else
1097         gv_efullname3(sv,((GV*)sv), "*");       /* a gv value, be nice */
1098     return 0;
1099 }
1100
1101 int
1102 magic_setglob(sv,mg)
1103 SV* sv;
1104 MAGIC* mg;
1105 {
1106     register char *s;
1107     GV* gv;
1108
1109     if (!SvOK(sv))
1110         return 0;
1111     s = SvPV(sv, na);
1112     if (*s == '*' && s[1])
1113         s++;
1114     gv = gv_fetchpv(s,TRUE, SVt_PVGV);
1115     if (sv == (SV*)gv)
1116         return 0;
1117     if (GvGP(sv))
1118         gp_free((GV*)sv);
1119     GvGP(sv) = gp_ref(GvGP(gv));
1120     return 0;
1121 }
1122
1123 int
1124 magic_setsubstr(sv,mg)
1125 SV* sv;
1126 MAGIC* mg;
1127 {
1128     STRLEN len;
1129     char *tmps = SvPV(sv,len);
1130     sv_insert(LvTARG(sv),LvTARGOFF(sv),LvTARGLEN(sv), tmps, len);
1131     return 0;
1132 }
1133
1134 int
1135 magic_gettaint(sv,mg)
1136 SV* sv;
1137 MAGIC* mg;
1138 {
1139     TAINT_IF((mg->mg_len & 1) ||
1140              (mg->mg_len & 2) && mg->mg_obj == sv);     /* kludge */
1141     return 0;
1142 }
1143
1144 int
1145 magic_settaint(sv,mg)
1146 SV* sv;
1147 MAGIC* mg;
1148 {
1149     dTHR;
1150     if (localizing) {
1151         if (localizing == 1)
1152             mg->mg_len <<= 1;
1153         else
1154             mg->mg_len >>= 1;
1155     }
1156     else if (tainted)
1157         mg->mg_len |= 1;
1158     else
1159         mg->mg_len &= ~1;
1160     return 0;
1161 }
1162
1163 int
1164 magic_setvec(sv,mg)
1165 SV* sv;
1166 MAGIC* mg;
1167 {
1168     do_vecset(sv);      /* XXX slurp this routine */
1169     return 0;
1170 }
1171
1172 int
1173 magic_getdefelem(sv,mg)
1174 SV* sv;
1175 MAGIC* mg;
1176 {
1177     SV *targ = Nullsv;
1178     if (LvTARGLEN(sv)) {
1179         if (mg->mg_obj) {
1180             HV* hv = (HV*)LvTARG(sv);
1181             HE* he = hv_fetch_ent(hv, mg->mg_obj, FALSE, 0);
1182             if (he)
1183                 targ = HeVAL(he);
1184         }
1185         else {
1186             AV* av = (AV*)LvTARG(sv);
1187             if ((I32)LvTARGOFF(sv) <= AvFILL(av))
1188                 targ = AvARRAY(av)[LvTARGOFF(sv)];
1189         }
1190         if (targ && targ != &sv_undef) {
1191             dTHR;               /* just for SvREFCNT_dec */
1192             /* somebody else defined it for us */
1193             SvREFCNT_dec(LvTARG(sv));
1194             LvTARG(sv) = SvREFCNT_inc(targ);
1195             LvTARGLEN(sv) = 0;
1196             SvREFCNT_dec(mg->mg_obj);
1197             mg->mg_obj = Nullsv;
1198             mg->mg_flags &= ~MGf_REFCOUNTED;
1199         }
1200     }
1201     else
1202         targ = LvTARG(sv);
1203     sv_setsv(sv, targ ? targ : &sv_undef);
1204     return 0;
1205 }
1206
1207 int
1208 magic_setdefelem(sv,mg)
1209 SV* sv;
1210 MAGIC* mg;
1211 {
1212     if (LvTARGLEN(sv))
1213         vivify_defelem(sv);
1214     if (LvTARG(sv)) {
1215         sv_setsv(LvTARG(sv), sv);
1216         SvSETMAGIC(LvTARG(sv));
1217     }
1218     return 0;
1219 }
1220
1221 int
1222 magic_freedefelem(sv,mg)
1223 SV* sv;
1224 MAGIC* mg;
1225 {
1226     SvREFCNT_dec(LvTARG(sv));
1227     return 0;
1228 }
1229
1230 void
1231 vivify_defelem(sv)
1232 SV* sv;
1233 {
1234     dTHR;                       /* just for SvREFCNT_inc and SvREFCNT_dec*/
1235     MAGIC* mg;
1236     SV* value;
1237
1238     if (!LvTARGLEN(sv) || !(mg = mg_find(sv, 'y')))
1239         return;
1240     if (mg->mg_obj) {
1241         HV* hv = (HV*)LvTARG(sv);
1242         HE* he = hv_fetch_ent(hv, mg->mg_obj, TRUE, 0);
1243         if (!he || (value = HeVAL(he)) == &sv_undef)
1244             croak(no_helem, SvPV(mg->mg_obj, na));
1245     }
1246     else {
1247         AV* av = (AV*)LvTARG(sv);
1248         if ((I32)LvTARGLEN(sv) < 0 && (I32)LvTARGOFF(sv) > AvFILL(av))
1249             LvTARG(sv) = Nullsv;        /* array can't be extended */
1250         else {
1251             SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE);
1252             if (!svp || (value = *svp) == &sv_undef)
1253                 croak(no_aelem, (I32)LvTARGOFF(sv));
1254         }
1255     }
1256     (void)SvREFCNT_inc(value);
1257     SvREFCNT_dec(LvTARG(sv));
1258     LvTARG(sv) = value;
1259     LvTARGLEN(sv) = 0;
1260     SvREFCNT_dec(mg->mg_obj);
1261     mg->mg_obj = Nullsv;
1262     mg->mg_flags &= ~MGf_REFCOUNTED;
1263 }
1264
1265 int
1266 magic_setmglob(sv,mg)
1267 SV* sv;
1268 MAGIC* mg;
1269 {
1270     mg->mg_len = -1;
1271     SvSCREAM_off(sv);
1272     return 0;
1273 }
1274
1275 int
1276 magic_setbm(sv,mg)
1277 SV* sv;
1278 MAGIC* mg;
1279 {
1280     sv_unmagic(sv, 'B');
1281     SvVALID_off(sv);
1282     return 0;
1283 }
1284
1285 int
1286 magic_setfm(sv,mg)
1287 SV* sv;
1288 MAGIC* mg;
1289 {
1290     sv_unmagic(sv, 'f');
1291     SvCOMPILED_off(sv);
1292     return 0;
1293 }
1294
1295 int
1296 magic_setuvar(sv,mg)
1297 SV* sv;
1298 MAGIC* mg;
1299 {
1300     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
1301
1302     if (uf && uf->uf_set)
1303         (*uf->uf_set)(uf->uf_index, sv);
1304     return 0;
1305 }
1306
1307 #ifdef USE_LOCALE_COLLATE
1308 int
1309 magic_setcollxfrm(sv,mg)
1310 SV* sv;
1311 MAGIC* mg;
1312 {
1313     /*
1314      * RenĂ© Descartes said "I think not."
1315      * and vanished with a faint plop.
1316      */
1317     if (mg->mg_ptr) {
1318         Safefree(mg->mg_ptr);
1319         mg->mg_ptr = NULL;
1320         mg->mg_len = -1;
1321     }
1322     return 0;
1323 }
1324 #endif /* USE_LOCALE_COLLATE */
1325
1326 int
1327 magic_set(sv,mg)
1328 SV* sv;
1329 MAGIC* mg;
1330 {
1331     dTHR;
1332     register char *s;
1333     I32 i;
1334     STRLEN len;
1335     switch (*mg->mg_ptr) {
1336     case '\001':        /* ^A */
1337         sv_setsv(bodytarget, sv);
1338         break;
1339     case '\004':        /* ^D */
1340         debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
1341         DEBUG_x(dump_all());
1342         break;
1343     case '\005':  /* ^E */
1344 #ifdef VMS
1345         set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1346 #else
1347         /* will anyone ever use this? */
1348         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
1349 #endif
1350         break;
1351     case '\006':        /* ^F */
1352         maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1353         break;
1354     case '\010':        /* ^H */
1355         hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1356         break;
1357     case '\t':  /* ^I */
1358         if (inplace)
1359             Safefree(inplace);
1360         if (SvOK(sv))
1361             inplace = savepv(SvPV(sv,na));
1362         else
1363             inplace = Nullch;
1364         break;
1365     case '\017':        /* ^O */
1366         if (osname)
1367             Safefree(osname);
1368         if (SvOK(sv))
1369             osname = savepv(SvPV(sv,na));
1370         else
1371             osname = Nullch;
1372         break;
1373     case '\020':        /* ^P */
1374         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1375         if (i != perldb) {
1376             if (perldb)
1377                 oldlastpm = curpm;
1378             else
1379                 curpm = oldlastpm;
1380         }
1381         perldb = i;
1382         break;
1383     case '\024':        /* ^T */
1384 #ifdef BIG_TIME
1385         basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
1386 #else
1387         basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1388 #endif
1389         break;
1390     case '\027':        /* ^W */
1391         dowarn = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1392         break;
1393     case '.':
1394         if (localizing) {
1395             if (localizing == 1)
1396                 save_sptr((SV**)&last_in_gv);
1397         }
1398         else if (SvOK(sv) && GvIO(last_in_gv))
1399             IoLINES(GvIOp(last_in_gv)) = (long)SvIV(sv);
1400         break;
1401     case '^':
1402         Safefree(IoTOP_NAME(GvIOp(defoutgv)));
1403         IoTOP_NAME(GvIOp(defoutgv)) = s = savepv(SvPV(sv,na));
1404         IoTOP_GV(GvIOp(defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1405         break;
1406     case '~':
1407         Safefree(IoFMT_NAME(GvIOp(defoutgv)));
1408         IoFMT_NAME(GvIOp(defoutgv)) = s = savepv(SvPV(sv,na));
1409         IoFMT_GV(GvIOp(defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1410         break;
1411     case '=':
1412         IoPAGE_LEN(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1413         break;
1414     case '-':
1415         IoLINES_LEFT(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1416         if (IoLINES_LEFT(GvIOp(defoutgv)) < 0L)
1417             IoLINES_LEFT(GvIOp(defoutgv)) = 0L;
1418         break;
1419     case '%':
1420         IoPAGE(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1421         break;
1422     case '|':
1423         {
1424             IO *io = GvIOp(defoutgv);
1425             if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0)
1426                 IoFLAGS(io) &= ~IOf_FLUSH;
1427             else {
1428                 if (!(IoFLAGS(io) & IOf_FLUSH)) {
1429                     PerlIO *ofp = IoOFP(io);
1430                     if (ofp)
1431                         (void)PerlIO_flush(ofp);
1432                     IoFLAGS(io) |= IOf_FLUSH;
1433                 }
1434             }
1435         }
1436         break;
1437     case '*':
1438         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1439         multiline = (i != 0);
1440         break;
1441     case '/':
1442         SvREFCNT_dec(nrs);
1443         nrs = newSVsv(sv);
1444         SvREFCNT_dec(rs);
1445         rs = SvREFCNT_inc(nrs);
1446         break;
1447     case '\\':
1448         if (ors)
1449             Safefree(ors);
1450         if (SvOK(sv) || SvGMAGICAL(sv))
1451             ors = savepv(SvPV(sv,orslen));
1452         else {
1453             ors = Nullch;
1454             orslen = 0;
1455         }
1456         break;
1457     case ',':
1458         if (ofs)
1459             Safefree(ofs);
1460         ofs = savepv(SvPV(sv, ofslen));
1461         break;
1462     case '#':
1463         if (ofmt)
1464             Safefree(ofmt);
1465         ofmt = savepv(SvPV(sv,na));
1466         break;
1467     case '[':
1468         compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1469         break;
1470     case '?':
1471 #ifdef COMPLEX_STATUS
1472         if (localizing == 2) {
1473             statusvalue = LvTARGOFF(sv);
1474             statusvalue_vms = LvTARGLEN(sv);
1475         }
1476         else
1477 #endif
1478 #ifdef VMSISH_STATUS
1479         if (VMSISH_STATUS)
1480             STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)));
1481         else
1482 #endif
1483             STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1484         break;
1485     case '!':
1486         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv),
1487                  (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
1488         break;
1489     case '<':
1490         uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1491         if (delaymagic) {
1492             delaymagic |= DM_RUID;
1493             break;                              /* don't do magic till later */
1494         }
1495 #ifdef HAS_SETRUID
1496         (void)setruid((Uid_t)uid);
1497 #else
1498 #ifdef HAS_SETREUID
1499         (void)setreuid((Uid_t)uid, (Uid_t)-1);
1500 #else
1501 #ifdef HAS_SETRESUID
1502       (void)setresuid((Uid_t)uid, (Uid_t)-1, (Uid_t)-1);
1503 #else
1504         if (uid == euid)                /* special case $< = $> */
1505             (void)setuid(uid);
1506         else {
1507             uid = (I32)getuid();
1508             croak("setruid() not implemented");
1509         }
1510 #endif
1511 #endif
1512 #endif
1513         uid = (I32)getuid();
1514         tainting |= (uid && (euid != uid || egid != gid));
1515         break;
1516     case '>':
1517         euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1518         if (delaymagic) {
1519             delaymagic |= DM_EUID;
1520             break;                              /* don't do magic till later */
1521         }
1522 #ifdef HAS_SETEUID
1523         (void)seteuid((Uid_t)euid);
1524 #else
1525 #ifdef HAS_SETREUID
1526         (void)setreuid((Uid_t)-1, (Uid_t)euid);
1527 #else
1528 #ifdef HAS_SETRESUID
1529         (void)setresuid((Uid_t)-1, (Uid_t)euid, (Uid_t)-1);
1530 #else
1531         if (euid == uid)                /* special case $> = $< */
1532             setuid(euid);
1533         else {
1534             euid = (I32)geteuid();
1535             croak("seteuid() not implemented");
1536         }
1537 #endif
1538 #endif
1539 #endif
1540         euid = (I32)geteuid();
1541         tainting |= (uid && (euid != uid || egid != gid));
1542         break;
1543     case '(':
1544         gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1545         if (delaymagic) {
1546             delaymagic |= DM_RGID;
1547             break;                              /* don't do magic till later */
1548         }
1549 #ifdef HAS_SETRGID
1550         (void)setrgid((Gid_t)gid);
1551 #else
1552 #ifdef HAS_SETREGID
1553         (void)setregid((Gid_t)gid, (Gid_t)-1);
1554 #else
1555 #ifdef HAS_SETRESGID
1556       (void)setresgid((Gid_t)gid, (Gid_t)-1, (Gid_t) 1);
1557 #else
1558         if (gid == egid)                        /* special case $( = $) */
1559             (void)setgid(gid);
1560         else {
1561             gid = (I32)getgid();
1562             croak("setrgid() not implemented");
1563         }
1564 #endif
1565 #endif
1566 #endif
1567         gid = (I32)getgid();
1568         tainting |= (uid && (euid != uid || egid != gid));
1569         break;
1570     case ')':
1571 #ifdef HAS_SETGROUPS
1572         {
1573             char *p = SvPV(sv, na);
1574             Groups_t gary[NGROUPS];
1575
1576             SET_NUMERIC_STANDARD();
1577             while (isSPACE(*p))
1578                 ++p;
1579             egid = I_V(atof(p));
1580             for (i = 0; i < NGROUPS; ++i) {
1581                 while (*p && !isSPACE(*p))
1582                     ++p;
1583                 while (isSPACE(*p))
1584                     ++p;
1585                 if (!*p)
1586                     break;
1587                 gary[i] = I_V(atof(p));
1588             }
1589             if (i)
1590                 (void)setgroups(i, gary);
1591         }
1592 #else  /* HAS_SETGROUPS */
1593         egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1594 #endif /* HAS_SETGROUPS */
1595         if (delaymagic) {
1596             delaymagic |= DM_EGID;
1597             break;                              /* don't do magic till later */
1598         }
1599 #ifdef HAS_SETEGID
1600         (void)setegid((Gid_t)egid);
1601 #else
1602 #ifdef HAS_SETREGID
1603         (void)setregid((Gid_t)-1, (Gid_t)egid);
1604 #else
1605 #ifdef HAS_SETRESGID
1606         (void)setresgid((Gid_t)-1, (Gid_t)egid, (Gid_t)-1);
1607 #else
1608         if (egid == gid)                        /* special case $) = $( */
1609             (void)setgid(egid);
1610         else {
1611             egid = (I32)getegid();
1612             croak("setegid() not implemented");
1613         }
1614 #endif
1615 #endif
1616 #endif
1617         egid = (I32)getegid();
1618         tainting |= (uid && (euid != uid || egid != gid));
1619         break;
1620     case ':':
1621         chopset = SvPV_force(sv,na);
1622         break;
1623     case '0':
1624         if (!origalen) {
1625             s = origargv[0];
1626             s += strlen(s);
1627             /* See if all the arguments are contiguous in memory */
1628             for (i = 1; i < origargc; i++) {
1629                 if (origargv[i] == s + 1)
1630                     s += strlen(++s);   /* this one is ok too */
1631             }
1632             /* can grab env area too? */
1633             if (origenviron && origenviron[0] == s + 1) {
1634                 my_setenv("NoNe  SuCh", Nullch);
1635                                             /* force copy of environment */
1636                 for (i = 0; origenviron[i]; i++)
1637                     if (origenviron[i] == s + 1)
1638                         s += strlen(++s);
1639             }
1640             origalen = s - origargv[0];
1641         }
1642         s = SvPV_force(sv,len);
1643         i = len;
1644         if (i >= origalen) {
1645             i = origalen;
1646             SvCUR_set(sv, i);
1647             *SvEND(sv) = '\0';
1648             Copy(s, origargv[0], i, char);
1649         }
1650         else {
1651             Copy(s, origargv[0], i, char);
1652             s = origargv[0]+i;
1653             *s++ = '\0';
1654             while (++i < origalen)
1655                 *s++ = ' ';
1656             s = origargv[0]+i;
1657             for (i = 1; i < origargc; i++)
1658                 origargv[i] = Nullch;
1659         }
1660         break;
1661     }
1662     return 0;
1663 }
1664
1665 #ifdef USE_THREADS
1666 int
1667 magic_mutexfree(sv, mg)
1668 SV *sv;
1669 MAGIC *mg;
1670 {
1671     dTHR;
1672     DEBUG_L(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
1673                           (unsigned long)thr, (unsigned long)sv);)
1674     if (MgOWNER(mg))
1675         croak("panic: magic_mutexfree");
1676     MUTEX_DESTROY(MgMUTEXP(mg));
1677     COND_DESTROY(MgCONDP(mg));
1678     return 0;
1679 }
1680 #endif /* USE_THREADS */
1681
1682 I32
1683 whichsig(sig)
1684 char *sig;
1685 {
1686     register char **sigv;
1687
1688     for (sigv = sig_name+1; *sigv; sigv++)
1689         if (strEQ(sig,*sigv))
1690             return sig_num[sigv - sig_name];
1691 #ifdef SIGCLD
1692     if (strEQ(sig,"CHLD"))
1693         return SIGCLD;
1694 #endif
1695 #ifdef SIGCHLD
1696     if (strEQ(sig,"CLD"))
1697         return SIGCHLD;
1698 #endif
1699     return 0;
1700 }
1701
1702 Signal_t
1703 sighandler(sig)
1704 int sig;
1705 {
1706     dTHR;
1707     dSP;
1708     GV *gv;
1709     HV *st;
1710     SV *sv;
1711     CV *cv;
1712     AV *oldstack;
1713
1714     if (!psig_ptr[sig])
1715         die("Signal SIG%s received, but no signal handler set.\n",
1716             sig_name[sig]);
1717
1718     cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE);
1719     if (!cv || !CvROOT(cv)) {
1720         if (dowarn)
1721             warn("SIG%s handler \"%s\" not defined.\n",
1722                 sig_name[sig], GvENAME(gv) );
1723         return;
1724     }
1725
1726     oldstack = curstack;
1727     if (curstack != signalstack)
1728         AvFILL(signalstack) = 0;
1729     SWITCHSTACK(curstack, signalstack);
1730
1731     if(psig_name[sig])
1732         sv = SvREFCNT_inc(psig_name[sig]);
1733     else {
1734         sv = sv_newmortal();
1735         sv_setpv(sv,sig_name[sig]);
1736     }
1737     PUSHMARK(sp);
1738     PUSHs(sv);
1739     PUTBACK;
1740
1741     perl_call_sv((SV*)cv, G_DISCARD);
1742
1743     SWITCHSTACK(signalstack, oldstack);
1744
1745     return;
1746 }