blob: 0341c159167836661e2d3027279bc7e3a4a86dba [file] [log] [blame]
/*
* Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
* Modified by Olaf Kirch, 1996.
* Modified by H.J. Lu, 1998.
* Modified by Lon Hohberger, Oct. 2000.
* - Fixed memory leaks, run-off-end problems, etc.
*
* NSM for Linux.
*/
/*
* Simple list management for notify list
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include "statd.h"
#include "notlist.h"
#ifdef DEBUG
/*
* LH - The linked list code had some bugs. Used this to help debug
* new code.
*/
static void
plist(notify_list *head, int en)
{
/* case where we ran off the end */
if (!head) return;
printf("Entry %d: %s\n",en, NL_MON_NAME(head));
plist(head->next, ++en);
}
static void
nlist_print(notify_list **head)
{
printf("--- Begin notify list dump ---\n");
plist(*head,1);
printf("--- End notify list dump ---\n");
}
#endif /* DEBUG */
/*
* Allocate memory and set up a new notify list entry.
*/
notify_list *
nlist_new(char *my_name, char *mon_name, int state)
{
notify_list *new;
new = (notify_list *) xmalloc(sizeof(notify_list));
memset(new, 0, sizeof(*new));
NL_TIMES(new) = MAX_TRIES;
NL_STATE(new) = state;
NL_MY_NAME(new) = xstrdup(my_name);
NL_MON_NAME(new) = xstrdup(mon_name);
return new;
}
/*
* Insert *entry into a notify list at the point specified by
* **head. This can be in the middle. However, we do not handle
* list _append_ in this function; rather, the only place we should
* have to worry about this case is in nlist_insert_timer below.
* - entry must not be NULL.
*/
void
nlist_insert(notify_list **head, notify_list *entry)
{
if (*head) {
/*
* Cases where we're prepending a non-empty list
* or inserting possibly in the middle somewhere (eg,
* nlist_insert_timer...)
*/
entry->next = (*head); /* Forward pointer */
entry->prev = (*head)->prev; /* Back pointer */
(*head)->prev = entry; /* head's new back pointer */
}
/* Common to all cases, including new list creation */
*head = entry; /* New head */
#ifdef DEBUG
nlist_print(head);
#endif
}
/*
* (re)insert *entry into notify_list **head. This requires that
* NL_WHEN(entry) has been set (usually, this is time() + 5 seconds).
* - entry must not be NULL
*
* LH - This used to cause (a) a memory leak and (b) dropped notify-list
* entries. The pointer ran off the end of the list, and changed the
* head-end to point to the new, one-entry list. All other entries became garbage.
*
* FIXME: Optimize this function. (I'll work on it - LH)
*/
void
nlist_insert_timer(notify_list **head, notify_list *entry)
{
notify_list *spot = *head, /* Insertion location */
/* ...Start at head */
*back = NULL; /* Back pointer */
/* Find first entry with higher timeout value or end of list */
while (spot && NL_WHEN(spot) <= NL_WHEN(entry)) {
/*
* Keep the back pointer in case we
* run off the end... (see below)
*/
back = spot;
spot = spot->next;
}
if (spot == (*head)) {
/*
* case where we're prepending an empty or non-empty
* list or inserting in the middle somewhere. Pass
* the real head of the list, since we'll be changing
* during the insert...
*/
nlist_insert(head, entry);
} else {
/* all other cases - don't move the real head pointer */
nlist_insert(&spot, entry);
/*
* If spot == entry, then spot was NULL when we called
* nlist_insert. This happened because we had run off
* the end of the list. Append entry to original list.
*/
if (spot == entry) {
back->next = entry;
entry->prev = back;
}
}
}
/*
* Remove *entry from the list pointed to by **head.
* Do not destroy *entry. This is normally done before
* a re-insertion with a timer, but can be done anywhere.
* - entry must not be NULL.
*/
void
nlist_remove(notify_list **head, notify_list *entry)
{
notify_list *prev = entry->prev,
*next = entry->next;
if (next) {
next->prev = prev;
}
if (prev) {
/* Case(s) where entry isn't at the front */
prev->next = next;
} else {
/* cases where entry is at the front */
*head = next;
}
entry->next = entry->prev = NULL;
#ifdef DEBUG
nlist_print(head);
#endif
}
/*
* Clone an entry in the notify list -
* - entry must not be NULL
*/
notify_list *
nlist_clone(notify_list *entry)
{
notify_list *new;
new = nlist_new(NL_MY_NAME(entry), NL_MON_NAME(entry), NL_STATE(entry));
NL_MY_PROG(new) = NL_MY_PROG(entry);
NL_MY_VERS(new) = NL_MY_VERS(entry);
NL_MY_PROC(new) = NL_MY_PROC(entry);
memcpy(NL_PRIV(new), NL_PRIV(entry), SM_PRIV_SIZE);
return new;
}
/*
* Destroy an entry in a notify list and free the memory.
* If *head is NULL, just free the entry. This would be
* done only when we know entry isn't in any list.
* - entry must not be NULL.
*/
void
nlist_free(notify_list **head, notify_list *entry)
{
if (head && (*head))
nlist_remove(head, entry);
if (NL_MY_NAME(entry))
free(NL_MY_NAME(entry));
if (NL_MON_NAME(entry))
free(NL_MON_NAME(entry));
free(entry->dns_name);
free(entry);
}
/*
* Destroy an entire notify list
*/
void
nlist_kill(notify_list **head)
{
while (*head)
nlist_free(head, *head);
}
/*
* Walk a list looking for a matching name in the NL_MON_NAME field.
*/
notify_list *
nlist_gethost(notify_list *list, char *host, int myname)
{
notify_list *lp;
for (lp = list; lp; lp = lp->next) {
if (statd_matchhostname(host,
myname? NL_MY_NAME(lp) : NL_MON_NAME(lp)))
return lp;
}
return (notify_list *) NULL;
}