xref: /illumos-gate/usr/src/cmd/cron/elm.c (revision 032624d5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate 
23*032624d5Sbasabi /*
24*032624d5Sbasabi  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25*032624d5Sbasabi  * Use is subject to license terms.
26*032624d5Sbasabi  */
27*032624d5Sbasabi 
287c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
297c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate 
33*032624d5Sbasabi #pragma ident	"%Z%%M%	%I%	%E% SMI"
347c478bd9Sstevel@tonic-gate /**************************************************************************
357c478bd9Sstevel@tonic-gate  ***		General-Purpose Event List Manager			***
367c478bd9Sstevel@tonic-gate  **************************************************************************
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate 	description:	These routines maintain a time-ordered list of events.
397c478bd9Sstevel@tonic-gate 	functions available:
407c478bd9Sstevel@tonic-gate 		init :	Creates and initializes the data structure.
417c478bd9Sstevel@tonic-gate 			See the reference for parameters to init.
427c478bd9Sstevel@tonic-gate 		add(&event,time,id) :	Adds an event to the list.
437c478bd9Sstevel@tonic-gate 		remove(id) :	Removes events (with appropriate id).
447c478bd9Sstevel@tonic-gate 		empty : Returns true if the list is empty, false otherwise.
457c478bd9Sstevel@tonic-gate 		first :	Removes the element at the head of the list.
467c478bd9Sstevel@tonic-gate 			Returns a pointer to the event.
477c478bd9Sstevel@tonic-gate 		delete : Frees up all allocated storage associated
487c478bd9Sstevel@tonic-gate 			 with the event list.
497c478bd9Sstevel@tonic-gate 	reference:	Franta, W. R. and Maly, K.,
507c478bd9Sstevel@tonic-gate 			"An efficient data structure for the
517c478bd9Sstevel@tonic-gate 			simulation event set ", CACM Vol. 20(8),
527c478bd9Sstevel@tonic-gate 			Aug 1977, pp. 596-602.
537c478bd9Sstevel@tonic-gate 	machine dependant:	the constant INFINITY
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate  *************************************************************************/
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate #include <sys/types.h>
597c478bd9Sstevel@tonic-gate #include <stdlib.h>
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate extern	void *xmalloc(size_t);
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #define	INFINITY	2147483647L	/* upper bound on time	*/
647c478bd9Sstevel@tonic-gate #define NULL		0		/* a null pointer 	*/
657c478bd9Sstevel@tonic-gate #define TRUE		1
667c478bd9Sstevel@tonic-gate #define FALSE		0
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /* the following parameters are set in init	*/
697c478bd9Sstevel@tonic-gate static int	DU;		/* number of time intervals	*/
707c478bd9Sstevel@tonic-gate static time_t	LB;		/* lower bound on time	*/
717c478bd9Sstevel@tonic-gate static time_t	DT;		/* width of interval	*/
727c478bd9Sstevel@tonic-gate static int	NLIM;		/* max notices per sublist	*/
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /* a notice points to an event.  a notice has the following fields:
757c478bd9Sstevel@tonic-gate 	time = time of the event.
767c478bd9Sstevel@tonic-gate 	id = identifier for an event or class of events that may need
777c478bd9Sstevel@tonic-gate 		to be removed (other than at the front of the list).
787c478bd9Sstevel@tonic-gate 	event = pointer to the event.
797c478bd9Sstevel@tonic-gate 	isdummy = tells whether this notice points to a real event or
807c478bd9Sstevel@tonic-gate 		is just a dummy notice (one that is used to "mark off"
817c478bd9Sstevel@tonic-gate 		the time intervals that the user specifies in init).
827c478bd9Sstevel@tonic-gate 	key = points back to the key that points to this notice,
837c478bd9Sstevel@tonic-gate 		if there is one.
847c478bd9Sstevel@tonic-gate 	left = points to the notice immediately preceding this one.
857c478bd9Sstevel@tonic-gate 	right = points to the notice immediately following this one.  */
867c478bd9Sstevel@tonic-gate struct notice {	time_t	time;
877c478bd9Sstevel@tonic-gate 		int	id;
887c478bd9Sstevel@tonic-gate 		void	*event;
897c478bd9Sstevel@tonic-gate 		short int	isdummy;
907c478bd9Sstevel@tonic-gate 		struct key	*key;
917c478bd9Sstevel@tonic-gate 		struct notice	*left;
927c478bd9Sstevel@tonic-gate 		struct notice	*right; };
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /* current points to the front of the list of notices (events)	*/
957c478bd9Sstevel@tonic-gate struct notice	*current=NULL;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /* a key points to a sublist of notices.  a key has the following fields:
987c478bd9Sstevel@tonic-gate 	time = max time of notices in sublist.
997c478bd9Sstevel@tonic-gate 	numnote = number of notices in sublist.
1007c478bd9Sstevel@tonic-gate 	notice = pointer to the notice with max time.
1017c478bd9Sstevel@tonic-gate 	left = points to the key immediately preceding this one.
1027c478bd9Sstevel@tonic-gate 	right = points to the key immediately following this one.     */
1037c478bd9Sstevel@tonic-gate struct key {	time_t	time;
1047c478bd9Sstevel@tonic-gate 		int	numnote;
1057c478bd9Sstevel@tonic-gate 		struct notice	*notice;
1067c478bd9Sstevel@tonic-gate 		struct key	*left;
1077c478bd9Sstevel@tonic-gate 		struct key	*right; };
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /* the index list breaks the keys into time intervals as specified in init.
1107c478bd9Sstevel@tonic-gate    the index is "shifted" one time interval whenever el_first returns an
1117c478bd9Sstevel@tonic-gate 	event with a time greater than the max time of the first interval
1127c478bd9Sstevel@tonic-gate 	(eg. with intervals of a day which span one week (MTWTFSS),
1137c478bd9Sstevel@tonic-gate 		if el_first finds the next event is on tuesday, then
1147c478bd9Sstevel@tonic-gate 		the intervals of the event list get shifted (TWTFSSM).	      */
1157c478bd9Sstevel@tonic-gate struct index {	struct key *key;
1167c478bd9Sstevel@tonic-gate 		struct index *right; };
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate static struct index *index=NULL; /* index pts to the front of the index list */
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate /***********************/
1217c478bd9Sstevel@tonic-gate void
1227c478bd9Sstevel@tonic-gate el_init(du,lb,dt,nlim)
1237c478bd9Sstevel@tonic-gate /***********************/
1247c478bd9Sstevel@tonic-gate int du, nlim;
1257c478bd9Sstevel@tonic-gate time_t lb, dt;
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate 	int	i;
1287c478bd9Sstevel@tonic-gate 	time_t	t;
1297c478bd9Sstevel@tonic-gate 	struct index *indprev,*ind;
1307c478bd9Sstevel@tonic-gate 	struct key *kprev, *k;
1317c478bd9Sstevel@tonic-gate 	struct notice *nprev, *n;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	if ((du<1) || (dt<1) || (nlim<1)) return;
1347c478bd9Sstevel@tonic-gate 	DU = du + 1;
1357c478bd9Sstevel@tonic-gate 	LB = lb;
1367c478bd9Sstevel@tonic-gate 	DT = dt;
1377c478bd9Sstevel@tonic-gate 	NLIM = nlim;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	/*
1407c478bd9Sstevel@tonic-gate 	 * initialize index, keys, and notices
1417c478bd9Sstevel@tonic-gate 	 */
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* create first dummy notice */
1447c478bd9Sstevel@tonic-gate 	n= (struct notice *) xmalloc(sizeof(struct notice));
1457c478bd9Sstevel@tonic-gate 	n->time = LB;
1467c478bd9Sstevel@tonic-gate 	n->isdummy = TRUE;
1477c478bd9Sstevel@tonic-gate 	n->left = NULL;
1487c478bd9Sstevel@tonic-gate 	nprev = n;
1497c478bd9Sstevel@tonic-gate 	/* create first dummy key */
1507c478bd9Sstevel@tonic-gate 	k= (struct key *) xmalloc(sizeof(struct key));
1517c478bd9Sstevel@tonic-gate 	k->time = LB;
1527c478bd9Sstevel@tonic-gate 	k->numnote = 1;
1537c478bd9Sstevel@tonic-gate 	k->notice = n;
1547c478bd9Sstevel@tonic-gate 	k->left = NULL;
1557c478bd9Sstevel@tonic-gate 	kprev = k;
1567c478bd9Sstevel@tonic-gate 	/* make notice point to key */
1577c478bd9Sstevel@tonic-gate 	n->key = k;
1587c478bd9Sstevel@tonic-gate 	/* no index element to allocate this time */
1597c478bd9Sstevel@tonic-gate 	indprev = NULL;
1607c478bd9Sstevel@tonic-gate 	/* create dummy notices, dummy keys, and index elements */
1617c478bd9Sstevel@tonic-gate 	t = LB;
1627c478bd9Sstevel@tonic-gate 	for (i=1; i<DU; i++) {
1637c478bd9Sstevel@tonic-gate 		t = t + DT;
1647c478bd9Sstevel@tonic-gate 		n = (struct notice *) xmalloc(sizeof(struct notice));
1657c478bd9Sstevel@tonic-gate 		n->time = t;
1667c478bd9Sstevel@tonic-gate 		n->isdummy = TRUE;
1677c478bd9Sstevel@tonic-gate 		n->left = nprev;
1687c478bd9Sstevel@tonic-gate 		nprev->right = n;
1697c478bd9Sstevel@tonic-gate 		nprev = n;
1707c478bd9Sstevel@tonic-gate 		k = (struct key *) xmalloc(sizeof(struct key));
1717c478bd9Sstevel@tonic-gate 		k->time = t;
1727c478bd9Sstevel@tonic-gate 		k->numnote = 1;
1737c478bd9Sstevel@tonic-gate 		k->notice = n;
1747c478bd9Sstevel@tonic-gate 		k->left = kprev;
1757c478bd9Sstevel@tonic-gate 		kprev->right = k;
1767c478bd9Sstevel@tonic-gate 		kprev = k;
1777c478bd9Sstevel@tonic-gate 		n->key = k;
1787c478bd9Sstevel@tonic-gate 		ind = (struct index *) xmalloc(sizeof(struct index));
1797c478bd9Sstevel@tonic-gate 		ind->key = k;
1807c478bd9Sstevel@tonic-gate 		if (indprev == NULL)  index = ind;
1817c478bd9Sstevel@tonic-gate 		 else indprev->right = ind;
1827c478bd9Sstevel@tonic-gate 		indprev = ind; }
1837c478bd9Sstevel@tonic-gate 	/* create last dummy notice */
1847c478bd9Sstevel@tonic-gate 	n = (struct notice *) xmalloc(sizeof(struct notice));
1857c478bd9Sstevel@tonic-gate 	n->time = INFINITY;
1867c478bd9Sstevel@tonic-gate 	n->isdummy = TRUE;
1877c478bd9Sstevel@tonic-gate 	n->left = nprev;
1887c478bd9Sstevel@tonic-gate 	n->right = NULL;
1897c478bd9Sstevel@tonic-gate 	nprev->right = n;
1907c478bd9Sstevel@tonic-gate 	/* create last dummy key */
1917c478bd9Sstevel@tonic-gate 	k = (struct key *) xmalloc(sizeof(struct key));
1927c478bd9Sstevel@tonic-gate 	k->time = INFINITY;
1937c478bd9Sstevel@tonic-gate 	k->numnote = 1;
1947c478bd9Sstevel@tonic-gate 	k->notice = n;
1957c478bd9Sstevel@tonic-gate 	k->left = kprev;
1967c478bd9Sstevel@tonic-gate 	k->right = NULL;
1977c478bd9Sstevel@tonic-gate 	kprev->right = k;
1987c478bd9Sstevel@tonic-gate 	n->key = k;
1997c478bd9Sstevel@tonic-gate 	/* create last index element */
2007c478bd9Sstevel@tonic-gate 	ind = (struct index *) xmalloc(sizeof(struct index));
2017c478bd9Sstevel@tonic-gate 	ind->key = k;
2027c478bd9Sstevel@tonic-gate 	ind->right = NULL;
2037c478bd9Sstevel@tonic-gate 	indprev->right = ind;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	current = NULL;
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /**************************/
2107c478bd9Sstevel@tonic-gate void
2117c478bd9Sstevel@tonic-gate el_add(event,time,id)
2127c478bd9Sstevel@tonic-gate /**************************/
2137c478bd9Sstevel@tonic-gate void	*event;
2147c478bd9Sstevel@tonic-gate int	id;
2157c478bd9Sstevel@tonic-gate time_t	time;
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate /* add works slightly differently than in the reference.  if the
2187c478bd9Sstevel@tonic-gate 	sublist to be inserted into is full (numnote = NLIM),
2197c478bd9Sstevel@tonic-gate 	the sublist is split in half.  thus the size of the sublists
2207c478bd9Sstevel@tonic-gate 	in this implementation normally ranges from NLIM/2 to NLIM.   */
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	struct index *ind;
2237c478bd9Sstevel@tonic-gate 	struct key *k,*k2;
2247c478bd9Sstevel@tonic-gate 	struct notice *n,*n2;
2257c478bd9Sstevel@tonic-gate 	int i;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	if ((index==NULL) || (time<LB)) return;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	/* allocate new notice */
2307c478bd9Sstevel@tonic-gate 	n = (struct notice *) xmalloc(sizeof(struct notice));
2317c478bd9Sstevel@tonic-gate 	n->time = time;
2327c478bd9Sstevel@tonic-gate 	n->id = id;
2337c478bd9Sstevel@tonic-gate 	n->event = event;
2347c478bd9Sstevel@tonic-gate 	n->isdummy = FALSE;
2357c478bd9Sstevel@tonic-gate 	n->key = NULL;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	/* find the right interval */
2387c478bd9Sstevel@tonic-gate 	ind = index;
2397c478bd9Sstevel@tonic-gate 	while ((ind->key)->time <= time) ind = ind->right;
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	/* find the right key */
2427c478bd9Sstevel@tonic-gate 	k = (ind->key)->left;
2437c478bd9Sstevel@tonic-gate 	while (k->time > time) k = k->left;
2447c478bd9Sstevel@tonic-gate 	k = k->right;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	/* (k->time>time) and ((k->left)->time<=time) */
2477c478bd9Sstevel@tonic-gate 	if (k->numnote == NLIM) {
2487c478bd9Sstevel@tonic-gate 		/* k's sublist is full, so split it */
2497c478bd9Sstevel@tonic-gate 		k->numnote = NLIM / 2;
2507c478bd9Sstevel@tonic-gate 		n2 = k->notice;
2517c478bd9Sstevel@tonic-gate 		for (i=1; i<=NLIM/2; i++) n2 = n2->left;
2527c478bd9Sstevel@tonic-gate 		/* create a key which will point to notice n2 */
2537c478bd9Sstevel@tonic-gate 		k2 = (struct key *) xmalloc(sizeof(struct key));
2547c478bd9Sstevel@tonic-gate 		k2->time = n2->time;
2557c478bd9Sstevel@tonic-gate 		k2->numnote = NLIM - NLIM/2;
2567c478bd9Sstevel@tonic-gate 		k2->notice = n2;
2577c478bd9Sstevel@tonic-gate 		k2->right = k;
2587c478bd9Sstevel@tonic-gate 		k2->left = k->left;
2597c478bd9Sstevel@tonic-gate 		k->left = k2;
2607c478bd9Sstevel@tonic-gate 		(k2->left)->right = k2;
2617c478bd9Sstevel@tonic-gate 		n2->key = k2;	/* have n2 point back to k2 */
2627c478bd9Sstevel@tonic-gate 		/* which of the new sublists will hold the new notice? */
2637c478bd9Sstevel@tonic-gate 		if (k2->time > time) k = k2; }
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	/* the new notice n is ready to be inserted
2667c478bd9Sstevel@tonic-gate 		k points to the appropriate sublist	*/
2677c478bd9Sstevel@tonic-gate 	k->numnote = k->numnote + 1;
2687c478bd9Sstevel@tonic-gate 	n2 = k->notice;
2697c478bd9Sstevel@tonic-gate 	while (n2->time > time) n2 = n2->left;
2707c478bd9Sstevel@tonic-gate 	n->right = n2->right;
2717c478bd9Sstevel@tonic-gate 	n->left = n2;
2727c478bd9Sstevel@tonic-gate 	(n2->right)->left = n;
2737c478bd9Sstevel@tonic-gate 	n2->right = n;
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate 	if ( (current == NULL) || (current->time > time) ) current = n;
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate /************************/
2807c478bd9Sstevel@tonic-gate void
2817c478bd9Sstevel@tonic-gate el_remove(id,flag)
2827c478bd9Sstevel@tonic-gate /************************/
2837c478bd9Sstevel@tonic-gate int	id,flag;
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate /* remove finds notices n that need to be removed by traversing thru
2867c478bd9Sstevel@tonic-gate 	the notice list.  if n is the sole element of a sublist, the
2877c478bd9Sstevel@tonic-gate 	sublist is deleted.  if not, an adjacent sublist is merged with
2887c478bd9Sstevel@tonic-gate 	n's sublist, if that is possible.  after these checks, n is removed. */
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	struct notice *n,*n2;
2917c478bd9Sstevel@tonic-gate 	struct key *k,*kl,*kr;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	if ((index==NULL) || (current==NULL)) return;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	n = current;
2967c478bd9Sstevel@tonic-gate 	while ( n != NULL) {
2977c478bd9Sstevel@tonic-gate 		while ( (n!=NULL) && ((n->isdummy)||(n->id!=id)) ) n = n->right;
2987c478bd9Sstevel@tonic-gate 		if (n != NULL) {
2997c478bd9Sstevel@tonic-gate 			/* n should be deleted */
3007c478bd9Sstevel@tonic-gate 			if ( (n->key!=NULL) && ((n->key)->numnote==1) ) {
3017c478bd9Sstevel@tonic-gate 				/* n = sole element of a sublist */
3027c478bd9Sstevel@tonic-gate 				k = n->key;
3037c478bd9Sstevel@tonic-gate 				(k->left)->right = k->right;
3047c478bd9Sstevel@tonic-gate 				(k->right)->left = k->left;
3057c478bd9Sstevel@tonic-gate 				free(k); }
3067c478bd9Sstevel@tonic-gate 			 else { if (n->key != NULL) {
3077c478bd9Sstevel@tonic-gate 					/* n has a key pointing to it */
3087c478bd9Sstevel@tonic-gate 					(n->left)->key = n->key;
3097c478bd9Sstevel@tonic-gate 					(n->key)->time = (n->left)->time;
3107c478bd9Sstevel@tonic-gate 					(n->key)->notice = n->left; }
3117c478bd9Sstevel@tonic-gate 				/* find the key that points to this sublist */
3127c478bd9Sstevel@tonic-gate 				n2 = n;
3137c478bd9Sstevel@tonic-gate 				while (n2->key == NULL) n2 = n2->right;
3147c478bd9Sstevel@tonic-gate 				k = n2->key;
3157c478bd9Sstevel@tonic-gate 				k->numnote = k->numnote - 1;
3167c478bd9Sstevel@tonic-gate 				/* check if two adjacent sublists can be merged
3177c478bd9Sstevel@tonic-gate 				   first check left, then check right  */
3187c478bd9Sstevel@tonic-gate 				kl = k->left;
3197c478bd9Sstevel@tonic-gate 				kr = k->right;
3207c478bd9Sstevel@tonic-gate 				if ( (!(kl->notice)->isdummy) &&
3217c478bd9Sstevel@tonic-gate 			     	     ((kl->numnote+k->numnote)<=NLIM) ) {
3227c478bd9Sstevel@tonic-gate 					/* delete the key to the left */
3237c478bd9Sstevel@tonic-gate 					(kl->notice)->key = NULL;
3247c478bd9Sstevel@tonic-gate 					k->numnote += kl->numnote;
3257c478bd9Sstevel@tonic-gate 					(kl->left)->right = k;
3267c478bd9Sstevel@tonic-gate 					k->left = kl->left;
3277c478bd9Sstevel@tonic-gate 					free(kl); }
3287c478bd9Sstevel@tonic-gate 				 else if ( (!(k->notice)->isdummy) &&
3297c478bd9Sstevel@tonic-gate 				           ((kr->numnote+k->numnote)<=NLIM) ) {
3307c478bd9Sstevel@tonic-gate 					/* delete this key */
3317c478bd9Sstevel@tonic-gate 					(k->notice)->key = NULL;
3327c478bd9Sstevel@tonic-gate 					kr->numnote += k->numnote;
3337c478bd9Sstevel@tonic-gate 					(k->left)->right = kr;
3347c478bd9Sstevel@tonic-gate 					kr->left = k->left;
3357c478bd9Sstevel@tonic-gate 					free(k); }
3367c478bd9Sstevel@tonic-gate 				}
3377c478bd9Sstevel@tonic-gate 			/* delete n, then advance n down the list */
3387c478bd9Sstevel@tonic-gate 			(n->left)->right = n->right;
3397c478bd9Sstevel@tonic-gate 			(n->right)->left = n->left;
3407c478bd9Sstevel@tonic-gate 			n2 = n->right;
3417c478bd9Sstevel@tonic-gate 			free(n);
3427c478bd9Sstevel@tonic-gate 			n = n2;
3437c478bd9Sstevel@tonic-gate 			}
3447c478bd9Sstevel@tonic-gate 		if (flag) break;
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 	/* now reset current */
3477c478bd9Sstevel@tonic-gate 	k = (index->key)->left;
3487c478bd9Sstevel@tonic-gate 	while (k->left != NULL) k = k->left;
3497c478bd9Sstevel@tonic-gate 	n = (k->notice)->right;
3507c478bd9Sstevel@tonic-gate 	while ((n!=NULL) && (n->isdummy)) n = n->right;
3517c478bd9Sstevel@tonic-gate 	current = n;
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate /*************************/
356*032624d5Sbasabi int
357*032624d5Sbasabi el_empty(void)
3587c478bd9Sstevel@tonic-gate /*************************/
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate 	if (current == NULL) return(1);
3617c478bd9Sstevel@tonic-gate 		else return(0);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate /*************************/
3667c478bd9Sstevel@tonic-gate void *
367*032624d5Sbasabi el_first(void)
3687c478bd9Sstevel@tonic-gate /*************************/
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate 	struct notice *n,*fn;
3717c478bd9Sstevel@tonic-gate 	struct key *k,*fk;
3727c478bd9Sstevel@tonic-gate 	struct index *ind,*fi;
3737c478bd9Sstevel@tonic-gate 	int ctr,*val;
3747c478bd9Sstevel@tonic-gate 	time_t next_int;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	if ((index==NULL) || (current==NULL)) return(NULL);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	while ((index->key)->time < current->time) {
3797c478bd9Sstevel@tonic-gate 		if (DU == 2) {
3807c478bd9Sstevel@tonic-gate 			/* only two intervals, so relabel first one */
3817c478bd9Sstevel@tonic-gate 			k = index->key;
3827c478bd9Sstevel@tonic-gate 			k->time += DT;
3837c478bd9Sstevel@tonic-gate 			(k->notice)->time += DT;
3847c478bd9Sstevel@tonic-gate 			continue; }
3857c478bd9Sstevel@tonic-gate 		/* remove the notice, key, and index corresponding
3867c478bd9Sstevel@tonic-gate 		   to the first time interval.  Then split the
3877c478bd9Sstevel@tonic-gate 		   overflow interval into a normal interval
3887c478bd9Sstevel@tonic-gate 		   plus an overflow interval. */
3897c478bd9Sstevel@tonic-gate 		fi = index;
3907c478bd9Sstevel@tonic-gate 		fk = fi->key;
3917c478bd9Sstevel@tonic-gate 		fn = fk->notice;
3927c478bd9Sstevel@tonic-gate 		(fn->left)->right = fn->right;
3937c478bd9Sstevel@tonic-gate 		(fn->right)->left = fn->left;
3947c478bd9Sstevel@tonic-gate 		(fk->left)->right = fk->right;
3957c478bd9Sstevel@tonic-gate 		(fk->right)->left = fk->left;
3967c478bd9Sstevel@tonic-gate 		index = index->right;
3977c478bd9Sstevel@tonic-gate 		/* find where to split	*/
3987c478bd9Sstevel@tonic-gate 		ind = index;
3997c478bd9Sstevel@tonic-gate 		while ((ind->right)->right != NULL) ind = ind->right;
4007c478bd9Sstevel@tonic-gate 		/* ind points to the next to last index interval	*/
4017c478bd9Sstevel@tonic-gate 		k = ind->key;
4027c478bd9Sstevel@tonic-gate 		next_int = k->time + DT;	/* upper bound on new inter.  */
4037c478bd9Sstevel@tonic-gate 		while (k->time < next_int) k = k->right;
4047c478bd9Sstevel@tonic-gate 		/* k points to the appropriate sublist of notices	*/
4057c478bd9Sstevel@tonic-gate 		n = (k->notice)->left;
4067c478bd9Sstevel@tonic-gate 		ctr = 1;
4077c478bd9Sstevel@tonic-gate 		while (n->time >= next_int) {
4087c478bd9Sstevel@tonic-gate 			ctr++;
4097c478bd9Sstevel@tonic-gate 			n = n->left; }
4107c478bd9Sstevel@tonic-gate 		n = n->right;
4117c478bd9Sstevel@tonic-gate 		/* n points to first notice of the new overflow interval
4127c478bd9Sstevel@tonic-gate 		   ctr tells how many notices are in the first sublist
4137c478bd9Sstevel@tonic-gate 			of the new overflow interval
4147c478bd9Sstevel@tonic-gate 		   insert the new index element	*/
4157c478bd9Sstevel@tonic-gate 		fi->right = ind->right;
4167c478bd9Sstevel@tonic-gate 		ind->right = fi;
4177c478bd9Sstevel@tonic-gate 		/* insert the new dummy key	*/
4187c478bd9Sstevel@tonic-gate 		fk->time = next_int;
4197c478bd9Sstevel@tonic-gate 		fk->numnote = k->numnote - ctr + 1;
4207c478bd9Sstevel@tonic-gate 		fk->left = k->left;
4217c478bd9Sstevel@tonic-gate 		fk->right = k;
4227c478bd9Sstevel@tonic-gate 		(k->left)->right = fk;
4237c478bd9Sstevel@tonic-gate 		k->left = fk;
4247c478bd9Sstevel@tonic-gate 		k->numnote = ctr;
4257c478bd9Sstevel@tonic-gate 		/* insert the new dummy notice	*/
4267c478bd9Sstevel@tonic-gate 		fn->time = next_int;
4277c478bd9Sstevel@tonic-gate 		fn->left = n->left;
4287c478bd9Sstevel@tonic-gate 		fn->right = n;
4297c478bd9Sstevel@tonic-gate 		(n->left)->right = fn;
4307c478bd9Sstevel@tonic-gate 		n->left = fn; }
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/* remove the first element of the list */
4337c478bd9Sstevel@tonic-gate 	(current->left)->right = current->right;
4347c478bd9Sstevel@tonic-gate 	(current->right)->left = current->left;
4357c478bd9Sstevel@tonic-gate 	/* now update the numnote field in the appropriate key */
4367c478bd9Sstevel@tonic-gate 	n = current;
4377c478bd9Sstevel@tonic-gate 	while ( n->key == NULL ) n = n->right;
4387c478bd9Sstevel@tonic-gate 	k = n->key;
4397c478bd9Sstevel@tonic-gate 	k->numnote = k->numnote - 1;
4407c478bd9Sstevel@tonic-gate 	/* if numnote = 0 then this key must be removed */
4417c478bd9Sstevel@tonic-gate 	if (k->numnote == 0) {
4427c478bd9Sstevel@tonic-gate 		(k->left)->right = k->right;
4437c478bd9Sstevel@tonic-gate 		(k->right)->left = k->left;
4447c478bd9Sstevel@tonic-gate 		free(k); }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	/* now set current to be the head of the list */
4477c478bd9Sstevel@tonic-gate 	fn = current->right;
4487c478bd9Sstevel@tonic-gate 	while ( (fn != NULL) && (fn->isdummy) )
4497c478bd9Sstevel@tonic-gate 		fn = fn->right;
4507c478bd9Sstevel@tonic-gate 	val = current->event;
4517c478bd9Sstevel@tonic-gate 	free(current);
4527c478bd9Sstevel@tonic-gate 	current = fn;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 	return(val);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate /******************/
4597c478bd9Sstevel@tonic-gate void
460*032624d5Sbasabi el_delete(void)
4617c478bd9Sstevel@tonic-gate /******************/
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate 	/* el_delete frees up all the space associated with the event list */
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	struct index *ind,*ind2;
4667c478bd9Sstevel@tonic-gate 	struct key *k,*k2;
4677c478bd9Sstevel@tonic-gate 	struct notice *n,*n2;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	if (index==NULL) return;
4707c478bd9Sstevel@tonic-gate 	ind = index;
4717c478bd9Sstevel@tonic-gate 	k = ind->key;
4727c478bd9Sstevel@tonic-gate 	while (k->left != NULL) k = k->left;
4737c478bd9Sstevel@tonic-gate 	n = k->notice;
4747c478bd9Sstevel@tonic-gate 	while (n!=NULL) {
4757c478bd9Sstevel@tonic-gate 		n2 = n->right;
4767c478bd9Sstevel@tonic-gate 		free(n);
4777c478bd9Sstevel@tonic-gate 		n = n2; }
4787c478bd9Sstevel@tonic-gate 	while (k!=NULL) {
4797c478bd9Sstevel@tonic-gate 		k2 = k->right;
4807c478bd9Sstevel@tonic-gate 		free(k);
4817c478bd9Sstevel@tonic-gate 		k = k2; }
4827c478bd9Sstevel@tonic-gate 	while (ind!=NULL) {
4837c478bd9Sstevel@tonic-gate 		ind2 = ind->right;
4847c478bd9Sstevel@tonic-gate 		free(ind);
4857c478bd9Sstevel@tonic-gate 		ind = ind2; }
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	index = NULL;
4887c478bd9Sstevel@tonic-gate 	current = NULL;
4897c478bd9Sstevel@tonic-gate }
490