Index: trunk/ippTools/src/pstamptool.c
===================================================================
--- trunk/ippTools/src/pstamptool.c	(revision 38134)
+++ trunk/ippTools/src/pstamptool.c	(revision 38157)
@@ -61,6 +61,13 @@
 static bool deletefileMode(pxConfig *config);
 
+static bool adddomainMode(pxConfig * config);
+static bool updatedomainMode(pxConfig * config);
 static bool listdomainMode(pxConfig *config);
+static bool adduserMode(pxConfig * config);
+static bool updateuserMode(pxConfig * config);
 static bool listuserMode(pxConfig * config);
+static bool addaccesslevelMode(pxConfig * config);
+static bool updateaccesslevelMode(pxConfig * config);
+static bool listaccesslevelMode(pxConfig * config);
 
 # define MODECASE(caseName, func) \
@@ -114,6 +121,13 @@
         MODECASE(PSTAMPTOOL_MODE_DELETEFILE, deletefileMode);
 
+        MODECASE(PSTAMPTOOL_MODE_ADDDOMAIN, adddomainMode);
+        MODECASE(PSTAMPTOOL_MODE_UPDATEDOMAIN, updatedomainMode);
         MODECASE(PSTAMPTOOL_MODE_LISTDOMAIN, listdomainMode);
+        MODECASE(PSTAMPTOOL_MODE_ADDUSER, adduserMode);
+        MODECASE(PSTAMPTOOL_MODE_UPDATEUSER, updateuserMode);
         MODECASE(PSTAMPTOOL_MODE_LISTUSER, listuserMode);
+        MODECASE(PSTAMPTOOL_MODE_ADDACCESSLEVEL, addaccesslevelMode);
+        MODECASE(PSTAMPTOOL_MODE_UPDATEACCESSLEVEL, updateaccesslevelMode);
+        MODECASE(PSTAMPTOOL_MODE_LISTACCESSLEVEL, listaccesslevelMode);
 
         default:
@@ -1709,4 +1723,80 @@
 }
 
+static bool adddomainMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(domainName,      config->args, "-domain",  true, false);
+    PXOPT_LOOKUP_S32(accessLevel,     config->args, "-accessLevel", true, false);
+    PXOPT_LOOKUP_STR(defaultProduct,  config->args, "-defaultProduct",  false, false);
+    PXOPT_LOOKUP_STR(defaultLabel,    config->args, "-defaultLabel",  false, false);
+
+    if (!pstampUserDomainInsert(config->dbh,
+        domainName,
+        accessLevel,
+        defaultProduct,
+        defaultLabel
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "failed to insert domain");
+        return false;
+    }
+
+    return true;
+}
+static bool updatedomainMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(domainName,      config->args, "-domain",  true, false);
+    PXOPT_LOOKUP_S32(accessLevel,     config->args, "-accessLevel", false, false);
+    PXOPT_LOOKUP_STR(defaultProduct,  config->args, "-defaultProduct",  false, false);
+    PXOPT_LOOKUP_STR(defaultLabel,    config->args, "-defaultLabel",  false, false);
+
+    if (!accessLevel && !defaultProduct && !defaultLabel) {
+        psError(PS_ERR_UNKNOWN, true, "at least one set option is required");
+        return false;
+    }
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-domain",   "domainName", "==");
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = psStringCopy("UPDATE pstampUserDomain SET");
+
+    char * sep = "";
+    if (accessLevel) {
+        psStringAppend(&query, "%s accessLevel = '%d'", sep, accessLevel);
+        sep = ", ";
+    }
+    if (defaultProduct) {
+        psStringAppend(&query, "%s  defaultProduct = '%s'", sep, defaultProduct);
+        sep = ", ";
+    }
+    if (defaultLabel) {
+        psStringAppend(&query, "%s defaultLabel = '%s'", sep, defaultLabel);
+        sep = ", ";
+    }
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, "\nWHERE %s", whereClause);
+    psFree(whereClause);
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    // psU64 affected = psDBAffectedRows(config->dbh);
+    // psLogMsg("pstamptool", PS_LOG_INFO, "Updated %" PRIu64 " pstampRequests", affected);
+
+    return true;
+}
+
 static bool listdomainMode(pxConfig *config)
 {
@@ -1715,5 +1805,5 @@
     psMetadata *where = psMetadataAlloc();
     PXOPT_COPY_STR(config->args, where, "-domain", "domainName", "=");
-    PXOPT_COPY_S32(config->args, where, "-access_level", "accessLevel", "=");
+    PXOPT_COPY_S32(config->args, where, "-accessLevel", "accessLevel", "=");
 
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
@@ -1764,4 +1854,83 @@
     return true;
 }
+static bool adduserMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(userName,        config->args, "-user",  true, false);
+    PXOPT_LOOKUP_STR(domainName,      config->args, "-domain",  true, false);
+    PXOPT_LOOKUP_S32(accessLevel,     config->args, "-accessLevel", false, false);
+    PXOPT_LOOKUP_STR(defaultProduct,  config->args, "-defaultProduct",  false, false);
+    PXOPT_LOOKUP_STR(defaultLabel,    config->args, "-defaultLabel",  false, false);
+
+    if (!pstampUserInsert(config->dbh,
+        userName,
+        domainName,
+        accessLevel,
+        defaultProduct,
+        defaultLabel
+        )) {
+        psError(PS_ERR_UNKNOWN, false, "failed to insert user");
+        return false;
+    }
+
+    return true;
+}
+static bool updateuserMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(userName,        config->args, "-user",  true, false);
+    PXOPT_LOOKUP_STR(domainName,      config->args, "-domain",  true, false);
+    PXOPT_LOOKUP_S32(accessLevel,     config->args, "-accessLevel", false, false);
+    PXOPT_LOOKUP_STR(defaultProduct,  config->args, "-defaultProduct",  false, false);
+    PXOPT_LOOKUP_STR(defaultLabel,    config->args, "-defaultLabel",  false, false);
+
+    if (!accessLevel && !defaultProduct && !defaultLabel) {
+        psError(PS_ERR_UNKNOWN, true, "at least one set option is required");
+        return false;
+    }
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-user",     "userName", "==");
+    PXOPT_COPY_STR(config->args, where, "-domain",   "domainName", "==");
+    if (!psListLength(where->list)) {
+        psFree(where);
+        psError(PXTOOLS_ERR_CONFIG, false, "search parameters are required");
+        return false;
+    }
+
+    psString query = psStringCopy("UPDATE pstampUser SET");
+
+    char * sep = "";
+    if (accessLevel) {
+        psStringAppend(&query, "%s accessLevel = '%d'", sep, accessLevel);
+        sep = ", ";
+    }
+    if (defaultProduct) {
+        psStringAppend(&query, "%s  defaultProduct = '%s'", sep, defaultProduct);
+        sep = ", ";
+    }
+    if (defaultLabel) {
+        psStringAppend(&query, "%s defaultLabel = '%s'", sep, defaultLabel);
+        sep = ", ";
+    }
+
+    psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+    psStringAppend(&query, "\nWHERE %s", whereClause);
+    psFree(whereClause);
+    psFree(where);
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+
+    // psU64 affected = psDBAffectedRows(config->dbh);
+    // psLogMsg("pstamptool", PS_LOG_INFO, "Updated %" PRIu64 " pstampRequests", affected);
+
+    return true;
+}
 static bool listuserMode(pxConfig *config)
 {
@@ -1771,5 +1940,5 @@
     PXOPT_COPY_STR(config->args, where, "-user", "userName", "=");
     PXOPT_COPY_STR(config->args, where, "-domain", "domainName", "=");
-    PXOPT_COPY_S32(config->args, where, "-access_level", "pstampUser.accessLevel", "=");
+    PXOPT_COPY_S32(config->args, where, "-accessLevel", "pstampUser.accessLevel", "=");
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
     PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
@@ -1822,3 +1991,100 @@
     return true;
 }
+
+static bool addaccesslevelMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_S64(proj_id,         config->args, "-proj_id", false, false);
+    PXOPT_LOOKUP_STR(project_name,    config->args, "-project_name",  false, false);
+    PXOPT_LOOKUP_S32(accessLevel,     config->args, "-accessLevel", true, false);
+    PXOPT_LOOKUP_F32(mjd_min,         config->args, "-mjd_min", false, false);
+    PXOPT_LOOKUP_F32(mjd_max,         config->args, "-mjd_max", false, false);
+
+    if (proj_id) {
+        if (!pstampAccessLevelInsert(config->dbh,
+            proj_id,
+            accessLevel,
+            mjd_min,
+            mjd_max
+        )) {
+            psError(PS_ERR_UNKNOWN, false, "failed to insert accessLevel");
+            return false;
+        }
+    } else if (project_name) {
+        // use select insert getting proj_id from pstampProject
+        psString query = pxDataGet("pstamptool_addaccesslevel.sql");
+        if (!p_psDBRunQueryF(config->dbh, query, accessLevel, mjd_min, mjd_max, project_name)) {
+            psError(PS_ERR_UNKNOWN, false, "database error");
+            psFree(query);
+            return false;
+        }
+        psFree(query);
+    } else {
+        psError(PS_ERR_UNKNOWN, true, "proj_id or project_name is required");
+        return false;
+    }
+
+    return true;
+}
+static bool updateaccesslevelMode(pxConfig *config)
+{
+    return false;
+}
+static bool listaccesslevelMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-project_name", "pstampProject.name", "=");
+    PXOPT_COPY_S64(config->args, where, "-proj_id", "proj_id", "=");
+    PXOPT_COPY_S32(config->args, where, "-accessLevel", "accessLevel", "=");
+
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+
+    psString query = psStringCopy("SELECT * from pstampAccessLevel join pstampProject USING(proj_id)");
+
+    if (psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " WHERE %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psFree(output);
+        return true;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "pstampAccessLevel", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
 # endif
