+int Bank_int_GetMinAllowedBalance(int ID)
+{
+ int flags;
+ if( ID < 0 || ID >= giBank_NumUsers )
+ return 0;
+
+ flags = Bank_GetFlags(ID);
+
+ // Internal accounts have no limit
+ if( (flags & USER_FLAG_INTERNAL) )
+ return INT_MIN;
+
+ // Wheel is allowed to go to -$100
+ if( (flags & USER_FLAG_ADMIN) )
+ return -10000;
+
+ // Coke is allowed to go to -$20
+ if( (flags & USER_FLAG_COKE) )
+ return -2000;
+
+ // For everyone else, no negative
+ return 0;
+}
+
+/*
+ * Create a new user in our database
+ */
+int Bank_int_AddUser(const char *Username)
+{
+ void *tmp;
+ int uid = Bank_int_GetUnixID(Username);
+
+ // Can has moar space plz?
+ // - Structures
+ tmp = realloc(gaBank_Users, (giBank_NumUsers+1)*sizeof(gaBank_Users[0]));
+ if( !tmp ) return -1;
+ gaBank_Users = tmp;
+ // - Name index
+ tmp = realloc(gaBank_UsersByName, (giBank_NumUsers+1)*sizeof(tUser*));
+ if( !tmp ) return -1;
+ gaBank_UsersByName = tmp;
+ // - Balance index
+ tmp = realloc(gaBank_UsersByBalance, (giBank_NumUsers+1)*sizeof(tUser*));
+ if( !tmp ) return -1;
+ gaBank_UsersByBalance = tmp;
+
+ // Crete new user
+ gaBank_Users[giBank_NumUsers].Name = NULL;
+ gaBank_Users[giBank_NumUsers].UnixID = uid;
+ gaBank_Users[giBank_NumUsers].Balance = 0;
+ gaBank_Users[giBank_NumUsers].Flags = 0;
+ gaBank_UsersByName[giBank_NumUsers] = &gaBank_Users[giBank_NumUsers];
+ gaBank_UsersByBalance[giBank_NumUsers] = &gaBank_Users[giBank_NumUsers];
+
+ // Set default flags
+ if( strcmp(Username, COKEBANK_DEBT_ACCT) == 0 ) {
+ gaBank_Users[giBank_NumUsers].Flags = USER_FLAG_INTERNAL;
+ }
+ else if( strcmp(Username, COKEBANK_SALES_ACCT) == 0 ) {
+ gaBank_Users[giBank_NumUsers].Flags = USER_FLAG_INTERNAL;
+ }
+ else if( strcmp(Username, "root") == 0 ) {
+ gaBank_Users[giBank_NumUsers].Flags = USER_FLAG_ADMIN|USER_FLAG_COKE;
+ }
+
+ // Increment count
+ giBank_NumUsers ++;
+
+ // Get name
+ gaBank_Users[giBank_NumUsers-1].Name = Bank_GetAcctName(giBank_NumUsers-1);
+
+ // Update indexes
+ qsort(gaBank_UsersByName, giBank_NumUsers, sizeof(tUser*), Bank_int_CompareNames);
+ qsort(gaBank_UsersByBalance, giBank_NumUsers, sizeof(tUser*), Bank_int_CompareBalance);
+
+ // Save
+ Bank_int_WriteEntry(giBank_NumUsers - 1);
+
+ return 0;
+}
+
+// ---
+// Unix user dependent code
+// TODO: Modify to keep its own list of usernames
+// ---
+char *Bank_GetAcctName(int ID)
+{
+ struct passwd *pwd;
+
+ if( ID < 0 || ID >= giBank_NumUsers )
+ return NULL;
+
+ if( gaBank_Users[ID].Name ) {
+ return strdup(gaBank_Users[ID].Name);
+ }
+
+ if( gaBank_Users[ID].UnixID == -1 )
+ return strdup(COKEBANK_SALES_ACCT);
+
+ if( gaBank_Users[ID].UnixID == -2 )
+ return strdup(COKEBANK_DEBT_ACCT);
+
+ pwd = getpwuid(gaBank_Users[ID].UnixID);
+ if( !pwd ) return NULL;
+
+ return strdup(pwd->pw_name);
+}
+
+int Bank_int_GetUnixID(const char *Username)
+{
+ int uid;
+
+ if( strcmp(Username, COKEBANK_SALES_ACCT) == 0 ) { // Pseudo account that sales are made into
+ uid = -1;
+ }
+ else if( strcmp(Username, COKEBANK_DEBT_ACCT) == 0 ) { // Pseudo acount that money is added from
+ uid = -2;
+ }
+ else {
+ struct passwd *pwd;
+ // Get user ID
+ pwd = getpwnam(Username);
+ if( !pwd ) return -1;
+ uid = pwd->pw_uid;
+ }
+ return uid;
+}
+
+
+/*
+ * Authenticate a user