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