Imported Debian patch 2.5.2p1-3
[debian/amanda] / server-src / changer.c
index 9a0cff0c11b850aebba1883fcb9a7681a48c03bb..84ea94296576f5bce504aff4b72bb562352e9b8b 100644 (file)
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: changer.c,v 1.14.4.6.4.1.2.3 2003/02/28 19:23:25 martinea Exp $
+ * $Id: changer.c,v 1.36 2006/08/24 01:57:16 paddy_s Exp $
  *
  * interface routines for tape changers
  */
 #include "amanda.h"
+#include "util.h"
 #include "conffile.h"
 #include "version.h"
 
@@ -55,16 +56,20 @@ char *changer_resultstr = NULL;
 static char *tapechanger = NULL;
 
 /* local functions */
-static int changer_command P((char *cmd, char *arg));
+static int changer_command(char *cmd, char *arg);
+static int report_bad_resultstr(void);
+static int run_changer_command(char *cmd, char *arg, char **slotstr, char **rest);
 
-int changer_init()
+int
+changer_init(void)
 {
     tapechanger = getconf_str(CNF_TPCHANGER);
     return strcmp(tapechanger, "") != 0;
 }
 
 
-static int report_bad_resultstr()
+static int
+report_bad_resultstr(void)
 {
     char *s;
 
@@ -76,11 +81,12 @@ static int report_bad_resultstr()
     return 2;
 }
 
-static int run_changer_command(cmd, arg, slotstr, rest)
-char *cmd;
-char *arg;
-char **slotstr;
-char **rest;
+static int
+run_changer_command(
+    char *     cmd,
+    char *     arg,
+    char **    slotstr,
+    char **    rest)
 {
     int exitcode;
     char *result_copy;
@@ -88,8 +94,12 @@ char **rest;
     char *s;
     int ch;
 
-    *slotstr = NULL;
-    *rest = NULL;
+    if (slotstr) {
+        *slotstr = NULL;
+    }
+    if (rest) {
+        *rest = NULL;
+    }
     exitcode = changer_command(cmd, arg);
     s = changer_resultstr;
     ch = *s++;
@@ -99,11 +109,15 @@ char **rest;
     slot = s - 1;
     skip_non_whitespace(s, ch);
     s[-1] = '\0';
-    *slotstr = newstralloc(*slotstr, slot);
-    s[-1] = ch;
+    if (slotstr) {
+        *slotstr = newstralloc(*slotstr, slot);
+    }
+    s[-1] = (char)ch;
 
     skip_whitespace(s, ch);
-    *rest = s - 1;
+    if (rest) {
+        *rest = s - 1;
+    }
 
     if(exitcode) {
        if(ch == '\0') return report_bad_resultstr();
@@ -115,56 +129,68 @@ char **rest;
     return 0;
 }
 
-int changer_reset(slotstr)
-char **slotstr;
+int
+changer_reset(
+    char **    slotstr)
 {
     char *rest;
 
     return run_changer_command("-reset", (char *) NULL, slotstr, &rest);
 }
 
-int changer_clean(slotstr)
-char **slotstr;
+int
+changer_clean(
+    char **    slotstr)
 {
     char *rest;
 
     return run_changer_command("-clean", (char *) NULL, slotstr, &rest);
 }
 
-int changer_eject(slotstr)
-char **slotstr;
+int
+changer_eject(
+    char **    slotstr)
 {
     char *rest;
 
     return run_changer_command("-eject", (char *) NULL, slotstr, &rest);
 }
 
-int changer_loadslot(inslotstr, outslotstr, devicename)
-char *inslotstr, **outslotstr, **devicename;
+int
+changer_loadslot(
+    char *inslotstr,
+    char **outslotstr,
+    char **devicename)
 {
     char *rest;
     int rc;
 
     rc = run_changer_command("-slot", inslotstr, outslotstr, &rest);
-    if(rc) return rc;
 
+    if(rc) return rc;
     if(*rest == '\0') return report_bad_resultstr();
 
     *devicename = newstralloc(*devicename, rest);
     return 0;
 }
 
-/* This function is somewhat equal to changer_info with one additional
-   parameter, to get information, if the changer is able to search for
-   tapelabels himself. E.g. Barcodereader
-   The changer_script answers with an additional parameter, if it is able
-   to search. This one should be 1, if it is able to search, and 0 if it
-   knows about the extension. If the additional answer is omitted, the
-   changer is not able to search for a tape. 
-*/
-int changer_query(nslotsp, curslotstr, backwardsp, searchable)
-int *nslotsp, *backwardsp, *searchable;
-char **curslotstr;
+
+/*
+ * This function is somewhat equal to changer_info with one additional
+ * parameter, to get information, if the changer is able to search for
+ * tapelabels himself. E.g. Barcodereader
+ * The changer_script answers with an additional parameter, if it is able
+ * to search. This one should be 1, if it is able to search, and 0 if it
+ * knows about the extension. If the additional answer is omitted, the
+ * changer is not able to search for a tape. 
+ */
+
+int
+changer_query(
+    int *      nslotsp,
+    char **    curslotstr,
+    int *      backwardsp,
+    int *      searchable)
 {
     char *rest;
     int rc;
@@ -184,9 +210,11 @@ char **curslotstr;
     return 0;
 }
 
-int changer_info(nslotsp, curslotstr, backwardsp)
-int *nslotsp, *backwardsp;
-char **curslotstr;
+int
+changer_info(
+    int *      nslotsp,
+    char **    curslotstr,
+    int *      backwardsp)
 {
     char *rest;
     int rc;
@@ -203,49 +231,33 @@ char **curslotstr;
 
 /* ---------------------------- */
 
-void changer_scan(user_init, user_slot)
-int (*user_init) P((int rc, int nslots, int backwards));
-int (*user_slot) P((int rc, char *slotstr, char *device));
-{
-    char *slotstr, *device = NULL, *curslotstr = NULL;
-    int nslots, checked, backwards, rc, done;
-
-    rc = changer_info(&nslots, &curslotstr, &backwards);
-    done = user_init(rc, nslots, backwards);
-    amfree(curslotstr);
-
-    slotstr = "current";
-    checked = 0;
-
-    while(!done && checked < nslots) {
-       rc = changer_loadslot(slotstr, &curslotstr, &device);
-       if(rc > 0)
-           done = user_slot(rc, curslotstr, device);
-       else if(!done)
-           done = user_slot(0,  curslotstr, device);
-       amfree(curslotstr);
-       amfree(device);
-
-       checked += 1;
-       slotstr = "next";
-    }
-}
+/*
+ * This function first uses searchlabel and changer_search, if
+ * the library is able to find a tape itself. If it is not, or if 
+ * the tape could not be found, then the normal scan is done.
+ *
+ * See interface documentation in changer.h.
+ */
 
-/* This function first uses searchlabel and changer_search, if
-   the library is able to find a tape itself. If it is not, or if 
-   the tape could not be found, then the normal scan is done like 
-   in changer_scan.
-*/
-void changer_find(user_init, user_slot, searchlabel)
-int (*user_init) P((int rc, int nslots, int backwards));
-int (*user_slot) P((int rc, char *slotstr, char *device));
-char *searchlabel;
+void
+changer_find(
+     void *    user_data,
+     int       (*user_init)(void *, int, int, int, int),
+     int       (*user_slot)(void *, int, char *, char *),
+     char *    searchlabel)
 {
     char *slotstr, *device = NULL, *curslotstr = NULL;
     int nslots, checked, backwards, rc, done, searchable;
 
     rc = changer_query(&nslots, &curslotstr, &backwards, &searchable);
-    done = user_init(rc, nslots, backwards);
+
+    if (rc != 0) {
+        /* Problem with the changer script. Bail. */
+        fprintf(stderr, "Changer problem: %s\n", changer_resultstr);
+        return;
+    }
+
+    done = user_init(user_data, rc, nslots, backwards, searchable);
     amfree(curslotstr);
    
     if (searchlabel != NULL)
@@ -258,9 +270,9 @@ char *searchlabel;
     }
 
     if ((searchlabel!=NULL) && searchable && !done){
-      rc=changer_search(searchlabel,&curslotstr,&device);
+      rc=changer_search(searchlabel, &curslotstr, &device);
       if(rc == 0)
-        done = user_slot(rc,curslotstr,device);
+        done = user_slot(user_data, rc, curslotstr, device);
     }
  
     slotstr = "current";
@@ -269,9 +281,9 @@ char *searchlabel;
     while(!done && checked < nslots) {
        rc = changer_loadslot(slotstr, &curslotstr, &device);
        if(rc > 0)
-           done = user_slot(rc, curslotstr, device);
+           done = user_slot(user_data, rc, curslotstr, device);
        else if(!done)
-           done = user_slot(0,  curslotstr, device);
+           done = user_slot(user_data, 0,  curslotstr, device);
        amfree(curslotstr);
        amfree(device);
 
@@ -282,22 +294,24 @@ char *searchlabel;
 
 /* ---------------------------- */
 
-void changer_current(user_init, user_slot)
-int (*user_init) P((int rc, int nslots, int backwards));
-int (*user_slot) P((int rc, char *slotstr, char *device));
+void
+changer_current(
+    void *     user_data,
+    int                (*user_init)(void *, int, int, int, int),
+    int                (*user_slot)(void *, int, char *, char *))
 {
     char *device = NULL, *curslotstr = NULL;
-    int nslots, backwards, rc, done;
+    int nslots, backwards, rc, done, searchable;
 
-    rc = changer_info(&nslots, &curslotstr, &backwards);
-    done = user_init(rc, nslots, backwards);
+    rc = changer_query(&nslots, &curslotstr, &backwards, &searchable);
+    done = user_init(user_data, rc, nslots, backwards, searchable);
     amfree(curslotstr);
 
     rc = changer_loadslot("current", &curslotstr, &device);
     if(rc > 0) {
-       done = user_slot(rc, curslotstr, device);
+       done = user_slot(user_data, rc, curslotstr, device);
     } else if(!done) {
-       done = user_slot(0,  curslotstr, device);
+       done = user_slot(user_data, 0,  curslotstr, device);
     }
     amfree(curslotstr);
     amfree(device);
@@ -305,17 +319,19 @@ int (*user_slot) P((int rc, char *slotstr, char *device));
 
 /* ---------------------------- */
 
-static int changer_command(cmd, arg)
-     char *cmd;
-     char *arg;
+static int
+changer_command(
+     char *cmd,
+     char *arg)
 {
     int fd[2];
-    amwait_t wait_exitcode;
+    amwait_t wait_exitcode = 1;
     int exitcode;
     char num1[NUM_STR_SIZE];
     char num2[NUM_STR_SIZE];
     char *cmdstr;
-    pid_t pid, changer_pid;
+    pid_t pid, changer_pid = 0;
+    int fd_to_close[4], *pfd_to_close = fd_to_close;
 
     if (*tapechanger != '/') {
        tapechanger = vstralloc(libexecdir, "/", tapechanger, versionsuffix(),
@@ -344,9 +360,26 @@ static int changer_command(cmd, arg)
        exitcode = 2;
        goto failed;
     }
-    if(fd[0] < 0 || fd[0] >= FD_SETSIZE) {
-       ap_snprintf(num1, sizeof(num1), "%d", fd[0]);
-       ap_snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1);
+
+    /* make sure fd[0] > 2  && fd[1] > 2 */
+    pfd_to_close = fd_to_close;
+    while(fd[0] <= 2) {
+       int a = dup(fd[0]);
+       *pfd_to_close++ = fd[0];
+       fd[0] = a;
+    }
+    while(fd[1] <= 2) {
+       int a = dup(fd[1]);
+       *pfd_to_close++ = fd[1];
+       fd[1] = a;
+    }
+    while (pfd_to_close > fd_to_close) {
+       close(*--pfd_to_close);
+    }
+
+    if(fd[0] < 0 || fd[0] >= (int)FD_SETSIZE) {
+       snprintf(num1, SIZEOF(num1), "%d", fd[0]);
+       snprintf(num2, SIZEOF(num2), "%d", FD_SETSIZE-1);
        changer_resultstr = vstralloc ("<error> ",
                                       "could not create pipe for \"",
                                       cmdstr,
@@ -360,9 +393,9 @@ static int changer_command(cmd, arg)
        exitcode = 2;
        goto done;
     }
-    if(fd[1] < 0 || fd[1] >= FD_SETSIZE) {
-       ap_snprintf(num1, sizeof(num1), "%d", fd[1]);
-       ap_snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1);
+    if(fd[1] < 0 || fd[1] >= (int)FD_SETSIZE) {
+       snprintf(num1, SIZEOF(num1), "%d", fd[1]);
+       snprintf(num2, SIZEOF(num2), "%d", FD_SETSIZE-1);
        changer_resultstr = vstralloc ("<error> ",
                                       "could not create pipe for \"",
                                       cmdstr,
@@ -388,14 +421,14 @@ static int changer_command(cmd, arg)
        exitcode = 2;
        goto done;
     case 0:
-       if(dup2(fd[1], 1) == -1 || dup2(fd[1], 2) == -1) {
+       if(dup2(fd[1], 1) == -1 || dup2(dbfd(), 2) == -1) {
            changer_resultstr = vstralloc ("<error> ",
                                           "could not open pipe to \"",
                                           cmdstr,
                                           "\": ",
                                           strerror(errno),
                                           NULL);
-           (void)write(fd[1], changer_resultstr, strlen(changer_resultstr));
+           (void)fullwrite(fd[1], changer_resultstr, strlen(changer_resultstr));
            exit(1);
        }
        aclose(fd[0]);
@@ -407,13 +440,14 @@ static int changer_command(cmd, arg)
                                           "\": ",
                                           strerror(errno),
                                           NULL);
-           (void)write(2, changer_resultstr, strlen(changer_resultstr));
+           (void)fullwrite(2, changer_resultstr, strlen(changer_resultstr));
            exit(1);
        }
        if(arg) {
-           execle(tapechanger, tapechanger, cmd, arg, NULL, safe_env());
+           execle(tapechanger, tapechanger, cmd, arg, (char *)NULL,
+                  safe_env());
        } else {
-           execle(tapechanger, tapechanger, cmd, NULL, safe_env());
+           execle(tapechanger, tapechanger, cmd, (char *)NULL, safe_env());
        }
        changer_resultstr = vstralloc ("<error> ",
                                       "could not exec \"",
@@ -421,7 +455,7 @@ static int changer_command(cmd, arg)
                                       "\": ",
                                       strerror(errno),
                                       NULL);
-       (void)write(2, changer_resultstr, strlen(changer_resultstr));
+       (void)fullwrite(2, changer_resultstr, strlen(changer_resultstr));
        exit(1);
     default:
        aclose(fd[1]);
@@ -451,7 +485,7 @@ static int changer_command(cmd, arg)
                goto done;
            }
        } else if (pid != changer_pid) {
-           ap_snprintf(num1, sizeof(num1), "%ld", (long)pid);
+           snprintf(num1, SIZEOF(num1), "%ld", (long)pid);
            changer_resultstr = vstralloc ("<error> ",
                                           "wait for \"",
                                           tapechanger,
@@ -467,7 +501,7 @@ static int changer_command(cmd, arg)
 
     /* mark out-of-control changers as fatal error */
     if(WIFSIGNALED(wait_exitcode)) {
-       ap_snprintf(num1, sizeof(num1), "%d", WTERMSIG(wait_exitcode));
+       snprintf(num1, SIZEOF(num1), "%d", WTERMSIG(wait_exitcode));
        changer_resultstr = newvstralloc (changer_resultstr,
                                          "<error> ",
                                          changer_resultstr,
@@ -483,19 +517,27 @@ done:
     aclose(fd[1]);
 
 failed:
-    dbprintf(("changer: got exit: %d str: %s\n", exitcode, changer_resultstr)); 
+    if (exitcode != 0) {
+        dbprintf(("changer: got exit: %d str: %s\n", exitcode, changer_resultstr)); 
+    }
 
     amfree(cmdstr);
 
     return exitcode;
 }
 
-/* This function commands the changerscript to look for a tape named
-   searchlabel. If is found, the changerscript answers with the device,
-   in which the tape can be accessed.
-*/
-int changer_search(searchlabel, outslotstr, devicename)
-char *searchlabel, **outslotstr, **devicename;
+
+/*
+ * This function commands the changerscript to look for a tape named
+ * searchlabel. If is found, the changerscript answers with the device,
+ * in which the tape can be accessed.
+ */
+
+int
+changer_search(
+    char *     searchlabel,
+    char **    outslotstr,
+    char **    devicename)
 {
     char *rest;
     int rc;
@@ -510,15 +552,19 @@ char *searchlabel, **outslotstr, **devicename;
     return 0;
 }
 
-/* Because barcodelabel are short, and may not be the same as the 
-   amandalabels, the changerscript should be informed, which tapelabel
-   is associated with a tape. This function should be called after 
-   giving a label for a tape. (Maybe also, when the label and the associated
-   slot is known. e.g. during library scan.
-*/
-int changer_label (slotsp,labelstr)
-char *slotsp; 
-char *labelstr;
+
+/*
+ * Because barcodelabel are short, and may not be the same as the 
+ * amandalabels, the changerscript should be informed, which tapelabel
+ * is associated with a tape. This function should be called after 
+ * giving a label for a tape. (Maybe also, when the label and the associated
+ * slot is known. e.g. during library scan.
+ */
+
+int
+changer_label(
+    char *     slotsp, 
+    char *     labelstr)
 {
     int rc;
     char *rest=NULL;