diff sqlickrypt.c @ 117:c08717cb7793

sqlickrypt: add getmail and setmail commands. Add the ability to retrieve and alter users' e-mail addresses, and clean up some of the code too.
author John "Elwin" Edwards <elwin@sdf.org>
date Wed, 18 Jul 2012 17:00:05 -0700
parents f275d816e857
children b1480488ce9d
line wrap: on
line diff
--- a/sqlickrypt.c	Mon Jul 16 14:52:04 2012 -0700
+++ b/sqlickrypt.c	Wed Jul 18 17:00:05 2012 -0700
@@ -9,6 +9,39 @@
 #define DATABASE "/dgldir/dgamelaunch.db"
 #define IBUFSIZE 200
 
+/* General idea for return status:
+ * 0: success
+ * 1: password check failed
+ * 2: username not found
+ * 3: database error
+ * 4: invalid input
+ */
+
+/* Opens the database and, less obviously, initializes a statement. */
+int opendb(sqlite3 **dbp, sqlite3_stmt **stmtp, char *query) {
+  int status;
+  status = sqlite3_open(DATABASE, dbp);
+  if (status) {
+    sqlite3_close(*dbp);
+    exit(3);
+  }
+  sqlite3_prepare_v2(*dbp, query, -1, stmtp, NULL);
+  if (*stmtp == NULL) {
+    sqlite3_close(*dbp);
+    exit(3);
+  }
+  return 0;
+}
+
+void cleanup(sqlite3 *db, sqlite3_stmt *stmt, int status) {
+  if (stmt)
+    sqlite3_finalize(stmt);
+  sqlite3_close(db);
+  if (status)
+    exit(status);
+  return;
+}
+
 int check(char *uname, char *pw) {
   char *pwhash, *comphash;
   char *query = "SELECT password FROM dglusers WHERE username=?;";
@@ -16,22 +49,10 @@
   sqlite3 *db;
   sqlite3_stmt *qstmt;
 
-  status = sqlite3_open(DATABASE, &db);
-  if (status) {
-    sqlite3_close(db);
-    return 3;
-  }
-  sqlite3_prepare_v2(db, query, -1, &qstmt, NULL);
-  if (qstmt == NULL) {
-    sqlite3_close(db);
-    return 3;
-  }
+  opendb(&db, &qstmt, query);
   status = sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
-  if (status) {
-    sqlite3_finalize(qstmt);
-    sqlite3_close(db);
-    return 3;
-  }
+  if (status)
+    cleanup(db, qstmt, 3);
   status = sqlite3_step(qstmt);
   if (status != SQLITE_ROW) {
     sqlite3_finalize(qstmt);
@@ -41,9 +62,7 @@
     return 3;
   }
   pwhash = strdup((char *) sqlite3_column_text(qstmt, 0));
-  /* Clean up */
-  sqlite3_finalize(qstmt);
-  sqlite3_close(db);
+  cleanup(db, qstmt, 0);
 
   /* Check the password */
   comphash = crypt(pw, pwhash);
@@ -62,22 +81,11 @@
   sqlite3 *db;
   sqlite3_stmt *qstmt;
 
-  status = sqlite3_open(DATABASE, &db);
-  if (status) {
-    sqlite3_close(db);
-    return 3;
-  }
+  opendb(&db, &qstmt, checkquery);
   /* Check for existing account in the same transaction with creating it. */
   status = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
-  if (status) {
-    sqlite3_close(db);
-    return 3;
-  }
-  sqlite3_prepare_v2(db, checkquery, -1, &qstmt, NULL);
-  if (qstmt == NULL) {
-    sqlite3_close(db);
-    return 3;
-  }
+  if (status)
+    cleanup(db, qstmt, 3);
   sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
   status = sqlite3_step(qstmt);
   if (status != SQLITE_DONE) {
@@ -90,51 +98,98 @@
   /* The username doesn't exist yet, so create a new account. */
   sqlite3_finalize(qstmt);
   sqlite3_prepare_v2(db, addquery, -1, &qstmt, NULL);
-  if (qstmt == NULL) {
-    sqlite3_close(db);
-    return 3;
-  }
+  if (qstmt == NULL)
+    cleanup(db, NULL, 3);
   sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
   sqlite3_bind_text(qstmt, 2, strdup(crypt(pw, pw)), -1, free);
   sqlite3_bind_text(qstmt, 3, email, -1, SQLITE_TRANSIENT);
   status = sqlite3_step(qstmt);
-  if (status != SQLITE_DONE) {
-    sqlite3_finalize(qstmt);
-    sqlite3_close(db);
-    return 3;
-  }
+  if (status != SQLITE_DONE)
+    cleanup(db, qstmt, 3);
   status = sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
-  sqlite3_finalize(qstmt);
-  sqlite3_close(db);
+  cleanup(db, qstmt, 0);
   return status;
 }
 
+int getmail(char *uname) {
+  char *mailquery = "SELECT email FROM dglusers WHERE username = ?;";
+  int status;
+  sqlite3 *db;
+  sqlite3_stmt *qstmt;
+
+  opendb(&db, &qstmt, mailquery);
+  status = sqlite3_bind_text(qstmt, 1, uname, -1, SQLITE_TRANSIENT);
+  if (status)
+    cleanup(db, qstmt, 3);
+  status = sqlite3_step(qstmt);
+  if (status != SQLITE_ROW) {
+    sqlite3_finalize(qstmt);
+    sqlite3_close(db);
+    if (status == SQLITE_DONE)
+      return 2; /* User not found */
+    return 3;
+  }
+  printf("%s\n", sqlite3_column_text(qstmt, 0));
+  cleanup(db, qstmt, 0);
+  return 0;
+}
+
+int setmail(char *uname, char *newmail) {
+  char *setquery = "UPDATE dglusers SET email = ? WHERE username = ?;";
+  sqlite3 *db;
+  sqlite3_stmt *qstmt;
+  int status;
+
+  opendb(&db, &qstmt, setquery);
+  status = sqlite3_bind_text(qstmt, 2, uname, -1, SQLITE_TRANSIENT);
+  if (status)
+    cleanup(db, qstmt, 3);
+  status = sqlite3_bind_text(qstmt, 1, newmail, -1, SQLITE_TRANSIENT);
+  if (status)
+    cleanup(db, qstmt, 3);
+  status = sqlite3_step(qstmt);
+  if (status != SQLITE_DONE)
+    cleanup(db, qstmt, 3);
+  cleanup(db, qstmt, 0);
+  return 0;
+}
+
 int main(int argc, char *argv[]) {
-  char ibuf[IBUFSIZE], *uname, *pw, *email;
+  char ibuf[IBUFSIZE], *uname, *line1, *line2;
   char *cptr; // Utility pointer
   int status;
 
   /* Read in the username and password */
   fgets(ibuf, IBUFSIZE, stdin);
   uname = ibuf;
-  pw = strchr(uname, '\n');
-  if (pw == NULL)
+  line1 = strchr(uname, '\n');
+  if (line1 == NULL)
     exit(4); /* Truncated */
-  *pw = '\0';
-  pw++;
-  fgets(pw, IBUFSIZE - (pw - ibuf), stdin);
-  if (pw[strlen(pw) - 1] == '\n')
-    pw[strlen(pw) - 1] = '\0';
-  else
-    exit(4); /* Truncated */
+  *line1 = '\0';
+  if (argc == 1 || strcmp(argv[1], "getmail")) {
+    line1++;
+    fgets(line1, IBUFSIZE - (line1 - ibuf), stdin);
+    if (line1[strlen(line1) - 1] == '\n')
+      line1[strlen(line1) - 1] = '\0';
+    else
+      exit(4); /* Truncated */
+  }
+  if (argc > 1 && !strcmp(argv[1], "setmail")) {
+    /* E-mail, sanitize */
+    for (cptr = line1; *cptr != '\0'; cptr++) {
+      if (!isalnum(*cptr) && !strchr("@._-", *cptr)) {
+        exit(4);
+      }
+    }
+  }
   if (argc > 1 && !strcmp(argv[1], "register")) {
-    email = pw + strlen(pw) + 1;
-    fgets(email, IBUFSIZE - (email - ibuf), stdin);
-    if (email[strlen(email) - 1] == '\n')
-      email[strlen(email) - 1] = '\0';
+    line2 = line1 + strlen(line1) + 1;
+    fgets(line2, IBUFSIZE - (line2 - ibuf), stdin);
+    if (line2[strlen(line2) - 1] == '\n')
+      line2[strlen(line2) - 1] = '\0';
     else
       exit(4);
-    for (cptr = email; *cptr != '\0'; cptr++) {
+    for (cptr = line2; *cptr != '\0'; cptr++) {
       if (!isalnum(*cptr) && !strchr("@._-", *cptr)) {
         exit(4);
       }
@@ -147,9 +202,15 @@
     }
   }
   if (argc == 1 || !strcmp(argv[1], "check"))
-    status = check(uname, pw);
+    status = check(uname, line1);
   else if (!strcmp(argv[1], "register")) {
-    status = insertuser(uname, pw, email);
+    status = insertuser(uname, line1, line2);
+  }
+  else if (!strcmp(argv[1], "getmail")) {
+    status = getmail(uname);
+  }
+  else if (!strcmp(argv[1], "setmail")) {
+    status = setmail(uname, line1);
   }
   else
     status = 127;