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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright (c) 1990-1996 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27#ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <unistd.h>
30#include <sys/errno.h>
31#include <sys/fcntl.h>
32#include <sys/filio.h>
33#include <sys/ioccom.h>
34#include <sys/syscall.h>
35
36
37/* The following is an array of fcntl commands. The numbers listed
38 * below are from SVR4. Array is indexed with SunOS 4.1 numbers to
39 * obtain the SVR4 numbers.
40 */
41int cmd_op[14] = {0, 1, 2, 3, 4, 23, 24, 14, 6, 7, 21, 20, -1, 22};
42
43/* SVR4/SunOS 5.0 equivalent modes */
44#define N_O_NDELAY      0x04
45#define N_O_SYNC	0x10
46#define N_O_NONBLOCK    0x80
47#define N_O_CREAT       0x100
48#define N_O_TRUNC       0x200
49#define N_O_EXCL	0x400
50
51#define	S5_FASYNC 0x1000
52
53/* from SVR4 stropts.h */
54#define	S5_S_RDNORM		0x0040
55#define	S5_S_WRNORM		0x0004
56#define	S5_S_RDBAND		0x0080
57#define	S5_S_BANDURG		0x0200
58#define	S5_I_SETSIG		(('S'<<8)|011)
59#define	S5_I_GETSIG		(('S'<<8)|012)
60
61/* Mask corresponding to the bits above in SunOS 4.x */
62#define FLAGS_MASK      (O_SYNC|O_NONBLOCK|O_CREAT|O_TRUNC|O_EXCL \
63			|O_NDELAY|FNBIO|FASYNC)
64#define N_FLAGS_MASK    (N_O_NDELAY|N_O_SYNC|N_O_NONBLOCK|N_O_CREAT \
65			|N_O_TRUNC|N_O_EXCL|S5_FASYNC)
66
67struct n_flock {
68	short	l_type;
69	short	l_whence;
70	long	l_start;
71	long	l_len;	  /* len == 0 means until end of file */
72	long	l_sysid;
73	long	l_pid;
74	long	pad[4];	 /* reserve area */
75} ;
76
77
78int fcntl(fd, cmd, arg)
79int fd, cmd, arg;
80{
81	return(bc_fcntl(fd, cmd, arg));
82}
83
84
85int bc_fcntl(fd, cmd, arg)
86int fd, cmd, arg;
87{
88	int fds, ret;
89	struct flock *savarg;
90	struct n_flock nfl;
91	extern int errno;
92	int i, narg;
93
94	if ((cmd == F_SETOWN) || (cmd == F_GETOWN)) {
95		ret = _s_fcntl(fd, cmd_op[cmd], arg);
96		if ((ret != -1) || (errno != EINVAL))
97			return (ret);
98		else {
99			if (cmd == F_GETOWN) {
100				if (_ioctl(fd, S5_I_GETSIG, &i) < 0) {
101					if (errno == EINVAL)
102						i = 0;
103					else
104						return (-1);
105				}
106				if (i & (S5_S_RDBAND|S5_S_BANDURG|
107				    S5_S_RDNORM|S5_S_WRNORM))
108					return (getpid());
109				return (0);
110			} else { /* cmd == F_SETOWN */
111				i = S5_S_RDNORM|S5_S_WRNORM|S5_S_RDBAND|S5_S_BANDURG;
112				return (ioctl(fd, S5_I_SETSIG, i));
113			}
114		}
115	}
116	if (cmd == F_SETFL) {
117		if (arg & FLAGS_MASK) {
118			narg = arg & ~FLAGS_MASK;
119			if (arg & FASYNC)
120				narg |= S5_FASYNC;
121			if (arg & O_SYNC)
122				narg |= N_O_SYNC;
123			if (arg & O_CREAT)
124				narg |= N_O_CREAT;
125			if (arg & O_TRUNC)
126				narg |= N_O_TRUNC;
127			if (arg & O_EXCL)
128				narg |= N_O_EXCL;
129			if (arg & (O_NDELAY))
130				narg |= N_O_NDELAY;
131			if (arg & O_NONBLOCK)
132				narg |= N_O_NONBLOCK;
133			if (arg & FNBIO)
134				narg |= N_O_NDELAY;
135			arg = narg;
136		}
137	} else if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK)  {
138		if (arg == 0 || arg == -1) {
139			errno = EFAULT;
140			return(-1);
141		}
142		savarg = (struct flock *)arg;
143		arg = (int) &nfl;
144		nfl.l_type = savarg->l_type;
145		nfl.l_whence = savarg->l_whence;
146		nfl.l_start = savarg->l_start;
147		nfl.l_len = savarg->l_len;
148		nfl.l_pid = savarg->l_pid;
149	}
150
151	ret = _s_fcntl(fd, cmd_op[cmd], arg);
152
153	if (ret != -1) {
154		if (cmd == F_DUPFD) {
155			if ((fds = fd_get(fd)) != -1)
156				fd_add(ret, fds);
157		} else if (cmd == F_GETFL) {
158			if (ret & N_FLAGS_MASK) {
159				narg = ret & ~N_FLAGS_MASK;
160				if (ret & S5_FASYNC)
161					narg |= FASYNC;
162				if (ret & N_O_SYNC)
163					narg |= O_SYNC;
164				if (ret & N_O_NONBLOCK)
165					narg |= O_NONBLOCK;
166				if (ret & N_O_CREAT)
167					narg |= O_CREAT;
168				if (ret & N_O_TRUNC)
169					narg |= O_TRUNC;
170				if (ret & N_O_EXCL)
171					narg |= O_EXCL;
172				if (ret & (N_O_NDELAY))
173					narg |= O_NDELAY;
174				ret = narg;
175			}
176		} else if (cmd == F_SETLK || cmd == F_SETLKW ||
177			cmd == F_GETLK) {
178			savarg->l_type = nfl.l_type;
179			savarg->l_whence = nfl.l_whence;
180			savarg->l_start = nfl.l_start;
181			savarg->l_len = nfl.l_len;
182			savarg->l_pid = nfl.l_pid;
183			arg = (int) savarg;
184		}
185	}
186	return(ret);
187}
188