1*2264Sjacobs /*
2*2264Sjacobs  * CDDL HEADER START
3*2264Sjacobs  *
4*2264Sjacobs  * The contents of this file are subject to the terms of the
5*2264Sjacobs  * Common Development and Distribution License (the "License").
6*2264Sjacobs  * You may not use this file except in compliance with the License.
7*2264Sjacobs  *
8*2264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2264Sjacobs  * or http://www.opensolaris.org/os/licensing.
10*2264Sjacobs  * See the License for the specific language governing permissions
11*2264Sjacobs  * and limitations under the License.
12*2264Sjacobs  *
13*2264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
14*2264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
16*2264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
17*2264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2264Sjacobs  *
19*2264Sjacobs  * CDDL HEADER END
20*2264Sjacobs  */
21*2264Sjacobs 
22*2264Sjacobs /*
23*2264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*2264Sjacobs  * Use is subject to license terms.
25*2264Sjacobs  *
26*2264Sjacobs  */
27*2264Sjacobs 
28*2264Sjacobs /* $Id: lpd-misc.c 155 2006-04-26 02:34:54Z ktou $ */
29*2264Sjacobs 
30*2264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*2264Sjacobs 
32*2264Sjacobs #define	__EXTENSIONS__	/* for strtok_r() */
33*2264Sjacobs #include <stdio.h>
34*2264Sjacobs #include <stdlib.h>
35*2264Sjacobs #include <unistd.h>
36*2264Sjacobs #include <sys/types.h>
37*2264Sjacobs #include <fcntl.h>
38*2264Sjacobs #include <stdarg.h>
39*2264Sjacobs #include <string.h>
40*2264Sjacobs #include <signal.h>
41*2264Sjacobs #include <sys/socket.h>
42*2264Sjacobs #include <errno.h>
43*2264Sjacobs #include <wait.h>
44*2264Sjacobs #include <stropts.h>
45*2264Sjacobs #include <papi_impl.h>
46*2264Sjacobs 
47*2264Sjacobs #include <config-site.h>
48*2264Sjacobs 
49*2264Sjacobs char *
50*2264Sjacobs fdgets(char *buf, size_t len, int fd)
51*2264Sjacobs {
52*2264Sjacobs 	char	tmp;
53*2264Sjacobs 	int	count = 0;
54*2264Sjacobs 
55*2264Sjacobs 	memset(buf, 0, len);
56*2264Sjacobs 	while ((count < len) && (read(fd, &tmp, 1) > 0))
57*2264Sjacobs 		if ((buf[count++] = tmp) == '\n') break;
58*2264Sjacobs 
59*2264Sjacobs 	if (count != 0)
60*2264Sjacobs 		return (buf);
61*2264Sjacobs 	return (NULL);
62*2264Sjacobs }
63*2264Sjacobs 
64*2264Sjacobs char *
65*2264Sjacobs queue_name_from_uri(uri_t *uri)
66*2264Sjacobs {
67*2264Sjacobs 	char *result = NULL;
68*2264Sjacobs 
69*2264Sjacobs 	if ((uri != NULL) && (uri->path != NULL)) {
70*2264Sjacobs 		char *ptr = strrchr(uri->path, '/');
71*2264Sjacobs 
72*2264Sjacobs 		if (ptr == NULL)
73*2264Sjacobs 			result = uri->path;
74*2264Sjacobs 		else
75*2264Sjacobs 			result = ++ptr;
76*2264Sjacobs 	}
77*2264Sjacobs 
78*2264Sjacobs 	return (result);
79*2264Sjacobs }
80*2264Sjacobs 
81*2264Sjacobs static int
82*2264Sjacobs recvfd(int sockfd)
83*2264Sjacobs {
84*2264Sjacobs 	int fd = -1;
85*2264Sjacobs #if defined(sun) && defined(unix) && defined(I_RECVFD)
86*2264Sjacobs 	struct strrecvfd recv_fd;
87*2264Sjacobs 
88*2264Sjacobs 	memset(&recv_fd, NULL, sizeof (recv_fd));
89*2264Sjacobs 	if (ioctl(sockfd, I_RECVFD, &recv_fd) == 0)
90*2264Sjacobs 		fd = recv_fd.fd;
91*2264Sjacobs #else
92*2264Sjacobs 	struct iovec    iov[1];
93*2264Sjacobs 	struct msghdr   msg;
94*2264Sjacobs 
95*2264Sjacobs #ifdef CMSG_DATA
96*2264Sjacobs 	struct cmsghdr cmp[1];
97*2264Sjacobs 	char buf[24];	/* send/recv 2 byte protocol */
98*2264Sjacobs 
99*2264Sjacobs 	memset(buf, 0, sizeof (buf));
100*2264Sjacobs 
101*2264Sjacobs 	iov[0].iov_base = buf;
102*2264Sjacobs 	iov[0].iov_len = sizeof (buf);
103*2264Sjacobs 
104*2264Sjacobs 	msg.msg_control = cmp;
105*2264Sjacobs 	msg.msg_controllen = sizeof (struct cmsghdr) + sizeof (int);
106*2264Sjacobs #else
107*2264Sjacobs 	iov[0].iov_base = NULL;
108*2264Sjacobs 	iov[0].iov_len = 0;
109*2264Sjacobs 	msg.msg_accrights = (caddr_t)&fd;
110*2264Sjacobs 	msg.msg_accrights = sizeof (fd);
111*2264Sjacobs #endif
112*2264Sjacobs 	msg.msg_iov = iov;
113*2264Sjacobs 	msg.msg_iovlen = 1;
114*2264Sjacobs 	msg.msg_name = NULL;
115*2264Sjacobs 	msg.msg_namelen = 0;
116*2264Sjacobs 
117*2264Sjacobs 	if (recvmsg(sockfd, &msg, 0) < 0)
118*2264Sjacobs 		fd = -1;
119*2264Sjacobs #ifdef CMSG_DATA
120*2264Sjacobs 	else
121*2264Sjacobs 		fd = * (int *)CMSG_DATA(cmp);
122*2264Sjacobs #endif
123*2264Sjacobs #endif
124*2264Sjacobs 	return (fd);
125*2264Sjacobs }
126*2264Sjacobs 
127*2264Sjacobs int
128*2264Sjacobs lpd_open(service_t *svc, char type, char **args, int timeout)
129*2264Sjacobs {
130*2264Sjacobs 	int ac, rc = -1, fds[2];
131*2264Sjacobs 	pid_t pid;
132*2264Sjacobs 	char *av[64], buf[BUFSIZ];
133*2264Sjacobs 
134*2264Sjacobs 	if ((svc == NULL) || (svc->uri == NULL))
135*2264Sjacobs 		return (-1);
136*2264Sjacobs 
137*2264Sjacobs #ifndef SUID_LPD_PORT
138*2264Sjacobs #define	SUID_LPD_PORT "/usr/lib/print/lpd-port"
139*2264Sjacobs #endif
140*2264Sjacobs 
141*2264Sjacobs 	av[0] = SUID_LPD_PORT; ac = 1;
142*2264Sjacobs 	uri_to_string(svc->uri, buf, sizeof (buf));
143*2264Sjacobs 	av[ac++] = "-u";
144*2264Sjacobs 	av[ac++] = strdup(buf);
145*2264Sjacobs 
146*2264Sjacobs 	if (timeout > 0) {
147*2264Sjacobs 		snprintf(buf, sizeof (buf), "%d", timeout);
148*2264Sjacobs 		av[ac++] = "-t";
149*2264Sjacobs 		av[ac++] = strdup(buf);
150*2264Sjacobs 	}
151*2264Sjacobs 	snprintf(buf, sizeof (buf), "-%c", type);
152*2264Sjacobs 	av[ac++] = buf;
153*2264Sjacobs 
154*2264Sjacobs 	if (args != NULL)
155*2264Sjacobs 		while ((*args != NULL) && (ac < 62))
156*2264Sjacobs 			av[ac++] = *args++;
157*2264Sjacobs 
158*2264Sjacobs 	av[ac++] = NULL;
159*2264Sjacobs 
160*2264Sjacobs #if defined(sun) && defined(unix) && defined(I_RECVFD)
161*2264Sjacobs 	pipe(fds);
162*2264Sjacobs #else
163*2264Sjacobs 	socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
164*2264Sjacobs #endif
165*2264Sjacobs 
166*2264Sjacobs 	switch (pid = fork()) {
167*2264Sjacobs 	case -1:	/* failed */
168*2264Sjacobs 		break;
169*2264Sjacobs 	case 0:	 /* child */
170*2264Sjacobs 		dup2(fds[1], 1);
171*2264Sjacobs 		execv(av[0], &av[0]);
172*2264Sjacobs 		perror("exec");
173*2264Sjacobs 		exit(1);
174*2264Sjacobs 		break;
175*2264Sjacobs 	default: {	/* parent */
176*2264Sjacobs 		int err, status = 0;
177*2264Sjacobs 
178*2264Sjacobs 		while ((waitpid(pid, &status, 0) < 0) && (errno == EINTR));
179*2264Sjacobs 		errno = WEXITSTATUS(status);
180*2264Sjacobs 
181*2264Sjacobs 		if (errno == 0)
182*2264Sjacobs 			rc = recvfd(fds[0]);
183*2264Sjacobs 
184*2264Sjacobs 		err = errno;
185*2264Sjacobs 		close(fds[0]);
186*2264Sjacobs 		close(fds[1]);
187*2264Sjacobs 		errno = err;
188*2264Sjacobs 		}
189*2264Sjacobs 	}
190*2264Sjacobs 
191*2264Sjacobs 	return (rc);
192*2264Sjacobs }
193