This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Merge maint-5.004 branch (5.004_04) with mainline.
[perl5.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         if (!(_emx_env & 0x200)) {      /* Under DOS */
361             sv_setnv(sv, (double)errno);
362             sv_setpv(sv, errno ? Strerror(errno) : "");
363         } else {
364             if (errno != errno_isOS2)
365                 Perl_rc = _syserrno();
366             sv_setnv(sv, (double)Perl_rc);
367             sv_setpv(sv, os2error(Perl_rc));
368         }
369 #else
370         sv_setnv(sv, (double)errno);
371         sv_setpv(sv, errno ? Strerror(errno) : "");
372 #endif
373 #endif
374         SvNOK_on(sv);   /* what a wonderful hack! */
375         break;
376     case '\006':                /* ^F */
377         sv_setiv(sv, (IV)maxsysfd);
378         break;
379     case '\010':                /* ^H */
380         sv_setiv(sv, (IV)hints);
381         break;
382     case '\t':                  /* ^I */
383         if (inplace)
384             sv_setpv(sv, inplace);
385         else
386             sv_setsv(sv, &sv_undef);
387         break;
388     case '\017':                /* ^O */
389         sv_setpv(sv, osname);
390         break;
391     case '\020':                /* ^P */
392         sv_setiv(sv, (IV)perldb);
393         break;
394     case '\023':                /* ^S */
395         {
396             dTHR;
397             if (lex_state != LEX_NOTPARSING)
398                 SvOK_off(sv);
399             else if (in_eval)
400                 sv_setiv(sv, 1);
401             else
402                 sv_setiv(sv, 0);
403         }
404         break;
405     case '\024':                /* ^T */
406 #ifdef BIG_TIME
407         sv_setnv(sv, basetime);
408 #else
409         sv_setiv(sv, (IV)basetime);
410 #endif
411         break;
412     case '\027':                /* ^W */
413         sv_setiv(sv, (IV)dowarn);
414         break;
415     case '1': case '2': case '3': case '4':
416     case '5': case '6': case '7': case '8': case '9': case '&':
417         if (curpm && (rx = curpm->op_pmregexp)) {
418             paren = atoi(GvENAME((GV*)mg->mg_obj));
419           getparen:
420             if (paren <= rx->nparens &&
421                 (s = rx->startp[paren]) &&
422                 (t = rx->endp[paren]))
423             {
424                 i = t - s;
425               getrx:
426                 if (i >= 0) {
427                     bool was_tainted;
428                     if (tainting) {
429                         was_tainted = tainted;
430                         tainted = FALSE;
431                     }
432                     sv_setpvn(sv,s,i);
433                     if (tainting)
434                         tainted = was_tainted || rx->exec_tainted;
435                     break;
436                 }
437             }
438         }
439         sv_setsv(sv,&sv_undef);
440         break;
441     case '+':
442         if (curpm && (rx = curpm->op_pmregexp)) {
443             paren = rx->lastparen;
444             if (paren)
445                 goto getparen;
446         }
447         sv_setsv(sv,&sv_undef);
448         break;
449     case '`':
450         if (curpm && (rx = curpm->op_pmregexp)) {
451             if ((s = rx->subbeg) && rx->startp[0]) {
452                 i = rx->startp[0] - s;
453                 goto getrx;
454             }
455         }
456         sv_setsv(sv,&sv_undef);
457         break;
458     case '\'':
459         if (curpm && (rx = curpm->op_pmregexp)) {
460             if (rx->subend && (s = rx->endp[0])) {
461                 i = rx->subend - s;
462                 goto getrx;
463             }
464         }
465         sv_setsv(sv,&sv_undef);
466         break;
467     case '.':
468 #ifndef lint
469         if (GvIO(last_in_gv)) {
470             sv_setiv(sv, (IV)IoLINES(GvIO(last_in_gv)));
471         }
472 #endif
473         break;
474     case '?':
475         {
476             dTHR;
477             sv_setiv(sv, (IV)STATUS_CURRENT);
478 #ifdef COMPLEX_STATUS
479             LvTARGOFF(sv) = statusvalue;
480             LvTARGLEN(sv) = statusvalue_vms;
481 #endif
482         }
483         break;
484     case '^':
485         s = IoTOP_NAME(GvIOp(defoutgv));
486         if (s)
487             sv_setpv(sv,s);
488         else {
489             sv_setpv(sv,GvENAME(defoutgv));
490             sv_catpv(sv,"_TOP");
491         }
492         break;
493     case '~':
494         s = IoFMT_NAME(GvIOp(defoutgv));
495         if (!s)
496             s = GvENAME(defoutgv);
497         sv_setpv(sv,s);
498         break;
499 #ifndef lint
500     case '=':
501         sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(defoutgv)));
502         break;
503     case '-':
504         sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(defoutgv)));
505         break;
506     case '%':
507         sv_setiv(sv, (IV)IoPAGE(GvIOp(defoutgv)));
508         break;
509 #endif
510     case ':':
511         break;
512     case '/':
513         break;
514     case '[':
515         WITH_THR(sv_setiv(sv, (IV)curcop->cop_arybase));
516         break;
517     case '|':
518         sv_setiv(sv, (IV)(IoFLAGS(GvIOp(defoutgv)) & IOf_FLUSH) != 0 );
519         break;
520     case ',':
521         sv_setpvn(sv,ofs,ofslen);
522         break;
523     case '\\':
524         sv_setpvn(sv,ors,orslen);
525         break;
526     case '#':
527         sv_setpv(sv,ofmt);
528         break;
529     case '!':
530 #ifdef VMS
531         sv_setnv(sv, (double)((errno == EVMSERR) ? vaxc$errno : errno));
532         sv_setpv(sv, errno ? Strerror(errno) : "");
533 #else
534         {
535         int saveerrno = errno;
536         sv_setnv(sv, (double)errno);
537 #ifdef OS2
538         if (errno == errno_isOS2) sv_setpv(sv, os2error(Perl_rc));
539         else
540 #endif
541         sv_setpv(sv, errno ? Strerror(errno) : "");
542         errno = saveerrno;
543         }
544 #endif
545         SvNOK_on(sv);   /* what a wonderful hack! */
546         break;
547     case '<':
548         sv_setiv(sv, (IV)uid);
549         break;
550     case '>':
551         sv_setiv(sv, (IV)euid);
552         break;
553     case '(':
554         sv_setiv(sv, (IV)gid);
555         sv_setpvf(sv, "%Vd", (IV)gid);
556         goto add_groups;
557     case ')':
558         sv_setiv(sv, (IV)egid);
559         sv_setpvf(sv, "%Vd", (IV)egid);
560       add_groups:
561 #ifdef HAS_GETGROUPS
562         {
563             Groups_t gary[NGROUPS];
564             i = getgroups(NGROUPS,gary);
565             while (--i >= 0)
566                 sv_catpvf(sv, " %Vd", (IV)gary[i]);
567         }
568 #endif
569         SvIOK_on(sv);   /* what a wonderful hack! */
570         break;
571     case '*':
572         break;
573     case '0':
574         break;
575     }
576     return 0;
577 }
578
579 int
580 magic_getuvar(sv, mg)
581 SV *sv;
582 MAGIC *mg;
583 {
584     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
585
586     if (uf && uf->uf_val)
587         (*uf->uf_val)(uf->uf_index, sv);
588     return 0;
589 }
590
591 int
592 magic_setenv(sv,mg)
593 SV* sv;
594 MAGIC* mg;
595 {
596     register char *s;
597     char *ptr;
598     STRLEN len, klen;
599     I32 i;
600
601     s = SvPV(sv,len);
602     ptr = MgPV(mg,klen);
603     my_setenv(ptr, s);
604
605 #ifdef DYNAMIC_ENV_FETCH
606      /* We just undefd an environment var.  Is a replacement */
607      /* waiting in the wings? */
608     if (!len) {
609         SV **valp;
610         if ((valp = hv_fetch(GvHVn(envgv), ptr, klen, FALSE)))
611             s = SvPV(*valp, len);
612     }
613 #endif
614
615 #if !defined(OS2) && !defined(AMIGAOS) && !defined(WIN32)
616                             /* And you'll never guess what the dog had */
617                             /*   in its mouth... */
618     if (tainting) {
619         MgTAINTEDDIR_off(mg);
620 #ifdef VMS
621         if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) {
622             char pathbuf[256], eltbuf[256], *cp, *elt = s;
623             struct stat sbuf;
624             int i = 0, j = 0;
625
626             do {          /* DCL$PATH may be a search list */
627                 while (1) {   /* as may dev portion of any element */
628                     if ( ((cp = strchr(elt,'[')) || (cp = strchr(elt,'<'))) ) {
629                         if ( *(cp+1) == '.' || *(cp+1) == '-' ||
630                              cando_by_name(S_IWUSR,0,elt) ) {
631                             MgTAINTEDDIR_on(mg);
632                             return 0;
633                         }
634                     }
635                     if ((cp = strchr(elt, ':')) != Nullch)
636                         *cp = '\0';
637                     if (my_trnlnm(elt, eltbuf, j++))
638                         elt = eltbuf;
639                     else
640                         break;
641                 }
642                 j = 0;
643             } while (my_trnlnm(s, pathbuf, i++) && (elt = pathbuf));
644         }
645 #endif /* VMS */
646         if (s && klen == 4 && strEQ(ptr,"PATH")) {
647             char *strend = s + len;
648
649             while (s < strend) {
650                 char tmpbuf[256];
651                 struct stat st;
652                 s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf,
653                              s, strend, ':', &i);
654                 s++;
655                 if (i >= sizeof tmpbuf   /* too long -- assume the worst */
656                       || *tmpbuf != '/'
657                       || (Stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) {
658                     MgTAINTEDDIR_on(mg);
659                     return 0;
660                 }
661             }
662         }
663     }
664 #endif /* neither OS2 nor AMIGAOS nor WIN32 */
665
666     return 0;
667 }
668
669 int
670 magic_clearenv(sv,mg)
671 SV* sv;
672 MAGIC* mg;
673 {
674     my_setenv(MgPV(mg,na),Nullch);
675     return 0;
676 }
677
678 int
679 magic_set_all_env(sv,mg)
680 SV* sv;
681 MAGIC* mg;
682 {
683 #if defined(VMS)
684     die("Can't make list assignment to %%ENV on this system");
685 #else
686     dTHR;
687     if (localizing) {
688         HE* entry;
689         magic_clear_all_env(sv,mg);
690         hv_iterinit((HV*)sv);
691         while (entry = hv_iternext((HV*)sv)) {
692             I32 keylen;
693             my_setenv(hv_iterkey(entry, &keylen),
694                       SvPV(hv_iterval((HV*)sv, entry), na));
695         }
696     }
697 #endif
698     return 0;
699 }
700
701 int
702 magic_clear_all_env(sv,mg)
703 SV* sv;
704 MAGIC* mg;
705 {
706 #if defined(VMS)
707     die("Can't make list assignment to %%ENV on this system");
708 #else
709 #ifdef WIN32
710     char *envv = GetEnvironmentStrings();
711     char *cur = envv;
712     STRLEN len;
713     while (*cur) {
714         char *end = strchr(cur,'=');
715         if (end && end != cur) {
716             *end = '\0';
717             my_setenv(cur,Nullch);
718             *end = '=';
719             cur += strlen(end+1)+1;
720         }
721         else if ((len = strlen(cur)))
722             cur += len+1;
723     }
724     FreeEnvironmentStrings(envv);
725 #else
726     I32 i;
727
728     if (environ == origenviron)
729         New(901, environ, 1, char*);
730     else
731         for (i = 0; environ[i]; i++)
732             Safefree(environ[i]);
733     environ[0] = Nullch;
734
735 #endif
736 #endif
737     return 0;
738 }
739
740 int
741 magic_getsig(sv,mg)
742 SV* sv;
743 MAGIC* mg;
744 {
745     I32 i;
746     /* Are we fetching a signal entry? */
747     i = whichsig(MgPV(mg,na));
748     if (i) {
749         if(psig_ptr[i])
750             sv_setsv(sv,psig_ptr[i]);
751         else {
752             dTHR;               /* just for SvREFCNT_inc */
753             Sighandler_t sigstate = rsignal_state(i);
754
755             /* cache state so we don't fetch it again */
756             if(sigstate == SIG_IGN)
757                 sv_setpv(sv,"IGNORE");
758             else
759                 sv_setsv(sv,&sv_undef);
760             psig_ptr[i] = SvREFCNT_inc(sv);
761             SvTEMP_off(sv);
762         }
763     }
764     return 0;
765 }
766 int
767 magic_clearsig(sv,mg)
768 SV* sv;
769 MAGIC* mg;
770 {
771     I32 i;
772     /* Are we clearing a signal entry? */
773     i = whichsig(MgPV(mg,na));
774     if (i) {
775         if(psig_ptr[i]) {
776             SvREFCNT_dec(psig_ptr[i]);
777             psig_ptr[i]=0;
778         }
779         if(psig_name[i]) {
780             SvREFCNT_dec(psig_name[i]);
781             psig_name[i]=0;
782         }
783     }
784     return 0;
785 }
786
787 int
788 magic_setsig(sv,mg)
789 SV* sv;
790 MAGIC* mg;
791 {
792     dTHR;
793     register char *s;
794     I32 i;
795     SV** svp;
796
797     s = MgPV(mg,na);
798     if (*s == '_') {
799         if (strEQ(s,"__DIE__"))
800             svp = &diehook;
801         else if (strEQ(s,"__WARN__"))
802             svp = &warnhook;
803         else if (strEQ(s,"__PARSE__"))
804             svp = &parsehook;
805         else
806             croak("No such hook: %s", s);
807         i = 0;
808         if (*svp) {
809             SvREFCNT_dec(*svp);
810             *svp = 0;
811         }
812     }
813     else {
814         i = whichsig(s);        /* ...no, a brick */
815         if (!i) {
816             if (dowarn || strEQ(s,"ALARM"))
817                 warn("No such signal: SIG%s", s);
818             return 0;
819         }
820         SvREFCNT_dec(psig_name[i]);
821         SvREFCNT_dec(psig_ptr[i]);
822         psig_ptr[i] = SvREFCNT_inc(sv);
823         SvTEMP_off(sv); /* Make sure it doesn't go away on us */
824         psig_name[i] = newSVpv(s, strlen(s));
825         SvREADONLY_on(psig_name[i]);
826     }
827     if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) {
828         if (i)
829             (void)rsignal(i, sighandlerp);
830         else
831             *svp = SvREFCNT_inc(sv);
832         return 0;
833     }
834     s = SvPV_force(sv,na);
835     if (strEQ(s,"IGNORE")) {
836         if (i)
837             (void)rsignal(i, SIG_IGN);
838         else
839             *svp = 0;
840     }
841     else if (strEQ(s,"DEFAULT") || !*s) {
842         if (i)
843             (void)rsignal(i, SIG_DFL);
844         else
845             *svp = 0;
846     }
847     else {
848         /*
849          * We should warn if HINT_STRICT_REFS, but without
850          * access to a known hint bit in a known OP, we can't
851          * tell whether HINT_STRICT_REFS is in force or not.
852          */
853         if (!strchr(s,':') && !strchr(s,'\''))
854             sv_setpv(sv, form("main::%s", s));
855         if (i)
856             (void)rsignal(i, sighandlerp);
857         else
858             *svp = SvREFCNT_inc(sv);
859     }
860     return 0;
861 }
862
863 int
864 magic_setisa(sv,mg)
865 SV* sv;
866 MAGIC* mg;
867 {
868     sub_generation++;
869     return 0;
870 }
871
872 #ifdef OVERLOAD
873
874 int
875 magic_setamagic(sv,mg)
876 SV* sv;
877 MAGIC* mg;
878 {
879     /* HV_badAMAGIC_on(Sv_STASH(sv)); */
880     amagic_generation++;
881
882     return 0;
883 }
884 #endif /* OVERLOAD */
885
886 int
887 magic_setnkeys(sv,mg)
888 SV* sv;
889 MAGIC* mg;
890 {
891     if (LvTARG(sv)) {
892         hv_ksplit((HV*)LvTARG(sv), SvIV(sv));
893         LvTARG(sv) = Nullsv;    /* Don't allow a ref to reassign this. */
894     }
895     return 0;
896 }
897
898 static int
899 magic_methpack(sv,mg,meth)
900 SV* sv;
901 MAGIC* mg;
902 char *meth;
903 {
904     dTHR;
905     dSP;
906
907     ENTER;
908     SAVETMPS;
909     PUSHMARK(sp);
910     EXTEND(sp, 2);
911     PUSHs(mg->mg_obj);
912     if (mg->mg_ptr) {
913         if (mg->mg_len >= 0)
914             PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
915         else if (mg->mg_len == HEf_SVKEY)
916             PUSHs((SV*)mg->mg_ptr);
917     }
918     else if (mg->mg_type == 'p')
919         PUSHs(sv_2mortal(newSViv(mg->mg_len)));
920     PUTBACK;
921
922     if (perl_call_method(meth, G_SCALAR))
923         sv_setsv(sv, *stack_sp--);
924
925     FREETMPS;
926     LEAVE;
927     return 0;
928 }
929
930 int
931 magic_getpack(sv,mg)
932 SV* sv;
933 MAGIC* mg;
934 {
935     magic_methpack(sv,mg,"FETCH");
936     if (mg->mg_ptr)
937         mg->mg_flags |= MGf_GSKIP;
938     return 0;
939 }
940
941 int
942 magic_setpack(sv,mg)
943 SV* sv;
944 MAGIC* mg;
945 {
946     dTHR;
947     dSP;
948
949     PUSHMARK(sp);
950     EXTEND(sp, 3);
951     PUSHs(mg->mg_obj);
952     if (mg->mg_ptr) {
953         if (mg->mg_len >= 0)
954             PUSHs(sv_2mortal(newSVpv(mg->mg_ptr, mg->mg_len)));
955         else if (mg->mg_len == HEf_SVKEY)
956             PUSHs((SV*)mg->mg_ptr);
957     }
958     else if (mg->mg_type == 'p')
959         PUSHs(sv_2mortal(newSViv(mg->mg_len)));
960     PUSHs(sv);
961     PUTBACK;
962
963     perl_call_method("STORE", G_SCALAR|G_DISCARD);
964
965     return 0;
966 }
967
968 int
969 magic_clearpack(sv,mg)
970 SV* sv;
971 MAGIC* mg;
972 {
973     return magic_methpack(sv,mg,"DELETE");
974 }
975
976 int magic_wipepack(sv,mg)
977 SV* sv;
978 MAGIC* mg;
979 {
980     dTHR;
981     dSP;
982
983     PUSHMARK(sp);
984     XPUSHs(mg->mg_obj);
985     PUTBACK;
986
987     perl_call_method("CLEAR", G_SCALAR|G_DISCARD);
988
989     return 0;
990 }
991
992 int
993 magic_nextpack(sv,mg,key)
994 SV* sv;
995 MAGIC* mg;
996 SV* key;
997 {
998     dTHR;
999     dSP;
1000     char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY";
1001
1002     ENTER;
1003     SAVETMPS;
1004     PUSHMARK(sp);
1005     EXTEND(sp, 2);
1006     PUSHs(mg->mg_obj);
1007     if (SvOK(key))
1008         PUSHs(key);
1009     PUTBACK;
1010
1011     if (perl_call_method(meth, G_SCALAR))
1012         sv_setsv(key, *stack_sp--);
1013
1014     FREETMPS;
1015     LEAVE;
1016     return 0;
1017 }
1018
1019 int
1020 magic_existspack(sv,mg)
1021 SV* sv;
1022 MAGIC* mg;
1023 {
1024     return magic_methpack(sv,mg,"EXISTS");
1025
1026
1027 int
1028 magic_setdbline(sv,mg)
1029 SV* sv;
1030 MAGIC* mg;
1031 {
1032     dTHR;
1033     OP *o;
1034     I32 i;
1035     GV* gv;
1036     SV** svp;
1037
1038     gv = DBline;
1039     i = SvTRUE(sv);
1040     svp = av_fetch(GvAV(gv),
1041                      atoi(MgPV(mg,na)), FALSE);
1042     if (svp && SvIOKp(*svp) && (o = (OP*)SvSTASH(*svp)))
1043         o->op_private = i;
1044     else
1045         warn("Can't break at that line\n");
1046     return 0;
1047 }
1048
1049 int
1050 magic_getarylen(sv,mg)
1051 SV* sv;
1052 MAGIC* mg;
1053 {
1054     dTHR;
1055     sv_setiv(sv, AvFILL((AV*)mg->mg_obj) + curcop->cop_arybase);
1056     return 0;
1057 }
1058
1059 int
1060 magic_setarylen(sv,mg)
1061 SV* sv;
1062 MAGIC* mg;
1063 {
1064     dTHR;
1065     av_fill((AV*)mg->mg_obj, SvIV(sv) - curcop->cop_arybase);
1066     return 0;
1067 }
1068
1069 int
1070 magic_getpos(sv,mg)
1071 SV* sv;
1072 MAGIC* mg;
1073 {
1074     SV* lsv = LvTARG(sv);
1075     
1076     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) {
1077         mg = mg_find(lsv, 'g');
1078         if (mg && mg->mg_len >= 0) {
1079             dTHR;
1080             sv_setiv(sv, mg->mg_len + curcop->cop_arybase);
1081             return 0;
1082         }
1083     }
1084     (void)SvOK_off(sv);
1085     return 0;
1086 }
1087
1088 int
1089 magic_setpos(sv,mg)
1090 SV* sv;
1091 MAGIC* mg;
1092 {
1093     SV* lsv = LvTARG(sv);
1094     SSize_t pos;
1095     STRLEN len;
1096
1097     mg = 0;
1098     
1099     if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv))
1100         mg = mg_find(lsv, 'g');
1101     if (!mg) {
1102         if (!SvOK(sv))
1103             return 0;
1104         sv_magic(lsv, (SV*)0, 'g', Nullch, 0);
1105         mg = mg_find(lsv, 'g');
1106     }
1107     else if (!SvOK(sv)) {
1108         mg->mg_len = -1;
1109         return 0;
1110     }
1111     len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv);
1112
1113     WITH_THR(pos = SvIV(sv) - curcop->cop_arybase);
1114     if (pos < 0) {
1115         pos += len;
1116         if (pos < 0)
1117             pos = 0;
1118     }
1119     else if (pos > len)
1120         pos = len;
1121     mg->mg_len = pos;
1122     mg->mg_flags &= ~MGf_MINMATCH;
1123
1124     return 0;
1125 }
1126
1127 int
1128 magic_getglob(sv,mg)
1129 SV* sv;
1130 MAGIC* mg;
1131 {
1132     if (SvFAKE(sv)) {                   /* FAKE globs can get coerced */
1133         SvFAKE_off(sv);
1134         gv_efullname3(sv,((GV*)sv), "*");
1135         SvFAKE_on(sv);
1136     }
1137     else
1138         gv_efullname3(sv,((GV*)sv), "*");       /* a gv value, be nice */
1139     return 0;
1140 }
1141
1142 int
1143 magic_setglob(sv,mg)
1144 SV* sv;
1145 MAGIC* mg;
1146 {
1147     register char *s;
1148     GV* gv;
1149
1150     if (!SvOK(sv))
1151         return 0;
1152     s = SvPV(sv, na);
1153     if (*s == '*' && s[1])
1154         s++;
1155     gv = gv_fetchpv(s,TRUE, SVt_PVGV);
1156     if (sv == (SV*)gv)
1157         return 0;
1158     if (GvGP(sv))
1159         gp_free((GV*)sv);
1160     GvGP(sv) = gp_ref(GvGP(gv));
1161     return 0;
1162 }
1163
1164 int
1165 magic_setsubstr(sv,mg)
1166 SV* sv;
1167 MAGIC* mg;
1168 {
1169     STRLEN len;
1170     char *tmps = SvPV(sv,len);
1171     sv_insert(LvTARG(sv),LvTARGOFF(sv),LvTARGLEN(sv), tmps, len);
1172     return 0;
1173 }
1174
1175 int
1176 magic_gettaint(sv,mg)
1177 SV* sv;
1178 MAGIC* mg;
1179 {
1180     TAINT_IF((mg->mg_len & 1) ||
1181              (mg->mg_len & 2) && mg->mg_obj == sv);     /* kludge */
1182     return 0;
1183 }
1184
1185 int
1186 magic_settaint(sv,mg)
1187 SV* sv;
1188 MAGIC* mg;
1189 {
1190     dTHR;
1191     if (localizing) {
1192         if (localizing == 1)
1193             mg->mg_len <<= 1;
1194         else
1195             mg->mg_len >>= 1;
1196     }
1197     else if (tainted)
1198         mg->mg_len |= 1;
1199     else
1200         mg->mg_len &= ~1;
1201     return 0;
1202 }
1203
1204 int
1205 magic_setvec(sv,mg)
1206 SV* sv;
1207 MAGIC* mg;
1208 {
1209     do_vecset(sv);      /* XXX slurp this routine */
1210     return 0;
1211 }
1212
1213 int
1214 magic_getdefelem(sv,mg)
1215 SV* sv;
1216 MAGIC* mg;
1217 {
1218     SV *targ = Nullsv;
1219     if (LvTARGLEN(sv)) {
1220         if (mg->mg_obj) {
1221             HV* hv = (HV*)LvTARG(sv);
1222             HE* he = hv_fetch_ent(hv, mg->mg_obj, FALSE, 0);
1223             if (he)
1224                 targ = HeVAL(he);
1225         }
1226         else {
1227             AV* av = (AV*)LvTARG(sv);
1228             if ((I32)LvTARGOFF(sv) <= AvFILL(av))
1229                 targ = AvARRAY(av)[LvTARGOFF(sv)];
1230         }
1231         if (targ && targ != &sv_undef) {
1232             dTHR;               /* just for SvREFCNT_dec */
1233             /* somebody else defined it for us */
1234             SvREFCNT_dec(LvTARG(sv));
1235             LvTARG(sv) = SvREFCNT_inc(targ);
1236             LvTARGLEN(sv) = 0;
1237             SvREFCNT_dec(mg->mg_obj);
1238             mg->mg_obj = Nullsv;
1239             mg->mg_flags &= ~MGf_REFCOUNTED;
1240         }
1241     }
1242     else
1243         targ = LvTARG(sv);
1244     sv_setsv(sv, targ ? targ : &sv_undef);
1245     return 0;
1246 }
1247
1248 int
1249 magic_setdefelem(sv,mg)
1250 SV* sv;
1251 MAGIC* mg;
1252 {
1253     if (LvTARGLEN(sv))
1254         vivify_defelem(sv);
1255     if (LvTARG(sv)) {
1256         sv_setsv(LvTARG(sv), sv);
1257         SvSETMAGIC(LvTARG(sv));
1258     }
1259     return 0;
1260 }
1261
1262 int
1263 magic_freedefelem(sv,mg)
1264 SV* sv;
1265 MAGIC* mg;
1266 {
1267     SvREFCNT_dec(LvTARG(sv));
1268     return 0;
1269 }
1270
1271 void
1272 vivify_defelem(sv)
1273 SV* sv;
1274 {
1275     dTHR;                       /* just for SvREFCNT_inc and SvREFCNT_dec*/
1276     MAGIC* mg;
1277     SV* value;
1278
1279     if (!LvTARGLEN(sv) || !(mg = mg_find(sv, 'y')))
1280         return;
1281     if (mg->mg_obj) {
1282         HV* hv = (HV*)LvTARG(sv);
1283         HE* he = hv_fetch_ent(hv, mg->mg_obj, TRUE, 0);
1284         if (!he || (value = HeVAL(he)) == &sv_undef)
1285             croak(no_helem, SvPV(mg->mg_obj, na));
1286     }
1287     else {
1288         AV* av = (AV*)LvTARG(sv);
1289         if ((I32)LvTARGLEN(sv) < 0 && (I32)LvTARGOFF(sv) > AvFILL(av))
1290             LvTARG(sv) = Nullsv;        /* array can't be extended */
1291         else {
1292             SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE);
1293             if (!svp || (value = *svp) == &sv_undef)
1294                 croak(no_aelem, (I32)LvTARGOFF(sv));
1295         }
1296     }
1297     (void)SvREFCNT_inc(value);
1298     SvREFCNT_dec(LvTARG(sv));
1299     LvTARG(sv) = value;
1300     LvTARGLEN(sv) = 0;
1301     SvREFCNT_dec(mg->mg_obj);
1302     mg->mg_obj = Nullsv;
1303     mg->mg_flags &= ~MGf_REFCOUNTED;
1304 }
1305
1306 int
1307 magic_setmglob(sv,mg)
1308 SV* sv;
1309 MAGIC* mg;
1310 {
1311     mg->mg_len = -1;
1312     SvSCREAM_off(sv);
1313     return 0;
1314 }
1315
1316 int
1317 magic_setbm(sv,mg)
1318 SV* sv;
1319 MAGIC* mg;
1320 {
1321     sv_unmagic(sv, 'B');
1322     SvVALID_off(sv);
1323     return 0;
1324 }
1325
1326 int
1327 magic_setfm(sv,mg)
1328 SV* sv;
1329 MAGIC* mg;
1330 {
1331     sv_unmagic(sv, 'f');
1332     SvCOMPILED_off(sv);
1333     return 0;
1334 }
1335
1336 int
1337 magic_setuvar(sv,mg)
1338 SV* sv;
1339 MAGIC* mg;
1340 {
1341     struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr;
1342
1343     if (uf && uf->uf_set)
1344         (*uf->uf_set)(uf->uf_index, sv);
1345     return 0;
1346 }
1347
1348 #ifdef USE_LOCALE_COLLATE
1349 int
1350 magic_setcollxfrm(sv,mg)
1351 SV* sv;
1352 MAGIC* mg;
1353 {
1354     /*
1355      * René Descartes said "I think not."
1356      * and vanished with a faint plop.
1357      */
1358     if (mg->mg_ptr) {
1359         Safefree(mg->mg_ptr);
1360         mg->mg_ptr = NULL;
1361         mg->mg_len = -1;
1362     }
1363     return 0;
1364 }
1365 #endif /* USE_LOCALE_COLLATE */
1366
1367 int
1368 magic_set(sv,mg)
1369 SV* sv;
1370 MAGIC* mg;
1371 {
1372     dTHR;
1373     register char *s;
1374     I32 i;
1375     STRLEN len;
1376     switch (*mg->mg_ptr) {
1377     case '\001':        /* ^A */
1378         sv_setsv(bodytarget, sv);
1379         break;
1380     case '\004':        /* ^D */
1381         debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | 0x80000000;
1382         DEBUG_x(dump_all());
1383         break;
1384     case '\005':  /* ^E */
1385 #ifdef VMS
1386         set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1387 #else
1388         /* will anyone ever use this? */
1389         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4);
1390 #endif
1391         break;
1392     case '\006':        /* ^F */
1393         maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1394         break;
1395     case '\010':        /* ^H */
1396         hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1397         break;
1398     case '\t':  /* ^I */
1399         if (inplace)
1400             Safefree(inplace);
1401         if (SvOK(sv))
1402             inplace = savepv(SvPV(sv,na));
1403         else
1404             inplace = Nullch;
1405         break;
1406     case '\017':        /* ^O */
1407         if (osname)
1408             Safefree(osname);
1409         if (SvOK(sv))
1410             osname = savepv(SvPV(sv,na));
1411         else
1412             osname = Nullch;
1413         break;
1414     case '\020':        /* ^P */
1415         perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1416         break;
1417     case '\024':        /* ^T */
1418 #ifdef BIG_TIME
1419         basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv));
1420 #else
1421         basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1422 #endif
1423         break;
1424     case '\027':        /* ^W */
1425         dowarn = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1426         break;
1427     case '.':
1428         if (localizing) {
1429             if (localizing == 1)
1430                 save_sptr((SV**)&last_in_gv);
1431         }
1432         else if (SvOK(sv) && GvIO(last_in_gv))
1433             IoLINES(GvIOp(last_in_gv)) = (long)SvIV(sv);
1434         break;
1435     case '^':
1436         Safefree(IoTOP_NAME(GvIOp(defoutgv)));
1437         IoTOP_NAME(GvIOp(defoutgv)) = s = savepv(SvPV(sv,na));
1438         IoTOP_GV(GvIOp(defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1439         break;
1440     case '~':
1441         Safefree(IoFMT_NAME(GvIOp(defoutgv)));
1442         IoFMT_NAME(GvIOp(defoutgv)) = s = savepv(SvPV(sv,na));
1443         IoFMT_GV(GvIOp(defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO);
1444         break;
1445     case '=':
1446         IoPAGE_LEN(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1447         break;
1448     case '-':
1449         IoLINES_LEFT(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1450         if (IoLINES_LEFT(GvIOp(defoutgv)) < 0L)
1451             IoLINES_LEFT(GvIOp(defoutgv)) = 0L;
1452         break;
1453     case '%':
1454         IoPAGE(GvIOp(defoutgv)) = (long)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1455         break;
1456     case '|':
1457         {
1458             IO *io = GvIOp(defoutgv);
1459             if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0)
1460                 IoFLAGS(io) &= ~IOf_FLUSH;
1461             else {
1462                 if (!(IoFLAGS(io) & IOf_FLUSH)) {
1463                     PerlIO *ofp = IoOFP(io);
1464                     if (ofp)
1465                         (void)PerlIO_flush(ofp);
1466                     IoFLAGS(io) |= IOf_FLUSH;
1467                 }
1468             }
1469         }
1470         break;
1471     case '*':
1472         i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1473         multiline = (i != 0);
1474         break;
1475     case '/':
1476         SvREFCNT_dec(nrs);
1477         nrs = newSVsv(sv);
1478         SvREFCNT_dec(rs);
1479         rs = SvREFCNT_inc(nrs);
1480         break;
1481     case '\\':
1482         if (ors)
1483             Safefree(ors);
1484         if (SvOK(sv) || SvGMAGICAL(sv))
1485             ors = savepv(SvPV(sv,orslen));
1486         else {
1487             ors = Nullch;
1488             orslen = 0;
1489         }
1490         break;
1491     case ',':
1492         if (ofs)
1493             Safefree(ofs);
1494         ofs = savepv(SvPV(sv, ofslen));
1495         break;
1496     case '#':
1497         if (ofmt)
1498             Safefree(ofmt);
1499         ofmt = savepv(SvPV(sv,na));
1500         break;
1501     case '[':
1502         compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1503         break;
1504     case '?':
1505 #ifdef COMPLEX_STATUS
1506         if (localizing == 2) {
1507             statusvalue = LvTARGOFF(sv);
1508             statusvalue_vms = LvTARGLEN(sv);
1509         }
1510         else
1511 #endif
1512 #ifdef VMSISH_STATUS
1513         if (VMSISH_STATUS)
1514             STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)));
1515         else
1516 #endif
1517             STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv));
1518         break;
1519     case '!':
1520         SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv),
1521                  (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno);
1522         break;
1523     case '<':
1524         uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1525         if (delaymagic) {
1526             delaymagic |= DM_RUID;
1527             break;                              /* don't do magic till later */
1528         }
1529 #ifdef HAS_SETRUID
1530         (void)setruid((Uid_t)uid);
1531 #else
1532 #ifdef HAS_SETREUID
1533         (void)setreuid((Uid_t)uid, (Uid_t)-1);
1534 #else
1535 #ifdef HAS_SETRESUID
1536       (void)setresuid((Uid_t)uid, (Uid_t)-1, (Uid_t)-1);
1537 #else
1538         if (uid == euid)                /* special case $< = $> */
1539             (void)setuid(uid);
1540         else {
1541             uid = (I32)getuid();
1542             croak("setruid() not implemented");
1543         }
1544 #endif
1545 #endif
1546 #endif
1547         uid = (I32)getuid();
1548         tainting |= (uid && (euid != uid || egid != gid));
1549         break;
1550     case '>':
1551         euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1552         if (delaymagic) {
1553             delaymagic |= DM_EUID;
1554             break;                              /* don't do magic till later */
1555         }
1556 #ifdef HAS_SETEUID
1557         (void)seteuid((Uid_t)euid);
1558 #else
1559 #ifdef HAS_SETREUID
1560         (void)setreuid((Uid_t)-1, (Uid_t)euid);
1561 #else
1562 #ifdef HAS_SETRESUID
1563         (void)setresuid((Uid_t)-1, (Uid_t)euid, (Uid_t)-1);
1564 #else
1565         if (euid == uid)                /* special case $> = $< */
1566             setuid(euid);
1567         else {
1568             euid = (I32)geteuid();
1569             croak("seteuid() not implemented");
1570         }
1571 #endif
1572 #endif
1573 #endif
1574         euid = (I32)geteuid();
1575         tainting |= (uid && (euid != uid || egid != gid));
1576         break;
1577     case '(':
1578         gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1579         if (delaymagic) {
1580             delaymagic |= DM_RGID;
1581             break;                              /* don't do magic till later */
1582         }
1583 #ifdef HAS_SETRGID
1584         (void)setrgid((Gid_t)gid);
1585 #else
1586 #ifdef HAS_SETREGID
1587         (void)setregid((Gid_t)gid, (Gid_t)-1);
1588 #else
1589 #ifdef HAS_SETRESGID
1590       (void)setresgid((Gid_t)gid, (Gid_t)-1, (Gid_t) 1);
1591 #else
1592         if (gid == egid)                        /* special case $( = $) */
1593             (void)setgid(gid);
1594         else {
1595             gid = (I32)getgid();
1596             croak("setrgid() not implemented");
1597         }
1598 #endif
1599 #endif
1600 #endif
1601         gid = (I32)getgid();
1602         tainting |= (uid && (euid != uid || egid != gid));
1603         break;
1604     case ')':
1605 #ifdef HAS_SETGROUPS
1606         {
1607             char *p = SvPV(sv, na);
1608             Groups_t gary[NGROUPS];
1609
1610             SET_NUMERIC_STANDARD();
1611             while (isSPACE(*p))
1612                 ++p;
1613             egid = I_V(atof(p));
1614             for (i = 0; i < NGROUPS; ++i) {
1615                 while (*p && !isSPACE(*p))
1616                     ++p;
1617                 while (isSPACE(*p))
1618                     ++p;
1619                 if (!*p)
1620                     break;
1621                 gary[i] = I_V(atof(p));
1622             }
1623             if (i)
1624                 (void)setgroups(i, gary);
1625         }
1626 #else  /* HAS_SETGROUPS */
1627         egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
1628 #endif /* HAS_SETGROUPS */
1629         if (delaymagic) {
1630             delaymagic |= DM_EGID;
1631             break;                              /* don't do magic till later */
1632         }
1633 #ifdef HAS_SETEGID
1634         (void)setegid((Gid_t)egid);
1635 #else
1636 #ifdef HAS_SETREGID
1637         (void)setregid((Gid_t)-1, (Gid_t)egid);
1638 #else
1639 #ifdef HAS_SETRESGID
1640         (void)setresgid((Gid_t)-1, (Gid_t)egid, (Gid_t)-1);
1641 #else
1642         if (egid == gid)                        /* special case $) = $( */
1643             (void)setgid(egid);
1644         else {
1645             egid = (I32)getegid();
1646             croak("setegid() not implemented");
1647         }
1648 #endif
1649 #endif
1650 #endif
1651         egid = (I32)getegid();
1652         tainting |= (uid && (euid != uid || egid != gid));
1653         break;
1654     case ':':
1655         chopset = SvPV_force(sv,na);
1656         break;
1657     case '0':
1658         if (!origalen) {
1659             s = origargv[0];
1660             s += strlen(s);
1661             /* See if all the arguments are contiguous in memory */
1662             for (i = 1; i < origargc; i++) {
1663                 if (origargv[i] == s + 1
1664 #ifdef OS2
1665                     || origargv[i] == s + 2
1666 #endif 
1667                    )
1668                     s += strlen(++s);   /* this one is ok too */
1669                 else
1670                     break;
1671             }
1672             /* can grab env area too? */
1673             if (origenviron && (origenviron[0] == s + 1
1674 #ifdef OS2
1675                                 || (origenviron[0] == s + 9 && (s += 8))
1676 #endif 
1677                )) {
1678                 my_setenv("NoNe  SuCh", Nullch);
1679                                             /* force copy of environment */
1680                 for (i = 0; origenviron[i]; i++)
1681                     if (origenviron[i] == s + 1)
1682                         s += strlen(++s);
1683                     else
1684                         break;
1685             }
1686             origalen = s - origargv[0];
1687         }
1688         s = SvPV_force(sv,len);
1689         i = len;
1690         if (i >= origalen) {
1691             i = origalen;
1692             /* don't allow system to limit $0 seen by script */
1693             /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */
1694             Copy(s, origargv[0], i, char);
1695             s = origargv[0]+i;
1696             *s = '\0';
1697         }
1698         else {
1699             Copy(s, origargv[0], i, char);
1700             s = origargv[0]+i;
1701             *s++ = '\0';
1702             while (++i < origalen)
1703                 *s++ = ' ';
1704             s = origargv[0]+i;
1705             for (i = 1; i < origargc; i++)
1706                 origargv[i] = Nullch;
1707         }
1708         break;
1709     }
1710     return 0;
1711 }
1712
1713 #ifdef USE_THREADS
1714 int
1715 magic_mutexfree(sv, mg)
1716 SV *sv;
1717 MAGIC *mg;
1718 {
1719     dTHR;
1720     DEBUG_L(PerlIO_printf(PerlIO_stderr(), "0x%lx: magic_mutexfree 0x%lx\n",
1721                           (unsigned long)thr, (unsigned long)sv);)
1722     if (MgOWNER(mg))
1723         croak("panic: magic_mutexfree");
1724     MUTEX_DESTROY(MgMUTEXP(mg));
1725     COND_DESTROY(MgCONDP(mg));
1726     return 0;
1727 }
1728 #endif /* USE_THREADS */
1729
1730 I32
1731 whichsig(sig)
1732 char *sig;
1733 {
1734     register char **sigv;
1735
1736     for (sigv = sig_name+1; *sigv; sigv++)
1737         if (strEQ(sig,*sigv))
1738             return sig_num[sigv - sig_name];
1739 #ifdef SIGCLD
1740     if (strEQ(sig,"CHLD"))
1741         return SIGCLD;
1742 #endif
1743 #ifdef SIGCHLD
1744     if (strEQ(sig,"CLD"))
1745         return SIGCHLD;
1746 #endif
1747     return 0;
1748 }
1749
1750 static SV* sig_sv;
1751
1752 static void
1753 unwind_handler_stack(p)
1754     void *p;
1755 {
1756     dTHR;
1757     U32 flags = *(U32*)p;
1758
1759     if (flags & 1)
1760         savestack_ix -= 5; /* Unprotect save in progress. */
1761     /* cxstack_ix-- Not needed, die already unwound it. */
1762     if (flags & 64)
1763         SvREFCNT_dec(sig_sv);
1764 }
1765
1766 Signal_t
1767 sighandler(sig)
1768 int sig;
1769 {
1770     dTHR;
1771     dSP;
1772     GV *gv;
1773     HV *st;
1774     SV *sv, *tSv = Sv;
1775     CV *cv;
1776     AV *oldstack;
1777     OP *myop = op;
1778     U32 flags = 0;
1779     I32 o_save_i = savestack_ix, type;
1780     CONTEXT *cx;
1781     XPV *tXpv = Xpv;
1782     
1783     if (savestack_ix + 15 <= savestack_max)
1784         flags |= 1;
1785     if (cxstack_ix < cxstack_max - 2)
1786         flags |= 2;
1787     if (markstack_ptr < markstack_max - 2)
1788         flags |= 4;
1789     if (retstack_ix < retstack_max - 2)
1790         flags |= 8;
1791     if (scopestack_ix < scopestack_max - 3)
1792         flags |= 16;
1793
1794     if (flags & 2) {            /* POPBLOCK may decrease cxstack too early. */
1795         cxstack_ix++;           /* Protect from overwrite. */
1796         cx = &cxstack[cxstack_ix];
1797         type = cx->cx_type;             /* Can be during partial write. */
1798         cx->cx_type = CXt_NULL;         /* Make it safe for unwind. */
1799     }
1800     if (!psig_ptr[sig])
1801         die("Signal SIG%s received, but no signal handler set.\n",
1802             sig_name[sig]);
1803
1804     /* Max number of items pushed there is 3*n or 4. We cannot fix
1805        infinity, so we fix 4 (in fact 5): */
1806     if (flags & 1) {
1807         savestack_ix += 5;              /* Protect save in progress. */
1808         o_save_i = savestack_ix;
1809         SAVEDESTRUCTOR(unwind_handler_stack, (void*)&flags);
1810     }
1811     if (flags & 4) 
1812         markstack_ptr++;                /* Protect mark. */
1813     if (flags & 8) {
1814         retstack_ix++;
1815         retstack[retstack_ix] = NULL;
1816     }
1817     if (flags & 16)
1818         scopestack_ix += 1;
1819     /* sv_2cv is too complicated, try a simpler variant first: */
1820     if (!SvROK(psig_ptr[sig]) || !(cv = (CV*)SvRV(psig_ptr[sig])) 
1821         || SvTYPE(cv) != SVt_PVCV)
1822         cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE);
1823
1824     if (!cv || !CvROOT(cv)) {
1825         if (dowarn)
1826             warn("SIG%s handler \"%s\" not defined.\n",
1827                 sig_name[sig], GvENAME(gv) );
1828         return;
1829     }
1830
1831     oldstack = curstack;
1832     if (curstack != signalstack)
1833         AvFILL(signalstack) = 0;
1834     SWITCHSTACK(curstack, signalstack);
1835
1836     if(psig_name[sig]) {
1837         sv = SvREFCNT_inc(psig_name[sig]);
1838         flags |= 64;
1839         sig_sv = sv;
1840     } else {
1841         sv = sv_newmortal();
1842         sv_setpv(sv,sig_name[sig]);
1843     }
1844     PUSHMARK(sp);
1845     PUSHs(sv);
1846     PUTBACK;
1847
1848     perl_call_sv((SV*)cv, G_DISCARD);
1849
1850     SWITCHSTACK(signalstack, oldstack);
1851     if (flags & 1)
1852         savestack_ix -= 8; /* Unprotect save in progress. */
1853     if (flags & 2) {
1854         cxstack[cxstack_ix].cx_type = type;
1855         cxstack_ix -= 1;
1856     }
1857     if (flags & 4) 
1858         markstack_ptr--;
1859     if (flags & 8) 
1860         retstack_ix--;
1861     if (flags & 16)
1862         scopestack_ix -= 1;
1863     if (flags & 64)
1864         SvREFCNT_dec(sv);
1865     op = myop;                  /* Apparently not needed... */
1866     
1867     Sv = tSv;                   /* Restore global temporaries. */
1868     Xpv = tXpv;
1869     return;
1870 }