X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fchanger.c;h=ad9a83224f9c08ab3c357e1eeb1f6dd6a2675a91;hb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;hp=0e4c36d8ac2ff406c9f714c4ddfb32e7b27b8e15;hpb=34197d9f46a5f4e944378cbb65fca32ee0eec7b9;p=debian%2Famanda diff --git a/server-src/changer.c b/server-src/changer.c index 0e4c36d..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.36.2.2 2007/01/25 19:47:37 martinea Exp $ + * $Id: changer.c,v 1.36 2006/08/24 01:57:16 paddy_s Exp $ * * interface routines for tape changers */ @@ -53,29 +53,29 @@ 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(char *cmd, char *arg); -static int report_bad_resultstr(void); +static int report_bad_resultstr(char *cmd); static int run_changer_command(char *cmd, char *arg, char **slotstr, char **rest); 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(void) +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; @@ -105,7 +105,7 @@ run_changer_command( 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'; @@ -120,7 +120,7 @@ run_changer_command( } 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; @@ -168,7 +168,7 @@ changer_loadslot( 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; @@ -198,15 +198,15 @@ changer_query( 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; } @@ -223,7 +223,7 @@ changer_info( if(rc) return rc; if (sscanf(rest, "%d %d", nslotsp, backwardsp) != 2) { - return report_bad_resultstr(); + return report_bad_resultstr("-info"); } return 0; } @@ -253,7 +253,8 @@ changer_find( if (rc != 0) { /* Problem with the changer script. Bail. */ - fprintf(stderr, "Changer problem: %s\n", changer_resultstr); + g_fprintf(stderr, _("Changer problem: %s\n"), changer_resultstr); + amfree(curslotstr); return; } @@ -262,11 +263,11 @@ changer_find( 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){ @@ -320,205 +321,131 @@ changer_current( /* ---------------------------- */ static int -changer_command( - char *cmd, - char *arg) +start_chg_glue(void) { - int fd[2]; - amwait_t wait_exitcode = 1; - int exitcode; - char num1[NUM_STR_SIZE]; - char num2[NUM_STR_SIZE]; - char *cmdstr; - pid_t pid, changer_pid = 0; - int fd_to_close[4], *pfd_to_close = fd_to_close; - - 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; } - /* 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); - } + cmdstr = vstralloc(cmd, + arg ? " " : "", + arg ? arg : "", + "\n", + NULL); - 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 (" ", - "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] >= (int)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; - } + g_debug("changer: >> %s %s", cmd, arg? arg : ""); - switch(changer_pid = fork()) { - case -1: - changer_resultstr = vstralloc (" ", - "could not fork for \"", - cmdstr, - "\": ", - strerror(errno), - NULL); + /* 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 done; - case 0: - if(dup2(fd[1], 1) == -1 || dup2(dbfd(), 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, (char *)NULL, - safe_env()); - } else { - execle(tapechanger, tapechanger, cmd, (char *)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]); - } - - if((changer_resultstr = areads(fd[0])) == NULL) { - changer_resultstr = vstralloc (" ", - "could not read result from \"", - tapechanger, - errno ? "\": " : "\"", - errno ? strerror(errno) : "", - NULL); + 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: if (exitcode != 0) { - dbprintf(("changer: got exit: %d str: %s\n", exitcode, changer_resultstr)); + g_debug("changer: ERROR %s", changer_resultstr); } amfree(cmdstr); @@ -542,11 +469,11 @@ changer_search( 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; @@ -572,12 +499,12 @@ changer_label( 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); }