+ char *buf;
+ int responseCode;
+
+ char *arrayType;
+ int count, i;
+ regmatch_t matches[4];
+
+ // Ask server for stock list
+ send(Socket, "ENUM_ITEMS\n", 11, 0);
+ buf = ReadLine(Socket);
+
+ //printf("Output: %s\n", buf);
+
+ responseCode = atoi(buf);
+ if( responseCode != 201 ) {
+ fprintf(stderr, "Unknown response from dispense server (Response Code %i)\n", responseCode);
+ exit(RV_UNKNOWN_ERROR);
+ }
+
+ // - Get item list -
+
+ // Expected format:
+ // 201 Items <count>
+ // 202 Item <count>
+ RunRegex(&gArrayRegex, buf, 4, matches, "Malformed server response");
+
+ arrayType = &buf[ matches[2].rm_so ]; buf[ matches[2].rm_eo ] = '\0';
+ count = atoi( &buf[ matches[3].rm_so ] );
+
+ // Check array type
+ if( strcmp(arrayType, "Items") != 0 ) {
+ // What the?!
+ fprintf(stderr, "Unexpected array type, expected 'Items', got '%s'\n",
+ arrayType);
+ exit(RV_UNKNOWN_ERROR);
+ }
+ free(buf);
+
+ giNumItems = count;
+ gaItems = malloc( giNumItems * sizeof(tItem) );
+
+ // Fetch item information
+ for( i = 0; i < giNumItems; i ++ )
+ {
+ ReadItemInfo( Socket, &gaItems[i] );
+ }
+
+ // Read end of list
+ buf = ReadLine(Socket);
+ responseCode = atoi(buf);
+
+ if( responseCode != 200 ) {
+ fprintf(stderr, "Unknown response from dispense server %i\n'%s'",
+ responseCode, buf
+ );
+ exit(-1);
+ }
+
+ free(buf);
+}
+
+
+/**
+ * \brief Get information on an item
+ * \return Boolean Failure
+ */
+int Dispense_ItemInfo(int Socket, const char *Type, int ID)
+{
+ tItem item;
+ int ret;
+
+ // Query
+ sendf(Socket, "ITEM_INFO %s:%i\n", Type, ID);
+
+ ret = ReadItemInfo(Socket, &item);
+ if(ret) return ret;
+
+ printf("%8s:%-2i %2i.%02i %s\n",
+ item.Type, item.ID,
+ item.Price/100, item.Price%100,
+ item.Desc);
+
+ free(item.Type);
+ free(item.Desc);
+
+ return 0;
+}
+
+/**
+ * \brief Dispense an item
+ * \return Boolean Failure
+ */
+int DispenseItem(int Socket, const char *Type, int ID)
+{
+ int ret, responseCode;
+ char *buf;
+
+ // Check for a dry run
+ if( gbDryRun ) {
+ printf("Dry Run - No action\n");
+ return 0;
+ }
+
+ // Dispense!
+ sendf(Socket, "DISPENSE %s:%i\n", Type, ID);
+ buf = ReadLine(Socket);
+
+ responseCode = atoi(buf);
+ switch( responseCode )
+ {
+ case 200:
+ printf("Dispense OK\n");
+ ret = 0;
+ break;
+ case 401:
+ printf("Not authenticated\n");
+ ret = RV_PERMISSIONS;
+ break;
+ case 402:
+ printf("Insufficient balance\n");
+ ret = RV_BALANCE;
+ break;
+ case 406:
+ printf("Bad item name\n");
+ ret = RV_BAD_ITEM;
+ break;
+ case 500:
+ printf("Item failed to dispense, is the slot empty?\n");
+ ret = RV_SERVER_ERROR;
+ break;
+ case 501:
+ printf("Dispense not possible (slot empty/permissions)\n");
+ ret = RV_SERVER_ERROR;
+ break;
+ default:
+ printf("Unknown response code %i ('%s')\n", responseCode, buf);
+ ret = RV_UNKNOWN_ERROR;
+ break;
+ }
+
+ free(buf);
+ return ret;
+}
+
+/**
+ * \brief Alter a user's balance
+ */
+int Dispense_AlterBalance(int Socket, const char *Username, int Ammount, const char *Reason)
+{
+ char *buf;
+ int responseCode, rv = -1;
+
+ // Check for a dry run
+ if( gbDryRun ) {
+ printf("Dry Run - No action\n");
+ return 0;
+ }
+
+ // Sanity
+ if( Ammount == 0 ) {
+ printf("An amount would be nice\n");
+ return RV_ARGUMENTS;
+ }
+
+ sendf(Socket, "ADD %s %i %s\n", Username, Ammount, Reason);
+ buf = ReadLine(Socket);
+
+ responseCode = atoi(buf);
+
+ switch(responseCode)
+ {
+ case 200:
+ rv = 0; // OK
+ break;
+ case 402:
+ fprintf(stderr, "Insufficient balance\n");
+ rv = RV_BAD_ITEM;
+ break;
+ case 403: // Not in coke
+ fprintf(stderr, "You are not in coke (sucker)\n");
+ rv = RV_PERMISSIONS;
+ break;
+ case 404: // Unknown user
+ fprintf(stderr, "Unknown user '%s'\n", Username);
+ rv = RV_INVALID_USER;
+ break;
+ default:
+ fprintf(stderr, "Unknown response code %i\n'%s'\n", responseCode, buf);
+ rv = RV_UNKNOWN_RESPONSE;
+ break;
+ }
+ free(buf);
+
+ return rv;
+}
+
+/**
+ * \brief Set a user's balance
+ * \note Only avaliable to dispense admins
+ */
+int Dispense_SetBalance(int Socket, const char *Username, int Balance, const char *Reason)
+{
+ char *buf;
+ int responseCode;
+
+ // Check for a dry run
+ if( gbDryRun ) {
+ printf("Dry Run - No action\n");
+ return 0;
+ }
+
+ sendf(Socket, "SET %s %i %s\n", Username, Balance, Reason);
+ buf = ReadLine(Socket);
+
+ responseCode = atoi(buf);
+ free(buf);
+
+ switch(responseCode)
+ {
+ case 200: return 0; // OK
+ case 403: // Not in coke
+ fprintf(stderr, "You are not an admin\n");
+ return RV_PERMISSIONS;
+ case 404: // Unknown user
+ fprintf(stderr, "Unknown user '%s'\n", Username);
+ return RV_INVALID_USER;
+ default:
+ fprintf(stderr, "Unknown response code %i\n", responseCode);
+ return RV_UNKNOWN_RESPONSE;
+ }
+
+ return -1;
+}
+
+/**
+ * \brief Give money to another user
+ */
+int Dispense_Give(int Socket, const char *Username, int Ammount, const char *Reason)
+{
+ char *buf;