Fix coding rule violation
[platform/core/system/tizen-platform-config.git] / src / passwd.c
1 /*
2  * Copyright (C) 2013-2014 Intel Corporation.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors:
19  *       José Bollo <jose.bollo@open.eurogiciel.org>
20  *       Stéphane Desneux <stephane.desneux@open.eurogiciel.org>
21  *       Jean-Benoit Martin <jean-benoit.martin@open.eurogiciel.org>
22  *
23  */
24 #define _GNU_SOURCE
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <errno.h>
34
35 #include "heap.h"
36 #include "passwd.h"
37
38 #ifndef NOT_PASSWD_ONLY
39
40 #include "buffer.h"
41
42 /* index of fields */
43 enum { iname, ipasswd, iuid, igid, icmt, idir, ishell };
44
45 static const char pwfile[] = "/etc/passwd";
46 static struct buffer buffer;
47 static size_t pos, lengths[7];
48 static const char *starts[7];
49
50 #define is(s, i) (!strncmp(s, starts[i], lengths[i]) && !s[lengths[i]])
51
52 /* open the passwd file */
53 static int oppw()
54 {
55         pos = 0;
56         return buffer_create(&buffer, pwfile);
57 }
58
59 /* close the passwd file */
60 static void clpw()
61 {
62         buffer_destroy(&buffer);
63 }
64
65 /* read the passwd file */
66 static int rdpw()
67 {
68         int col = 0;
69         const char *head = buffer.buffer + pos;
70         const char *end = buffer.buffer + buffer.length;
71         while (head != end) {
72                 starts[col] = head;
73                 while (head != end && *head != ':' && *head != '\n') head++;
74                 lengths[col] = head - starts[col];
75                 col++;
76                 if (col == 7) {
77                         if (head == end) {
78                                 pos = head - buffer.buffer;
79                                 return 1;
80                         }
81                         if (*head == '\n') {
82                                 head++;
83                                 pos = head - buffer.buffer;
84                                 return 1;
85                         }
86                         while (head != end && *head != '\n') head++;
87                         if (head != end) head++;
88                         col = 0;
89                 } else {
90                         if (head != end) {
91                                 if (*head++ == '\n')
92                                         col = 0;
93                         }
94                 }
95         }
96         pos = head - buffer.buffer;
97         return 0;
98 }
99
100 int pw_get(struct heap *heap, struct pwget **items)
101 {
102         size_t user, home;
103         int result;
104         int i, n, s;
105
106         for (n = 0 ; items[n] != NULL ; n++)
107                 items[n]->set = 0;
108
109         result = oppw();
110         if (result == 0) {
111                 s = n;
112                 while (s && rdpw()) {
113                         user = home = HNULL;
114                         for (i = 0 ; i < n ; i++) {
115                                 if (!items[i]->set && is(items[i]->id, iuid)) {
116                                         if (user == HNULL) {
117                                                 user = heap_strndup(heap,
118                                                                                         starts[iname], lengths[iname]);
119                                                 home = heap_strndup(heap,
120                                                                                         starts[idir], lengths[idir]);
121                                         }
122                                         items[i]->set = 1;
123                                         items[i]->user = user;
124                                         items[i]->home = home;
125                                         s--;
126                                 }
127                         }
128                 }
129                 clpw();
130         }
131         return result;
132 }
133
134 int pw_has_uid(uid_t uid)
135 {
136         if (oppw() == 0) {
137                 while (rdpw()) {
138                         if (lengths[iuid] && (int)uid == atoi(starts[iuid])) {
139                                 clpw();
140                                 return 1;
141                         }
142                 }
143                 clpw();
144         }
145         return 0;
146 }
147
148 int pw_get_uid(const char *name, uid_t *uid)
149 {
150         int result = oppw();
151         if (result == 0) {
152                 while (rdpw()) {
153                         if (is(name, iname)) {
154                                 *uid = (uid_t)atoi(starts[iuid]);
155                                 clpw();
156                                 return 0;
157                         }
158                 }
159                 clpw();
160                 result = -1;
161                 errno = EEXIST;
162         }
163         return result;
164 }
165
166 int pw_get_gid(const char *name, gid_t *gid)
167 {
168         int result = oppw();
169         if (result == 0) {
170                 while (rdpw()) {
171                         if (is(name, iname)) {
172                                 *gid = (gid_t)atoi(starts[igid]);
173                                 clpw();
174                                 return 0;
175                         }
176                 }
177                 clpw();
178                 result = -1;
179                 errno = EEXIST;
180         }
181         return result;
182 }
183
184 #else
185
186 #include <pwd.h>
187
188 #define BUFSIZE  4096
189
190 int pw_get(struct heap *heap, struct pwget **items)
191 {
192         char buffer[BUFSIZE];
193         struct passwd entry, *pe;
194         int result;
195         int n;
196         uid_t id;
197
198         for (n = 0 ; items[n] != NULL ; n++) {
199                 id = (uid_t)atoi(items[n]->id);
200                 result = getpwuid_r(id, &entry, buffer, sizeof buffer, &pe);
201                 if (result != 0) {
202                         while (items[n] != NULL) items[n++]->set = 0;
203                         return result;
204                 }
205                 if (pe == NULL)
206                         items[n]->set = 0;
207                 else {
208                         items[n]->set = 1;
209                         items[n]->user = heap_strdup(heap, pe->pw_name);
210                         items[n]->home = heap_strdup(heap, pe->pw_dir);
211                 }
212         }
213         return 0;
214 }
215
216 int pw_has_uid(uid_t uid)
217 {
218         char buffer[BUFSIZE];
219         struct passwd entry, *pe;
220         int result;
221
222         result = getpwuid_r(uid, &entry, buffer, sizeof buffer, &pe);
223         return !result && pe;
224 }
225
226 int pw_get_uid(const char *name, uid_t *uid)
227 {
228         char buffer[BUFSIZE];
229         struct passwd entry, *pe;
230         int result = getpwnam_r(name, &entry, buffer, sizeof buffer, &pe);
231         if (result == 0) {
232                 if (pe == NULL) {
233                         errno = EEXIST;
234                         result = -1;
235                 } else {
236                         *uid = entry.pw_uid;
237                 }
238         }
239         return result;
240 }
241
242 int pw_get_gid(const char *name, gid_t *gid)
243 {
244         char buffer[BUFSIZE];
245         struct passwd entry, *pe;
246         int result = getpwnam_r(name, &entry, buffer, sizeof buffer, &pe);
247         if (result == 0) {
248                 if (pe == NULL) {
249                         errno = EEXIST;
250                         result = -1;
251                 } else {
252                         *gid = entry.pw_gid;
253                 }
254         }
255         return result;
256 }
257
258 #endif
259
260 #ifdef TEST_PASSWD
261 #include <stdio.h>
262 int main(int argc, char**argv)
263 {
264         struct heap heap;
265         enum { uid, gid, names } action = uid;
266         heap_create(&heap, 1000);
267         while (*++argv) {
268                 if (!strcmp(*argv, "-u"))
269                         action = uid;
270                 else if (!strcmp(*argv, "-g"))
271                         action = gid;
272                 else if (!strcmp(*argv, "-n"))
273                         action = names;
274                 else if (action == uid) {
275                         uid_t u = 0;
276                         int sts = pw_get_uid(*argv, &u);
277                         printf("uid(%s)=%d [%d]\n", *argv, (int)u, sts);
278                 } else if (action == gid) {
279                         gid_t g = 0;
280                         int sts = pw_get_gid(*argv, &g);
281                         printf("gid(%s)=%d [%d]\n", *argv, (int)g, sts);
282                 } else if (action == names) {
283                         struct pwget pw = { .id = *argv }, *ppw[2] = { &pw, NULL };
284                         int sts = pw_get(&heap, ppw);
285                         printf("names(%s) set=%d", *argv, pw.set);
286                         if (pw.set) {
287                                 printf(" name=%s home=%s",
288                                         pw.user == HNULL ? "(null)"
289                                                                         : (char*)heap_address(&heap, pw.user),
290                                         pw.home == HNULL ? "(null)"
291                                                                         : (char*)heap_address(&heap, pw.home));
292                         }
293                         printf(" [%d]\n", sts);
294                 }
295         }
296         return 0;
297 }
298 #endif
299
300