Imported Upstream version 3.2.0
[debian/amanda] / common-src / alloc.c
index 07bab02fc09b86ecadf390c4cc27479ecc0136f5..c470b9d974c33a248edca731b19bce016f8396fe 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 1991-1999 University of Maryland at College Park
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: alloc.c,v 1.17.2.1.4.3.2.3 2002/10/27 14:31:18 martinea Exp $
+ * $Id: alloc.c 5280 2007-02-13 15:58:56Z martineau $
  *
  * Memory allocators with error handling.  If the allocation fails,
  * errordump() is called, relieving the caller from checking the return
 #include "amanda.h"
 #include "arglist.h"
 
-/*
- *=====================================================================
- * debug_caller_loc -- keep track of all allocation callers
- *
- * char *debug_caller_loc(char *file, int line)
- *
- * entry:      file = source file
- *             line = source line
- * exit:       a string like "genversion.c@999"
- *
- * The debug malloc library has a concept of a call stack that can be used
- * to fine tune what was running when a particular allocation was done.
- * We use it to tell who called our various allocation wrappers since
- * it wouldn't do much good to tell us a problem happened because of
- * the malloc call in alloc (they are all from there at some point).
- *
- * But the library expects the string passed to malloc_enter/malloc_leave
- * to be static, so we build a linked list of each one we get (there are
- * not really that many during a given execution).  When we get a repeat
- * we return the previously allocated string.  For a bit of performance,
- * we keep the list in least recently used order, which helps because
- * the calls to us come in pairs (one for malloc_enter and one right
- * after for malloc_leave).
- *=====================================================================
- */
-
-char *
-debug_caller_loc(file, line)
-    char *file;
-    int line;
-{
-    struct loc_str {
-       char *str;
-       struct loc_str *next;
-    };
-    static struct loc_str *root = NULL;
-    struct loc_str *ls, *ls_last;
-    int len;
-    int size;
-    char *p;
-    static char *loc = NULL;
-    static int loc_size = 0;
-
-    if ((p = strrchr(file, '/')) == NULL) {
-       p = file;                               /* keep the whole name */
-    } else {
-       p++;                                    /* just the last path element */
-    }
-
-    len = strlen (p);
-    size = len + 1 + NUM_STR_SIZE + 1;
-    if (size > loc_size) {
-       size = ((size + 64 - 1) / 64) * 64;     /* might as well get a bunch */
-       /*
-        * We should free the previous loc area, but we have marked it
-        * as a non-leak and the library considers it an error to free
-        * such an area, so we just ignore it.  We probably grabbed
-        * enough the first time that this will not even happen.
-        */
-       loc = malloc (size);
-       if (loc == NULL) {
-           return "??";                        /* not much better than abort */
-       }
-       malloc_mark (loc);
-       loc_size = size;
-    }
-
-    strcpy (loc, p);
-    ap_snprintf(loc + len, 1 + NUM_STR_SIZE, "@%d", line);
-
-    for (ls_last = NULL, ls = root; ls != NULL; ls_last = ls, ls = ls->next) {
-       if (strcmp (loc, ls->str) == 0) {
-           break;
-       }
-    }
-
-    if (ls == NULL) {
-       /*
-        * This is a new entry.  Put it at the head of the list.
-        */
-       ls = malloc (sizeof (*ls));
-       if (ls == NULL) {
-           return "??";                        /* not much better than abort */
-       }
-       malloc_mark (ls);
-       size = strlen (loc) + 1;
-       ls->str = malloc (size);
-       if (ls->str == NULL) {
-           free (ls);
-           return "??";                        /* not much better than abort */
-       }
-       malloc_mark (ls->str);
-       strcpy (ls->str, loc);
-       ls->next = root;
-       root = ls;
-    } else if (ls_last != NULL) {
-       /*
-        * This is a repeat and was not at the head of the list.
-        * Unlink it and move it to the front.
-        */
-       ls_last->next = ls->next;
-       ls->next = root;
-       root = ls;
-    } else {
-       /*
-        * This is a repeat but was already at the head of the list,
-        * so nothing else needs to be done.
-        */
-    }
-    return ls->str;
-}
-
-/*
- *=====================================================================
- * Save the current source line for vstralloc/newvstralloc.
- *
- * int debug_alloc_push (char *s, int l)
- *
- * entry:      s = source file
- *             l = source line
- * exit:       always zero
- * 
- * See the comments in amanda.h about what this is used for.
- *=====================================================================
- */
-
-#define        DEBUG_ALLOC_SAVE_MAX    10
-
-static struct {
-       char            *file;
-       int             line;
-} debug_alloc_loc_info[DEBUG_ALLOC_SAVE_MAX];
-static int debug_alloc_ptr = 0;
-
-static char            *saved_file;
-static int             saved_line;
-
-int
-debug_alloc_push (s, l)
-    char *s;
-    int l;
-{
-    debug_alloc_loc_info[debug_alloc_ptr].file = s;
-    debug_alloc_loc_info[debug_alloc_ptr].line = l;
-    debug_alloc_ptr = (debug_alloc_ptr + 1) % DEBUG_ALLOC_SAVE_MAX;
-    return 0;
-}
-
-/*
- *=====================================================================
- * Pop the current source line information for vstralloc/newvstralloc.
- *
- * int debug_alloc_pop (void)
- *
- * entry:      none
- * exit:       none
- * 
- * See the comments in amanda.h about what this is used for.
- *=====================================================================
- */
+#define        MIN_ALLOC       64
 
-void
-debug_alloc_pop ()
-{
-    debug_alloc_ptr =
-      (debug_alloc_ptr + DEBUG_ALLOC_SAVE_MAX - 1) % DEBUG_ALLOC_SAVE_MAX;
-    saved_file = debug_alloc_loc_info[debug_alloc_ptr].file;
-    saved_line = debug_alloc_loc_info[debug_alloc_ptr].line;
-}
+static char *internal_vstralloc(const char *, int, const char *, va_list);
 
 /*
  * alloc - a wrapper for malloc.
  */
 void *
-debug_alloc(s, l, size)
-    char *s;
-    int l;
-    size_t size;
+debug_alloc(
+    const char *file,
+    int                line,
+    size_t     size)
 {
     void *addr;
 
-    malloc_enter(debug_caller_loc(s, l));
     addr = (void *)malloc(max(size, 1));
-    if(addr == NULL) {
-       errordump("%s@%d: memory allocation failed (%u bytes requested)",
-                 s ? s : "(unknown)",
-                 s ? l : -1,
+    if (addr == NULL) {
+       errordump(_("%s@%d: memory allocation failed (%zu bytes requested)"),
+                 file ? file : _("(unknown)"),
+                 file ? line : -1,
                  size);
+       /*NOTREACHED*/
     }
-    malloc_leave(debug_caller_loc(s, l));
     return addr;
 }
 
@@ -231,18 +64,16 @@ debug_alloc(s, l, size)
  * newalloc - free existing buffer and then alloc a new one.
  */
 void *
-debug_newalloc(s, l, old, size)
-    char *s;
-    int l;
-    void *old;
-    size_t size;
+debug_newalloc(
+    const char *file,
+    int                line,
+    void *     old,
+    size_t     size)
 {
     char *addr;
 
-    malloc_enter(debug_caller_loc(s, l));
-    addr = debug_alloc(s, l, size);
+    addr = debug_alloc(file, line, size);
     amfree(old);
-    malloc_leave(debug_caller_loc(s, l));
     return addr;
 }
 
@@ -252,21 +83,18 @@ debug_newalloc(s, l, old, size)
  *            Just like strdup()!
  */
 char *
-debug_stralloc(s, l, str)
-    char *s;
-    int l;
-    const char *str;
+debug_stralloc(
+    const char *file,
+    int                line,
+    const char *str)
 {
     char *addr;
 
-    malloc_enter(debug_caller_loc(s, l));
-    addr = debug_alloc(s, l, strlen(str) + 1);
+    addr = debug_alloc(file, line, strlen(str) + 1);
     strcpy(addr, str);
-    malloc_leave(debug_caller_loc(s, l));
-    return addr;
+    return (addr);
 }
 
-
 /*
  * internal_vstralloc - copies up to MAX_STR_ARGS strings into newly
  * allocated memory.
@@ -275,24 +103,26 @@ debug_stralloc(s, l, str)
  * to scan the strings more than necessary.
  */
 
-#define        MAX_VSTRALLOC_ARGS      32
+#define        MAX_VSTRALLOC_ARGS      40
 
 static char *
-internal_vstralloc(str, argp)
-    const char *str;
-    va_list argp;
+internal_vstralloc(
+    const char *file,
+    int                line,
+    const char *str,
+    va_list argp)
 {
     char *next;
     char *result;
-    int a;
+    int a, b;
     size_t total_len;
     const char *arg[MAX_VSTRALLOC_ARGS+1];
     size_t len[MAX_VSTRALLOC_ARGS+1];
     size_t l;
-    const char *s;
 
     if (str == NULL) {
-       return NULL;                            /* probably will not happen */
+       errordump(_("internal_vstralloc: str is NULL"));
+       /*NOTREACHED*/
     }
 
     a = 0;
@@ -306,24 +136,24 @@ internal_vstralloc(str, argp)
            continue;                           /* minor optimisation */
        }
        if (a >= MAX_VSTRALLOC_ARGS) {
-           errordump("%s@%d: more than %d arg%s to vstralloc",
-                     saved_file ? saved_file : "(unknown)",
-                     saved_file ? saved_line : -1,
-                     MAX_VSTRALLOC_ARGS,
-                     (MAX_VSTRALLOC_ARGS == 1) ? "" : "s");
+           errordump(_("%s@%d: more than %d args to vstralloc"),
+                     file ? file : _("(unknown)"),
+                     file ? line : -1,
+                     MAX_VSTRALLOC_ARGS);
+           /*NOTREACHED*/
        }
        arg[a] = next;
        len[a] = l;
        total_len += l;
        a++;
     }
-    arg[a] = NULL;
-    len[a] = 0;
 
-    next = result = debug_alloc(saved_file, saved_line, total_len+1);
-    for (a = 0; (s = arg[a]) != NULL; a++) {
-       memcpy(next, s, len[a]);
-       next += len[a];
+    result = debug_alloc(file, line, total_len+1);
+
+    next = result;
+    for (b = 0; b < a; b++) {
+       memcpy(next, arg[b], len[b]);
+       next += len[b];
     }
     *next = '\0';
 
@@ -334,17 +164,19 @@ internal_vstralloc(str, argp)
 /*
  * vstralloc - copies multiple strings into newly allocated memory.
  */
-arglist_function(char *debug_vstralloc, const char *, str)
+char *
+debug_vstralloc(
+    const char *file,
+    int                line,
+    const char *str,
+    ...)
 {
     va_list argp;
     char *result;
 
-    debug_alloc_pop();
-    malloc_enter(debug_caller_loc(saved_file, saved_line));
     arglist_start(argp, str);
-    result = internal_vstralloc(str, argp);
+    result = internal_vstralloc(file, line, str, argp);
     arglist_end(argp);
-    malloc_leave(debug_caller_loc(saved_file, saved_line));
     return result;
 }
 
@@ -353,95 +185,151 @@ arglist_function(char *debug_vstralloc, const char *, str)
  * newstralloc - free existing string and then stralloc a new one.
  */
 char *
-debug_newstralloc(s, l, oldstr, newstr)
-    char *s;
-    int l;
-    char *oldstr;
-    const char *newstr;
+debug_newstralloc(
+    const char *file,
+    int                line,
+    char *     oldstr,
+    const char *newstr)
 {
     char *addr;
 
-    malloc_enter(debug_caller_loc(s, l));
-    addr = debug_stralloc(s, l, newstr);
+    addr = debug_stralloc(file, line, newstr);
     amfree(oldstr);
-    malloc_leave(debug_caller_loc(s, l));
-    return addr;
+    return (addr);
 }
 
 
 /*
  * newvstralloc - free existing string and then vstralloc a new one.
  */
-arglist_function1(char *debug_newvstralloc,
-                 char *,
-                 oldstr,
-                 const char *,
-                 newstr)
+char *
+debug_newvstralloc(
+    const char *file,
+    int                line,
+    char *     oldstr,
+    const char *newstr,
+    ...)
 {
     va_list argp;
     char *result;
 
-    debug_alloc_pop();
-    malloc_enter(debug_caller_loc(saved_file, saved_line));
     arglist_start(argp, newstr);
-    result = internal_vstralloc(newstr, argp);
+    result = internal_vstralloc(file, line, newstr, argp);
     arglist_end(argp);
     amfree(oldstr);
-    malloc_leave(debug_caller_loc(saved_file, saved_line));
     return result;
 }
 
 
 /*
- * sbuf_man - static buffer manager.
- *
- * Manage a bunch of static buffer pointers.
+ * vstrallocf - copies printf formatted string into newly allocated memory.
  */
-void *sbuf_man(e_bufs, ptr)
-    void *e_bufs; /* XXX - I dont think this is right */
-    void *ptr;
+char *
+debug_vstrallocf(
+    const char *file,
+    int                line,
+    const char *fmt,
+    ...)
 {
-       SBUF2_DEF(1) *bufs;
-       int slot;
+    char *     result;
+    size_t     size;
+    va_list    argp;
+
 
-       bufs = e_bufs;
+    result = debug_alloc(file, line, MIN_ALLOC);
+    if (result != NULL) {
 
-       /* try and trap bugs */
-       assert(bufs->magic == SBUF_MAGIC);
-       assert(bufs->max > 0);
+       arglist_start(argp, fmt);
+       size = g_vsnprintf(result, MIN_ALLOC, fmt, argp);
+       arglist_end(argp);
 
-       /* initialise first time through */
-       if(bufs->cur == -1)
-               for(slot=0; slot < bufs->max; slot++) {
-                       bufs->bufp[slot] = (void *)0;
-               } 
+       if (size >= (size_t)MIN_ALLOC) {
+           amfree(result);
+           result = debug_alloc(file, line, size + 1);
+
+           arglist_start(argp, fmt);
+           (void)g_vsnprintf(result, size + 1, fmt, argp);
+           arglist_end(argp);
+       }
+    }
+
+    return result;
+}
+
+
+/*
+ * newvstrallocf - free existing string and then vstrallocf a new one.
+ */
+char *
+debug_newvstrallocf(
+    const char *file,
+    int                line,
+    char *     oldstr,
+    const char *fmt,
+    ...)
+{
+    size_t     size;
+    char *     result;
+    va_list    argp;
 
-       /* calculate the next slot */
-       slot = bufs->cur + 1;
-       if (slot >= bufs->max) slot = 0;
+    result = debug_alloc(file, line, MIN_ALLOC);
+    if (result != NULL) {
 
-       /* free the previous inhabitant */
-       if(bufs->bufp[slot] != (void *)0) free(bufs->bufp[slot]);
+       arglist_start(argp, fmt);
+       size = g_vsnprintf(result, MIN_ALLOC, fmt, argp);
+       arglist_end(argp);
 
-       /* store the new one */
-       bufs->bufp[slot] = ptr;
-       bufs->cur = slot;
+       if (size >= MIN_ALLOC) {
+           amfree(result);
+           result = debug_alloc(file, line, size + 1);
 
-       return ptr;
+           arglist_start(argp, fmt);
+           (void)g_vsnprintf(result, size + 1, fmt, argp);
+           arglist_end(argp);
+       }
+    }
+    amfree(oldstr);
+    return result;
 }
 
+/* vstrextend -- Extends the existing string by appending the other 
+ * arguments. */
+char *
+debug_vstrextend(
+    const char *file,
+    int                line,
+    char **    oldstr,
+    ...)
+{
+       char *keep = *oldstr;
+       va_list ap;
+
+       arglist_start(ap, oldstr);
+
+       if (*oldstr == NULL)
+               *oldstr = "";
+       *oldstr = internal_vstralloc(file, line, *oldstr, ap);
+        amfree(keep);
+
+       arglist_end(ap);
+        return *oldstr;
+}
 
 /*
- * safe_env - build a "safe" environment list.
+ * safe_env_full - build a "safe" environment list.
  */
 char **
-safe_env()
+safe_env_full(char **add)
 {
     static char *safe_env_list[] = {
        "TZ",
+#ifdef __CYGWIN__
+       "SYSTEMROOT",
+#endif
 #ifdef NEED_PATH_ENV
        "PATH",
 #endif
+       "DISPLAY",
        NULL
     };
 
@@ -451,7 +339,7 @@ safe_env()
      * safe_env_list so our result is always a valid, although possibly
      * empty, environment list.
      */
-#define SAFE_ENV_CNT   (sizeof(safe_env_list) / sizeof(*safe_env_list))
+#define SAFE_ENV_CNT   (size_t)(sizeof(safe_env_list) / sizeof(*safe_env_list))
     char **envp = safe_env_list + SAFE_ENV_CNT - 1;
 
     char **p;
@@ -459,9 +347,47 @@ safe_env()
     char *s;
     char *v;
     size_t l1, l2;
+    char **env;
+    int    env_cnt;
+    int nadd = 0;
+
+    /* count ADD */
+    for (p = add; p && *p; p++)
+       nadd++;
+
+    if (getuid() == geteuid() && getgid() == getegid()) {
+       env_cnt = 1;
+       for (env = environ; *env != NULL; env++)
+           env_cnt++;
+       if ((q = (char **)malloc((nadd+env_cnt)*SIZEOF(char *))) != NULL) {
+           envp = q;
+           p = envp;
+           /* copy in ADD */
+           for (env = add; env && *env; env++) {
+               *p = *env;
+               p++;
+           }
+           for (env = environ; *env != NULL; env++) {
+               if (strncmp("LANG=", *env, 5) != 0 &&
+                   strncmp("LC_", *env, 3) != 0) {
+                   *p = stralloc(*env);
+                   p++;
+               }
+           }
+           *p = NULL;
+       }
+       return envp;
+    }
 
-    if ((q = (char **)malloc(sizeof(safe_env_list))) != NULL) {
+    if ((q = (char **)malloc(nadd*sizeof(char *) + SIZEOF(safe_env_list))) != NULL) {
        envp = q;
+       /* copy in ADD */
+       for (p = add; p && *p; p++) {
+           *q = *p;
+           q++;
+       }
+
+       /* and copy any SAFE_ENV that are already set */
        for (p = safe_env_list; *p != NULL; p++) {
            if ((v = getenv(*p)) == NULL) {
                continue;                       /* no variable to dup */
@@ -481,70 +407,3 @@ safe_env()
     }
     return envp;
 }
-
-/*
- * amtable_alloc -- (re)allocate enough space for some number of elements.
- *
- * input:      table -- pointer to pointer to table
- *             current -- pointer to current number of elements
- *             elsize -- size of a table element
- *             count -- desired number of elements
- *             bump -- round up factor
- *             init_func -- optional element initialization function
- * output:     table -- possibly adjusted to point to new table area
- *             current -- possibly adjusted to new number of elements
- */
-
-int
-debug_amtable_alloc(s, l, table, current, elsize, count, bump, init_func)
-    char *s;
-    int l;
-    void **table;
-    int *current;
-    size_t elsize;
-    int count;
-    int bump;
-    void (*init_func)(void *);
-{
-    void *table_new;
-    int table_count_new;
-    int i;
-
-    if (count >= *current) {
-       table_count_new = ((count + bump) / bump) * bump;
-       table_new = debug_alloc(s, l, table_count_new * elsize);
-       if (0 != *table) {
-           memcpy(table_new, *table, *current * elsize);
-           free(*table);
-       }
-       *table = table_new;
-       memset(((char *)*table) + *current * elsize,
-              0,
-              (table_count_new - *current) * elsize);
-       if (init_func != NULL) {
-           for (i = *current; i < table_count_new; i++) {
-               (*init_func)(((char *)*table) + i * elsize);
-           }
-       }
-       *current = table_count_new;
-    }
-    return 0;
-}
-
-/*
- * amtable_free -- release a table.
- *
- * input:      table -- pointer to pointer to table
- *             current -- pointer to current number of elements
- * output:     table -- possibly adjusted to point to new table area
- *             current -- possibly adjusted to new number of elements
- */
-
-void
-amtable_free(table, current)
-    void **table;
-    int *current;
-{
-    amfree(*table);
-    *current = 0;
-}