12264Sjacobs /*
22264Sjacobs  * CDDL HEADER START
32264Sjacobs  *
42264Sjacobs  * The contents of this file are subject to the terms of the
52264Sjacobs  * Common Development and Distribution License (the "License").
62264Sjacobs  * You may not use this file except in compliance with the License.
72264Sjacobs  *
82264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs  * or http://www.opensolaris.org/os/licensing.
102264Sjacobs  * See the License for the specific language governing permissions
112264Sjacobs  * and limitations under the License.
122264Sjacobs  *
132264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs  *
192264Sjacobs  * CDDL HEADER END
202264Sjacobs  */
212264Sjacobs 
222264Sjacobs /*
23*4275Sjacobs  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
242264Sjacobs  * Use is subject to license terms.
252264Sjacobs  *
262264Sjacobs  */
272264Sjacobs 
282264Sjacobs /* $Id: lpd-misc.c 155 2006-04-26 02:34:54Z ktou $ */
292264Sjacobs 
302264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
312264Sjacobs 
322264Sjacobs #define	__EXTENSIONS__	/* for strtok_r() */
332264Sjacobs #include <stdio.h>
342264Sjacobs #include <stdlib.h>
352264Sjacobs #include <unistd.h>
362264Sjacobs #include <sys/types.h>
372264Sjacobs #include <fcntl.h>
382264Sjacobs #include <stdarg.h>
392264Sjacobs #include <string.h>
402264Sjacobs #include <signal.h>
412264Sjacobs #include <sys/socket.h>
422264Sjacobs #include <errno.h>
432264Sjacobs #include <wait.h>
442264Sjacobs #include <stropts.h>
452264Sjacobs #include <papi_impl.h>
462264Sjacobs 
472264Sjacobs #include <config-site.h>
482264Sjacobs 
492264Sjacobs char *
502264Sjacobs fdgets(char *buf, size_t len, int fd)
512264Sjacobs {
522264Sjacobs 	char	tmp;
532264Sjacobs 	int	count = 0;
542264Sjacobs 
552264Sjacobs 	memset(buf, 0, len);
562264Sjacobs 	while ((count < len) && (read(fd, &tmp, 1) > 0))
572264Sjacobs 		if ((buf[count++] = tmp) == '\n') break;
582264Sjacobs 
592264Sjacobs 	if (count != 0)
602264Sjacobs 		return (buf);
612264Sjacobs 	return (NULL);
622264Sjacobs }
632264Sjacobs 
642264Sjacobs char *
652264Sjacobs queue_name_from_uri(uri_t *uri)
662264Sjacobs {
672264Sjacobs 	char *result = NULL;
682264Sjacobs 
692264Sjacobs 	if ((uri != NULL) && (uri->path != NULL)) {
702264Sjacobs 		char *ptr = strrchr(uri->path, '/');
712264Sjacobs 
722264Sjacobs 		if (ptr == NULL)
732264Sjacobs 			result = uri->path;
742264Sjacobs 		else
752264Sjacobs 			result = ++ptr;
762264Sjacobs 	}
772264Sjacobs 
782264Sjacobs 	return (result);
792264Sjacobs }
802264Sjacobs 
812264Sjacobs static int
822264Sjacobs recvfd(int sockfd)
832264Sjacobs {
842264Sjacobs 	int fd = -1;
852264Sjacobs #if defined(sun) && defined(unix) && defined(I_RECVFD)
862264Sjacobs 	struct strrecvfd recv_fd;
872264Sjacobs 
882264Sjacobs 	memset(&recv_fd, NULL, sizeof (recv_fd));
892264Sjacobs 	if (ioctl(sockfd, I_RECVFD, &recv_fd) == 0)
902264Sjacobs 		fd = recv_fd.fd;
912264Sjacobs #else
922264Sjacobs 	struct iovec    iov[1];
932264Sjacobs 	struct msghdr   msg;
942264Sjacobs 
952264Sjacobs #ifdef CMSG_DATA
962264Sjacobs 	struct cmsghdr cmp[1];
972264Sjacobs 	char buf[24];	/* send/recv 2 byte protocol */
982264Sjacobs 
992264Sjacobs 	memset(buf, 0, sizeof (buf));
1002264Sjacobs 
1012264Sjacobs 	iov[0].iov_base = buf;
1022264Sjacobs 	iov[0].iov_len = sizeof (buf);
1032264Sjacobs 
1042264Sjacobs 	msg.msg_control = cmp;
1052264Sjacobs 	msg.msg_controllen = sizeof (struct cmsghdr) + sizeof (int);
1062264Sjacobs #else
1072264Sjacobs 	iov[0].iov_base = NULL;
1082264Sjacobs 	iov[0].iov_len = 0;
1092264Sjacobs 	msg.msg_accrights = (caddr_t)&fd;
1102264Sjacobs 	msg.msg_accrights = sizeof (fd);
1112264Sjacobs #endif
1122264Sjacobs 	msg.msg_iov = iov;
1132264Sjacobs 	msg.msg_iovlen = 1;
1142264Sjacobs 	msg.msg_name = NULL;
1152264Sjacobs 	msg.msg_namelen = 0;
1162264Sjacobs 
1172264Sjacobs 	if (recvmsg(sockfd, &msg, 0) < 0)
1182264Sjacobs 		fd = -1;
1192264Sjacobs #ifdef CMSG_DATA
1202264Sjacobs 	else
1212264Sjacobs 		fd = * (int *)CMSG_DATA(cmp);
1222264Sjacobs #endif
1232264Sjacobs #endif
1242264Sjacobs 	return (fd);
1252264Sjacobs }
1262264Sjacobs 
1272264Sjacobs int
1282264Sjacobs lpd_open(service_t *svc, char type, char **args, int timeout)
1292264Sjacobs {
1302264Sjacobs 	int ac, rc = -1, fds[2];
1312264Sjacobs 	pid_t pid;
132*4275Sjacobs 	char *av[64], *tmp, buf[BUFSIZ];
1332264Sjacobs 
1342264Sjacobs 	if ((svc == NULL) || (svc->uri == NULL))
1352264Sjacobs 		return (-1);
1362264Sjacobs 
1372264Sjacobs #ifndef SUID_LPD_PORT
1382264Sjacobs #define	SUID_LPD_PORT "/usr/lib/print/lpd-port"
1392264Sjacobs #endif
1402264Sjacobs 
1412264Sjacobs 	av[0] = SUID_LPD_PORT; ac = 1;
1422264Sjacobs 
143*4275Sjacobs 	/* server */
144*4275Sjacobs 	av[ac++] = "-H";
145*4275Sjacobs 	av[ac++] = svc->uri->host;
146*4275Sjacobs 
147*4275Sjacobs 	/* timeout */
1482264Sjacobs 	if (timeout > 0) {
1492264Sjacobs 		snprintf(buf, sizeof (buf), "%d", timeout);
1502264Sjacobs 		av[ac++] = "-t";
1512264Sjacobs 		av[ac++] = strdup(buf);
1522264Sjacobs 	}
153*4275Sjacobs 
154*4275Sjacobs 	/* operation */
1552264Sjacobs 	snprintf(buf, sizeof (buf), "-%c", type);
1562264Sjacobs 	av[ac++] = buf;
1572264Sjacobs 
158*4275Sjacobs 	/* queue */
159*4275Sjacobs 	if ((tmp = strrchr(svc->uri->path, '/')) == NULL)
160*4275Sjacobs 		tmp = svc->uri->path;
161*4275Sjacobs 	else
162*4275Sjacobs 		tmp++;
163*4275Sjacobs 	av[ac++] = tmp;
164*4275Sjacobs 
165*4275Sjacobs 	/* args */
1662264Sjacobs 	if (args != NULL)
1672264Sjacobs 		while ((*args != NULL) && (ac < 62))
1682264Sjacobs 			av[ac++] = *args++;
1692264Sjacobs 
1702264Sjacobs 	av[ac++] = NULL;
1712264Sjacobs 
1722264Sjacobs #if defined(sun) && defined(unix) && defined(I_RECVFD)
1732264Sjacobs 	pipe(fds);
1742264Sjacobs #else
1752264Sjacobs 	socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
1762264Sjacobs #endif
1772264Sjacobs 
1782264Sjacobs 	switch (pid = fork()) {
1792264Sjacobs 	case -1:	/* failed */
1802264Sjacobs 		break;
1812264Sjacobs 	case 0:	 /* child */
1822264Sjacobs 		dup2(fds[1], 1);
1832264Sjacobs 		execv(av[0], &av[0]);
1842264Sjacobs 		perror("exec");
1852264Sjacobs 		exit(1);
1862264Sjacobs 		break;
1872264Sjacobs 	default: {	/* parent */
1882264Sjacobs 		int err, status = 0;
1892264Sjacobs 
1902264Sjacobs 		while ((waitpid(pid, &status, 0) < 0) && (errno == EINTR));
1912264Sjacobs 		errno = WEXITSTATUS(status);
1922264Sjacobs 
1932264Sjacobs 		if (errno == 0)
1942264Sjacobs 			rc = recvfd(fds[0]);
1952264Sjacobs 
1962264Sjacobs 		err = errno;
1972264Sjacobs 		close(fds[0]);
1982264Sjacobs 		close(fds[1]);
1992264Sjacobs 		errno = err;
2002264Sjacobs 		}
2012264Sjacobs 	}
2022264Sjacobs 
2032264Sjacobs 	return (rc);
2042264Sjacobs }
205