xref: /illumos-gate/usr/src/lib/print/libpapi-lpd/common/lpd-misc.c (revision ed5289f91b9bf164dccd6c75398362be77a4478d)
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 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  */
27 
28 /* $Id: lpd-misc.c 155 2006-04-26 02:34:54Z ktou $ */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #define	__EXTENSIONS__	/* for strtok_r() */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <sys/types.h>
37 #include <fcntl.h>
38 #include <stdarg.h>
39 #include <string.h>
40 #include <signal.h>
41 #include <sys/socket.h>
42 #include <errno.h>
43 #include <wait.h>
44 #include <stropts.h>
45 #include <papi_impl.h>
46 
47 #include <config-site.h>
48 
49 char *
50 fdgets(char *buf, size_t len, int fd)
51 {
52 	char	tmp;
53 	int	count = 0;
54 
55 	memset(buf, 0, len);
56 	while ((count < len) && (read(fd, &tmp, 1) > 0))
57 		if ((buf[count++] = tmp) == '\n') break;
58 
59 	if (count != 0)
60 		return (buf);
61 	return (NULL);
62 }
63 
64 char *
65 queue_name_from_uri(uri_t *uri)
66 {
67 	char *result = NULL;
68 
69 	if ((uri != NULL) && (uri->path != NULL)) {
70 		char *ptr = strrchr(uri->path, '/');
71 
72 		if (ptr == NULL)
73 			result = uri->path;
74 		else
75 			result = ++ptr;
76 	}
77 
78 	return (result);
79 }
80 
81 static int
82 recvfd(int sockfd)
83 {
84 	int fd = -1;
85 #if defined(sun) && defined(unix) && defined(I_RECVFD)
86 	struct strrecvfd recv_fd;
87 
88 	memset(&recv_fd, NULL, sizeof (recv_fd));
89 	if (ioctl(sockfd, I_RECVFD, &recv_fd) == 0)
90 		fd = recv_fd.fd;
91 #else
92 	struct iovec    iov[1];
93 	struct msghdr   msg;
94 
95 #ifdef CMSG_DATA
96 	struct cmsghdr cmp[1];
97 	char buf[24];	/* send/recv 2 byte protocol */
98 
99 	memset(buf, 0, sizeof (buf));
100 
101 	iov[0].iov_base = buf;
102 	iov[0].iov_len = sizeof (buf);
103 
104 	msg.msg_control = cmp;
105 	msg.msg_controllen = sizeof (struct cmsghdr) + sizeof (int);
106 #else
107 	iov[0].iov_base = NULL;
108 	iov[0].iov_len = 0;
109 	msg.msg_accrights = (caddr_t)&fd;
110 	msg.msg_accrights = sizeof (fd);
111 #endif
112 	msg.msg_iov = iov;
113 	msg.msg_iovlen = 1;
114 	msg.msg_name = NULL;
115 	msg.msg_namelen = 0;
116 
117 	if (recvmsg(sockfd, &msg, 0) < 0)
118 		fd = -1;
119 #ifdef CMSG_DATA
120 	else
121 		fd = * (int *)CMSG_DATA(cmp);
122 #endif
123 #endif
124 	return (fd);
125 }
126 
127 int
128 lpd_open(service_t *svc, char type, char **args, int timeout)
129 {
130 	int ac, rc = -1, fds[2];
131 	pid_t pid;
132 	char *av[64], *tmp, buf[BUFSIZ];
133 
134 	if ((svc == NULL) || (svc->uri == NULL))
135 		return (-1);
136 
137 #ifndef SUID_LPD_PORT
138 #define	SUID_LPD_PORT "/usr/lib/print/lpd-port"
139 #endif
140 
141 	av[0] = SUID_LPD_PORT; ac = 1;
142 
143 	/* server */
144 	av[ac++] = "-H";
145 	av[ac++] = svc->uri->host;
146 
147 	/* timeout */
148 	if (timeout > 0) {
149 		snprintf(buf, sizeof (buf), "%d", timeout);
150 		av[ac++] = "-t";
151 		av[ac++] = strdup(buf);
152 	}
153 
154 	/* operation */
155 	snprintf(buf, sizeof (buf), "-%c", type);
156 	av[ac++] = buf;
157 
158 	/* queue */
159 	if ((tmp = strrchr(svc->uri->path, '/')) == NULL)
160 		tmp = svc->uri->path;
161 	else
162 		tmp++;
163 	av[ac++] = tmp;
164 
165 	/* args */
166 	if (args != NULL)
167 		while ((*args != NULL) && (ac < 62))
168 			av[ac++] = *args++;
169 
170 	av[ac++] = NULL;
171 
172 #if defined(sun) && defined(unix) && defined(I_RECVFD)
173 	pipe(fds);
174 #else
175 	socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
176 #endif
177 
178 	switch (pid = fork()) {
179 	case -1:	/* failed */
180 		break;
181 	case 0:	 /* child */
182 		dup2(fds[1], 1);
183 		execv(av[0], &av[0]);
184 		perror("exec");
185 		exit(1);
186 		break;
187 	default: {	/* parent */
188 		int err, status = 0;
189 
190 		while ((waitpid(pid, &status, 0) < 0) && (errno == EINTR));
191 		errno = WEXITSTATUS(status);
192 
193 		if (errno == 0)
194 			rc = recvfd(fds[0]);
195 
196 		err = errno;
197 		close(fds[0]);
198 		close(fds[1]);
199 		errno = err;
200 		}
201 	}
202 
203 	return (rc);
204 }
205