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