home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume22 / queuer / part03 / qmaster.c < prev   
C/C++ Source or Header  |  1990-06-07  |  19KB  |  864 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. /* qmaster.c - Dan Lanciani '89 */
  16.  
  17. /*
  18. refresh hosts less
  19. pick up strays
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <sys/wait.h>
  26. #include <sys/time.h>
  27. #include <netinet/in.h>
  28. #include <netdb.h>
  29. #include <errno.h>
  30. #include <signal.h>
  31. #include <sgtty.h>
  32. #include <setjmp.h>
  33.  
  34. #include "queue.h"
  35.  
  36. #define GARBAGE (1*60)
  37. #define HOLDDOWN (2*60)
  38. #define HOSTPOLLTIME (5*60)
  39. #define DEADMAN (1*60)
  40.  
  41. struct hostinfo {
  42.     struct hostinfo *hi_next;
  43.     char *hi_name;
  44.     struct sockaddr_in hi_addr;
  45.     int hi_equiv;
  46.     int hi_load;
  47.     time_t hi_timestamp;
  48.     int hi_dead;
  49.     int hi_queued;
  50. } *hostinfo;
  51.  
  52. struct userinfo {
  53.     struct userinfo *ui_next;
  54.     long ui_unid;
  55.     struct sockaddr_in ui_addr;
  56.     char *ui_name;
  57.     struct proginfo *ui_prog;
  58.     time_t ui_timestamp;
  59.     int ui_mark;
  60. };
  61.  
  62. struct queueinfo {
  63.     struct queueinfo *qi_next;
  64.     char *qi_name;
  65.     int qi_maxrun;
  66.     int qi_minload;
  67.     int qi_maxperu;
  68.     int qi_hcnt;
  69.     struct hostinfo *qi_hosts[MAXHCNT];
  70.     struct userinfo *qi_heads[MAXHCNT];
  71.     struct userinfo *qi_head;
  72. } *queueinfo;
  73.  
  74. struct proginfo {
  75.     struct proginfo *pi_next;
  76.     char *pi_name;
  77.     struct queueinfo *pi_queue;
  78. } *proginfo;
  79.  
  80. struct sockaddr_in sin = { AF_INET };
  81. time_t time();
  82. extern int errno;
  83. int reapchild();
  84. long atol();
  85.  
  86. long
  87. newunid()
  88. {
  89.     static int fd = -1;
  90.     long unid;
  91.     char buf[100];
  92.  
  93.     if(fd < 0) {
  94.         if((fd = open(UNID, 2)) < 0) {
  95.             if((fd = creat(UNID, 0644)) < 0) {
  96.                 perror("creat");
  97.                 exit(1);
  98.             }
  99.             sprintf(buf, "%ld", FIRSTUNID);
  100.             write(fd, buf, strlen(buf) + 1);
  101.             close(fd);
  102.             if((fd = open(UNID, 2)) < 0) {
  103.                 perror("open");
  104.                 exit(1);
  105.             }
  106.         }
  107.     }
  108.     lseek(fd, 0L, 0);
  109.     read(fd, buf, sizeof(buf));
  110.     unid = atol(buf) + 1;
  111.     if(!isunid(unid))
  112.         unid = FIRSTUNID;
  113.     sprintf(buf, "%ld", unid);
  114.     lseek(fd, 0L, 0);
  115.     write(fd, buf, strlen(buf) + 1);
  116.     return(unid);
  117. }
  118.  
  119. #define refresh(hi) \
  120.     if(time((time_t)0) - (hi)->hi_timestamp > HOSTPOLLTIME) { \
  121.         (hi)->hi_load = getrload((hi)->hi_name); \
  122.         (hi)->hi_timestamp = time((time_t)0); \
  123.     } \
  124.     else
  125.  
  126. struct hostinfo *
  127. hibyname(name)
  128. register char *name;
  129. {
  130.     register struct hostinfo *hi;
  131.     register struct hostent *hp;
  132.  
  133.     for(hi = hostinfo; hi; hi = hi->hi_next)
  134.         if(!strcmp(hi->hi_name, name)) {
  135.             refresh(hi);
  136.             return(hi);
  137.         }
  138.     if(!(hp = gethostbyname(name)))
  139.         return(0);
  140.     hi = (struct hostinfo *)malloc(sizeof(struct hostinfo));
  141.     hi->hi_name = newstring(name);
  142.     if(infile(EQUIVFILE, hi->hi_name))
  143.         hi->hi_equiv = 1;
  144.     else
  145.         hi->hi_equiv = 0;
  146.     hi->hi_addr.sin_family = hp->h_addrtype;
  147.     bcopy(hp->h_addr, &hi->hi_addr.sin_addr, hp->h_length);
  148.     hi->hi_load = getrload(name);
  149.     hi->hi_timestamp = time((time_t)0);
  150.     hi->hi_dead = 0;
  151.     hi->hi_queued = 0;
  152.     hi->hi_next = hostinfo;
  153.     hostinfo = hi;
  154.     return(hi);
  155. }
  156.  
  157. struct hostinfo *
  158. hibyaddr(addr)
  159. register struct sockaddr_in *addr;
  160. {
  161.     register struct hostinfo *hi;
  162.     register struct hostent *hp;
  163.  
  164.     for(hi = hostinfo; hi; hi = hi->hi_next)
  165.         if(addr->sin_addr.s_addr == hi->hi_addr.sin_addr.s_addr) {
  166.             refresh(hi);
  167.             return(hi);
  168.         }
  169.     if(!(hp=gethostbyaddr(&addr->sin_addr, sizeof(struct in_addr),AF_INET)))
  170.         return(0);
  171.     hi = (struct hostinfo *)malloc(sizeof(struct hostinfo));
  172.     hi->hi_name = newstring(hp->h_name);
  173.     if(index(hi->hi_name, '.'))
  174.         *index(hi->hi_name, '.') = '\0';
  175.     if(infile(EQUIVFILE, hi->hi_name))
  176.         hi->hi_equiv = 1;
  177.     else
  178.         hi->hi_equiv = 0;
  179.     hi->hi_addr.sin_family = hp->h_addrtype;
  180.     bcopy(hp->h_addr, &hi->hi_addr.sin_addr, hp->h_length);
  181.     hi->hi_load = getrload(hi->hi_name);
  182.     hi->hi_timestamp = time((time_t)0);
  183.     hi->hi_dead = 0;
  184.     hi->hi_queued = 0;
  185.     hi->hi_next = hostinfo;
  186.     hostinfo = hi;
  187.     return(hi);
  188. }
  189.  
  190. struct userinfo *
  191. uibyunid(unid, unlnk)
  192. register long unid;
  193. {
  194.     register struct queueinfo *qi;
  195.     register struct userinfo *ui, *pu;
  196.     register int i;
  197.  
  198.     for(qi = queueinfo; qi; qi = qi->qi_next) {
  199.         for(i = 0; i < qi->qi_hcnt; i++)
  200.             for(pu = 0, ui =qi->qi_heads[i];ui;pu=ui,ui=ui->ui_next)
  201.                 if(unid == ui->ui_unid) {
  202.                     if(unlnk)
  203.                     if(pu)
  204.                         pu->ui_next = ui->ui_next;
  205.                     else
  206.                         qi->qi_heads[i] = ui->ui_next;
  207.                     return(ui);
  208.                 }
  209.         for(pu = 0, ui = qi->qi_head; ui; pu = ui, ui = ui->ui_next)
  210.             if(unid == ui->ui_unid) {
  211.                 if(unlnk)
  212.                     if(pu)
  213.                         pu->ui_next = ui->ui_next;
  214.                     else
  215.                         qi->qi_head = ui->ui_next;
  216.                 return(ui);
  217.             }
  218.     }
  219.     return(0);
  220. }
  221.  
  222. struct queueinfo *
  223. qibyname(name)
  224. register char *name;
  225. {
  226.     register struct queueinfo *qi;
  227.  
  228.     for(qi = queueinfo; qi; qi = qi->qi_next)
  229.         if(!strcmp(qi->qi_name, name))
  230.             return(qi);
  231.     return(0);
  232. }
  233.  
  234. struct proginfo *
  235. pibyname(name)
  236. register char *name;
  237. {
  238.     register struct proginfo *pi;
  239.     register struct queueinfo *qi;
  240.     register int i;
  241.  
  242.     for(pi = proginfo; pi; pi = pi->pi_next)
  243.         if(!strcmp(pi->pi_name, name))
  244.             return(pi);
  245.     if(readconf(name))
  246.         return(0);
  247.     if(!(qi = qibyname(queue))) {
  248.         qi = (struct queueinfo *)malloc(sizeof(struct queueinfo));
  249.         qi->qi_name = newstring(queue);
  250.         qi->qi_maxrun = maxrun;
  251.         qi->qi_minload = minload;
  252.         qi->qi_maxperu = maxperu;
  253.         for(i = 0; i < hcnt; i++) {
  254.             if(!(qi->qi_hosts[i] = hibyname(hosts[i]))) {
  255.                 i--;
  256.                 hcnt--;
  257.                 continue;
  258.             }
  259.             qi->qi_hosts[i]->hi_queued = 1;
  260.             qi->qi_heads[i] = 0;
  261.         }
  262.         if(hcnt <= 0) {
  263.             free(qi);
  264.             return(0);
  265.         }
  266.         qi->qi_hcnt = hcnt;
  267.         qi->qi_head = 0;
  268.         qi->qi_next = queueinfo;
  269.         queueinfo = qi;
  270.     }
  271.     pi = (struct proginfo *)malloc(sizeof(struct proginfo));
  272.     pi->pi_name = newstring(name);
  273.     pi->pi_queue = qi;
  274.     pi->pi_next = proginfo;
  275.     proginfo = pi;
  276.     return(pi);
  277. }
  278.  
  279. char *
  280. getln(n, buf)
  281. char *buf;
  282. {
  283.     register char *p = buf;
  284.  
  285.     do
  286.         if(read(n, p, 1) != 1)
  287.             return(0);
  288.     while(*p++ != '\n');
  289.     p[-1] = 0;
  290.     return(buf);
  291. }
  292.  
  293. char *
  294. getstr(n, buf)
  295. char *buf;
  296. {
  297.     register char *p = buf;
  298.  
  299.     do
  300.         if(read(n, p, 1) != 1)
  301.             return(0);
  302.     while(*p++);
  303.     return(buf);
  304. }
  305.  
  306. struct timeval timeout = { 60, 0 };
  307. char myname[100];
  308. int s, u, on = 1;
  309. int strays, dropouts, upstarts;
  310. int deadmans, enqueues, dequeues, showqueues;
  311. jmp_buf jb;
  312.  
  313. catch()
  314. {
  315.     deadmans++;
  316.     longjmp(jb, 1);
  317. }
  318.  
  319. main(argc, argv, envp)
  320. char **argv, **envp;
  321. {
  322.     register struct servent *sp;
  323.     register struct queueinfo *qi;
  324.     register struct userinfo *ui, *pu;
  325.     register struct hostinfo *hi, *garbagehi = 0;
  326.     register int i, j, qport;
  327.     long probe, mask, unid;
  328.     char buf[BUFSIZ];
  329.     time_t garbage = 0;
  330.  
  331.     gethostname(myname, sizeof(myname));
  332.     if(argc > 1) {
  333.         for(i = 1; i < argc; i++)
  334.             if(!strcmp(argv[i], myname))
  335.                 goto iammaster;
  336. fprintf(stderr, "I am not master %s\n", myname);
  337.         exit(0);
  338.     }
  339. iammaster:
  340. #ifndef DEBUG
  341.     for(s = 0; s < 30; s++)
  342.         close(s);
  343.     if((s = open("/dev/tty", 2)) >= 0) {
  344.         ioctl(s, TIOCNOTTY, 0);
  345.         close(s);
  346.     }
  347.     s = open("/", 0);
  348.     dup(s);
  349.     dup(s);
  350.     signal(SIGALRM, SIG_IGN);
  351.     signal(SIGPIPE, SIG_IGN);
  352.     if(fork())
  353.         exit(0);
  354. #endif
  355.  
  356.     while(fork()) {
  357.         wait((int *)0);
  358.         sleep(15);
  359.     }
  360.     if(!(sp = getservbyname("queue", "tcp"))) {
  361.         fprintf(stderr, "queue/tcp: Bad service?!?\n");
  362.         exit(1);
  363.     }
  364.     qport = sp->s_port;
  365.     if(!(sp = getservbyname("qmaster", "tcp"))) {
  366.         fprintf(stderr, "qmaster/tcp: Bad service?!?\n");
  367.         exit(1);
  368.     }
  369.     if((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  370.         perror("socket");
  371.         exit(1);
  372.     }
  373.     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  374.     setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
  375.     sin.sin_port = sp->s_port;
  376.     if(bind(s, &sin, sizeof(sin))) {
  377.         perror("bind");
  378.         exit(1);
  379.     }
  380.     listen(s, 10);
  381.     mask = (1L << s);
  382.     if(!(sp = getservbyname("qmaster", "udp"))) {
  383.         fprintf(stderr, "qmaster/udp: Bad service?!?\n");
  384.         exit(1);
  385.     }
  386.     if((u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  387.         perror("socket");
  388.         exit(1);
  389.     }
  390.     setsockopt(u, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
  391.     sin.sin_port = sp->s_port;
  392.     if(bind(u, &sin, sizeof(sin))) {
  393.         perror("bind");
  394.         exit(1);
  395.     }
  396.     mask |= (1L << u);
  397.     while(1) {
  398.         struct sockaddr_in from;
  399.         int s0, fromlen;
  400.         signal(SIGCHLD, reapchild);
  401.         probe = mask;
  402.         if(select(32, &probe, 0, 0, &timeout) < 0) {
  403.             sleep(1);
  404.             continue;
  405.         }
  406.         if(probe & (1L << s)) {
  407.             fromlen = sizeof(from);
  408.             if((s0 = accept(s, &from, &fromlen)) < 0) {
  409.                 if(errno = EINTR)
  410.                     continue;
  411.                 perror("accept");
  412.                 sleep(1);
  413.                 continue;
  414.             }
  415.             if(from.sin_family != AF_INET ||
  416.                 htons((u_short)from.sin_port) >= IPPORT_RESERVED
  417.                 || htons((u_short)from.sin_port)
  418.                 < IPPORT_RESERVED / 2) {
  419.                 close(s0);
  420.                 continue;
  421.             }
  422.             dostream(s0, &from);
  423.         }
  424.         if(probe & (1L << u))
  425.             dodgram(u);
  426.         for(hi = hostinfo; hi; hi = hi->hi_next)
  427.             if(hi->hi_queued)
  428.                 refresh(hi);
  429.         for(qi = queueinfo; qi; qi = qi->qi_next) {
  430.             if(!qi->qi_head)
  431.                 continue;
  432.             for(i = 0; i < qi->qi_hcnt; i++)
  433.                 for(j = i + 1; j < qi->qi_hcnt; j++)
  434.                     if(qi->qi_hosts[j]->hi_load <
  435.                         qi->qi_hosts[i]->hi_load) {
  436.                         ui = qi->qi_heads[i];
  437.                         hi = qi->qi_hosts[i];
  438.                         qi->qi_heads[i]=qi->qi_heads[j];
  439.                         qi->qi_hosts[i]=qi->qi_hosts[j];
  440.                         qi->qi_heads[j] = ui;
  441.                         qi->qi_hosts[j] = hi;
  442.                     }
  443.             for(i = 0; i < qi->qi_hcnt && qi->qi_head; i++) {
  444.                 if(qi->qi_hosts[i]->hi_dead)
  445.                     continue;
  446.                 if(qi->qi_minload &&
  447.                     qi->qi_hosts[i]->hi_load>qi->qi_minload)
  448.                     continue;
  449.                 j = 0;
  450.                 for(ui = qi->qi_heads[i]; ui; ui = ui->ui_next)
  451.                     j++;
  452.                 while(j < qi->qi_maxrun && (ui = qi->qi_head)) {
  453.                     qi->qi_head = ui->ui_next;
  454.                     ui->ui_next = qi->qi_heads[i];
  455.                     qi->qi_heads[i] = ui;
  456.                     sprintf(buf, "\1%s",
  457.                         qi->qi_hosts[i]->hi_name);
  458.                     sendto(u, buf, strlen(buf) + 1, 0,
  459.                         &ui->ui_addr,
  460.                         sizeof(ui->ui_addr));
  461.                     ui->ui_timestamp = time((time_t)0);
  462.                     j++;
  463.                 }
  464.             }
  465.             *buf = 0;
  466.             for(ui = qi->qi_head; ui; ui = ui->ui_next)
  467.                 sendto(u, buf, 1, 0, &ui->ui_addr,
  468.                     sizeof(ui->ui_addr));
  469.         }
  470.         if(time((time_t)0) - garbage > GARBAGE) {
  471.             int rp = IPPORT_RESERVED - 1;
  472.             register char *p;
  473.             if(!garbagehi)
  474.                 garbagehi = hostinfo;
  475.             if(!(hi = garbagehi) || !hi->hi_queued)
  476.                 goto out;
  477.             hi->hi_addr.sin_port = qport;
  478.             if((i = rresvport(&rp)) < 0)
  479.                 goto out;
  480.             if(setjmp(jb))
  481.                 goto out2;
  482. #ifdef DEBUG
  483.             fprintf(stderr, "gc host %s\n", hi->hi_name);
  484. #endif
  485.             signal(SIGALRM, catch);
  486.             alarm(DEADMAN);
  487.             if(connect(i, &hi->hi_addr, sizeof(hi->hi_addr))) {
  488.                 hi->hi_dead = 1;
  489.                 goto out2;
  490.             }
  491.             hi->hi_dead = 0;
  492.             alarm(DEADMAN);
  493.             write(i, "\1", 2);
  494.             alarm(DEADMAN);
  495.             while(getln(i, buf)) {
  496.                 alarm(0);
  497.                 if(strncmp(buf, "Queue: ", 7))
  498.                     goto out2;
  499.                 if(!(p = index(buf + 7, ',')))
  500.                     goto out2;
  501.                 *p = 0;
  502. #ifdef DEBUG
  503.                 fprintf(stderr, "queue = %s\n", buf);
  504. #endif
  505.                 if(!(qi = qibyname(buf + 7))) {
  506.                 skip:
  507.                     alarm(DEADMAN);
  508.                     while(getln(i, buf) && *buf)
  509.                         alarm(DEADMAN);
  510.                     continue;
  511.                 }
  512.                 for(j = 0; j < qi->qi_hcnt; j++)
  513.                     if(hi == qi->qi_hosts[j])
  514.                         break;
  515.                 if(j >= qi->qi_hcnt)
  516.                     goto skip;
  517.                 for(ui = qi->qi_heads[j]; ui; ui = ui->ui_next)
  518.                     ui->ui_mark = 0;
  519.                 alarm(DEADMAN);
  520.                 if(!getln(i, buf) || strncmp(buf, "Pid", 3))
  521.                     goto out2;
  522. #ifdef DEBUG
  523.                 fprintf(stderr, "header = %s\n", buf);
  524. #endif
  525.                 while(getln(i, buf) && *buf) {
  526.                     alarm(0);
  527. #ifdef DEBUG
  528.                 fprintf(stderr, "entry = %s\n", buf);
  529. #endif
  530.                     unid = atol(buf);
  531.                     for(ui = qi->qi_heads[j]; ui;
  532.                         ui = ui->ui_next)
  533.                         if(ui->ui_unid == unid) {
  534.                             /* XXX check mark */
  535.                             ui->ui_mark = 1;
  536.                             break;
  537.                         }
  538.                     if(ui) {
  539.                         alarm(DEADMAN);
  540.                         continue;
  541.                     }
  542.                     if(ui = uibyunid(unid, 1)) {
  543.                         ui->ui_mark = 1;
  544.                         ui->ui_next = qi->qi_heads[j];
  545.                         qi->qi_heads[j] = ui;
  546.                         upstarts++;
  547.                         alarm(DEADMAN);
  548.                         continue;
  549.                     }
  550.                     /* XXX add it */
  551.                     strays++;
  552.                     alarm(DEADMAN);
  553.                 }
  554.                 alarm(0);
  555.             again:
  556.                 for(pu = 0, ui = qi->qi_heads[j]; ui;
  557.                 pu = ui, ui = ui->ui_next)
  558.                 if(!ui->ui_mark && time((time_t)0) -
  559.                     ui->ui_timestamp > HOLDDOWN) {
  560.                     if(pu)
  561.                         pu->ui_next = ui->ui_next;
  562.                     else
  563.                         qi->qi_heads[j] = ui->ui_next;
  564.                     free(ui->ui_name);
  565.                     free(ui);
  566.                     dropouts++;
  567.                     goto again;
  568.                 }
  569.                 alarm(DEADMAN);
  570.             }
  571.         out2:
  572.             close(i);
  573.         out:
  574.             alarm(0);
  575.             signal(SIGALRM, SIG_DFL);
  576.             garbagehi = hi->hi_next;
  577.             garbage = time((time_t)0);
  578.         }
  579.     }
  580. }
  581.  
  582. reapchild()
  583. {
  584.     union wait status;
  585.  
  586.     while(wait3(&status, WNOHANG, 0) > 0);
  587. }
  588.  
  589. dostream(s, sin)
  590. register int s;
  591. struct sockaddr_in *sin;
  592. {
  593.     register struct hostinfo *hi;
  594.  
  595.     if(!(hi = hibyaddr(sin)))
  596.         goto bad;
  597.     if(setjmp(jb))
  598.         goto bad;
  599.     signal(SIGALRM, catch);
  600.     alarm(DEADMAN);
  601.     if(!strcmp(hi->hi_name, "localhost") || !strcmp(hi->hi_name, myname))
  602.         qservice(s, myname, sin, 1);
  603.     else if(hi->hi_equiv)
  604.         qservice(s, hi->hi_name, sin, 0);
  605. bad:
  606.     alarm(0);
  607.     signal(SIGALRM, SIG_IGN);
  608.     close(s);
  609. }
  610.  
  611. dodgram(s)
  612. register int s;
  613. {
  614.     char buf[BUFSIZ];
  615.     struct sockaddr_in sin;
  616.     int len, fromlen = sizeof(sin);
  617.     register struct userinfo *ui;
  618.  
  619.     if(setjmp(jb))
  620.         goto bad;
  621.     signal(SIGALRM, catch);
  622.     alarm(10);
  623.     if((len = recvfrom(s, buf, sizeof(buf), 0, &sin, sizeof(sin))) <= 0)
  624.         goto bad;
  625.     alarm(0);
  626.     switch(*buf&0377) {
  627.  
  628.         case 0:
  629.             if(ui = uibyunid(atol(buf + 1), 1)) {
  630.                 free(ui->ui_name);
  631.                 free(ui);
  632.             }
  633.             break;
  634.     }
  635. bad:
  636.     alarm(0);
  637.     signal(SIGALRM, SIG_IGN);
  638. }
  639.  
  640. qservice(s, host, sin, local)
  641. register int s;
  642. register char *host;
  643. register struct sockaddr_in *sin;
  644. register int local;
  645. {
  646.     char request;
  647.  
  648.     if(read(s, &request, 1) != 1)
  649.         return;
  650.     switch(request&0377) {
  651.  
  652.         case 0:
  653.             menqueue(s, host, sin, local);
  654.             enqueues++;
  655.             break;
  656.  
  657.         case 1:
  658.             mshowqueue(s, host, sin, local);
  659.             showqueues++;
  660.             break;
  661.  
  662.         case 2:
  663.             mdequeue(s, host, sin, local);
  664.             dequeues++;
  665.             break;
  666.     }
  667. }
  668.  
  669. menqueue(s, host, sin, local)
  670. register int s;
  671. register char *host;
  672. register struct sockaddr_in *sin;
  673. register int local;
  674. {
  675.     char what[BUFSIZ], prog[BUFSIZ], user[BUFSIZ], buf[BUFSIZ];
  676.     register struct proginfo *pi;
  677.     register struct queueinfo *qi;
  678.     register struct userinfo *ui, *u2;
  679.     register int i, j;
  680.  
  681.     if(!getstr(s, what) || !getstr(s, prog) || !getstr(s, user))
  682.         return;
  683.     alarm(0);
  684.     if(!(pi = pibyname(prog)))
  685.         return;
  686.     qi = pi->pi_queue;
  687.     if(qi->qi_maxperu) {
  688.         for(i = j = 0; i < qi->qi_hcnt; i++)
  689.             for(ui = qi->qi_heads[i]; ui; ui = ui->ui_next)
  690.                 if(!strcmp(user, ui->ui_name))
  691.                     j++;
  692.         for(ui = qi->qi_head; ui; ui = ui->ui_next)
  693.             if(!strcmp(user, ui->ui_name))
  694.                 j++;
  695.         if(j >= qi->qi_maxperu) {
  696.             *buf = 1;
  697.             sprintf(buf + 1, "You already have %d jobs queued", j);
  698.             alarm(DEADMAN);
  699.             write(s, buf, strlen(buf + 1) + 2);
  700.             return;
  701.         }
  702.     }
  703.     ui = (struct userinfo *)malloc(sizeof(struct userinfo));
  704.     *buf = 0;
  705.     sprintf(buf + 1, "%ld", ui->ui_unid = newunid());
  706.     alarm(DEADMAN);
  707.     write(s, buf, strlen(buf + 1) + 2);
  708.     alarm(0);
  709.     ui->ui_addr = *sin;
  710.     ui->ui_addr.sin_port = atoi(what);
  711.     ui->ui_name = newstring(user);
  712.     ui->ui_prog = pi;
  713.     ui->ui_next = 0;
  714.     if(u2 = qi->qi_head) {
  715.         while(u2->ui_next)
  716.             u2 = u2->ui_next;
  717.         u2->ui_next = ui;
  718.     }
  719.     else
  720.         qi->qi_head = ui;
  721. }
  722.  
  723. mshowqueue(s, host, sin, local)
  724. register int s;
  725. register char *host;
  726. register struct sockaddr_in *sin;
  727. register int local;
  728. {
  729.     register int i;
  730.     register struct queueinfo *qi;
  731.     register struct userinfo *ui;
  732.     register struct hostinfo *hi;
  733.     char buf[BUFSIZ];
  734.  
  735.     alarm(0);
  736.     if(fork())
  737.         return;
  738.     for(i = 0; i < 3; i++)
  739.         dup2(s, i);
  740.     if(!getstr(s, buf))
  741.         exit(1);
  742.     if(s > 2)
  743.         close(s);
  744.     if(!strcmp(buf, "test")) {
  745.         printf("Debugging information:\n");
  746.         printf("Strays: %d, Dropouts: %d, Upstarts: %d\n",
  747.             strays, dropouts, upstarts);
  748.         printf("Deadmans: %d\n", deadmans);
  749.         printf("Enqueues: %d, Dequeues: %d, Showqueues: %d\n",
  750.                 enqueues, dequeues, showqueues);
  751.         printf("Host\t\tAddr\t\tEquiv\tLoad\tDead\tQueued\n");
  752.         for(hi = hostinfo; hi; hi = hi->hi_next)
  753.             printf("%-16s%s\t%d\t%d\t%d\t%d\n",
  754.                 hi->hi_name, inet_ntoa(hi->hi_addr.sin_addr),
  755.                 hi->hi_equiv, hi->hi_load,
  756.                 hi->hi_dead, hi->hi_queued);
  757.         printf("\n");
  758.     }
  759.     printf("Queue: %s\n", buf);
  760.     printf("Pid\t\tState\tUser\tHost\tCommand\n");
  761.     fflush(stdout);
  762.     if(!(qi = qibyname(buf)))
  763.         exit(1);
  764.     for(i = 0; i < qi->qi_hcnt; i++)
  765.         for(ui = qi->qi_heads[i]; ui; ui = ui->ui_next) {
  766.             printf("%-16ld", ui->ui_unid);
  767.             printf("RUN\t");
  768.             printf("%s\t", ui->ui_name);
  769.             if(hi = hibyaddr(&ui->ui_addr))
  770.                 printf("%s\t", hi->hi_name);
  771.             else
  772.             printf("%s\t", inet_ntoa(ui->ui_addr.sin_addr.s_addr));
  773.             printf("%s\n", ui->ui_prog->pi_name);
  774.         }
  775.     for(ui = qi->qi_head; ui; ui = ui->ui_next) {
  776.         printf("%-16ld", ui->ui_unid);
  777.         printf("WAIT\t");
  778.         printf("%s\t", ui->ui_name);
  779.         if(hi = hibyaddr(&ui->ui_addr))
  780.             printf("%s\t", hi->hi_name);
  781.         else
  782.         printf("%s\t", inet_ntoa(ui->ui_addr.sin_addr.s_addr));
  783.         printf("%s\n", ui->ui_prog->pi_name);
  784.     }
  785.     fflush(stdout);
  786.     exit(0);
  787. }
  788.  
  789. mdequeue(s, host, sin, local)
  790. register int s;
  791. register char *host;
  792. register struct sockaddr_in *sin;
  793. register int local;
  794. {
  795.     char what[BUFSIZ], prog[BUFSIZ], user[BUFSIZ], buf[BUFSIZ];
  796.     long unid;
  797.     register struct proginfo *pi;
  798.     register struct queueinfo *qi;
  799.     register struct userinfo *ui, *pu;
  800.     register int i;
  801.  
  802.     if(!getstr(s, user) || !getstr(s, prog) || !getstr(s, what))
  803.         return;
  804.     if(!(pi = pibyname(prog)))
  805.         return;
  806.     qi = pi->pi_queue;
  807.     if(strcmp(what, "all"))
  808.         unid = atol(what);
  809.     else
  810.         unid = -1;
  811.     alarm(DEADMAN);
  812.     for(i = 0; i < qi->qi_hcnt; i++)
  813.     top:    for(pu = 0, ui = qi->qi_heads[i]; ui; pu = ui, ui = ui->ui_next)
  814.             if(ui->ui_unid == unid ||
  815.                 (!unid && !strcmp(ui->ui_name, what)) ||
  816.                 unid == -1) {
  817.                 if(strcmp(ui->ui_name, user) &&
  818.                     strcmp(user, "root")) {
  819.                     /*sprintf(buf, "Not owner (%s, %d)\n",
  820.                         ui->ui_name, ui->ui_unid);
  821.                     write(s, buf, strlen(buf));*/
  822.                     continue;
  823.                 }
  824.                 alarm(0);
  825.                 if(pu)
  826.                     pu->ui_next = ui->ui_next;
  827.                 else
  828.                     qi->qi_heads[i] = ui->ui_next;
  829.                 free(ui->ui_name);
  830.                 free(ui);
  831.                 alarm(DEADMAN);
  832.                 /*sprintf(buf, "Killed %d of %s for %s\n",
  833.                     ui->ui_unid, ui->ui_name, user);
  834.                 write(s, buf, strlen(buf));*/
  835.                 goto top;
  836.             }
  837.     alarm(DEADMAN);
  838. top2:    for(pu = 0, ui = qi->qi_head; ui; pu = ui, ui = ui->ui_next)
  839.         if(ui->ui_unid == unid ||
  840.             (!unid && !strcmp(ui->ui_name, what)) || unid == -1) {
  841.             if(strcmp(ui->ui_name, user) &&
  842.                 strcmp(user, "root")) {
  843.                 sprintf(buf, "Not owner (%s, %d)\n",
  844.                     ui->ui_name, ui->ui_unid);
  845.                 write(s, buf, strlen(buf));
  846.                 continue;
  847.             }
  848.             alarm(0);
  849.             if(pu)
  850.                 pu->ui_next = ui->ui_next;
  851.             else
  852.                 qi->qi_head = ui->ui_next;
  853.             *buf = 2;
  854.             sendto(u, buf, 1, 0, &ui->ui_addr, sizeof(ui->ui_addr));
  855.             free(ui->ui_name);
  856.             free(ui);
  857.             alarm(DEADMAN);
  858.             sprintf(buf, "Killed %d of %s for %s\n",
  859.                 ui->ui_unid, ui->ui_name, user);
  860.             write(s, buf, strlen(buf));
  861.             goto top2;
  862.         }
  863. }
  864.