2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/io/io_unix.c - UNIX IO layer
11 This is the Parrot UNIX IO layer. It implements unbuffered, low-level,
12 UNIX-specific functionality.
14 As "UNIX" is already a generalization, it may be necessary to create
15 separate OS-specific layers for UNIX flavors, to avoid
16 over-complicating this file.
20 APitUE - W. Richard Stevens, AT&T SFIO, Perl 5 (Nick Ing-Simmons)
30 #include "parrot/parrot.h"
31 #include "io_private.h"
35 /* Defined at bottom */
36 extern const ParrotIOLayerAPI pio_unix_layer_api
;
38 ParrotIOLayer pio_unix_layer
= {
46 /* HEADERIZER HFILE: none */
48 /* HEADERIZER BEGIN: static */
49 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
52 static INTVAL
flags_to_unix(INTVAL flags
);
54 PARROT_WARN_UNUSED_RESULT
55 PARROT_CAN_RETURN_NULL
56 static ParrotIO
* PIO_unix_accept(PARROT_INTERP
,
57 SHIM(ParrotIOLayer
*layer
),
59 __attribute__nonnull__(1)
60 __attribute__nonnull__(3)
63 static INTVAL
PIO_unix_bind(SHIM_INTERP
,
64 SHIM(ParrotIOLayer
*layer
),
67 __attribute__nonnull__(3)
68 __attribute__nonnull__(4)
72 static INTVAL
PIO_unix_close(SHIM_INTERP
,
73 SHIM(ParrotIOLayer
*layer
),
75 __attribute__nonnull__(3)
78 static INTVAL
PIO_unix_connect(SHIM_INTERP
,
79 SHIM(ParrotIOLayer
*layer
),
81 ARGIN_NULLOK(STRING
*r
))
82 __attribute__nonnull__(3)
85 PARROT_WARN_UNUSED_RESULT
86 PARROT_CANNOT_RETURN_NULL
87 static ParrotIO
* PIO_unix_fdopen(PARROT_INTERP
,
88 SHIM(ParrotIOLayer
*layer
),
91 __attribute__nonnull__(1);
93 static INTVAL
PIO_unix_flush(SHIM_INTERP
,
94 SHIM(ParrotIOLayer
*layer
),
96 __attribute__nonnull__(3)
99 static INTVAL
PIO_unix_init(PARROT_INTERP
, ARGIN(ParrotIOLayer
*layer
))
100 __attribute__nonnull__(1)
101 __attribute__nonnull__(2);
103 static INTVAL
PIO_unix_isatty(PIOHANDLE fd
);
104 static INTVAL
PIO_unix_listen(SHIM_INTERP
,
105 SHIM(ParrotIOLayer
*layer
),
108 __attribute__nonnull__(3);
110 PARROT_WARN_UNUSED_RESULT
111 PARROT_CAN_RETURN_NULL
112 static ParrotIO
* PIO_unix_open(PARROT_INTERP
,
113 ARGIN(ParrotIOLayer
*layer
),
114 ARGIN(const char *spath
),
116 __attribute__nonnull__(1)
117 __attribute__nonnull__(2)
118 __attribute__nonnull__(3);
120 PARROT_WARN_UNUSED_RESULT
121 PARROT_CAN_RETURN_NULL
122 static ParrotIO
* PIO_unix_pipe(PARROT_INTERP
,
123 SHIM(ParrotIOLayer
*l
),
124 ARGIN(const char *cmd
),
126 __attribute__nonnull__(1)
127 __attribute__nonnull__(3);
129 static INTVAL
PIO_unix_poll(SHIM_INTERP
,
130 SHIM(ParrotIOLayer
*l
),
131 ARGMOD(ParrotIO
*io
),
135 __attribute__nonnull__(3)
138 static size_t PIO_unix_read(PARROT_INTERP
,
139 SHIM(ParrotIOLayer
*layer
),
140 ARGMOD(ParrotIO
*io
),
142 __attribute__nonnull__(1)
143 __attribute__nonnull__(3)
144 __attribute__nonnull__(4)
147 static INTVAL
PIO_unix_recv(PARROT_INTERP
,
148 SHIM(ParrotIOLayer
*layer
),
149 ARGMOD(ParrotIO
*io
),
151 __attribute__nonnull__(1)
152 __attribute__nonnull__(3)
153 __attribute__nonnull__(4)
157 static PIOOFF_T
PIO_unix_seek(SHIM_INTERP
,
158 SHIM(ParrotIOLayer
*layer
),
159 ARGMOD(ParrotIO
*io
),
162 __attribute__nonnull__(3)
165 static INTVAL
PIO_unix_send(SHIM_INTERP
,
166 SHIM(ParrotIOLayer
*layer
),
167 ARGMOD(ParrotIO
*io
),
169 __attribute__nonnull__(3)
170 __attribute__nonnull__(4)
174 PARROT_WARN_UNUSED_RESULT
175 PARROT_CAN_RETURN_NULL
176 static ParrotIO
* PIO_unix_socket(PARROT_INTERP
,
177 SHIM(ParrotIOLayer
*layer
),
181 __attribute__nonnull__(1);
183 static PIOOFF_T
PIO_unix_tell(SHIM_INTERP
,
184 SHIM(ParrotIOLayer
*layer
),
185 ARGMOD(ParrotIO
*io
))
186 __attribute__nonnull__(3)
189 static size_t PIO_unix_write(SHIM_INTERP
,
190 SHIM(ParrotIOLayer
*layer
),
191 ARGMOD(ParrotIO
*io
),
193 __attribute__nonnull__(3)
194 __attribute__nonnull__(4)
198 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
199 /* HEADERIZER END: static */
204 =item C<static INTVAL flags_to_unix>
206 Returns a UNIX-specific interpretation of C<flags> suitable for passing
207 to C<open()> and C<fopen()> in C<PIO_unix_open()> and
208 C<PIO_unix_fdopen()> respectively.
214 PARROT_CONST_FUNCTION
216 flags_to_unix(INTVAL flags
)
220 if ((flags
& (PIO_F_WRITE
| PIO_F_READ
)) == (PIO_F_WRITE
| PIO_F_READ
)) {
221 oflags
|= O_RDWR
| O_CREAT
;
223 else if (flags
& PIO_F_WRITE
) {
224 oflags
|= O_WRONLY
| O_CREAT
;
226 else if (flags
& PIO_F_READ
) {
230 if (flags
& PIO_F_APPEND
) {
233 else if (flags
& PIO_F_TRUNC
) {
241 =item C<static INTVAL PIO_unix_init>
243 Sets up the interpreter's standard C<std*> IO handles. Returns C<0> on
244 success and C<-1> on error.
251 PIO_unix_init(PARROT_INTERP
, ARGIN(ParrotIOLayer
*layer
))
253 ParrotIOData
* const d
= interp
->piodata
;
254 if (d
!= NULL
&& d
->table
!= NULL
) {
257 io
= PIO_unix_fdopen(interp
, layer
, STDIN_FILENO
, PIO_F_READ
);
260 _PIO_STDIN(interp
) = new_io_pmc(interp
, io
);
262 io
= PIO_unix_fdopen(interp
, layer
, STDOUT_FILENO
, PIO_F_WRITE
);
265 _PIO_STDOUT(interp
) = new_io_pmc(interp
, io
);
267 io
= PIO_unix_fdopen(interp
, layer
, STDERR_FILENO
, PIO_F_WRITE
);
270 _PIO_STDERR(interp
) = new_io_pmc(interp
, io
);
279 =item C<static ParrotIO * PIO_unix_open>
281 Opens C<*spath>. C<flags> is a bitwise C<or> combination of C<PIO_F_*>
288 PARROT_WARN_UNUSED_RESULT
289 PARROT_CAN_RETURN_NULL
291 PIO_unix_open(PARROT_INTERP
, ARGIN(ParrotIOLayer
*layer
),
292 ARGIN(const char *spath
), INTVAL flags
)
297 const INTVAL type
= PIO_TYPE_FILE
;
298 const INTVAL mode
= DEFAULT_OPEN_MODE
;
300 if (flags
& PIO_F_PIPE
)
301 return PIO_unix_pipe(interp
, layer
, spath
, flags
);
303 if ((flags
& (PIO_F_WRITE
| PIO_F_READ
)) == 0)
306 oflags
= flags_to_unix(flags
);
308 /* Only files for now */
311 /* Try open with no create first */
312 while ((fd
= open(spath
, oflags
& (O_WRONLY
| O_RDWR
| O_APPEND
), mode
))
313 < 0 && errno
== EINTR
)
319 * Now check if we specified O_CREAT|O_EXCL or not.
320 * If so, we must return NULL, else either use the
321 * descriptor or create the file.
323 if ((oflags
& (O_CREAT
| O_EXCL
)) == (O_CREAT
| O_EXCL
)) {
328 * Check for truncate?
330 if (oflags
& O_TRUNC
) {
332 while ((tfd
= creat(spath
, PIO_DEFAULTMODE
)) < 0 && errno
== EINTR
)
337 else if (oflags
& O_CREAT
) {
338 /* O_CREAT and file doesn't exist. */
339 while ((fd
= creat(spath
, PIO_DEFAULTMODE
)) < 0 && errno
== EINTR
)
341 if (!(oflags
& O_WRONLY
)) {
344 * File created, reopen with read+write
346 while ((fd
= open(spath
, oflags
& (O_WRONLY
| O_RDWR
),
347 mode
)) < 0 && errno
== EINTR
)
352 /* File doesn't exist and O_CREAT not specified */
356 /* Set generic flag here if is a terminal then
357 * higher layers can know how to setup buffering.
358 * STDIN, STDOUT, STDERR would be in this case
359 * so we would setup linebuffering.
362 if (PIO_unix_isatty(fd
))
363 flags
|= PIO_F_CONSOLE
;
364 io
= PIO_new(interp
, type
, flags
, mode
);
372 # if PARROT_ASYNC_DEVEL
376 =item C<INTVAL PIO_unix_async>
378 Experimental asynchronous IO.
380 This is available if C<PARROT_ASYNC_DEVEL> is defined.
382 Only works on Linux at the moment.
384 Toggles the C<O_ASYNC> flag on the IO file descriptor.
391 PIO_unix_async(PARROT_INTERP
, ARGMOD(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
), INTVAL b
)
395 if ((rflags
= fcntl(io
->fd
, F_GETFL
, 0)) >= 0) {
400 return fcntl(io
->fd
, F_SETFL
, rflags
);
403 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_PIO_NOT_IMPLEMENTED
,
404 "Async support not available");
413 =item C<static ParrotIO * PIO_unix_fdopen>
415 Returns a new C<ParrotIO> with file descriptor C<fd>.
421 PARROT_WARN_UNUSED_RESULT
422 PARROT_CANNOT_RETURN_NULL
424 PIO_unix_fdopen(PARROT_INTERP
, SHIM(ParrotIOLayer
*layer
), PIOHANDLE fd
, INTVAL flags
)
427 const INTVAL mode
= 0;
430 /* XXX the fcntl fails (-1, errno=0) with
431 * ./parrot -tf - < foo.pir
434 /* FIXME - Check file handle flags, validity */
435 # ifdef PARROT_HAS_HEADER_FCNTL
438 /* Get descriptor flags */
439 if ((rflags
= fcntl(fd
, F_GETFL
, 0)) >= 0) {
441 /*int accmode = rflags & O_ACCMODE; */
442 /* Check other flags (APPEND, ASYNC, etc) */
445 /* Probably invalid descriptor */
452 if (PIO_unix_isatty(fd
))
453 flags
|= PIO_F_CONSOLE
;
455 /* fdopened files are always shared */
456 flags
|= PIO_F_SHARED
;
458 io
= PIO_new(interp
, PIO_F_FILE
, flags
, mode
);
465 =item C<static INTVAL PIO_unix_close>
467 Closes C<*io>'s file descriptor.
474 PIO_unix_close(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
))
476 /* BSD and Solaris need explicit fsync() */
487 =item C<static INTVAL PIO_unix_isatty>
489 Returns a boolean value indicating whether C<fd> is a console/tty.
496 PIO_unix_isatty(PIOHANDLE fd
)
503 =item C<INTVAL PIO_unix_getblksize>
505 Various ways of determining block size.
507 If passed a file descriptor then C<fstat()> and the C<stat> buffer are
510 If called without an argument then the C<BLKSIZE> constant is returned
511 if it was available at compile time, otherwise C<PIO_BLKSIZE> is returned.
518 PIO_unix_getblksize(PIOHANDLE fd
)
521 /* Try to get the block size of a regular file */
524 * Is it even worth adding non-portable code here
525 * or should we just estimate a nice buffer size?
526 * Some systems have st_blksize, some don't.
531 err
= fstat(fd
, &sbuf
);
533 return sbuf
.st_blksize
;
538 /* Try to determine it from general means. */
548 =item C<static INTVAL PIO_unix_flush>
550 At lowest layer all we can do for C<flush> is to ask the kernel to
553 XXX: Is it necessary to C<sync()> here?
560 PIO_unix_flush(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
))
562 return fsync(io
->fd
);
567 =item C<static size_t PIO_unix_read>
569 Calls C<read()> to return up to C<len> bytes in the memory starting at
577 PIO_unix_read(PARROT_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
),
580 STRING
* const s
= PIO_make_io_string(interp
, buf
, 2048);
582 const size_t len
= s
->bufused
;
583 void * const buffer
= s
->strstart
;
586 const int bytes
= read(io
->fd
, buffer
, len
);
588 s
->bufused
= s
->strlen
= bytes
;
591 else if (bytes
< 0) {
596 s
->bufused
= s
->strlen
= 0;
601 /* Read returned 0, EOF if len requested > 0 */
603 io
->flags
|= PIO_F_EOF
;
604 s
->bufused
= s
->strlen
= 0;
612 =item C<static size_t PIO_unix_write>
614 Calls C<write()> to write C<len> bytes from the memory starting at
615 C<buffer> to the file descriptor in C<*io>.
622 PIO_unix_write(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
), ARGMOD(STRING
*s
))
624 const char * const buffer
= s
->strstart
;
625 const char * ptr
= buffer
;
627 size_t to_write
= s
->bufused
;
631 while (to_write
> 0) {
632 const int err
= write(io
->fd
, ptr
, to_write
);
656 =item C<static PIOOFF_T PIO_unix_seek>
660 Calls C<lseek()> to advance the read/write position on C<*io>'s file
661 descriptor to C<offset> bytes from the location indicated by C<whence>.
668 PIO_unix_seek(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
),
669 PIOOFF_T offset
, INTVAL whence
)
671 const PIOOFF_T pos
= lseek(io
->fd
, offset
, whence
);
676 io
->fsize
= offset
> io
->fsize
? offset
: io
->fsize
;
680 const PIOOFF_T avail
= io
->b
.next
- io
->b
.startb
+ offset
;
681 io
->fsize
= (avail
> io
->fsize
) ? avail
: io
->fsize
;
692 /* Seek clears EOF */
693 io
->flags
&= ~PIO_F_EOF
;
699 =item C<static PIOOFF_T PIO_unix_tell>
701 Returns the current read/write position on C<*io>'s file discriptor.
708 PIO_unix_tell(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
))
710 const PIOOFF_T pos
= lseek(io
->fd
, (PIOOFF_T
)0, SEEK_CUR
);
721 Define C<PARROT_NET_DEVEL> to enable networking.
723 These could be native extensions but they probably should be here if we
724 wish to make them integrated with the async IO system.
726 Very minimal stubs for now, maybe someone will run with these.
730 =item C<STRING * PIO_sockaddr_in>
732 C<PIO_sockaddr_in()> is not part of the layer and so must be C<extern>.
734 XXX: We can probably just write our own routines (C<htons()>,
735 C<inet_aton()>, etc.) and take this out of platform specific compilation
741 PARROT_WARN_UNUSED_RESULT
742 PARROT_CANNOT_RETURN_NULL
744 PIO_sockaddr_in(PARROT_INTERP
, unsigned short port
, ARGIN(STRING
*addr
))
746 struct sockaddr_in sa
;
747 /* Hard coded to IPv4 for now */
748 const int family
= AF_INET
;
750 char * const s
= string_to_cstring(interp
, addr
);
752 * due to a bug in OS/X, we've to zero the struct
753 * else bind is failing erratically
755 memset(&sa
, 0, sizeof (sa
));
756 # ifdef PARROT_DEF_INET_ATON
757 if (inet_aton(s
, &sa
.sin_addr
) != 0) {
759 /* positive retval is success */
760 if (inet_pton(family
, s
, &sa
.sin_addr
) > 0) {
762 /* Success converting numeric IP */
765 /* Maybe it is a hostname, try to lookup */
766 /* XXX Check PIO option before doing a name lookup,
767 * it may have been toggled off.
769 struct hostent
*he
= gethostbyname(s
);
770 /* XXX FIXME - Handle error condition better */
772 string_cstring_free(s
);
773 fprintf(stderr
, "gethostbyname failure [%s]\n", s
);
776 memcpy((char*)&sa
.sin_addr
, he
->h_addr
, sizeof (sa
.sin_addr
));
778 string_cstring_free(s
);
780 sa
.sin_family
= family
;
781 sa
.sin_port
= htons(port
);
783 return string_make(interp
, (char *)&sa
, sizeof (struct sockaddr_in
),
788 # if PARROT_NET_DEVEL
792 =item C<static ParrotIO * PIO_unix_socket>
794 Uses C<socket()> to create a socket with the specified address family,
795 socket type and protocol number.
801 PARROT_WARN_UNUSED_RESULT
802 PARROT_CAN_RETURN_NULL
804 PIO_unix_socket(PARROT_INTERP
, SHIM(ParrotIOLayer
*layer
), int fam
, int type
, int proto
)
806 const int sock
= socket(fam
, type
, proto
);
808 ParrotIO
* const io
= PIO_new(interp
, PIO_F_SOCKET
, 0, PIO_F_READ
|PIO_F_WRITE
);
810 memset(&io
->local
, 0, sizeof (struct sockaddr_in
));
811 memset(&io
->remote
, 0, sizeof (struct sockaddr_in
));
812 io
->remote
.sin_family
= fam
;
820 =item C<static INTVAL PIO_unix_connect>
822 Connects C<*io>'s socket to address C<*r>.
829 PIO_unix_connect(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
),
830 ARGIN_NULLOK(STRING
*r
))
832 struct sockaddr_in
* saddr
= &io
->remote
;
835 memcpy(&io
->remote
, PObj_bufstart(r
), sizeof (struct sockaddr_in
));
838 if ((connect(io
->fd
, (struct sockaddr
*)saddr
,
839 sizeof (struct sockaddr_in
))) != 0) {
857 =item C<static INTVAL PIO_unix_bind>
859 Binds C<*io>'s socket to the local address and port specified by C<*l>.
866 PIO_unix_bind(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
),
869 struct sockaddr_in
* saddr
= &io
->local
;
874 memcpy(&io
->local
, PObj_bufstart(l
), sizeof (struct sockaddr_in
));
876 if ((bind(io
->fd
, (struct sockaddr
*) saddr
,
877 sizeof (struct sockaddr_in
))) == -1) {
886 =item C<static INTVAL PIO_unix_listen>
888 Listen for new connections. This is only applicable to C<STREAM> or
896 PIO_unix_listen(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGIN(ParrotIO
*io
),
899 if ((listen(io
->fd
, sec
)) == -1) {
907 =item C<static ParrotIO * PIO_unix_accept>
909 Accept a new connection and return a newly created C<ParrotIO> socket.
915 PARROT_WARN_UNUSED_RESULT
916 PARROT_CAN_RETURN_NULL
918 PIO_unix_accept(PARROT_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
))
920 ParrotIO
* const newio
= PIO_new(interp
, PIO_F_SOCKET
, 0,
921 PIO_F_READ
|PIO_F_WRITE
);
922 Parrot_Socklen_t addrlen
= sizeof (struct sockaddr_in
);
923 struct sockaddr_in
*saddr
= &newio
->remote
;
924 const int newsock
= accept(io
->fd
, (struct sockaddr
*)saddr
,
934 /* XXX FIXME: Need to do a getsockname and getpeername here to
935 * fill in the sockaddr_in structs for local and peer */
937 /* Optionally do a gethostyaddr() to resolve remote IP address.
938 * This should be based on an option set in the master socket */
945 =item C<static INTVAL PIO_unix_send>
947 Send the message C<*s> to C<*io>'s connected socket.
954 PIO_unix_send(SHIM_INTERP
, SHIM(ParrotIOLayer
*layer
), ARGMOD(ParrotIO
*io
),
957 int error
, bytes
, byteswrote
;
963 * Ignore encoding issues for now.
965 if ((error
= send(io
->fd
, (char *)s
->strstart
+ byteswrote
,
986 /* XXX why close it here and not below */
997 =item C<static INTVAL PIO_unix_recv>
999 Receives a message in C<**s> from C<*io>'s connected socket.
1006 PIO_unix_recv(PARROT_INTERP
, SHIM(ParrotIOLayer
*layer
),
1007 ARGMOD(ParrotIO
*io
), ARGOUT(STRING
**s
))
1010 unsigned int bytesread
= 0;
1014 if ((error
= recv(io
->fd
, buf
, 2048, 0)) >= 0) {
1016 /* The charset should probably be 'binary', but right now httpd.pir
1017 * only works with 'ascii'
1019 *s
= string_make(interp
, buf
, bytesread
, "ascii", 0);
1034 /* XXX why close it on err return result is -1 anyway */
1036 *s
= string_make_empty(interp
, enum_stringrep_one
, 0);
1040 *s
= string_make_empty(interp
, enum_stringrep_one
, 0);
1048 =item C<static INTVAL PIO_unix_poll>
1050 Utility function for polling a single IO stream with a timeout.
1052 Returns a 1 | 2 | 4 (read, write, error) value.
1054 This is not equivalent to any speficic POSIX or BSD socket call, however
1055 it is a useful, common primitive.
1057 Not at all usefule --leo.
1059 Also, a buffering layer above this may choose to reimpliment by checking
1067 PIO_unix_poll(SHIM_INTERP
, SHIM(ParrotIOLayer
*l
), ARGMOD(ParrotIO
*io
), int which
,
1076 FD_ZERO(&r
); FD_ZERO(&w
); FD_ZERO(&e
);
1077 /* These should be defined in header */
1078 if (which
& 1) FD_SET(io
->fd
, &r
);
1079 if (which
& 2) FD_SET(io
->fd
, &w
);
1080 if (which
& 4) FD_SET(io
->fd
, &e
);
1082 if ((select(io
->fd
+1, &r
, &w
, &e
, &t
)) >= 0) {
1083 n
= (FD_ISSET(io
->fd
, &r
) ? 1 : 0);
1084 n
|= (FD_ISSET(io
->fd
, &w
) ? 2 : 0);
1085 n
|= (FD_ISSET(io
->fd
, &e
) ? 4 : 0);
1090 case EINTR
: goto AGAIN
;
1099 =item C<static ParrotIO * PIO_unix_pipe>
1101 Very limited C<exec> for now.
1103 XXX: Where does this fit, should it belong in the ParrotIOLayerAPI?
1109 PARROT_WARN_UNUSED_RESULT
1110 PARROT_CAN_RETURN_NULL
1112 PIO_unix_pipe(PARROT_INTERP
, SHIM(ParrotIOLayer
*l
), ARGIN(const char *cmd
), int flags
)
1115 * pipe(), fork() should be defined, if this header is present
1116 * if that's not true, we need a test
1118 # ifdef PARROT_HAS_HEADER_UNISTD
1119 int pid
, err
, fds
[2];
1126 /* Parent - return IO stream */
1127 if ((pid
= fork()) > 0) {
1128 ParrotIO
* const io
=
1129 PIO_new(interp
, PIO_F_PIPE
, 0, flags
& (PIO_F_READ
|PIO_F_WRITE
));
1130 if (flags
& PIO_F_READ
) {
1131 /* close this writer's end of pipe */
1136 else { /* assume write only for now */
1137 /* close this reader's end */
1145 /* Child - exec process */
1147 char *argv
[10], *p
, *c
;
1150 if (flags
& PIO_F_WRITE
) {
1151 /* the other end is writing - we read from the pipe */
1152 close(STDIN_FILENO
);
1154 if (Parrot_dup(fds
[0]) != STDIN_FILENO
) {
1159 /* XXX redirect stdout, stderr to pipe */
1160 close(STDIN_FILENO
);
1161 close(STDOUT_FILENO
);
1162 close(STDERR_FILENO
);
1163 if (Parrot_dup(fds
[0]) != STDIN_FILENO
1164 || Parrot_dup(fds
[1]) != STDOUT_FILENO
1165 || Parrot_dup(fds
[1]) != STDERR_FILENO
)
1171 * XXX ugly hack to be able to pass some arguments
1172 * split cmd at blanks
1175 for (n
= 0, p
= strtok(c
, " "); n
< 9 && p
; p
= strtok(NULL
, " ")) {
1181 execv(cmd
, argv
); /* XXX use execvp ? */
1182 /* Will never reach this unless exec fails. */
1192 Parrot_ex_throw_from_c_args(interp
, NULL
, EXCEPTION_UNIMPLEMENTED
,
1193 "pipe() unimplemented");
1199 const ParrotIOLayerAPI pio_unix_layer_api
= {
1202 PIO_base_delete_layer
,
1203 PIO_null_push_layer
,
1208 PIO_null_open_async
,
1212 PIO_null_write_async
,
1214 PIO_null_read_async
,
1220 PIO_null_setlinebuf
,
1224 # if PARROT_NET_DEVEL
1235 NULL
, /* no socket */
1236 NULL
, /* no connect */
1240 NULL
, /* no listen */
1241 NULL
/* no accept */
1246 #endif /* PIO_OS_UNIX */
1255 F<src/io/io_passdown.c>,
1256 F<src/io/io_stdio.c>,
1257 F<src/io/io_unix.c>,
1258 F<src/io/io_win32.c>,
1260 F<src/io/io_private.h>.
1264 Initially written by Melvin Smith (mrjoltcola@mindspring.com).
1273 * c-file-style: "parrot"
1275 * vim: expandtab shiftwidth=4: