tst-utmp.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  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. The GNU C Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. The GNU C 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. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with the GNU C Library; if not, see
  15. <http://www.gnu.org/licenses/>. */
  16. #include <errno.h>
  17. #include <error.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <sys/types.h>
  21. #include <time.h>
  22. #ifdef UTMPX
  23. # include <utmpx.h>
  24. # define utmp utmpx
  25. # define utmpname utmpxname
  26. # define setutent setutxent
  27. # define getutent getutxent
  28. # define endutent endutxent
  29. # define getutline getutxline
  30. # define getutid getutxid
  31. # define pututline pututxline
  32. #else
  33. # include <utmp.h>
  34. #endif
  35. #if _HAVE_UT_TYPE || defined UTMPX
  36. /* Prototype for our test function. */
  37. static int do_test (int argc, char *argv[]);
  38. /* We have a preparation function. */
  39. static void do_prepare (int argc, char *argv[]);
  40. #define PREPARE do_prepare
  41. /* This defines the `main' function and some more. */
  42. #include "../test-skeleton.c"
  43. /* These are for the temporary file we generate. */
  44. char *name;
  45. int fd;
  46. static void
  47. do_prepare (int argc, char *argv[])
  48. {
  49. size_t name_len;
  50. name_len = strlen (test_dir);
  51. name = malloc (name_len + sizeof ("/utmpXXXXXX"));
  52. mempcpy (mempcpy (name, test_dir, name_len),
  53. "/utmpXXXXXX", sizeof ("/utmpXXXXXX"));
  54. add_temp_file (name);
  55. /* Open our test file. */
  56. fd = mkstemp (name);
  57. if (fd == -1)
  58. error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
  59. }
  60. struct utmp entry[] =
  61. {
  62. #if _HAVE_UT_TV || defined UTMPX
  63. #define UT(a) .ut_tv = { .tv_sec = (a)}
  64. #else
  65. #define UT(a) .ut_time = (a)
  66. #endif
  67. { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
  68. { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
  69. { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) },
  70. { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1",
  71. .ut_user = "LOGIN", UT(4000) },
  72. { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2",
  73. .ut_user = "albert", UT(8000) },
  74. { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0",
  75. .ut_user = "niels", UT(10000) },
  76. { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) },
  77. { .ut_type = EMPTY },
  78. { .ut_type = EMPTY }
  79. };
  80. int num_entries = sizeof entry / sizeof (struct utmp);
  81. time_t entry_time = 20000;
  82. pid_t entry_pid = 234;
  83. static int
  84. do_init (void)
  85. {
  86. int n;
  87. setutent ();
  88. for (n = 0; n < num_entries; n++)
  89. {
  90. if (pututline (&entry[n]) == NULL)
  91. {
  92. error (0, errno, "cannot write UTMP entry");
  93. return 1;
  94. }
  95. }
  96. endutent ();
  97. return 0;
  98. }
  99. static int
  100. do_check (void)
  101. {
  102. struct utmp *ut;
  103. int n;
  104. setutent ();
  105. n = 0;
  106. while ((ut = getutent ()))
  107. {
  108. if (n < num_entries &&
  109. memcmp (ut, &entry[n], sizeof (struct utmp)))
  110. {
  111. error (0, 0, "UTMP entry does not match");
  112. return 1;
  113. }
  114. n++;
  115. }
  116. if (n != num_entries)
  117. {
  118. error (0, 0, "number of UTMP entries is incorrect");
  119. return 1;
  120. }
  121. endutent ();
  122. return 0;
  123. }
  124. static int
  125. simulate_login (const char *line, const char *user)
  126. {
  127. int n;
  128. for (n = 0; n < num_entries; n++)
  129. {
  130. if (strcmp (line, entry[n].ut_line) == 0 ||
  131. entry[n].ut_type == DEAD_PROCESS)
  132. {
  133. if (entry[n].ut_pid == DEAD_PROCESS)
  134. entry[n].ut_pid = (entry_pid += 27);
  135. entry[n].ut_type = USER_PROCESS;
  136. strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
  137. #if _HAVE_UT_TV - 0 || defined UTMPX
  138. entry[n].ut_tv.tv_sec = (entry_time += 1000);
  139. #else
  140. entry[n].ut_time = (entry_time += 1000);
  141. #endif
  142. setutent ();
  143. if (pututline (&entry[n]) == NULL)
  144. {
  145. error (0, errno, "cannot write UTMP entry");
  146. return 1;
  147. }
  148. endutent ();
  149. return 0;
  150. }
  151. }
  152. error (0, 0, "no entries available");
  153. return 1;
  154. }
  155. static int
  156. simulate_logout (const char *line)
  157. {
  158. int n;
  159. for (n = 0; n < num_entries; n++)
  160. {
  161. if (strcmp (line, entry[n].ut_line) == 0)
  162. {
  163. entry[n].ut_type = DEAD_PROCESS;
  164. strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
  165. #if _HAVE_UT_TV - 0 || defined UTMPX
  166. entry[n].ut_tv.tv_sec = (entry_time += 1000);
  167. #else
  168. entry[n].ut_time = (entry_time += 1000);
  169. #endif
  170. setutent ();
  171. if (pututline (&entry[n]) == NULL)
  172. {
  173. error (0, errno, "cannot write UTMP entry");
  174. return 1;
  175. }
  176. endutent ();
  177. return 0;
  178. }
  179. }
  180. error (0, 0, "no entry found for `%s'", line);
  181. return 1;
  182. }
  183. static int
  184. check_login (const char *line)
  185. {
  186. struct utmp *up;
  187. struct utmp ut;
  188. int n;
  189. setutent ();
  190. strcpy (ut.ut_line, line);
  191. up = getutline (&ut);
  192. if (up == NULL)
  193. {
  194. error (0, errno, "cannot get entry for line `%s'", line);
  195. return 1;
  196. }
  197. endutent ();
  198. for (n = 0; n < num_entries; n++)
  199. {
  200. if (strcmp (line, entry[n].ut_line) == 0)
  201. {
  202. if (memcmp (up, &entry[n], sizeof (struct utmp)))
  203. {
  204. error (0, 0, "UTMP entry does not match");
  205. return 1;
  206. }
  207. return 0;
  208. }
  209. }
  210. error (0, 0, "bogus entry for line `%s'", line);
  211. return 1;
  212. }
  213. static int
  214. check_logout (const char *line)
  215. {
  216. struct utmp ut;
  217. setutent ();
  218. strcpy (ut.ut_line, line);
  219. if (getutline (&ut) != NULL)
  220. {
  221. error (0, 0, "bogus login entry for `%s'", line);
  222. return 1;
  223. }
  224. endutent ();
  225. return 0;
  226. }
  227. static int
  228. check_id (const char *id)
  229. {
  230. struct utmp *up;
  231. struct utmp ut;
  232. int n;
  233. setutent ();
  234. ut.ut_type = USER_PROCESS;
  235. strcpy (ut.ut_id, id);
  236. up = getutid (&ut);
  237. if (up == NULL)
  238. {
  239. error (0, errno, "cannot get entry for ID `%s'", id);
  240. return 1;
  241. }
  242. endutent ();
  243. for (n = 0; n < num_entries; n++)
  244. {
  245. if (strcmp (id, entry[n].ut_id) == 0)
  246. {
  247. if (memcmp (up, &entry[n], sizeof (struct utmp)))
  248. {
  249. error (0, 0, "UTMP entry does not match");
  250. return 1;
  251. }
  252. return 0;
  253. }
  254. }
  255. error (0, 0, "bogus entry for ID `%s'", id);
  256. return 1;
  257. }
  258. static int
  259. check_type (int type)
  260. {
  261. struct utmp *up;
  262. struct utmp ut;
  263. int n;
  264. setutent ();
  265. ut.ut_type = type;
  266. up = getutid (&ut);
  267. if (up == NULL)
  268. {
  269. error (0, errno, "cannot get entry for type `%d'", type);
  270. return 1;
  271. }
  272. endutent ();
  273. for (n = 0; n < num_entries; n++)
  274. {
  275. if (type == entry[n].ut_type)
  276. {
  277. if (memcmp (up, &entry[n], sizeof (struct utmp)))
  278. {
  279. error (0, 0, "UTMP entry does not match");
  280. return 1;
  281. }
  282. return 0;
  283. }
  284. }
  285. error (0, 0, "bogus entry for type `%d'", type);
  286. return 1;
  287. }
  288. static int
  289. do_test (int argc, char *argv[])
  290. {
  291. int result = 0;
  292. utmpname (name);
  293. result |= do_init ();
  294. result |= do_check ();
  295. result |= simulate_login ("tty1", "erwin");
  296. result |= do_check ();
  297. result |= simulate_login ("ttyp1", "paul");
  298. result |= do_check ();
  299. result |= simulate_logout ("tty2");
  300. result |= do_check ();
  301. result |= simulate_logout ("ttyp0");
  302. result |= do_check ();
  303. result |= simulate_login ("ttyp2", "richard");
  304. result |= do_check ();
  305. result |= check_login ("tty1");
  306. result |= check_logout ("ttyp0");
  307. result |= check_id ("p1");
  308. result |= check_id ("2");
  309. result |= check_id ("si");
  310. result |= check_type (BOOT_TIME);
  311. result |= check_type (RUN_LVL);
  312. return result;
  313. }
  314. #else
  315. /* No field 'ut_type' in struct utmp. */
  316. int
  317. main ()
  318. {
  319. return 0;
  320. }
  321. #endif