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