Changes to use new list functions.
[privoxy.git] / list.c
1 const char list_rcs[] = "$Id: list.c,v 1.8 2001/08/07 14:00:20 oes Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/list.c,v $
5  *
6  * Purpose     :  Declares functions to handle lists.
7  *                Functions declared include:
8  *                   `destroy_list', `enlist' and `list_to_text'
9  *
10  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
11  *                IJBSWA team.  http://ijbswa.sourceforge.net
12  *
13  *                Based on the Internet Junkbuster originally written
14  *                by and Copyright (C) 1997 Anonymous Coders and 
15  *                Junkbusters Corporation.  http://www.junkbusters.com
16  *
17  *                This program is free software; you can redistribute it 
18  *                and/or modify it under the terms of the GNU General
19  *                Public License as published by the Free Software
20  *                Foundation; either version 2 of the License, or (at
21  *                your option) any later version.
22  *
23  *                This program is distributed in the hope that it will
24  *                be useful, but WITHOUT ANY WARRANTY; without even the
25  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
26  *                PARTICULAR PURPOSE.  See the GNU General Public
27  *                License for more details.
28  *
29  *                The GNU General Public License should be included with
30  *                this file.  If not, you can view it at
31  *                http://www.gnu.org/copyleft/gpl.html
32  *                or write to the Free Software Foundation, Inc., 59
33  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
34  *
35  * Revisions   :
36  *    $Log: list.c,v $
37  *    Revision 1.8  2001/08/07 14:00:20  oes
38  *    Fixed comment
39  *
40  *    Revision 1.7  2001/08/05 16:06:20  jongfoster
41  *    Modifiying "struct map" so that there are now separate header and
42  *    "map_entry" structures.  This means that functions which modify a
43  *    map no longer need to return a pointer to the modified map.
44  *    Also, it no longer reverses the order of the entries (which may be
45  *    important with some advanced template substitutions).
46  *
47  *    Revision 1.6  2001/07/31 14:44:51  oes
48  *    list_to_text() now appends empty line at end
49  *
50  *    Revision 1.5  2001/06/29 21:45:41  oes
51  *    Indentation, CRLF->LF, Tab-> Space
52  *
53  *    Revision 1.4  2001/06/29 13:30:22  oes
54  *    - Added Convenience function enlist_unique_header(),
55  *      which takes the Header name and value as separate
56  *      arguments and thus saves the pain of sprintf()ing
57  *      and determining the Header name length to enlist_unique
58  *    - Improved comments
59  *    - Removed logentry from cancelled commit
60  *
61  *    Revision 1.3  2001/06/03 19:12:24  oes
62  *    functions for new struct map, extended enlist_unique
63  *
64  *    Revision 1.2  2001/06/01 18:49:17  jongfoster
65  *    Replaced "list_share" with "list" - the tiny memory gain was not
66  *    worth the extra complexity.
67  *
68  *    Revision 1.1  2001/05/31 21:11:53  jongfoster
69  *    - Moved linked list support to new "list.c" file.
70  *      Structure definitions are still in project.h,
71  *      function prototypes are now in "list.h".
72  *    - Added support for "struct list_share", which is identical
73  *      to "struct list" except it saves memory by not duplicating
74  *      the strings.  Obviously, this only works if there is some
75  *      other way of managing the memory used by the strings.
76  *      (These list_share lists are used for lists which last
77  *      for only 1 request, and where all the list entries are
78  *      just coming directly from entries in the actionsfile.)
79  *      Note that you still need to destroy list_share lists
80  *      properly to free the nodes - it's only the strings
81  *      which are shared.
82  *
83  *
84  *********************************************************************/
85 \f
86
87 #include "config.h"
88
89 #include <stdio.h>
90 #include <sys/types.h>
91 #include <stdlib.h>
92 #include <ctype.h>
93 #include <string.h>
94
95 #ifndef _WIN32
96 #include <unistd.h>
97 #endif
98
99 #include <assert.h>
100
101 #include "project.h"
102 #include "jcc.h"
103 #include "list.h"
104 #include "miscutil.h"
105
106 const char list_h_rcs[] = LIST_H_VERSION;
107
108
109 /*********************************************************************
110  *
111  * Function    :  list_init
112  *
113  * Description :  Create a new, empty list in user-allocated memory.
114  *                Caller should allocate a "struct list" variable,
115  *                then pass it to this function.
116  *                (Implementation note:  Rather than calling this
117  *                function, you can also just memset the memory to
118  *                zero, e.g. if you have a larger structure you 
119  *                want to initialize quickly.  However, that isn't 
120  *                really good design.)
121  *
122  * Parameters  :
123  *          1  :  the_list = pointer to list
124  *
125  * Returns     :  N/A
126  *
127  *********************************************************************/
128 void init_list(struct list *the_list)
129 {
130    memset(the_list, '\0', sizeof(*the_list));
131 }
132
133
134 /*********************************************************************
135  *
136  * Function    :  destroy_list
137  *
138  * Description :  Destroy a string list (opposite of list_init).
139  *                On return, the memory used by the list entries has
140  *                been freed, but not the memory used by the_list
141  *                itself.  You should not re-use the_list without
142  *                calling list_init().
143  *
144  *                (Implementation note:  You *can* reuse the_list
145  *                without calling list_init(), but please don't.  
146  *                If you want to remove all entries from a list
147  *                and still have a usable list, then use 
148  *                list_remove_all().)
149  *
150  * Parameters  :
151  *          1  :  the_list = pointer to list
152  *
153  * Returns     :  N/A
154  *
155  *********************************************************************/
156 void destroy_list (struct list *the_list)
157 {
158    struct list_entry *cur_entry, *next_entry;
159
160    assert(the_list);
161
162    for (cur_entry = the_list->first; cur_entry ; cur_entry = next_entry)
163    {
164       next_entry = cur_entry->next;
165       freez((char *)cur_entry->str);
166       free(cur_entry);
167    }
168
169    the_list->first = NULL;
170    the_list->last = NULL;
171 }
172
173
174 /*********************************************************************
175  *
176  * Function    :  list_is_valid
177  *
178  * Description :  Check that a string list is valid.  The intended
179  *                usage is "assert(list_is_valid(the_list))".
180  *                Currently this checks that "the_list->last"
181  *                is correct, and that the list dosn't contain 
182  *                circular references.  It is likely to crash if
183  *                it's passed complete garbage.
184  *
185  * Parameters  :
186  *          1  :  the_list = pointer to list.  Must be non-null.
187  *
188  * Returns     :  1 if list is valid, 0 otherwise.
189  *
190  *********************************************************************/
191 static int list_is_valid (const struct list *the_list)
192 {
193    /*
194     * If you don't want this check, just change the line below
195     * from "#if 1" to "#if 0".
196     */
197 #if 1
198    const struct list_entry *cur_entry;
199    const struct list_entry *last_entry = NULL;
200    int length = 0;
201
202    assert(the_list);
203
204    for (cur_entry = the_list->first; cur_entry ; cur_entry = cur_entry->next)
205    {
206       last_entry = cur_entry;
207
208       if (cur_entry->str)
209       {
210          /*
211           * Just check that this string can be accessed - i.e. it's a valid 
212           * pointer.
213           */
214          strlen(cur_entry->str);
215       }
216
217       /*
218        * Check for looping back to first
219        */
220       if ((length != 0) && (cur_entry == the_list->first))
221       {
222          return 0;
223       }
224
225       /*
226        * Arbitrarily limit length to prevent infinite loops.
227        */
228       if (++length > 1000)
229       {
230          return 0;
231       }
232
233       /*
234        * Check this isn't marked as the last entry, unless of course it's
235        * *really* the last entry.
236        */
237       if ((the_list->last == cur_entry) && (cur_entry->next != NULL))
238       {
239          /* This is the last entry, but there's data after it !!?? */
240          return 0;
241       }
242    }
243
244    return (the_list->last == last_entry);
245 #else
246    return 1;
247 #endif
248 }
249
250 /*********************************************************************
251  *
252  * Function    :  enlist
253  *
254  * Description :  Append a string into a specified string list.
255  *
256  * Parameters  :
257  *          1  :  the_list = pointer to list
258  *          2  :  str = string to add to the list (maybe NULL)
259  *
260  * Returns     :  0 on success, nonzero on out-of-memory error.  On
261  *                error, the_list will be unchanged.
262  *
263  *********************************************************************/
264 int enlist(struct list *the_list, const char *str)
265 {
266    struct list_entry *cur;
267
268    assert(the_list);
269    assert(list_is_valid(the_list));
270
271    if (NULL == (cur = (struct list_entry *)zalloc(sizeof(*cur))))
272    {
273       return 1;
274    }
275
276    if (str)
277    {
278       if (NULL == (cur->str = strdup(str)))
279       {
280          free(cur);
281          return 1;
282       }
283    }
284    /* else { cur->str = NULL; }  - implied by zalloc */
285
286    /* cur->next = NULL;  - implied by zalloc */
287
288    if (the_list->last)
289    {
290       the_list->last->next = cur;
291       the_list->last = cur;
292    }
293    else
294    {
295       the_list->first = cur;
296       the_list->last = cur;
297    }
298
299    assert(list_is_valid(the_list));
300    return 0;
301 }
302
303
304 /*********************************************************************
305  *
306  * Function    :  enlist_first
307  *
308  * Description :  Append a string as first element into a specified
309  *                string list.
310  *
311  * Parameters  :
312  *          1  :  the_list = pointer to list
313  *          2  :  str = string to add to the list (maybe NULL)
314  *
315  * Returns     :  0 on success, nonzero on out-of-memory error.  On
316  *                error, the_list will be unchanged.
317  *
318  *********************************************************************/
319 int enlist_first(struct list *the_list, const char *str)
320 {
321    struct list_entry *cur;
322
323    assert(the_list);
324    assert(list_is_valid(the_list));
325
326    if (NULL == (cur = (struct list_entry *)zalloc(sizeof(*cur))))
327    {
328       return 1;
329    }
330
331    if (str)
332    {
333       if (NULL == (cur->str = strdup(str)))
334       {
335          free(cur);
336          return 1;
337       }
338    }
339    /* else { cur->str = NULL; }  - implied by zalloc */
340    
341    cur->next = the_list->first;
342
343    the_list->first = cur;
344    if (the_list->last == NULL)
345    {
346       the_list->last = cur;
347    }
348
349    assert(list_is_valid(the_list));
350    return 0;
351 }
352
353
354 /*********************************************************************
355  *
356  * Function    :  enlist_unique
357  *
358  * Description :  Append a string into a specified string list,
359  *                if & only if it's not there already.
360  *                If the num_significant_chars argument is nonzero,
361  *                only compare up to the nth character. 
362  *
363  * Parameters  :
364  *          1  :  the_list = pointer to list
365  *          2  :  str = string to add to the list
366  *          3  :  num_significant_chars = number of chars to use
367  *                for uniqueness test, or 0 to require an exact match.
368  *
369  * Returns     :  0 on success, nonzero on out-of-memory error.  On
370  *                error, the_list will be unchanged.  "Success"
371  *                does not indicate whether or not the item was
372  *                already in the list.
373  *
374  *********************************************************************/
375 int enlist_unique(struct list *the_list, const char *str,
376                   int num_significant_chars)
377 {
378    struct list_entry *cur_entry;
379
380    assert(the_list);
381    assert(list_is_valid(the_list));
382    assert(str);
383    assert(num_significant_chars >= 0);
384    assert((size_t)num_significant_chars <= strlen(str));
385
386    if (num_significant_chars > 0)
387    {
388       for (cur_entry = the_list->first; cur_entry != NULL; cur_entry = cur_entry->next)
389       {
390          if ( (cur_entry->str != NULL)
391            && (0 == strncmp(str, cur_entry->str, num_significant_chars)))
392          {
393             /* Already there */
394             return 0;
395          }
396       }
397    }
398    else
399    {
400       /* Test whole string */
401       for (cur_entry = the_list->first; cur_entry != NULL; cur_entry = cur_entry->next)
402       {
403          if ( (cur_entry->str != NULL) && (0 == strcmp(str, cur_entry->str)))
404          {
405             /* Already there */
406             return 0;
407          }
408       }
409    }
410
411    return enlist(the_list, str);
412 }
413
414
415 /*********************************************************************
416  *
417  * Function    :  enlist_unique_header
418  *
419  * Description :  Make a HTTP header from the two strings name and value,
420  *                and append the result into a specified string list,
421  *                if & only if there isn't already a header with that name.
422  *
423  * Parameters  :
424  *          1  :  the_list = pointer to list
425  *          2  :  name = HTTP header name (e.g. "Content-type")
426  *          3  :  value = HTTP header value (e.g. "text/html")
427  *
428  * Returns     :  0 on success, nonzero on out-of-memory error.  On
429  *                error, the_list will be unchanged.  "Success"
430  *                does not indicate whether or not the header was
431  *                already in the list.
432  *
433  *********************************************************************/
434 int enlist_unique_header(struct list *the_list, const char *name, const char *value)
435 {
436    int length;
437    int result;
438    char *str;
439
440    assert(the_list);
441    assert(list_is_valid(the_list));
442    assert(name);
443    assert(value);
444
445    length = strlen(name) + 2;
446    if (NULL == (str = (char *)malloc(length + strlen(value) + 1)))
447    {
448       return 1;
449    }
450    strcpy(str, name);
451    str[length - 2] = ':';
452    str[length - 1] = ' ';
453    strcpy(str + length, value);
454
455    result = enlist_unique(the_list, str, length);
456
457    free(str);
458
459    assert(list_is_valid(the_list));
460
461    return result;
462 }
463
464
465 /*********************************************************************
466  *
467  * Function    :  list_remove_all
468  *
469  * Description :  Remove all entries from a list.  On return, the_list
470  *                is a valid, empty list.  Note that this is similar
471  *                to destroy_list(), but the difference is that this
472  *                function guarantees that the list structure is still 
473  *                valid after the call.
474  *
475  * Parameters  :
476  *          1  :  the_list = pointer to list
477  *
478  * Returns     :  N/A
479  *
480  *********************************************************************/
481 void list_remove_all(struct list *the_list)
482 {
483    struct list_entry *cur_entry;
484    struct list_entry *next_entry;
485
486    assert(the_list);
487    assert(list_is_valid(the_list));
488
489    for (cur_entry = the_list->first; cur_entry ; cur_entry = next_entry)
490    {
491       next_entry = cur_entry->next;
492       freez((char *)cur_entry->str);
493       free(cur_entry);
494    }
495
496    the_list->first = the_list->last = NULL;
497
498    assert(list_is_valid(the_list));
499 }
500
501
502 /*********************************************************************
503  *
504  * Function    :  list_to_text
505  *
506  * Description :  "Flatten" a string list into 1 long \r\n delimited string,
507  *                adding an empty line at the end.  NULL entries are ignored.
508  *                This function does not change the_list.
509  *
510  * Parameters  :
511  *          1  :  the_list = pointer to list
512  *
513  * Returns     :  NULL on malloc error, else new long string.
514  *                Caller must free() it.
515  *
516  *********************************************************************/
517 char *list_to_text(const struct list *the_list)
518 {
519    struct list_entry *cur_entry;
520    char *ret = NULL;
521    char *s;
522    int size = 2;
523
524    assert(the_list);
525    assert(list_is_valid(the_list));
526
527    for (cur_entry = the_list->first; cur_entry ; cur_entry = cur_entry->next)
528    {
529       if (cur_entry->str)
530       {
531          size += strlen(cur_entry->str) + 2;
532       }
533    }
534
535    if ((ret = (char *)malloc(size + 1)) == NULL)
536    {
537       return(NULL);
538    }
539
540    ret[size] = '\0';
541
542    s = ret;
543
544    for (cur_entry = the_list->first; cur_entry ; cur_entry = cur_entry->next)
545    {
546       if (cur_entry->str)
547       {
548          strcpy(s, cur_entry->str);
549          s += strlen(s);
550          *s++ = '\r'; *s++ = '\n';
551       }
552    }
553    *s++ = '\r'; *s++ = '\n';
554
555    return(ret);
556 }
557
558
559 /*********************************************************************
560  *
561  * Function    :  list_remove_item
562  *
563  * Description :  Remove a string from a specified string list.
564  *
565  * Parameters  :
566  *          1  :  the_list = pointer to list
567  *          2  :  str = string to remove from the list - non-NULL
568  *
569  * Returns     :  Number of times it was removed.
570  *
571  *********************************************************************/
572 int list_remove_item(struct list *the_list, const char *str)
573 {
574    struct list_entry *prev = NULL;
575    struct list_entry *cur;
576    struct list_entry *next;
577    int count = 0;
578
579    assert(the_list);
580    assert(list_is_valid(the_list));
581    assert(str);
582
583    cur = the_list->first;
584
585    while (cur != NULL)
586    {
587       next = cur->next;
588
589       if ((cur->str != NULL) && (0 == strcmp(str, cur->str)))
590       {
591          count++;
592
593          if (prev != NULL)
594          {
595             prev->next = next;
596          }
597          else
598          {
599             the_list->first = next;
600          }
601          free((char *)cur->str);
602          free(cur);
603       }
604       else
605       {
606          prev = cur;
607       }
608       cur = next;
609    }
610
611    the_list->last = prev;
612
613    assert(list_is_valid(the_list));
614
615    return count;
616 }
617
618
619 /*********************************************************************
620  *
621  * Function    :  list_remove_list
622  *
623  * Description :  Remove all strings in one list from another list.
624  *                This is currently a brute-force algorithm
625  *                (it compares every pair of strings).
626  *
627  * Parameters  :
628  *          1  :  dest = list to change
629  *          2  :  src = list of strings to remove
630  *
631  * Returns     :  Total number of strings removed.
632  *
633  *********************************************************************/
634 int list_remove_list(struct list *dest, const struct list *src)
635 {
636    struct list_entry *cur;
637    int count = 0;
638
639    assert(src);
640    assert(dest);
641    assert(list_is_valid(src));
642    assert(list_is_valid(dest));
643
644    for (cur = src->first; cur != NULL; cur = cur->next)
645    {
646       if (cur->str != NULL)
647       {
648          count += list_remove_item(dest, cur->str);
649       }
650    }
651
652    assert(list_is_valid(src));
653    assert(list_is_valid(dest));
654
655    return count;
656 }
657
658
659 /*********************************************************************
660  *
661  * Function    :  list_duplicate
662  *
663  * Description :  Copy a string list
664  *
665  * Parameters  :
666  *          1  :  dest = Destination list.  Must be a valid list.
667  *                       All existing entries will be removed.
668  *          1  :  src = pointer to source list for copy.
669  *
670  * Returns     :  0 on success, nonzero on error.  On error, dest
671  *                will be empty.
672  *
673  *********************************************************************/
674 int list_duplicate(struct list *dest, const struct list *src)
675 {
676    struct list_entry * cur_src;
677    struct list_entry * cur_dest;
678
679    assert(src);
680    assert(dest);
681    assert(list_is_valid(src));
682    assert(list_is_valid(dest));
683
684    list_remove_all(dest);
685
686    /* Need to process first entry specially so we can set dest->first */
687    cur_src = src->first;
688    if (cur_src)
689    {
690       cur_dest = dest->first = (struct list_entry *)zalloc(sizeof(*cur_dest));
691       if (cur_dest == NULL)
692       {
693          destroy_list(dest);
694
695          assert(list_is_valid(src));
696          assert(list_is_valid(dest));
697
698          return 1;
699       }
700
701       if (cur_src->str)
702       {
703          cur_dest->str = strdup(cur_src->str);
704          if (cur_dest->str == NULL)
705          {
706             destroy_list(dest);
707
708             assert(list_is_valid(src));
709             assert(list_is_valid(dest));
710
711             return 1;
712          }
713       }
714       /* else { cur_dest->str = NULL; }  - implied by zalloc */
715
716       /* Now process the rest */
717       for (cur_src = cur_src->next; cur_src; cur_src = cur_src->next)
718       {
719          cur_dest = cur_dest->next = (struct list_entry *)zalloc(sizeof(*cur_dest));
720          if (cur_dest == NULL)
721          {
722             destroy_list(dest);
723
724             assert(list_is_valid(src));
725             assert(list_is_valid(dest));
726
727             return 1;
728          }
729          if (cur_src->str)
730          {
731             cur_dest->str = strdup(cur_src->str);
732             if (cur_dest->str == NULL)
733             {
734                destroy_list(dest);
735
736                assert(list_is_valid(src));
737                assert(list_is_valid(dest));
738
739                return 1;
740             }
741          }
742          /* else { cur_dest->str = NULL; }  - implied by zalloc */
743       }
744
745       dest->last = cur_dest;
746    }
747
748    assert(list_is_valid(src));
749    assert(list_is_valid(dest));
750
751    return 0;
752 }
753
754
755 /*********************************************************************
756  *
757  * Function    :  list_append_list_unique
758  *
759  * Description :  Append a string list to another list.
760  *                Duplicate items are not added.
761  *
762  * Parameters  :
763  *          1  :  dest = pointer to destination list for merge.
764  *          2  :  src = pointer to source for merge.
765  *
766  * Returns     :  0 on success, nonzero on out-of-memory error.
767  *                On error, some (but not all) of src might have
768  *                been copied into dest.
769  *
770  *********************************************************************/
771 int list_append_list_unique(struct list *dest, const struct list *src)
772 {
773    struct list_entry * cur;
774
775    assert(src);
776    assert(dest);
777    assert(list_is_valid(src));
778    assert(list_is_valid(dest));
779
780    for (cur = src->first; cur; cur = cur->next)
781    {
782       if (cur->str)
783       {
784          if (enlist_unique(dest, cur->str, 0))
785          {
786             assert(list_is_valid(src));
787             assert(list_is_valid(dest));
788
789             return 1;
790          }
791       }
792    }
793
794    assert(list_is_valid(src));
795    assert(list_is_valid(dest));
796
797    return 0;
798 }
799
800
801 /*********************************************************************
802  *
803  * Function    :  list_is_empty
804  *
805  * Description :  Test whether a list is empty.  Does not change the list.
806  *
807  * Parameters  :
808  *          1  :  the_list = pointer to list to test.
809  *
810  * Returns     :  Nonzero iff the list contains no entries.
811  *
812  *********************************************************************/
813 int list_is_empty(const struct list *the_list)
814 {
815    assert(the_list);
816    assert(list_is_valid(the_list));
817    
818    return (the_list->first == NULL);
819 }
820
821
822 /*********************************************************************
823  *
824  * Function    :  new_map
825  *
826  * Description :  Create a new, empty map.
827  *
828  * Parameters  :  N/A
829  *
830  * Returns     :  A new, empty map, or NULL if out of memory.
831  *
832  *********************************************************************/
833 struct map *new_map(void)
834 {
835    return (struct map *) zalloc(sizeof(struct map));
836 }
837
838
839 /*********************************************************************
840  *
841  * Function    :  free_map
842  *
843  * Description :  Free the memory occupied by a map and its
844  *                depandant strings
845  *
846  * Parameters  :
847  *          1  :  the_map = map to be freed.  May be NULL.
848  *
849  * Returns     :  N/A
850  *
851  *********************************************************************/
852 void free_map(struct map *the_map)
853 {
854    struct map_entry *cur_entry;
855    struct map_entry *next_entry;
856
857    if (the_map == NULL)
858    {
859       return;
860    }
861
862    for (cur_entry = the_map->first; cur_entry != NULL; cur_entry = next_entry) 
863    {
864       freez((char *)cur_entry->name);
865       freez((char *)cur_entry->value);
866
867       next_entry = cur_entry->next;
868       free(cur_entry);
869    }
870
871    the_map->first = the_map->last = NULL;
872
873    free(the_map);
874 }
875
876
877 /*********************************************************************
878  *
879  * Function    :  map
880  *
881  * Description :  Add a mapping from given name to given value to a
882  *                given map.
883  *
884  *                Note: Since all strings will be free()d in free_map()
885  *                      later, set the copy flags for constants or
886  *                      strings that will be independantly free()d.
887  *
888  * Parameters  :
889  *          1  :  the_map = map to add to
890  *          2  :  name = name to add
891  *          3  :  name_needs_copying = flag set if a copy of name should be used
892  *          4  :  value = value to add
893  *          5  :  value_needs_copying = flag set if a copy of value should be used
894  *
895  * Returns     :  0 on success, nonzero on out-of-memory error.
896  *
897  *********************************************************************/
898 int map(struct map *the_map,
899         const char *name, int name_needs_copying,
900         const char *value, int value_needs_copying)
901 {
902    struct map_entry *new_entry;
903
904    assert(the_map);
905    assert(name);
906    assert(value);
907
908    if (NULL == (new_entry = zalloc(sizeof(*new_entry))))
909    {
910       return 1;
911    }
912
913    if (name_needs_copying)
914    {
915       if (NULL == (name = strdup(name)))
916       {
917          free(new_entry);
918          return 1;
919       }
920    }
921
922    if (value_needs_copying)
923    {
924       if (NULL == (value = strdup(value)))
925       {
926          if (name_needs_copying)
927          {
928              free((char *)name);
929          }
930          free(new_entry);
931          return 1;
932       }
933    }
934
935    new_entry->name = name;
936    new_entry->value = value;
937    /* new_entry->next = NULL;  - implied by zalloc */
938
939    if (the_map->last)
940    {
941       the_map->last->next = new_entry;
942       the_map->last = new_entry;
943    }
944    else
945    {
946       the_map->first = new_entry;
947       the_map->last = new_entry;
948    }
949
950    return 0;
951 }
952
953
954 /*********************************************************************
955  *
956  * Function    :  lookup
957  *
958  * Description :  Look up an item with a given name in a map, and
959  *                return its value
960  *
961  * Parameters  :
962  *          1  :  the_map = map to look in
963  *          2  :  name = name parameter to look for
964  *
965  * Returns     :  the value if found, else the empty string.
966  *                Return value is alloced as part of the map, so
967  *                it is freed when the map is destroyed.  Caller
968  *                must not free or modify it.
969  *
970  *********************************************************************/
971 const char *lookup(const struct map *the_map, const char *name)
972 {
973    const struct map_entry *cur_entry;
974
975    assert(the_map);
976    assert(name);
977
978    for (cur_entry = the_map->first; cur_entry != NULL; cur_entry = cur_entry->next)
979    {
980       if (!strcmp(name, cur_entry->name))
981       {
982          return cur_entry->value;
983       }
984    }
985    return "";
986 }
987
988
989 /*
990   Local Variables:
991   tab-width: 3
992   end:
993 */