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