From ce6018836c422c86a729ba39fe5433ec11b87b02 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 14 Sep 1997 18:12:16 +0000 Subject: Pull in sources from zephyr locker. See /mit/zephyr/repository for detailed change information. --- zhm/Imakefile | 27 --- zhm/Makefile.in | 48 +++++ zhm/TODO | 9 - zhm/queue.c | 383 +++++++++++++++++------------------- zhm/timer.c | 257 +++++++++++++++++++++++++ zhm/timer.h | 56 ++++++ zhm/zhm.c | 576 +++++++++++++++++++++++++------------------------------ zhm/zhm.h | 96 ++++------ zhm/zhm_client.c | 125 ++++++------ zhm/zhm_server.c | 216 +++++++++++---------- 10 files changed, 1021 insertions(+), 772 deletions(-) delete mode 100644 zhm/Imakefile create mode 100644 zhm/Makefile.in delete mode 100644 zhm/TODO create mode 100644 zhm/timer.c create mode 100644 zhm/timer.h (limited to 'zhm') diff --git a/zhm/Imakefile b/zhm/Imakefile deleted file mode 100644 index f008e04..0000000 --- a/zhm/Imakefile +++ /dev/null @@ -1,27 +0,0 @@ -/**/# Copyright 1988, 1993 Massachusetts Institute of Technology. -/**/# -/**/# For copying and distribution information, see the file -/**/# "mit-copyright.h". -/**/# -/**/# $Source$ -/**/# $Author$ -/**/# $Zephyr: /mit/zephyr/src/zhm/RCS/Imakefile,v 1.8 91/03/21 11:38:01 raeburn Exp $ -/**/# - -#if defined(SYSLOG_COMPAT42) -SOBJS= ../clients/syslogd/syslog.o -SINCLUDE= -I../clients/syslogd -#endif - -#ifdef __NetBSD__ -OSLIBS=-lcompat /* for insque() */ -#endif - -SRCS= zhm.c zhm_server.c zhm_client.c queue.c -OBJS= zhm.o zhm_server.o zhm_client.o queue.o - -XDEFS= $(SINCLUDE) -DPIDFILE=\"$(ZPIDDIR)/zhm.pid\" - -SimpleProgram(zhm,$(OBJS) $(SOBJS) $(ZLIB),$(ZLIBS) $(OSLIBS),$(ATHRETCDIR)) -install_man(zhm.8,zhm.8) -create_depend($(SRCS)) diff --git a/zhm/Makefile.in b/zhm/Makefile.in new file mode 100644 index 0000000..d591586 --- /dev/null +++ b/zhm/Makefile.in @@ -0,0 +1,48 @@ +SHELL = /bin/sh + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +datadir=@datadir@ +confdir=@confdir@ +sbindir=@sbindir@ +lsbindir=@lsbindir@ + +includedir=${prefix}/include +mandir=${prefix}/man +libdir=${exec_prefix}/lib + +srcdir=@srcdir@ +top_srcdir=@top_srcdir@ +BUILDTOP=.. +VPATH=@srcdir@ +CC=@CC@ +INSTALL=@INSTALL@ + +DEBUG=-O +CFLAGS=${DEBUG} -DCONFDIR=\"${confdir}\" -I${top_srcdir}/h -I${BUILDTOP}/h \ + @CPPFLAGS@ +LDFLAGS=${DEBUG} -L${BUILDTOP}/lib/zephyr @ET_LDFLAGS@ @LDFLAGS@ +LIBS=-lzephyr @LIBS@ -lcom_err + +OBJS= timer.o queue.o zhm.o zhm_client.o zhm_server.o + +all: zhm + +zhm: ${OBJS} ${BUILDTOP}/lib/zephyr/libzephyr.a @ETDEP@ + ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS} + +check: + +install: zhm + ${INSTALL} -m 755 -s zhm ${DESTDIR}${lsbindir} + ${INSTALL} -m 644 ${srcdir}/zhm.8 ${DESTDIR}${mandir}/man8 + +clean: + rm -f ${OBJS} zhm + +${OBJS}: zhm.h timer.h ${top_srcdir}/h/internal.h ${top_srcdir}/h/sysdep.h +${OBJS}: ${BUILDTOP}/h/config.h ${BUILDTOP}/h/zephyr/zephyr.h +${OBJS}: ${BUILDTOP}/h/zephyr/zephyr_err.h + +.PHONY: all check install clean + diff --git a/zhm/TODO b/zhm/TODO deleted file mode 100644 index 4562044..0000000 --- a/zhm/TODO +++ /dev/null @@ -1,9 +0,0 @@ - -Search for all occurences of (void) typecasting, and see whether I -should be checking return values. Make sure all mallocs are checked -for return values. - -Set system up to handle SERVNAK returns if we cannot reach a server. - -Set to handle emergency notices. - diff --git a/zhm/queue.c b/zhm/queue.c index fd87546..5e0ca3a 100644 --- a/zhm/queue.c +++ b/zhm/queue.c @@ -20,249 +20,224 @@ static char rcsid_queue_c[] = "$Header$"; #endif /* lint */ typedef struct _Queue { - long timeout; - int retries; - ZNotice_t z_notice; - caddr_t z_packet; - struct sockaddr_in reply; + Timer *timer; + int retries; + ZNotice_t notice; + caddr_t packet; + struct sockaddr_in reply; + struct _Queue *next, **prev_p; } Queue; -struct _qelem { - struct _qelem *q_forw; - struct _qelem *q_back; - Queue *q_data; -}; +static Queue *hm_queue; +static int retransmits_enabled = 0; -typedef struct _qelem Qelem; - -Qelem hm_queue = { &hm_queue, &hm_queue, NULL }, *is_in_queue(); +static Queue *find_notice_in_queue __P((ZNotice_t *notice)); +static Code_t dump_queue __P((void)); +static void queue_timeout __P((void *arg)); int rexmit_times[] = { 2, 2, 4, 4, 8, -1 }; -extern long time(); -extern int timeout_type; +#ifdef DEBUG +Code_t dump_queue(); +#endif void init_queue() { - while (hm_queue.q_forw != &hm_queue) { - free(hm_queue.q_forw->q_data->z_packet); - free((char *)hm_queue.q_forw->q_data); - remque(hm_queue.q_forw); - free((char *)hm_queue.q_forw); - } - - hm_queue.q_forw = hm_queue.q_back = &hm_queue; - hm_queue.q_data = NULL; - DPR ("Queue initialized and flushed.\n"); + Queue *q; + + while (hm_queue) { + q = hm_queue; + if (q->timer) + timer_reset(q->timer); + free(q->packet); + hm_queue = q->next; + free(q); + } + + DPR("Queue initialized and flushed.\n"); } Code_t add_notice_to_queue(notice, packet, repl, len) -ZNotice_t *notice; -caddr_t packet; -struct sockaddr_in *repl; -int len; + ZNotice_t *notice; + char * packet; + struct sockaddr_in *repl; + int len; { - Qelem *elem; - Queue *entry; - - DPR ("Adding notice to queue...\n"); - if (!is_in_queue(notice)) { - elem = (Qelem *)malloc(sizeof(Qelem)); - entry = (Queue *)malloc(sizeof(Queue)); - entry->timeout = time((time_t *)0) + rexmit_times[0]; - entry->retries = 0; - entry->z_packet = (char *)malloc(Z_MAXPKTLEN); - (void) memcpy(entry->z_packet, packet, Z_MAXPKTLEN); - if (ZParseNotice(entry->z_packet, len, &entry->z_notice) - != ZERR_NONE) { - syslog(LOG_ERR, "ZParseNotice failed, but succeeded before"); - free(entry->z_packet); - } else { - entry->reply = *repl; - elem->q_data = entry; - elem->q_forw = elem; - elem->q_back = elem; - insque(elem, hm_queue.q_back); - } - } -#ifdef DEBUG - if (!is_in_queue(notice)) - return(ZERR_NONOTICE); - else -#endif /* DEBUG */ - return(ZERR_NONE); + Queue *entry; + + DPR("Adding notice to queue...\n"); + if (!find_notice_in_queue(notice)) { + entry = (Queue *) malloc(sizeof(Queue)); + entry->retries = 0; + entry->packet = (char *) malloc(Z_MAXPKTLEN); + memcpy(entry->packet, packet, Z_MAXPKTLEN); + if (ZParseNotice(entry->packet, len, &entry->notice) != ZERR_NONE) { + syslog(LOG_ERR, "ZParseNotice failed, but succeeded before"); + free(entry->packet); + } else { + entry->reply = *repl; + LIST_INSERT(&hm_queue, entry); + } + entry->timer = (retransmits_enabled) ? + timer_set_rel(rexmit_times[0], queue_timeout, entry) : NULL; + } + return(ZERR_NONE); } Code_t remove_notice_from_queue(notice, kind, repl) -ZNotice_t *notice; -ZNotice_Kind_t *kind; -struct sockaddr_in *repl; + ZNotice_t *notice; + ZNotice_Kind_t *kind; + struct sockaddr_in *repl; { - Qelem *elem; - - DPR ("Removing notice from queue...\n"); - if ((elem = is_in_queue(notice)) == NULL) - return(ZERR_NONOTICE); - else { - *kind = elem->q_data->z_notice.z_kind; - *repl = elem->q_data->reply; - free(elem->q_data->z_packet); - free((char *)elem->q_data); - remque(elem); - free((char *)elem); - if (hm_queue.q_forw == &hm_queue) - (void)alarm(0); + Queue *entry; + + DPR("Removing notice from queue...\n"); + entry = find_notice_in_queue(notice); + if (entry == NULL) + return(ZERR_NONOTICE); + + *kind = entry->notice.z_kind; + *repl = entry->reply; + timer_reset(entry->timer); + free(entry->packet); + LIST_DELETE(entry); #ifdef DEBUG - dump_queue(); + dump_queue(); #endif /* DEBUG */ - return(ZERR_NONE); - } + return(ZERR_NONE); } +/* We have a server; transmit all of our packets. */ void retransmit_queue(sin) -struct sockaddr_in *sin; + struct sockaddr_in *sin; { - Qelem *srch; - Code_t ret; + Queue *entry; + Code_t ret; + + DPR("Retransmitting queue to new server...\n"); + ret = ZSetDestAddr(sin); + if (ret != ZERR_NONE) { + Zperr (ret); + com_err("queue", ret, "setting destination"); + } + for (entry = hm_queue; entry; entry = entry->next) { + DPR("notice:\n"); + DPR2("\tz_kind: %d\n", entry->notice.z_kind); + DPR2("\tz_port: %u\n", ntohs(entry->notice.z_port)); + DPR2("\tz_class: %s\n", entry->notice.z_class); + DPR2("\tz_clss_inst: %s\n", entry->notice.z_class_inst); + DPR2("\tz_opcode: %s\n", entry->notice.z_opcode); + DPR2("\tz_sender: %s\n", entry->notice.z_sender); + DPR2("\tz_recip: %s\n", entry->notice.z_recipient); + ret = send_outgoing(&entry->notice); + if (ret != ZERR_NONE) { + Zperr(ret); + com_err("queue", ret, "sending raw notice"); + } + entry->timer = timer_set_rel(rexmit_times[0], queue_timeout, entry); + entry->retries = 0; + } + retransmits_enabled = 1; +} - DPR ("Retransmitting queue to new server...\n"); - if ((ret = ZSetDestAddr(sin)) != ZERR_NONE) { - Zperr (ret); - com_err("queue", ret, "setting destination"); - } - if ((srch = hm_queue.q_forw) != &hm_queue) { - do { - DPR ("notice:\n"); - DPR2 ("\tz_kind: %d\n", srch->q_data->z_notice.z_kind); - DPR2 ("\tz_port: %u\n", - ntohs(srch->q_data->z_notice.z_port)); - DPR2 ("\tz_class: %s\n", srch->q_data->z_notice.z_class); - DPR2 ("\tz_clss_inst: %s\n", - srch->q_data->z_notice.z_class_inst); - DPR2 ("\tz_opcode: %s\n", srch->q_data->z_notice.z_opcode); - DPR2 ("\tz_sender: %s\n", srch->q_data->z_notice.z_sender); - DPR2 ("\tz_recip: %s\n", srch->q_data->z_notice.z_recipient); - if ((ret = send_outgoing(&srch->q_data->z_notice)) - != ZERR_NONE) { - Zperr (ret); - com_err("queue", ret, "sending raw notice"); - } - srch->q_data->timeout = time(0) + rexmit_times[0]; - srch->q_data->retries = 0; - srch = srch->q_forw; - } while (srch != &hm_queue); - timeout_type = NOTICES; - (void)alarm(rexmit_times[0]); - } +/* We lost our server; nuke all of our timers. */ +void disable_queue_retransmits() +{ + Queue *entry; + + for (entry = hm_queue; entry; entry = entry->next) { + if (entry->timer) + timer_reset(entry->timer); + entry->timer = NULL; + } + retransmits_enabled = 0; } #ifdef DEBUG -Code_t dump_queue() +static Code_t dump_queue() { - Qelem *srch; - caddr_t mp; - int ml; - - DPR ("Dumping queue...\n"); - if ((srch = hm_queue.q_forw) == &hm_queue) - printf("Queue is empty.\n"); - else do { - printf("notice:\n"); - printf("\tz_kind: %d\n", srch->q_data->z_notice.z_kind); - printf("\tz_port: %u\n", ntohs(srch->q_data->z_notice.z_port)); - printf("\tz_class: %s\n", srch->q_data->z_notice.z_class); - printf("\tz_clss_inst: %s\n", srch->q_data->z_notice.z_class_inst); - printf("\tz_opcode: %s\n", srch->q_data->z_notice.z_opcode); - printf("\tz_sender: %s\n", srch->q_data->z_notice.z_sender); - printf("\tz_recip: %s\n", srch->q_data->z_notice.z_recipient); - printf("\tMessage:\n"); - mp = srch->q_data->z_notice.z_message; - for (ml = strlen(mp)+1; - ml <= srch->q_data->z_notice.z_message_len; ml++) { - printf("\t%s\n", mp); - mp += strlen(mp)+1; - ml += strlen(mp); - } - srch = srch->q_forw; - } while (srch != &hm_queue); + Queue *entry; + caddr_t mp; + int ml; + + DPR("Dumping queue...\n"); + if (!hm_queue) { + printf("Queue is empty.\n"); + return; + } + + for (entry = hm_queue; entry; entry = entry->next) { + printf("notice:\n"); + printf("\tz_kind: %d\n", entry->notice.z_kind); + printf("\tz_port: %u\n", ntohs(entry->notice.z_port)); + printf("\tz_class: %s\n", entry->notice.z_class); + printf("\tz_clss_inst: %s\n", entry->notice.z_class_inst); + printf("\tz_opcode: %s\n", entry->notice.z_opcode); + printf("\tz_sender: %s\n", entry->notice.z_sender); + printf("\tz_recip: %s\n", entry->notice.z_recipient); + printf("\tMessage:\n"); + mp = entry->notice.z_message; + for (ml = strlen(mp) + 1; ml <= entry->notice.z_message_len; ml++) { + printf("\t%s\n", mp); + mp += strlen(mp)+1; + ml += strlen(mp); + } + } } #endif /* DEBUG */ int queue_len() { - int length = 0; - Qelem *srch; + int length = 0; + Queue *entry; - if ((srch = hm_queue.q_forw) != &hm_queue) { - do { - length++; - srch = srch->q_forw; - } while (srch != &hm_queue); - } - return(length); + for (entry = hm_queue; entry; entry = entry->next) + length++; + return length; } -Qelem *is_in_queue(notice) -ZNotice_t *notice; +static Queue *find_notice_in_queue(notice) + ZNotice_t *notice; { - Qelem *srch; + Queue *entry; - srch = hm_queue.q_forw; - if (srch == &hm_queue) - return(NULL); - do { - if (ZCompareUID(&(srch->q_data->z_notice.z_uid), &(notice->z_uid))) - return(srch); - srch = srch->q_forw; - } while (srch != &hm_queue); - return(NULL); + for (entry = hm_queue; entry; entry = entry->next) { + if (ZCompareUID(&entry->notice.z_uid, ¬ice->z_uid)) + return entry; + } + return NULL; } -void resend_notices(sin) -struct sockaddr_in *sin; +static void queue_timeout(arg) + void *arg; { - Qelem *srch; - Code_t ret; - - DPR ("Resending notices...\n"); - if ((ret = ZSetDestAddr(sin)) != ZERR_NONE) { - Zperr(ret); - com_err("queue", ret, "setting destination"); - } - if ((srch = hm_queue.q_forw) == &hm_queue) { - syslog (LOG_INFO, "No notices, shouldn't have happened!"); - } else do { - if (srch->q_data->timeout <= time((time_t *)0)) { - srch->q_data->retries++; - if (rexmit_times[srch->q_data->retries] == -1) { - new_server((char *)NULL); - break; - } else { - DPR ("notice:\n"); - DPR2 ("\tz_kind: %d\n", srch->q_data->z_notice.z_kind); - DPR2 ("\tz_port: %u\n", - ntohs(srch->q_data->z_notice.z_port)); - DPR2 ("\tz_class: %s\n", - srch->q_data->z_notice.z_class); - DPR2 ("\tz_clss_inst: %s\n", - srch->q_data->z_notice.z_class_inst); - DPR2 ("\tz_opcode: %s\n", - srch->q_data->z_notice.z_opcode); - DPR2 ("\tz_sender: %s\n", - srch->q_data->z_notice.z_sender); - DPR2 ("\tz_recip: %s\n", - srch->q_data->z_notice.z_recipient); - if ((ret = send_outgoing(&srch->q_data->z_notice)) - != ZERR_NONE) { - Zperr(ret); - com_err("queue", ret, "sending raw notice"); - } - srch->q_data->timeout = time((time_t *)0) + - rexmit_times[srch->q_data->retries]; - } - srch = srch->q_forw; - } - } while (srch != &hm_queue); - if (timeout_type == NOTICES) - (void)alarm(rexmit_times[0]); + Queue *entry = (Queue *) arg; + Code_t ret; + + ret = ZSetDestAddr(&serv_sin); + if (ret != ZERR_NONE) { + Zperr(ret); + com_err("queue", ret, "setting destination"); + } + entry->retries++; + if (rexmit_times[entry->retries] == -1) { + new_server(NULL); + return; + } + DPR("Resending notice:\n"); + DPR2("\tz_kind: %d\n", entry->notice.z_kind); + DPR2("\tz_port: %u\n", ntohs(entry->notice.z_port)); + DPR2("\tz_class: %s\n", entry->notice.z_class); + DPR2("\tz_clss_inst: %s\n", entry->notice.z_class_inst); + DPR2("\tz_opcode: %s\n", entry->notice.z_opcode); + DPR2("\tz_sender: %s\n", entry->notice.z_sender); + DPR2("\tz_recip: %s\n", entry->notice.z_recipient); + ret = send_outgoing(&entry->notice); + if (ret != ZERR_NONE) { + Zperr(ret); + com_err("queue", ret, "sending raw notice"); + } + entry->timer = timer_set_rel(rexmit_times[entry->retries], queue_timeout, + entry); } + diff --git a/zhm/timer.c b/zhm/timer.c new file mode 100644 index 0000000..8fb68e5 --- /dev/null +++ b/zhm/timer.c @@ -0,0 +1,257 @@ +/* This file is part of the Project Athena Zephyr Notification System. + * It contains functions for managing multiple timeouts. + * + * Created by: John T. Kohl + * Derived from timer_manager_ by Ken Raeburn + * + * $Source$ + * $Author$ + * + */ + +#include "internal.h" +#include "timer.h" + +#ifndef SABER +#ifndef lint +static const char rcsid[] = +"$Id$"; +#endif /* lint */ +#endif /* SABER */ + +/* + * timer_manager_ -- routines for handling timers in login_shell + * (and elsewhere) + * + * Copyright 1986 Student Information Processing Board, + * Massachusetts Institute of Technology + * + * written by Ken Raeburn + + Permission to use, copy, modify, and distribute this + software and its documentation for any purpose and without + fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright + notice and this permission notice appear in supporting + documentation, and that the name of M.I.T. and the Student + Information Processing Board not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + M.I.T. and the Student Information Processing Board + make no representations about the suitability of + this software for any purpose. It is provided "as is" + without express or implied warranty. + + */ + + +/* + * External functions: + * + * Timer *timer_set_rel (time_rel, proc, arg) + * long time_rel; + * void (*proc)(); + * caddr_t arg; + * Timer *timer_set_abs (time_abs, proc, arg) + * long time_abs; + * void (*proc)(); + * caddr_t arg; + * + * void timer_reset(tmr) + * Timer *tmr; + * + * void timer_process() + * + */ + +/* DELTA is just an offset to keep the size a bit less than a power + * of two. It's measured in pointers, so it's 32 bytes on most + * systems. */ +#define DELTA 8 +#define INITIAL_HEAP_SIZE (1024 - DELTA) + +/* We have three operations which we need to be able to perform + * quickly: adding a timer, deleting a timer given a pointer to + * it, and determining which timer will be the next to go off. A + * heap is an ideal data structure for these purposes, so we use + * one. The heap is an array of pointers to timers, and each timer + * knows the position of its pointer in the heap. + * + * Okay, what is the heap, exactly? It's a data structure, + * represented as an array, with the invariant condition that + * the timeout of heap[i] is less than or equal to the timeout of + * heap[i * 2 + 1] and heap[i * 2 + 2] (assuming i * 2 + 1 and + * i * 2 + 2 are valid * indices). An obvious consequence of this + * is that heap[0] has the lowest timer value, so finding the first + * timer to go off is easy. We say that an index i has "children" + * i * 2 + 1 and i * 2 + 1, and the "parent" (i - 1) / 2. + * + * To add a timer to the heap, we start by adding it to the end, and + * then keep swapping it with its parent until it has a parent with + * a timer value less than its value. With a little bit of thought, + * you can see that this preserves the heap property on all indices + * of the array. + * + * To delete a timer at position i from the heap, we discard it and + * fill in its position with the last timer in the heap. In order + * to restore the heap, we have to consider two cases: the timer + * value at i is less than that of its parent, or the timer value at + * i is greater than that of one of its children. In the first case, + * we propagate the timer at i up the tree, swapping it with its + * parent, until the heap is restored; in the second case, we + * propagate the timer down the tree, swapping it with its least + * child, until the heap is restored. */ + +/* In order to ensure that the back pointers from timers are consistent + * with the heap pointers, all heap assignments should be done with the + * HEAP_ASSIGN() macro, which sets the back pointer and updates the + * heap at the same time. */ +#define PARENT(i) (((i) - 1) / 2) +#define CHILD1(i) ((i) * 2 + 1) +#define CHILD2(i) ((i) * 2 + 2) +#define TIME(i) (heap[i]->abstime) +#define HEAP_ASSIGN(pos, tmr) ((heap[pos] = (tmr))->heap_pos = (pos)) + +static Timer **heap; +static int num_timers = 0; +static int heap_size = 0; + +static void timer_botch __P((void*)); +static Timer *add_timer __P((Timer *)); + +Timer *timer_set_rel(time_rel, proc, arg) + long time_rel; + void (*proc) __P((void *)); + void *arg; +{ + Timer *new_t; + + new_t = (Timer *) malloc(sizeof(*new_t)); + if (new_t == NULL) + return(NULL); + new_t->abstime = time_rel + time(NULL); + new_t->func = proc; + new_t->arg = arg; + return add_timer(new_t); +} + +void +timer_reset(tmr) + Timer *tmr; +{ + int pos, min; + + /* Free the timer, saving its heap position. */ + pos = tmr->heap_pos; + free(tmr); + + if (pos != num_timers - 1) { + /* Replace the timer with the last timer in the heap and + * restore the heap, propagating the timer either up or + * down, depending on which way it violates the heap + * property to insert the last timer in place of the + * deleted timer. */ + if (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos))) { + do { + HEAP_ASSIGN(pos, heap[PARENT(pos)]); + pos = PARENT(pos); + } while (pos > 0 && TIME(num_timers - 1) < TIME(PARENT(pos))); + HEAP_ASSIGN(pos, heap[num_timers - 1]); + } else { + while (CHILD2(pos) < num_timers) { + min = num_timers - 1; + if (TIME(CHILD1(pos)) < TIME(min)) + min = CHILD1(pos); + if (TIME(CHILD2(pos)) < TIME(min)) + min = CHILD2(pos); + HEAP_ASSIGN(pos, heap[min]); + pos = min; + } + if (pos != num_timers - 1) + HEAP_ASSIGN(pos, heap[num_timers - 1]); + } + } + num_timers--; +} + + +#define set_timeval(t,s) ((t).tv_sec=(s),(t).tv_usec=0,(t)) + +static Timer * +add_timer(new) + Timer *new; +{ + int pos; + + /* Create or resize the heap as necessary. */ + if (heap_size == 0) { + heap_size = INITIAL_HEAP_SIZE; + heap = (Timer **) malloc(heap_size * sizeof(Timer *)); + } else if (num_timers >= heap_size) { + heap_size = heap_size * 2 + DELTA; + heap = (Timer **) realloc(heap, heap_size * sizeof(Timer *)); + } + if (!heap) { + free(new); + return NULL; + } + + /* Insert the Timer *into the heap. */ + pos = num_timers; + while (pos > 0 && new->abstime < TIME(PARENT(pos))) { + HEAP_ASSIGN(pos, heap[PARENT(pos)]); + pos = PARENT(pos); + } + HEAP_ASSIGN(pos, new); + num_timers++; + + return new; +} + +void +timer_process() +{ + Timer *t; + timer_proc func; + void *arg; + int valid = 0; + + if (num_timers == 0 || heap[0]->abstime > time(NULL)) + return; + + /* Remove the first timer from the heap, remembering its + * function and argument. */ + t = heap[0]; + func = t->func; + arg = t->arg; + t->func = timer_botch; + t->arg = NULL; + timer_reset(t); + + /* Run the function. */ + func(arg); +} + +struct timeval * +timer_timeout(tvbuf) + struct timeval *tvbuf; +{ + if (num_timers > 0) { + tvbuf->tv_sec = heap[0]->abstime - time(NULL); + if (tvbuf->tv_sec < 0) + tvbuf->tv_sec = 0; + tvbuf->tv_usec = 0; + return tvbuf; + } else { + return NULL; + } +} + +static void +timer_botch(arg) + void *arg; +{ + syslog(LOG_CRIT, "timer botch\n"); + abort(); +} + diff --git a/zhm/timer.h b/zhm/timer.h new file mode 100644 index 0000000..42c0081 --- /dev/null +++ b/zhm/timer.h @@ -0,0 +1,56 @@ +/* This file is part of the Project Athena Zephyr Notification System. + * It contains definitions used by timer.c + * + * Created by: John T. Kohl + * Derived from timer_manager_.h by Ken Raeburn + * + * $Source$ + * $Author$ + * $Header$ + * + */ + +#ifndef __TIMER_H + +/* + * timer_manager_ -- routines for handling timers in login_shell + * (and elsewhere) + * + * Copyright 1986 Student Information Processing Board, + * Massachusetts Institute of Technology + * + * written by Ken Raeburn + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of M.I.T. and the Student +Information Processing Board not be used in +advertising or publicity pertaining to distribution of the +software without specific, written prior permission. +M.I.T. and the Student Information Processing Board +make no representations about the suitability of +this software for any purpose. It is provided "as is" +without express or implied warranty. + + */ + +typedef void (*timer_proc) __P((void *)); + +typedef struct _Timer { + int heap_pos; /* Position in timer heap */ + long abstime; + timer_proc func; + void *arg; +} Timer; + +Timer *timer_set_rel __P((long, timer_proc, void *)); +Timer *timer_set_abs __P((long, timer_proc, void *)); +void timer_reset __P((Timer *)); +void timer_process __P((void)); +struct timeval *timer_timeout __P((struct timeval *tvbuf)); + +#endif /* __TIMER_H */ + diff --git a/zhm/zhm.c b/zhm/zhm.c index ff89aec..51a67af 100644 --- a/zhm/zhm.c +++ b/zhm/zhm.c @@ -13,28 +13,9 @@ #include "zhm.h" -static char rcsid_hm_c[] = "$Id$"; +static const char rcsid_hm_c[] = "$Id$"; -#ifdef POSIX -#include -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -/* - * warning: sys/param.h may include sys/types.h which may not be protected from - * multiple inclusions on your system - */ -#include - -#ifdef Z_HaveHesiod -#include +#ifdef ZEPHYR_USES_HESIOD int use_hesiod = 0; #endif @@ -42,6 +23,12 @@ int use_hesiod = 0; #define srandom srand48 #endif +#ifdef _PATH_VARRUN +#define PIDDIR _PATH_VARRUN +#else +#define PIDDIR "/etc/" +#endif + int hmdebug, rebootflag, errflg, dieflag, inetd, oldpid, nofork; int no_server = 1, nservchang, nserv, nclt; int booting = 1, timeout_type, deactivated = 1; @@ -49,219 +36,220 @@ long starttime; u_short cli_port; struct sockaddr_in cli_sin, serv_sin, from; int numserv; -char **serv_list = (char **)0; +char **serv_list = NULL; char prim_serv[MAXHOSTNAMELEN], cur_serv[MAXHOSTNAMELEN]; char *zcluster; -int sig_type; +int deactivating = 0; +int terminating = 0; struct hostent *hp; char **clust_info; char hostname[MAXHOSTNAMELEN], loopback[4]; -char *PidFile = PIDFILE; - -void choose_server(), init_hm(), detach(), - handle_timeout(), resend_notices(), die_gracefully(); - -#ifdef POSIX -void -#endif - set_sig_type(sig) - int sig; +char PidFile[128]; + +static RETSIGTYPE deactivate __P((void)); +static RETSIGTYPE terminate __P((void)); +static void choose_server __P((void)); +static void init_hm __P((void)); +static void detach __P((void)); +static void send_stats __P((ZNotice_t *, struct sockaddr_in *)); +static char *strsave __P((const char *)); +extern int optind; + +static RETSIGTYPE deactivate() { - sig_type = sig; + deactivating = 1; } -char *strsave(); +static RETSIGTYPE terminate() +{ + terminating = 1; +} main(argc, argv) char *argv[]; { - ZNotice_t notice; - ZPacket_t packet; - Code_t ret; - int opt, pak_len; - extern int optind; - register int i, j = 0; - -#ifdef _AIX - struct sigaction sa; - - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_FULLDUMP; - sa.sa_handler = SIG_DFL; - sigaction(SIGSEGV, &sa, (struct sigaction *)0); -#endif - - if (gethostname(hostname, MAXHOSTNAMELEN) < 0) { - printf("Can't find my hostname?!\n"); - exit(-1); - } - prim_serv[0] = '\0'; - while ((opt = getopt(argc, argv, "drhin")) != EOF) - switch(opt) { + ZNotice_t notice; + ZPacket_t packet; + Code_t ret; + int opt, pak_len, i, j = 0, fd, count; + fd_set readers; + struct timeval tv; + + sprintf(PidFile, "%szhm.pid", PIDDIR); + + if (gethostname(hostname, MAXHOSTNAMELEN) < 0) { + printf("Can't find my hostname?!\n"); + exit(-1); + } + prim_serv[0] = '\0'; + while ((opt = getopt(argc, argv, "drhin")) != EOF) + switch(opt) { case 'd': - hmdebug++; - break; + hmdebug = 1; + break; case 'h': - /* Die on SIGHUP */ - dieflag++; - break; + /* Die on SIGHUP */ + dieflag = 1; + break; case 'r': - /* Reboot host -- send boot notice -- and exit */ - rebootflag++; - break; + /* Reboot host -- send boot notice -- and exit */ + rebootflag= 1; + break; case 'i': - /* inetd operation: don't do bind ourselves, fd 0 is - already connected to a socket. Implies -h */ - inetd++; - dieflag++; - break; + /* inetd operation: don't do bind ourselves, fd 0 is + already connected to a socket. Implies -h */ + inetd = 1; + dieflag = 1; + break; case 'n': - nofork = 1; - break; + nofork = 1; + break; case '?': default: - errflg++; - break; - } - if (errflg) { - fprintf(stderr, "Usage: %s [-d] [-h] [-r] [-n] [server]\n", argv[0]); - exit(2); - } + errflg++; + break; + } + if (errflg) { + fprintf(stderr, "Usage: %s [-d] [-h] [-r] [-n] [server]\n", argv[0]); + exit(2); + } + + numserv = 0; - numserv = 0; - - /* Override server argument? */ - if (optind < argc) { - if ((hp = gethostbyname(argv[optind++])) == NULL) { - printf("Unknown server name: %s\n", argv[optind-1]); - } else - (void) strcpy(prim_serv, hp->h_name); - - /* argc-optind is the # of other servers on the command line */ - serv_list = (char **)malloc((argc-optind + 2) * sizeof(char *)); - serv_list[numserv++] = prim_serv; - for (; optind < argc; optind++) { - if ((hp = gethostbyname(argv[optind])) == NULL) { - printf("Unknown server name '%s', ignoring\n", argv[optind]); - continue; - } + /* Override server argument? */ + if (optind < argc) { + if ((hp = gethostbyname(argv[optind++])) == NULL) { + printf("Unknown server name: %s\n", argv[optind-1]); + } else + strcpy(prim_serv, hp->h_name); + + /* argc-optind is the # of other servers on the command line */ + serv_list = (char **) malloc((argc - optind + 2) * sizeof(char *)); + serv_list[numserv++] = prim_serv; + for (; optind < argc; optind++) { + if ((hp = gethostbyname(argv[optind])) == NULL) { + printf("Unknown server name '%s', ignoring\n", argv[optind]); + continue; + } serv_list[numserv++] = strsave(hp->h_name); - } - serv_list[numserv] = NULL; - } -#ifdef Z_HaveHesiod - else - use_hesiod = 1; + } + serv_list[numserv] = NULL; + } +#ifdef ZEPHYR_USES_HESIOD + else + use_hesiod = 1; #endif - choose_server(); - if (*prim_serv == '\0') { - printf("No valid primary server found, exiting.\n"); - exit(ZERR_SERVNAK); - } - init_hm(); + choose_server(); + if (*prim_serv == '\0') { + printf("No valid primary server found, exiting.\n"); + exit(ZERR_SERVNAK); + } + init_hm(); - DPR2 ("zephyr server port: %u\n", ntohs(serv_sin.sin_port)); - DPR2 ("zephyr client port: %u\n", ntohs(cli_port)); + DPR2("zephyr server port: %u\n", ntohs(serv_sin.sin_port)); + DPR2("zephyr client port: %u\n", ntohs(cli_port)); - /* Main loop */ - for ever { - DPR ("Waiting for a packet..."); - switch(sig_type) { - case 0: - break; - case SIGHUP: /* A SIGHUP means we are deactivating the ws. */ - sig_type = 0; - if (dieflag) { - die_gracefully(); - } else { - choose_server(); - send_flush_notice(HM_FLUSH); - deactivated = 1; - } - break; - case SIGTERM: - sig_type = 0; - die_gracefully(); - break; - case SIGALRM: - sig_type = 0; - handle_timeout(); - break; - default: - sig_type = 0; - syslog (LOG_WARNING, "Unknown system interrupt."); - break; - } - ret = ZReceivePacket(packet, &pak_len, &from); - if ((ret != ZERR_NONE) && (ret != EINTR)){ - Zperr(ret); - com_err("hm", ret, "receiving notice"); - } else if (ret != EINTR) { - /* Where did it come from? */ - if ((ret = ZParseNotice(packet, pak_len, ¬ice)) - != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "parsing notice"); - } else { - DPR ("Got a packet.\n"); - DPR ("notice:\n"); - DPR2("\tz_kind: %d\n", notice.z_kind); - DPR2("\tz_port: %u\n", ntohs(notice.z_port)); - DPR2("\tz_class: %s\n", notice.z_class); - DPR2("\tz_class_inst: %s\n", notice.z_class_inst); - DPR2("\tz_opcode: %s\n", notice.z_opcode); - DPR2("\tz_sender: %s\n", notice.z_sender); - DPR2("\tz_recip: %s\n", notice.z_recipient); - DPR2("\tz_def_format: %s\n", notice.z_default_format); - DPR2("\tz_message: %s\n", notice.z_message); - if (memcmp(loopback, (char *)&from.sin_addr, 4) && - ((notice.z_kind == SERVACK) || - (notice.z_kind == SERVNAK) || - (notice.z_kind == HMCTL))) { - server_manager(¬ice); - } else { - if (!memcmp(loopback, (char *)&from.sin_addr, 4) && - ((notice.z_kind == UNSAFE) || - (notice.z_kind == UNACKED) || - (notice.z_kind == ACKED) || - (notice.z_kind == HMCTL))) { - /* Client program... */ - if (deactivated) { + /* Main loop */ + for ever { + /* Wait for incoming packets or queue timeouts. */ + DPR("Waiting for a packet..."); + fd = ZGetFD(); + FD_ZERO(&readers); + FD_SET(fd, &readers); + count = select(fd + 1, &readers, NULL, NULL, timer_timeout(&tv)); + if (count == -1 && errno != EINTR) { + syslog(LOG_CRIT, "select() failed: %m"); + die_gracefully(); + } + + if (terminating) + die_gracefully(); + + if (deactivating) { + deactivating = 0; + if (dieflag) { + die_gracefully(); + } else { + choose_server(); + send_flush_notice(HM_FLUSH); + deactivated = 1; + } + } + + timer_process(); + + if (count > 0) { + ret = ZReceivePacket(packet, &pak_len, &from); + if ((ret != ZERR_NONE) && (ret != EINTR)){ + Zperr(ret); + com_err("hm", ret, "receiving notice"); + } else if (ret != EINTR) { + /* Where did it come from? */ + if ((ret = ZParseNotice(packet, pak_len, ¬ice)) + != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "parsing notice"); + } else { + DPR("Got a packet.\n"); + DPR("notice:\n"); + DPR2("\tz_kind: %d\n", notice.z_kind); + DPR2("\tz_port: %u\n", ntohs(notice.z_port)); + DPR2("\tz_class: %s\n", notice.z_class); + DPR2("\tz_class_inst: %s\n", notice.z_class_inst); + DPR2("\tz_opcode: %s\n", notice.z_opcode); + DPR2("\tz_sender: %s\n", notice.z_sender); + DPR2("\tz_recip: %s\n", notice.z_recipient); + DPR2("\tz_def_format: %s\n", notice.z_default_format); + DPR2("\tz_message: %s\n", notice.z_message); + if (memcmp(loopback, &from.sin_addr, 4) && + ((notice.z_kind == SERVACK) || + (notice.z_kind == SERVNAK) || + (notice.z_kind == HMCTL))) { + server_manager(¬ice); + } else { + if (!memcmp(loopback, &from.sin_addr, 4) && + ((notice.z_kind == UNSAFE) || + (notice.z_kind == UNACKED) || + (notice.z_kind == ACKED) || + (notice.z_kind == HMCTL))) { + /* Client program... */ + if (deactivated) { send_boot_notice(HM_BOOT); deactivated = 0; - } - transmission_tower(¬ice, packet, pak_len); - DPR2 ("Pending = %d\n", ZPending()); - } else { - if (notice.z_kind == STAT) { + } + transmission_tower(¬ice, packet, pak_len); + DPR2("Pending = %d\n", ZPending()); + } else { + if (notice.z_kind == STAT) { send_stats(¬ice, &from); - } else { + } else { syslog(LOG_INFO, "Unknown notice type: %d", notice.z_kind); - } - } - } - } - } - } + } + } + } + } + } + } + } } -void choose_server() +static void choose_server() { int i = 0; -#ifdef Z_HaveHesiod +#ifdef ZEPHYR_USES_HESIOD if (use_hesiod) { /* Free up any previously used resources */ if (prim_serv[0]) i = 1; while (i < numserv) - (void) free(serv_list[i++]); + free(serv_list[i++]); if (serv_list) - (void) free(serv_list); + free(serv_list); numserv = 0; prim_serv[0] = '\0'; @@ -280,7 +268,7 @@ void choose_server() if ((c = strchr(*clust_info, ' ')) == 0) { printf("Hesiod error getting primary server info.\n"); } else - (void)strcpy(prim_serv, c+1); + strcpy(prim_serv, c+1); break; } if (!strncasecmp("ZCLUSTER", *clust_info, 9)) { @@ -291,7 +279,7 @@ void choose_server() } else { if ((zcluster = malloc((unsigned)(strlen(c+1)+1))) != NULL) { - (void)strcpy(zcluster, c+1); + strcpy(zcluster, c+1); } else { printf("Out of memory.\n"); exit(-5); @@ -303,14 +291,14 @@ void choose_server() if (zcluster == NULL) { if ((zcluster = malloc((unsigned)(strlen("zephyr")+1))) != NULL) - (void)strcpy(zcluster, "zephyr"); + strcpy(zcluster, "zephyr"); } while ((serv_list = hes_resolve(zcluster, "sloc")) == (char **)NULL) { syslog(LOG_ERR, "No servers or no hesiod"); /* wait a bit, and try again */ sleep(30); } - clust_info = (char **)malloc(2*sizeof(char *)); + clust_info = (char **) malloc(2 * sizeof(char *)); if (prim_serv[0]) clust_info[numserv++] = prim_serv; for (i = 0; serv_list[i]; i++) @@ -327,85 +315,68 @@ void choose_server() #endif if (!prim_serv[0] && numserv) { - srandom(time((long *) 0)); - (void) strcpy(prim_serv, serv_list[random() % numserv]); + srandom(time(NULL)); + strcpy(prim_serv, serv_list[random() % numserv]); } } -void init_hm() +static void init_hm() { struct servent *sp; Code_t ret; FILE *fp; -#ifdef POSIX +#ifdef _POSIX_VERSION struct sigaction sa; #endif starttime = time((time_t *)0); OPENLOG("hm", LOG_PID, LOG_DAEMON); + ZSetServerState(1); /* Aargh!!! */ if ((ret = ZInitialize()) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "initializing"); - closelog(); - exit(-1); + Zperr(ret); + com_err("hm", ret, "initializing"); + closelog(); + exit(-1); } - (void)ZSetServerState(1); /* Aargh!!! */ init_queue(); if (*prim_serv == '\0') - (void)strcpy(prim_serv, *serv_list); + strcpy(prim_serv, *serv_list); loopback[0] = 127; loopback[1] = 0; loopback[2] = 0; loopback[3] = 1; - /* kill old hm if it exists */ - fp = fopen(PidFile, "r"); - if (fp != NULL) { - (void)fscanf(fp, "%d\n", &oldpid); - while (!kill(oldpid, SIGTERM)) - sleep(1); - syslog(LOG_INFO, "Killed old image."); - (void) fclose(fp); - } - if (inetd) { - (void) ZSetFD(0); /* fd 0 is on the socket, - thanks to inetd */ + ZSetFD(0); /* fd 0 is on the socket, thanks to inetd */ } else { - /* Open client socket, for receiving client and server notices */ - if ((sp = getservbyname(HM_SVCNAME, "udp")) == NULL) { - printf("No %s entry in /etc/services.\n", HM_SVCNAME); - exit(1); - } - cli_port = sp->s_port; + /* Open client socket, for receiving client and server notices */ + sp = getservbyname(HM_SVCNAME, "udp"); + cli_port = (sp) ? sp->s_port : HM_SVC_FALLBACK; - if ((ret = ZOpenPort(&cli_port)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "opening port"); - exit(ret); - } + if ((ret = ZOpenPort(&cli_port)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "opening port"); + exit(ret); + } } cli_sin = ZGetDestAddr(); - - /* Open the server socket */ - - if ((sp = getservbyname(SERVER_SVCNAME, "udp")) == NULL) { - printf("No %s entry in /etc/services.\n", SERVER_SVCNAME); - exit(1); - } + sp = getservbyname(SERVER_SVCNAME, "udp"); + memset(&serv_sin, 0, sizeof(struct sockaddr_in)); + serv_sin.sin_port = (sp) ? sp->s_port : SERVER_SVC_FALLBACK; + #ifndef DEBUG if (!inetd && !nofork) - detach(); + detach(); /* Write pid to file */ fp = fopen(PidFile, "w"); if (fp != NULL) { - fprintf(fp, "%d\n", getpid()); - (void) fclose(fp); + fprintf(fp, "%d\n", getpid()); + fclose(fp); } #endif /* DEBUG */ @@ -413,9 +384,6 @@ void init_hm() syslog(LOG_INFO, "Debugging on."); } - (void) memset((char *)&serv_sin, 0, sizeof(struct sockaddr_in)); - serv_sin.sin_port = sp->s_port; - /* Set up communications with server */ /* target is SERVER_SVCNAME port on server machine */ @@ -424,31 +392,30 @@ void init_hm() /* who to talk to */ if ((hp = gethostbyname(prim_serv)) == NULL) { DPR("gethostbyname failed\n"); - find_next_server((char *)NULL); + find_next_server(NULL); } else { - DPR2 ("Server = %s\n", prim_serv); - (void)strcpy(cur_serv, prim_serv); - (void)memcpy((char *)&serv_sin.sin_addr, hp->h_addr, hp->h_length); + DPR2("Server = %s\n", prim_serv); + strcpy(cur_serv, prim_serv); + memcpy(&serv_sin.sin_addr, hp->h_addr, hp->h_length); } send_boot_notice(HM_BOOT); deactivated = 0; -#ifdef POSIX +#ifdef _POSIX_VERSION sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - sa.sa_handler = set_sig_type; + sa.sa_handler = deactivate; sigaction(SIGHUP, &sa, (struct sigaction *)0); - sigaction(SIGALRM, &sa, (struct sigaction *)0); + sa.sa_handler = terminate; sigaction(SIGTERM, &sa, (struct sigaction *)0); #else - (void)signal (SIGHUP, set_sig_type); - (void)signal (SIGALRM, set_sig_type); - (void)signal (SIGTERM, set_sig_type); + signal(SIGHUP, deactivate); + signal(SIGTERM, terminate); #endif } -void detach() +static void detach() { /* detach from terminal and fork. */ register int i, x = ZGetFD(); @@ -459,31 +426,36 @@ void detach() perror("fork"); exit(0); } -#ifdef POSIX +#ifdef _POSIX_VERSION size = sysconf(_SC_OPEN_MAX); #else size = getdtablesize(); #endif for (i = 0; i < size; i++) if (i != x) - (void) close(i); + close(i); - if ((i = open("/dev/tty", O_RDWR, 666)) < 0) + if ((i = open("/dev/tty", O_RDWR, 0666)) < 0) ; /* Can't open tty, but don't flame about it. */ else { #ifdef TIOCNOTTY - (void) ioctl(i, TIOCNOTTY, (caddr_t) 0); + /* Necessary for old non-POSIX systems which automatically assign + * an opened tty as the controlling terminal of a process which + * doesn't already have one. POSIX systems won't include + * (see ../h/sysdep.h); if TIOCNOTTY is defined anyway, + * this is unnecessary but won't hurt. */ + ioctl(i, TIOCNOTTY, (caddr_t) 0); #endif - (void) close(i); + close(i); } -#ifdef POSIX - (void) setsid(); +#ifdef _POSIX_VERSION + setsid(); #endif } static char version[BUFSIZ]; -send_stats(notice, sin) +static void send_stats(notice, sin) ZNotice_t *notice; struct sockaddr_in *sin; { @@ -492,7 +464,7 @@ send_stats(notice, sin) char *bfr; char *list[20]; int len, i, nitems = 10; - unsigned int size; + unsigned long size; newnotice = *notice; @@ -502,91 +474,75 @@ send_stats(notice, sin) } newnotice.z_kind = HMACK; - list[0] = (char *)malloc(MAXHOSTNAMELEN); - (void)strcpy(list[0], cur_serv); - list[1] = (char *)malloc(64); - (void)sprintf(list[1], "%d", queue_len()); - list[2] = (char *)malloc(64); - (void)sprintf(list[2], "%d", nclt); - list[3] = (char *)malloc(64); - (void)sprintf(list[3], "%d", nserv); - list[4] = (char *)malloc(64); - (void)sprintf(list[4], "%d", nservchang); - list[5] = (char *)malloc(64); - (void)strcpy(list[5], rcsid_hm_c); - list[6] = (char *)malloc(64); + list[0] = (char *) malloc(MAXHOSTNAMELEN); + strcpy(list[0], cur_serv); + list[1] = (char *) malloc(64); + sprintf(list[1], "%d", queue_len()); + list[2] = (char *) malloc(64); + sprintf(list[2], "%d", nclt); + list[3] = (char *) malloc(64); + sprintf(list[3], "%d", nserv); + list[4] = (char *) malloc(64); + sprintf(list[4], "%d", nservchang); + list[5] = (char *) malloc(64); + strcpy(list[5], rcsid_hm_c); + list[6] = (char *) malloc(64); if (no_server) - (void)sprintf(list[6], "yes"); + sprintf(list[6], "yes"); else - (void)sprintf(list[6], "no"); - list[7] = (char *)malloc(64); - (void)sprintf(list[7], "%ld", time((time_t *)0) - starttime); + sprintf(list[6], "no"); + list[7] = (char *) malloc(64); + sprintf(list[7], "%ld", time((time_t *)0) - starttime); #ifdef adjust_size - size = (unsigned int)sbrk(0); + size = (unsigned long)sbrk(0); adjust_size (size); #else size = -1; #endif list[8] = (char *)malloc(64); - (void)sprintf(list[8], "%ld", size); + sprintf(list[8], "%ld", size); list[9] = (char *)malloc(32); - (void)strcpy(list[9], MACHINE); + strcpy(list[9], MACHINE_TYPE); /* Since ZFormatRaw* won't change the version number on notices, we need to set the version number explicitly. This code is taken from Zinternal.c, function Z_FormatHeader */ if (!*version) - (void) sprintf(version, "%s%d.%d", ZVERSIONHDR, ZVERSIONMAJOR, - ZVERSIONMINOR); + sprintf(version, "%s%d.%d", ZVERSIONHDR, ZVERSIONMAJOR, + ZVERSIONMINOR); newnotice.z_version = version; if ((ret = ZFormatRawNoticeList(&newnotice, list, nitems, &bfr, &len)) != ZERR_NONE) { - syslog(LOG_INFO, "Couldn't format stats packet"); - } else - if ((ret = ZSendPacket(bfr, len, 0)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "sending stats"); - } + syslog(LOG_INFO, "Couldn't format stats packet"); + } else { + if ((ret = ZSendPacket(bfr, len, 0)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending stats"); + } + } free(bfr); for(i=0;i -#include -#include +#include #include -#include -#include -#ifdef lint -#include /* make lint shut up */ -#endif /* lint */ +#include +#include "timer.h" + +/* These macros are for insertion into and deletion from a singly-linked list + * with back pointers to the previous element's next pointer. In order to + * make these macros act like expressions, they use the comma operator for + * sequenced evaluations of assignment, and "a && b" for "evaluate assignment + * b if expression a is true". */ +#define LIST_INSERT(head, elem) \ + ((elem)->next = *(head), \ + (*head) && ((*(head))->prev_p = &(elem)->next), \ + (*head) = (elem), (elem)->prev_p = (head)) +#define LIST_DELETE(elem) \ + (*(elem)->prev_p = (elem)->next, \ + (elem)->next && ((elem)->next->prev_p = (elem)->prev_p)) #ifdef DEBUG #define DPR(a) fprintf(stderr, a); fflush(stderr) @@ -36,76 +45,58 @@ #define ever (;;) -#define SERV_TIMEOUT 20 +#define SERV_TIMEOUT 5 #define BOOTING 1 #define NOTICES 2 -extern Code_t send_outgoing(); -extern void init_queue(), retransmit_queue(); +/* main.c */ +void die_gracefully __P((void)); + +/* zhm_client.c */ +void transmission_tower __P((ZNotice_t *, char *, int)); +Code_t send_outgoing __P((ZNotice_t *)); + +/* queue.c */ +void init_queue __P((void)); +Code_t add_notice_to_queue __P((ZNotice_t *, char *, struct sockaddr_in *, + int)); +Code_t remove_notice_from_queue __P((ZNotice_t *, ZNotice_Kind_t *, + struct sockaddr_in *)); +void retransmit_queue __P((struct sockaddr_in *)); +void disable_queue_retransmits __P((void)); +int queue_len __P((void)); + +struct sockaddr_in serv_sin; extern int rexmit_times[]; #ifdef vax -#define MACHINE "vax" #define use_etext -#define ok #endif /* vax */ #ifdef ibm032 -#define MACHINE "rt" #define adjust_size(size) size -= 0x10000000 -#define ok #endif /* ibm032 */ -#ifdef NeXT -#define MACHINE "NeXT" -#define ok -#endif /* NeXT */ - -#ifdef sun -#ifdef SUN2_ARCH -#define MACHINE "sun2" -#define ok -#endif /* SUN2_ARCH */ - -#ifdef SUN3_ARCH -#define MACHINE "sun3" -#define ok -#endif /* SUN3_ARCH */ - -#if defined (SUN4_ARCH) || defined (sparc) -#define MACHINE "sun4" +#if defined(sun) && (defined (SUN4_ARCH) || defined (sparc)) #define use_etext -#define ok -#endif /* SUN4_ARCH */ - -#ifndef ok -#if defined (m68k) -#define MACHINE "sun (unknown 68k)" -#else -#define MACHINE "sun (unknown)" #endif -#define ok -#endif /* ! ok */ -#endif /* sun */ #ifdef _AIX #ifdef i386 -#define MACHINE "ps2" #define adjust_size(size) size -= 0x400000 #endif #ifdef _IBMR2 -#define MACHINE "IBM RISC/6000" #define adjust_size(size) size -= 0x20000000 #endif -#define ok #endif -#if defined(ultrix) && defined(mips) -#define MACHINE "decmips" +#if (defined(ultrix) || defined(sgi)) && defined(mips) #define adjust_size(size) size -= 0x10000000 -#define ok -#endif /* ultrix && mips */ +#endif /* (ultrix || sgi) && mips */ +#if defined(__alpha) +#define adjust_size(size) size -= 0x140000000 +#endif /* alpha */ #ifdef use_etext extern int etext; @@ -113,9 +104,4 @@ extern int etext; #undef use_etext #endif -#ifndef ok -#define MACHINE "unknown" -#endif -#undef ok - #endif diff --git a/zhm/zhm_client.c b/zhm/zhm_client.c index ec41466..ff7d3ea 100644 --- a/zhm/zhm_client.c +++ b/zhm/zhm_client.c @@ -19,89 +19,84 @@ static char rcsid_hm_client_c[] = "$Header$"; #endif /* SABER */ #endif /* lint */ -extern int no_server, timeout_type, nclt, deactivated; +extern int no_server, nclt, deactivated; extern struct sockaddr_in cli_sin, serv_sin, from; -transmission_tower(notice, packet, pak_len) +void transmission_tower(notice, packet, pak_len) ZNotice_t *notice; - caddr_t packet; + char *packet; int pak_len; { - ZNotice_t gack; - Code_t ret; - struct sockaddr_in gsin; - unsigned int tleft; + ZNotice_t gack; + Code_t ret; + struct sockaddr_in gsin; - nclt++; - if (notice->z_kind == HMCTL) { - if (!strcmp(notice->z_opcode, CLIENT_FLUSH)) { - send_flush_notice(HM_FLUSH); - deactivated = 1; - } - else if (!strcmp(notice->z_opcode, CLIENT_NEW_SERVER)) - new_server((char *)NULL); - else - syslog (LOG_INFO, "Bad control notice from client."); - return; - } else + nclt++; + if (notice->z_kind == HMCTL) { + if (!strcmp(notice->z_opcode, CLIENT_FLUSH)) { + send_flush_notice(HM_FLUSH); + deactivated = 1; + } else if (!strcmp(notice->z_opcode, CLIENT_NEW_SERVER)) { + new_server((char *)NULL); + } else { + syslog (LOG_INFO, "Bad control notice from client."); + } + return; + } else { if (notice->z_kind != UNSAFE) { - gack = *notice; - gack.z_kind = HMACK; - gack.z_message_len = 0; - gack.z_multinotice = ""; - gsin = cli_sin; - gsin.sin_port = from.sin_port; - if (gack.z_port == 0) + gack = *notice; + gack.z_kind = HMACK; + gack.z_message_len = 0; + gack.z_multinotice = ""; + gsin = cli_sin; + gsin.sin_port = from.sin_port; + if (gack.z_port == 0) gack.z_port = from.sin_port; - DPR2 ("Client Port = %u\n", ntohs(gack.z_port)); - notice->z_port = gack.z_port; - if ((ret = ZSetDestAddr(&gsin)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "setting destination"); - } - /* Bounce ACK to library */ - if ((ret = send_outgoing(&gack)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "sending raw notice"); - } - } - if (!no_server) { - DPR2 ("Server Port = %u\n", ntohs(serv_sin.sin_port)); - if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "setting destination"); + DPR2 ("Client Port = %u\n", ntohs(gack.z_port)); + notice->z_port = gack.z_port; + if ((ret = ZSetDestAddr(&gsin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); } - if ((ret = send_outgoing(notice)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "while sending raw notice"); + /* Bounce ACK to library */ + if ((ret = send_outgoing(&gack)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending raw notice"); } - if (tleft = alarm(0)) - (void)alarm(tleft); - else { - timeout_type = NOTICES; - (void)alarm(rexmit_times[0]); - } - } - (void)add_notice_to_queue(notice, packet, &gsin, pak_len); + } + } + if (!no_server) { + DPR2 ("Server Port = %u\n", ntohs(serv_sin.sin_port)); + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = send_outgoing(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "while sending raw notice"); + } + } + add_notice_to_queue(notice, packet, &gsin, pak_len); } Code_t send_outgoing(notice) ZNotice_t *notice; { - Code_t retval; - char *packet; - int length; + Code_t retval; + char *packet; + int length; - if (!(packet = (char *) malloc((unsigned)sizeof(ZPacket_t)))) - return(ENOMEM); + if (!(packet = (char *) malloc((unsigned)sizeof(ZPacket_t)))) + return(ENOMEM); - if ((retval = ZFormatSmallRawNotice(notice, packet, &length)) - != ZERR_NONE) { - free(packet); - return(retval); - } - retval = ZSendPacket(packet, length, 0); + if ((retval = ZFormatSmallRawNotice(notice, packet, &length)) + != ZERR_NONE) { free(packet); return(retval); + } + retval = ZSendPacket(packet, length, 0); + free(packet); + return(retval); } + diff --git a/zhm/zhm_server.c b/zhm/zhm_server.c index 8d95788..760d4c7 100644 --- a/zhm/zhm_server.c +++ b/zhm/zhm_server.c @@ -19,6 +19,10 @@ static char rcsid_hm_server_c[] = "$Header$"; #endif /* SABER */ #endif /* lint */ +static void boot_timeout __P((void *)); + +static Timer *boot_timer = NULL; + int serv_loop = 0; extern u_short cli_port; extern struct sockaddr_in serv_sin, from; @@ -59,8 +63,7 @@ char *op; Zperr(ret); com_err("hm", ret, "sending startup notice"); } - timeout_type = BOOTING; - (void)alarm(SERV_TIMEOUT); + boot_timer = timer_set_rel(SERV_TIMEOUT, boot_timeout, NULL); } /* Argument is whether we are detaching or really going down */ @@ -165,121 +168,130 @@ char *sugg_serv; server_manager(notice) ZNotice_t *notice; { - if (memcmp((char *)&serv_sin.sin_addr, (char *)&from.sin_addr, 4) || - (serv_sin.sin_port != from.sin_port)) { - syslog (LOG_INFO, "Bad notice from port %u.", notice->z_port); - } else { - /* This is our server, handle the notice */ - booting = 0; - DPR ("A notice came in from the server.\n"); - nserv++; - switch(notice->z_kind) { - case HMCTL: - hm_control(notice); - break; - case SERVNAK: - case SERVACK: - send_back(notice); - break; - default: - syslog (LOG_INFO, "Bad notice kind!?"); - break; - } - } + if (memcmp((char *)&serv_sin.sin_addr, (char *)&from.sin_addr, 4) || + (serv_sin.sin_port != from.sin_port)) { + syslog (LOG_INFO, "Bad notice from port %u.", notice->z_port); + } else { + /* This is our server, handle the notice */ + if (boot_timer) { + timer_reset(boot_timer); + boot_timer = NULL; + } + DPR ("A notice came in from the server.\n"); + nserv++; + switch(notice->z_kind) { + case HMCTL: + hm_control(notice); + break; + case SERVNAK: + case SERVACK: + send_back(notice); + break; + default: + syslog (LOG_INFO, "Bad notice kind!?"); + break; + } + } } hm_control(notice) ZNotice_t *notice; { - Code_t ret; - struct hostent *hp; - char suggested_server[64]; - unsigned long addr; + Code_t ret; + struct hostent *hp; + char suggested_server[64]; + unsigned long addr; - DPR("Control message!\n"); - if (!strcmp(notice->z_opcode, SERVER_SHUTDOWN)) { - if (notice->z_message_len) { - addr = inet_addr(notice->z_message); - if ((hp = gethostbyaddr((char *)&addr, sizeof(addr), - AF_INET)) != NULL) { - (void)strcpy(suggested_server, hp->h_name); - new_server(suggested_server); - } else - new_server((char *)NULL); - } - else - new_server((char *)NULL); - } else if (!strcmp(notice->z_opcode, SERVER_PING)) { - if (no_server) - (void)alarm(0); - notice->z_kind = HMACK; - if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "setting destination"); - } - if ((ret = send_outgoing(notice)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "sending ACK"); - } - if (no_server) { - no_server = 0; - retransmit_queue(&serv_sin); - } - } else - syslog (LOG_INFO, "Bad control message."); + DPR("Control message!\n"); + if (!strcmp(notice->z_opcode, SERVER_SHUTDOWN)) { + if (notice->z_message_len) { + addr = inet_addr(notice->z_message); + hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET); + if (hp != NULL) { + strcpy(suggested_server, hp->h_name); + new_server(suggested_server); + } else { + new_server(NULL); + } + } else { + new_server((char *)NULL); + } + } else if (!strcmp(notice->z_opcode, SERVER_PING)) { + notice->z_kind = HMACK; + if ((ret = ZSetDestAddr(&serv_sin)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = send_outgoing(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending ACK"); + } + if (no_server) { + no_server = 0; + retransmit_queue(&serv_sin); + } + } else { + syslog (LOG_INFO, "Bad control message."); + } } send_back(notice) ZNotice_t *notice; { - ZNotice_Kind_t kind; - struct sockaddr_in repl; - Code_t ret; + ZNotice_Kind_t kind; + struct sockaddr_in repl; + Code_t ret; - if (no_server) - (void)alarm(0); - if (!strcmp(notice->z_opcode, HM_BOOT) || - !strcmp(notice->z_opcode, HM_ATTACH)) { - /* ignore message, just an ack from boot, but exit if we - * are rebooting. - */ - if (rebootflag) - die_gracefully(); - } else { - if (remove_notice_from_queue(notice, &kind, - &repl) != ZERR_NONE) { - syslog (LOG_INFO, "Hey! This packet isn't in my queue!"); - } else { - /* check if client wants an ACK, and send it */ - if (kind == ACKED) { - DPR2 ("Client ACK port: %u\n", ntohs(repl.sin_port)); - if ((ret = ZSetDestAddr(&repl)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "setting destination"); - } - if ((ret = send_outgoing(notice)) != ZERR_NONE) { - Zperr(ret); - com_err("hm", ret, "sending ACK"); - } - } - } - } - if (no_server) { - no_server = 0; - retransmit_queue(&serv_sin); - } + if (!strcmp(notice->z_opcode, HM_BOOT) || + !strcmp(notice->z_opcode, HM_ATTACH)) { + /* ignore message, just an ack from boot, but exit if we + * are rebooting. + */ + if (rebootflag) + die_gracefully(); + } else { + if (remove_notice_from_queue(notice, &kind, &repl) != ZERR_NONE) { + syslog (LOG_INFO, "Hey! This packet isn't in my queue!"); + } else { + /* check if client wants an ACK, and send it */ + if (kind == ACKED) { + DPR2 ("Client ACK port: %u\n", ntohs(repl.sin_port)); + if ((ret = ZSetDestAddr(&repl)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "setting destination"); + } + if ((ret = send_outgoing(notice)) != ZERR_NONE) { + Zperr(ret); + com_err("hm", ret, "sending ACK"); + } + } + } + } + if (no_server) { + no_server = 0; + retransmit_queue(&serv_sin); + } } new_server(sugg_serv) char *sugg_serv; { - no_server = 1; - syslog (LOG_INFO, "Server went down, finding new server."); - send_flush_notice(HM_DETACH); - find_next_server(sugg_serv); - if (booting) { - send_boot_notice(HM_BOOT); - deactivated = 0; - } else - send_boot_notice(HM_ATTACH); + no_server = 1; + syslog (LOG_INFO, "Server went down, finding new server."); + send_flush_notice(HM_DETACH); + find_next_server(sugg_serv); + if (booting) { + send_boot_notice(HM_BOOT); + deactivated = 0; + } else { + send_boot_notice(HM_ATTACH); + } + disable_queue_retransmits(); } + +static void boot_timeout(arg) +void *arg; +{ + new_server(NULL); +} + -- cgit v1.2.3