version 1.0
[platform/core/system/tizen-platform-wrapper.git] / src / passwd.c
1 /*
2  * Copyright (C) 2013 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         }
90         else {
91             if (head != end) {
92                 if (*head++=='\n') 
93                     col = 0;
94             }
95         }
96     }
97     pos = head - buffer.buffer;
98     return 0;
99 }
100
101 int pw_get( struct heap *heap, struct pwget **items)
102 {
103     size_t user, home;
104     int result;
105     int i, n, s;
106
107     for( n = 0 ; items[n] != NULL ; n++ )
108         items[n]->set = 0;
109
110     result = oppw();
111     if (result == 0) {
112         s = n;
113         while (s && rdpw()) {
114             user = home = HNULL;
115             for( i = 0 ; i < n ; i++ ) {
116                 if (!items[i]->set && is(items[i]->id,iuid)) {
117                     if (user==HNULL) {
118                         user = heap_strndup( heap,
119                                             starts[iname], lengths[iname]);
120                         home = heap_strndup( heap,
121                                             starts[idir], lengths[idir]);
122                     }
123                     items[i]->set = 1;
124                     items[i]->user = user;
125                     items[i]->home = home;
126                     s--;
127                 }
128             }
129         }
130         clpw();
131     }
132     return result;
133 }
134
135 int pw_get_uid( const char *name, uid_t *uid)
136 {
137     int result = oppw();
138     if (result == 0) {
139         while (rdpw()) {
140             if (is(name,iname)) {
141                 *uid = (uid_t)atoi(starts[iuid]);
142                 clpw();
143                 return 0;
144             }
145         }
146         clpw();
147         result = -1;
148         errno = EEXIST;
149     }
150     return result;
151 }
152
153 int pw_get_gid( const char *name, gid_t *gid)
154 {
155     int result = oppw();
156     if (result == 0) {
157         while (rdpw()) {
158             if (is(name,iname)) {
159                 *gid = (gid_t)atoi(starts[igid]);
160                 clpw();
161                 return 0;
162             }
163         }
164         clpw();
165         result = -1;
166         errno = EEXIST;
167     }
168     return result;
169 }
170
171 #else
172
173 #include <pwd.h>
174
175 #define BUFSIZE  4096
176
177 int pw_get( struct heap *heap, struct pwget **items)
178 {
179     char buffer[BUFSIZE];
180     struct passwd entry, *pe;
181     int result;
182     int n;
183     uid_t id;
184
185     for( n = 0 ; items[n] != NULL ; n++ ) {
186         id = (uid_t)atoi(items[n]->id);
187         result = getpwuid_r( id, &entry, buffer, sizeof buffer, &pe);
188         if (result != 0) {
189             while(items[n] != NULL) items[n++]->set = 0;
190             return result;
191         }
192         if (pe == NULL) 
193             items[n]->set = 0;
194         else {
195             items[n]->set = 1;
196             items[n]->user = heap_strdup( heap, pe->pw_name);
197             items[n]->home = heap_strdup( heap, pe->pw_dir);
198         }
199     }
200     return 0;
201 }
202
203 int pw_get_uid( const char *name, uid_t *uid)
204 {
205     char buffer[BUFSIZE];
206     struct passwd entry, *pe;
207     int result = getpwnam_r( name, &entry, buffer, sizeof buffer, &pe);
208     if (result == 0) {
209         if (pe == NULL) {
210             errno = EEXIST;
211             result = -1;
212         }
213         else {
214             *uid = entry.pw_uid;
215         }
216     }
217     return result;
218 }
219
220 int pw_get_gid( const char *name, gid_t *gid)
221 {
222     char buffer[BUFSIZE];
223     struct passwd entry, *pe;
224     int result = getpwnam_r( name, &entry, buffer, sizeof buffer, &pe);
225     if (result == 0) {
226         if (pe == NULL) {
227             errno = EEXIST;
228             result = -1;
229         }
230         else {
231             *gid = entry.pw_gid;
232         }
233     }
234     return result;
235 }
236
237 #endif
238
239 #ifdef TEST_PASSWD
240 #include <stdio.h>
241 int main(int argc,char**argv) {
242     struct heap heap;
243     enum { uid, gid, names } action = uid;
244     heap_create(&heap,1000);
245     while(*++argv) {
246         if (!strcmp(*argv,"-u"))
247             action = uid;
248         else if (!strcmp(*argv,"-g"))
249             action = gid;
250         else if (!strcmp(*argv,"-n"))
251             action = names;
252         else if (action == uid) {
253             uid_t u = 0;
254             int sts = pw_get_uid( *argv, &u);
255             printf("uid(%s)=%d [%d]\n",*argv,(int)u,sts);
256         }
257         else if (action == gid) {
258             gid_t g = 0;
259             int sts = pw_get_gid( *argv, &g);
260             printf("gid(%s)=%d [%d]\n",*argv,(int)g,sts);
261         }
262         else if (action == names) {
263             struct pwget pw = { .id=*argv }, *ppw[2] = { &pw, NULL };
264             int sts = pw_get( &heap, ppw);
265             printf("names(%s) set=%d",*argv,pw.set);
266             if (pw.set) {
267                 printf(" name=%s home=%s",
268                     pw.user==HNULL ? "(null)" 
269                                     : (char*)heap_address( &heap, pw.user),
270                     pw.home==HNULL ? "(null)" 
271                                     : (char*)heap_address( &heap, pw.home));
272             }
273             printf(" [%d]\n",sts);
274         }
275     }
276     return 0;
277 }
278 #endif
279
280