#define __EXTENSIONS__
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <errno.h>
#include <wait.h>
#include <stropts.h>
#include <papi_impl.h>
#include <config-site.h>
char *
fdgets(char *buf, size_t len, int fd)
{
char tmp;
int count = 0;
memset(buf, 0, len);
while ((count < len) && (read(fd, &tmp, 1) > 0))
if ((buf[count++] = tmp) == '\n') break;
if (count != 0)
return (buf);
return (NULL);
}
char *
queue_name_from_uri(uri_t *uri)
{
char *result = NULL;
if ((uri != NULL) && (uri->path != NULL)) {
char *ptr = strrchr(uri->path, '/');
if (ptr == NULL)
result = uri->path;
else
result = ++ptr;
}
return (result);
}
static int
recvfd(int sockfd)
{
int fd = -1;
#if defined(sun) && defined(unix) && defined(I_RECVFD)
struct strrecvfd recv_fd;
memset(&recv_fd, 0, sizeof (recv_fd));
if (ioctl(sockfd, I_RECVFD, &recv_fd) == 0)
fd = recv_fd.fd;
#else
struct iovec iov[1];
struct msghdr msg;
#ifdef CMSG_DATA
struct cmsghdr cmp[1];
char buf[24];
memset(buf, 0, sizeof (buf));
iov[0].iov_base = buf;
iov[0].iov_len = sizeof (buf);
msg.msg_control = cmp;
msg.msg_controllen = sizeof (struct cmsghdr) + sizeof (int);
#else
iov[0].iov_base = NULL;
iov[0].iov_len = 0;
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrights = sizeof (fd);
#endif
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
if (recvmsg(sockfd, &msg, 0) < 0)
fd = -1;
#ifdef CMSG_DATA
else
fd = * (int *)CMSG_DATA(cmp);
#endif
#endif
return (fd);
}
int
lpd_open(service_t *svc, char type, char **args, int timeout)
{
int ac, rc = -1, fds[2];
pid_t pid;
char *av[64], *tmp, buf[BUFSIZ];
if ((svc == NULL) || (svc->uri == NULL))
return (-1);
#ifndef SUID_LPD_PORT
#define SUID_LPD_PORT "/usr/lib/print/lpd-port"
#endif
av[0] = SUID_LPD_PORT;
ac = 1;
av[ac++] = "-H";
av[ac++] = svc->uri->host;
if (timeout > 0) {
snprintf(buf, sizeof (buf), "%d", timeout);
av[ac++] = "-t";
av[ac++] = strdup(buf);
}
snprintf(buf, sizeof (buf), "-%c", type);
av[ac++] = buf;
if (svc->uri->path == NULL) {
tmp = "";
} else {
if ((tmp = strrchr(svc->uri->path, '/')) == NULL)
tmp = svc->uri->path;
else
tmp++;
}
av[ac++] = tmp;
if (args != NULL)
while ((*args != NULL) && (ac < 62))
av[ac++] = *args++;
av[ac++] = NULL;
#if defined(sun) && defined(unix) && defined(I_RECVFD)
pipe(fds);
#else
socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
#endif
switch (pid = fork()) {
case -1:
break;
case 0:
dup2(fds[1], 1);
execv(av[0], &av[0]);
perror("exec");
exit(1);
break;
default: {
int err, status = 0;
while ((waitpid(pid, &status, 0) < 0) && (errno == EINTR))
;
errno = WEXITSTATUS(status);
if (errno == 0)
rc = recvfd(fds[0]);
err = errno;
close(fds[0]);
close(fds[1]);
errno = err;
}
}
return (rc);
}