8 #define USERS_FILE "./users"
11 static int check_user_name (const char *name
)
16 if (!isalpha(name
[i
])) return 0;
18 for (i
= 1; name
[i
] != 0; i
++)
20 if (!isalnum(name
[i
])) return 0;
30 * str must be 0-terminated
31 * NB! content of str will be destroyed in the process
33 static int parse_user (user
*usr
, char *str
)
36 if ((s
= strstr(str
, ":")) == NULL
) return 0;
43 if ((s
= strstr(str
, ":")) == NULL
) return 0;
47 strncpy (usr
->name
, str
, USER_NAME_LEN
);
48 usr
->name
[USER_NAME_LEN
- 1] = 0;
51 if ((s
= strstr(str
, ":")) == NULL
) return 0;
55 strncpy (usr
->pass
, str
, USER_PASS_LEN
);
56 usr
->name
[USER_PASS_LEN
- 1] = 0;
59 if ((s
= strstr(str
, "\n")) != NULL
) *s
= 0; // remove optional \n at the end
62 strncpy (usr
->email
, str
, USER_EMAIL_LEN
);
63 usr
->name
[USER_EMAIL_LEN
- 1] = 0;
73 * if user is not found usr will be filled with garbage
74 * and also if max_id is not NULL, it will contain max encountered user id
76 static int find_user (const char *name
, user
*usr
, FILE *f
, int *max_id
)
85 if (fgets(buf
, BUF_SZ
, f
) == NULL
) break;
87 // skip comments and empty lines
88 if (buf
[0] == '#' || buf
[0] == 0) continue;
90 if (!parse_user(usr
, buf
))
95 // logins are case-insensitive
96 if (strcasecmp(name
, usr
->name
) == 0) return usr
->id
;
99 if (usr
->id
> m
) m
= usr
->id
;
102 if (max_id
!= NULL
) *max_id
= m
;
108 int add_user (user
*usr
, const char *name
, const char *pass
, const char *email
)
113 if (!check_user_name(name
)) return -1;
115 f
= fopen(USERS_FILE
, "r+");
116 if (f
== NULL
) return -2;
118 // lock file to block access from other threads
119 if (lockf(fileno(f
), F_LOCK
, 0) != 0)
125 // user already exists
126 if (find_user(name
, usr
, f
, &id
))
135 strncpy (usr
->name
, name
, USER_NAME_LEN
);
136 usr
->name
[USER_NAME_LEN
- 1] = 0;
138 strncpy (usr
->pass
, pass
, USER_PASS_LEN
);
139 usr
->pass
[USER_PASS_LEN
- 1] = 0;
141 strncpy (usr
->email
, email
, USER_EMAIL_LEN
);
142 usr
->email
[USER_EMAIL_LEN
- 1] = 0;
144 // add user record to the file
145 fseek (f
, 0, SEEK_END
);
146 fprintf (f
, "%d:%s:%s:%s\n", usr
->id
, usr
->name
, usr
->pass
, usr
->email
);
155 int user_login (user
*usr
, const char *name
, const char *pass
)
161 f
= fopen(USERS_FILE
, "r+"); // r+ is needed for locking
162 if (f
== NULL
) return -2;
164 // lock file to block access from other threads
165 if (lockf(fileno(f
), F_LOCK
, 0) != 0)
171 id
= find_user(name
, usr
, f
, NULL
);
174 if (id
<= 0) return -4;
176 if (strcmp(pass
, usr
->pass
) != 0) return -5;