9b9e2d57d6dd7ce3d5103a20d42a7627d3a8858b
[tpg/opendispense2.git] / src / cokebank_basic / bank.c
1 /*
2  * OpenDispense 2
3  * UCC (University [of WA] Computer Club) Electronic Accounting System
4  * - Cokebank (Basic Version)
5  *
6  * bank.c - Actual bank database
7  *
8  * This file is licenced under the 3-clause BSD Licence. See the file COPYING
9  * for full details.
10  */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <limits.h>
15 #include <pwd.h>
16 #include <grp.h>
17 #include "common.h"
18
19 #define USE_UNIX_GROUPS 1
20
21 // === PROTOTYPES ===
22 static int      GetUnixID(const char *Username);
23
24 // === GLOBALS ===
25 tUser   *gaBank_Users;
26  int    giBank_NumUsers;
27 FILE    *gBank_File;
28
29 // === CODE ===
30 int Bank_GetUserByName(const char *Username)
31 {
32          int    i, uid;
33         
34         uid = GetUnixID(Username);
35         
36         // Expensive search :(
37         for( i = 0; i < giBank_NumUsers; i ++ )
38         {
39                 if( gaBank_Users[i].UnixID == uid )
40                         return i;
41         }
42
43         return -1;
44 }
45
46 int Bank_GetUserBalance(int ID)
47 {
48         if( ID < 0 || ID >= giBank_NumUsers )
49                 return INT_MIN;
50
51         return gaBank_Users[ID].Balance;
52 }
53
54 int Bank_GetUserFlags(int ID)
55 {
56         if( ID < 0 || ID >= giBank_NumUsers )
57                 return -1;
58                 
59         // TODO: Implement checking the PAM groups and status instead, then
60         // fall back on the database. (and update if there is a difference)
61
62         // root
63         if( gaBank_Users[ID].UnixID == 0 ) {
64                 gaBank_Users[ID].Flags &= ~USER_FLAG_TYPEMASK;
65                 gaBank_Users[ID].Flags |= USER_TYPE_WHEEL;
66         }
67
68         #if USE_UNIX_GROUPS
69         if( gaBank_Users[ID].UnixID > 0 )
70         {
71                 struct passwd   *pwd;
72                 struct group    *grp;
73                  int    i;
74                 
75                 // Get username
76                 pwd = getpwuid( gaBank_Users[ID].UnixID );
77                 
78                 // Check for additions to the "coke" group
79                 grp = getgrnam("coke");
80                 if( grp ) {
81                         for( i = 0; grp->gr_mem[i]; i ++ )
82                         {
83                                 if( strcmp(grp->gr_mem[i], pwd->pw_name) == 0 )
84                                 {
85                                         gaBank_Users[ID].Flags &= ~USER_FLAG_TYPEMASK;
86                                         gaBank_Users[ID].Flags |= USER_TYPE_COKE;
87                                 }
88                         }
89                 }
90                 
91                 // Check for additions to the "wheel" group
92                 grp = getgrnam("wheel");
93                 if( grp ) {
94                         for( i = 0; grp->gr_mem[i]; i ++ )
95                         {
96                                 if( strcmp(grp->gr_mem[i], pwd->pw_name) == 0 )
97                                 {
98                                         gaBank_Users[ID].Flags &= ~USER_FLAG_TYPEMASK;
99                                         gaBank_Users[ID].Flags |= USER_TYPE_WHEEL;
100                                 }
101                         }
102                 }
103         }
104         #endif
105
106         return gaBank_Users[ID].Flags;
107 }
108
109 int Bank_AlterUserBalance(int ID, int Delta)
110 {
111         // Sanity
112         if( ID < 0 || ID >= giBank_NumUsers )
113                 return -1;
114
115         // Update
116         gaBank_Users[ID].Balance += Delta;
117
118         // Commit
119         fseek(gBank_File, ID*sizeof(gaBank_Users[0]), SEEK_SET);
120         fwrite(&gaBank_Users[ID], sizeof(gaBank_Users[0]), 1, gBank_File);
121         
122         return 0;
123 }
124
125 int Bank_SetUserBalance(int ID, int Value)
126 {
127         // Sanity
128         if( ID < 0 || ID >= giBank_NumUsers )
129                 return -1;
130
131         // Update
132         gaBank_Users[ID].Balance = Value;
133         
134         // Commit
135         fseek(gBank_File, ID*sizeof(gaBank_Users[0]), SEEK_SET);
136         fwrite(&gaBank_Users[ID], sizeof(gaBank_Users[0]), 1, gBank_File);
137         
138         return 0;
139 }
140
141 int Bank_GetMinAllowedBalance(int ID)
142 {
143         if( ID < 0 || ID >= giBank_NumUsers )
144                 return 0;
145
146         switch( Bank_GetUserFlags(ID) & USER_FLAG_TYPEMASK )
147         {
148         case USER_TYPE_NORMAL:  return      0;
149         case USER_TYPE_COKE:    return  -2000;
150         case USER_TYPE_WHEEL:   return -10000;
151         case USER_TYPE_GOD:     return INT_MIN;
152         default:        return 0;
153         }
154 }
155
156 /**
157  * \brief Create a new user in our database
158  */
159 int Bank_AddUser(const char *Username)
160 {
161         void    *tmp;
162          int    uid = GetUnixID(Username);
163
164         // Can has moar space plz?
165         tmp = realloc(gaBank_Users, (giBank_NumUsers+1)*sizeof(gaBank_Users[0]));
166         if( !tmp )      return -1;
167         gaBank_Users = tmp;
168
169         // Crete new user
170         gaBank_Users[giBank_NumUsers].UnixID = uid;
171         gaBank_Users[giBank_NumUsers].Balance = 0;
172         gaBank_Users[giBank_NumUsers].Flags = 0;
173         
174         if( strcmp(Username, COKEBANK_DEBT_ACCT) == 0 ) {
175                 gaBank_Users[giBank_NumUsers].Flags = USER_TYPE_GOD;    // No minium
176         }
177         else if( strcmp(Username, "root") == 0 ) {
178                 gaBank_Users[giBank_NumUsers].Flags = USER_TYPE_GOD;    // No minium
179         }
180         
181         // Commit to file
182         fseek(gBank_File, giBank_NumUsers*sizeof(gaBank_Users[0]), SEEK_SET);
183         fwrite(&gaBank_Users[giBank_NumUsers], sizeof(gaBank_Users[0]), 1, gBank_File);
184
185         // Increment count
186         giBank_NumUsers ++;
187
188         return 0;
189 }
190
191 // ---
192 // Unix user dependent code
193 // TODO: Modify to keep its own list of usernames
194 // ---
195 char *Bank_GetUserName(int ID)
196 {
197         struct passwd   *pwd;
198         
199         if( ID < 0 || ID >= giBank_NumUsers )
200                 return NULL;
201         
202         if( gaBank_Users[ID].UnixID == -1 )
203                 return strdup(COKEBANK_SALES_ACCT);
204
205         if( gaBank_Users[ID].UnixID == -2 )
206                 return strdup(COKEBANK_DEBT_ACCT);
207
208         pwd = getpwuid(gaBank_Users[ID].UnixID);
209         if( !pwd )      return NULL;
210
211         return strdup(pwd->pw_name);
212 }
213
214 static int GetUnixID(const char *Username)
215 {
216          int    uid;
217
218         if( strcmp(Username, COKEBANK_SALES_ACCT) == 0 ) {      // Pseudo account that sales are made into
219                 uid = -1;
220         }
221         else if( strcmp(Username, COKEBANK_DEBT_ACCT) == 0 ) {  // Pseudo acount that money is added from
222                 uid = -2;
223         }
224         else {
225                 struct passwd   *pwd;
226                 // Get user ID
227                 pwd = getpwnam(Username);
228                 if( !pwd )      return -1;
229                 uid = pwd->pw_uid;
230         }
231         return uid;
232 }

UCC git Repository :: git.ucc.asn.au