home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1990 The President and Fellows of Harvard University
-
- Permission to use, copy, modify, and distribute this program for any
- purpose and without fee is hereby granted, provided that this
- copyright and permission notice appear on all copies and supporting
- documentation, the name of Harvard University not be used in advertising
- or publicity pertaining to distribution of the program, or to results
- derived from its use, without specific prior written permission, and notice
- be given in supporting documentation that copying and distribution is by
- permission of Harvard University. Harvard University makes no
- representations about the suitability of this software for any purpose.
- It is provided "as is" without express or implied warranty. */
-
-
- /* queued.c - Dan Lanciani '85 */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/wait.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <errno.h>
- #include <signal.h>
- #include <sgtty.h>
-
- #include "queue.h"
-
- struct sockaddr_in sin = { AF_INET };
- extern int errno;
- int reapchild();
-
- main(argc, argv, envp)
- char **argv, **envp;
- {
- struct servent *sp;
- int s, on = 1;
- char buf[BUFSIZ], tbuf[BUFSIZ];
- FILE *n, *m;
-
- #ifndef DEBUG
- for(s = 0; s < 30; s++)
- close(s);
- if((s = open("/dev/tty", 2)) >= 0) {
- ioctl(s, TIOCNOTTY, 0);
- close(s);
- }
- if((s = open("/dev/console", 2)) >= 0) {
- close(s);
- setpgrp(0, 0);
- }
- s = open("/", 0);
- dup(s);
- dup(s);
- signal(SIGALRM, SIG_IGN);
- signal(SIGPIPE, SIG_IGN);
- if(fork())
- exit(0);
- #endif
-
- if(!(sp = getservbyname("queue", "tcp"))) {
- fprintf(stderr, "queue: Bad service?!?\n");
- exit(1);
- }
- if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket");
- exit(1);
- }
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
- setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
- sin.sin_port = sp->s_port;
- if(bind(s, &sin, sizeof(sin))) {
- perror("bind");
- exit(1);
- }
- listen(s, 10);
- if(n = fopen(QUEUES, "r")) {
- while(fgets(buf, sizeof(buf), n)) {
- buf[strlen(buf)-1] = '\0';
- sprintf(tbuf, "%s/%s", SPOOLDIR, buf);
- if(m = fopen(tbuf, "r")) {
- unlink(tbuf);
- creat(tbuf, 0644);
- while(fgets(buf, sizeof(buf), m)) {
- buf[strlen(buf)-1] = '\0';
- if(!fork()) {
- close(s);
- fclose(m);
- fclose(n);
- recover(buf);
- exit(0);
- }
- }
- fclose(m);
- }
- else
- creat(tbuf, 0644);
- }
- fclose(n);
- }
- while(1) {
- struct sockaddr_in from;
- int pid, s0, fromlen;
- signal(SIGCHLD, reapchild);
- fromlen = sizeof(from);
- if((s0 = accept(s, &from, &fromlen)) < 0) {
- if(errno = EINTR)
- continue;
- perror("accept");
- exit(1);
- }
- if(from.sin_family != AF_INET ||
- htons((u_short)from.sin_port) >= IPPORT_RESERVED ||
- htons((u_short)from.sin_port) < IPPORT_RESERVED / 2) {
- close(s0);
- continue;
- }
- if((pid = fork()) < 0) {
- perror("fork");
- exit(1);
- }
- if(!pid) {
- signal(SIGCHLD, SIG_DFL);
- signal(SIGALRM, SIG_DFL);
- signal(SIGPIPE, SIG_DFL);
- close(s);
- doit(s0, &from);
- exit(0);
- }
- close(s0);
- }
- }
-
- reapchild()
- {
- union wait status;
- char buf[BUFSIZ], name1[BUFSIZ], name2[BUFSIZ];
- FILE *n, *m;
- register int pid, i;
- long unid;
-
- while((pid = wait3(&status, WNOHANG, 0)) > 0) {
- sprintf(buf, "%s/%d", SPOOLDIR, pid);
- if(n = fopen(buf, "r")) {
- unlink(buf);
- fgetstr(n, buf);
- fgetstr(n, buf);
- unid = atol(buf);
- fgetstr(n, buf);
- fgetstr(n, buf);
- fclose(n);
- if(!fork()) {
- signal(SIGCHLD, SIG_DFL);
- for(i = 0; i < 30; i++)
- close(i);
- if(readconf(buf))
- exit(1);
- if(unid) {
- sprintf(buf, "%s/%ld", SPOOLDIR, unid);
- unlink(buf);
- }
- sprintf(buf, "%s/%d.dir", SPOOLDIR, pid);
- if(!access(buf, 0)) {
- if(!vfork()) {
- execl("/bin/rm", "rm", "-rf", buf, 0);
- exit(1);
- }
- wait(0);
- }
- sprintf(buf, "%s/%d.batch", SPOOLDIR, pid);
- unlink(buf);
- sprintf(buf, "%s/%d.ebatch", SPOOLDIR, pid);
- unlink(buf);
- sprintf(name1, "%s/%s", SPOOLDIR, queue);
- lock(name1);
- n = fopen(name1, "r");
- strcpy(name2, name1);
- strcat(name2, ".tmp");
- m = fopen(name2, "w");
- i = 0;
- while(fgets(buf, sizeof(buf), n))
- if(atoi(buf) != pid) {
- if(i++ < maxrun)
- kill(atoi(buf), SIGALRM);
- fputs(buf, m);
- }
- fclose(m);
- fclose(n);
- unlink(name1);
- link(name2, name1);
- unlink(name2);
- unlock(name1);
- exit(0);
- }
- }
- }
- }
-
- doit(s, sin)
- struct sockaddr_in *sin;
- {
- struct hostent *hp;
- char buf[BUFSIZ];
-
- if(!(hp=gethostbyaddr(&sin->sin_addr, sizeof(struct in_addr), AF_INET)))
- exit(1);
- if(index(hp->h_name, '.'))
- *index(hp->h_name, '.') = '\0';
- gethostname(buf, BUFSIZ);
- if(!strcmp(hp->h_name, "localhost")) {
- qservice(s, buf, sin, 1);
- exit(0);
- }
- if(!strcmp(hp->h_name, buf)) {
- qservice(s, buf, sin, 1);
- exit(0);
- }
- if(infile(EQUIVFILE, hp->h_name)) {
- qservice(s, hp->h_name, sin, 0);
- exit(0);
- }
- exit(1);
- }
-
- qservice(s, host, sin, local)
- char *host;
- struct sockaddr_in *sin;
- {
- char request;
-
- if(read(s, &request, 1) != 1)
- exit(1);
- switch(request&0377) {
-
- case 0:
- enqueue(s, host, sin, local, 0);
- break;
-
- case 1:
- showqueue(s, host, sin, local);
- break;
-
- case 2:
- dequeue(s, host, sin, local);
- break;
-
- default:
- exit(1);
- break;
- }
- }
-
- recover(job)
- char *job;
- {
- int s;
- char buf1[BUFSIZ], buf2[BUFSIZ];
-
- sprintf(buf2, "%s/%d", SPOOLDIR, atoi(job));
- if((s = open(buf2, 0)) < 0)
- exit(0);
- unlink(buf2);
- sprintf(buf1, "%s/%d.dir", SPOOLDIR, getpid());
- sprintf(buf2, "%s/%d.dir", SPOOLDIR, atoi(job));
- rename(buf2, buf1);
- sprintf(buf2, "%s/%d.batch", SPOOLDIR, atoi(job));
- unlink(buf2);
- sprintf(buf2, "%s/%d.ebatch", SPOOLDIR, atoi(job));
- unlink(buf2);
- enqueue(s, 0, 0, 0, 1);
- exit(1);
- }
-