xref: /illumos-gate/usr/src/cmd/lp/lib/msgs/mconnect.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 /* LINTLIBRARY */
32 
33 # include	<unistd.h>
34 # include	<fcntl.h>
35 # include	<errno.h>
36 # include	<sys/utsname.h>
37 # include	<stdlib.h>
38 # include	<sys/types.h>
39 # include	<sys/stat.h>
40 
41 #include "lp.h"
42 #include "msgs.h"
43 
44 #define TURN_OFF(X,F)	(void)Fcntl(X, F_SETFL, (Fcntl(X, F_GETFL, 0) & ~(F)))
45 
46 #if	defined(__STDC__)
47 static int	checklock ( void );
48 #else
49 static int	checklock();
50 #endif
51 
52 /*
53 ** mconnect() - OPEN A MESSAGE PATH
54 */
55 
56 #if	defined(__STDC__)
57 MESG * mconnect ( char * path, int id1, int id2 )
58 #else
59 MESG * mconnect ()
60     char	*path;
61     int		id1;
62     int		id2;
63 #endif
64 {
65     int		fd;
66     int		wronly = 0;
67     int		count = 0;
68     MESG	*md;
69     struct stat	stbuf;
70 
71     /*
72     **	invoked as mconnect(path, 0, 0)
73     **
74     **	Open <path>, if isastream() is true for the returned file
75     **	descriptor, then we're done.
76     */
77 
78     if (path)
79     {
80 	/*
81 	**	Verify that the spooler is running and that the
82 	**	<path> identifies a pipe.
83 	**	This prevents us from getting hung in the open
84 	**	and from thinking the <path> is a non-streams pipe.
85 	*/
86 	if (checklock() == -1)
87 	    return(NULL);
88 Again:	if (stat(path, &stbuf) == -1)
89 	    return(NULL);
90 	if ((stbuf.st_mode & S_IFMT) != S_IFIFO) {
91             if (count++ > 20)
92 		return (NULL);
93 	    sleep(1);
94 	    goto Again;
95 	}
96 
97 	if ((fd = Open(path, O_RDWR, 0)) == -1)
98 	    if ((fd = Open(path, O_WRONLY, 0)) == -1)
99 		return(NULL);
100 	    else
101 		wronly = 1;
102 
103 	if (isastream(fd) && !wronly)
104 	{
105 #if	defined(NOCONNLD)
106 	    int		fds[2];
107 
108 	    if (pipe(fds) != 0)
109 		return(NULL);
110 
111 	    if (ioctl(fd, I_SENDFD, fds[1]) != 0)
112 		return(NULL);
113 
114 	    (void)_Close(fd);
115 
116 	    fd = fds[0];
117 	    (void)_Close(fds[1]);
118 #endif
119 
120 	    if ((md = (MESG *)Malloc(MDSIZE)) == NULL)
121 	    {
122 		errno = ENOMEM;
123 		return(NULL);
124 	    }
125 
126 	    memset(md, 0, sizeof (MESG));
127 	    md->gid = getgid();
128 	    md->on_discon = NULL;
129 	    md->readfd = fd;
130 	    md->state = MDS_IDLE;
131 	    md->type = MD_STREAM;
132 	    md->uid = getuid();
133 	    md->writefd = fd;
134 
135 	    ResetFifoBuffer (md->readfd);
136 	    return(md);
137 	}
138 
139 	return(NULL);
140     }
141 
142     if (id1 > 0 && id2 > 0)
143     {
144 	if ((md = (MESG *)Malloc(MDSIZE)) == NULL)
145 	{
146 	    errno = ENOMEM;
147 	    return(NULL);
148 	}
149 
150 	memset(md, 0, sizeof (MESG));
151 	md->gid = getgid();
152 	md->on_discon = NULL;
153 	md->readfd = id1;
154 	md->state = MDS_IDLE;
155 	md->type = MD_BOUND;
156 	md->uid = getuid();
157 	md->writefd = id2;
158 
159 	ResetFifoBuffer (md->readfd);
160 
161 	return(md);
162     }
163 
164     errno = EINVAL;
165     return(NULL);
166 }
167 
168 #if	defined(__STDC__)
169 static int checklock ( void )
170 #else
171 static int checklock()
172 #endif
173 {
174     int			fd;
175     struct flock	lock;
176 
177     if ((fd = Open(Lp_Schedlock, O_RDONLY, 0666)) == -1)
178 	return (-1);
179 
180     /*
181      * Now, we try to read-lock the lock file. This can only succeed if
182      * the Spooler (lpsched) is down.
183      */
184 
185     lock.l_type = F_RDLCK;
186     lock.l_whence = 0;
187     lock.l_start = 0;
188     lock.l_len = 0;	/* till end of file */
189 
190     if (Fcntl(fd, F_SETLK, &lock) != -1 || errno != EAGAIN)
191     {
192 	(void)Close (fd);
193 	return (-1);
194     }
195 
196     /*
197      * We can get here only when fcntl() == -1 && errno == EAGAIN,
198      * i.e., spooler (lpsched) is running.
199      */
200 
201     (void)Close (fd);
202 
203     return(0);
204 }
205