33fd1192a70d7ec62a0e106ffb7da51961b1c6f8 jcasper Thu Aug 22 14:47:59 2013 -0700 Removed redundancy from sqlExecProg* functions, added test and error message for crash of execvp() diff --git src/hg/lib/sqlProg.c src/hg/lib/sqlProg.c index 636e0eb..b7ff07e 100644 --- src/hg/lib/sqlProg.c +++ src/hg/lib/sqlProg.c @@ -59,145 +59,82 @@ safef(field, sizeof(field), "%s.password", profile); safef(fileData, sizeof(fileData), "password=%s\n", cfgVal(field)); if (write (fileNo, fileData, strlen(fileData)) == -1) errAbort("sqlMakeExtraFile: Writing password to temporary file %s failed with errno %d", extraFileName, errno); return fileNo; } void sqlExecProg(char *prog, char **progArgs, int userArgc, char *userArgv[]) /* Exec one of the sql programs using user and password from ~/.hg.conf. * progArgs is NULL-terminate array of program-specific arguments to add, * which maybe NULL. userArgv are arguments passed in from the command line. * The program is execvp-ed, this function does not return. */ { -int i, j = 0, nargc=cntArgv(progArgs)+userArgc+6, extraFileNo; -pid_t child_id; -char **nargv, extraFileArg[256], *homeDir, extraFileName[256]; - -/* Assemble defaults file */ -if ((homeDir = getenv("HOME")) == NULL) - errAbort("sqlExecProg: HOME is not defined in environment; cannot create temporary password file"); -safef(extraFileName, sizeof(extraFileName), "%s/.hgsql.cnfXXXXXX", homeDir); -extraFileNo=sqlMakeExtraFile(extraFileName, "db", "client"); -safef(extraFileArg, sizeof(extraFileArg), "--defaults-extra-file=%s", extraFileName); - -AllocArray(nargv, nargc); - -nargv[j++] = prog; -nargv[j++] = extraFileArg; /* --defaults-extra-file must come before other options */ -if (progArgs != NULL) - { - for (i = 0; progArgs[i] != NULL; i++) - nargv[j++] = progArgs[i]; - } -for (i = 0; i < userArgc; i++) - nargv[j++] = userArgv[i]; -nargv[j++] = NULL; - -child_id = fork(); -if (child_id == 0) - { - execvp(nargv[0], nargv); - _exit(1); - } -else - { - /* Wait until the called process completes, then delete the temp file */ - wait(NULL); - unlink (extraFileName); - } +sqlExecProgProfile("db", prog, progArgs, userArgc, userArgv); } void sqlExecProgLocal(char *prog, char **progArgs, int userArgc, char *userArgv[]) /* * Exec one of the sql programs using user and password defined in localDb.XXX variables from ~/.hg.conf * progArgs is NULL-terminate array of program-specific arguments to add, * which maybe NULL. userArgv are arguments passed in from the command line. * The program is execvp-ed, this function does not return. */ { -int i, j = 0, nargc=cntArgv(progArgs)+userArgc+6, extraFileNo; -pid_t child_id; -char **nargv, extraFileName[256], extraFileArg[256], *homeDir; - -/* Assemble defaults file */ -if ((homeDir = getenv("HOME")) == NULL) - errAbort("sqlExecProg: HOME is not defined in environment; cannot create temporary password file"); -safef(extraFileName, sizeof(extraFileName), "%s/.hgsql.cnfXXXXXX", homeDir); -extraFileNo=sqlMakeExtraFile(extraFileName, "localDb", "client"); -safef(extraFileArg, sizeof(extraFileArg), "--defaults-extra-file=%s", extraFileName); - -AllocArray(nargv, nargc); - -nargv[j++] = prog; -nargv[j++] = extraFileArg; /* --defaults-extra-file must come before other options */ -if (progArgs != NULL) - { - for (i = 0; progArgs[i] != NULL; i++) - nargv[j++] = progArgs[i]; - } -for (i = 0; i < userArgc; i++) - nargv[j++] = userArgv[i]; -nargv[j++] = NULL; - -child_id = fork(); -if (child_id == 0) - { - execvp(nargv[0], nargv); - _exit(1); - } -else - { - /* Wait until the called process completes, then delete the temp file */ - wait(NULL); - unlink (extraFileName); - } +sqlExecProgProfile("localDb", prog, progArgs, userArgc, userArgv); } void sqlExecProgProfile(char *profile, char *prog, char **progArgs, int userArgc, char *userArgv[]) /* * Exec one of the sql programs using user and password defined in localDb.XXX variables from ~/.hg.conf * progArgs is NULL-terminate array of program-specific arguments to add, * which maybe NULL. userArgv are arguments passed in from the command line. * The program is execvp-ed, this function does not return. */ { -int i, j = 0, nargc=cntArgv(progArgs)+userArgc+6, extraFileNo; +int i, j = 0, nargc=cntArgv(progArgs)+userArgc+6, extraFileNo, returnStatus; pid_t child_id; char **nargv, extraFileName[256], extraFileArg[256], *homeDir; /* Assemble defaults file */ if ((homeDir = getenv("HOME")) == NULL) - errAbort("sqlExecProg: HOME is not defined in environment; cannot create temporary password file"); + errAbort("sqlExecProgProfile: HOME is not defined in environment; cannot create temporary password file"); safef(extraFileName, sizeof(extraFileName), "%s/.hgsql.cnfXXXXXX", homeDir); extraFileNo=sqlMakeExtraFile(extraFileName, profile, "client"); safef(extraFileArg, sizeof(extraFileArg), "--defaults-extra-file=%s", extraFileName); AllocArray(nargv, nargc); nargv[j++] = prog; nargv[j++] = extraFileArg; /* --defaults-extra-file must come before other options */ if (progArgs != NULL) { for (i = 0; progArgs[i] != NULL; i++) nargv[j++] = progArgs[i]; } for (i = 0; i < userArgc; i++) nargv[j++] = userArgv[i]; nargv[j++] = NULL; child_id = fork(); if (child_id == 0) { execvp(nargv[0], nargv); - _exit(1); + _exit(42); /* Why 42? Why not? Need something user defined that mysql isn't going to return */ } else { - /* Wait until the called process completes, then delete the temp file */ - wait(NULL); + /* Wait until the child process completes, then delete the temp file */ + wait(&returnStatus); unlink (extraFileName); + if (WIFEXITED(returnStatus)) + { + if (WEXITSTATUS(returnStatus) == 42) + errAbort("sqlExecProgProfile: exec failed"); + } + else + errAbort("sqlExecProgProfile: child process exited with abnormal status %d", returnStatus); } }