This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add $^E and $^O
[perl5.git] / pp_sys.c
1 /*    pp_sys.c
2  *
3  *    Copyright (c) 1991-1994, 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  * But only a short way ahead its floor and the walls on either side were
12  * cloven by a great fissure, out of which the red glare came, now leaping
13  * up, now dying down into darkness; and all the while far below there was
14  * a rumour and a trouble as of great engines throbbing and labouring.
15  */
16
17 #include "EXTERN.h"
18 #include "perl.h"
19
20 /* XXX Omit this -- it causes too much grief on mixed systems.
21    Next time, I should force broken systems to unset i_unistd in
22    hint files.
23 */
24 #if 0
25 # ifdef I_UNISTD
26 #  include <unistd.h>
27 # endif
28 #endif
29
30 /* Put this after #includes because fork and vfork prototypes may
31    conflict.
32 */
33 #ifndef HAS_VFORK
34 #   define vfork fork
35 #endif
36
37 #if defined(HAS_SOCKET) && !defined(VMS) /* VMS handles sockets via vmsish.h */
38 # include <sys/socket.h>
39 # include <netdb.h>
40 # ifndef ENOTSOCK
41 #  ifdef I_NET_ERRNO
42 #   include <net/errno.h>
43 #  endif
44 # endif
45 #endif
46
47 #ifdef HAS_SELECT
48 #ifdef I_SYS_SELECT
49 #ifndef I_SYS_TIME
50 #include <sys/select.h>
51 #endif
52 #endif
53 #endif
54
55 #ifdef HOST_NOT_FOUND
56 extern int h_errno;
57 #endif
58
59 #ifdef HAS_PASSWD
60 # ifdef I_PWD
61 #  include <pwd.h>
62 # else
63     struct passwd *getpwnam _((char *));
64     struct passwd *getpwuid _((Uid_t));
65 # endif
66   struct passwd *getpwent _((void));
67 #endif
68
69 #ifdef HAS_GROUP
70 # ifdef I_GRP
71 #  include <grp.h>
72 # else
73     struct group *getgrnam _((char *));
74     struct group *getgrgid _((Gid_t));
75 # endif
76     struct group *getgrent _((void));
77 #endif
78
79 #ifdef I_UTIME
80 #include <utime.h>
81 #endif
82 #ifdef I_FCNTL
83 #include <fcntl.h>
84 #endif
85 #ifdef I_SYS_FILE
86 #include <sys/file.h>
87 #endif
88
89 #if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
90 static int dooneliner _((char *cmd, char *filename));
91 #endif
92 /* Pushy I/O. */
93
94 PP(pp_backtick)
95 {
96     dSP; dTARGET;
97     FILE *fp;
98     char *tmps = POPp;
99     TAINT_PROPER("``");
100     fp = my_popen(tmps, "r");
101     if (fp) {
102         sv_setpv(TARG, "");     /* note that this preserves previous buffer */
103         if (GIMME == G_SCALAR) {
104             while (sv_gets(TARG, fp, SvCUR(TARG)) != Nullch)
105                 /*SUPPRESS 530*/
106                 ;
107             XPUSHs(TARG);
108         }
109         else {
110             SV *sv;
111
112             for (;;) {
113                 sv = NEWSV(56, 80);
114                 if (sv_gets(sv, fp, 0) == Nullch) {
115                     SvREFCNT_dec(sv);
116                     break;
117                 }
118                 XPUSHs(sv_2mortal(sv));
119                 if (SvLEN(sv) - SvCUR(sv) > 20) {
120                     SvLEN_set(sv, SvCUR(sv)+1);
121                     Renew(SvPVX(sv), SvLEN(sv), char);
122                 }
123             }
124         }
125         statusvalue = FIXSTATUS(my_pclose(fp));
126     }
127     else {
128         statusvalue = -1;
129         if (GIMME == G_SCALAR)
130             RETPUSHUNDEF;
131     }
132
133     RETURN;
134 }
135
136 PP(pp_glob)
137 {
138     OP *result;
139     ENTER;
140
141     SAVESPTR(last_in_gv);       /* We don't want this to be permanent. */
142     last_in_gv = (GV*)*stack_sp--;
143
144     SAVESPTR(rs);               /* This is not permanent, either. */
145     rs = sv_2mortal(newSVpv("", 1));
146 #ifndef DOSISH
147 #ifndef CSH
148     *SvPVX(rs) = '\n';
149 #endif  /* !CSH */
150 #endif  /* !MSDOS */
151
152     result = do_readline();
153     LEAVE;
154     return result;
155 }
156
157 PP(pp_indread)
158 {
159     last_in_gv = gv_fetchpv(SvPVx(GvSV((GV*)(*stack_sp--)), na), TRUE,SVt_PVIO);
160     return do_readline();
161 }
162
163 PP(pp_rcatline)
164 {
165     last_in_gv = cGVOP->op_gv;
166     return do_readline();
167 }
168
169 PP(pp_warn)
170 {
171     dSP; dMARK;
172     char *tmps;
173     if (SP - MARK != 1) {
174         dTARGET;
175         do_join(TARG, &sv_no, MARK, SP);
176         tmps = SvPV(TARG, na);
177         SP = MARK + 1;
178     }
179     else {
180         tmps = SvPV(TOPs, na);
181     }
182     if (!tmps || !*tmps) {
183         SV *error = GvSV(errgv);
184         (void)SvUPGRADE(error, SVt_PV);
185         if (SvPOK(error) && SvCUR(error))
186             sv_catpv(error, "\t...caught");
187         tmps = SvPV(error, na);
188     }
189     if (!tmps || !*tmps)
190         tmps = "Warning: something's wrong";
191     warn("%s", tmps);
192     RETSETYES;
193 }
194
195 PP(pp_die)
196 {
197     dSP; dMARK;
198     char *tmps;
199     if (SP - MARK != 1) {
200         dTARGET;
201         do_join(TARG, &sv_no, MARK, SP);
202         tmps = SvPV(TARG, na);
203         SP = MARK + 1;
204     }
205     else {
206         tmps = SvPV(TOPs, na);
207     }
208     if (!tmps || !*tmps) {
209         SV *error = GvSV(errgv);
210         (void)SvUPGRADE(error, SVt_PV);
211         if (SvPOK(error) && SvCUR(error))
212             sv_catpv(error, "\t...propagated");
213         tmps = SvPV(error, na);
214     }
215     if (!tmps || !*tmps)
216         tmps = "Died";
217     DIE("%s", tmps);
218 }
219
220 /* I/O. */
221
222 PP(pp_open)
223 {
224     dSP; dTARGET;
225     GV *gv;
226     SV *sv;
227     char *tmps;
228     STRLEN len;
229
230     if (MAXARG > 1)
231         sv = POPs;
232     else if (SvTYPE(TOPs) == SVt_PVGV)
233         sv = GvSV(TOPs);
234     else
235         DIE(no_usym, "filehandle");
236     gv = (GV*)POPs;
237     tmps = SvPV(sv, len);
238     if (do_open(gv, tmps, len, FALSE, 0, 0, Nullfp)) {
239         IoLINES(GvIOp(gv)) = 0;
240         PUSHi( (I32)forkprocess );
241     }
242     else if (forkprocess == 0)          /* we are a new child */
243         PUSHi(0);
244     else
245         RETPUSHUNDEF;
246     RETURN;
247 }
248
249 PP(pp_close)
250 {
251     dSP;
252     GV *gv;
253
254     if (MAXARG == 0)
255         gv = defoutgv;
256     else
257         gv = (GV*)POPs;
258     EXTEND(SP, 1);
259     PUSHs( do_close(gv, TRUE) ? &sv_yes : &sv_no );
260     RETURN;
261 }
262
263 PP(pp_pipe_op)
264 {
265     dSP;
266 #ifdef HAS_PIPE
267     GV *rgv;
268     GV *wgv;
269     register IO *rstio;
270     register IO *wstio;
271     int fd[2];
272
273     wgv = (GV*)POPs;
274     rgv = (GV*)POPs;
275
276     if (!rgv || !wgv)
277         goto badexit;
278
279     if (SvTYPE(rgv) != SVt_PVGV || SvTYPE(wgv) != SVt_PVGV)
280         DIE(no_usym, "filehandle");
281     rstio = GvIOn(rgv);
282     wstio = GvIOn(wgv);
283
284     if (IoIFP(rstio))
285         do_close(rgv, FALSE);
286     if (IoIFP(wstio))
287         do_close(wgv, FALSE);
288
289     if (pipe(fd) < 0)
290         goto badexit;
291
292     IoIFP(rstio) = fdopen(fd[0], "r");
293     IoOFP(wstio) = fdopen(fd[1], "w");
294     IoIFP(wstio) = IoOFP(wstio);
295     IoTYPE(rstio) = '<';
296     IoTYPE(wstio) = '>';
297
298     if (!IoIFP(rstio) || !IoOFP(wstio)) {
299         if (IoIFP(rstio)) fclose(IoIFP(rstio));
300         else close(fd[0]);
301         if (IoOFP(wstio)) fclose(IoOFP(wstio));
302         else close(fd[1]);
303         goto badexit;
304     }
305
306     RETPUSHYES;
307
308 badexit:
309     RETPUSHUNDEF;
310 #else
311     DIE(no_func, "pipe");
312 #endif
313 }
314
315 PP(pp_fileno)
316 {
317     dSP; dTARGET;
318     GV *gv;
319     IO *io;
320     FILE *fp;
321     if (MAXARG < 1)
322         RETPUSHUNDEF;
323     gv = (GV*)POPs;
324     if (!gv || !(io = GvIO(gv)) || !(fp = IoIFP(io)))
325         RETPUSHUNDEF;
326     PUSHi(fileno(fp));
327     RETURN;
328 }
329
330 PP(pp_umask)
331 {
332     dSP; dTARGET;
333     int anum;
334
335 #ifdef HAS_UMASK
336     if (MAXARG < 1) {
337         anum = umask(0);
338         (void)umask(anum);
339     }
340     else
341         anum = umask(POPi);
342     TAINT_PROPER("umask");
343     XPUSHi(anum);
344 #else
345     DIE(no_func, "Unsupported function umask");
346 #endif
347     RETURN;
348 }
349
350 PP(pp_binmode)
351 {
352     dSP;
353     GV *gv;
354     IO *io;
355     FILE *fp;
356
357     if (MAXARG < 1)
358         RETPUSHUNDEF;
359
360     gv = (GV*)POPs;
361
362     EXTEND(SP, 1);
363     if (!(io = GvIO(gv)) || !(fp = IoIFP(io)))
364         RETSETUNDEF;
365
366 #ifdef DOSISH
367 #ifdef atarist
368     if (!Fflush(fp) && (fp->_flag |= _IOBIN))
369         RETPUSHYES;
370     else
371         RETPUSHUNDEF;
372 #else
373     if (setmode(fileno(fp), OP_BINARY) != -1)
374         RETPUSHYES;
375     else
376         RETPUSHUNDEF;
377 #endif
378 #else
379     RETPUSHYES;
380 #endif
381 }
382
383 PP(pp_tie)
384 {
385     dSP;
386     SV *varsv;
387     HV* stash;
388     GV *gv;
389     BINOP myop;
390     SV *sv;
391     SV **mark = stack_base + ++*markstack_ptr;  /* reuse in entersub */
392     I32 markoff = mark - stack_base - 1;
393     char *methname;
394
395     varsv = mark[0];
396     if (SvTYPE(varsv) == SVt_PVHV)
397         methname = "TIEHASH";
398     else if (SvTYPE(varsv) == SVt_PVAV)
399         methname = "TIEARRAY";
400     else if (SvTYPE(varsv) == SVt_PVGV)
401         methname = "TIEHANDLE";
402     else
403         methname = "TIESCALAR";
404
405     stash = gv_stashsv(mark[1], FALSE);
406     if (!stash || !(gv = gv_fetchmethod(stash, methname)) || !GvCV(gv))
407         DIE("Can't locate object method \"%s\" via package \"%s\"",
408                 methname, SvPV(mark[1],na));
409
410     Zero(&myop, 1, BINOP);
411     myop.op_last = (OP *) &myop;
412     myop.op_next = Nullop;
413     myop.op_flags = OPf_KNOW|OPf_STACKED;
414
415     ENTER;
416     SAVESPTR(op);
417     op = (OP *) &myop;
418
419     XPUSHs(gv);
420     PUTBACK;
421
422     if (op = pp_entersub())
423         run();
424     SPAGAIN;
425
426     sv = TOPs;
427     if (sv_isobject(sv)) {
428         if (SvTYPE(varsv) == SVt_PVHV || SvTYPE(varsv) == SVt_PVAV) {
429             sv_unmagic(varsv, 'P');
430             sv_magic(varsv, sv, 'P', Nullch, 0);
431         }
432         else {
433             sv_unmagic(varsv, 'q');
434             sv_magic(varsv, sv, 'q', Nullch, 0);
435         }
436     }
437     LEAVE;
438     SP = stack_base + markoff;
439     PUSHs(sv);
440     RETURN;
441 }
442
443 PP(pp_untie)
444 {
445     dSP;
446     if (SvTYPE(TOPs) == SVt_PVHV || SvTYPE(TOPs) == SVt_PVAV)
447         sv_unmagic(TOPs, 'P');
448     else
449         sv_unmagic(TOPs, 'q');
450     RETSETYES;
451 }
452
453 PP(pp_tied)
454 {
455     dSP;
456     SV * sv ;
457     MAGIC * mg ;
458
459     sv = POPs;
460     if (SvMAGICAL(sv)) {
461         if (SvTYPE(sv) == SVt_PVHV || SvTYPE(sv) == SVt_PVAV)
462             mg = mg_find(sv, 'P') ;
463         else
464             mg = mg_find(sv, 'q') ;
465
466         if (mg)  {
467             PUSHs(sv_2mortal(newSVsv(mg->mg_obj))) ; 
468             RETURN ;
469         }
470     }
471
472     RETPUSHUNDEF;
473 }
474
475 PP(pp_dbmopen)
476 {
477     dSP;
478     HV *hv;
479     dPOPPOPssrl;
480     HV* stash;
481     GV *gv;
482     BINOP myop;
483     SV *sv;
484
485     hv = (HV*)POPs;
486
487     sv = sv_mortalcopy(&sv_no);
488     sv_setpv(sv, "AnyDBM_File");
489     stash = gv_stashsv(sv, FALSE);
490     if (!stash || !(gv = gv_fetchmethod(stash, "TIEHASH")) || !GvCV(gv)) {
491         PUTBACK;
492         perl_require_pv("AnyDBM_File.pm");
493         SPAGAIN;
494         if (!(gv = gv_fetchmethod(stash, "TIEHASH")) || !GvCV(gv))
495             DIE("No dbm on this machine");
496     }
497
498     Zero(&myop, 1, BINOP);
499     myop.op_last = (OP *) &myop;
500     myop.op_next = Nullop;
501     myop.op_flags = OPf_KNOW|OPf_STACKED;
502
503     ENTER;
504     SAVESPTR(op);
505     op = (OP *) &myop;
506     PUTBACK;
507     pp_pushmark();
508
509     EXTEND(sp, 5);
510     PUSHs(sv);
511     PUSHs(left);
512     if (SvIV(right))
513         PUSHs(sv_2mortal(newSViv(O_RDWR|O_CREAT)));
514     else
515         PUSHs(sv_2mortal(newSViv(O_RDWR)));
516     PUSHs(right);
517     PUSHs(gv);
518     PUTBACK;
519
520     if (op = pp_entersub())
521         run();
522     SPAGAIN;
523
524     if (!sv_isobject(TOPs)) {
525         sp--;
526         op = (OP *) &myop;
527         PUTBACK;
528         pp_pushmark();
529
530         PUSHs(sv);
531         PUSHs(left);
532         PUSHs(sv_2mortal(newSViv(O_RDONLY)));
533         PUSHs(right);
534         PUSHs(gv);
535         PUTBACK;
536
537         if (op = pp_entersub())
538             run();
539         SPAGAIN;
540     }
541
542     if (sv_isobject(TOPs))
543         sv_magic((SV*)hv, TOPs, 'P', Nullch, 0);
544     LEAVE;
545     RETURN;
546 }
547
548 PP(pp_dbmclose)
549 {
550     return pp_untie(ARGS);
551 }
552
553 PP(pp_sselect)
554 {
555     dSP; dTARGET;
556 #ifdef HAS_SELECT
557     register I32 i;
558     register I32 j;
559     register char *s;
560     register SV *sv;
561     double value;
562     I32 maxlen = 0;
563     I32 nfound;
564     struct timeval timebuf;
565     struct timeval *tbuf = &timebuf;
566     I32 growsize;
567     char *fd_sets[4];
568 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
569         I32 masksize;
570         I32 offset;
571         I32 k;
572
573 #   if BYTEORDER & 0xf0000
574 #       define ORDERBYTE (0x88888888 - BYTEORDER)
575 #   else
576 #       define ORDERBYTE (0x4444 - BYTEORDER)
577 #   endif
578
579 #endif
580
581     SP -= 4;
582     for (i = 1; i <= 3; i++) {
583         if (!SvPOK(SP[i]))
584             continue;
585         j = SvCUR(SP[i]);
586         if (maxlen < j)
587             maxlen = j;
588     }
589
590 #if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
591 #ifdef __linux__
592     growsize = sizeof(fd_set);
593 #else
594     growsize = maxlen;          /* little endians can use vecs directly */
595 #endif
596 #else
597 #ifdef NFDBITS
598
599 #ifndef NBBY
600 #define NBBY 8
601 #endif
602
603     masksize = NFDBITS / NBBY;
604 #else
605     masksize = sizeof(long);    /* documented int, everyone seems to use long */
606 #endif
607     growsize = maxlen + (masksize - (maxlen % masksize));
608     Zero(&fd_sets[0], 4, char*);
609 #endif
610
611     sv = SP[4];
612     if (SvOK(sv)) {
613         value = SvNV(sv);
614         if (value < 0.0)
615             value = 0.0;
616         timebuf.tv_sec = (long)value;
617         value -= (double)timebuf.tv_sec;
618         timebuf.tv_usec = (long)(value * 1000000.0);
619     }
620     else
621         tbuf = Null(struct timeval*);
622
623     for (i = 1; i <= 3; i++) {
624         sv = SP[i];
625         if (!SvOK(sv)) {
626             fd_sets[i] = 0;
627             continue;
628         }
629         else if (!SvPOK(sv))
630             SvPV_force(sv,na);  /* force string conversion */
631         j = SvLEN(sv);
632         if (j < growsize) {
633             Sv_Grow(sv, growsize);
634         }
635         j = SvCUR(sv);
636         s = SvPVX(sv) + j;
637         while (++j <= growsize) {
638             *s++ = '\0';
639         }
640
641 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
642         s = SvPVX(sv);
643         New(403, fd_sets[i], growsize, char);
644         for (offset = 0; offset < growsize; offset += masksize) {
645             for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
646                 fd_sets[i][j+offset] = s[(k % masksize) + offset];
647         }
648 #else
649         fd_sets[i] = SvPVX(sv);
650 #endif
651     }
652
653     nfound = select(
654         maxlen * 8,
655         (Select_fd_set_t) fd_sets[1],
656         (Select_fd_set_t) fd_sets[2],
657         (Select_fd_set_t) fd_sets[3],
658         tbuf);
659     for (i = 1; i <= 3; i++) {
660         if (fd_sets[i]) {
661             sv = SP[i];
662 #if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
663             s = SvPVX(sv);
664             for (offset = 0; offset < growsize; offset += masksize) {
665                 for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
666                     s[(k % masksize) + offset] = fd_sets[i][j+offset];
667             }
668             Safefree(fd_sets[i]);
669 #endif
670             SvSETMAGIC(sv);
671         }
672     }
673
674     PUSHi(nfound);
675     if (GIMME == G_ARRAY && tbuf) {
676         value = (double)(timebuf.tv_sec) +
677                 (double)(timebuf.tv_usec) / 1000000.0;
678         PUSHs(sv = sv_mortalcopy(&sv_no));
679         sv_setnv(sv, value);
680     }
681     RETURN;
682 #else
683     DIE("select not implemented");
684 #endif
685 }
686
687 void
688 setdefout(gv)
689 GV *gv;
690 {
691     if (gv)
692         (void)SvREFCNT_inc(gv);
693     if (defoutgv)
694         SvREFCNT_dec(defoutgv);
695     defoutgv = gv;
696 }
697
698 PP(pp_select)
699 {
700     dSP; dTARGET;
701     GV *newdefout, *egv;
702     HV *hv;
703
704     newdefout = (op->op_private > 0) ? ((GV *) POPs) : NULL;
705
706     egv = GvEGV(defoutgv);
707     if (!egv)
708         egv = defoutgv;
709     hv = GvSTASH(egv);
710     if (! hv)
711         XPUSHs(&sv_undef);
712     else {
713         GV **gvp = hv_fetch(hv, GvNAME(egv), GvNAMELEN(egv), FALSE);
714         if (gvp && *gvp == egv)
715             gv_efullname(TARG, defoutgv);
716         else
717             sv_setsv(TARG, sv_2mortal(newRV(egv)));
718         XPUSHTARG;
719     }
720
721     if (newdefout) {
722         if (!GvIO(newdefout))
723             gv_IOadd(newdefout);
724         setdefout(newdefout);
725     }
726
727     RETURN;
728 }
729
730 PP(pp_getc)
731 {
732     dSP; dTARGET;
733     GV *gv;
734
735     if (MAXARG <= 0)
736         gv = stdingv;
737     else
738         gv = (GV*)POPs;
739     if (!gv)
740         gv = argvgv;
741     if (!gv || do_eof(gv)) /* make sure we have fp with something */
742         RETPUSHUNDEF;
743     TAINT_IF(1);
744     sv_setpv(TARG, " ");
745     *SvPVX(TARG) = getc(IoIFP(GvIOp(gv))); /* should never be EOF */
746     PUSHTARG;
747     RETURN;
748 }
749
750 PP(pp_read)
751 {
752     return pp_sysread(ARGS);
753 }
754
755 static OP *
756 doform(cv,gv,retop)
757 CV *cv;
758 GV *gv;
759 OP *retop;
760 {
761     register CONTEXT *cx;
762     I32 gimme = GIMME;
763     AV* padlist = CvPADLIST(cv);
764     SV** svp = AvARRAY(padlist);
765
766     ENTER;
767     SAVETMPS;
768
769     push_return(retop);
770     PUSHBLOCK(cx, CXt_SUB, stack_sp);
771     PUSHFORMAT(cx);
772     SAVESPTR(curpad);
773     curpad = AvARRAY((AV*)svp[1]);
774
775     setdefout(gv);          /* locally select filehandle so $% et al work */
776     return CvSTART(cv);
777 }
778
779 PP(pp_enterwrite)
780 {
781     dSP;
782     register GV *gv;
783     register IO *io;
784     GV *fgv;
785     CV *cv;
786
787     if (MAXARG == 0)
788         gv = defoutgv;
789     else {
790         gv = (GV*)POPs;
791         if (!gv)
792             gv = defoutgv;
793     }
794     EXTEND(SP, 1);
795     io = GvIO(gv);
796     if (!io) {
797         RETPUSHNO;
798     }
799     if (IoFMT_GV(io))
800         fgv = IoFMT_GV(io);
801     else
802         fgv = gv;
803
804     cv = GvFORM(fgv);
805
806     if (!cv) {
807         if (fgv) {
808             SV *tmpsv = sv_newmortal();
809             gv_efullname(tmpsv, gv);
810             DIE("Undefined format \"%s\" called",SvPVX(tmpsv));
811         }
812         DIE("Not a format reference");
813     }
814     IoFLAGS(io) &= ~IOf_DIDTOP;
815
816     return doform(cv,gv,op->op_next);
817 }
818
819 PP(pp_leavewrite)
820 {
821     dSP;
822     GV *gv = cxstack[cxstack_ix].blk_sub.gv;
823     register IO *io = GvIOp(gv);
824     FILE *ofp = IoOFP(io);
825     FILE *fp;
826     SV **newsp;
827     I32 gimme;
828     register CONTEXT *cx;
829
830     DEBUG_f(fprintf(stderr,"left=%ld, todo=%ld\n",
831           (long)IoLINES_LEFT(io), (long)FmLINES(formtarget)));
832     if (IoLINES_LEFT(io) < FmLINES(formtarget) &&
833         formtarget != toptarget)
834     {
835         GV *fgv;
836         CV *cv;
837         if (!IoTOP_GV(io)) {
838             GV *topgv;
839             char tmpbuf[256];
840
841             if (!IoTOP_NAME(io)) {
842                 if (!IoFMT_NAME(io))
843                     IoFMT_NAME(io) = savepv(GvNAME(gv));
844                 sprintf(tmpbuf, "%s_TOP", IoFMT_NAME(io));
845                 topgv = gv_fetchpv(tmpbuf,FALSE, SVt_PVFM);
846                 if ((topgv && GvFORM(topgv)) ||
847                   !gv_fetchpv("top",FALSE,SVt_PVFM))
848                     IoTOP_NAME(io) = savepv(tmpbuf);
849                 else
850                     IoTOP_NAME(io) = savepv("top");
851             }
852             topgv = gv_fetchpv(IoTOP_NAME(io),FALSE, SVt_PVFM);
853             if (!topgv || !GvFORM(topgv)) {
854                 IoLINES_LEFT(io) = 100000000;
855                 goto forget_top;
856             }
857             IoTOP_GV(io) = topgv;
858         }
859         if (IoFLAGS(io) & IOf_DIDTOP) { /* Oh dear.  It still doesn't fit. */
860             I32 lines = IoLINES_LEFT(io);
861             char *s = SvPVX(formtarget);
862             if (lines <= 0)             /* Yow, header didn't even fit!!! */
863                 goto forget_top;
864             while (lines-- > 0) {
865                 s = strchr(s, '\n');
866                 if (!s)
867                     break;
868                 s++;
869             }
870             if (s) {
871                 fwrite1(SvPVX(formtarget), s - SvPVX(formtarget), 1, ofp);
872                 sv_chop(formtarget, s);
873                 FmLINES(formtarget) -= IoLINES_LEFT(io);
874             }
875         }
876         if (IoLINES_LEFT(io) >= 0 && IoPAGE(io) > 0)
877             fwrite1(SvPVX(formfeed), SvCUR(formfeed), 1, ofp);
878         IoLINES_LEFT(io) = IoPAGE_LEN(io);
879         IoPAGE(io)++;
880         formtarget = toptarget;
881         IoFLAGS(io) |= IOf_DIDTOP;
882         fgv = IoTOP_GV(io);
883         if (!fgv)
884             DIE("bad top format reference");
885         cv = GvFORM(fgv);
886         if (!cv) {
887             SV *tmpsv = sv_newmortal();
888             gv_efullname(tmpsv, fgv);
889             DIE("Undefined top format \"%s\" called",SvPVX(tmpsv));
890         }
891         return doform(cv,gv,op);
892     }
893
894   forget_top:
895     POPBLOCK(cx,curpm);
896     POPFORMAT(cx);
897     LEAVE;
898
899     fp = IoOFP(io);
900     if (!fp) {
901         if (dowarn) {
902             if (IoIFP(io))
903                 warn("Filehandle only opened for input");
904             else
905                 warn("Write on closed filehandle");
906         }
907         PUSHs(&sv_no);
908     }
909     else {
910         if ((IoLINES_LEFT(io) -= FmLINES(formtarget)) < 0) {
911             if (dowarn)
912                 warn("page overflow");
913         }
914         if (!fwrite1(SvPVX(formtarget), 1, SvCUR(formtarget), ofp) ||
915                 ferror(fp))
916             PUSHs(&sv_no);
917         else {
918             FmLINES(formtarget) = 0;
919             SvCUR_set(formtarget, 0);
920             *SvEND(formtarget) = '\0';
921             if (IoFLAGS(io) & IOf_FLUSH)
922                 (void)Fflush(fp);
923             PUSHs(&sv_yes);
924         }
925     }
926     formtarget = bodytarget;
927     PUTBACK;
928     return pop_return();
929 }
930
931 PP(pp_prtf)
932 {
933     dSP; dMARK; dORIGMARK;
934     GV *gv;
935     IO *io;
936     FILE *fp;
937     SV *sv = NEWSV(0,0);
938
939     if (op->op_flags & OPf_STACKED)
940         gv = (GV*)*++MARK;
941     else
942         gv = defoutgv;
943     if (!(io = GvIO(gv))) {
944         if (dowarn) {
945             gv_fullname(sv,gv);
946             warn("Filehandle %s never opened", SvPV(sv,na));
947         }
948         SETERRNO(EBADF,RMS$_IFI);
949         goto just_say_no;
950     }
951     else if (!(fp = IoOFP(io))) {
952         if (dowarn)  {
953             gv_fullname(sv,gv);
954             if (IoIFP(io))
955                 warn("Filehandle %s opened only for input", SvPV(sv,na));
956             else
957                 warn("printf on closed filehandle %s", SvPV(sv,na));
958         }
959         SETERRNO(EBADF,IoIFP(io)?RMS$_FAC:RMS$_IFI);
960         goto just_say_no;
961     }
962     else {
963         do_sprintf(sv, SP - MARK, MARK + 1);
964         if (!do_print(sv, fp))
965             goto just_say_no;
966
967         if (IoFLAGS(io) & IOf_FLUSH)
968             if (Fflush(fp) == EOF)
969                 goto just_say_no;
970     }
971     SvREFCNT_dec(sv);
972     SP = ORIGMARK;
973     PUSHs(&sv_yes);
974     RETURN;
975
976   just_say_no:
977     SvREFCNT_dec(sv);
978     SP = ORIGMARK;
979     PUSHs(&sv_undef);
980     RETURN;
981 }
982
983 PP(pp_sysopen)
984 {
985     dSP;
986     GV *gv;
987     SV *sv;
988     char *tmps;
989     STRLEN len;
990     int mode, perm;
991
992     if (MAXARG > 3)
993         perm = POPi;
994     else
995         perm = 0666;
996     mode = POPi;
997     sv = POPs;
998     gv = (GV *)POPs;
999
1000     tmps = SvPV(sv, len);
1001     if (do_open(gv, tmps, len, TRUE, mode, perm, Nullfp)) {
1002         IoLINES(GvIOp(gv)) = 0;
1003         PUSHs(&sv_yes);
1004     }
1005     else {
1006         PUSHs(&sv_undef);
1007     }
1008     RETURN;
1009 }
1010
1011 PP(pp_sysread)
1012 {
1013     dSP; dMARK; dORIGMARK; dTARGET;
1014     int offset;
1015     GV *gv;
1016     IO *io;
1017     char *buffer;
1018     int length;
1019     int bufsize;
1020     SV *bufsv;
1021     STRLEN blen;
1022
1023     gv = (GV*)*++MARK;
1024     if (!gv)
1025         goto say_undef;
1026     bufsv = *++MARK;
1027     buffer = SvPV_force(bufsv, blen);
1028     length = SvIVx(*++MARK);
1029     if (length < 0)
1030         DIE("Negative length");
1031     SETERRNO(0,0);
1032     if (MARK < SP)
1033         offset = SvIVx(*++MARK);
1034     else
1035         offset = 0;
1036     io = GvIO(gv);
1037     if (!io || !IoIFP(io))
1038         goto say_undef;
1039 #ifdef HAS_SOCKET
1040     if (op->op_type == OP_RECV) {
1041         bufsize = sizeof buf;
1042         buffer = SvGROW(bufsv, length+1);
1043         length = recvfrom(fileno(IoIFP(io)), buffer, length, offset,
1044             (struct sockaddr *)buf, &bufsize);
1045         if (length < 0)
1046             RETPUSHUNDEF;
1047         SvCUR_set(bufsv, length);
1048         *SvEND(bufsv) = '\0';
1049         (void)SvPOK_only(bufsv);
1050         SvSETMAGIC(bufsv);
1051         if (tainting)
1052             sv_magic(bufsv, Nullsv, 't', Nullch, 0);
1053         SP = ORIGMARK;
1054         sv_setpvn(TARG, buf, bufsize);
1055         PUSHs(TARG);
1056         RETURN;
1057     }
1058 #else
1059     if (op->op_type == OP_RECV)
1060         DIE(no_sock_func, "recv");
1061 #endif
1062     buffer = SvGROW(bufsv, length+offset+1);
1063     if (op->op_type == OP_SYSREAD) {
1064         length = read(fileno(IoIFP(io)), buffer+offset, length);
1065     }
1066     else
1067 #ifdef HAS_SOCKET__bad_code_maybe
1068     if (IoTYPE(io) == 's') {
1069         bufsize = sizeof buf;
1070         length = recvfrom(fileno(IoIFP(io)), buffer+offset, length, 0,
1071             (struct sockaddr *)buf, &bufsize);
1072     }
1073     else
1074 #endif
1075         length = fread(buffer+offset, 1, length, IoIFP(io));
1076     if (length < 0)
1077         goto say_undef;
1078     SvCUR_set(bufsv, length+offset);
1079     *SvEND(bufsv) = '\0';
1080     (void)SvPOK_only(bufsv);
1081     SvSETMAGIC(bufsv);
1082     if (tainting)
1083         sv_magic(bufsv, Nullsv, 't', Nullch, 0);
1084     SP = ORIGMARK;
1085     PUSHi(length);
1086     RETURN;
1087
1088   say_undef:
1089     SP = ORIGMARK;
1090     RETPUSHUNDEF;
1091 }
1092
1093 PP(pp_syswrite)
1094 {
1095     return pp_send(ARGS);
1096 }
1097
1098 PP(pp_send)
1099 {
1100     dSP; dMARK; dORIGMARK; dTARGET;
1101     GV *gv;
1102     IO *io;
1103     int offset;
1104     SV *bufsv;
1105     char *buffer;
1106     int length;
1107     STRLEN blen;
1108
1109     gv = (GV*)*++MARK;
1110     if (!gv)
1111         goto say_undef;
1112     bufsv = *++MARK;
1113     buffer = SvPV(bufsv, blen);
1114     length = SvIVx(*++MARK);
1115     if (length < 0)
1116         DIE("Negative length");
1117     SETERRNO(0,0);
1118     io = GvIO(gv);
1119     if (!io || !IoIFP(io)) {
1120         length = -1;
1121         if (dowarn) {
1122             if (op->op_type == OP_SYSWRITE)
1123                 warn("Syswrite on closed filehandle");
1124             else
1125                 warn("Send on closed socket");
1126         }
1127     }
1128     else if (op->op_type == OP_SYSWRITE) {
1129         if (MARK < SP)
1130             offset = SvIVx(*++MARK);
1131         else
1132             offset = 0;
1133         if (length > blen - offset)
1134             length = blen - offset;
1135         length = write(fileno(IoIFP(io)), buffer+offset, length);
1136     }
1137 #ifdef HAS_SOCKET
1138     else if (SP > MARK) {
1139         char *sockbuf;
1140         STRLEN mlen;
1141         sockbuf = SvPVx(*++MARK, mlen);
1142         length = sendto(fileno(IoIFP(io)), buffer, blen, length,
1143                                 (struct sockaddr *)sockbuf, mlen);
1144     }
1145     else
1146         length = send(fileno(IoIFP(io)), buffer, blen, length);
1147 #else
1148     else
1149         DIE(no_sock_func, "send");
1150 #endif
1151     if (length < 0)
1152         goto say_undef;
1153     SP = ORIGMARK;
1154     PUSHi(length);
1155     RETURN;
1156
1157   say_undef:
1158     SP = ORIGMARK;
1159     RETPUSHUNDEF;
1160 }
1161
1162 PP(pp_recv)
1163 {
1164     return pp_sysread(ARGS);
1165 }
1166
1167 PP(pp_eof)
1168 {
1169     dSP;
1170     GV *gv;
1171
1172     if (MAXARG <= 0)
1173         gv = last_in_gv;
1174     else
1175         gv = last_in_gv = (GV*)POPs;
1176     PUSHs(!gv || do_eof(gv) ? &sv_yes : &sv_no);
1177     RETURN;
1178 }
1179
1180 PP(pp_tell)
1181 {
1182     dSP; dTARGET;
1183     GV *gv;
1184
1185     if (MAXARG <= 0)
1186         gv = last_in_gv;
1187     else
1188         gv = last_in_gv = (GV*)POPs;
1189     PUSHi( do_tell(gv) );
1190     RETURN;
1191 }
1192
1193 PP(pp_seek)
1194 {
1195     dSP;
1196     GV *gv;
1197     int whence = POPi;
1198     long offset = POPl;
1199
1200     gv = last_in_gv = (GV*)POPs;
1201     PUSHs( do_seek(gv, offset, whence) ? &sv_yes : &sv_no );
1202     RETURN;
1203 }
1204
1205 PP(pp_truncate)
1206 {
1207     dSP;
1208     Off_t len = (Off_t)POPn;
1209     int result = 1;
1210     GV *tmpgv;
1211
1212     SETERRNO(0,0);
1213 #if defined(HAS_TRUNCATE) || defined(HAS_CHSIZE) || defined(F_FREESP)
1214 #ifdef HAS_TRUNCATE
1215     if (op->op_flags & OPf_SPECIAL) {
1216         tmpgv = gv_fetchpv(POPp,FALSE, SVt_PVIO);
1217         if (!GvIO(tmpgv) || !IoIFP(GvIOp(tmpgv)) ||
1218           ftruncate(fileno(IoIFP(GvIOn(tmpgv))), len) < 0)
1219             result = 0;
1220     }
1221     else if (truncate(POPp, len) < 0)
1222         result = 0;
1223 #else
1224     if (op->op_flags & OPf_SPECIAL) {
1225         tmpgv = gv_fetchpv(POPp,FALSE, SVt_PVIO);
1226         if (!GvIO(tmpgv) || !IoIFP(GvIOp(tmpgv)) ||
1227           chsize(fileno(IoIFP(GvIOn(tmpgv))), len) < 0)
1228             result = 0;
1229     }
1230     else {
1231         int tmpfd;
1232
1233         if ((tmpfd = open(POPp, 0)) < 0)
1234             result = 0;
1235         else {
1236             if (chsize(tmpfd, len) < 0)
1237                 result = 0;
1238             close(tmpfd);
1239         }
1240     }
1241 #endif
1242
1243     if (result)
1244         RETPUSHYES;
1245     if (!errno)
1246         SETERRNO(EBADF,RMS$_IFI);
1247     RETPUSHUNDEF;
1248 #else
1249     DIE("truncate not implemented");
1250 #endif
1251 }
1252
1253 PP(pp_fcntl)
1254 {
1255     return pp_ioctl(ARGS);
1256 }
1257
1258 PP(pp_ioctl)
1259 {
1260     dSP; dTARGET;
1261     SV *argsv = POPs;
1262     unsigned int func = U_I(POPn);
1263     int optype = op->op_type;
1264     char *s;
1265     int retval;
1266     GV *gv = (GV*)POPs;
1267     IO *io = GvIOn(gv);
1268
1269     if (!io || !argsv || !IoIFP(io)) {
1270         SETERRNO(EBADF,RMS$_IFI);       /* well, sort of... */
1271         RETPUSHUNDEF;
1272     }
1273
1274     if (SvPOK(argsv) || !SvNIOK(argsv)) {
1275         STRLEN len;
1276         s = SvPV_force(argsv, len);
1277         retval = IOCPARM_LEN(func);
1278         if (len < retval) {
1279             s = Sv_Grow(argsv, retval+1);
1280             SvCUR_set(argsv, retval);
1281         }
1282
1283         s[SvCUR(argsv)] = 17;   /* a little sanity check here */
1284     }
1285     else {
1286         retval = SvIV(argsv);
1287 #ifdef DOSISH
1288         s = (char*)(long)retval;        /* ouch */
1289 #else
1290         s = (char*)retval;              /* ouch */
1291 #endif
1292     }
1293
1294     TAINT_PROPER(optype == OP_IOCTL ? "ioctl" : "fcntl");
1295
1296     if (optype == OP_IOCTL)
1297 #ifdef HAS_IOCTL
1298         retval = ioctl(fileno(IoIFP(io)), func, s);
1299 #else
1300         DIE("ioctl is not implemented");
1301 #endif
1302     else
1303 #if defined(DOSISH) && !defined(OS2)
1304         DIE("fcntl is not implemented");
1305 #else
1306 #   ifdef HAS_FCNTL
1307 #     if defined(OS2) && defined(__EMX__)
1308         retval = fcntl(fileno(IoIFP(io)), func, (int)s);
1309 #     else
1310         retval = fcntl(fileno(IoIFP(io)), func, s);
1311 #     endif 
1312 #   else
1313         DIE("fcntl is not implemented");
1314 #   endif
1315 #endif
1316
1317     if (SvPOK(argsv)) {
1318         if (s[SvCUR(argsv)] != 17)
1319             DIE("Possible memory corruption: %s overflowed 3rd argument",
1320                 op_name[optype]);
1321         s[SvCUR(argsv)] = 0;            /* put our null back */
1322         SvSETMAGIC(argsv);              /* Assume it has changed */
1323     }
1324
1325     if (retval == -1)
1326         RETPUSHUNDEF;
1327     if (retval != 0) {
1328         PUSHi(retval);
1329     }
1330     else {
1331         PUSHp("0 but true", 10);
1332     }
1333     RETURN;
1334 }
1335
1336 PP(pp_flock)
1337 {
1338     dSP; dTARGET;
1339     I32 value;
1340     int argtype;
1341     GV *gv;
1342     FILE *fp;
1343
1344 #if !defined(HAS_FLOCK) && defined(HAS_LOCKF)
1345 #  define flock lockf_emulate_flock
1346 #endif
1347
1348 #if defined(HAS_FLOCK) || defined(flock)
1349     argtype = POPi;
1350     if (MAXARG <= 0)
1351         gv = last_in_gv;
1352     else
1353         gv = (GV*)POPs;
1354     if (gv && GvIO(gv))
1355         fp = IoIFP(GvIOp(gv));
1356     else
1357         fp = Nullfp;
1358     if (fp) {
1359         value = (I32)(flock(fileno(fp), argtype) >= 0);
1360     }
1361     else
1362         value = 0;
1363     PUSHi(value);
1364     RETURN;
1365 #else
1366     DIE(no_func, "flock()");
1367 #endif
1368 }
1369
1370 /* Sockets. */
1371
1372 PP(pp_socket)
1373 {
1374     dSP;
1375 #ifdef HAS_SOCKET
1376     GV *gv;
1377     register IO *io;
1378     int protocol = POPi;
1379     int type = POPi;
1380     int domain = POPi;
1381     int fd;
1382
1383     gv = (GV*)POPs;
1384
1385     if (!gv) {
1386         SETERRNO(EBADF,LIB$_INVARG);
1387         RETPUSHUNDEF;
1388     }
1389
1390     io = GvIOn(gv);
1391     if (IoIFP(io))
1392         do_close(gv, FALSE);
1393
1394     TAINT_PROPER("socket");
1395     fd = socket(domain, type, protocol);
1396     if (fd < 0)
1397         RETPUSHUNDEF;
1398     IoIFP(io) = fdopen(fd, "r");        /* stdio gets confused about sockets */
1399     IoOFP(io) = fdopen(fd, "w");
1400     IoTYPE(io) = 's';
1401     if (!IoIFP(io) || !IoOFP(io)) {
1402         if (IoIFP(io)) fclose(IoIFP(io));
1403         if (IoOFP(io)) fclose(IoOFP(io));
1404         if (!IoIFP(io) && !IoOFP(io)) close(fd);
1405         RETPUSHUNDEF;
1406     }
1407
1408     RETPUSHYES;
1409 #else
1410     DIE(no_sock_func, "socket");
1411 #endif
1412 }
1413
1414 PP(pp_sockpair)
1415 {
1416     dSP;
1417 #ifdef HAS_SOCKETPAIR
1418     GV *gv1;
1419     GV *gv2;
1420     register IO *io1;
1421     register IO *io2;
1422     int protocol = POPi;
1423     int type = POPi;
1424     int domain = POPi;
1425     int fd[2];
1426
1427     gv2 = (GV*)POPs;
1428     gv1 = (GV*)POPs;
1429     if (!gv1 || !gv2)
1430         RETPUSHUNDEF;
1431
1432     io1 = GvIOn(gv1);
1433     io2 = GvIOn(gv2);
1434     if (IoIFP(io1))
1435         do_close(gv1, FALSE);
1436     if (IoIFP(io2))
1437         do_close(gv2, FALSE);
1438
1439     TAINT_PROPER("socketpair");
1440     if (socketpair(domain, type, protocol, fd) < 0)
1441         RETPUSHUNDEF;
1442     IoIFP(io1) = fdopen(fd[0], "r");
1443     IoOFP(io1) = fdopen(fd[0], "w");
1444     IoTYPE(io1) = 's';
1445     IoIFP(io2) = fdopen(fd[1], "r");
1446     IoOFP(io2) = fdopen(fd[1], "w");
1447     IoTYPE(io2) = 's';
1448     if (!IoIFP(io1) || !IoOFP(io1) || !IoIFP(io2) || !IoOFP(io2)) {
1449         if (IoIFP(io1)) fclose(IoIFP(io1));
1450         if (IoOFP(io1)) fclose(IoOFP(io1));
1451         if (!IoIFP(io1) && !IoOFP(io1)) close(fd[0]);
1452         if (IoIFP(io2)) fclose(IoIFP(io2));
1453         if (IoOFP(io2)) fclose(IoOFP(io2));
1454         if (!IoIFP(io2) && !IoOFP(io2)) close(fd[1]);
1455         RETPUSHUNDEF;
1456     }
1457
1458     RETPUSHYES;
1459 #else
1460     DIE(no_sock_func, "socketpair");
1461 #endif
1462 }
1463
1464 PP(pp_bind)
1465 {
1466     dSP;
1467 #ifdef HAS_SOCKET
1468     SV *addrsv = POPs;
1469     char *addr;
1470     GV *gv = (GV*)POPs;
1471     register IO *io = GvIOn(gv);
1472     STRLEN len;
1473
1474     if (!io || !IoIFP(io))
1475         goto nuts;
1476
1477     addr = SvPV(addrsv, len);
1478     TAINT_PROPER("bind");
1479     if (bind(fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0)
1480         RETPUSHYES;
1481     else
1482         RETPUSHUNDEF;
1483
1484 nuts:
1485     if (dowarn)
1486         warn("bind() on closed fd");
1487     SETERRNO(EBADF,SS$_IVCHAN);
1488     RETPUSHUNDEF;
1489 #else
1490     DIE(no_sock_func, "bind");
1491 #endif
1492 }
1493
1494 PP(pp_connect)
1495 {
1496     dSP;
1497 #ifdef HAS_SOCKET
1498     SV *addrsv = POPs;
1499     char *addr;
1500     GV *gv = (GV*)POPs;
1501     register IO *io = GvIOn(gv);
1502     STRLEN len;
1503
1504     if (!io || !IoIFP(io))
1505         goto nuts;
1506
1507     addr = SvPV(addrsv, len);
1508     TAINT_PROPER("connect");
1509     if (connect(fileno(IoIFP(io)), (struct sockaddr *)addr, len) >= 0)
1510         RETPUSHYES;
1511     else
1512         RETPUSHUNDEF;
1513
1514 nuts:
1515     if (dowarn)
1516         warn("connect() on closed fd");
1517     SETERRNO(EBADF,SS$_IVCHAN);
1518     RETPUSHUNDEF;
1519 #else
1520     DIE(no_sock_func, "connect");
1521 #endif
1522 }
1523
1524 PP(pp_listen)
1525 {
1526     dSP;
1527 #ifdef HAS_SOCKET
1528     int backlog = POPi;
1529     GV *gv = (GV*)POPs;
1530     register IO *io = GvIOn(gv);
1531
1532     if (!io || !IoIFP(io))
1533         goto nuts;
1534
1535     if (listen(fileno(IoIFP(io)), backlog) >= 0)
1536         RETPUSHYES;
1537     else
1538         RETPUSHUNDEF;
1539
1540 nuts:
1541     if (dowarn)
1542         warn("listen() on closed fd");
1543     SETERRNO(EBADF,SS$_IVCHAN);
1544     RETPUSHUNDEF;
1545 #else
1546     DIE(no_sock_func, "listen");
1547 #endif
1548 }
1549
1550 PP(pp_accept)
1551 {
1552     dSP; dTARGET;
1553 #ifdef HAS_SOCKET
1554     GV *ngv;
1555     GV *ggv;
1556     register IO *nstio;
1557     register IO *gstio;
1558     struct sockaddr saddr;      /* use a struct to avoid alignment problems */
1559     int len = sizeof saddr;
1560     int fd;
1561
1562     ggv = (GV*)POPs;
1563     ngv = (GV*)POPs;
1564
1565     if (!ngv)
1566         goto badexit;
1567     if (!ggv)
1568         goto nuts;
1569
1570     gstio = GvIO(ggv);
1571     if (!gstio || !IoIFP(gstio))
1572         goto nuts;
1573
1574     nstio = GvIOn(ngv);
1575     if (IoIFP(nstio))
1576         do_close(ngv, FALSE);
1577
1578     fd = accept(fileno(IoIFP(gstio)), (struct sockaddr *)&saddr, &len);
1579     if (fd < 0)
1580         goto badexit;
1581     IoIFP(nstio) = fdopen(fd, "r");
1582     IoOFP(nstio) = fdopen(fd, "w");
1583     IoTYPE(nstio) = 's';
1584     if (!IoIFP(nstio) || !IoOFP(nstio)) {
1585         if (IoIFP(nstio)) fclose(IoIFP(nstio));
1586         if (IoOFP(nstio)) fclose(IoOFP(nstio));
1587         if (!IoIFP(nstio) && !IoOFP(nstio)) close(fd);
1588         goto badexit;
1589     }
1590
1591     PUSHp((char *)&saddr, len);
1592     RETURN;
1593
1594 nuts:
1595     if (dowarn)
1596         warn("accept() on closed fd");
1597     SETERRNO(EBADF,SS$_IVCHAN);
1598
1599 badexit:
1600     RETPUSHUNDEF;
1601
1602 #else
1603     DIE(no_sock_func, "accept");
1604 #endif
1605 }
1606
1607 PP(pp_shutdown)
1608 {
1609     dSP; dTARGET;
1610 #ifdef HAS_SOCKET
1611     int how = POPi;
1612     GV *gv = (GV*)POPs;
1613     register IO *io = GvIOn(gv);
1614
1615     if (!io || !IoIFP(io))
1616         goto nuts;
1617
1618     PUSHi( shutdown(fileno(IoIFP(io)), how) >= 0 );
1619     RETURN;
1620
1621 nuts:
1622     if (dowarn)
1623         warn("shutdown() on closed fd");
1624     SETERRNO(EBADF,SS$_IVCHAN);
1625     RETPUSHUNDEF;
1626 #else
1627     DIE(no_sock_func, "shutdown");
1628 #endif
1629 }
1630
1631 PP(pp_gsockopt)
1632 {
1633 #ifdef HAS_SOCKET
1634     return pp_ssockopt(ARGS);
1635 #else
1636     DIE(no_sock_func, "getsockopt");
1637 #endif
1638 }
1639
1640 PP(pp_ssockopt)
1641 {
1642     dSP;
1643 #ifdef HAS_SOCKET
1644     int optype = op->op_type;
1645     SV *sv;
1646     int fd;
1647     unsigned int optname;
1648     unsigned int lvl;
1649     GV *gv;
1650     register IO *io;
1651     int aint;
1652
1653     if (optype == OP_GSOCKOPT)
1654         sv = sv_2mortal(NEWSV(22, 257));
1655     else
1656         sv = POPs;
1657     optname = (unsigned int) POPi;
1658     lvl = (unsigned int) POPi;
1659
1660     gv = (GV*)POPs;
1661     io = GvIOn(gv);
1662     if (!io || !IoIFP(io))
1663         goto nuts;
1664
1665     fd = fileno(IoIFP(io));
1666     switch (optype) {
1667     case OP_GSOCKOPT:
1668         SvGROW(sv, 257);
1669         (void)SvPOK_only(sv);
1670         SvCUR_set(sv,256);
1671         *SvEND(sv) ='\0';
1672         aint = SvCUR(sv);
1673         if (getsockopt(fd, lvl, optname, SvPVX(sv), &aint) < 0)
1674             goto nuts2;
1675         SvCUR_set(sv,aint);
1676         *SvEND(sv) ='\0';
1677         PUSHs(sv);
1678         break;
1679     case OP_SSOCKOPT: {
1680             STRLEN len = 0;
1681             char *buf = 0;
1682             if (SvPOKp(sv))
1683                 buf = SvPV(sv, len);
1684             else if (SvOK(sv)) {
1685                 aint = (int)SvIV(sv);
1686                 buf = (char*)&aint;
1687                 len = sizeof(int);
1688             }
1689             if (setsockopt(fd, lvl, optname, buf, (int)len) < 0)
1690                 goto nuts2;
1691             PUSHs(&sv_yes);
1692         }
1693         break;
1694     }
1695     RETURN;
1696
1697 nuts:
1698     if (dowarn)
1699         warn("[gs]etsockopt() on closed fd");
1700     SETERRNO(EBADF,SS$_IVCHAN);
1701 nuts2:
1702     RETPUSHUNDEF;
1703
1704 #else
1705     DIE(no_sock_func, "setsockopt");
1706 #endif
1707 }
1708
1709 PP(pp_getsockname)
1710 {
1711 #ifdef HAS_SOCKET
1712     return pp_getpeername(ARGS);
1713 #else
1714     DIE(no_sock_func, "getsockname");
1715 #endif
1716 }
1717
1718 PP(pp_getpeername)
1719 {
1720     dSP;
1721 #ifdef HAS_SOCKET
1722     int optype = op->op_type;
1723     SV *sv;
1724     int fd;
1725     GV *gv = (GV*)POPs;
1726     register IO *io = GvIOn(gv);
1727     int aint;
1728
1729     if (!io || !IoIFP(io))
1730         goto nuts;
1731
1732     sv = sv_2mortal(NEWSV(22, 257));
1733     (void)SvPOK_only(sv);
1734     SvCUR_set(sv,256);
1735     *SvEND(sv) ='\0';
1736     aint = SvCUR(sv);
1737     fd = fileno(IoIFP(io));
1738     switch (optype) {
1739     case OP_GETSOCKNAME:
1740         if (getsockname(fd, (struct sockaddr *)SvPVX(sv), &aint) < 0)
1741             goto nuts2;
1742         break;
1743     case OP_GETPEERNAME:
1744         if (getpeername(fd, (struct sockaddr *)SvPVX(sv), &aint) < 0)
1745             goto nuts2;
1746         break;
1747     }
1748     SvCUR_set(sv,aint);
1749     *SvEND(sv) ='\0';
1750     PUSHs(sv);
1751     RETURN;
1752
1753 nuts:
1754     if (dowarn)
1755         warn("get{sock, peer}name() on closed fd");
1756     SETERRNO(EBADF,SS$_IVCHAN);
1757 nuts2:
1758     RETPUSHUNDEF;
1759
1760 #else
1761     DIE(no_sock_func, "getpeername");
1762 #endif
1763 }
1764
1765 /* Stat calls. */
1766
1767 PP(pp_lstat)
1768 {
1769     return pp_stat(ARGS);
1770 }
1771
1772 PP(pp_stat)
1773 {
1774     dSP;
1775     GV *tmpgv;
1776     I32 max = 13;
1777
1778     if (op->op_flags & OPf_REF) {
1779         tmpgv = cGVOP->op_gv;
1780       do_fstat:
1781         if (tmpgv != defgv) {
1782             laststype = OP_STAT;
1783             statgv = tmpgv;
1784             sv_setpv(statname, "");
1785             if (!GvIO(tmpgv) || !IoIFP(GvIOp(tmpgv)) ||
1786               Fstat(fileno(IoIFP(GvIOn(tmpgv))), &statcache) < 0) {
1787                 max = 0;
1788                 laststatval = -1;
1789             }
1790         }
1791         else if (laststatval < 0)
1792             max = 0;
1793     }
1794     else {
1795         SV* sv = POPs;
1796         if (SvTYPE(sv) == SVt_PVGV) {
1797             tmpgv = (GV*)sv;
1798             goto do_fstat;
1799         }
1800         else if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVGV) {
1801             tmpgv = (GV*)SvRV(sv);
1802             goto do_fstat;
1803         }
1804         sv_setpv(statname, SvPV(sv,na));
1805         statgv = Nullgv;
1806 #ifdef HAS_LSTAT
1807         laststype = op->op_type;
1808         if (op->op_type == OP_LSTAT)
1809             laststatval = lstat(SvPV(statname, na), &statcache);
1810         else
1811 #endif
1812             laststatval = Stat(SvPV(statname, na), &statcache);
1813         if (laststatval < 0) {
1814             if (dowarn && strchr(SvPV(statname, na), '\n'))
1815                 warn(warn_nl, "stat");
1816             max = 0;
1817         }
1818     }
1819
1820     EXTEND(SP, 13);
1821     if (GIMME != G_ARRAY) {
1822         if (max)
1823             RETPUSHYES;
1824         else
1825             RETPUSHUNDEF;
1826     }
1827     if (max) {
1828         PUSHs(sv_2mortal(newSViv((I32)statcache.st_dev)));
1829         PUSHs(sv_2mortal(newSViv((I32)statcache.st_ino)));
1830         PUSHs(sv_2mortal(newSViv((I32)statcache.st_mode)));
1831         PUSHs(sv_2mortal(newSViv((I32)statcache.st_nlink)));
1832         PUSHs(sv_2mortal(newSViv((I32)statcache.st_uid)));
1833         PUSHs(sv_2mortal(newSViv((I32)statcache.st_gid)));
1834         PUSHs(sv_2mortal(newSViv((I32)statcache.st_rdev)));
1835         PUSHs(sv_2mortal(newSViv((I32)statcache.st_size)));
1836         PUSHs(sv_2mortal(newSViv((I32)statcache.st_atime)));
1837         PUSHs(sv_2mortal(newSViv((I32)statcache.st_mtime)));
1838         PUSHs(sv_2mortal(newSViv((I32)statcache.st_ctime)));
1839 #ifdef USE_STAT_BLOCKS
1840         PUSHs(sv_2mortal(newSViv((I32)statcache.st_blksize)));
1841         PUSHs(sv_2mortal(newSViv((I32)statcache.st_blocks)));
1842 #else
1843         PUSHs(sv_2mortal(newSVpv("", 0)));
1844         PUSHs(sv_2mortal(newSVpv("", 0)));
1845 #endif
1846     }
1847     RETURN;
1848 }
1849
1850 PP(pp_ftrread)
1851 {
1852     I32 result = my_stat(ARGS);
1853     dSP;
1854     if (result < 0)
1855         RETPUSHUNDEF;
1856     if (cando(S_IRUSR, 0, &statcache))
1857         RETPUSHYES;
1858     RETPUSHNO;
1859 }
1860
1861 PP(pp_ftrwrite)
1862 {
1863     I32 result = my_stat(ARGS);
1864     dSP;
1865     if (result < 0)
1866         RETPUSHUNDEF;
1867     if (cando(S_IWUSR, 0, &statcache))
1868         RETPUSHYES;
1869     RETPUSHNO;
1870 }
1871
1872 PP(pp_ftrexec)
1873 {
1874     I32 result = my_stat(ARGS);
1875     dSP;
1876     if (result < 0)
1877         RETPUSHUNDEF;
1878     if (cando(S_IXUSR, 0, &statcache))
1879         RETPUSHYES;
1880     RETPUSHNO;
1881 }
1882
1883 PP(pp_fteread)
1884 {
1885     I32 result = my_stat(ARGS);
1886     dSP;
1887     if (result < 0)
1888         RETPUSHUNDEF;
1889     if (cando(S_IRUSR, 1, &statcache))
1890         RETPUSHYES;
1891     RETPUSHNO;
1892 }
1893
1894 PP(pp_ftewrite)
1895 {
1896     I32 result = my_stat(ARGS);
1897     dSP;
1898     if (result < 0)
1899         RETPUSHUNDEF;
1900     if (cando(S_IWUSR, 1, &statcache))
1901         RETPUSHYES;
1902     RETPUSHNO;
1903 }
1904
1905 PP(pp_fteexec)
1906 {
1907     I32 result = my_stat(ARGS);
1908     dSP;
1909     if (result < 0)
1910         RETPUSHUNDEF;
1911     if (cando(S_IXUSR, 1, &statcache))
1912         RETPUSHYES;
1913     RETPUSHNO;
1914 }
1915
1916 PP(pp_ftis)
1917 {
1918     I32 result = my_stat(ARGS);
1919     dSP;
1920     if (result < 0)
1921         RETPUSHUNDEF;
1922     RETPUSHYES;
1923 }
1924
1925 PP(pp_fteowned)
1926 {
1927     return pp_ftrowned(ARGS);
1928 }
1929
1930 PP(pp_ftrowned)
1931 {
1932     I32 result = my_stat(ARGS);
1933     dSP;
1934     if (result < 0)
1935         RETPUSHUNDEF;
1936     if (statcache.st_uid == (op->op_type == OP_FTEOWNED ? euid : uid) )
1937         RETPUSHYES;
1938     RETPUSHNO;
1939 }
1940
1941 PP(pp_ftzero)
1942 {
1943     I32 result = my_stat(ARGS);
1944     dSP;
1945     if (result < 0)
1946         RETPUSHUNDEF;
1947     if (!statcache.st_size)
1948         RETPUSHYES;
1949     RETPUSHNO;
1950 }
1951
1952 PP(pp_ftsize)
1953 {
1954     I32 result = my_stat(ARGS);
1955     dSP; dTARGET;
1956     if (result < 0)
1957         RETPUSHUNDEF;
1958     PUSHi(statcache.st_size);
1959     RETURN;
1960 }
1961
1962 PP(pp_ftmtime)
1963 {
1964     I32 result = my_stat(ARGS);
1965     dSP; dTARGET;
1966     if (result < 0)
1967         RETPUSHUNDEF;
1968     PUSHn( (basetime - statcache.st_mtime) / 86400.0 );
1969     RETURN;
1970 }
1971
1972 PP(pp_ftatime)
1973 {
1974     I32 result = my_stat(ARGS);
1975     dSP; dTARGET;
1976     if (result < 0)
1977         RETPUSHUNDEF;
1978     PUSHn( (basetime - statcache.st_atime) / 86400.0 );
1979     RETURN;
1980 }
1981
1982 PP(pp_ftctime)
1983 {
1984     I32 result = my_stat(ARGS);
1985     dSP; dTARGET;
1986     if (result < 0)
1987         RETPUSHUNDEF;
1988     PUSHn( (basetime - statcache.st_ctime) / 86400.0 );
1989     RETURN;
1990 }
1991
1992 PP(pp_ftsock)
1993 {
1994     I32 result = my_stat(ARGS);
1995     dSP;
1996     if (result < 0)
1997         RETPUSHUNDEF;
1998     if (S_ISSOCK(statcache.st_mode))
1999         RETPUSHYES;
2000     RETPUSHNO;
2001 }
2002
2003 PP(pp_ftchr)
2004 {
2005     I32 result = my_stat(ARGS);
2006     dSP;
2007     if (result < 0)
2008         RETPUSHUNDEF;
2009     if (S_ISCHR(statcache.st_mode))
2010         RETPUSHYES;
2011     RETPUSHNO;
2012 }
2013
2014 PP(pp_ftblk)
2015 {
2016     I32 result = my_stat(ARGS);
2017     dSP;
2018     if (result < 0)
2019         RETPUSHUNDEF;
2020     if (S_ISBLK(statcache.st_mode))
2021         RETPUSHYES;
2022     RETPUSHNO;
2023 }
2024
2025 PP(pp_ftfile)
2026 {
2027     I32 result = my_stat(ARGS);
2028     dSP;
2029     if (result < 0)
2030         RETPUSHUNDEF;
2031     if (S_ISREG(statcache.st_mode))
2032         RETPUSHYES;
2033     RETPUSHNO;
2034 }
2035
2036 PP(pp_ftdir)
2037 {
2038     I32 result = my_stat(ARGS);
2039     dSP;
2040     if (result < 0)
2041         RETPUSHUNDEF;
2042     if (S_ISDIR(statcache.st_mode))
2043         RETPUSHYES;
2044     RETPUSHNO;
2045 }
2046
2047 PP(pp_ftpipe)
2048 {
2049     I32 result = my_stat(ARGS);
2050     dSP;
2051     if (result < 0)
2052         RETPUSHUNDEF;
2053     if (S_ISFIFO(statcache.st_mode))
2054         RETPUSHYES;
2055     RETPUSHNO;
2056 }
2057
2058 PP(pp_ftlink)
2059 {
2060     I32 result = my_lstat(ARGS);
2061     dSP;
2062     if (result < 0)
2063         RETPUSHUNDEF;
2064     if (S_ISLNK(statcache.st_mode))
2065         RETPUSHYES;
2066     RETPUSHNO;
2067 }
2068
2069 PP(pp_ftsuid)
2070 {
2071     dSP;
2072 #ifdef S_ISUID
2073     I32 result = my_stat(ARGS);
2074     SPAGAIN;
2075     if (result < 0)
2076         RETPUSHUNDEF;
2077     if (statcache.st_mode & S_ISUID)
2078         RETPUSHYES;
2079 #endif
2080     RETPUSHNO;
2081 }
2082
2083 PP(pp_ftsgid)
2084 {
2085     dSP;
2086 #ifdef S_ISGID
2087     I32 result = my_stat(ARGS);
2088     SPAGAIN;
2089     if (result < 0)
2090         RETPUSHUNDEF;
2091     if (statcache.st_mode & S_ISGID)
2092         RETPUSHYES;
2093 #endif
2094     RETPUSHNO;
2095 }
2096
2097 PP(pp_ftsvtx)
2098 {
2099     dSP;
2100 #ifdef S_ISVTX
2101     I32 result = my_stat(ARGS);
2102     SPAGAIN;
2103     if (result < 0)
2104         RETPUSHUNDEF;
2105     if (statcache.st_mode & S_ISVTX)
2106         RETPUSHYES;
2107 #endif
2108     RETPUSHNO;
2109 }
2110
2111 PP(pp_fttty)
2112 {
2113     dSP;
2114     int fd;
2115     GV *gv;
2116     char *tmps;
2117     if (op->op_flags & OPf_REF) {
2118         gv = cGVOP->op_gv;
2119         tmps = "";
2120     }
2121     else
2122         gv = gv_fetchpv(tmps = POPp, FALSE, SVt_PVIO);
2123     if (GvIO(gv) && IoIFP(GvIOp(gv)))
2124         fd = fileno(IoIFP(GvIOp(gv)));
2125     else if (isDIGIT(*tmps))
2126         fd = atoi(tmps);
2127     else
2128         RETPUSHUNDEF;
2129     if (isatty(fd))
2130         RETPUSHYES;
2131     RETPUSHNO;
2132 }
2133
2134 #if defined(atarist) /* this will work with atariST. Configure will
2135                         make guesses for other systems. */
2136 # define FILE_base(f) ((f)->_base)
2137 # define FILE_ptr(f) ((f)->_ptr)
2138 # define FILE_cnt(f) ((f)->_cnt)
2139 # define FILE_bufsiz(f) ((f)->_cnt + ((f)->_ptr - (f)->_base))
2140 #endif
2141
2142 PP(pp_fttext)
2143 {
2144     dSP;
2145     I32 i;
2146     I32 len;
2147     I32 odd = 0;
2148     STDCHAR tbuf[512];
2149     register STDCHAR *s;
2150     register IO *io;
2151     SV *sv;
2152
2153     if (op->op_flags & OPf_REF) {
2154         EXTEND(SP, 1);
2155         if (cGVOP->op_gv == defgv) {
2156             if (statgv)
2157                 io = GvIO(statgv);
2158             else {
2159                 sv = statname;
2160                 goto really_filename;
2161             }
2162         }
2163         else {
2164             statgv = cGVOP->op_gv;
2165             sv_setpv(statname, "");
2166             io = GvIO(statgv);
2167         }
2168         if (io && IoIFP(io)) {
2169 #ifdef FILE_base
2170             Fstat(fileno(IoIFP(io)), &statcache);
2171             if (S_ISDIR(statcache.st_mode))     /* handle NFS glitch */
2172                 if (op->op_type == OP_FTTEXT)
2173                     RETPUSHNO;
2174                 else
2175                     RETPUSHYES;
2176             if (FILE_cnt(IoIFP(io)) <= 0) {
2177                 i = getc(IoIFP(io));
2178                 if (i != EOF)
2179                     (void)ungetc(i, IoIFP(io));
2180             }
2181             if (FILE_cnt(IoIFP(io)) <= 0)       /* null file is anything */
2182                 RETPUSHYES;
2183             len = FILE_bufsiz(IoIFP(io));
2184             s = FILE_base(IoIFP(io));
2185 #else
2186             DIE("-T and -B not implemented on filehandles");
2187 #endif
2188         }
2189         else {
2190             if (dowarn)
2191                 warn("Test on unopened file <%s>",
2192                   GvENAME(cGVOP->op_gv));
2193             SETERRNO(EBADF,RMS$_IFI);
2194             RETPUSHUNDEF;
2195         }
2196     }
2197     else {
2198         sv = POPs;
2199         statgv = Nullgv;
2200         sv_setpv(statname, SvPV(sv, na));
2201       really_filename:
2202 #ifdef HAS_OPEN3
2203         i = open(SvPV(sv, na), O_RDONLY, 0);
2204 #else
2205         i = open(SvPV(sv, na), 0);
2206 #endif
2207         if (i < 0) {
2208             if (dowarn && strchr(SvPV(sv, na), '\n'))
2209                 warn(warn_nl, "open");
2210             RETPUSHUNDEF;
2211         }
2212         Fstat(i, &statcache);
2213         len = read(i, tbuf, 512);
2214         (void)close(i);
2215         if (len <= 0) {
2216             if (S_ISDIR(statcache.st_mode) && op->op_type == OP_FTTEXT)
2217                 RETPUSHNO;              /* special case NFS directories */
2218             RETPUSHYES;         /* null file is anything */
2219         }
2220         s = tbuf;
2221     }
2222
2223     /* now scan s to look for textiness */
2224     /*   XXX ASCII dependent code */
2225
2226     for (i = 0; i < len; i++, s++) {
2227         if (!*s) {                      /* null never allowed in text */
2228             odd += len;
2229             break;
2230         }
2231         else if (*s & 128)
2232             odd++;
2233         else if (*s < 32 &&
2234           *s != '\n' && *s != '\r' && *s != '\b' &&
2235           *s != '\t' && *s != '\f' && *s != 27)
2236             odd++;
2237     }
2238
2239     if ((odd * 3 > len) == (op->op_type == OP_FTTEXT)) /* allow 1/3 odd */
2240         RETPUSHNO;
2241     else
2242         RETPUSHYES;
2243 }
2244
2245 PP(pp_ftbinary)
2246 {
2247     return pp_fttext(ARGS);
2248 }
2249
2250 /* File calls. */
2251
2252 PP(pp_chdir)
2253 {
2254     dSP; dTARGET;
2255     char *tmps;
2256     SV **svp;
2257
2258     if (MAXARG < 1)
2259         tmps = Nullch;
2260     else
2261         tmps = POPp;
2262     if (!tmps || !*tmps) {
2263         svp = hv_fetch(GvHVn(envgv), "HOME", 4, FALSE);
2264         if (svp)
2265             tmps = SvPV(*svp, na);
2266     }
2267     if (!tmps || !*tmps) {
2268         svp = hv_fetch(GvHVn(envgv), "LOGDIR", 6, FALSE);
2269         if (svp)
2270             tmps = SvPV(*svp, na);
2271     }
2272     TAINT_PROPER("chdir");
2273     PUSHi( chdir(tmps) >= 0 );
2274 #ifdef VMS
2275     /* Clear the DEFAULT element of ENV so we'll get the new value
2276      * in the future. */
2277     hv_delete(GvHVn(envgv),"DEFAULT",7,G_DISCARD);
2278 #endif
2279     RETURN;
2280 }
2281
2282 PP(pp_chown)
2283 {
2284     dSP; dMARK; dTARGET;
2285     I32 value;
2286 #ifdef HAS_CHOWN
2287     value = (I32)apply(op->op_type, MARK, SP);
2288     SP = MARK;
2289     PUSHi(value);
2290     RETURN;
2291 #else
2292     DIE(no_func, "Unsupported function chown");
2293 #endif
2294 }
2295
2296 PP(pp_chroot)
2297 {
2298     dSP; dTARGET;
2299     char *tmps;
2300 #ifdef HAS_CHROOT
2301     tmps = POPp;
2302     TAINT_PROPER("chroot");
2303     PUSHi( chroot(tmps) >= 0 );
2304     RETURN;
2305 #else
2306     DIE(no_func, "chroot");
2307 #endif
2308 }
2309
2310 PP(pp_unlink)
2311 {
2312     dSP; dMARK; dTARGET;
2313     I32 value;
2314     value = (I32)apply(op->op_type, MARK, SP);
2315     SP = MARK;
2316     PUSHi(value);
2317     RETURN;
2318 }
2319
2320 PP(pp_chmod)
2321 {
2322     dSP; dMARK; dTARGET;
2323     I32 value;
2324     value = (I32)apply(op->op_type, MARK, SP);
2325     SP = MARK;
2326     PUSHi(value);
2327     RETURN;
2328 }
2329
2330 PP(pp_utime)
2331 {
2332     dSP; dMARK; dTARGET;
2333     I32 value;
2334     value = (I32)apply(op->op_type, MARK, SP);
2335     SP = MARK;
2336     PUSHi(value);
2337     RETURN;
2338 }
2339
2340 PP(pp_rename)
2341 {
2342     dSP; dTARGET;
2343     int anum;
2344
2345     char *tmps2 = POPp;
2346     char *tmps = SvPV(TOPs, na);
2347     TAINT_PROPER("rename");
2348 #ifdef HAS_RENAME
2349     anum = rename(tmps, tmps2);
2350 #else
2351     if (same_dirent(tmps2, tmps))       /* can always rename to same name */
2352         anum = 1;
2353     else {
2354         if (euid || Stat(tmps2, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
2355             (void)UNLINK(tmps2);
2356         if (!(anum = link(tmps, tmps2)))
2357             anum = UNLINK(tmps);
2358     }
2359 #endif
2360     SETi( anum >= 0 );
2361     RETURN;
2362 }
2363
2364 PP(pp_link)
2365 {
2366     dSP; dTARGET;
2367 #ifdef HAS_LINK
2368     char *tmps2 = POPp;
2369     char *tmps = SvPV(TOPs, na);
2370     TAINT_PROPER("link");
2371     SETi( link(tmps, tmps2) >= 0 );
2372 #else
2373     DIE(no_func, "Unsupported function link");
2374 #endif
2375     RETURN;
2376 }
2377
2378 PP(pp_symlink)
2379 {
2380     dSP; dTARGET;
2381 #ifdef HAS_SYMLINK
2382     char *tmps2 = POPp;
2383     char *tmps = SvPV(TOPs, na);
2384     TAINT_PROPER("symlink");
2385     SETi( symlink(tmps, tmps2) >= 0 );
2386     RETURN;
2387 #else
2388     DIE(no_func, "symlink");
2389 #endif
2390 }
2391
2392 PP(pp_readlink)
2393 {
2394     dSP; dTARGET;
2395 #ifdef HAS_SYMLINK
2396     char *tmps;
2397     int len;
2398     tmps = POPp;
2399     len = readlink(tmps, buf, sizeof buf);
2400     EXTEND(SP, 1);
2401     if (len < 0)
2402         RETPUSHUNDEF;
2403     PUSHp(buf, len);
2404     RETURN;
2405 #else
2406     EXTEND(SP, 1);
2407     RETSETUNDEF;                /* just pretend it's a normal file */
2408 #endif
2409 }
2410
2411 #if !defined(HAS_MKDIR) || !defined(HAS_RMDIR)
2412 static int
2413 dooneliner(cmd, filename)
2414 char *cmd;
2415 char *filename;
2416 {
2417     char mybuf[8192];
2418     char *s,
2419          *save_filename = filename;
2420     int anum = 1;
2421     FILE *myfp;
2422
2423     strcpy(mybuf, cmd);
2424     strcat(mybuf, " ");
2425     for (s = mybuf+strlen(mybuf); *filename; ) {
2426         *s++ = '\\';
2427         *s++ = *filename++;
2428     }
2429     strcpy(s, " 2>&1");
2430     myfp = my_popen(mybuf, "r");
2431     if (myfp) {
2432         *mybuf = '\0';
2433         s = fgets(mybuf, sizeof mybuf, myfp);
2434         (void)my_pclose(myfp);
2435         if (s != Nullch) {
2436             for (errno = 1; errno < sys_nerr; errno++) {
2437 #ifdef HAS_SYS_ERRLIST
2438                 if (instr(mybuf, sys_errlist[errno]))   /* you don't see this */
2439                     return 0;
2440 #else
2441                 char *errmsg;                           /* especially if it isn't there */
2442
2443                 if (instr(mybuf,
2444                           (errmsg = strerror(errno)) ? errmsg : "NoErRoR"))
2445                     return 0;
2446 #endif
2447             }
2448             SETERRNO(0,0);
2449 #ifndef EACCES
2450 #define EACCES EPERM
2451 #endif
2452             if (instr(mybuf, "cannot make"))
2453                 SETERRNO(EEXIST,RMS$_FEX);
2454             else if (instr(mybuf, "existing file"))
2455                 SETERRNO(EEXIST,RMS$_FEX);
2456             else if (instr(mybuf, "ile exists"))
2457                 SETERRNO(EEXIST,RMS$_FEX);
2458             else if (instr(mybuf, "non-exist"))
2459                 SETERRNO(ENOENT,RMS$_FNF);
2460             else if (instr(mybuf, "does not exist"))
2461                 SETERRNO(ENOENT,RMS$_FNF);
2462             else if (instr(mybuf, "not empty"))
2463                 SETERRNO(EBUSY,SS$_DEVOFFLINE);
2464             else if (instr(mybuf, "cannot access"))
2465                 SETERRNO(EACCES,RMS$_PRV);
2466             else
2467                 SETERRNO(EPERM,RMS$_PRV);
2468             return 0;
2469         }
2470         else {  /* some mkdirs return no failure indication */
2471             anum = (Stat(save_filename, &statbuf) >= 0);
2472             if (op->op_type == OP_RMDIR)
2473                 anum = !anum;
2474             if (anum)
2475                 SETERRNO(0,0);
2476             else
2477                 SETERRNO(EACCES,RMS$_PRV);      /* a guess */
2478         }
2479         return anum;
2480     }
2481     else
2482         return 0;
2483 }
2484 #endif
2485
2486 PP(pp_mkdir)
2487 {
2488     dSP; dTARGET;
2489     int mode = POPi;
2490 #ifndef HAS_MKDIR
2491     int oldumask;
2492 #endif
2493     char *tmps = SvPV(TOPs, na);
2494
2495     TAINT_PROPER("mkdir");
2496 #ifdef HAS_MKDIR
2497     SETi( mkdir(tmps, mode) >= 0 );
2498 #else
2499     SETi( dooneliner("mkdir", tmps) );
2500     oldumask = umask(0);
2501     umask(oldumask);
2502     chmod(tmps, (mode & ~oldumask) & 0777);
2503 #endif
2504     RETURN;
2505 }
2506
2507 PP(pp_rmdir)
2508 {
2509     dSP; dTARGET;
2510     char *tmps;
2511
2512     tmps = POPp;
2513     TAINT_PROPER("rmdir");
2514 #ifdef HAS_RMDIR
2515     XPUSHi( rmdir(tmps) >= 0 );
2516 #else
2517     XPUSHi( dooneliner("rmdir", tmps) );
2518 #endif
2519     RETURN;
2520 }
2521
2522 /* Directory calls. */
2523
2524 PP(pp_open_dir)
2525 {
2526     dSP;
2527 #if defined(Direntry_t) && defined(HAS_READDIR)
2528     char *dirname = POPp;
2529     GV *gv = (GV*)POPs;
2530     register IO *io = GvIOn(gv);
2531
2532     if (!io)
2533         goto nope;
2534
2535     if (IoDIRP(io))
2536         closedir(IoDIRP(io));
2537     if (!(IoDIRP(io) = opendir(dirname)))
2538         goto nope;
2539
2540     RETPUSHYES;
2541 nope:
2542     if (!errno)
2543         SETERRNO(EBADF,RMS$_DIR);
2544     RETPUSHUNDEF;
2545 #else
2546     DIE(no_dir_func, "opendir");
2547 #endif
2548 }
2549
2550 PP(pp_readdir)
2551 {
2552     dSP;
2553 #if defined(Direntry_t) && defined(HAS_READDIR)
2554 #ifndef I_DIRENT
2555     Direntry_t *readdir _((DIR *));
2556 #endif
2557     register Direntry_t *dp;
2558     GV *gv = (GV*)POPs;
2559     register IO *io = GvIOn(gv);
2560
2561     if (!io || !IoDIRP(io))
2562         goto nope;
2563
2564     if (GIMME == G_ARRAY) {
2565         /*SUPPRESS 560*/
2566         while (dp = (Direntry_t *)readdir(IoDIRP(io))) {
2567 #ifdef DIRNAMLEN
2568             XPUSHs(sv_2mortal(newSVpv(dp->d_name, dp->d_namlen)));
2569 #else
2570             XPUSHs(sv_2mortal(newSVpv(dp->d_name, 0)));
2571 #endif
2572         }
2573     }
2574     else {
2575         if (!(dp = (Direntry_t *)readdir(IoDIRP(io))))
2576             goto nope;
2577 #ifdef DIRNAMLEN
2578         XPUSHs(sv_2mortal(newSVpv(dp->d_name, dp->d_namlen)));
2579 #else
2580         XPUSHs(sv_2mortal(newSVpv(dp->d_name, 0)));
2581 #endif
2582     }
2583     RETURN;
2584
2585 nope:
2586     if (!errno)
2587         SETERRNO(EBADF,RMS$_ISI);
2588     if (GIMME == G_ARRAY)
2589         RETURN;
2590     else
2591         RETPUSHUNDEF;
2592 #else
2593     DIE(no_dir_func, "readdir");
2594 #endif
2595 }
2596
2597 PP(pp_telldir)
2598 {
2599     dSP; dTARGET;
2600 #if defined(HAS_TELLDIR) || defined(telldir)
2601 #if !defined(telldir) && !defined(HAS_TELLDIR_PROTOTYPE)
2602     long telldir _((DIR *));
2603 #endif
2604     GV *gv = (GV*)POPs;
2605     register IO *io = GvIOn(gv);
2606
2607     if (!io || !IoDIRP(io))
2608         goto nope;
2609
2610     PUSHi( telldir(IoDIRP(io)) );
2611     RETURN;
2612 nope:
2613     if (!errno)
2614         SETERRNO(EBADF,RMS$_ISI);
2615     RETPUSHUNDEF;
2616 #else
2617     DIE(no_dir_func, "telldir");
2618 #endif
2619 }
2620
2621 PP(pp_seekdir)
2622 {
2623     dSP;
2624 #if defined(HAS_SEEKDIR) || defined(seekdir)
2625     long along = POPl;
2626     GV *gv = (GV*)POPs;
2627     register IO *io = GvIOn(gv);
2628
2629     if (!io || !IoDIRP(io))
2630         goto nope;
2631
2632     (void)seekdir(IoDIRP(io), along);
2633
2634     RETPUSHYES;
2635 nope:
2636     if (!errno)
2637         SETERRNO(EBADF,RMS$_ISI);
2638     RETPUSHUNDEF;
2639 #else
2640     DIE(no_dir_func, "seekdir");
2641 #endif
2642 }
2643
2644 PP(pp_rewinddir)
2645 {
2646     dSP;
2647 #if defined(HAS_REWINDDIR) || defined(rewinddir)
2648     GV *gv = (GV*)POPs;
2649     register IO *io = GvIOn(gv);
2650
2651     if (!io || !IoDIRP(io))
2652         goto nope;
2653
2654     (void)rewinddir(IoDIRP(io));
2655     RETPUSHYES;
2656 nope:
2657     if (!errno)
2658         SETERRNO(EBADF,RMS$_ISI);
2659     RETPUSHUNDEF;
2660 #else
2661     DIE(no_dir_func, "rewinddir");
2662 #endif
2663 }
2664
2665 PP(pp_closedir)
2666 {
2667     dSP;
2668 #if defined(Direntry_t) && defined(HAS_READDIR)
2669     GV *gv = (GV*)POPs;
2670     register IO *io = GvIOn(gv);
2671
2672     if (!io || !IoDIRP(io))
2673         goto nope;
2674
2675 #ifdef VOID_CLOSEDIR
2676     closedir(IoDIRP(io));
2677 #else
2678     if (closedir(IoDIRP(io)) < 0) {
2679         IoDIRP(io) = 0; /* Don't try to close again--coredumps on SysV */
2680         goto nope;
2681     }
2682 #endif
2683     IoDIRP(io) = 0;
2684
2685     RETPUSHYES;
2686 nope:
2687     if (!errno)
2688         SETERRNO(EBADF,RMS$_IFI);
2689     RETPUSHUNDEF;
2690 #else
2691     DIE(no_dir_func, "closedir");
2692 #endif
2693 }
2694
2695 /* Process control. */
2696
2697 PP(pp_fork)
2698 {
2699     dSP; dTARGET;
2700     int childpid;
2701     GV *tmpgv;
2702
2703     EXTEND(SP, 1);
2704 #ifdef HAS_FORK
2705     childpid = fork();
2706     if (childpid < 0)
2707         RETSETUNDEF;
2708     if (!childpid) {
2709         /*SUPPRESS 560*/
2710         if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV))
2711             sv_setiv(GvSV(tmpgv), (I32)getpid());
2712         hv_clear(pidstatus);    /* no kids, so don't wait for 'em */
2713     }
2714     PUSHi(childpid);
2715     RETURN;
2716 #else
2717     DIE(no_func, "Unsupported function fork");
2718 #endif
2719 }
2720
2721 PP(pp_wait)
2722 {
2723     dSP; dTARGET;
2724     int childpid;
2725     int argflags;
2726     I32 value;
2727
2728     EXTEND(SP, 1);
2729 #ifdef HAS_WAIT
2730     childpid = wait(&argflags);
2731     if (childpid > 0)
2732         pidgone(childpid, argflags);
2733     value = (I32)childpid;
2734     statusvalue = FIXSTATUS(argflags);
2735     PUSHi(value);
2736     RETURN;
2737 #else
2738     DIE(no_func, "Unsupported function wait");
2739 #endif
2740 }
2741
2742 PP(pp_waitpid)
2743 {
2744     dSP; dTARGET;
2745     int childpid;
2746     int optype;
2747     int argflags;
2748     I32 value;
2749
2750 #ifdef HAS_WAIT
2751     optype = POPi;
2752     childpid = TOPi;
2753     childpid = wait4pid(childpid, &argflags, optype);
2754     value = (I32)childpid;
2755     statusvalue = FIXSTATUS(argflags);
2756     SETi(value);
2757     RETURN;
2758 #else
2759     DIE(no_func, "Unsupported function wait");
2760 #endif
2761 }
2762
2763 PP(pp_system)
2764 {
2765     dSP; dMARK; dORIGMARK; dTARGET;
2766     I32 value;
2767     int childpid;
2768     int result;
2769     int status;
2770     Signal_t (*ihand)();     /* place to save signal during system() */
2771     Signal_t (*qhand)();     /* place to save signal during system() */
2772
2773 #if defined(HAS_FORK) && !defined(VMS) && !defined(OS2)
2774     if (SP - MARK == 1) {
2775         if (tainting) {
2776             char *junk = SvPV(TOPs, na);
2777             TAINT_ENV();
2778             TAINT_PROPER("system");
2779         }
2780     }
2781     while ((childpid = vfork()) == -1) {
2782         if (errno != EAGAIN) {
2783             value = -1;
2784             SP = ORIGMARK;
2785             PUSHi(value);
2786             RETURN;
2787         }
2788         sleep(5);
2789     }
2790     if (childpid > 0) {
2791         ihand = signal(SIGINT, SIG_IGN);
2792         qhand = signal(SIGQUIT, SIG_IGN);
2793         do {
2794             result = wait4pid(childpid, &status, 0);
2795         } while (result == -1 && errno == EINTR);
2796         (void)signal(SIGINT, ihand);
2797         (void)signal(SIGQUIT, qhand);
2798         statusvalue = FIXSTATUS(status);
2799         if (result < 0)
2800             value = -1;
2801         else {
2802             value = (I32)((unsigned int)status & 0xffff);
2803         }
2804         do_execfree();  /* free any memory child malloced on vfork */
2805         SP = ORIGMARK;
2806         PUSHi(value);
2807         RETURN;
2808     }
2809     if (op->op_flags & OPf_STACKED) {
2810         SV *really = *++MARK;
2811         value = (I32)do_aexec(really, MARK, SP);
2812     }
2813     else if (SP - MARK != 1)
2814         value = (I32)do_aexec(Nullsv, MARK, SP);
2815     else {
2816         value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), na));
2817     }
2818     _exit(-1);
2819 #else /* ! FORK or VMS or OS/2 */
2820     if (op->op_flags & OPf_STACKED) {
2821         SV *really = *++MARK;
2822         value = (I32)do_aspawn(really, MARK, SP);
2823     }
2824     else if (SP - MARK != 1)
2825         value = (I32)do_aspawn(Nullsv, MARK, SP);
2826     else {
2827         value = (I32)do_spawn(SvPVx(sv_mortalcopy(*SP), na));
2828     }
2829     statusvalue = FIXSTATUS(value);
2830     do_execfree();
2831     SP = ORIGMARK;
2832     PUSHi(value);
2833 #endif /* !FORK or VMS */
2834     RETURN;
2835 }
2836
2837 PP(pp_exec)
2838 {
2839     dSP; dMARK; dORIGMARK; dTARGET;
2840     I32 value;
2841
2842     if (op->op_flags & OPf_STACKED) {
2843         SV *really = *++MARK;
2844         value = (I32)do_aexec(really, MARK, SP);
2845     }
2846     else if (SP - MARK != 1)
2847 #ifdef VMS
2848         value = (I32)vms_do_aexec(Nullsv, MARK, SP);
2849 #else
2850         value = (I32)do_aexec(Nullsv, MARK, SP);
2851 #endif
2852     else {
2853         if (tainting) {
2854             char *junk = SvPV(*SP, na);
2855             TAINT_ENV();
2856             TAINT_PROPER("exec");
2857         }
2858 #ifdef VMS
2859         value = (I32)vms_do_exec(SvPVx(sv_mortalcopy(*SP), na));
2860 #else
2861         value = (I32)do_exec(SvPVx(sv_mortalcopy(*SP), na));
2862 #endif
2863     }
2864     SP = ORIGMARK;
2865     PUSHi(value);
2866     RETURN;
2867 }
2868
2869 PP(pp_kill)
2870 {
2871     dSP; dMARK; dTARGET;
2872     I32 value;
2873 #ifdef HAS_KILL
2874     value = (I32)apply(op->op_type, MARK, SP);
2875     SP = MARK;
2876     PUSHi(value);
2877     RETURN;
2878 #else
2879     DIE(no_func, "Unsupported function kill");
2880 #endif
2881 }
2882
2883 PP(pp_getppid)
2884 {
2885 #ifdef HAS_GETPPID
2886     dSP; dTARGET;
2887     XPUSHi( getppid() );
2888     RETURN;
2889 #else
2890     DIE(no_func, "getppid");
2891 #endif
2892 }
2893
2894 PP(pp_getpgrp)
2895 {
2896 #ifdef HAS_GETPGRP
2897     dSP; dTARGET;
2898     int pid;
2899     I32 value;
2900
2901     if (MAXARG < 1)
2902         pid = 0;
2903     else
2904         pid = SvIVx(POPs);
2905 #ifdef BSD_GETPGRP
2906     value = (I32)BSD_GETPGRP(pid);
2907 #else
2908     if (pid != 0)
2909         DIE("POSIX getpgrp can't take an argument");
2910     value = (I32)getpgrp();
2911 #endif
2912     XPUSHi(value);
2913     RETURN;
2914 #else
2915     DIE(no_func, "getpgrp()");
2916 #endif
2917 }
2918
2919 PP(pp_setpgrp)
2920 {
2921 #ifdef HAS_SETPGRP
2922     dSP; dTARGET;
2923     int pgrp;
2924     int pid;
2925     if (MAXARG < 2) {
2926         pgrp = 0;
2927         pid = 0;
2928     }
2929     else {
2930         pgrp = POPi;
2931         pid = TOPi;
2932     }
2933
2934     TAINT_PROPER("setpgrp");
2935 #ifdef BSD_SETPGRP
2936     SETi( BSD_SETPGRP(pid, pgrp) >= 0 );
2937 #else
2938     if ((pgrp != 0) || (pid != 0)) {
2939         DIE("POSIX setpgrp can't take an argument");
2940     }
2941     SETi( setpgrp() >= 0 );
2942 #endif /* USE_BSDPGRP */
2943     RETURN;
2944 #else
2945     DIE(no_func, "setpgrp()");
2946 #endif
2947 }
2948
2949 PP(pp_getpriority)
2950 {
2951     dSP; dTARGET;
2952     int which;
2953     int who;
2954 #ifdef HAS_GETPRIORITY
2955     who = POPi;
2956     which = TOPi;
2957     SETi( getpriority(which, who) );
2958     RETURN;
2959 #else
2960     DIE(no_func, "getpriority()");
2961 #endif
2962 }
2963
2964 PP(pp_setpriority)
2965 {
2966     dSP; dTARGET;
2967     int which;
2968     int who;
2969     int niceval;
2970 #ifdef HAS_SETPRIORITY
2971     niceval = POPi;
2972     who = POPi;
2973     which = TOPi;
2974     TAINT_PROPER("setpriority");
2975     SETi( setpriority(which, who, niceval) >= 0 );
2976     RETURN;
2977 #else
2978     DIE(no_func, "setpriority()");
2979 #endif
2980 }
2981
2982 /* Time calls. */
2983
2984 PP(pp_time)
2985 {
2986     dSP; dTARGET;
2987     XPUSHi( time(Null(Time_t*)) );
2988     RETURN;
2989 }
2990
2991 #ifndef HZ
2992 #define HZ 60
2993 #endif
2994
2995 PP(pp_tms)
2996 {
2997     dSP;
2998
2999 #if defined(MSDOS) || !defined(HAS_TIMES)
3000     DIE("times not implemented");
3001 #else
3002     EXTEND(SP, 4);
3003
3004 #ifndef VMS
3005     (void)times(&timesbuf);
3006 #else
3007     (void)times((tbuffer_t *)&timesbuf);  /* time.h uses different name for */
3008                                           /* struct tms, though same data   */
3009                                           /* is returned.                   */
3010 #undef HZ
3011 #define HZ CLK_TCK
3012 #endif
3013
3014     PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_utime)/HZ)));
3015     if (GIMME == G_ARRAY) {
3016         PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_stime)/HZ)));
3017         PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_cutime)/HZ)));
3018         PUSHs(sv_2mortal(newSVnv(((double)timesbuf.tms_cstime)/HZ)));
3019     }
3020     RETURN;
3021 #endif /* MSDOS */
3022 }
3023
3024 PP(pp_localtime)
3025 {
3026     return pp_gmtime(ARGS);
3027 }
3028
3029 PP(pp_gmtime)
3030 {
3031     dSP;
3032     Time_t when;
3033     struct tm *tmbuf;
3034     static char *dayname[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
3035     static char *monname[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
3036                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
3037
3038     if (MAXARG < 1)
3039         (void)time(&when);
3040     else
3041         when = (Time_t)SvIVx(POPs);
3042
3043     if (op->op_type == OP_LOCALTIME)
3044         tmbuf = localtime(&when);
3045     else
3046         tmbuf = gmtime(&when);
3047
3048     EXTEND(SP, 9);
3049     if (GIMME != G_ARRAY) {
3050         dTARGET;
3051         char mybuf[30];
3052         if (!tmbuf)
3053             RETPUSHUNDEF;
3054         sprintf(mybuf, "%s %s %2d %02d:%02d:%02d %d",
3055             dayname[tmbuf->tm_wday],
3056             monname[tmbuf->tm_mon],
3057             tmbuf->tm_mday,
3058             tmbuf->tm_hour,
3059             tmbuf->tm_min,
3060             tmbuf->tm_sec,
3061             tmbuf->tm_year + 1900);
3062         PUSHp(mybuf, strlen(mybuf));
3063     }
3064     else if (tmbuf) {
3065         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_sec)));
3066         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_min)));
3067         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_hour)));
3068         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mday)));
3069         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_mon)));
3070         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_year)));
3071         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_wday)));
3072         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_yday)));
3073         PUSHs(sv_2mortal(newSViv((I32)tmbuf->tm_isdst)));
3074     }
3075     RETURN;
3076 }
3077
3078 PP(pp_alarm)
3079 {
3080     dSP; dTARGET;
3081     int anum;
3082 #ifdef HAS_ALARM
3083     anum = POPi;
3084     anum = alarm((unsigned int)anum);
3085     EXTEND(SP, 1);
3086     if (anum < 0)
3087         RETPUSHUNDEF;
3088     PUSHi((I32)anum);
3089     RETURN;
3090 #else
3091     DIE(no_func, "Unsupported function alarm");
3092 #endif
3093 }
3094
3095 PP(pp_sleep)
3096 {
3097     dSP; dTARGET;
3098     I32 duration;
3099     Time_t lasttime;
3100     Time_t when;
3101
3102     (void)time(&lasttime);
3103     if (MAXARG < 1)
3104         pause();
3105     else {
3106         duration = POPi;
3107         sleep((unsigned int)duration);
3108     }
3109     (void)time(&when);
3110     XPUSHi(when - lasttime);
3111     RETURN;
3112 }
3113
3114 /* Shared memory. */
3115
3116 PP(pp_shmget)
3117 {
3118     return pp_semget(ARGS);
3119 }
3120
3121 PP(pp_shmctl)
3122 {
3123     return pp_semctl(ARGS);
3124 }
3125
3126 PP(pp_shmread)
3127 {
3128     return pp_shmwrite(ARGS);
3129 }
3130
3131 PP(pp_shmwrite)
3132 {
3133 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
3134     dSP; dMARK; dTARGET;
3135     I32 value = (I32)(do_shmio(op->op_type, MARK, SP) >= 0);
3136     SP = MARK;
3137     PUSHi(value);
3138     RETURN;
3139 #else
3140     return pp_semget(ARGS);
3141 #endif
3142 }
3143
3144 /* Message passing. */
3145
3146 PP(pp_msgget)
3147 {
3148     return pp_semget(ARGS);
3149 }
3150
3151 PP(pp_msgctl)
3152 {
3153     return pp_semctl(ARGS);
3154 }
3155
3156 PP(pp_msgsnd)
3157 {
3158 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
3159     dSP; dMARK; dTARGET;
3160     I32 value = (I32)(do_msgsnd(MARK, SP) >= 0);
3161     SP = MARK;
3162     PUSHi(value);
3163     RETURN;
3164 #else
3165     return pp_semget(ARGS);
3166 #endif
3167 }
3168
3169 PP(pp_msgrcv)
3170 {
3171 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
3172     dSP; dMARK; dTARGET;
3173     I32 value = (I32)(do_msgrcv(MARK, SP) >= 0);
3174     SP = MARK;
3175     PUSHi(value);
3176     RETURN;
3177 #else
3178     return pp_semget(ARGS);
3179 #endif
3180 }
3181
3182 /* Semaphores. */
3183
3184 PP(pp_semget)
3185 {
3186 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
3187     dSP; dMARK; dTARGET;
3188     int anum = do_ipcget(op->op_type, MARK, SP);
3189     SP = MARK;
3190     if (anum == -1)
3191         RETPUSHUNDEF;
3192     PUSHi(anum);
3193     RETURN;
3194 #else
3195     DIE("System V IPC is not implemented on this machine");
3196 #endif
3197 }
3198
3199 PP(pp_semctl)
3200 {
3201 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
3202     dSP; dMARK; dTARGET;
3203     int anum = do_ipcctl(op->op_type, MARK, SP);
3204     SP = MARK;
3205     if (anum == -1)
3206         RETSETUNDEF;
3207     if (anum != 0) {
3208         PUSHi(anum);
3209     }
3210     else {
3211         PUSHp("0 but true",10);
3212     }
3213     RETURN;
3214 #else
3215     return pp_semget(ARGS);
3216 #endif
3217 }
3218
3219 PP(pp_semop)
3220 {
3221 #if defined(HAS_MSG) || defined(HAS_SEM) || defined(HAS_SHM)
3222     dSP; dMARK; dTARGET;
3223     I32 value = (I32)(do_semop(MARK, SP) >= 0);
3224     SP = MARK;
3225     PUSHi(value);
3226     RETURN;
3227 #else
3228     return pp_semget(ARGS);
3229 #endif
3230 }
3231
3232 /* Get system info. */
3233
3234 PP(pp_ghbyname)
3235 {
3236 #ifdef HAS_SOCKET
3237     return pp_ghostent(ARGS);
3238 #else
3239     DIE(no_sock_func, "gethostbyname");
3240 #endif
3241 }
3242
3243 PP(pp_ghbyaddr)
3244 {
3245 #ifdef HAS_SOCKET
3246     return pp_ghostent(ARGS);
3247 #else
3248     DIE(no_sock_func, "gethostbyaddr");
3249 #endif
3250 }
3251
3252 PP(pp_ghostent)
3253 {
3254     dSP;
3255 #ifdef HAS_SOCKET
3256     I32 which = op->op_type;
3257     register char **elem;
3258     register SV *sv;
3259     struct hostent *gethostbyname();
3260     struct hostent *gethostbyaddr();
3261 #ifdef HAS_GETHOSTENT
3262     struct hostent *gethostent();
3263 #endif
3264     struct hostent *hent;
3265     unsigned long len;
3266
3267     EXTEND(SP, 10);
3268     if (which == OP_GHBYNAME) {
3269         hent = gethostbyname(POPp);
3270     }
3271     else if (which == OP_GHBYADDR) {
3272         int addrtype = POPi;
3273         SV *addrsv = POPs;
3274         STRLEN addrlen;
3275         char *addr = SvPV(addrsv, addrlen);
3276
3277         hent = gethostbyaddr(addr, addrlen, addrtype);
3278     }
3279     else
3280 #ifdef HAS_GETHOSTENT
3281         hent = gethostent();
3282 #else
3283         DIE("gethostent not implemented");
3284 #endif
3285
3286 #ifdef HOST_NOT_FOUND
3287     if (!hent)
3288         statusvalue = FIXSTATUS(h_errno);
3289 #endif
3290
3291     if (GIMME != G_ARRAY) {
3292         PUSHs(sv = sv_newmortal());
3293         if (hent) {
3294             if (which == OP_GHBYNAME) {
3295                 if (hent->h_addr)
3296                     sv_setpvn(sv, hent->h_addr, hent->h_length);
3297             }
3298             else
3299                 sv_setpv(sv, (char*)hent->h_name);
3300         }
3301         RETURN;
3302     }
3303
3304     if (hent) {
3305         PUSHs(sv = sv_mortalcopy(&sv_no));
3306         sv_setpv(sv, (char*)hent->h_name);
3307         PUSHs(sv = sv_mortalcopy(&sv_no));
3308         for (elem = hent->h_aliases; elem && *elem; elem++) {
3309             sv_catpv(sv, *elem);
3310             if (elem[1])
3311                 sv_catpvn(sv, " ", 1);
3312         }
3313         PUSHs(sv = sv_mortalcopy(&sv_no));
3314         sv_setiv(sv, (I32)hent->h_addrtype);
3315         PUSHs(sv = sv_mortalcopy(&sv_no));
3316         len = hent->h_length;
3317         sv_setiv(sv, (I32)len);
3318 #ifdef h_addr
3319         for (elem = hent->h_addr_list; elem && *elem; elem++) {
3320             XPUSHs(sv = sv_mortalcopy(&sv_no));
3321             sv_setpvn(sv, *elem, len);
3322         }
3323 #else
3324         PUSHs(sv = sv_mortalcopy(&sv_no));
3325         if (hent->h_addr)
3326             sv_setpvn(sv, hent->h_addr, len);
3327 #endif /* h_addr */
3328     }
3329     RETURN;
3330 #else
3331     DIE(no_sock_func, "gethostent");
3332 #endif
3333 }
3334
3335 PP(pp_gnbyname)
3336 {
3337 #ifdef HAS_SOCKET
3338     return pp_gnetent(ARGS);
3339 #else
3340     DIE(no_sock_func, "getnetbyname");
3341 #endif
3342 }
3343
3344 PP(pp_gnbyaddr)
3345 {
3346 #ifdef HAS_SOCKET
3347     return pp_gnetent(ARGS);
3348 #else
3349     DIE(no_sock_func, "getnetbyaddr");
3350 #endif
3351 }
3352
3353 PP(pp_gnetent)
3354 {
3355     dSP;
3356 #ifdef HAS_SOCKET
3357     I32 which = op->op_type;
3358     register char **elem;
3359     register SV *sv;
3360     struct netent *getnetbyname();
3361     struct netent *getnetbyaddr();
3362     struct netent *getnetent();
3363     struct netent *nent;
3364
3365     if (which == OP_GNBYNAME)
3366         nent = getnetbyname(POPp);
3367     else if (which == OP_GNBYADDR) {
3368         int addrtype = POPi;
3369         unsigned long addr = U_L(POPn);
3370         nent = getnetbyaddr((long)addr, addrtype);
3371     }
3372     else
3373         nent = getnetent();
3374
3375     EXTEND(SP, 4);
3376     if (GIMME != G_ARRAY) {
3377         PUSHs(sv = sv_newmortal());
3378         if (nent) {
3379             if (which == OP_GNBYNAME)
3380                 sv_setiv(sv, (I32)nent->n_net);
3381             else
3382                 sv_setpv(sv, nent->n_name);
3383         }
3384         RETURN;
3385     }
3386
3387     if (nent) {
3388         PUSHs(sv = sv_mortalcopy(&sv_no));
3389         sv_setpv(sv, nent->n_name);
3390         PUSHs(sv = sv_mortalcopy(&sv_no));
3391         for (elem = nent->n_aliases; *elem; elem++) {
3392             sv_catpv(sv, *elem);
3393             if (elem[1])
3394                 sv_catpvn(sv, " ", 1);
3395         }
3396         PUSHs(sv = sv_mortalcopy(&sv_no));
3397         sv_setiv(sv, (I32)nent->n_addrtype);
3398         PUSHs(sv = sv_mortalcopy(&sv_no));
3399         sv_setiv(sv, (I32)nent->n_net);
3400     }
3401
3402     RETURN;
3403 #else
3404     DIE(no_sock_func, "getnetent");
3405 #endif
3406 }
3407
3408 PP(pp_gpbyname)
3409 {
3410 #ifdef HAS_SOCKET
3411     return pp_gprotoent(ARGS);
3412 #else
3413     DIE(no_sock_func, "getprotobyname");
3414 #endif
3415 }
3416
3417 PP(pp_gpbynumber)
3418 {
3419 #ifdef HAS_SOCKET
3420     return pp_gprotoent(ARGS);
3421 #else
3422     DIE(no_sock_func, "getprotobynumber");
3423 #endif
3424 }
3425
3426 PP(pp_gprotoent)
3427 {
3428     dSP;
3429 #ifdef HAS_SOCKET
3430     I32 which = op->op_type;
3431     register char **elem;
3432     register SV *sv;
3433     struct protoent *getprotobyname();
3434     struct protoent *getprotobynumber();
3435     struct protoent *getprotoent();
3436     struct protoent *pent;
3437
3438     if (which == OP_GPBYNAME)
3439         pent = getprotobyname(POPp);
3440     else if (which == OP_GPBYNUMBER)
3441         pent = getprotobynumber(POPi);
3442     else
3443         pent = getprotoent();
3444
3445     EXTEND(SP, 3);
3446     if (GIMME != G_ARRAY) {
3447         PUSHs(sv = sv_newmortal());
3448         if (pent) {
3449             if (which == OP_GPBYNAME)
3450                 sv_setiv(sv, (I32)pent->p_proto);
3451             else
3452                 sv_setpv(sv, pent->p_name);
3453         }
3454         RETURN;
3455     }
3456
3457     if (pent) {
3458         PUSHs(sv = sv_mortalcopy(&sv_no));
3459         sv_setpv(sv, pent->p_name);
3460         PUSHs(sv = sv_mortalcopy(&sv_no));
3461         for (elem = pent->p_aliases; *elem; elem++) {
3462             sv_catpv(sv, *elem);
3463             if (elem[1])
3464                 sv_catpvn(sv, " ", 1);
3465         }
3466         PUSHs(sv = sv_mortalcopy(&sv_no));
3467         sv_setiv(sv, (I32)pent->p_proto);
3468     }
3469
3470     RETURN;
3471 #else
3472     DIE(no_sock_func, "getprotoent");
3473 #endif
3474 }
3475
3476 PP(pp_gsbyname)
3477 {
3478 #ifdef HAS_SOCKET
3479     return pp_gservent(ARGS);
3480 #else
3481     DIE(no_sock_func, "getservbyname");
3482 #endif
3483 }
3484
3485 PP(pp_gsbyport)
3486 {
3487 #ifdef HAS_SOCKET
3488     return pp_gservent(ARGS);
3489 #else
3490     DIE(no_sock_func, "getservbyport");
3491 #endif
3492 }
3493
3494 PP(pp_gservent)
3495 {
3496     dSP;
3497 #ifdef HAS_SOCKET
3498     I32 which = op->op_type;
3499     register char **elem;
3500     register SV *sv;
3501     struct servent *getservbyname();
3502     struct servent *getservbynumber();
3503     struct servent *getservent();
3504     struct servent *sent;
3505
3506     if (which == OP_GSBYNAME) {
3507         char *proto = POPp;
3508         char *name = POPp;
3509
3510         if (proto && !*proto)
3511             proto = Nullch;
3512
3513         sent = getservbyname(name, proto);
3514     }
3515     else if (which == OP_GSBYPORT) {
3516         char *proto = POPp;
3517         int port = POPi;
3518
3519         sent = getservbyport(port, proto);
3520     }
3521     else
3522         sent = getservent();
3523
3524     EXTEND(SP, 4);
3525     if (GIMME != G_ARRAY) {
3526         PUSHs(sv = sv_newmortal());
3527         if (sent) {
3528             if (which == OP_GSBYNAME) {
3529 #ifdef HAS_NTOHS
3530                 sv_setiv(sv, (I32)ntohs(sent->s_port));
3531 #else
3532                 sv_setiv(sv, (I32)(sent->s_port));
3533 #endif
3534             }
3535             else
3536                 sv_setpv(sv, sent->s_name);
3537         }
3538         RETURN;
3539     }
3540
3541     if (sent) {
3542         PUSHs(sv = sv_mortalcopy(&sv_no));
3543         sv_setpv(sv, sent->s_name);
3544         PUSHs(sv = sv_mortalcopy(&sv_no));
3545         for (elem = sent->s_aliases; *elem; elem++) {
3546             sv_catpv(sv, *elem);
3547             if (elem[1])
3548                 sv_catpvn(sv, " ", 1);
3549         }
3550         PUSHs(sv = sv_mortalcopy(&sv_no));
3551 #ifdef HAS_NTOHS
3552         sv_setiv(sv, (I32)ntohs(sent->s_port));
3553 #else
3554         sv_setiv(sv, (I32)(sent->s_port));
3555 #endif
3556         PUSHs(sv = sv_mortalcopy(&sv_no));
3557         sv_setpv(sv, sent->s_proto);
3558     }
3559
3560     RETURN;
3561 #else
3562     DIE(no_sock_func, "getservent");
3563 #endif
3564 }
3565
3566 PP(pp_shostent)
3567 {
3568     dSP;
3569 #ifdef HAS_SOCKET
3570     sethostent(TOPi);
3571     RETSETYES;
3572 #else
3573     DIE(no_sock_func, "sethostent");
3574 #endif
3575 }
3576
3577 PP(pp_snetent)
3578 {
3579     dSP;
3580 #ifdef HAS_SOCKET
3581     setnetent(TOPi);
3582     RETSETYES;
3583 #else
3584     DIE(no_sock_func, "setnetent");
3585 #endif
3586 }
3587
3588 PP(pp_sprotoent)
3589 {
3590     dSP;
3591 #ifdef HAS_SOCKET
3592     setprotoent(TOPi);
3593     RETSETYES;
3594 #else
3595     DIE(no_sock_func, "setprotoent");
3596 #endif
3597 }
3598
3599 PP(pp_sservent)
3600 {
3601     dSP;
3602 #ifdef HAS_SOCKET
3603     setservent(TOPi);
3604     RETSETYES;
3605 #else
3606     DIE(no_sock_func, "setservent");
3607 #endif
3608 }
3609
3610 PP(pp_ehostent)
3611 {
3612     dSP;
3613 #ifdef HAS_SOCKET
3614     endhostent();
3615     EXTEND(sp,1);
3616     RETPUSHYES;
3617 #else
3618     DIE(no_sock_func, "endhostent");
3619 #endif
3620 }
3621
3622 PP(pp_enetent)
3623 {
3624     dSP;
3625 #ifdef HAS_SOCKET
3626     endnetent();
3627     EXTEND(sp,1);
3628     RETPUSHYES;
3629 #else
3630     DIE(no_sock_func, "endnetent");
3631 #endif
3632 }
3633
3634 PP(pp_eprotoent)
3635 {
3636     dSP;
3637 #ifdef HAS_SOCKET
3638     endprotoent();
3639     EXTEND(sp,1);
3640     RETPUSHYES;
3641 #else
3642     DIE(no_sock_func, "endprotoent");
3643 #endif
3644 }
3645
3646 PP(pp_eservent)
3647 {
3648     dSP;
3649 #ifdef HAS_SOCKET
3650     endservent();
3651     EXTEND(sp,1);
3652     RETPUSHYES;
3653 #else
3654     DIE(no_sock_func, "endservent");
3655 #endif
3656 }
3657
3658 PP(pp_gpwnam)
3659 {
3660 #ifdef HAS_PASSWD
3661     return pp_gpwent(ARGS);
3662 #else
3663     DIE(no_func, "getpwnam");
3664 #endif
3665 }
3666
3667 PP(pp_gpwuid)
3668 {
3669 #ifdef HAS_PASSWD
3670     return pp_gpwent(ARGS);
3671 #else
3672     DIE(no_func, "getpwuid");
3673 #endif
3674 }
3675
3676 PP(pp_gpwent)
3677 {
3678     dSP;
3679 #ifdef HAS_PASSWD
3680     I32 which = op->op_type;
3681     register SV *sv;
3682     struct passwd *pwent;
3683
3684     if (which == OP_GPWNAM)
3685         pwent = getpwnam(POPp);
3686     else if (which == OP_GPWUID)
3687         pwent = getpwuid(POPi);
3688     else
3689         pwent = (struct passwd *)getpwent();
3690
3691     EXTEND(SP, 10);
3692     if (GIMME != G_ARRAY) {
3693         PUSHs(sv = sv_newmortal());
3694         if (pwent) {
3695             if (which == OP_GPWNAM)
3696                 sv_setiv(sv, (I32)pwent->pw_uid);
3697             else
3698                 sv_setpv(sv, pwent->pw_name);
3699         }
3700         RETURN;
3701     }
3702
3703     if (pwent) {
3704         PUSHs(sv = sv_mortalcopy(&sv_no));
3705         sv_setpv(sv, pwent->pw_name);
3706         PUSHs(sv = sv_mortalcopy(&sv_no));
3707         sv_setpv(sv, pwent->pw_passwd);
3708         PUSHs(sv = sv_mortalcopy(&sv_no));
3709         sv_setiv(sv, (I32)pwent->pw_uid);
3710         PUSHs(sv = sv_mortalcopy(&sv_no));
3711         sv_setiv(sv, (I32)pwent->pw_gid);
3712         PUSHs(sv = sv_mortalcopy(&sv_no));
3713 #ifdef PWCHANGE
3714         sv_setiv(sv, (I32)pwent->pw_change);
3715 #else
3716 #ifdef PWQUOTA
3717         sv_setiv(sv, (I32)pwent->pw_quota);
3718 #else
3719 #ifdef PWAGE
3720         sv_setpv(sv, pwent->pw_age);
3721 #endif
3722 #endif
3723 #endif
3724         PUSHs(sv = sv_mortalcopy(&sv_no));
3725 #ifdef PWCLASS
3726         sv_setpv(sv, pwent->pw_class);
3727 #else
3728 #ifdef PWCOMMENT
3729         sv_setpv(sv, pwent->pw_comment);
3730 #endif
3731 #endif
3732         PUSHs(sv = sv_mortalcopy(&sv_no));
3733         sv_setpv(sv, pwent->pw_gecos);
3734         PUSHs(sv = sv_mortalcopy(&sv_no));
3735         sv_setpv(sv, pwent->pw_dir);
3736         PUSHs(sv = sv_mortalcopy(&sv_no));
3737         sv_setpv(sv, pwent->pw_shell);
3738 #ifdef PWEXPIRE
3739         PUSHs(sv = sv_mortalcopy(&sv_no));
3740         sv_setiv(sv, (I32)pwent->pw_expire);
3741 #endif
3742     }
3743     RETURN;
3744 #else
3745     DIE(no_func, "getpwent");
3746 #endif
3747 }
3748
3749 PP(pp_spwent)
3750 {
3751     dSP;
3752 #ifdef HAS_PASSWD
3753     setpwent();
3754     RETPUSHYES;
3755 #else
3756     DIE(no_func, "setpwent");
3757 #endif
3758 }
3759
3760 PP(pp_epwent)
3761 {
3762     dSP;
3763 #ifdef HAS_PASSWD
3764     endpwent();
3765     RETPUSHYES;
3766 #else
3767     DIE(no_func, "endpwent");
3768 #endif
3769 }
3770
3771 PP(pp_ggrnam)
3772 {
3773 #ifdef HAS_GROUP
3774     return pp_ggrent(ARGS);
3775 #else
3776     DIE(no_func, "getgrnam");
3777 #endif
3778 }
3779
3780 PP(pp_ggrgid)
3781 {
3782 #ifdef HAS_GROUP
3783     return pp_ggrent(ARGS);
3784 #else
3785     DIE(no_func, "getgrgid");
3786 #endif
3787 }
3788
3789 PP(pp_ggrent)
3790 {
3791     dSP;
3792 #ifdef HAS_GROUP
3793     I32 which = op->op_type;
3794     register char **elem;
3795     register SV *sv;
3796     struct group *grent;
3797
3798     if (which == OP_GGRNAM)
3799         grent = (struct group *)getgrnam(POPp);
3800     else if (which == OP_GGRGID)
3801         grent = (struct group *)getgrgid(POPi);
3802     else
3803         grent = (struct group *)getgrent();
3804
3805     EXTEND(SP, 4);
3806     if (GIMME != G_ARRAY) {
3807         PUSHs(sv = sv_newmortal());
3808         if (grent) {
3809             if (which == OP_GGRNAM)
3810                 sv_setiv(sv, (I32)grent->gr_gid);
3811             else
3812                 sv_setpv(sv, grent->gr_name);
3813         }
3814         RETURN;
3815     }
3816
3817     if (grent) {
3818         PUSHs(sv = sv_mortalcopy(&sv_no));
3819         sv_setpv(sv, grent->gr_name);
3820         PUSHs(sv = sv_mortalcopy(&sv_no));
3821         sv_setpv(sv, grent->gr_passwd);
3822         PUSHs(sv = sv_mortalcopy(&sv_no));
3823         sv_setiv(sv, (I32)grent->gr_gid);
3824         PUSHs(sv = sv_mortalcopy(&sv_no));
3825         for (elem = grent->gr_mem; *elem; elem++) {
3826             sv_catpv(sv, *elem);
3827             if (elem[1])
3828                 sv_catpvn(sv, " ", 1);
3829         }
3830     }
3831
3832     RETURN;
3833 #else
3834     DIE(no_func, "getgrent");
3835 #endif
3836 }
3837
3838 PP(pp_sgrent)
3839 {
3840     dSP;
3841 #ifdef HAS_GROUP
3842     setgrent();
3843     RETPUSHYES;
3844 #else
3845     DIE(no_func, "setgrent");
3846 #endif
3847 }
3848
3849 PP(pp_egrent)
3850 {
3851     dSP;
3852 #ifdef HAS_GROUP
3853     endgrent();
3854     RETPUSHYES;
3855 #else
3856     DIE(no_func, "endgrent");
3857 #endif
3858 }
3859
3860 PP(pp_getlogin)
3861 {
3862     dSP; dTARGET;
3863 #ifdef HAS_GETLOGIN
3864     char *tmps;
3865     EXTEND(SP, 1);
3866     if (!(tmps = getlogin()))
3867         RETPUSHUNDEF;
3868     PUSHp(tmps, strlen(tmps));
3869     RETURN;
3870 #else
3871     DIE(no_func, "getlogin");
3872 #endif
3873 }
3874
3875 /* Miscellaneous. */
3876
3877 PP(pp_syscall)
3878 {
3879 #ifdef HAS_SYSCALL
3880     dSP; dMARK; dORIGMARK; dTARGET;
3881     register I32 items = SP - MARK;
3882     unsigned long a[20];
3883     register I32 i = 0;
3884     I32 retval = -1;
3885     MAGIC *mg;
3886
3887     if (tainting) {
3888         while (++MARK <= SP) {
3889             if (SvGMAGICAL(*MARK) && SvSMAGICAL(*MARK) &&
3890               (mg = mg_find(*MARK, 't')) && mg->mg_len & 1)
3891                 tainted = TRUE;
3892         }
3893         MARK = ORIGMARK;
3894         TAINT_PROPER("syscall");
3895     }
3896
3897     /* This probably won't work on machines where sizeof(long) != sizeof(int)
3898      * or where sizeof(long) != sizeof(char*).  But such machines will
3899      * not likely have syscall implemented either, so who cares?
3900      */
3901     while (++MARK <= SP) {
3902         if (SvNIOK(*MARK) || !i)
3903             a[i++] = SvIV(*MARK);
3904         else if (*MARK == &sv_undef)
3905             a[i++] = 0;
3906         else 
3907             a[i++] = (unsigned long)SvPV_force(*MARK, na);
3908         if (i > 15)
3909             break;
3910     }
3911     switch (items) {
3912     default:
3913         DIE("Too many args to syscall");
3914     case 0:
3915         DIE("Too few args to syscall");
3916     case 1:
3917         retval = syscall(a[0]);
3918         break;
3919     case 2:
3920         retval = syscall(a[0],a[1]);
3921         break;
3922     case 3:
3923         retval = syscall(a[0],a[1],a[2]);
3924         break;
3925     case 4:
3926         retval = syscall(a[0],a[1],a[2],a[3]);
3927         break;
3928     case 5:
3929         retval = syscall(a[0],a[1],a[2],a[3],a[4]);
3930         break;
3931     case 6:
3932         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5]);
3933         break;
3934     case 7:
3935         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6]);
3936         break;
3937     case 8:
3938         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]);
3939         break;
3940 #ifdef atarist
3941     case 9:
3942         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
3943         break;
3944     case 10:
3945         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]);
3946         break;
3947     case 11:
3948         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
3949           a[10]);
3950         break;
3951     case 12:
3952         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
3953           a[10],a[11]);
3954         break;
3955     case 13:
3956         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
3957           a[10],a[11],a[12]);
3958         break;
3959     case 14:
3960         retval = syscall(a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],
3961           a[10],a[11],a[12],a[13]);
3962         break;
3963 #endif /* atarist */
3964     }
3965     SP = ORIGMARK;
3966     PUSHi(retval);
3967     RETURN;
3968 #else
3969     DIE(no_func, "syscall");
3970 #endif
3971 }
3972
3973 #if !defined(HAS_FLOCK) && defined(HAS_LOCKF)
3974
3975 /*  XXX Emulate flock() with lockf().  This is just to increase
3976     portability of scripts.  The calls are not completely
3977     interchangeable.  What's really needed is a good file
3978     locking module.
3979 */
3980
3981 /*  We might need <unistd.h> because it sometimes defines the lockf()
3982     constants.  Unfortunately, <unistd.h> causes troubles on some mixed
3983     (BSD/POSIX) systems, such as SunOS 4.1.3.  We could just try including
3984     <unistd.h> here in this part of the file, but that might
3985     conflict with various other #defines and includes above, such as
3986         #define vfork fork above.
3987
3988    Further, the lockf() constants aren't POSIX, so they might not be
3989    visible if we're compiling with _POSIX_SOURCE defined.  Thus, we'll
3990    just stick in the SVID values and be done with it.  Sigh.
3991 */
3992
3993 # ifndef F_ULOCK
3994 #  define F_ULOCK       0       /* Unlock a previously locked region */
3995 # endif
3996 # ifndef F_LOCK
3997 #  define F_LOCK        1       /* Lock a region for exclusive use */
3998 # endif
3999 # ifndef F_TLOCK
4000 #  define F_TLOCK       2       /* Test and lock a region for exclusive use */
4001 # endif
4002 # ifndef F_TEST
4003 #  define F_TEST        3       /* Test a region for other processes locks */
4004 # endif
4005
4006 /* These are the flock() constants.  Since this sytems doesn't have
4007    flock(), the values of the constants are probably not available.
4008 */
4009 # ifndef LOCK_SH
4010 #  define LOCK_SH 1
4011 # endif
4012 # ifndef LOCK_EX
4013 #  define LOCK_EX 2
4014 # endif
4015 # ifndef LOCK_NB
4016 #  define LOCK_NB 4
4017 # endif
4018 # ifndef LOCK_UN
4019 #  define LOCK_UN 8
4020 # endif
4021
4022 int
4023 lockf_emulate_flock (fd, operation)
4024 int fd;
4025 int operation;
4026 {
4027     int i;
4028     switch (operation) {
4029
4030         /* LOCK_SH - get a shared lock */
4031         case LOCK_SH:
4032         /* LOCK_EX - get an exclusive lock */
4033         case LOCK_EX:
4034             i = lockf (fd, F_LOCK, 0);
4035             break;
4036
4037         /* LOCK_SH|LOCK_NB - get a non-blocking shared lock */
4038         case LOCK_SH|LOCK_NB:
4039         /* LOCK_EX|LOCK_NB - get a non-blocking exclusive lock */
4040         case LOCK_EX|LOCK_NB:
4041             i = lockf (fd, F_TLOCK, 0);
4042             if (i == -1)
4043                 if ((errno == EAGAIN) || (errno == EACCES))
4044                     errno = EWOULDBLOCK;
4045             break;
4046
4047         /* LOCK_UN - unlock */
4048         case LOCK_UN:
4049             i = lockf (fd, F_ULOCK, 0);
4050             break;
4051
4052         /* Default - can't decipher operation */
4053         default:
4054             i = -1;
4055             errno = EINVAL;
4056             break;
4057     }
4058     return (i);
4059 }
4060 #endif