abf5763711440fd8870d6b57e6ed49d3b8859029
[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_SetUserFlags(int ID, int Mask, int Value)
110 {
111         // Sanity
112         if( ID < 0 || ID >= giBank_NumUsers )
113                 return -1;
114         
115         // Silently ignore changes to root and meta accounts
116         if( gaBank_Users[ID].UnixID <= 0 )      return 0;
117         
118         gaBank_Users[ID].Flags &= Mask;
119         gaBank_Users[ID].Flags |= Value;
120         
121         return 0;
122 }
123
124 int Bank_AlterUserBalance(int ID, int Delta)
125 {
126         // Sanity
127         if( ID < 0 || ID >= giBank_NumUsers )
128                 return -1;
129
130         // Update
131         gaBank_Users[ID].Balance += Delta;
132
133         // Commit
134         fseek(gBank_File, ID*sizeof(gaBank_Users[0]), SEEK_SET);
135         fwrite(&gaBank_Users[ID], sizeof(gaBank_Users[0]), 1, gBank_File);
136         
137         return 0;
138 }
139
140 int Bank_SetUserBalance(int ID, int Value)
141 {
142         // Sanity
143         if( ID < 0 || ID >= giBank_NumUsers )
144                 return -1;
145
146         // Update
147         gaBank_Users[ID].Balance = Value;
148         
149         // Commit
150         fseek(gBank_File, ID*sizeof(gaBank_Users[0]), SEEK_SET);
151         fwrite(&gaBank_Users[ID], sizeof(gaBank_Users[0]), 1, gBank_File);
152         
153         return 0;
154 }
155
156 int Bank_GetMinAllowedBalance(int ID)
157 {
158         if( ID < 0 || ID >= giBank_NumUsers )
159                 return 0;
160
161         switch( Bank_GetUserFlags(ID) & USER_FLAG_TYPEMASK )
162         {
163         case USER_TYPE_NORMAL:  return      0;
164         case USER_TYPE_COKE:    return  -2000;
165         case USER_TYPE_WHEEL:   return -10000;
166         case USER_TYPE_GOD:     return INT_MIN;
167         default:        return 0;
168         }
169 }
170
171 /**
172  * \brief Create a new user in our database
173  */
174 int Bank_AddUser(const char *Username)
175 {
176         void    *tmp;
177          int    uid = GetUnixID(Username);
178
179         // Can has moar space plz?
180         tmp = realloc(gaBank_Users, (giBank_NumUsers+1)*sizeof(gaBank_Users[0]));
181         if( !tmp )      return -1;
182         gaBank_Users = tmp;
183
184         // Crete new user
185         gaBank_Users[giBank_NumUsers].UnixID = uid;
186         gaBank_Users[giBank_NumUsers].Balance = 0;
187         gaBank_Users[giBank_NumUsers].Flags = 0;
188         
189         if( strcmp(Username, COKEBANK_DEBT_ACCT) == 0 ) {
190                 gaBank_Users[giBank_NumUsers].Flags = USER_TYPE_GOD;    // No minium
191         }
192         else if( strcmp(Username, "root") == 0 ) {
193                 gaBank_Users[giBank_NumUsers].Flags = USER_TYPE_GOD;    // No minium
194         }
195         
196         // Commit to file
197         fseek(gBank_File, giBank_NumUsers*sizeof(gaBank_Users[0]), SEEK_SET);
198         fwrite(&gaBank_Users[giBank_NumUsers], sizeof(gaBank_Users[0]), 1, gBank_File);
199
200         // Increment count
201         giBank_NumUsers ++;
202
203         return 0;
204 }
205
206 // ---
207 // Unix user dependent code
208 // TODO: Modify to keep its own list of usernames
209 // ---
210 char *Bank_GetUserName(int ID)
211 {
212         struct passwd   *pwd;
213         
214         if( ID < 0 || ID >= giBank_NumUsers )
215                 return NULL;
216         
217         if( gaBank_Users[ID].UnixID == -1 )
218                 return strdup(COKEBANK_SALES_ACCT);
219
220         if( gaBank_Users[ID].UnixID == -2 )
221                 return strdup(COKEBANK_DEBT_ACCT);
222
223         pwd = getpwuid(gaBank_Users[ID].UnixID);
224         if( !pwd )      return NULL;
225
226         return strdup(pwd->pw_name);
227 }
228
229 static int GetUnixID(const char *Username)
230 {
231          int    uid;
232
233         if( strcmp(Username, COKEBANK_SALES_ACCT) == 0 ) {      // Pseudo account that sales are made into
234                 uid = -1;
235         }
236         else if( strcmp(Username, COKEBANK_DEBT_ACCT) == 0 ) {  // Pseudo acount that money is added from
237                 uid = -2;
238         }
239         else {
240                 struct passwd   *pwd;
241                 // Get user ID
242                 pwd = getpwnam(Username);
243                 if( !pwd )      return -1;
244                 uid = pwd->pw_uid;
245         }
246         return uid;
247 }

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