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