0b58e5e9f51f08b8f4dab0c5b363265d401cd6d5
jcasper
  Mon Aug 19 18:20:44 2013 -0700
Placed all config values in temp file instead of just password, propagated change to related functions
diff --git src/hg/lib/sqlProg.c src/hg/lib/sqlProg.c
index 8a02e8a..636e0eb 100644
--- src/hg/lib/sqlProg.c
+++ src/hg/lib/sqlProg.c
@@ -1,160 +1,203 @@
 /* sqlProg - functions for building command line programs to deal with
  * sql databases.*/
 #include "common.h"
 #include "sqlProg.h"
 #include "hgConfig.h"
 #include <sys/types.h>
 #include <sys/wait.h>
 
 static int cntArgv(char **argv)
 /* count number of elements in a null terminated vector of strings. 
  * NULL is considered empty */
 {
 if (argv == NULL)
     return 0;
 else
     {
     int i;
     for (i = 0; argv[i] != NULL; i++)
         continue;
     return i;
     }
 }
 
 
-int sqlMakePassFile(char* passFileName)
-/* Create a password file in the supplied directory to be passed to
- * mysql with --defaults-extra-file.  Writes a mysql options set using
- * the profile [client] and the password from cfgVal("db.password").
- * passFileName cannot be static, and the last 6 characters should
+int sqlMakeExtraFile(char* extraFileName, char* profile, char* group)
+/* Create a temporary file in the supplied directory to be passed to
+ * mysql with --defaults-extra-file.  Writes a mysql options set for
+ * the mysql group [group] with the profile.host, profile.user, and
+ * profile.password values returned from cfgVal().  If group is not
+ * client or mysql, a --defaults-group-suffix=group must be passed to
+ * mysql to actually invoke the settings.
+ * passFileName cannot be static, and the last 6 characters must
  * be XXXXXX.  Those characters will be modified to form a unique suffix.
- * Returns the file descriptor of the password file */
-/* This should later be modified to accept a profile argument, to select
- * which profile the password (and other options?) comes from */
+ * Returns a file descriptor for the file or dies with an error */
 {
-int passFileNo;
-char passFileData[256];
-
-if ((passFileNo=mkstemp(passFileName)) == -1)
-    errAbort("Could not create unique temporary file %s", passFileName);
-safef(passFileData, sizeof(passFileData), "[client]\npassword=%s", cfgVal("db.password"));
-if (write (passFileNo, passFileData, strlen(passFileData)) == -1)
-    errAbort("Writing to temporary file %s failed with errno %d", passFileName, errno);
-return passFileNo;
+int fileNo;
+char paddedGroup [256]; /* string with brackets around the group name */
+char fileData[256];  /* constructed variable=value data for the mysql config file */
+char field[256];  /* constructed profile.field name to pass to cfgVal */
+
+if ((fileNo=mkstemp(extraFileName)) == -1)
+    errAbort("sqlMakeExtraFile: Could not create unique temporary file %s", extraFileName);
+
+/* write out the group name, user, host, and password */
+safef(paddedGroup, sizeof(paddedGroup), "[%s]\n", group);
+if (write (fileNo, paddedGroup, strlen(paddedGroup)) == -1)
+    errAbort("sqlMakeExtraFile: Writing group to temporary file %s failed with errno %d", extraFileName, errno);
+
+safef(field, sizeof(field), "%s.host", profile);
+safef(fileData, sizeof(fileData), "host=%s\n", cfgVal(field));
+if (write (fileNo, fileData, strlen(fileData)) == -1)
+    errAbort("sqlMakeExtraFile: Writing host to temporary file %s failed with errno %d", extraFileName, errno);
+
+safef(field, sizeof(field), "%s.user", profile);
+safef(fileData, sizeof(fileData), "user=%s\n", cfgVal(field));
+if (write (fileNo, fileData, strlen(fileData)) == -1)
+    errAbort("sqlMakeExtraFile: Writing user to temporary file %s failed with errno %d", extraFileName, errno);
+
+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, passFileNo;
+int i, j = 0, nargc=cntArgv(progArgs)+userArgc+6, extraFileNo;
 pid_t child_id;
-char **nargv, passArg[256], hostArg[128], *homeDir, passFileName[256];
+char **nargv, extraFileArg[256], *homeDir, extraFileName[256];
 
 /* Assemble defaults file */
 if ((homeDir = getenv("HOME")) == NULL)
-    errAbort("HOME is not defined in environment; cannot create temporary password file");
-safef(passFileName, sizeof(passFileName), "%s/.hgsql.cnfXXXXXX", homeDir);
-passFileNo=sqlMakePassFile(passFileName);
-safef(passArg, sizeof(passArg), "--defaults-extra-file=%s", passFileName);
+    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);
 
-safef(hostArg, sizeof(hostArg), "-h%s", cfgVal("db.host"));
 AllocArray(nargv, nargc);
 
 nargv[j++] = prog;
-/* --defaults-extra-file must come before other options */
-nargv[j++] = passArg;
-nargv[j++] = "-u";
-nargv[j++] = cfgVal("db.user");
-nargv[j++] = hostArg;
+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);
-    errnoAbort("exec of %s failed with errno %d", nargv[0], errno);
+    _exit(1);
     }
 else
     {
     /* Wait until the called process completes, then delete the temp file */
     wait(NULL);
-    unlink (passFileName);
+    unlink (extraFileName);
     }
 }
 
 
 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;
-char **nargv, passArg[128], hostArg[128];
-safef(passArg, sizeof(passArg), "-p%s", cfgOption("localDb.password"));
-safef(hostArg, sizeof(hostArg), "-h%s", cfgOption("localDb.host"));
+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++] = "-u";
-nargv[j++] = cfgOption("localDb.user");
-nargv[j++] = passArg;
-nargv[j++] = hostArg;
+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);
-errnoAbort("exec of %s failed", nargv[0]);
+    _exit(1);
+    }
+else
+    {
+    /* Wait until the called process completes, then delete the temp file */
+    wait(NULL);
+    unlink (extraFileName);
+    }
 }
 
 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;
-char **nargv, passArg[128], hostArg[128], optionStr[128];
-safef(optionStr, sizeof(optionStr), "%s.password", profile);
-safef(passArg, sizeof(passArg), "-p%s", cfgOption(optionStr));
-safef(optionStr, sizeof(optionStr), "%s.host", profile);
-safef(hostArg, sizeof(hostArg), "-h%s", cfgOption(optionStr));
+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, profile, "client");
+safef(extraFileArg, sizeof(extraFileArg), "--defaults-extra-file=%s", extraFileName);
+
 AllocArray(nargv, nargc);
 
 nargv[j++] = prog;
-nargv[j++] = "-u";
-safef(optionStr, sizeof(optionStr), "%s.user", profile);
-nargv[j++] = cfgOption(optionStr);
-nargv[j++] = passArg;
-nargv[j++] = hostArg;
+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);
-errnoAbort("exec of %s failed", nargv[0]);
+    _exit(1);
+    }
+else
+    {
+    /* Wait until the called process completes, then delete the temp file */
+    wait(NULL);
+    unlink (extraFileName);
+    }
 }