utmpstat.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*+-------------------------------------------------------------------------
  2. utmpstat.c - utmp status for XENIX/UNIX line
  3. wht@wht.net
  4. Defined functions:
  5. US_text(us_val)
  6. strcmpi(s1, s2)
  7. to_lower(ch)
  8. to_upper(ch)
  9. ut_type_text(ut_type)
  10. utmp_status(line)
  11. system boot 0 Fri Apr 24 07:18:52 1992
  12. run-level 2 0 Fri Apr 24 07:18:52 1992
  13. asktimerck ck 15 Fri Apr 24 07:19:38 1992
  14. cat copy 17 Fri Apr 24 07:19:38 1992
  15. brc brc 18 Fri Apr 24 07:19:39 1992
  16. brc mt 22 Fri Apr 24 07:19:39 1992
  17. authckrcac ack 26 Fri Apr 24 07:19:39 1992
  18. rc2 r2 27 Fri Apr 24 07:20:05 1992
  19. LOGIN co tty01 170 Fri Apr 24 07:20:09 1992
  20. LOGIN c02 tty02 171 Fri Apr 24 07:20:09 1992
  21. uugetty u2B tty2B 3837 Fri Apr 24 21:24:38 1992
  22. uugetty u2h 190 Fri Apr 24 07:20:08 1992
  23. uugetty u1A 3830 Fri Apr 24 21:24:10 1992
  24. wht p0 ttyp0 206 Fri Apr 24 07:20:43 1992
  25. wht p1 ttyp1 1515 Fri Apr 24 20:55:53 1992
  26. wht p2 ttyp2 2929 Fri Apr 24 20:55:45 1992
  27. --------------------------------------------------------------------------*/
  28. /*+:EDITS:*/
  29. /*:04-26-2000-11:16-wht@bob-RELEASE 4.42 */
  30. /*:01-24-1997-02:38-wht@yuriatin-SOURCE RELEASE 4.00 */
  31. /*:09-11-1996-20:01-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  32. /*:08-20-1996-12:39-wht@kepler-locale/ctype fixes from ache@nagual.ru */
  33. /*:08-11-1996-02:10-wht@kepler-rename ecu_log_event to logevent */
  34. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  35. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  36. /*:11-03-1995-18:20-wht@wwtp1-internationalize to_lower/to_upper */
  37. /*:01-12-1995-15:20-wht@n4hgf-apply Andrew Chernov 8-bit clean+FreeBSD patch */
  38. /*:05-04-1994-04:40-wht@n4hgf-ECU release 3.30 */
  39. /*:10-28-1993-12:07-wht@n4hgf-Gert Doering fixes -- he be kool */
  40. /*:07-10-1993-18:24-wht@n4hgf-add ut_type tests */
  41. /*:06-26-1993-16:59-wht@n4hgf-enhance US_text */
  42. /*:05-29-1993-20:23-wht@n4hgf-handle /dev/ in ut_line and flex 'getty' test */
  43. /*:05-29-1993-19:55-wht@n4hgf-add US_text */
  44. /*:09-10-1992-14:00-wht@n4hgf-ECU release 3.20 */
  45. /*:09-02-1992-14:18-wht@n4hgf-some mark dead utmp entries instead of rming */
  46. /*:08-22-1992-15:39-wht@n4hgf-ECU release 3.20 BETA */
  47. /*:06-30-1992-14:46-wht@n4hgf-honor DIALOUT set by 3.2v4 getty when we lock */
  48. /*:04-28-1992-03:58-wht@n4hgf-check SCO utmp entry against ut_id */
  49. /*:04-24-1992-21:59-wht@n4hgf-more SCO tty name normalizing */
  50. /*:11-08-1991-21:09-root@n4hgf-bug in strcmpi made for erratic return value */
  51. /*:08-25-1991-14:39-wht@n4hgf-SVR4 port thanks to aega84!lh */
  52. /*:08-21-1991-02:23-wht@n4hgf-sun port */
  53. /*:08-10-1991-17:39-wht@n4hgf-US_WEGOTIT handling */
  54. /*:07-25-1991-12:59-wht@n4hgf-ECU release 3.10 */
  55. /*:02-13-1991-02:00-ache@hq.demos.su-swap patch 5 US_ return values */
  56. /*:02-07-1991-00:28-wht@n4hgf-utmp_status() was really messed up */
  57. /*:02-03-1991-17:52-ache@hq.demos.su-fix for XENIX utmp handling bug */
  58. /*:10-16-1990-20:43-wht@n4hgf-add SHARE_DEBUG */
  59. /*:09-19-1990-19:36-wht@n4hgf-logevent now gets pid for log from caller */
  60. /*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  61. #include "ecu.h"
  62. #include "termecu.h"
  63. #include "utmpstatus.h"
  64. #include "ecuungetty.h"
  65. #include "dialprog.h"
  66. #include <errno.h>
  67. #include <utmp.h>
  68. #ifdef __FreeBSD__ /* superfluous? */
  69. #include <ctype.h>
  70. #endif
  71. #if defined(sun)
  72. #define ut_id ut_host /* fake debug info */
  73. #else
  74. #if !defined(ut_name) /* nobody can keep their mind made up; ... */
  75. #define ut_name ut_user /* ... this is getting verry difficult, very
  76. * old */
  77. #endif
  78. #endif /* sun */
  79. #if defined(SVR4)
  80. char *utmp_file = "/var/adm/utmp";
  81. #else
  82. #ifdef _PATH_UTMP
  83. char *utmp_file = _PATH_UTMP;
  84. #else
  85. char *utmp_file = "/etc/utmp";
  86. #endif
  87. #endif
  88. struct utmp last_utmp;
  89. /*+-------------------------------------------------------------------------
  90. to_upper() / to_lower()
  91. One would think that these were relatively standard types of
  92. thing, but System V specifies toupper() to convert to upper case
  93. if not already and BSD says to adjust without testing, so, two
  94. stupid little routines here. ASCII only -- no EBCDIC gradoo here please.
  95. --------------------------------------------------------------------------*/
  96. UINT
  97. to_upper(ch)
  98. unsigned char ch;
  99. {
  100. return islower(ch) ? toupper(ch) : ch;
  101. } /* end of to_upper() */
  102. UINT
  103. to_lower(ch)
  104. unsigned char ch;
  105. {
  106. return isupper(ch) ? tolower(ch) : ch;
  107. } /* end of to_lower() */
  108. /*+-------------------------------------------------------------------------
  109. strcmpi(s1,s2) - case-insensitive strcmp
  110. This version of strcmp() is case-insensitive and works like a sane one
  111. should, per strcmp(3), not per the K&R1 example or POSIX/ANSI.
  112. In here rather than ecuutil.c since other executables besides ecu
  113. uses this module and strcmpi needed there too
  114. --------------------------------------------------------------------------*/
  115. int
  116. strcmpi(s1, s2)
  117. char *s1;
  118. char *s2;
  119. {
  120. while (*s1)
  121. {
  122. if (to_upper(*s1++) != to_upper(*s2++))
  123. {
  124. s1--;
  125. s2--;
  126. break;
  127. }
  128. }
  129. return (to_upper(*s1) - to_upper(*s2));
  130. } /* end of strcmpi */
  131. /*+-------------------------------------------------------------------------
  132. US_text(us_val) - text for US_xxx utmp status codes
  133. --------------------------------------------------------------------------*/
  134. char *
  135. US_text(us_val)
  136. enum utmp_status us_val;
  137. {
  138. static char errant[32];
  139. switch (us_val)
  140. {
  141. case US_UNDEF:
  142. return ("UNDEF");
  143. case US_NOTFOUND:
  144. return ("NOTFOUND");
  145. case US_LOGIN:
  146. return ("LOGIN");
  147. case US_DIALOUT:
  148. return ("DIALOUT");
  149. case US_LOGGEDIN:
  150. return ("LOGGEDIN");
  151. case US_WEGOTIT:
  152. return ("WEGOTIT");
  153. default:
  154. sprintf(errant, "<US=%u?>", us_val);
  155. return (errant);
  156. }
  157. } /* end of US_text */
  158. /*+-------------------------------------------------------------------------
  159. ut_type_text(ut_type) - text for ut_type_xxx utmp status codes
  160. --------------------------------------------------------------------------*/
  161. #ifdef INIT_PROCESS
  162. char *
  163. ut_type_text(ut_type)
  164. int ut_type;
  165. {
  166. static char errant[32];
  167. switch (ut_type)
  168. {
  169. #ifdef EMPTY
  170. case EMPTY:
  171. return ("EMPTY");
  172. #endif
  173. #ifdef RUN_LVL
  174. case RUN_LVL:
  175. return ("RUN_LVL");
  176. #endif
  177. #ifdef BOOT_TIME
  178. case BOOT_TIME:
  179. return ("BOOT_TIME");
  180. #endif
  181. #ifdef OLD_TIME
  182. case OLD_TIME:
  183. return ("OLD_TIME");
  184. #endif
  185. #ifdef NEW_TIME
  186. case NEW_TIME:
  187. return ("NEW_TIME");
  188. #endif
  189. #ifdef INIT_PROCESS
  190. case INIT_PROCESS:
  191. return ("INIT_PROCESS");
  192. #endif
  193. #ifdef LOGIN_PROCESS
  194. case LOGIN_PROCESS:
  195. return ("LOGIN_PROCESS");
  196. #endif
  197. #ifdef USER_PROCESS
  198. case USER_PROCESS:
  199. return ("USER_PROCESS");
  200. #endif
  201. #ifdef DEAD_PROCESS
  202. case DEAD_PROCESS:
  203. return ("DEAD_PROCESS");
  204. #endif
  205. #ifdef ACCOUNTING
  206. case ACCOUNTING:
  207. return ("ACCOUNTING");
  208. #endif
  209. default:
  210. sprintf(errant, "<ut_type=%u?>", ut_type);
  211. return (errant);
  212. }
  213. } /* end of ut_type_text */
  214. #endif /* INIT_PROCESS */
  215. /*+-------------------------------------------------------------------------
  216. utmp_status(line) - check line status in utmp
  217. 'line' is "/dev/ttyxx"-style
  218. returns US_ value and global utmp struct last_utmp;
  219. --------------------------------------------------------------------------*/
  220. enum utmp_status
  221. utmp_status(line)
  222. char *line;
  223. {
  224. #if defined sun || defined(BSD) || defined(__FreeBSD__)
  225. return (US_NOTFOUND);
  226. #else
  227. int itmp;
  228. int status = US_NOTFOUND;
  229. int ufd;
  230. #if defined(UTMP_DEBUG)
  231. char s512[512];
  232. #endif
  233. /*
  234. * crock/bozo alert:
  235. * ut_name ain't but EIGHT characters long, but
  236. * EIGHT characters are often stored, so ya don't get no null
  237. * ut_id ain't but FOUR characters long, but
  238. * FOUR characters are routinely stored, so ya don't get no null
  239. */
  240. char namecopy[sizeof(last_utmp.ut_name) + 1];
  241. char idcopy[sizeof(last_utmp.ut_id) + 1];
  242. char linecopy[sizeof(last_utmp.ut_line) + 1];
  243. if ((ufd = open(utmp_file, O_RDONLY, 755)) < 0)
  244. {
  245. perror(utmp_file);
  246. termecu(TERMECU_LINE_OPEN_ERROR);
  247. }
  248. while ((status == US_NOTFOUND) &&
  249. (read(ufd, (char *)&last_utmp, sizeof(last_utmp)) == sizeof(last_utmp)))
  250. {
  251. /*
  252. * make copies of each utmp entry we think might not be zero
  253. * padded
  254. *
  255. * be polite and skip over any non-standard "/dev/" we might find in
  256. * a ut_line entry
  257. */
  258. strncpy(namecopy, last_utmp.ut_name, sizeof(last_utmp.ut_name));
  259. namecopy[sizeof(last_utmp.ut_name)] = 0;
  260. strncpy(idcopy, last_utmp.ut_id, sizeof(last_utmp.ut_id));
  261. idcopy[sizeof(last_utmp.ut_id)] = 0;
  262. itmp = (!strncmp(last_utmp.ut_line, "/dev/", 5)) ? 5 : 0;
  263. strncpy(linecopy, last_utmp.ut_line + itmp,
  264. sizeof(last_utmp.ut_line) - itmp);
  265. linecopy[sizeof(last_utmp.ut_line) - itmp] = 0;
  266. /*
  267. * yetch! SCO uugetty doesn't always plug ut_line!!!
  268. *
  269. * However, most folks seem to follow the convention of making the
  270. * last two characters of the inittab id field (hence the ut_id
  271. * field) match the last two characters of the tty name
  272. *
  273. * The following code runs on SCO to check the last two characters of
  274. * the ut_id field against the last two characters of the line
  275. * being tested
  276. *
  277. * This only works for ttys with "standard" names. If you don't find
  278. * standard names, you probably won't find the convention followed
  279. * anyway.
  280. */
  281. #if defined(M_SYSV) || defined(SCO32v5) /* SCO */
  282. if (!linecopy[0]) /* if ut_line entry is null */
  283. {
  284. int itmp2;
  285. if (!linecopy[0] &&
  286. ((itmp = strlen(line)) > 2) &&
  287. ((itmp2 = strlen(idcopy)) > 2) &&
  288. !strcmpi(line + itmp - 2, idcopy + itmp2 - 2))
  289. {
  290. if (itmp = line_lock_status(line))
  291. {
  292. if (itmp == LINST_WEGOTIT)
  293. status = US_WEGOTIT;
  294. else
  295. status = US_DIALOUT;
  296. }
  297. else
  298. status = US_LOGIN;
  299. break;
  300. }
  301. continue;
  302. }
  303. #endif
  304. /*
  305. * if the name does not match, skip this entry
  306. */
  307. if (TTYNAME_STRCMP(linecopy, line + 5))
  308. continue;
  309. /*
  310. * THE LINE MATCHES -- now determine its status
  311. */
  312. #ifdef INIT_PROCESS
  313. if (last_utmp.ut_type == INIT_PROCESS)
  314. goto GETTY_RUNNING;
  315. #endif /* INIT_PROCESS */
  316. #ifdef LOGIN_PROCESS
  317. if (last_utmp.ut_type == LOGIN_PROCESS)
  318. {
  319. status = US_LOGIN;
  320. break;
  321. }
  322. #endif
  323. if (!strncmp(namecopy, "LOGIN", 5))
  324. status = US_LOGIN;
  325. else if (ulindex(namecopy, "getty") >= 0)
  326. {
  327. GETTY_RUNNING:
  328. /*
  329. * some getty is running (note we match "getty", "uugetty" or
  330. * "XYZGETTY")
  331. */
  332. if (itmp = line_lock_status(line))
  333. {
  334. if (itmp == LINST_WEGOTIT)
  335. status = US_WEGOTIT; /* hmmm.. 'getty' still in
  336. * utmp? */
  337. else
  338. status = US_DIALOUT; /* SCO locks tty during DCE
  339. * init */
  340. }
  341. else
  342. status = US_LOGIN;
  343. }
  344. else if (!strcmp(namecopy, "DIALOUT"))
  345. {
  346. /*
  347. * getty has seen a lock on a line and marked the utmp entry
  348. * "DIALOUT". This status is not reflected until
  349. *
  350. * <1> getty has been SIGUSR1'd by ecuungetty on systems that
  351. * support it, or
  352. *
  353. * <2> getty sees carrier (when ECU connects outward and getty's
  354. * waited open succeeds)
  355. */
  356. status = US_DIALOUT;
  357. if (last_utmp.ut_pid == xmtr_pid)
  358. status = US_WEGOTIT;
  359. else if (line_lock_status(line) == LINST_WEGOTIT)
  360. status = US_WEGOTIT;
  361. }
  362. else if (!kill((CFG_PidType) last_utmp.ut_pid, 0) || (errno != ESRCH))
  363. {
  364. /*
  365. * The process that "owns" the utmp entry (hence the line) is
  366. * not getty mor login and is alive and presumably well; if it
  367. * is WE who own it (for historical reasons, this was
  368. * possible), then say so, else we cannot have the line.
  369. *
  370. * We assume it is a dial in call since no DIALOUT status was
  371. * posted; even if the assumption is wrong and the user is
  372. * confused, the line remains protected
  373. */
  374. status = (last_utmp.ut_pid == xmtr_pid) ? US_WEGOTIT : US_LOGGEDIN;
  375. }
  376. }
  377. #if defined(UTMP_DEBUG)
  378. if (status == US_NOTFOUND)
  379. sprintf(s512, "UTMP %s: no entry in utmp", line);
  380. else
  381. {
  382. sprintf(s512, "UTMP %s:%s:%s:%d:%s",
  383. namecopy, idcopy, linecopy, last_utmp.ut_pid, US_text(status));
  384. }
  385. #ifdef INIT_PROCESS
  386. sprintf(s512 + strlen(s512), ":%s", ut_type_text(last_utmp.ut_type));
  387. #endif /* INIT_PROCESS */
  388. logevent(getpid(), s512);
  389. #endif /* UTMP_DEBUG */
  390. close(ufd);
  391. return (status);
  392. #endif /* sun */
  393. } /* end of utmp_status */
  394. /* vi: set tabstop=4 shiftwidth=4: */
  395. /* end of utmpstat.c */