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