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. */
-
-
- /* selhost.c - Dan Lanciani '85 '89 */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <stdio.h>
- #include <netdb.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <pwd.h>
- #include "queue.h"
-
- extern struct servent *sp;
- extern struct passwd *pw;
- extern long unid;
- extern int tolduser;
- static jmp_buf jb;
-
- static struct ht {
- char *ht_name;
- int ht_load;
- } ht[MAXHCNT];
-
- static
- cmp(a, b)
- struct ht *a, *b;
- {
- return(a->ht_load - b->ht_load);
- }
-
- static
- catch()
- {
- longjmp(jb, 1);
- }
-
- static char *
- ngetstr(n, buf)
- char *buf;
- {
- register char *p = buf;
-
- do
- if(read(n, p, 1) != 1)
- return(0);
- while(*p++);
- return(buf);
- }
-
- static char *argv0;
-
- static
- doqrm()
- {
- char buf[20];
-
- if(argv0 && unid) {
- sprintf(buf, "%ld", unid);
- execl("/usr/local/bin/qrm", "qrm", argv0, buf, 0);
- }
- exit(-1);
- }
-
- selhost(argc, argv)
- char **argv;
- {
- register int i, s, u;
- int sz;
- unsigned char buf[BUFSIZ];
- struct sockaddr_in sin;
-
- argv0 = argv[0];
- if(hcnt < 2 && !*qm)
- return;
- for(i = 0; i < hcnt; i++) {
- ht[i].ht_name = hosts[i];
- ht[i].ht_load = getrload(hosts[i]);
- }
- qsort((char *)ht, hcnt, sizeof(ht[0]), cmp);
- for(i = 0; i < hcnt; i++)
- hosts[i] = ht[i].ht_name;
- if(!*qm || !(sp = getservbyname("qmaster", "tcp")) ||(s=qconnect(qm))<0)
- return;
- if((u = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- perror("socket");
- close(s);
- return;
- }
- bzero(&sin, sizeof(sin));
- if(bind(u, &sin, sizeof(sin))) {
- perror("bind");
- close(u);
- close(s);
- return;
- }
- sz = sizeof(sin);
- if(getsockname(u, &sin, &sz)) {
- perror("getsockname");
- close(u);
- close(s);
- return;
- }
- if(setjmp(jb)) {
- out:
- alarm(0);
- signal(SIGALRM, SIG_DFL);
- close(u);
- if(s >= 0)
- close(s);
- signal(SIGPIPE, SIG_DFL);
- return;
- }
- signal(SIGALRM, catch);
- alarm(5*60);
- signal(SIGPIPE, SIG_IGN);
- *buf = 0;
- sprintf(buf + 1, "%d", sin.sin_port);
- write(s, buf, strlen(buf + 1) + 2);
- write(s, argv0, strlen(argv0) + 1);
- write(s, pw->pw_name, strlen(pw->pw_name) + 1);
- signal(SIGPIPE, SIG_DFL);
- if(read(s, buf, 1) != 1)
- goto out;
- i = *buf;
- if(!ngetstr(s, buf))
- goto out;
- if(i == 1) {
- fprintf(stderr, "%s\n", buf);
- exit(1);
- }
- unid = atol(buf);
- if(!isunid(unid)) {
- unid = 0;
- goto out;
- }
- close(s);
- s = -1;
- alarm(0);
- if(mode == QM_BATCH) {
- tolduser++;
- if(fork()) {
- fprintf(stderr, "Job queued.\n");
- exit(0);
- }
- }
- signal(SIGINT, doqrm);
- alarm(5*60);
- while(1) {
- sz = sizeof(sin);
- if(recvfrom(u, buf, sizeof(buf), 0, &sin, &sz) <= 0) {
- i = alarm(0);
- sleep(10);
- alarm(i);
- continue;
- }
- switch(*buf) {
- case 0:
- alarm(5*60);
- continue;
- case 1:
- alarm(0);
- signal(SIGALRM, SIG_DFL);
- close(u);
- i = hcnt;
- if(i == MAXHCNT)
- i--;
- while(i) {
- hosts[i] = hosts[i - 1];
- i--;
- }
- hosts[0] = newstring(buf + 1);
- return;
- case 2:
- exit(0);
- default:
- goto out;
- }
- }
- }
-