utmpx.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright (c) 2004 Gunnar Ritter
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute
  10. * it freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. *
  17. * 2. Altered source versions must be plainly marked as such, and must not be
  18. * misrepresented as being the original software.
  19. *
  20. * 3. This notice may not be removed or altered from any source distribution.
  21. */
  22. /* Sccsid @(#)utmpx.c 1.13 (gritter) 12/16/07 */
  23. #include <stdio.h>
  24. #if defined (__FreeBSD__) || defined (__dietlibc__) || defined (__NetBSD__) || \
  25. defined (__UCLIBC__) || defined (__OpenBSD__) || \
  26. defined (__DragonFly__) || \
  27. defined (__APPLE__) && \
  28. (__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_OS_X_VERSION_10_5)
  29. #include <sys/types.h>
  30. #include <sys/time.h>
  31. #include <utmp.h>
  32. #include <string.h>
  33. #include "utmpx.h"
  34. static FILE *utfp;
  35. static struct utmpx utx;
  36. static const char *utmpfile = _PATH_UTMP;
  37. static FILE *
  38. init(void)
  39. {
  40. if (utfp == NULL && (utfp = fopen(utmpfile, "r+")) == NULL)
  41. if ((utfp = fopen(utmpfile, "r")) == NULL)
  42. return NULL;
  43. return utfp;
  44. }
  45. static struct utmpx *
  46. utmp2utmpx(struct utmpx *ux, const struct utmp *up)
  47. {
  48. #ifndef __dietlibc__
  49. memset(ux, 0, sizeof *ux);
  50. ux->ut_tv.tv_sec = up->ut_time;
  51. memcpy(ux->ut_line, up->ut_line, UT_LINESIZE);
  52. memcpy(ux->ut_user, up->ut_name, UT_NAMESIZE);
  53. memcpy(ux->ut_host, up->ut_host, UT_HOSTSIZE);
  54. if (strcmp(up->ut_line, "~") == 0)
  55. ux->ut_type = BOOT_TIME;
  56. else if (strcmp(up->ut_line, "|") == 0)
  57. ux->ut_type = OLD_TIME;
  58. else if (strcmp(up->ut_line, "}") == 0)
  59. ux->ut_type = NEW_TIME;
  60. else if (*up->ut_name == 0)
  61. ux->ut_type = DEAD_PROCESS;
  62. else
  63. ux->ut_type = USER_PROCESS;
  64. #else /* __dietlibc__ */
  65. *ux = *up;
  66. #endif /* __dietlibc__ */
  67. return ux;
  68. }
  69. static struct utmp *
  70. utmpx2utmp(struct utmp *up, const struct utmpx *ux)
  71. {
  72. #ifndef __dietlibc__
  73. memset(up, 0, sizeof *up);
  74. up->ut_time = ux->ut_tv.tv_sec;
  75. switch (ux->ut_type) {
  76. case DEAD_PROCESS:
  77. memcpy(up->ut_line, ux->ut_line, UT_LINESIZE);
  78. break;
  79. default:
  80. case EMPTY:
  81. case INIT_PROCESS:
  82. case LOGIN_PROCESS:
  83. case RUN_LVL:
  84. case ACCOUNTING:
  85. return NULL;
  86. case BOOT_TIME:
  87. strcpy(up->ut_name, "reboot");
  88. strcpy(up->ut_line, "~");
  89. break;
  90. case OLD_TIME:
  91. strcpy(up->ut_name, "date");
  92. strcpy(up->ut_line, "|");
  93. break;
  94. case NEW_TIME:
  95. strcpy(up->ut_name, "date");
  96. strcpy(up->ut_line, "{");
  97. break;
  98. case USER_PROCESS:
  99. memcpy(up->ut_line, ux->ut_line, UT_LINESIZE);
  100. memcpy(up->ut_name, ux->ut_user, UT_NAMESIZE);
  101. memcpy(up->ut_host, ux->ut_host, UT_HOSTSIZE);
  102. }
  103. #else /* __dietlibc__ */
  104. *up = *ux;
  105. #endif /* __dietlibc__ */
  106. return up;
  107. }
  108. struct utmpx *
  109. getutxent(void)
  110. {
  111. static struct utmp zero;
  112. struct utmp ut;
  113. if (init() == NULL)
  114. return NULL;
  115. do {
  116. if (fread(&ut, sizeof ut, 1, utfp) != 1)
  117. return NULL;
  118. } while (memcmp(&ut, &zero, sizeof ut) == 0);
  119. return utmp2utmpx(&utx, &ut);
  120. }
  121. struct utmpx *
  122. getutxline(const struct utmpx *ux)
  123. {
  124. struct utmp ut;
  125. if (init() == NULL)
  126. return NULL;
  127. fseek(utfp, 0, SEEK_SET);
  128. while (fread(&ut, sizeof ut, 1, utfp) == 1) {
  129. utmp2utmpx(&utx, &ut);
  130. if ((utx.ut_type == LOGIN_PROCESS ||
  131. utx.ut_type == USER_PROCESS) &&
  132. strcmp(ut.ut_line, utx.ut_line) == 0)
  133. return &utx;
  134. }
  135. return NULL;
  136. }
  137. struct utmpx *
  138. getutxid(const struct utmpx *ux)
  139. {
  140. #ifdef __dietlibc__
  141. struct utmp ut;
  142. #endif
  143. if (init() == NULL)
  144. return NULL;
  145. #ifdef __dietlibc__
  146. fseek(utfp, 0, SEEK_SET);
  147. while (fread(&ut, sizeof ut, 1, utfp) == 1) {
  148. utmp2utmpx(&utx, &ut);
  149. switch (ux->ut_type) {
  150. case BOOT_TIME:
  151. case OLD_TIME:
  152. case NEW_TIME:
  153. if (ux->ut_type == utx.ut_type)
  154. return &utx;
  155. break;
  156. case INIT_PROCESS:
  157. case LOGIN_PROCESS:
  158. case USER_PROCESS:
  159. case DEAD_PROCESS:
  160. if (ux->ut_type == utx.ut_type &&
  161. ux->ut_id == utx.ut_id)
  162. return &utx;
  163. break;
  164. }
  165. }
  166. #endif /* __dietlibc__ */
  167. return NULL;
  168. }
  169. void
  170. setutxent(void)
  171. {
  172. if (init() == NULL)
  173. return;
  174. fseek(utfp, 0, SEEK_SET);
  175. }
  176. void
  177. endutxent(void)
  178. {
  179. FILE *fp;
  180. if (init() == NULL)
  181. return;
  182. fp = utfp;
  183. utfp = NULL;
  184. fclose(fp);
  185. }
  186. int
  187. utmpxname(const char *name)
  188. {
  189. utmpfile = strdup(name);
  190. return 0;
  191. }
  192. extern struct utmpx *
  193. pututxline(const struct utmpx *up)
  194. {
  195. struct utmp ut;
  196. struct utmpx *rp;
  197. if (init() == NULL)
  198. return NULL;
  199. /*
  200. * Cannot use getutxid() because there is no id field. Use
  201. * the equivalent of getutxline() instead.
  202. */
  203. while (fread(&ut, sizeof ut, 1, utfp) == 1) {
  204. if (strncmp(ut.ut_line, up->ut_line, UT_LINESIZE) == 0) {
  205. fseek(utfp, -sizeof ut, SEEK_CUR);
  206. break;
  207. }
  208. }
  209. fflush(utfp);
  210. if (utmpx2utmp(&ut, up) == NULL)
  211. rp = NULL;
  212. else if (fwrite(&ut, sizeof ut, 1, utfp) == 1) {
  213. utx = *up;
  214. rp = &utx;
  215. } else
  216. rp = NULL;
  217. fflush(utfp);
  218. return rp;
  219. }
  220. extern void
  221. updwtmpx(const char *name, const struct utmpx *up)
  222. {
  223. FILE *fp;
  224. if ((fp = fopen(name, "a")) == NULL)
  225. return;
  226. fwrite(up, sizeof *up, 1, fp);
  227. fclose(fp);
  228. }
  229. #endif /* __FreeBSD__ || __dietlibc__ || __NetBSD__ || __UCLIBC__ ||
  230. __OpenBSD__ || __DragonFly__ || __APPLE__ */