1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29
30 #pragma ident "%Z%%M% %I% %E% SMI" /* from SVr4.0 1.11 */
31
32 #include <sys/types.h>
33 #include <sys/sysmacros.h>
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/cred.h>
37 #include <sys/user.h>
38 #include <sys/vnode.h>
39 #include <sys/file.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
46 /*
47 * This is the loadable module wrapper.
48 */
49 #include <sys/modctl.h>
50 #include <sys/syscall.h>
51
52 char _depends_on[] = "fs/fifofs";
53
54 longlong_t pipe();
55
56 static struct sysent pipe_sysent = {
57 0,
58 SE_32RVAL1 | SE_32RVAL2 | SE_NOUNLOAD | SE_ARGC,
59 (int (*)())pipe
60 };
61
62 /*
63 * Module linkage information for the kernel.
64 */
65 static struct modlsys modlsys = {
66 &mod_syscallops, "pipe(2) syscall", &pipe_sysent
67 };
68
69 #ifdef _SYSCALL32_IMPL
70 static struct modlsys modlsys32 = {
71 &mod_syscallops32, "32-bit pipe(2) syscall", &pipe_sysent
72 };
73 #endif
74
75 static struct modlinkage modlinkage = {
76 MODREV_1,
77 &modlsys,
78 #ifdef _SYSCALL32_IMPL
79 &modlsys32,
80 #endif
81 NULL
82 };
83
84 int
_init(void)85 _init(void)
86 {
87 return (mod_install(&modlinkage));
88 }
89
90 int
_fini(void)91 _fini(void)
92 {
93 return (EBUSY);
94 }
95
96 int
_info(struct modinfo * modinfop)97 _info(struct modinfo *modinfop)
98 {
99 return (mod_info(&modlinkage, modinfop));
100 }
101
102 /*
103 * pipe(2) system call.
104 * Create a pipe by connecting two streams together. Associate
105 * each end of the pipe with a vnode, a file descriptor and
106 * one of the streams.
107 */
108 longlong_t
pipe()109 pipe()
110 {
111 vnode_t *vp1, *vp2;
112 struct file *fp1, *fp2;
113 int error = 0;
114 int fd1, fd2;
115 rval_t r;
116
117 /*
118 * Allocate and initialize two vnodes.
119 */
120 makepipe(&vp1, &vp2);
121
122 /*
123 * Allocate and initialize two file table entries and two
124 * file pointers. Each file pointer is open for read and
125 * write.
126 */
127 if (error = falloc(vp1, FWRITE|FREAD, &fp1, &fd1)) {
128 VN_RELE(vp1);
129 VN_RELE(vp2);
130 return ((longlong_t)set_errno(error));
131 }
132
133 if (error = falloc(vp2, FWRITE|FREAD, &fp2, &fd2))
134 goto out2;
135
136 /*
137 * Create two stream heads and attach to each vnode.
138 */
139 if (error = fifo_stropen(&vp1, FWRITE|FREAD, fp1->f_cred, 0, 0))
140 goto out;
141
142 if (error = fifo_stropen(&vp2, FWRITE|FREAD, fp2->f_cred, 0, 0)) {
143 (void) VOP_CLOSE(vp1, FWRITE|FREAD, 1, (offset_t)0,
144 fp1->f_cred, NULL);
145 goto out;
146 }
147
148 strmate(vp1, vp2);
149
150 VTOF(vp1)->fn_ino = VTOF(vp2)->fn_ino = fifogetid();
151
152 /*
153 * Now fill in the entries that falloc reserved
154 */
155 mutex_exit(&fp1->f_tlock);
156 mutex_exit(&fp2->f_tlock);
157 setf(fd1, fp1);
158 setf(fd2, fp2);
159
160 /*
161 * Return the file descriptors to the user. They now
162 * point to two different vnodes which have different
163 * stream heads.
164 */
165 r.r_val1 = fd1;
166 r.r_val2 = fd2;
167 return (r.r_vals);
168 out:
169 unfalloc(fp2);
170 setf(fd2, NULL);
171 out2:
172 unfalloc(fp1);
173 setf(fd1, NULL);
174 VN_RELE(vp1);
175 VN_RELE(vp2);
176 return ((longlong_t)set_errno(error));
177 }
178