283 lines
4.3 KiB
C
283 lines
4.3 KiB
C
/*
|
|
* pserver.c
|
|
*
|
|
* Copyright (C) 1996 by Volker Lendecke
|
|
*
|
|
*/
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <signal.h>
|
|
#include "ncplib.h"
|
|
|
|
struct nw_queue {
|
|
struct ncp_conn *conn;
|
|
|
|
char queue_name[NCP_BINDERY_NAME_LEN];
|
|
__u32 queue_id;
|
|
__u16 job_type;
|
|
|
|
char *command;
|
|
};
|
|
|
|
static struct nw_queue q;
|
|
|
|
static int term_request;
|
|
|
|
static int
|
|
init_queue(struct ncp_conn *conn, char *queue_name,
|
|
char *command, struct nw_queue *q);
|
|
|
|
static int
|
|
poll_queue(struct nw_queue *q);
|
|
|
|
void
|
|
usage(void)
|
|
{
|
|
/* Obviously, there's more to do */
|
|
return;
|
|
}
|
|
|
|
#ifndef NCP_BINDERY_PSERVER
|
|
#define NCP_BINDERY_PSERVER (0x0007)
|
|
#endif
|
|
|
|
static void
|
|
terminate_handler()
|
|
{
|
|
signal(SIGTERM,terminate_handler);
|
|
term_request=1;
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
daemonize()
|
|
{
|
|
int fd,c;
|
|
|
|
if ((c = fork()) > 0) exit(0);
|
|
if (c < 0)
|
|
{
|
|
fprintf(stderr, "ipxripd: can't fork: %s\n",strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
close(0);
|
|
close(1);
|
|
close(2);
|
|
if ((fd = open("/dev/tty", O_RDWR)) >= 0)
|
|
{
|
|
ioctl(fd, TIOCNOTTY, NULL);
|
|
close(fd);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
struct ncp_conn conn;
|
|
int poll_timeout = 30;
|
|
int opt;
|
|
int job_type = 0xffff;
|
|
int debug = 0;
|
|
|
|
char *queue_name = NULL;
|
|
|
|
char default_command[] = "lpr";
|
|
char *command = default_command;
|
|
|
|
if (ncp_initialize_as(&conn, &argc, argv, 1, NCP_BINDERY_PSERVER) != 0)
|
|
{
|
|
perror("Could not open connection");
|
|
return 1;
|
|
}
|
|
|
|
while ((opt = getopt(argc, argv, "q:c:j:t:d")) != EOF)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 'q':
|
|
queue_name = optarg;
|
|
break;
|
|
case 'c':
|
|
command = optarg;
|
|
break;
|
|
case 'j':
|
|
job_type = atoi(optarg);
|
|
break;
|
|
case 't':
|
|
poll_timeout = atoi(optarg);
|
|
break;
|
|
case 'd':
|
|
debug = 1;
|
|
break;
|
|
default:
|
|
usage();
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
memzero(q);
|
|
|
|
if (debug == 0)
|
|
{
|
|
/* We can not daemonize after ncp_initialize, sorry */
|
|
/* daemonize(); */
|
|
}
|
|
|
|
if (init_queue(&conn, queue_name, command, &q) != 0)
|
|
{
|
|
perror("Could not init queue");
|
|
ncp_close(&conn);
|
|
return 1;
|
|
}
|
|
|
|
q.job_type = job_type;
|
|
|
|
term_request = 0;
|
|
signal(SIGTERM,terminate_handler);
|
|
|
|
while (1)
|
|
{
|
|
if ( (poll_queue(&q) != 0)
|
|
&& (term_request == 0))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (term_request != 0)
|
|
{
|
|
break;
|
|
}
|
|
sleep(poll_timeout);
|
|
}
|
|
|
|
ncp_detach_from_queue(&conn, q.queue_id);
|
|
|
|
ncp_close(&conn);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
init_queue(struct ncp_conn *conn, char *queue_name, char *command,
|
|
struct nw_queue *q)
|
|
{
|
|
struct ncp_bindery_object obj;
|
|
|
|
str_upper(queue_name);
|
|
|
|
q->conn = conn;
|
|
q->command = command;
|
|
|
|
if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE,
|
|
queue_name, &obj) != 0)
|
|
{
|
|
fprintf(stderr, "Queue %s not found\n", queue_name);
|
|
return -1;
|
|
}
|
|
|
|
q->queue_id = obj.object_id;
|
|
memcpy(q->queue_name, obj.object_name, sizeof(q->queue_name));
|
|
|
|
if (ncp_attach_to_queue(conn, q->queue_id) != 0)
|
|
{
|
|
fprintf(stderr, "Could not attach to queue %s\n",
|
|
queue_name);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
poll_queue(struct nw_queue *q)
|
|
{
|
|
struct queue_job job;
|
|
int fd[2];
|
|
int pid;
|
|
|
|
if (ncp_service_queue_job(q->conn, q->queue_id, q->job_type,
|
|
&job) != 0)
|
|
{
|
|
/* No job for us */
|
|
return 0;
|
|
}
|
|
|
|
if (pipe(fd) < 0)
|
|
{
|
|
perror("pipe");
|
|
goto fail;
|
|
}
|
|
|
|
if ((pid = fork()) < 0)
|
|
{
|
|
perror("fork");
|
|
goto fail;
|
|
}
|
|
|
|
if (pid > 0)
|
|
{
|
|
/* parent */
|
|
char buf[1024];
|
|
size_t result;
|
|
off_t offset = 0;
|
|
|
|
close(fd[0]); /* close read end */
|
|
|
|
while ((result = ncp_read(q->conn, job.file_handle, offset,
|
|
sizeof(buf), buf)) > 0)
|
|
{
|
|
offset += result;
|
|
if (write(fd[1], buf, result) != result)
|
|
{
|
|
goto fail;
|
|
}
|
|
}
|
|
|
|
close(fd[1]); /* and close write end */
|
|
|
|
if (waitpid(pid, NULL, 0) < 0)
|
|
{
|
|
perror("waitpid");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* child */
|
|
|
|
close(fd[1]); /* close write end */
|
|
|
|
if (fd[0] != STDIN_FILENO)
|
|
{
|
|
if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
|
|
{
|
|
perror("dup2");
|
|
close(fd[0]);
|
|
exit(1);
|
|
}
|
|
close(fd[0]);
|
|
}
|
|
|
|
execl("/bin/sh", "sh", "-c", q->command, NULL);
|
|
perror("exec");
|
|
close(fd[0]);
|
|
exit(1);
|
|
}
|
|
|
|
ncp_finish_servicing_job(q->conn, q->queue_id, job.j.JobNumber,0);
|
|
return 1;
|
|
|
|
fail:
|
|
ncp_abort_servicing_job(q->conn, q->queue_id, job.j.JobNumber);
|
|
/* We tell that we did not have a job to avoid overloading
|
|
when something's wrong */
|
|
return 0;
|
|
}
|