source: trunk/third/perl/mg.c @ 10724

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