utmpentry.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /* $NetBSD: utmpentry.c,v 1.5 2004/10/22 15:50:47 christos Exp $ */
  2. /*-
  3. * Copyright (c) 2002 The NetBSD Foundation, Inc.
  4. * All rights reserved.
  5. *
  6. * This code is derived from software contributed to The NetBSD Foundation
  7. * by Christos Zoulas.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by the NetBSD
  20. * Foundation, Inc. and its contributors.
  21. * 4. Neither the name of The NetBSD Foundation nor the names of its
  22. * contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  26. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  27. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  28. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  29. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #include <sys/cdefs.h>
  38. #ifndef lint
  39. __RCSID("$NetBSD: utmpentry.c,v 1.5 2004/10/22 15:50:47 christos Exp $");
  40. #endif
  41. #include <sys/stat.h>
  42. #include <time.h>
  43. #include <string.h>
  44. #include <err.h>
  45. #include <stdlib.h>
  46. #ifdef SUPPORT_UTMP
  47. #include <utmp.h>
  48. #endif
  49. #ifdef SUPPORT_UTMPX
  50. #include <utmpx.h>
  51. #endif
  52. #include "utmpentry.h"
  53. #ifdef SUPPORT_UTMP
  54. static void getentry(struct utmpentry *, struct utmp *);
  55. static time_t utmptime = 0;
  56. #endif
  57. #ifdef SUPPORT_UTMPX
  58. static void getentryx(struct utmpentry *, struct utmpx *);
  59. static time_t utmpxtime = 0;
  60. #endif
  61. #if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
  62. static int setup(const char *);
  63. static void adjust_size(struct utmpentry *e);
  64. #endif
  65. int maxname = 8, maxline = 8, maxhost = 16;
  66. static int numutmp = 0;
  67. static struct utmpentry *ehead;
  68. #if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
  69. static void
  70. adjust_size(struct utmpentry *e)
  71. {
  72. int max;
  73. if ((max = strlen(e->name)) > maxname)
  74. maxname = max;
  75. if ((max = strlen(e->line)) > maxline)
  76. maxline = max;
  77. if ((max = strlen(e->host)) > maxhost)
  78. maxhost = max;
  79. }
  80. static int
  81. setup(const char *fname)
  82. {
  83. int what = 3;
  84. struct stat st;
  85. const char *sfname;
  86. if (fname == NULL) {
  87. #ifdef SUPPORT_UTMPX
  88. setutxent();
  89. #endif
  90. #ifdef SUPPORT_UTMP
  91. setutent();
  92. #endif
  93. } else {
  94. size_t len = strlen(fname);
  95. if (len == 0)
  96. errx(1, "Filename cannot be 0 length.");
  97. what = fname[len - 1] == 'x' ? 1 : 2;
  98. if (what == 1) {
  99. #ifdef SUPPORT_UTMPX
  100. if (utmpxname(fname) == 0)
  101. warnx("Cannot set utmpx file to `%s'",
  102. fname);
  103. #else
  104. warnx("utmpx support not compiled in");
  105. #endif
  106. } else {
  107. #ifdef SUPPORT_UTMP
  108. if (utmpname(fname) == 0)
  109. warnx("Cannot set utmp file to `%s'",
  110. fname);
  111. #else
  112. warnx("utmp support not compiled in");
  113. #endif
  114. }
  115. }
  116. #ifdef SUPPORT_UTMPX
  117. if (what & 1) {
  118. sfname = fname ? fname : _PATH_UTMPX;
  119. if (stat(sfname, &st) == -1) {
  120. warn("Cannot stat `%s'", sfname);
  121. what &= ~1;
  122. } else {
  123. if (st.st_mtime > utmpxtime)
  124. utmpxtime = st.st_mtime;
  125. else
  126. what &= ~1;
  127. }
  128. }
  129. #endif
  130. #ifdef SUPPORT_UTMP
  131. if (what & 2) {
  132. sfname = fname ? fname : _PATH_UTMP;
  133. if (stat(sfname, &st) == -1) {
  134. warn("Cannot stat `%s'", sfname);
  135. what &= ~2;
  136. } else {
  137. if (st.st_mtime > utmptime)
  138. utmptime = st.st_mtime;
  139. else
  140. what &= ~2;
  141. }
  142. }
  143. #endif
  144. return what;
  145. }
  146. #endif
  147. void
  148. freeutentries(struct utmpentry *ep)
  149. {
  150. #ifdef SUPPORT_UTMP
  151. utmptime = 0;
  152. #endif
  153. #ifdef SUPPORT_UTMPX
  154. utmpxtime = 0;
  155. #endif
  156. if (ep == ehead) {
  157. ehead = NULL;
  158. numutmp = 0;
  159. }
  160. while (ep) {
  161. struct utmpentry *sep = ep;
  162. ep = ep->next;
  163. free(sep);
  164. }
  165. }
  166. int
  167. getutentries(const char *fname, struct utmpentry **epp)
  168. {
  169. #ifdef SUPPORT_UTMPX
  170. struct utmpx *utx;
  171. #endif
  172. #ifdef SUPPORT_UTMP
  173. struct utmp *ut;
  174. #endif
  175. #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
  176. struct utmpentry *ep;
  177. int what = setup(fname);
  178. struct utmpentry **nextp = &ehead;
  179. switch (what) {
  180. case 0:
  181. /* No updates */
  182. *epp = ehead;
  183. return numutmp;
  184. default:
  185. /* Need to re-scan */
  186. ehead = NULL;
  187. numutmp = 0;
  188. }
  189. #endif
  190. #ifdef SUPPORT_UTMPX
  191. while ((what & 1) && (utx = getutxent()) != NULL) {
  192. if (fname == NULL && utx->ut_type != USER_PROCESS)
  193. continue;
  194. if ((ep = calloc(1, sizeof(struct utmpentry))) == NULL) {
  195. warn(NULL);
  196. return 0;
  197. }
  198. getentryx(ep, utx);
  199. *nextp = ep;
  200. nextp = &(ep->next);
  201. }
  202. #endif
  203. #ifdef SUPPORT_UTMP
  204. while ((what & 2) && (ut = getutent()) != NULL) {
  205. if (fname == NULL && (*ut->ut_name == '\0' ||
  206. *ut->ut_line == '\0'))
  207. continue;
  208. /* Don't process entries that we have utmpx for */
  209. for (ep = ehead; ep != NULL; ep = ep->next) {
  210. if (strncmp(ep->line, ut->ut_line,
  211. sizeof(ut->ut_line)) == 0)
  212. break;
  213. }
  214. if (ep != NULL)
  215. continue;
  216. if ((ep = calloc(1, sizeof(struct utmpentry))) == NULL) {
  217. warn(NULL);
  218. return 0;
  219. }
  220. getentry(ep, ut);
  221. *nextp = ep;
  222. nextp = &(ep->next);
  223. }
  224. #endif
  225. numutmp = 0;
  226. #if defined(SUPPORT_UTMP) && defined(SUPPORT_UTMPX)
  227. if (ehead != NULL) {
  228. struct utmpentry *from = ehead, *save;
  229. ehead = NULL;
  230. while (from != NULL) {
  231. for (nextp = &ehead;
  232. (*nextp) && strcmp(from->line, (*nextp)->line) > 0;
  233. nextp = &(*nextp)->next)
  234. continue;
  235. save = from;
  236. from = from->next;
  237. save->next = *nextp;
  238. *nextp = save;
  239. numutmp++;
  240. }
  241. }
  242. *epp = ehead;
  243. return numutmp;
  244. #else
  245. *epp = NULL;
  246. return 0;
  247. #endif
  248. }
  249. #ifdef SUPPORT_UTMP
  250. static void
  251. getentry(struct utmpentry *e, struct utmp *up)
  252. {
  253. (void)strncpy(e->name, up->ut_name, sizeof(up->ut_name));
  254. e->name[sizeof(e->name) - 1] = '\0';
  255. (void)strncpy(e->line, up->ut_line, sizeof(up->ut_line));
  256. e->line[sizeof(e->line) - 1] = '\0';
  257. (void)strncpy(e->host, up->ut_host, sizeof(up->ut_host));
  258. e->name[sizeof(e->host) - 1] = '\0';
  259. e->tv.tv_sec = up->ut_time;
  260. e->tv.tv_usec = 0;
  261. adjust_size(e);
  262. }
  263. #endif
  264. #ifdef SUPPORT_UTMPX
  265. static void
  266. getentryx(struct utmpentry *e, struct utmpx *up)
  267. {
  268. (void)strncpy(e->name, up->ut_name, sizeof(up->ut_name));
  269. e->name[sizeof(e->name) - 1] = '\0';
  270. (void)strncpy(e->line, up->ut_line, sizeof(up->ut_line));
  271. e->line[sizeof(e->line) - 1] = '\0';
  272. (void)strncpy(e->host, up->ut_host, sizeof(up->ut_host));
  273. e->name[sizeof(e->host) - 1] = '\0';
  274. e->tv = up->ut_tv;
  275. adjust_size(e);
  276. }
  277. #endif