4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2013 OmniTI Computer Consulting, Inc. All rights reserved.
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
29 /* All Rights Reserved */
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
34 #include <sys/param.h>
35 #include <sys/systm.h>
38 #include <sys/vnode.h>
40 #include <sys/stream.h>
41 #include <sys/strsubr.h>
42 #include <sys/errno.h>
43 #include <sys/debug.h>
44 #include <sys/fs/fifonode.h>
45 #include <sys/fcntl.h>
48 * This is the loadable module wrapper.
50 #include <sys/modctl.h>
51 #include <sys/syscall.h>
53 int pipe(intptr_t fds
, int);
55 static struct sysent pipe_sysent
= {
57 SE_ARGC
| SE_32RVAL1
| SE_NOUNLOAD
,
62 * Module linkage information for the kernel.
64 static struct modlsys modlsys
= {
65 &mod_syscallops
, "pipe(2) syscall", &pipe_sysent
68 #ifdef _SYSCALL32_IMPL
69 static struct modlsys modlsys32
= {
70 &mod_syscallops32
, "32-bit pipe(2) syscall", &pipe_sysent
74 static struct modlinkage modlinkage
= {
77 #ifdef _SYSCALL32_IMPL
86 return (mod_install(&modlinkage
));
96 _info(struct modinfo
*modinfop
)
98 return (mod_info(&modlinkage
, modinfop
));
102 * pipe(2) system call.
103 * Create a pipe by connecting two streams together. Associate
104 * each end of the pipe with a vnode, a file descriptor and
105 * one of the streams.
108 pipe(intptr_t arg
, int flags
)
111 struct file
*fp1
, *fp2
;
113 int flag1
, flag2
, iflags
;
117 * Validate allowed flags.
119 if ((flags
& ~(FCLOEXEC
|FNONBLOCK
)) != 0) {
120 return (set_errno(EINVAL
));
123 * Allocate and initialize two vnodes.
125 makepipe(&vp1
, &vp2
);
128 * Allocate and initialize two file table entries and two
129 * file pointers. Each file pointer is open for read and
132 if (error
= falloc(vp1
, FWRITE
|FREAD
, &fp1
, &fd1
)) {
135 return (set_errno(error
));
138 if (error
= falloc(vp2
, FWRITE
|FREAD
, &fp2
, &fd2
))
142 * Create two stream heads and attach to each vnode.
144 if (error
= fifo_stropen(&vp1
, FWRITE
|FREAD
, fp1
->f_cred
, 0, 0))
147 if (error
= fifo_stropen(&vp2
, FWRITE
|FREAD
, fp2
->f_cred
, 0, 0)) {
148 (void) fop_close(vp1
, FWRITE
|FREAD
, 1, (offset_t
)0,
155 VTOF(vp1
)->fn_ino
= VTOF(vp2
)->fn_ino
= fifogetid();
158 * Set the O_NONBLOCK flag if requested.
160 if (flags
& FNONBLOCK
) {
163 iflags
= flags
& FNONBLOCK
;
165 if (error
= fop_setfl(vp1
, flag1
, iflags
, fp1
->f_cred
, NULL
)) {
168 fp1
->f_flag
|= iflags
;
170 if (error
= fop_setfl(vp2
, flag2
, iflags
, fp2
->f_cred
, NULL
)) {
173 fp2
->f_flag
|= iflags
;
177 * Return the file descriptors to the user. They now
178 * point to two different vnodes which have different
181 if (copyout(&fd1
, &((int *)arg
)[0], sizeof (int)) ||
182 copyout(&fd2
, &((int *)arg
)[1], sizeof (int))) {
188 * Now fill in the entries that falloc reserved
190 mutex_exit(&fp1
->f_tlock
);
191 mutex_exit(&fp2
->f_tlock
);
196 * Optionally set the FCLOEXEC flag
198 if ((flags
& FCLOEXEC
) != 0) {
199 f_setfd(fd1
, FD_CLOEXEC
);
200 f_setfd(fd2
, FD_CLOEXEC
);
205 (void) fop_close(vp1
, FWRITE
|FREAD
, 1, (offset_t
)0, fp1
->f_cred
, NULL
);
206 (void) fop_close(vp2
, FWRITE
|FREAD
, 1, (offset_t
)0, fp2
->f_cred
, NULL
);
215 return (set_errno(error
));