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