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);
     }
 }