]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/statd/notlist.c
Autogen update
[nfs-utils.git] / utils / statd / notlist.c
1 /*
2  * Copyright (C) 1995, 1997-1999 Jeffrey A. Uphoff
3  * Modified by Olaf Kirch, 1996.
4  * Modified by H.J. Lu, 1998.
5  * Modified by Lon Hohberger, Oct. 2000.
6  *   - Fixed memory leaks, run-off-end problems, etc.
7  *
8  * NSM for Linux.
9  */
10
11 /*
12  * Simple list management for notify list
13  */
14
15 #ifdef HAVE_CONFIG_H
16 #include <config.h>
17 #endif
18
19 #include <string.h>
20 #include "misc.h"
21 #include "statd.h"
22 #include "notlist.h"
23
24
25 #ifdef DEBUG
26 /* 
27  * LH - The linked list code had some bugs.  Used this to help debug
28  * new code. 
29  */
30 static void 
31 plist(notify_list *head, int en)
32 {
33         /* case where we ran off the end */
34         if (!head) return;
35
36         printf("Entry %d: %s\n",en, NL_MON_NAME(head));
37         plist(head->next, ++en);
38 }
39
40 static void 
41 nlist_print(notify_list **head)
42 {
43         printf("--- Begin notify list dump ---\n");
44         plist(*head,1);
45         printf("--- End notify list dump ---\n");
46 }
47 #endif /* DEBUG */
48
49 /* 
50  * Allocate memory and set up a new notify list entry.
51  */
52 notify_list * 
53 nlist_new(char *my_name, char *mon_name, int state)
54 {
55         notify_list     *new;
56
57         if (!(new = (notify_list *) xmalloc(sizeof(notify_list))))
58                 return NULL;
59         memset(new, 0, sizeof(*new));
60
61         NL_TIMES(new) = MAX_TRIES;
62         NL_STATE(new) = state;
63         if (!(NL_MY_NAME(new) = xstrdup(my_name))
64                         || !(NL_MON_NAME(new) = xstrdup(mon_name)))
65                 return NULL;
66
67         return new;
68 }
69
70 /*
71  * Insert *entry into a notify list at the point specified by
72  * **head.  This can be in the middle.  However, we do not handle
73  * list _append_ in this function; rather, the only place we should
74  * have to worry about this case is in nlist_insert_timer below.
75  * - entry must not be NULL.
76  */
77 void 
78 nlist_insert(notify_list **head, notify_list *entry)
79 {
80         if (*head) {
81                 /* 
82                  * Cases where we're prepending a non-empty list
83                  * or inserting possibly in the middle somewhere (eg,
84                  * nlist_insert_timer...)
85                  */
86                 entry->next = (*head);          /* Forward pointer */
87                 entry->prev = (*head)->prev;    /* Back pointer */
88                 (*head)->prev = entry;          /* head's new back pointer */
89         }
90
91         /* Common to all cases, including new list creation */
92         *head = entry;                  /* New head */
93
94 #ifdef DEBUG
95         nlist_print(head);
96 #endif
97 }
98
99 /* 
100  * (re)insert *entry into notify_list **head.  This requires that
101  * NL_WHEN(entry) has been set (usually, this is time() + 5 seconds).
102  * - entry must not be NULL
103  *
104  * LH - This used to cause (a) a memory leak and (b) dropped notify-list
105  * entries.  The pointer ran off the end of the list, and changed the 
106  * head-end to point to the new, one-entry list.  All other entries became garbage.
107  *
108  * FIXME: Optimize this function. (I'll work on it - LH)
109  */
110 void 
111 nlist_insert_timer(notify_list **head, notify_list *entry)
112 {
113         notify_list     *spot = *head,          /* Insertion location */
114                                                 /* ...Start at head */
115                         *back = NULL;           /* Back pointer */
116
117
118         /* Find first entry with higher timeout value or end of list */
119         while (spot && NL_WHEN(spot) <= NL_WHEN(entry)) {
120                 /* 
121                  * Keep the back pointer in case we 
122                  * run off the end...  (see below)
123                  */
124                 back = spot;
125                 spot = spot->next;
126         }
127
128         if (spot == (*head)) {
129                 /* 
130                  * case where we're prepending an empty or non-empty
131                  * list or inserting in the middle somewhere.  Pass 
132                  * the real head of the list, since we'll be changing 
133                  * during the insert... 
134                  */
135                 nlist_insert(head, entry);
136         } else {
137                 /* all other cases - don't move the real head pointer */
138                 nlist_insert(&spot, entry);
139
140                 /* 
141                  * If spot == entry, then spot was NULL when we called
142                  * nlist_insert.  This happened because we had run off 
143                  * the end of the list.  Append entry to original list.
144                  */
145                 if (spot == entry) {
146                         back->next = entry;
147                         entry->prev = back;
148                 }
149         }
150 }
151
152 /* 
153  * Remove *entry from the list pointed to by **head.
154  * Do not destroy *entry.  This is normally done before
155  * a re-insertion with a timer, but can be done anywhere.
156  * - entry must not be NULL.
157  */
158 void 
159 nlist_remove(notify_list **head, notify_list *entry)
160 {
161         notify_list     *prev = entry->prev,
162                         *next = entry->next;
163
164         if (next) {
165                 next->prev = prev;
166         }
167
168         if (prev) {
169                 /* Case(s) where entry isn't at the front */
170                 prev->next = next; 
171         } else {
172                 /* cases where entry is at the front */
173                 *head = next;
174         }
175
176         entry->next = entry->prev = NULL;
177 #ifdef DEBUG
178         nlist_print(head);
179 #endif
180 }
181
182 /* 
183  * Clone an entry in the notify list -
184  * - entry must not be NULL
185  */
186 notify_list *
187 nlist_clone(notify_list *entry)
188 {
189         notify_list     *new;
190
191         new = nlist_new(NL_MY_NAME(entry), NL_MON_NAME(entry), NL_STATE(entry));
192         NL_MY_PROG(new) = NL_MY_PROG(entry);
193         NL_MY_VERS(new) = NL_MY_VERS(entry);
194         NL_MY_PROC(new) = NL_MY_PROC(entry);
195         NL_ADDR(new)    = NL_ADDR(entry);
196         memcpy(NL_PRIV(new), NL_PRIV(entry), SM_PRIV_SIZE);
197
198         return new;
199 }
200
201 /* 
202  * Destroy an entry in a notify list and free the memory.
203  * If *head is NULL, just free the entry.  This would be
204  * done only when we know entry isn't in any list.
205  * - entry must not be NULL.
206  */
207 void 
208 nlist_free(notify_list **head, notify_list *entry)
209 {
210         if (head && (*head))
211                 nlist_remove(head, entry);
212         if (NL_MY_NAME(entry))
213                 free(NL_MY_NAME(entry));
214         if (NL_MON_NAME(entry))
215                 free(NL_MON_NAME(entry));
216         free(entry);
217 }
218
219 /* 
220  * Destroy an entire notify list 
221  */
222 void 
223 nlist_kill(notify_list **head)
224 {
225         while (*head)
226                 nlist_free(head, *head);
227 }
228
229 /*
230  * Walk a list looking for a matching name in the NL_MON_NAME field.
231  */
232 notify_list *
233 nlist_gethost(notify_list *list, char *host, int myname)
234 {
235         notify_list     *lp;
236
237         for (lp = list; lp; lp = lp->next) {
238                 if (matchhostname(host, myname? NL_MY_NAME(lp) : NL_MON_NAME(lp)))
239                         return lp;
240         }
241
242         return (notify_list *) NULL;
243 }