X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fchanger.c;h=ad9a83224f9c08ab3c357e1eeb1f6dd6a2675a91;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=c4e2935a0a69a4942b991e00d9ea8a52356230d4;hpb=1194fb66aa28d9929c3f2bef3cc6c1c3f40a60a4;p=debian%2Famanda diff --git a/server-src/changer.c b/server-src/changer.c index c4e2935..ad9a832 100644 --- a/server-src/changer.c +++ b/server-src/changer.c @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: changer.c,v 1.29 2006/01/14 04:37:19 paddy_s Exp $ + * $Id: changer.c,v 1.36 2006/08/24 01:57:16 paddy_s Exp $ * * interface routines for tape changers */ @@ -53,35 +53,40 @@ int changer_debug = 0; char *changer_resultstr = NULL; -static char *tapechanger = NULL; +static pid_t tpchanger_pid = -1; +static int tpchanger_stdout = -1; +static int tpchanger_stdin = -1; /* local functions */ -static int changer_command P((char *cmd, char *arg)); +static int changer_command(char *cmd, char *arg); +static int report_bad_resultstr(char *cmd); +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; + return strcmp(getconf_str(CNF_TPCHANGER), "") != 0; } -static int report_bad_resultstr() +static int +report_bad_resultstr(char *cmd) { char *s; - s = vstralloc("badly formed result from changer: ", - "\"", changer_resultstr, "\"", - NULL); + s = vstrallocf(_(" badly formed result from changer command %s: \"%s\""), + cmd, changer_resultstr); amfree(changer_resultstr); changer_resultstr = s; 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; @@ -89,25 +94,33 @@ 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++; skip_whitespace(s, ch); - if(ch == '\0') return report_bad_resultstr(); + if(ch == '\0') return report_bad_resultstr(cmd); 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(); + if(ch == '\0') return report_bad_resultstr(cmd); result_copy = stralloc(s - 1); amfree(changer_resultstr); changer_resultstr = result_copy; @@ -116,32 +129,38 @@ 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; @@ -149,23 +168,29 @@ char *inslotstr, **outslotstr, **devicename; rc = run_changer_command("-slot", inslotstr, outslotstr, &rest); if(rc) return rc; - if(*rest == '\0') return report_bad_resultstr(); + if(*rest == '\0') return report_bad_resultstr("-slot"); *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; @@ -173,21 +198,23 @@ char **curslotstr; rc = run_changer_command("-info", (char *) NULL, curslotstr, &rest); if(rc) return rc; - dbprintf(("changer_query: changer return was %s\n",rest)); + dbprintf(_("changer_query: changer return was %s\n"),rest); if (sscanf(rest, "%d %d %d", nslotsp, backwardsp, searchable) != 3) { if (sscanf(rest, "%d %d", nslotsp, backwardsp) != 2) { - return report_bad_resultstr(); + return report_bad_resultstr("-info"); } else { *searchable = 0; } } - dbprintf(("changer_query: searchable = %d\n",*searchable)); + dbprintf(_("changer_query: searchable = %d\n"),*searchable); 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; @@ -196,7 +223,7 @@ char **curslotstr; if(rc) return rc; if (sscanf(rest, "%d %d", nslotsp, backwardsp) != 2) { - return report_bad_resultstr(); + return report_bad_resultstr("-info"); } return 0; } @@ -204,40 +231,49 @@ char **curslotstr; /* ---------------------------- */ -/* 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. -*/ -void changer_find(user_data, user_init, user_slot, searchlabel) - void *user_data; - int (*user_init) P((void *user_data, int rc, int nslots, int backwards, - int searchable)); - int (*user_slot) P((void *user_data, int rc, char *slotstr, - char *device)); - char *searchlabel; +/* + * 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. + */ + +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); + + if (rc != 0) { + /* Problem with the changer script. Bail. */ + g_fprintf(stderr, _("Changer problem: %s\n"), changer_resultstr); + amfree(curslotstr); + return; + } + done = user_init(user_data, rc, nslots, backwards, searchable); amfree(curslotstr); if (searchlabel != NULL) { - dbprintf(("changer_find: looking for %s changer is searchable = %d\n", - searchlabel, searchable)); + dbprintf(_("changer_find: looking for %s changer is searchable = %d\n"), + searchlabel, searchable); } else { - dbprintf(("changer_find: looking for NULL changer is searchable = %d\n", - searchable)); + dbprintf(_("changer_find: looking for NULL changer is searchable = %d\n"), + searchable); } if ((searchlabel!=NULL) && searchable && !done){ - rc=changer_search(searchlabel,&curslotstr,&device); + rc=changer_search(searchlabel, &curslotstr, &device); if(rc == 0) - done = user_slot(user_data, rc,curslotstr,device); + done = user_slot(user_data, rc, curslotstr, device); } slotstr = "current"; @@ -259,10 +295,11 @@ void changer_find(user_data, user_init, user_slot, searchlabel) /* ---------------------------- */ -void changer_current(user_data, user_init, user_slot) - void *user_data; -int (*user_init) P((void *ud, int rc, int nslots, int backwards, int searchable)); -int (*user_slot) P((void *ud, 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, searchable; @@ -283,220 +320,178 @@ int (*user_slot) P((void *ud, int rc, char *slotstr, char *device)); /* ---------------------------- */ -static int changer_command(cmd, arg) - char *cmd; - char *arg; +static int +start_chg_glue(void) { - int fd[2]; - amwait_t wait_exitcode; - int exitcode; - char num1[NUM_STR_SIZE]; - char num2[NUM_STR_SIZE]; - char *cmdstr; - pid_t pid, changer_pid = 0; - - if (*tapechanger != '/') { - tapechanger = vstralloc(libexecdir, "/", tapechanger, versionsuffix(), - NULL); - malloc_mark(tapechanger); + int stdin_pipe[2] = { -1, -1 }; + int stdout_pipe[2] = { -1, -1 }; + char *chg_glue; + + /* is it already running? */ + if (tpchanger_pid != -1) + return 1; + + if (pipe(stdin_pipe) == -1 || pipe(stdout_pipe) == -1) { + changer_resultstr = vstrallocf( + _(" could not make pipe: %s"), strerror(errno)); + goto error; } - cmdstr = vstralloc(tapechanger, " ", - cmd, arg ? " " : "", - arg ? arg : "", - NULL); - if(changer_debug) { - fprintf(stderr, "changer: opening pipe to: %s\n", cmdstr); - fflush(stderr); + switch(tpchanger_pid = fork()) { + case -1: + changer_resultstr = vstrallocf( + _(" could not fork: %s"), strerror(errno)); + goto error; + + case 0: + debug_dup_stderr_to_debug(); + if(dup2(stdin_pipe[0], 0) == -1) { + changer_resultstr = vstrallocf( + _(" could not dup2: %s"), strerror(errno)); + goto child_err; + } + + if(dup2(stdout_pipe[1], 1) == -1) { + changer_resultstr = vstrallocf( + _(" could not dup2: %s"), strerror(errno)); + goto child_err; + } + safe_fd(-1, 0); + + chg_glue = g_strdup_printf("%s/chg-glue", amlibexecdir); + + execl(chg_glue, chg_glue, get_config_name(), NULL); + changer_resultstr = vstrallocf( + _(" could not exec \"chg-glue\": %s"), strerror(errno)); + goto child_err; + +child_err: + (void)full_write(stdout_pipe[1], changer_resultstr, strlen(changer_resultstr)); + exit(1); + + default: + aclose(stdin_pipe[0]); + aclose(stdout_pipe[1]); + + tpchanger_stdout = stdout_pipe[0]; + tpchanger_stdin = stdin_pipe[1]; + + return 1; } +error: + aclose(stdin_pipe[0]); + aclose(stdin_pipe[1]); + aclose(stdout_pipe[0]); + aclose(stdout_pipe[1]); + + return 0; +} + +static int +changer_command( + char *cmd, + char *arg) +{ + int exitcode = 0; + char *cmdstr = NULL; + amfree(changer_resultstr); - if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) { - changer_resultstr = vstralloc (" ", - "could not create pipe for \"", - cmdstr, - "\": ", - strerror(errno), - NULL); + if (!start_chg_glue()) { exitcode = 2; goto failed; } - if(fd[0] < 0 || fd[0] >= FD_SETSIZE) { - snprintf(num1, sizeof(num1), "%d", fd[0]); - snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1); - changer_resultstr = vstralloc (" ", - "could not create pipe for \"", - cmdstr, - "\": ", - "socketpair 0: descriptor ", - num1, - " out of range ( .. ", - num2, - ")", - NULL); - exitcode = 2; - goto done; - } - if(fd[1] < 0 || fd[1] >= FD_SETSIZE) { - snprintf(num1, sizeof(num1), "%d", fd[1]); - snprintf(num2, sizeof(num2), "%d", FD_SETSIZE-1); - changer_resultstr = vstralloc (" ", - "could not create pipe for \"", - cmdstr, - "\": ", - "socketpair 1: descriptor ", - num1, - " out of range ( .. ", - num2, - ")", - NULL); - exitcode = 2; - goto done; - } - switch(changer_pid = fork()) { - case -1: - changer_resultstr = vstralloc (" ", - "could not fork for \"", - cmdstr, - "\": ", - strerror(errno), - NULL); - exitcode = 2; - goto done; - case 0: - if(dup2(fd[1], 1) == -1 || dup2(fd[1], 2) == -1) { - changer_resultstr = vstralloc (" ", - "could not open pipe to \"", - cmdstr, - "\": ", - strerror(errno), - NULL); - (void)fullwrite(fd[1], changer_resultstr, strlen(changer_resultstr)); - exit(1); - } - aclose(fd[0]); - aclose(fd[1]); - if(config_dir && chdir(config_dir) == -1) { - changer_resultstr = vstralloc (" ", - "could not cd to \"", - config_dir, - "\": ", - strerror(errno), - NULL); - (void)fullwrite(2, changer_resultstr, strlen(changer_resultstr)); - exit(1); - } - if(arg) { - execle(tapechanger, tapechanger, cmd, arg, NULL, safe_env()); - } else { - execle(tapechanger, tapechanger, cmd, NULL, safe_env()); - } - changer_resultstr = vstralloc (" ", - "could not exec \"", - tapechanger, - "\": ", - strerror(errno), - NULL); - (void)fullwrite(2, changer_resultstr, strlen(changer_resultstr)); - exit(1); - default: - aclose(fd[1]); - } + cmdstr = vstralloc(cmd, + arg ? " " : "", + arg ? arg : "", + "\n", + NULL); - if((changer_resultstr = areads(fd[0])) == NULL) { - changer_resultstr = vstralloc (" ", - "could not read result from \"", - tapechanger, - errno ? "\": " : "\"", - errno ? strerror(errno) : "", - NULL); + g_debug("changer: >> %s %s", cmd, arg? arg : ""); + + /* write the command to chg_glue */ + if (full_write(tpchanger_stdin, cmdstr, strlen(cmdstr)) != strlen(cmdstr)) { + changer_resultstr = g_strdup(" chg-glue exited unexpectedly"); + exitcode = 2; + goto failed; } - while(1) { - if ((pid = wait(&wait_exitcode)) == -1) { - if(errno == EINTR) { - continue; - } else { - changer_resultstr = vstralloc (" ", - "wait for \"", - tapechanger, - "\" failed: ", - strerror(errno), - NULL); - exitcode = 2; - goto done; - } - } else if (pid != changer_pid) { - snprintf(num1, sizeof(num1), "%ld", (long)pid); - changer_resultstr = vstralloc (" ", - "wait for \"", - tapechanger, - "\" returned unexpected pid ", - num1, - NULL); - exitcode = 2; - goto done; - } else { - break; - } + /* read the first line of the response */ + changer_resultstr = areads(tpchanger_stdout); + if (!changer_resultstr || !*changer_resultstr) { + changer_resultstr = g_strdup(" unexpected EOF"); + exitcode = 2; + goto failed; } + g_debug("changer: << %s", changer_resultstr); - /* mark out-of-control changers as fatal error */ - if(WIFSIGNALED(wait_exitcode)) { - snprintf(num1, sizeof(num1), "%d", WTERMSIG(wait_exitcode)); - changer_resultstr = newvstralloc (changer_resultstr, - " ", - changer_resultstr, - " (got signal ", num1, ")", - NULL); + if (strncmp_const(changer_resultstr, "EXITSTATUS ") != 0) { + report_bad_resultstr(cmd); exitcode = 2; - } else { - exitcode = WEXITSTATUS(wait_exitcode); + goto failed; } - -done: - aclose(fd[0]); - aclose(fd[1]); + exitcode = atoi(changer_resultstr + strlen("EXITSTATUS ")); + + /* and the second */ + changer_resultstr = areads(tpchanger_stdout); + if (!changer_resultstr) { + changer_resultstr = g_strdup(" unexpected EOF"); + exitcode = 2; + goto failed; + } + g_debug("changer: << %s", changer_resultstr); failed: - dbprintf(("changer: got exit: %d str: %s\n", exitcode, changer_resultstr)); + if (exitcode != 0) { + g_debug("changer: ERROR %s", 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; - dbprintf(("changer_search: %s\n",searchlabel)); + dbprintf("changer_search: %s\n",searchlabel); rc = run_changer_command("-search", searchlabel, outslotstr, &rest); if(rc) return rc; - if(*rest == '\0') return report_bad_resultstr(); + if(*rest == '\0') return report_bad_resultstr("-search"); *devicename = newstralloc(*devicename, rest); 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; @@ -504,12 +499,12 @@ char *labelstr; char *curslotstr = NULL; int nslots, backwards, searchable; - dbprintf(("changer_label: %s for slot %s\n",labelstr,slotsp)); + dbprintf(_("changer_label: %s for slot %s\n"),labelstr,slotsp); rc = changer_query(&nslots, &curslotstr, &backwards,&searchable); amfree(curslotstr); if ((rc == 0) && (searchable == 1)){ - dbprintf(("changer_label: calling changer -label %s\n",labelstr)); + dbprintf(_("changer_label: calling changer -label %s\n"),labelstr); rc = run_changer_command("-label", labelstr, &slotstr, &rest); amfree(slotstr); }