OSDN Git Service

test: Some more tests under conditionals
[uclinux-h8/uClibc.git] / test / misc / tst-utmp.c
1 /* Tests for UTMP functions.
2    Copyright (C) 1998, 2001-2003 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1998.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <time.h>
25
26 #ifdef UTMPX
27 # include <utmpx.h>
28 # define utmp utmpx
29 # define utmpname utmpxname
30 # define setutent setutxent
31 # define getutent getutxent
32 # define endutent endutxent
33 # define getutline getutxline
34 # define getutid getutxid
35 # define pututline pututxline
36 #else
37 # include <utmp.h>
38 #endif
39
40
41 #if _HAVE_UT_TYPE || defined UTMPX
42
43 /* Prototype for our test function.  */
44 static int do_test (int argc, char *argv[]);
45
46 /* We have a preparation function.  */
47 static void do_prepare (int argc, char *argv[]);
48 #define PREPARE do_prepare
49
50 /* This defines the `main' function and some more.  */
51 #include "../test-skeleton.c"
52
53
54 /* These are for the temporary file we generate.  */
55 char *name;
56 int fd;
57
58 static void
59 do_prepare (int argc, char *argv[])
60 {
61   size_t name_len;
62
63   name_len = strlen (test_dir);
64   name = malloc (name_len + sizeof ("/utmpXXXXXX"));
65   mempcpy (mempcpy (name, test_dir, name_len),
66            "/utmpXXXXXX", sizeof ("/utmpXXXXXX"));
67   add_temp_file (name);
68
69   /* Open our test file.  */
70   fd = mkstemp (name);
71   if (fd == -1) {
72     fprintf (stderr, "cannot open test file `%s': ", name);
73     perror (NULL);
74     exit (EXIT_FAILURE);
75   }
76 }
77
78 struct utmp entry[] =
79 {
80 #if _HAVE_UT_TV || defined UTMPX
81 #define UT(a)  .ut_tv = { .tv_sec = (a)}
82 #else
83 #define UT(a)  .ut_time = (a)
84 #endif
85
86   { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
87   { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
88   { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) },
89   { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1",
90     .ut_user = "LOGIN", UT(4000) },
91   { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2",
92     .ut_user = "albert", UT(8000) },
93   { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0",
94     .ut_user = "niels", UT(10000) },
95   { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) },
96   { .ut_type = EMPTY },
97   { .ut_type = EMPTY }
98 };
99 int num_entries = sizeof entry / sizeof (struct utmp);
100
101 time_t entry_time = 20000;
102 pid_t entry_pid = 234;
103
104 static int
105 do_init (void)
106 {
107   int n;
108
109   setutent ();
110
111   for (n = 0; n < num_entries; n++)
112     {
113       if (pututline (&entry[n]) == NULL)
114         {
115           perror ("cannot write UTMP entry");
116           return 1;
117         }
118     }
119
120   endutent ();
121
122   return 0;
123 }
124
125
126 static int
127 do_check (void)
128 {
129   struct utmp *ut;
130   int n;
131
132   setutent ();
133
134   n = 0;
135   while ((ut = getutent ()))
136     {
137       if (n < num_entries &&
138           memcmp (ut, &entry[n], sizeof (struct utmp)))
139         {
140           fprintf (stderr, "UTMP entry does not match\n");
141           return 1;
142         }
143
144       n++;
145     }
146
147   if (n != num_entries)
148     {
149       fprintf (stderr, "number of UTMP entries is incorrect\n");
150       return 1;
151     }
152
153   endutent ();
154
155   return 0;
156 }
157
158 static int
159 simulate_login (const char *line, const char *user)
160 {
161   int n;
162
163   for (n = 0; n < num_entries; n++)
164     {
165       if (strcmp (line, entry[n].ut_line) == 0 ||
166           entry[n].ut_type == DEAD_PROCESS)
167         {
168           if (entry[n].ut_pid == DEAD_PROCESS)
169             entry[n].ut_pid = (entry_pid += 27);
170           entry[n].ut_type = USER_PROCESS;
171           strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
172 #if _HAVE_UT_TV - 0 || defined UTMPX
173           entry[n].ut_tv.tv_sec = (entry_time += 1000);
174 #else
175           entry[n].ut_time = (entry_time += 1000);
176 #endif
177           setutent ();
178
179           if (pututline (&entry[n]) == NULL)
180             {
181               perror ("cannot write UTMP entry");
182               return 1;
183             }
184
185           endutent ();
186
187           return 0;
188         }
189     }
190
191   fprintf (stderr, "no entries available\n");
192   return 1;
193 }
194
195 static int
196 simulate_logout (const char *line)
197 {
198   int n;
199
200   for (n = 0; n < num_entries; n++)
201     {
202       if (strcmp (line, entry[n].ut_line) == 0)
203         {
204           entry[n].ut_type = DEAD_PROCESS;
205           strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
206 #if _HAVE_UT_TV - 0 || defined UTMPX
207           entry[n].ut_tv.tv_sec = (entry_time += 1000);
208 #else
209           entry[n].ut_time = (entry_time += 1000);
210 #endif
211           setutent ();
212
213           if (pututline (&entry[n]) == NULL)
214             {
215               perror ("cannot write UTMP entry");
216               return 1;
217             }
218
219           endutent ();
220
221           return 0;
222         }
223     }
224
225   fprintf (stderr, "no entry found for `%s'\n", line);
226   return 1;
227 }
228
229 static int
230 check_login (const char *line)
231 {
232   struct utmp *up;
233   struct utmp ut;
234   int n;
235
236   setutent ();
237
238   strcpy (ut.ut_line, line);
239   up = getutline (&ut);
240   if (up == NULL)
241     {
242       fprintf (stderr, "cannot get entry for line `%s': ", line);
243           perror(NULL);
244       return 1;
245     }
246
247   endutent ();
248
249   for (n = 0; n < num_entries; n++)
250     {
251       if (strcmp (line, entry[n].ut_line) == 0)
252         {
253           if (memcmp (up, &entry[n], sizeof (struct utmp)))
254             {
255               fprintf (stderr, "UTMP entry does not match\n");
256               return 1;
257             }
258
259           return 0;
260         }
261     }
262
263   fprintf (stderr, "bogus entry for line `%s'\n", line);
264   return 1;
265 }
266
267 static int
268 check_logout (const char *line)
269 {
270   struct utmp ut;
271
272   setutent ();
273
274   strcpy (ut.ut_line, line);
275   if (getutline (&ut) != NULL)
276     {
277       fprintf (stderr, "bogus login entry for `%s'\n", line);
278       return 1;
279     }
280
281   endutent ();
282
283   return 0;
284 }
285
286 static int
287 check_id (const char *id)
288 {
289   struct utmp *up;
290   struct utmp ut;
291   int n;
292
293   setutent ();
294
295   ut.ut_type = USER_PROCESS;
296   strcpy (ut.ut_id, id);
297   up = getutid (&ut);
298   if (up == NULL)
299     {
300       fprintf (stderr, "cannot get entry for ID `%s': ", id);
301           perror (NULL);
302       return 1;
303     }
304
305   endutent ();
306
307   for (n = 0; n < num_entries; n++)
308     {
309       if (strcmp (id, entry[n].ut_id) == 0)
310         {
311           if (memcmp (up, &entry[n], sizeof (struct utmp)))
312             {
313               fprintf (stderr, "UTMP entry does not match\n");
314               return 1;
315             }
316
317           return 0;
318         }
319     }
320
321   fprintf (stderr, "bogus entry for ID `%s'\n", id);
322   return 1;
323 }
324
325 static int
326 check_type (int type)
327 {
328   struct utmp *up;
329   struct utmp ut;
330   int n;
331
332   setutent ();
333
334   ut.ut_type = type;
335   up = getutid (&ut);
336   if (up == NULL)
337     {
338       fprintf (stderr, "cannot get entry for type `%d': ", type);
339           perror (NULL);
340       return 1;
341     }
342
343   endutent ();
344
345   for (n = 0; n < num_entries; n++)
346     {
347       if (type == entry[n].ut_type)
348         {
349           if (memcmp (up, &entry[n], sizeof (struct utmp)))
350             {
351               fprintf (stderr, "UTMP entry does not match\n");
352               return 1;
353             }
354
355           return 0;
356         }
357     }
358
359   fprintf (stderr, "bogus entry for type `%d'\n", type);
360   return 1;
361 }
362
363 static int
364 do_test (int argc, char *argv[])
365 {
366   int result = 0;
367
368   utmpname (name);
369
370   result |= do_init ();
371   result |= do_check ();
372
373   result |= simulate_login ("tty1", "erwin");
374   result |= do_check ();
375
376   result |= simulate_login ("ttyp1", "paul");
377   result |= do_check ();
378
379   result |= simulate_logout ("tty2");
380   result |= do_check ();
381
382   result |= simulate_logout ("ttyp0");
383   result |= do_check ();
384
385   result |= simulate_login ("ttyp2", "richard");
386   result |= do_check ();
387
388   result |= check_login ("tty1");
389   result |= check_logout ("ttyp0");
390   result |= check_id ("p1");
391   result |= check_id ("2");
392   result |= check_id ("si");
393   result |= check_type (BOOT_TIME);
394   result |= check_type (RUN_LVL);
395
396   return result;
397 }
398
399 #else
400
401 /* No field 'ut_type' in struct utmp.  */
402 int
403 main ()
404 {
405   return 0;
406 }
407
408 #endif