home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume22 / queuer / part02 / queued.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-07  |  5.6 KB  |  273 lines

  1. /* Copyright 1990  The President and Fellows of Harvard University
  2.  
  3. Permission to use, copy, modify, and distribute this program for any
  4. purpose and without fee is hereby granted, provided that this
  5. copyright and permission notice appear on all copies and supporting
  6. documentation, the name of Harvard University not be used in advertising
  7. or publicity pertaining to distribution of the program, or to results
  8. derived from its use, without specific prior written permission, and notice
  9. be given in supporting documentation that copying and distribution is by
  10. permission of Harvard University.  Harvard University makes no
  11. representations about the suitability of this software for any purpose.
  12. It is provided "as is" without express or implied warranty.    */
  13.  
  14.  
  15. /* queued.c - Dan Lanciani '85 */
  16.  
  17. #include <stdio.h>
  18. #include <sys/types.h>
  19. #include <sys/socket.h>
  20. #include <sys/wait.h>
  21. #include <netinet/in.h>
  22. #include <netdb.h>
  23. #include <errno.h>
  24. #include <signal.h>
  25. #include <sgtty.h>
  26.  
  27. #include "queue.h"
  28.  
  29. struct sockaddr_in sin = { AF_INET };
  30. extern int errno;
  31. int reapchild();
  32.  
  33. main(argc, argv, envp)
  34. char **argv, **envp;
  35. {
  36.     struct servent *sp;
  37.     int s, on = 1;
  38.     char buf[BUFSIZ], tbuf[BUFSIZ];
  39.     FILE *n, *m;
  40.  
  41. #ifndef DEBUG
  42.     for(s = 0; s < 30; s++)
  43.         close(s);
  44.     if((s = open("/dev/tty", 2)) >= 0) {
  45.         ioctl(s, TIOCNOTTY, 0);
  46.         close(s);
  47.     }
  48.     if((s = open("/dev/console", 2)) >= 0) {
  49.         close(s);
  50.         setpgrp(0, 0);
  51.     }
  52.     s = open("/", 0);
  53.     dup(s);
  54.     dup(s);
  55.     signal(SIGALRM, SIG_IGN);
  56.     signal(SIGPIPE, SIG_IGN);
  57.     if(fork())
  58.         exit(0);
  59. #endif
  60.  
  61.     if(!(sp = getservbyname("queue", "tcp"))) {
  62.         fprintf(stderr, "queue: Bad service?!?\n");
  63.         exit(1);
  64.     }
  65.     if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  66.         perror("socket");
  67.         exit(1);
  68.     }
  69.     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  70.     setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
  71.     sin.sin_port = sp->s_port;
  72.     if(bind(s, &sin, sizeof(sin))) {
  73.         perror("bind");
  74.         exit(1);
  75.     }
  76.     listen(s, 10);
  77.     if(n = fopen(QUEUES, "r")) {
  78.         while(fgets(buf, sizeof(buf), n)) {
  79.             buf[strlen(buf)-1] = '\0';
  80.             sprintf(tbuf, "%s/%s", SPOOLDIR, buf);
  81.             if(m = fopen(tbuf, "r")) {
  82.                 unlink(tbuf);
  83.                 creat(tbuf, 0644);
  84.                 while(fgets(buf, sizeof(buf), m)) {
  85.                     buf[strlen(buf)-1] = '\0';
  86.                     if(!fork()) {
  87.                         close(s);
  88.                         fclose(m);
  89.                         fclose(n);
  90.                         recover(buf);
  91.                         exit(0);
  92.                     }
  93.                 }
  94.                 fclose(m);
  95.             }
  96.             else
  97.                 creat(tbuf, 0644);
  98.         }
  99.         fclose(n);
  100.     }
  101.     while(1) {
  102.         struct sockaddr_in from;
  103.         int pid, s0, fromlen;
  104.         signal(SIGCHLD, reapchild);
  105.         fromlen = sizeof(from);
  106.         if((s0 = accept(s, &from, &fromlen)) < 0) {
  107.             if(errno = EINTR)
  108.                 continue;
  109.             perror("accept");
  110.             exit(1);
  111.         }
  112.         if(from.sin_family != AF_INET ||
  113.             htons((u_short)from.sin_port) >= IPPORT_RESERVED ||
  114.             htons((u_short)from.sin_port) < IPPORT_RESERVED / 2) {
  115.             close(s0);
  116.             continue;
  117.         }
  118.         if((pid = fork()) < 0) {
  119.             perror("fork");
  120.             exit(1);
  121.         }
  122.         if(!pid) {
  123.             signal(SIGCHLD, SIG_DFL);
  124.             signal(SIGALRM, SIG_DFL);
  125.             signal(SIGPIPE, SIG_DFL);
  126.             close(s);
  127.             doit(s0, &from);
  128.             exit(0);
  129.         }
  130.         close(s0);
  131.     }
  132. }
  133.  
  134. reapchild()
  135. {
  136.     union wait status;
  137.     char buf[BUFSIZ], name1[BUFSIZ], name2[BUFSIZ];
  138.     FILE *n, *m;    
  139.     register int pid, i;
  140.     long unid;
  141.  
  142.     while((pid = wait3(&status, WNOHANG, 0)) > 0) {
  143.         sprintf(buf, "%s/%d", SPOOLDIR, pid);
  144.         if(n = fopen(buf, "r")) {
  145.             unlink(buf);
  146.             fgetstr(n, buf);
  147.             fgetstr(n, buf);
  148.             unid = atol(buf);
  149.             fgetstr(n, buf);
  150.             fgetstr(n, buf);
  151.             fclose(n);
  152.             if(!fork()) {
  153.                 signal(SIGCHLD, SIG_DFL);
  154.                 for(i = 0; i < 30; i++)
  155.                     close(i);
  156.                 if(readconf(buf))
  157.                     exit(1);
  158.                 if(unid) {
  159.                     sprintf(buf, "%s/%ld", SPOOLDIR, unid);
  160.                     unlink(buf);
  161.                 }
  162.                 sprintf(buf, "%s/%d.dir", SPOOLDIR, pid);
  163.                 if(!access(buf, 0)) {
  164.                     if(!vfork()) {
  165.                     execl("/bin/rm", "rm", "-rf", buf, 0);
  166.                         exit(1);
  167.                     }
  168.                     wait(0);
  169.                 }
  170.                 sprintf(buf, "%s/%d.batch", SPOOLDIR, pid);
  171.                 unlink(buf);
  172.                 sprintf(buf, "%s/%d.ebatch", SPOOLDIR, pid);
  173.                 unlink(buf);
  174.                 sprintf(name1, "%s/%s", SPOOLDIR, queue);
  175.                 lock(name1);
  176.                 n = fopen(name1, "r");
  177.                 strcpy(name2, name1);
  178.                 strcat(name2, ".tmp");
  179.                 m = fopen(name2, "w");
  180.                 i = 0;
  181.                 while(fgets(buf, sizeof(buf), n))
  182.                     if(atoi(buf) != pid) {
  183.                         if(i++ < maxrun)
  184.                         kill(atoi(buf), SIGALRM);
  185.                         fputs(buf, m);
  186.                     }
  187.                 fclose(m);
  188.                 fclose(n);
  189.                 unlink(name1);
  190.                 link(name2, name1);
  191.                 unlink(name2);
  192.                 unlock(name1);
  193.                 exit(0);
  194.             }
  195.         }
  196.     }
  197. }
  198.  
  199. doit(s, sin)
  200. struct sockaddr_in *sin;
  201. {
  202.     struct hostent *hp;
  203.     char buf[BUFSIZ];
  204.  
  205.     if(!(hp=gethostbyaddr(&sin->sin_addr, sizeof(struct in_addr), AF_INET)))
  206.         exit(1);
  207.     if(index(hp->h_name, '.'))
  208.         *index(hp->h_name, '.') = '\0';
  209.     gethostname(buf, BUFSIZ);
  210.     if(!strcmp(hp->h_name, "localhost")) {
  211.         qservice(s, buf, sin, 1);
  212.         exit(0);
  213.     }
  214.     if(!strcmp(hp->h_name, buf)) {
  215.         qservice(s, buf, sin, 1);
  216.         exit(0);
  217.     }
  218.     if(infile(EQUIVFILE, hp->h_name)) {
  219.         qservice(s, hp->h_name, sin, 0);
  220.         exit(0);
  221.     }
  222.     exit(1);
  223. }
  224.  
  225. qservice(s, host, sin, local)
  226. char *host;
  227. struct sockaddr_in *sin;
  228. {
  229.     char request;
  230.  
  231.     if(read(s, &request, 1) != 1)
  232.         exit(1);
  233.     switch(request&0377) {
  234.  
  235.         case 0:
  236.             enqueue(s, host, sin, local, 0);
  237.             break;
  238.  
  239.         case 1:
  240.             showqueue(s, host, sin, local);
  241.             break;
  242.  
  243.         case 2:
  244.             dequeue(s, host, sin, local);
  245.             break;
  246.  
  247.         default:
  248.             exit(1);
  249.             break;
  250.     }
  251. }
  252.  
  253. recover(job)
  254. char *job;
  255. {
  256.     int s;
  257.     char buf1[BUFSIZ], buf2[BUFSIZ];
  258.  
  259.     sprintf(buf2, "%s/%d", SPOOLDIR, atoi(job));
  260.     if((s = open(buf2, 0)) < 0)
  261.         exit(0);
  262.     unlink(buf2);
  263.     sprintf(buf1, "%s/%d.dir", SPOOLDIR, getpid());
  264.     sprintf(buf2, "%s/%d.dir", SPOOLDIR, atoi(job));
  265.     rename(buf2, buf1);
  266.     sprintf(buf2, "%s/%d.batch", SPOOLDIR, atoi(job));
  267.     unlink(buf2);
  268.     sprintf(buf2, "%s/%d.ebatch", SPOOLDIR, atoi(job));
  269.     unlink(buf2);
  270.     enqueue(s, 0, 0, 0, 1);
  271.     exit(1);
  272. }
  273.