home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / freeks / part01 next >
Text File  |  1994-07-02  |  37KB  |  1,435 lines

  1. Newsgroups: comp.sources.unix
  2. From: lytras@avalon.unizh.ch (Apostolos Lytras)
  3. Subject: v28i080: freeks - a who-is-logged-on report similar to "geeks", V1.32, Part01/01
  4. Message-id: <1.773199264.16584@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: lytras@avalon.unizh.ch (Apostolos Lytras)
  9. Posting-Number: Volume 28, Issue 80
  10. Archive-Name: freeks/part01
  11.  
  12. here is a clone for 'geeks' I have written. It is significantly 
  13. faster than geeks but doesn't have as many fancy options.
  14.  
  15. From the 'man' page:
  16.  
  17. DESCRIPTION
  18.      Freeks produces a report on system usage based on  the  con-
  19.      tents  of wtmp and sorted by the actual time different users
  20.      have spent on the system.   The  format  of  the  output  is
  21.      almost  similar  to geeks(6). The first lines are different,
  22.      they contain general information about the  system.  In  the
  23.      'User  statistics' section the last field is different also,
  24.      containing the percentage of total  uptime  the  user  spent
  25.      logged in to the system.
  26.  
  27. This new version has some SVR4 support built into it, but I couldn't
  28. test that enough, so I'd be happy to hear from you, if you have SVR4
  29. and notice a bug...
  30.  
  31.     Enjoy
  32.     - Apostolos 
  33.  
  34. #! /bin/sh
  35. # This is a shell archive.  Save it in a file, remove anything before
  36. # this line, and then unpack it by entering "sh file".  Note, it may
  37. # create directories; files and directories will be owned by you and
  38. # have default permissions.
  39. #
  40. # This archive contains:
  41. #
  42. #    freeks-1.32/Makefile
  43. #    freeks-1.32/README
  44. #    freeks-1.32/configfile-example
  45. #    freeks-1.32/freeks.6
  46. #    freeks-1.32/freeks.c
  47. #    freeks-1.32/freeks.cat
  48. #    freeks-1.32/freeks.h
  49. #    freeks-1.32/gecos.c
  50. #
  51. echo x - freeks-1.32/Makefile
  52. sed 's/^X//' >freeks-1.32/Makefile << 'END-of-freeks-1.32/Makefile'
  53. X# Makefile for freeks 1.32
  54. X
  55. X# Configure this for your system (default is {SunOS,Ultrix} with gcc)
  56. X# 
  57. X# NOTE: if your system has far more (or far less) users than 1021, you
  58. X#       may wish to change the value for HASHTABLESIZE. That value must
  59. X#       be prime. You can change it in freeks.c, or here by adding
  60. X#       -DHASHTABLESIZE=2003 (for about 2000 users for example) to CFLAGS.
  61. X#       If you have a lot of users and you want to improve performance a bit,
  62. X#       it's probably best to test a prime number around (1.5*number_of_users)
  63. X#       which should cause less searching for free positions in the hash
  64. X#       table (the searching is linear!) when the table gets full.
  65. X#
  66. X# NOTE FOR SYSTEM V: System V doesn't log shutdowns by default. If you
  67. X#       want accurate information about system uptime then create a
  68. X#       shutdown user whose login will indicate that the system was shut 
  69. X#       down. Then define CONFIGFILE in freeks.c (or call the account
  70. X#       "shutdown") and create the configfile in the appropriate
  71. X#       place.
  72. X
  73. X# Some general Variables
  74. X#
  75. Xprefix = /usr/local
  76. Xpostfix = 6
  77. XMANPATH = ${prefix}/man/man${postfix}
  78. XCP = install -c -m
  79. XMODE1 = 755
  80. XMODE2 = 644
  81. XOBJS = freeks.o gecos.o
  82. X
  83. X# SunOS 4.1.3  / Ultrix 4.0 with gcc
  84. X#
  85. XCC = gcc
  86. XCFLAGS = -Wall -W -Wno-implicit -O 
  87. X
  88. X# SunOS 4.1.3 with Sun C compiler
  89. X#
  90. X#CC = cc
  91. X#CFLAGS = -O
  92. X
  93. X# Slowaris 2.3 with gcc
  94. X#
  95. X#CC = gcc
  96. X#CFLAGS = -Wall -W -O -DSYSV
  97. X
  98. X# HP/UX 9.0x.
  99. X#
  100. X# CC = cc
  101. X# CFLAGS = -Aa -O
  102. X
  103. X# Nextstep 3.x with NeXT's (g)cc
  104. X#
  105. X# CC = cc
  106. X# CFLAGS = -Wall -W -Dnextstep3 -O
  107. X
  108. X# more flags
  109. X# DEBUGFLAGS = -DDEBUG -g -ansi -pedantic -DWANTGECOS
  110. XDEBUGFLAGS = 
  111. X# LDFLAGS = -s
  112. XLDFLAGS =
  113. X
  114. X# -------- from here on you shouldn't need to change anything ---
  115. X
  116. Xall:     freeks  
  117. X
  118. Xfreeks: ${OBJS}
  119. X    ${CC} ${CFLAGS} ${DEBUGFLAGS} ${LDFLAGS} -o $@ ${OBJS}
  120. X
  121. Xfreeks.o:
  122. X    ${CC} ${CFLAGS} ${DEBUGFLAGS} -c $*.c
  123. X
  124. Xgecos.o:
  125. X     ${CC} ${CFLAGS} ${DEBUGFLAGS} -c $*.c
  126. X
  127. Xinstall: all
  128. X    ${CP} ${MODE1} ${BINARY} ${prefix}/bin; \
  129. X    ${CP} ${MODE2} freeks.6 ${MANPATH}/freeks.${postfix}
  130. X
  131. Xclean:
  132. X    rm -f freeks *~ core *.o
  133. END-of-freeks-1.32/Makefile
  134. echo x - freeks-1.32/README
  135. sed 's/^X//' >freeks-1.32/README << 'END-of-freeks-1.32/README'
  136. XFirst of all read the manual page... 
  137. X(e.g. with 'nroff -man freeks.6 | more')
  138. X
  139. XINSTALLATION:
  140. X
  141. X1) Edit the Makefile to match your system.
  142. X2) Check if you have to change anything in 'freeks.h'
  143. X3) 'make'
  144. X4) Test-run freeks.
  145. X5) 'make install'
  146. X6) 'make clean'
  147. X
  148. XPORTABILITY:
  149. X
  150. XI've tested this on the following systems:
  151. XMachine Type     Operating System        Compiler
  152. XDecsystem 5200   Ultrix 4.0              gcc 2.2.2
  153. XNextstation m68k Nextstep 3.2            cc (Next's Version of gcc 2.2.2)
  154. XSparcstation 1   SunOS 4.1.3             gcc 2.5.8
  155. XSparcClassic     SunOS 5.3 (Solaris 2.3) gcc 2.5.8
  156. X
  157. XTHANKS:
  158. X
  159. Xbruce@slc.com (Bruce Schuchardt) sent me some patches to make freeks
  160. Xrun on HP/UX 9.0x with HP's cc. I've built them into the source. He said
  161. Xthat there are a couple of minor compilation warnings which could be 
  162. Xignored.
  163. X
  164. XWietse Venema for his feedback on SysV peculiarities...
  165. X
  166. XEnjoy!
  167. X- Apostolos Lytras (lytras@avalon.unizh.ch)
  168. END-of-freeks-1.32/README
  169. echo x - freeks-1.32/configfile-example
  170. sed 's/^X//' >freeks-1.32/configfile-example << 'END-of-freeks-1.32/configfile-example'
  171. Xhalt
  172. Xarmageddon
  173. Xshutdown
  174. Xpowerdown
  175. END-of-freeks-1.32/configfile-example
  176. echo x - freeks-1.32/freeks.6
  177. sed 's/^X//' >freeks-1.32/freeks.6 << 'END-of-freeks-1.32/freeks.6'
  178. X.TH freeks 6 "June 24, 1994" "Apostolos Lytras" "Freeks 1.32 Geeking Manual"
  179. X.SH NAME
  180. Xfreeks \- fast 'geeks style' login accounting
  181. X.SH SYNOPSIS
  182. Xfreeks [\-w
  183. X.I wtmp
  184. X] [\-t] [\-c
  185. X.I configfile
  186. X]
  187. X
  188. X.SH DESCRIPTION
  189. X.B Freeks
  190. Xis a
  191. X.B fast
  192. Xand
  193. X.B reduced
  194. Xversion of
  195. X.B geeks(6).
  196. XThe default for
  197. X.I wtmp
  198. Xis "/usr/adm/wtmp".
  199. X
  200. X.B Freeks
  201. Xproduces a report on system usage based on the contents of
  202. X.I wtmp
  203. Xand sorted by the actual time different users have spent on the
  204. Xsystem.  The format of the output is almost similar to
  205. X.B geeks(6).
  206. XThe first lines are different, they contain general information about
  207. Xthe system. In the 'User statistics' section the last field is
  208. Xdifferent also, containing the percentage of total uptime the user
  209. Xspent logged in to the system.
  210. X
  211. X
  212. X.SH OPTIONS
  213. XYou may specify an alternate
  214. X.I wtmp
  215. Xfile on the command line.
  216. X
  217. XWith the 't' option the user statistics are modified, showing the
  218. X\'geek rank\', the name, the time the user was actually logged in and
  219. Xthe number of logins. 
  220. X
  221. XWith the \'c\' option you can specify a 
  222. X.I configfile 
  223. Xcontaining the names of alternative 'shutdown' users (cf. TODO), which
  224. Xis probably interesting to SysV machine owners only.
  225. X
  226. X.SH BUGS
  227. X.B Freeks
  228. Xis (almost) limited to BSD style
  229. X.I wtmp
  230. Xfiles (cf. TODO below). It does not have a lot of fancy options. It
  231. Xdoes not include a server similar to
  232. X.B geeksd(6).
  233. XFreeks does make some mistakes, e.g. when a reboot entry in
  234. X.I wtmp
  235. Xhappened without a shutdown before it. If the last entry happened more
  236. Xthan a day before the reboot entry, freeks presumes that the machine
  237. Xcrashed, and will use the time of the last entry before the crash as
  238. Xtime of shutdown. This may lead to marginal errors in 'uptime' and the
  239. Xlogin times of users still logged in at that time.
  240. X
  241. XAnother bug happens when time is changed in single user mode which
  242. Xmeans it doesn't get logged. Don't do that, or delete the
  243. X.I wtmp
  244. Xfile afterwards.
  245. X
  246. X.SH TODO
  247. XSystem V has changed a lot in 
  248. X.I wtmp
  249. Xbut it should be possible to run the program, if you rarely shut
  250. Xyour machine down or have a dedicated 'shutdown' user that logs in
  251. Xwhen you shut down. If this user is called 'shutdown' you needn't 
  252. Xdo nothing, if his login name is something else, you can specify that in
  253. X.I configfile
  254. X(if, of course, freeks had been compiled with CONFIGFILE defined...).
  255. X
  256. X
  257. X.SH "SEE ALSO"
  258. X.BR geeks(5)
  259. X.BR geeks(6)
  260. X.BR ac(8)
  261. X.BR wtmp(5)
  262. X.BR wtmpfix(8)
  263. X.BR login(1)
  264. X.BR init(8)
  265. X
  266. X.SH FILES
  267. X.PD 0
  268. X.TP 20
  269. X.B /usr/adm/wtmp
  270. Xwtmp file
  271. X
  272. X.SH AUTHOR
  273. XCopyright (C) 1994 by Apostolos Lytras (lytras@avalon.unizh.ch).
  274. X
  275. XThanks to Dave P. Gymer (dpg@cs.nott.ac.uk) and everyone that helped
  276. Xhim write geeks(6). It has been an important inspiration and a reason
  277. Xto write this program (because it was just too slow, geeks! ;-).
  278. X
  279. XThanks also to Wietse Venema for his information on SVR4's wtmp.
  280. X
  281. XSome of the credit must also go to the University of California,
  282. XBerkeley, for their programs ac(8), last(1) and uptime(1), which
  283. Xevaluate /usr/adm/wtmp as well. These programs were inspiring as well,
  284. Xbecause they couldn't do everything real geeks needed them to.
  285. X
  286. XThis is free software; you can redistribute it and/or modify it under
  287. Xthe terms of the GNU General Public License as published by the Free
  288. XSoftware Foundation; either version 2 of the License, or (at your
  289. Xoption) any later version.
  290. X
  291. XThe GNU General Public License is not included in the original
  292. Xdistrubution of freeks. If you don't have a copy of it already, write
  293. Xto the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
  294. XUSA.
  295. X
  296. XThis program is distributed in the hope that  it  will  be useful, but
  297. XWITHOUT ANY WARRANTY; without even the implied warranty of
  298. XMERCHANTABILITY or FITNESS  FOR  A  PARTICULAR PURPOSE.   See  the
  299. XGNU  General  Public License for more details.
  300. X
  301. END-of-freeks-1.32/freeks.6
  302. echo x - freeks-1.32/freeks.c
  303. sed 's/^X//' >freeks-1.32/freeks.c << 'END-of-freeks-1.32/freeks.c'
  304. X/********************************************************************/
  305. X/*                                                                  */
  306. X/* freeks.c - login accounting                                      */
  307. X/* Copyright (C) 1994 by Apostolos Lytras (lytras@avalon.unizh.ch)  */
  308. X/* Version 1.32, June 24, 1994                                      */
  309. X/*                                                                  */
  310. X/*            1.32  SysV support almost in. fixed more bugs.        */
  311. X/*            1.31  time handling still not okay.                   */
  312. X/*                  finally got some SysV help from Wietse Venema   */
  313. X/*            1.30  first attempt to include SysV support           */
  314. X/*            1.22  included hints for HP/UX 9.0x with              */
  315. X/*                  CLASSIC_ID_TYPES                                */ 
  316. X/*                  suggested by bruce@slc.com (Bruce Schuchardt)   */
  317. X/*            1.21  included bugfix for J_hash suggested by         */
  318. X/*                  awick@csugrad.cs.vt.edu (Andy Wick)             */
  319. X/*                  posted to alt.sources March 30, 1994            */
  320. X/*            1.20  first edition, posted to alt.sources            */
  321. X/*                  March 29, 1994                                  */
  322. X/*                                                                  */
  323. X/*                                                                  */
  324. X/* See the manual page (freeks.6) distributed with this file, for   */
  325. X/* restriction and warranty information.                            */
  326. X/*                                                                  */
  327. X/********************************************************************/
  328. X
  329. X#include "freeks.h"
  330. X
  331. X#ifdef NO_STRDUP
  332. Xchar           *
  333. Xstrdup(char *s)
  334. X{
  335. X  char           *t = (char *) malloc(strlen(s) + 1);
  336. X
  337. X  return t ? strcpy(t, s) : t;
  338. X}
  339. X#else
  340. Xextern char    *strdup();
  341. X#endif
  342. X
  343. X
  344. XUSER            userlist[HASHTABLESIZE];
  345. XTTY            *ttylist;
  346. X
  347. Xlong            s_uptime;
  348. Xlong            s_start;
  349. Xlong            s_corr = 0;
  350. Xlong            t_corr = 0;
  351. Xlong            s_stop;
  352. Xunsigned int    s_reboots = 0;
  353. Xunsigned int    s_shutdowns = 0;
  354. Xunsigned int    s_crashes = 0;
  355. Xunsigned int    s_logouts = 0;
  356. Xunsigned int    s_logins = 0;
  357. Xunsigned int    toptenmode = 0;
  358. Xlong            now = 0;
  359. Xstatic int      shutd_state = FALSE;
  360. X
  361. X#ifdef __STDC__
  362. Xvoid J_init_all(void)
  363. X#else
  364. XJ_init_all()
  365. X#endif
  366. X{ int i;
  367. X  for ( i = 0 ; i <= HASHTABLESIZE ; i++)
  368. X  {
  369. X   if (userlist[i].name != NULL)
  370. X    { 
  371. X    userlist[i].name = NULL; 
  372. X    userlist[i].current_logins = 0;
  373. X    userlist[i].max_conc_logins = 0;
  374. X    userlist[i].logins = 0;
  375. X    userlist[i].logintimebuf = 0;
  376. X    userlist[i].needs_timeset = FALSE;
  377. X    userlist[i].time = 0;
  378. X    userlist[i].total = 0;
  379. X    userlist[i].max_time = 0;
  380. X    }
  381. X  }
  382. X  ttylist = NULL;
  383. X  s_uptime = 0;
  384. X  s_start = 0;
  385. X  s_corr = 0;
  386. X  t_corr =0;
  387. X  s_stop = 0;
  388. X  s_reboots = 0;
  389. X  s_shutdowns = 0;
  390. X  s_crashes = 0;
  391. X  s_logouts = 0;
  392. X  s_logins = 0;
  393. X  shutd_state = FALSE;
  394. X  now = 0;
  395. X}
  396. X
  397. X#ifdef CONFIGFILE
  398. X
  399. XPRIVILEGED *shutdownusers;
  400. X
  401. XPRIVILEGED *config_init(filename)
  402. Xchar *filename;
  403. X{
  404. X  FILE *fp;
  405. X  PRIVILEGED *tmp = (PRIVILEGED *)NULL;
  406. X  char priv_user[UT_NAMESIZE];
  407. X
  408. X  fp =  (FILE *)fopen(filename,"r");
  409. X  if (fp == NULL) { 
  410. X       fprintf(stderr,"Warning: Could not open config file (%s)\n", 
  411. X               filename ); return((PRIVILEGED *)NULL);
  412. X  }
  413. X  while (fscanf(fp,"%s",&priv_user) != EOF) {
  414. X    priv_user[UT_NAMESIZE] = '\0';
  415. X    if ((tmp = (PRIVILEGED *)malloc(sizeof(PRIVILEGED))) == (PRIVILEGED *)NULL)
  416. X      fprintf(stderr,("Fatal: malloc failed in config\n"));
  417. X    else {
  418. X       tmp->next = shutdownusers;
  419. X       tmp->user = (char *) strdup (priv_user);
  420. X       shutdownusers = tmp;
  421. X    }
  422. X  }
  423. X  if (fclose(fp) == 0)
  424. X  {
  425. X    return(tmp);
  426. X  }
  427. X  else
  428. X  {
  429. X    fprintf(stderr, "Fatal: couldn't close %s\n", filename);
  430. X    exit(1);
  431. X  }
  432. X}
  433. X
  434. Xint privilege_check(username,list)
  435. Xchar *username;
  436. XPRIVILEGED *list;
  437. X{
  438. X  PRIVILEGED *T;
  439. X
  440. X  if (list != NULL) {
  441. X   for (T=list ; T != NULL ; T = T->next) {
  442. X#ifdef DEBUG
  443. X    fprintf(stderr,"Debug: privileges test %s for %s\n",list->user, username);
  444. X#endif /* DEBUG */
  445. X    if (!strncmp(T->user,username,UT_NAMESIZE))  return TRUE;
  446. X   }
  447. X  };
  448. X  return FALSE;
  449. X}
  450. X
  451. X#endif /* CONFIGFILE */
  452. X
  453. Xstatic int
  454. XSedgeHash(arg)
  455. Xchar           *arg;
  456. X{
  457. X  int             h;
  458. X
  459. X  for (h = 0; *arg != '\0'; arg++)
  460. X  {
  461. X    h = (64 * h + *arg) % HASHTABLESIZE;
  462. X  }
  463. X  return h;
  464. X}
  465. X
  466. Xstatic int
  467. XJ_hash(arg)
  468. Xchar           *arg;
  469. X{
  470. X  int             Index, i, count=0;
  471. X
  472. X  Index = (int) SedgeHash(arg);
  473. X
  474. X  if (userlist[Index].name == NULL)
  475. X  {
  476. X    return Index;
  477. X  }
  478. X  for (i = Index; userlist[i].name != NULL; i++)
  479. X  {
  480. X    count++;
  481. X    if (i == HASHTABLESIZE)
  482. X    {
  483. X      i = 0;
  484. X      if (userlist[i].name == NULL)
  485. X    return i;
  486. X    }
  487. X    else if (count == HASHTABLESIZE)
  488. X    {
  489. X      fprintf(stderr, "Fatal: Hash table is full.\n");
  490. X      exit(2);
  491. X    };
  492. X    if (strcmp(userlist[i].name, arg) == 0)
  493. X      return i;
  494. X  }
  495. X  return i;
  496. X}
  497. X
  498. Xint
  499. Xucompare(i, j)
  500. XUSER           *i, *j;
  501. X{
  502. X  if (i->time > j->time)
  503. X    return -1;
  504. X  else if (i->time < j->time)
  505. X    return 1;
  506. X  return 0;
  507. X}
  508. X
  509. Xstatic TTY     *
  510. XJ_gettty(thetty)
  511. Xchar           *thetty;
  512. X{
  513. X  register TTY   *cur, *T;
  514. X
  515. X  if (ttylist != NULL)
  516. X  {
  517. X    for (T = ttylist; T != NULL; T = T->next)
  518. X    {
  519. X      if (strncmp(thetty, T->tty, UT_LINESIZE) == 0)
  520. X      {
  521. X    return (T);
  522. X      };
  523. X    }
  524. X  };
  525. X  if ((cur = (TTY *) malloc(sizeof(TTY))) == NULL)
  526. X  {
  527. X    fprintf(stderr, "Fatal: malloc failed !\n");
  528. X    exit(1);
  529. X  }
  530. X  cur->next = ttylist;
  531. X  cur->tty = (char *) strdup(thetty);
  532. X  ttylist = cur;
  533. X  return (cur);
  534. X}
  535. X
  536. Xstatic int
  537. XJ_countlogins(uhash)
  538. Xint             uhash;
  539. X{
  540. X  register TTY   *curt;
  541. X  int             count = 0;
  542. X
  543. X  if (ttylist != NULL)
  544. X  {
  545. X    for (curt = ttylist; curt != NULL; curt = curt->next)
  546. X    {
  547. X      if ((curt->used) && (uhash == curt->user_hash))
  548. X      {
  549. X    count++;
  550. X      }
  551. X      else
  552. X    continue;
  553. X    }
  554. X  };
  555. X  return count;
  556. X}
  557. X
  558. Xstatic void
  559. XJ_logout(logouttime, cur)
  560. Xlong            logouttime;
  561. XTTY            *cur;
  562. X{
  563. X  long            stayed;
  564. X  long            definite;
  565. X  int             current;
  566. X
  567. X  if (cur->used == 0)
  568. X  {
  569. X    return;
  570. X  }
  571. X  else
  572. X  {
  573. X    cur->used = 0;
  574. X    if ((logouttime != now) || (now == 0))
  575. X      /* avoid counting users still logged in */ 
  576. X    { 
  577. X      s_logouts++;
  578. X    }
  579. X    current = J_countlogins(cur->user_hash);
  580. X    userlist[cur->user_hash].current_logins = current;
  581. X    stayed = logouttime - cur->time_in;
  582. X    if (stayed < 0) 
  583. X    {
  584. X      fprintf(stderr,"Error: user %s has a negative session time.\n",
  585. X                      userlist[cur->user_hash].name);
  586. X    };
  587. X    if (stayed > userlist[cur->user_hash].max_time)
  588. X    {
  589. X      userlist[cur->user_hash].max_time = stayed;
  590. X    };
  591. X    userlist[cur->user_hash].total += stayed;
  592. X    if (current == 0)
  593. X    {
  594. X      definite = logouttime - userlist[cur->user_hash].logintimebuf;
  595. X      userlist[cur->user_hash].time += definite;
  596. X    };
  597. X  }
  598. X}
  599. X
  600. Xstatic void
  601. XJ_login(inname, logintime, tty)
  602. Xchar           *inname, *tty;
  603. Xlong            logintime;
  604. X{
  605. X  int             uhash;
  606. X  register TTY   *thistty;
  607. X
  608. X  
  609. X  uhash = J_hash(inname);
  610. X  if (userlist[uhash].name == NULL)
  611. X  {
  612. X    userlist[uhash].name = (char *) strdup(inname);
  613. X  }
  614. X  else
  615. X  {
  616. X    while (strncmp(userlist[uhash].name, inname, sizeof(inname)) != 0)
  617. X    {
  618. X      fprintf(stderr, "Fatal: could not avoid hash collision at %d: %s %s\n",
  619. X          uhash, inname, userlist[uhash].name);
  620. X      exit(2);
  621. X    }
  622. X  }
  623. X  thistty = J_gettty(tty);
  624. X  if (thistty->used)
  625. X  { /* the tty is already in use */
  626. X    if (strcmp(userlist[thistty->user_hash].name,userlist[uhash].name) == 0)
  627. X    { /* the newly logged in user is already logged in */
  628. X      return;
  629. X    }
  630. X    else
  631. X    {
  632. X      J_logout(logintime, thistty);
  633. X        
  634. X#ifdef DEBUG
  635. X      fprintf(stderr, "Debug: %s did not log out. Replaced by %s...\n",
  636. X          userlist[thistty->user_hash].name,
  637. X          userlist[uhash].name);
  638. X#endif 
  639. X    }
  640. X  };
  641. X  s_logins++;
  642. X  userlist[uhash].logins++;
  643. X  if (userlist[uhash].current_logins < 0)
  644. X  {
  645. X    userlist[uhash].current_logins = 1;
  646. X  }
  647. X  else
  648. X  {
  649. X    userlist[uhash].current_logins++;
  650. X  }
  651. X  if (userlist[uhash].current_logins == 1)
  652. X  {
  653. X    userlist[uhash].logintimebuf = logintime;
  654. X  };
  655. X  if (userlist[uhash].max_conc_logins < userlist[uhash].current_logins)
  656. X  {
  657. X    userlist[uhash].max_conc_logins = userlist[uhash].current_logins;
  658. X  };
  659. X  thistty->time_in = logintime;
  660. X  thistty->user_hash = uhash;
  661. X  thistty->used = 1;
  662. X}
  663. X
  664. X#if __STDC__
  665. Xstatic void
  666. XJ_timeprep(void)
  667. X#else
  668. Xstatic void
  669. XJ_timeprep()
  670. X#endif
  671. X{
  672. X  register TTY   *cur;
  673. X
  674. X  if (ttylist != NULL)
  675. X  {
  676. X    for (cur = ttylist; cur != NULL; cur = cur->next)
  677. X    {
  678. X      if (cur->used == 1)
  679. X      {
  680. X    userlist[cur->user_hash].needs_timeset = TRUE;
  681. X      };
  682. X    }
  683. X  };
  684. X}
  685. X
  686. Xstatic void
  687. XJ_timeset(oldtime, newtime)
  688. Xlong            oldtime, newtime;
  689. X{
  690. X  long            diff;
  691. X  register TTY   *cur;
  692. X
  693. X  diff = newtime - oldtime;
  694. X  if (ttylist != NULL)
  695. X  {
  696. X    for (cur = ttylist; cur != NULL; cur = cur->next)
  697. X    {
  698. X      if (cur->used == 1)
  699. X      {
  700. X    cur->time_in += diff;
  701. X    if (userlist[cur->user_hash].needs_timeset == TRUE)
  702. X    {
  703. X      userlist[cur->user_hash].logintimebuf += diff;
  704. X      userlist[cur->user_hash].needs_timeset = FALSE;
  705. X    };
  706. X      };
  707. X    }
  708. X  };
  709. X  s_corr += diff;
  710. X  t_corr += diff;
  711. X#ifdef DEBUG
  712. X  fprintf(stderr, "Debug: date got set. Difference is: %ld\n", diff);
  713. X#endif
  714. X}
  715. X
  716. Xvoid
  717. XJ_cleanup(endtime)
  718. Xlong            endtime;
  719. X{
  720. X  register TTY   *cur;
  721. X
  722. X  if (ttylist != NULL)
  723. X  {
  724. X    for (cur = ttylist; cur != NULL; cur = cur->next)
  725. X    {
  726. X      if (cur->used)
  727. X      {
  728. X    J_logout(endtime, cur);
  729. X      }
  730. X      else
  731. X    continue;
  732. X    }
  733. X  };
  734. X}
  735. X
  736. Xstatic void
  737. XJ_reboot(sometime, reboottime, shutdowntime)
  738. Xlong            sometime, reboottime, shutdowntime;
  739. X{
  740. X  long            thetime, timediff;
  741. X
  742. X  if (shutd_state == TRUE)
  743. X  {
  744. X    timediff = reboottime - shutdowntime;
  745. X    s_corr += timediff;
  746. X    if (timediff < 0)
  747. X    {
  748. X      thetime = reboottime;
  749. X    }
  750. X    else
  751. X    {
  752. X      thetime = shutdowntime;
  753. X    }
  754. X    s_reboots++;
  755. X  }
  756. X  else
  757. X  {
  758. X    if (((reboottime - sometime) > 86400) || (sometime > shutdowntime))
  759. X    {
  760. X      fprintf(stderr, "Warning: You have had a serious crash, I suppose\n");
  761. X      thetime = sometime;
  762. X      timediff = reboottime - sometime;
  763. X      s_corr += timediff;
  764. X      s_crashes++;
  765. X    }
  766. X    else
  767. X    {
  768. X      thetime = reboottime;
  769. X      s_shutdowns++;
  770. X      s_reboots++;
  771. X    }
  772. X  }
  773. X  J_cleanup(thetime);
  774. X}
  775. X
  776. Xstatic void
  777. XJ_print(list)
  778. XUSER           *list;
  779. X{
  780. X  int             i,rank=0;
  781. X  long            localv;
  782. X
  783. X  localv = now - (s_start + t_corr);
  784. X  if (localv < 0) {
  785. X    fprintf(stderr,"Warning: negative time covered!\n");
  786. X  };
  787. X
  788. X  s_uptime = now - (s_start + s_corr);
  789. X  if (s_uptime < 0) {
  790. X    fprintf(stderr,"Warning: negative uptime!\n");
  791. X  };
  792. X
  793. X  printf("--- System statistics---\n");
  794. X  printf("Start at:     %s", ctime((time_t *)&s_start));
  795. X  printf("End at:       %s", ctime((time_t *)&now));
  796. X  printf("Time covered:");
  797. X  timefmt(localv);
  798. X  printf("\n");
  799. X  printf("Uptime:      ");
  800. X  timefmt(s_uptime);
  801. X  printf("  (%.1f %% of total time)\n",
  802. X     (((float) s_uptime / (float) localv) * 100.0));
  803. X  printf("Booted:       %d times", s_reboots);
  804. X  printf("  (shut down %d times)\n", s_shutdowns);
  805. X  printf("Crashed:      %d times\n", s_crashes);
  806. X  printf("Logins:       %d\n", s_logins);
  807. X  printf("Logouts:      %d\n", s_logouts);
  808. X  printf("\n--- User statistics---\n");
  809. X  qsort((char *) ((USER *) list), (size_t) HASHTABLESIZE, (size_t) sizeof(struct anUser), ucompare);
  810. X if(toptenmode == 1) {
  811. X  for (i = 0; i < HASHTABLESIZE; i++)
  812. X  {
  813. X    if (list[i].name != NULL)
  814. X    {
  815. X      rank++;
  816. X      printf("%4d %-22s",
  817. X             rank,
  818. X             (char *)J_gecos_parse(list[i].name));
  819. X      timefmt(list[i].time);
  820. X      printf(" (%6d logins)\n",list[i].logins);
  821. X    };
  822. X  } 
  823. X } 
  824. X else {
  825. X  printf("user      logins ttys       real      total    longest    average   %%uptime\n");
  826. X
  827. X  for (i = 0; i < HASHTABLESIZE; i++)
  828. X  {
  829. X    if (list[i].name != NULL)
  830. X    {
  831. X      printf("%-9s %6d %4d", list[i].name, list[i].logins,
  832. X         list[i].max_conc_logins);
  833. X      timefmt(list[i].time);
  834. X      timefmt(list[i].total);
  835. X#ifdef DEBUG
  836. X      if (list[i].time > list[i].total) 
  837. X      {
  838. X        fprintf(stderr,"Debug: total time greater than real time: %s\n",
  839. X                       list[i].name);
  840. X      }
  841. X#endif
  842. X      timefmt(list[i].max_time);
  843. X      timefmt((list[i].total / list[i].logins));
  844. X      printf("   %7.2f\n", (((float) list[i].time / (float) s_uptime) * 100));
  845. X    };
  846. X  }
  847. X }
  848. X}
  849. X
  850. Xvoid
  851. XJ_read_wtmp(fp, def)
  852. XFILE           *fp;
  853. Xint             def;
  854. X{
  855. X  struct utmp     logbuf, *uptr;
  856. X  int             first = TRUE;
  857. X  long            timebuf = 0;
  858. X  char            curuser[UT_NAMESIZE+1];
  859. X  char            curline[UT_LINESIZE+1];
  860. X  long            tob = 0, dot = 0;
  861. X  
  862. X  while (fread((char *) &logbuf, 1, sizeof(logbuf), fp) == sizeof(logbuf))
  863. X  {
  864. X    s_stop = logbuf.ut_time;
  865. X    if (first == TRUE)
  866. X    {
  867. X      first = FALSE;
  868. X      tob = s_stop;
  869. X      s_start = s_stop;
  870. X    };
  871. X    if ( s_stop < s_start ) 
  872. X    {
  873. X      fprintf(stderr,"Error: time scope vulneration... resetting\n");
  874. X      J_init_all();
  875. X    };
  876. X#ifndef SYSV
  877. X    if (!strncmp("reboot", logbuf.ut_name, 6))
  878. X#else
  879. X    if (logbuf.ut_type == BOOT_TIME)
  880. X#endif
  881. X    {
  882. X      J_reboot(tob, s_stop, dot);
  883. X      shutd_state = FALSE;
  884. X      continue;
  885. X    }
  886. X    else if (!strncmp("shutdown", logbuf.ut_name, UT_NAMESIZE)
  887. X#ifndef SYSV
  888. X         || logbuf.ut_line[0] == '~' 
  889. X#endif
  890. X             || shutd_state == TRUE 
  891. X#ifdef CONFIGFILE
  892. X             || (privilege_check(logbuf.ut_name,shutdownusers) == TRUE) 
  893. X#endif
  894. X            )
  895. X    {
  896. X      tob = s_stop;
  897. X      if (shutd_state == FALSE)
  898. X      {
  899. X    shutd_state = TRUE;
  900. X    s_shutdowns++;
  901. X    dot = logbuf.ut_time;
  902. X    continue;
  903. X      }
  904. X      else
  905. X    continue;
  906. X    }
  907. X#ifndef SYSV
  908. X    else if (logbuf.ut_line[0] == '|' && !logbuf.ut_line[1])
  909. X#else
  910. X    else if (logbuf.ut_type == OLD_TIME)
  911. X#endif
  912. X  {
  913. X      timebuf = logbuf.ut_time;
  914. X      J_timeprep();
  915. X      tob = s_stop;
  916. X      continue;
  917. X    }
  918. X#ifndef SYSV
  919. X    else if (logbuf.ut_line[0] == '{' && !logbuf.ut_line[1])
  920. X#else
  921. X    else if (logbuf.ut_type == NEW_TIME)
  922. X#endif
  923. X    {
  924. X      tob = s_stop;
  925. X      if (timebuf != 0)
  926. X      {
  927. X#ifdef DEBUG
  928. X        fprintf(stderr,"Debug: timesetting %ld\n",(logbuf.ut_time - timebuf));
  929. X#endif
  930. X    J_timeset(timebuf, logbuf.ut_time);
  931. X    continue;
  932. X      }
  933. X      else
  934. X    continue;
  935. X    }
  936. X    else if ((!strncmp("ftp", logbuf.ut_line, 3)) ||
  937. X         (!strncmp("uucp", logbuf.ut_line, 4)))
  938. X    {
  939. X      shutd_state = FALSE;
  940. X      tob = s_stop;
  941. X      continue;
  942. X    }
  943. X#ifndef SYSV
  944. X    else if (isalnum(logbuf.ut_name[0]) != 0)
  945. X#else
  946. X    else if (logbuf.ut_type == USER_PROCESS)
  947. X#endif
  948. X    {
  949. X      shutd_state = FALSE;
  950. X      uptr = &logbuf;
  951. X      curuser[UT_NAMESIZE] = '\0';
  952. X      curline[UT_LINESIZE] = '\0';
  953. X
  954. X      strncpy(curuser, uptr->ut_name, UT_NAMESIZE);
  955. X      strncpy(curline, uptr->ut_line, UT_LINESIZE);
  956. X      J_login(curuser, uptr->ut_time, curline);
  957. X      tob = s_stop;
  958. X      continue;
  959. X    }
  960. X#ifndef SYSV
  961. X    else if (logbuf.ut_line != NULL)
  962. X#else
  963. X    else if (logbuf.ut_type == DEAD_PROCESS)
  964. X#endif
  965. X    {
  966. X      curline[UT_LINESIZE] = '\0';
  967. X      strncpy(curline, logbuf.ut_line, UT_LINESIZE);
  968. X      J_logout(logbuf.ut_time, J_gettty(curline));
  969. X      tob = s_stop;
  970. X      continue;
  971. X    }
  972. X    else
  973. X    {
  974. X#ifndef SYSV
  975. X      fprintf(stderr, "Warning: Strange entry at %s\n%s %s\n",
  976. X              ctime((time_t *)&logbuf.ut_time), 
  977. X              logbuf.ut_name, logbuf.ut_line);
  978. X#endif
  979. X      tob = s_stop;
  980. X      continue;
  981. X    }
  982. X  }
  983. X  if (def == 0)
  984. X  {
  985. X    now = s_stop;
  986. X  }
  987. X  else
  988. X  {
  989. X    now = (long) time((time_t *) 0);
  990. X  }
  991. X  J_cleanup(now);
  992. X  J_print(userlist);
  993. X}
  994. X
  995. Xvoid
  996. Xmain(argc, argv)
  997. Xint             argc;
  998. Xchar          **argv;
  999. X{
  1000. X  FILE           *fd;
  1001. X#ifdef WTMP_FILE
  1002. X  char           *wtmp = WTMP_FILE;
  1003. X#else
  1004. X  char           *wtmp = "/usr/adm/wtmp";
  1005. X#endif
  1006. X#ifdef CONFIGFILE
  1007. X  char           *configfile = CONFIGFILE;
  1008. X#endif
  1009. X  int             def = 1;
  1010. X
  1011. X  while (--argc > 0 && **++argv == '-')
  1012. X    switch (*++*argv)
  1013. X    {
  1014. X    case 'w':
  1015. X      if (--argc > 0)
  1016. X      {
  1017. X    wtmp = *++argv;
  1018. X    def--;
  1019. X      }
  1020. X      continue;
  1021. X    case 't':
  1022. X      toptenmode++;
  1023. X      continue;
  1024. X#ifdef CONFIGFILE
  1025. X    case 'c':
  1026. X      if (--argc > 0)
  1027. X      {
  1028. X        configfile = *++argv;
  1029. X      }
  1030. X      continue;
  1031. X#endif
  1032. X    }
  1033. X#ifdef CONFIGFILE 
  1034. X    shutdownusers = config_init(configfile);
  1035. X#endif 
  1036. X
  1037. X  fd = (FILE *) fopen(wtmp, "r");
  1038. X  if (fd == NULL)
  1039. X  {
  1040. X    fprintf(stderr, "Fatal: %s ... no such file\n", wtmp);
  1041. X    exit(1);
  1042. X  }
  1043. X  J_read_wtmp(fd, def);
  1044. X  if (fclose(fd) == 0)
  1045. X  {
  1046. X    exit(0);
  1047. X  }
  1048. X  else
  1049. X  {
  1050. X    fprintf(stderr, "Fatal: couldn't close %s\n", wtmp);
  1051. X    exit(1);
  1052. X  }
  1053. X}
  1054. END-of-freeks-1.32/freeks.c
  1055. echo x - freeks-1.32/freeks.cat
  1056. sed 's/^X//' >freeks-1.32/freeks.cat << 'END-of-freeks-1.32/freeks.cat'
  1057. X
  1058. X
  1059. X
  1060. Xfreeks(6)          Freeks 1.32 Geeking Manual           freeks(6)
  1061. X
  1062. X
  1063. X
  1064. XNAME
  1065. X     freeks - fast 'geeks style' login accounting
  1066. X
  1067. XSYNOPSIS
  1068. X     freeks [-w wtmp ] [-t] [-c configfile ]
  1069. X
  1070. X
  1071. XDESCRIPTION
  1072. X     Freeks is a  fast  and  reduced  version  of  geeks(6).  The
  1073. X     default for wtmp is "/usr/adm/wtmp".
  1074. X
  1075. X     Freeks produces a report on system usage based on  the  con-
  1076. X     tents  of wtmp and sorted by the actual time different users
  1077. X     have spent on the system.   The  format  of  the  output  is
  1078. X     almost  similar  to geeks(6). The first lines are different,
  1079. X     they contain general information about the  system.  In  the
  1080. X     'User  statistics' section the last field is different also,
  1081. X     containing the percentage of total  uptime  the  user  spent
  1082. X     logged in to the system.
  1083. X
  1084. X
  1085. X
  1086. XOPTIONS
  1087. X     You may specify an alternate wtmp file on the command line.
  1088. X
  1089. X     With the 't' option the user statistics are modified,  show-
  1090. X     ing  the  'geek rank', the name, the time the user was actu-
  1091. X     ally logged in and the number of logins.
  1092. X
  1093. X     With the 'c' option you can specify a configfile  containing
  1094. X     the  names of alternative 'shutdown' users (cf. TODO), which
  1095. X     is probably interesting to SysV machine owners only.
  1096. X
  1097. X
  1098. XBUGS
  1099. X     Freeks is (almost) limited to BSD style wtmp files (cf. TODO
  1100. X     below). It does not have a lot of fancy options. It does not
  1101. X     include a server similar to geeksd(6). Freeks does make some
  1102. X     mistakes,  e.g. when a reboot entry in wtmp happened without
  1103. X     a shutdown before it. If the last entry happened more than a
  1104. X     day  before  the  reboot  entry,  freeks  presumes  that the
  1105. X     machine crashed, and will use the time  of  the  last  entry
  1106. X     before  the crash as time of shutdown. This may lead to mar-
  1107. X     ginal errors in 'uptime' and the login times of users  still
  1108. X     logged in at that time.
  1109. X
  1110. X     Another bug happens when time is changed in single user mode
  1111. X     which  means it doesn't get logged. Don't do that, or delete
  1112. X     the wtmp file afterwards.
  1113. X
  1114. X
  1115. X
  1116. X
  1117. X
  1118. X
  1119. XApostolos Lytras   Last change: June 24, 1994                   1
  1120. X
  1121. X
  1122. X
  1123. X
  1124. X
  1125. X
  1126. Xfreeks(6)          Freeks 1.32 Geeking Manual           freeks(6)
  1127. X
  1128. X
  1129. X
  1130. XTODO
  1131. X     System V has changed a lot in wtmp but it should be possible
  1132. X     to  run the program, if you rarely shut your machine down or
  1133. X     have a dedicated 'shutdown' user that logs in when you  shut
  1134. X     down. If this user is called 'shutdown' you needn't do noth-
  1135. X     ing, if his login name is something else,  you  can  specify
  1136. X     that  in configfile (if, of course, freeks had been compiled
  1137. X     with CONFIGFILE defined...).
  1138. X
  1139. X
  1140. X
  1141. XSEE ALSO
  1142. X     geeks(5) geeks(6) ac(8) wtmp(5) wtmpfix(8) login(1) init(8)
  1143. X
  1144. X
  1145. XFILES
  1146. X     /usr/adm/wtmp       wtmp file
  1147. X
  1148. XAUTHOR
  1149. X     Copyright     (C)     1994     by      Apostolos      Lytras
  1150. X     (lytras@avalon.unizh.ch).
  1151. X
  1152. X     Thanks to Dave P.  Gymer  (dpg@cs.nott.ac.uk)  and  everyone
  1153. X     that  helped  him  write  geeks(6). It has been an important
  1154. X     inspiration and a reason to write this program  (because  it
  1155. X     was just too slow, geeks! ;-).
  1156. X
  1157. X     Thanks also to Wietse Venema for his information  on  SVR4's
  1158. X     wtmp.
  1159. X
  1160. X     Some of the credit must also go to the University  of  Cali-
  1161. X     fornia,  Berkeley,  for  their  programs  ac(8), last(1) and
  1162. X     uptime(1), which evaluate /usr/adm/wtmp as well. These  pro-
  1163. X     grams  were  inspiring  as  well,  because  they couldn't do
  1164. X     everything real geeks needed them to.
  1165. X
  1166. X     This is free software; you can redistribute it and/or modify
  1167. X     it under the terms of the GNU General Public License as pub-
  1168. X     lished by the Free Software Foundation; either version 2  of
  1169. X     the License, or (at your option) any later version.
  1170. X
  1171. X     The GNU General Public License is not included in the origi-
  1172. X     nal  distrubution  of freeks. If you don't have a copy of it
  1173. X     already, write to the Free  Software  Foundation,  675  Mass
  1174. X     Ave, Cambridge, MA 02139, USA.
  1175. X
  1176. X     This program is distributed in the hope that  it   will   be
  1177. X     useful,  but  WITHOUT ANY WARRANTY; without even the implied
  1178. X     warranty of MERCHANTABILITY or FITNESS  FOR   A   PARTICULAR
  1179. X     PURPOSE.    See   the  GNU  General  Public License for more
  1180. X     details.
  1181. X
  1182. X
  1183. X
  1184. X
  1185. XApostolos Lytras   Last change: June 24, 1994                   2
  1186. X
  1187. X
  1188. X
  1189. X
  1190. X
  1191. X
  1192. Xfreeks(6)          Freeks 1.32 Geeking Manual           freeks(6)
  1193. X
  1194. X
  1195. X
  1196. X
  1197. X
  1198. X
  1199. X
  1200. X
  1201. X
  1202. X
  1203. X
  1204. X
  1205. X
  1206. X
  1207. X
  1208. X
  1209. X
  1210. X
  1211. X
  1212. X
  1213. X
  1214. X
  1215. X
  1216. X
  1217. X
  1218. X
  1219. X
  1220. X
  1221. X
  1222. X
  1223. X
  1224. X
  1225. X
  1226. X
  1227. X
  1228. X
  1229. X
  1230. X
  1231. X
  1232. X
  1233. X
  1234. X
  1235. X
  1236. X
  1237. X
  1238. X
  1239. X
  1240. X
  1241. X
  1242. X
  1243. X
  1244. X
  1245. X
  1246. X
  1247. X
  1248. XApostolos Lytras   Last change: June 24, 1994                   3
  1249. X
  1250. X
  1251. X
  1252. X
  1253. X
  1254. X
  1255. END-of-freeks-1.32/freeks.cat
  1256. echo x - freeks-1.32/freeks.h
  1257. sed 's/^X//' >freeks-1.32/freeks.h << 'END-of-freeks-1.32/freeks.h'
  1258. X/* --- start of configurable section --- */
  1259. X/*
  1260. X * HASHTABLESIZE must be prime, such as 61,113,251,509,1021 To save memory
  1261. X * choose a value close to the number of users on your system.
  1262. X *
  1263. X * Note:
  1264. X * This is not a full-fledged hashing library, just some code stolen from
  1265. X * "Algorithms in C" by Robert Sedgewick which has been refined to avoid hash
  1266. X * collisions. The algorithm which does this is very simple and probably not
  1267. X * worth a lot in more complex programs. (It does not handle removal from the
  1268. X * list, because that won't happen in this application.)
  1269. X */
  1270. X#ifndef HASHTABLESIZE
  1271. X#define HASHTABLESIZE 1021
  1272. X#endif
  1273. X
  1274. X/* NO_STRDUP:
  1275. X * if your system doesn't have the strdup routine, then uncomment the
  1276. X * definition below.  
  1277. X */
  1278. X/* #define NO_STRDUP */
  1279. X
  1280. X/* WANTGECOS:
  1281. X * If you want to use GECOS entries ("real names") in 'freeks -t' output
  1282. X * define this
  1283. X */
  1284. X#ifndef WANTGECOS
  1285. X#define WANTGECOS
  1286. X#endif
  1287. X
  1288. X/* DEBUG:
  1289. X * If you want to get more debugging output on standard error, then
  1290. X * uncomment this here or look at the debugflags in the Makefile
  1291. X */
  1292. X/* #define DEBUG */
  1293. X
  1294. X/* CONFIGFILE */
  1295. X/* System V users might want to create a configfile containing the   */
  1296. X/* names of additional usernames that create a shutdown, like `halt' */
  1297. X/* or `powerdown'. Each username must appear separately on a line in */
  1298. X/* the file                                                          */
  1299. X/* #define CONFIGFILE "/usr/local/lib/freeks/config" */
  1300. X
  1301. X/* --- you shouldn't need to change much below this --- */
  1302. X
  1303. X#if defined(__hpux)
  1304. X#ifndef SYSV
  1305. X#define _CLASSIC_ID_TYPES
  1306. X#endif
  1307. X#endif
  1308. X
  1309. X#include <stdlib.h>
  1310. X#include <stdio.h>
  1311. X#include <time.h>
  1312. X#include <sys/file.h>
  1313. X#include <ctype.h>
  1314. X#ifndef SYSV
  1315. X#include <utmp.h>
  1316. X#include <strings.h>
  1317. X#else
  1318. X#include <utmpx.h>
  1319. X#include <string.h>
  1320. X#ifndef ut_name
  1321. X#define ut_name ut_user
  1322. X#endif
  1323. X#endif
  1324. X
  1325. X#ifdef WANTGECOS
  1326. X#include <pwd.h>
  1327. X/***************************************************************/
  1328. X/* MAX_GECOS_LEN is the maximum length of a gecos entry in the */
  1329. X/* password database for use in topten ( option '-t' ) mode    */
  1330. X/* Default: 20                                                 */
  1331. X/***************************************************************/
  1332. X#define MAX_GECOS_LEN 20
  1333. X#define minimum(a,b)  (a < b) ? a : b 
  1334. X#endif /* WANTGECOS */
  1335. X
  1336. Xstruct utmp dummy;
  1337. X#define UT_NAMESIZE sizeof (dummy.ut_name)
  1338. X#define UT_LINESIZE sizeof (dummy.ut_line)
  1339. X
  1340. X#define TRUE 1
  1341. X#define FALSE 0
  1342. X
  1343. X#define timefmt(time) \
  1344. Xprintf(" %4ld:%02ld:%02ld", (time) / 3600, ((time) / 60) % 60, (time) % 60)
  1345. X
  1346. X#ifndef NO_STRDUP
  1347. X#if (defined(__ultrix__) || defined(nextstep3))
  1348. X#define NO_STRDUP
  1349. X#endif /* ultrix or nextstep */
  1350. X#endif
  1351. X
  1352. Xtypedef struct anUser
  1353. X{
  1354. X  char           *name;
  1355. X  int             current_logins;
  1356. X  int             max_conc_logins;
  1357. X  int             logins;
  1358. X  long            logintimebuf;
  1359. X  int             needs_timeset;
  1360. X  long            time;
  1361. X  long            total;
  1362. X  long            max_time;
  1363. X}               USER;
  1364. X
  1365. Xtypedef struct aTty
  1366. X{
  1367. X  char           *tty;
  1368. X  int             used;
  1369. X  int             user_hash;
  1370. X  long            time_in;
  1371. X  struct aTty    *next;
  1372. X}               TTY;
  1373. X
  1374. X#ifdef CONFIGFILE
  1375. Xtypedef struct priv_list {
  1376. X  char             *user;
  1377. X  struct priv_list *next;
  1378. X}               PRIVILEGED ;
  1379. X#endif
  1380. X
  1381. END-of-freeks-1.32/freeks.h
  1382. echo x - freeks-1.32/gecos.c
  1383. sed 's/^X//' >freeks-1.32/gecos.c << 'END-of-freeks-1.32/gecos.c'
  1384. X/* gecos.c                                                             */
  1385. X/* Apostolos Lytras. June 1994                                         */
  1386. X/* This little program gets a user name on its command line for which  */
  1387. X/* it searches /etc/passwd's gecos entry and strips everything but the */
  1388. X/* first of its (comma delimited) fields...                            */
  1389. X/* BUGS: maybe the first field is not the user's real name... ?!       */
  1390. X
  1391. X#include "freeks.h"
  1392. X
  1393. X#ifndef WANTGECOS
  1394. X
  1395. Xchar *J_gecos_parse(string)
  1396. Xchar *string;
  1397. X{ 
  1398. X   return string;  /* dummy function */
  1399. X}
  1400. X
  1401. X#else
  1402. X
  1403. Xchar *J_gecos_parse(namen)
  1404. Xchar *namen;
  1405. X{
  1406. X  char out[MAX_GECOS_LEN], *output, *input;
  1407. X  int len, i;
  1408. X  struct passwd *dastruct;
  1409. X
  1410. X  dastruct = (struct passwd *) malloc (sizeof(struct passwd *));
  1411. X  if ((dastruct = getpwnam(namen)) == (struct passwd *)NULL )
  1412. X  { 
  1413. X#ifdef DEBUG
  1414. X    fprintf(stderr,"Debug: user %s is not in password file.\n",namen); 
  1415. X#endif
  1416. X    return namen;
  1417. X  };
  1418. X  if ((input = (char *)strdup(dastruct->pw_gecos)) == (char *)NULL)
  1419. X  {
  1420. X    fprintf(stderr,"Fatal: allocation for GECOS failed.\n");
  1421. X    exit(-2);
  1422. X  };
  1423. X  len = minimum((MAX_GECOS_LEN - 1),strlen(input));
  1424. X  for ( i = 0; (i <= len) && (input[i] != ',') ; i++, out[i] = '\0')
  1425. X  {
  1426. X    out[i] = input[i];
  1427. X  }
  1428. X  output = (char *)strdup(out);
  1429. X  return output;
  1430. X}
  1431. X
  1432. X#endif
  1433. END-of-freeks-1.32/gecos.c
  1434. exit
  1435.