1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
|
/*
* 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 "misc.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);
NL_ADDR(new) = NL_ADDR(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);
}
/*
* 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 (matchhostname(host, myname? NL_MY_NAME(lp) : NL_MON_NAME(lp)))
return lp;
}
return (notify_list *) NULL;
}
|