home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume41 / casu / part03 < prev    next >
Encoding:
Text File  |  1994-01-09  |  54.4 KB  |  2,153 lines

  1. Newsgroups: comp.sources.misc
  2. From: lm@rmit.edu.au (Luke Mewburn)
  3. Subject: v41i078:  casu - comms. & status utils, v3.3, Part03/04
  4. Message-ID: <1994Jan10.025649.4047@sparky.sterling.com>
  5. X-Md4-Signature: 3bf92249c483c0d79f2794f14a265997
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Mon, 10 Jan 1994 02:56:49 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: lm@rmit.edu.au (Luke Mewburn)
  12. Posting-number: Volume 41, Issue 78
  13. Archive-name: casu/part03
  14. Environment: UNIX, ANSI-C
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  casu-3.3/FLON.rof casu-3.3/TO.rof casu-3.3/casu.h
  21. #   casu-3.3/fileio.c casu-3.3/print.c
  22. # Wrapped by kent@sparky on Sun Jan  9 20:46:38 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 3 (of 4)."'
  26. if test -f 'casu-3.3/FLON.rof' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'casu-3.3/FLON.rof'\"
  28. else
  29.   echo shar: Extracting \"'casu-3.3/FLON.rof'\" \(10759 characters\)
  30.   sed "s/^X//" >'casu-3.3/FLON.rof' <<'END_OF_FILE'
  31. X'\" t
  32. X.\" (the above line is to tell sun's man to run through tbl first)
  33. X.\"
  34. X.\"    flon - lists your friends who are logged on
  35. X.\"
  36. X.\" Part of the CaSU package written by Luke Mewburn <lm@rmit.edu.au>
  37. X.\"
  38. X.\" To format this manual page, format it through a `tbl' compatible
  39. X.\" filter, then through an nroff or troff compatible formatter.
  40. X.\"
  41. X.TH FLON 1 "December 23 1993"
  42. X.SH NAME
  43. Xflon \- show which of your friends are logged on
  44. X.SH SYNOPSIS
  45. X.B flon
  46. X.RB [ \-a ]
  47. X.RB [ \-A ]
  48. X.RB [ \-b ]
  49. X.RB [ \-B ]
  50. X.RB [ \-d ]
  51. X.RB [ \-D ]
  52. X.RB [ \-e ]
  53. X.RB [ \-E ]
  54. X.RB [ \-h ]
  55. X.RB [ \-H ]
  56. X.RB [ \-i ]
  57. X.RB [ \-I ]
  58. X.RB [ \-p\c
  59. X.IR "\ max_idle" ]
  60. X.RB [ \-P\c
  61. X.IR "\ min_idle" ]
  62. X.RB [ \-t ]
  63. X.RB [ \-T ]
  64. X.RB [ \-f\c
  65. X.IR "\ file" ]
  66. X.RB [ \-o\c
  67. X.IR "\ format" ]
  68. X.RB [ \-O ]
  69. X.RB [ \-y\c
  70. X.IR "\ mesgy" ]
  71. X.RB [ \-Y ]
  72. X.RB [ \-n\c
  73. X.IR "\ mesgn" ]
  74. X.RB [ \-N ]
  75. X.RB [ \-U\c
  76. X.IR "\ file" ]
  77. X.RB [ \-v ]
  78. X.RB [ \-V ]
  79. X.RB [ \-w ]
  80. X.SH DESCRIPTION
  81. X.I flon
  82. Xshows which of your friends are currently logged on
  83. Xby matching entries in
  84. X.B /etc/utmp
  85. Xwith entries in
  86. X.BR "$HOME/.friends" ,
  87. Xand displaying the matches.
  88. X.PP
  89. XThe output that can displayed by
  90. X.I flon
  91. Xis extremely configurable, and a variety of information
  92. Xabout your friends can be discovered.
  93. XEven the output of
  94. X.I who
  95. Xcan be emulated, (but
  96. X.I flon
  97. Xis often much faster.)
  98. X.PP
  99. XThe actual
  100. X.B friends file
  101. Xthat
  102. X.I flon
  103. Xuses is user definable.
  104. X.PP
  105. XThe friends file has the following format:
  106. X.TS
  107. Xcenter;
  108. Xl l.
  109. Xuserid    pseudonym
  110. Xuserid    pseudonym
  111. Xuserid    pseudonym
  112. X.TE
  113. X.PP
  114. XAny number of blank lines can occur between userid and pseudonym
  115. Xpairs, and field separators are any white space,
  116. X.B except
  117. Xfor one case: A pseudonym is only terminated
  118. Xby an end of line or EOF, because tabs and spaces can exist in
  119. Xpseudonyms.
  120. X.PP
  121. XInformation such as
  122. X.BR "user name" ,
  123. X.BR "pseudonym" ,
  124. X.BR "real name" ,
  125. X.BR "login time" ,
  126. X.BR "idle time" ,
  127. X.BR "tty" ,
  128. X.BR "remote host"
  129. X(if supported on your system), and
  130. X.B "mesg status"
  131. Xcan all be displayed by
  132. X.IR "flon" .
  133. X.PP
  134. XThe
  135. X.B pseudonym
  136. Xrefers to the entry in the friends file corresponding to a particular
  137. X.BR "user name" .
  138. X.PP
  139. XIf
  140. X.I who
  141. Xis linked to
  142. X.IR "flon" ,
  143. Xthen flon will act much the same as the BSD version of who.
  144. X.SH OPTIONS
  145. X.I flon
  146. Xaccepts the following options:
  147. X.TP
  148. X.B \-a
  149. XShow all entries, irrespective of whether or not they appear in the
  150. Xcurrent friends file.
  151. XIf
  152. X.B "%p"
  153. Xis present in the format string, and the current entry is in the
  154. Xfriends file, the appropriate pseudonym is listed, otherwise a blank
  155. Xentry is displayed.
  156. X.TP
  157. X.B \-A
  158. XThe opposite of
  159. X.BR "\-a" ,
  160. Xthis only lists users in the friends file.
  161. X.TP
  162. X.B \-b
  163. XWhen used in conjunction with the format string specifier
  164. X.BR "%p" ,
  165. Xthen whenever a pseudonym cannot be found for the current entry, the
  166. Xappropriate real name for that user (obtained from the GCOS field of the
  167. X.B /etc/passwd
  168. Xfile) will be used (if there is one.)
  169. XThis option is only useful if
  170. X.B \-a
  171. Xis used.
  172. X.TP
  173. X.B \-B
  174. XThe opposite of
  175. X.BR "\-b" ,
  176. Xwhich only prints pseudonyms with the
  177. X.B "%p"
  178. Xformat specifier.
  179. X.TP
  180. X.B \-d
  181. XDon't print duplicates (where the user name is the same.)
  182. XFor the
  183. X.BR "%l" ,
  184. X.BR "%i" ,
  185. X.BR "%m" ,
  186. Xand
  187. X.B %t
  188. Xoptions,
  189. X.I flon
  190. Xprints the information of the session with the least
  191. Xidle time.
  192. X.TP
  193. X.B \-D
  194. XDo print duplicates.
  195. X(Opposite of
  196. X.BR "\-d" .)
  197. X.TP
  198. X.B \-e
  199. XExclude the listing of your friends.
  200. XThis option implies
  201. X.BR "\-a" .
  202. X.TP
  203. X.B \-E
  204. XInclude the listing of your friends.
  205. X(Opposite of
  206. X.BR "\-e" .)
  207. X.TP
  208. X.B \-h
  209. XDon\'t display the header at the top of the output of
  210. X.IR "flon" .
  211. X.TP
  212. X.B \-H
  213. XDisplay the header at the top of the output.
  214. X.TP
  215. X.B \-i
  216. XDon't display people that have been idle for longer than
  217. Xfive minutes (This cutout time can be changed with
  218. X.BR "\-p" .)
  219. X.TP
  220. X.B \-I
  221. XDisplay people that have been idle for longer than five minutes.
  222. X(Opposite of
  223. X.BR "\-i" .)
  224. X.TP
  225. X.BI \-p " limit"
  226. XSets the idle cutout limit for
  227. X.B \-i
  228. Xand
  229. X.B \-I
  230. Xto
  231. X.IR "limit" .
  232. XThe default unit for this limit is minutes, but a suffix of
  233. X.I "s"
  234. Xor
  235. X.I "S"
  236. Xindicates that the figure is in seconds.
  237. X(A suffix of
  238. X.I "m"
  239. Xor
  240. X.I "M"
  241. Xexplicitly specificies that the units are minutes.)
  242. X.TP
  243. X.BI \-P " limit"
  244. XSet the minimum period at which the idle message switches from
  245. X.RB \` ... \'
  246. Xto the actual value.
  247. XRefer to
  248. X.B \-p
  249. Xfor information on valid suffixes to this figure.
  250. X.TP
  251. X.B \-t
  252. XDon't display the trailer \(em the count of how many times
  253. Xyou are logged on, and the total of how many people are logged on.
  254. X.TP
  255. X.B \-T
  256. XDisplay the trailer.
  257. X.TP
  258. X.BI \-f " file"
  259. XUse
  260. X.I file
  261. Xas the friends file (instead of
  262. X.B $HOME/.friends .)
  263. X.TP
  264. X.BI \-o " format"
  265. XUse
  266. X.I format
  267. Xas the template for
  268. X.IR "flon" 's
  269. Xoutput.
  270. X(See below for the specification of
  271. X.IR "format" .)
  272. X.TP
  273. X.B \-O
  274. XUse the default compiled-in format, which is usually:
  275. X.br
  276. X.BI "%-u | %p | %12l | %i | %t | %2mTalk"
  277. X.TP
  278. X.BI \-y " string"
  279. XUse
  280. X.I string
  281. Xas the string to print in
  282. X.B "%p"
  283. Xwhen messages are on.
  284. X.TP
  285. X.B \-Y
  286. XUse the compiled in default for ontalk, usually
  287. X.RB \` On \'\&.
  288. X.TP
  289. X.BI \-n " string"
  290. XUse
  291. X.I string
  292. Xas the string to print in
  293. X.B "%p"
  294. Xwhen messages are off.
  295. X.TP
  296. X.B \-N
  297. XUse the compiled in default for notalk, usually
  298. X.RB \` No \'\&.
  299. X.TP
  300. X.BI \-U " file"
  301. XUse
  302. X.I file
  303. Xas the utmp file (instead of
  304. X.BR "/etc/utmp" .)
  305. X.TP
  306. X.BI "\-v, \-V"
  307. XDisplay the version, usage and copyright information.
  308. X.TP
  309. X.B \-w
  310. XInvoke
  311. X.I flon
  312. Xas if it was invoked as
  313. X.IR "who" .
  314. X(I.e., simulate that it's name is
  315. X.IR "who" ,
  316. Xto the point where
  317. X.RI \` "flon -w am I" \'
  318. Xacts as
  319. X.RI \` "who am I" \',
  320. Xetc.)
  321. X.SH FORMAT SPECIFIERS
  322. X.I flon
  323. Xhas a highly configurable output, which consists of a format
  324. Xstring with static and variable fields.
  325. XMuch like
  326. X.IR "printf" (3),
  327. Xthe format string of
  328. X.I flon
  329. Xuses the
  330. X.B %
  331. Xcharacter as a specifier for the variable fields.
  332. XThis is the format of the specifier:
  333. X.B %\c
  334. X.RI [ flags ]\c
  335. X.RI [ width ]\c
  336. X.IR "command" .
  337. X.PP
  338. X.I flags
  339. Xare optional.
  340. XThere are two flags currently available:
  341. X.TP
  342. X.B \-
  343. Xuse right justification for formatting that field.
  344. X.TP
  345. X.B \&.
  346. Xuse a variant width record (i.e, extra space won't be added
  347. Xas padding to fill out the field to the required width.)
  348. X.PP
  349. X.I width
  350. Xcan be anything from 0 to 255.
  351. XIf a width of
  352. X.BR "0" ,
  353. Xor no width at all is specified,
  354. Xthe default width for that field is assumed.
  355. X.PP
  356. X.I specifiers
  357. Xcan be any of:
  358. X.TP
  359. X.B %
  360. XA single % sign.
  361. X.TP
  362. X.B u
  363. XUser name of the current entry.
  364. X.TP
  365. X.B r
  366. XReal name of the current entry.
  367. X(From the
  368. X.B /etc/passwd
  369. Xfile.)
  370. X.TP
  371. X.B p
  372. XPseudonym of this person.
  373. XWhen
  374. X.I flon
  375. Xis started with
  376. X.BR "\-a" ,
  377. Xa pseudonym will be shown only for those people who have one in your
  378. Xfriends file.
  379. XThe only exception is when
  380. X.B \-b
  381. Xis used - then the real name will be printed instead (
  382. X.B "%p"
  383. Xacts the same as the
  384. X.B "%r"
  385. Xin this case)
  386. X.TP
  387. X.B l
  388. XLogin time on that particular session.
  389. X.TP
  390. X.B i
  391. XIdle time of that session.
  392. XThe value is in
  393. X.BR "minutes : seconds" .
  394. XIf the string
  395. X.RB \` >>> \'
  396. Xis displayed, the session has been idle longer than 99 minutes, 59
  397. Xseconds.
  398. XIf
  399. X.RB \` ... \'
  400. Xis displayed, the terminal has not been idle for at least 5 minutes.
  401. X(The latter time is changable with
  402. X.BR "\-P" .)
  403. X.TP
  404. X.B t
  405. XThe tty of that particular session.
  406. X.TP
  407. X.B m
  408. X.I mesg
  409. Xstatus of that session.
  410. XIf
  411. X.IR "y" ,
  412. X.RB \` On \'
  413. Xis displayed (unless
  414. X.B \-y
  415. X.I mesgy
  416. Xis defined, then
  417. X.I mesgy
  418. Xwill be displayed.)
  419. XIf it is
  420. X.IR "n" ,
  421. X.RB \` No \'
  422. Xis displayed (or
  423. X.I mesgn
  424. Xif
  425. X.B \-n
  426. X.I mesgn
  427. Xis used.)
  428. X.TP
  429. X.B c
  430. XNumber of times that person is logged on.
  431. X.TP
  432. X.B x
  433. XPrints an
  434. X.RB \` x \'
  435. Xif the number of times logged on is greater than 1.
  436. X.TP
  437. X.B a
  438. XPrints the 
  439. X.I mesgy
  440. Xstring if any of the sessions for that person have messages on.
  441. X(The `availability' field.)
  442. XIf all sessions have messages off, the
  443. X.I mesgn
  444. Xstring is printed.
  445. X.TP
  446. X.B h
  447. XPrint the host that the user logged in from, but only if your system
  448. Xsupports it (via the existance of the
  449. X.I ut_host
  450. Xfield in the 
  451. X.BR "/etc/utmp" .)
  452. XOtherwise, an empty string will be printed.
  453. X.TP
  454. X.B b
  455. XPrint the host (see
  456. X.BR "%h" )
  457. Xin parenthesis if the field is non-empty.
  458. X.SH ENVIRONMENT
  459. X.TP
  460. X.B FLON
  461. XContains default arguments that the user wants
  462. X.I flon
  463. Xto use.
  464. XCommand line options override any settings in
  465. X.IR "FLON" .
  466. X.TP
  467. X\&
  468. XThe
  469. X.I FLON
  470. Xvariable can contain any of the command line arguments.
  471. XIf a string is to have a space in it, it should be quoted with
  472. Xsingle quotes, as:
  473. X.RB \' word1 ... wordn \'
  474. XNote that some options (like
  475. X.BR "\-V" )
  476. Xwont make sense in the environment variable.
  477. X.TP
  478. X\&
  479. XFor example (in
  480. X.IR "csh" (1))
  481. X.IP
  482. Xsetenv FLON "-ip30 -o'%-u %32p'"
  483. X.TP
  484. X\&
  485. Xwill mean that by default,
  486. X.I flon
  487. Xwon't print sessions idle longer than 30 minutes, and for each friend,
  488. Xonly the username (right justified), and the pseudonym (field width of
  489. X32 characters) will be printed.
  490. X.SH FILES
  491. X.PD 0
  492. X.TP 20
  493. X.B $\s-1HOME\s0/.friends
  494. X.TP 20
  495. X.B /etc/utmp
  496. X.TP 20
  497. X.B /etc/passwd
  498. X.PD
  499. X.SH EXAMPLE FRIENDS FILE
  500. X.TS
  501. Xl l.
  502. Xs902113    Zak
  503. Xroot    Deus ex Machina
  504. Xzrmitcs    Rmit Computer Society
  505. Xnroot    Root with a _REAL_ shell
  506. X.TE
  507. X.SH SEE ALSO
  508. X.IR "who" (1),
  509. X.IR "utmp" (5).
  510. X.SH LIMITATIONS
  511. XThe maximum width of any specified field is 255 characters.
  512. X.PP
  513. X.SH WARNINGS
  514. XIf a tty in /dev cannot be statted, flon will print an entry
  515. Xfor that user, but without the mesg or idle status.
  516. X.PP
  517. XIf the friends file is unavailable (due to permissions or non-existance),
  518. Xthen flon will operate as if run with the
  519. X.I \-a
  520. X(list all) option, with no pseudonyms.
  521. X.SH HISTORY
  522. X.I flon
  523. Xhas a long line of ancestors.
  524. XMany years ago at RMIT, on the
  525. X.I Cyber 760
  526. Xrunning
  527. X.IR "NOS" ,
  528. XMarc Boschma [Tau] wrote lon.
  529. XPrimitive as it was, it did the job, looking up your friends logged on.
  530. XWhen UNIX arrived at RMIT, it was soon ported, with a version by Simon
  531. XBurge [Snark] also appearing.
  532. XOther versions were written, including a derivative
  533. X.IR "bcoh" .
  534. XThe problem was that
  535. X.IR "lon" ,
  536. X.IR "bcoh" ,
  537. Xand all the derivatives were slow, and lacked
  538. X.IR "rampant featuritus"
  539. X(although some may consider this lack a
  540. X.BR "good thing" .)
  541. XThese factors prompted me to write
  542. X.IR "flon" .
  543. X.PP
  544. XFor their suggestions, bug fixes, and hints, thanks go to:
  545. X.TS
  546. Xcenter;
  547. Xl l.
  548. XAlbert Zvara    <s902117@minyos.xx.rmit.oz.au>
  549. XAndrew Vanderstock    <rxkajv@minyos.xx.rmit.oz.au>
  550. XCedric    <rcv@ukc.ac.uk>
  551. XCraig Humphrey    <Craig.Humphrey@comp.vuw.ac.nz>
  552. XDavid W. Sanderson    <dws@ssec.wisc.edu>
  553. XHoward Picaizen    <doctor@binkley.cs.mcgill.ca>
  554. XKeith    <basil@cs.odu.edu>
  555. XKen Weaverling    <weave@pima.dtcc.edu>
  556. XMarc Boschma    <s861298@minyos.xx.rmit.oz.au>
  557. XMatthew Korth    <sparhawk@camelot.bradley.edu>
  558. XJohn DuBois    <spcecdt@armory.com>
  559. XStuart Bishop    <zen@rmit.edu.au>
  560. XWes W. Price II    <ww2@bullwinkle.ssc.gov>
  561. XWillem Kasdorp    <wkasdo@nikhefk.nikhef.nl>
  562. X.TE
  563. X.PP
  564. X.SH AUTHOR
  565. XLuke Mewburn, <lm@rmit.edu.au>.
  566. X.PP
  567. XPortions of the environment variable code are derived from code from
  568. X.IR "gzip" ,
  569. Xby Jean-loup Gailey, which in turn was derived from code I donated
  570. Xto that package.
  571. X.SH VERSION
  572. XThis manual documents
  573. X.I flon
  574. Xversion 3.3.1, 931223.
  575. END_OF_FILE
  576.   if test 10759 -ne `wc -c <'casu-3.3/FLON.rof'`; then
  577.     echo shar: \"'casu-3.3/FLON.rof'\" unpacked with wrong size!
  578.   fi
  579.   # end of 'casu-3.3/FLON.rof'
  580. fi
  581. if test -f 'casu-3.3/TO.rof' -a "${1}" != "-c" ; then 
  582.   echo shar: Will not clobber existing file \"'casu-3.3/TO.rof'\"
  583. else
  584.   echo shar: Extracting \"'casu-3.3/TO.rof'\" \(8063 characters\)
  585.   sed "s/^X//" >'casu-3.3/TO.rof' <<'END_OF_FILE'
  586. X'\" t
  587. X.\" (the above line is to tell sun's man to run through tbl first)
  588. X.\"
  589. X.\"    To - send a one line message to another user
  590. X.\"
  591. X.\" Part of the CaSU package written by Luke Mewburn <lm@rmit.edu.au>
  592. X.\"
  593. X.\" To format this manual page, format it through a `tbl' compatible
  594. X.\" filter, then through an nroff or troff compatible formatter.
  595. X.\"
  596. X.TH TO 1 "December 23 1993"
  597. X.SH NAME
  598. Xto \- send a one line message to another user.
  599. X.SH SYNOPSIS
  600. X.B to
  601. X.RB [ \-a\c
  602. X.IR "\ alias\ user" ]
  603. X.RB [ \-b ]
  604. X.RB [ \-e\c
  605. X.IR "\ user" ]
  606. X.RB [ \-h ]
  607. X.RB [ \-l ]
  608. X.RB [ \-r ]
  609. X.RB [ \-t\c
  610. X.IR "\ term" ]
  611. X.RB [ \-u\c
  612. X.IR "\ alias" ]
  613. X.RB [ \-n ]
  614. X.RB [ \-y ]
  615. X.RB [ \-P\c
  616. X.IR "\ pseudonym" ]
  617. X.RB [ \-G\c
  618. X.IR "\ gonereply" ]
  619. X.RB [ \-N\c
  620. X.IR "\ noreply" ]
  621. X.RB [ \-Y\c
  622. X.IR "\ yesreply" ]
  623. X.RB [ \-I\c
  624. X.IR "\ idlereply" ]
  625. X.RB [ \-X\c
  626. X.IR "\ excludereply" ]
  627. X[
  628. X.I user
  629. X[ 
  630. X.IR message
  631. X] ]
  632. X.SH DESCRIPTION
  633. X.I to
  634. Xsends a short message to another user.
  635. XThe default format for the message that the destination user receives is:
  636. X.IP
  637. X-=> From user ( userid@host ) on ttyxx at 12:00 :-
  638. X.br
  639. X.I message
  640. X.PP
  641. XThe recipient of the message can, at this point, choose to reply
  642. Xusing the same method.
  643. XIf the recipient has defined an
  644. X.B auto-reply
  645. Xmessage, you will receive a message back of the form:
  646. X.IP
  647. X-=> Auto-reply from username :-
  648. X.br
  649. X.I message
  650. X.PP
  651. XAll of the arguments to
  652. X.I to
  653. Xafter the username are treated as part of the message.
  654. XIf a message isn't specified, then you are prompted to enter a
  655. Xmessage interactively.
  656. XThis is useful if you wish to enter a message that has characters
  657. Xwhich would need to be escaped from the shell, and you're too
  658. Xlazy to do that.
  659. XIf no message is entered, then
  660. X.RI \` "I would like to talk to you" \'
  661. Xis sent.
  662. X.PP
  663. XYou can specify a user by a username, an alias, or with
  664. X.RB \` \&. \'
  665. X(a period.)
  666. XThe use of a period indicates that you wish to send the message to
  667. Xthe last person that you sent a message to (if you've sent one.)
  668. XThe message will be sent to the same tty as last time unless you
  669. Xspecify a new tty via the
  670. X.B \-t
  671. Xoption.
  672. X.PP
  673. XIf an alias is defined for the user string you entered, it will be
  674. Xused, otherwise 
  675. X.I to
  676. Xwill attempt to send the message to the user on the system with
  677. Xthat name.
  678. X.PP
  679. XIf the recipient is logged on in more that one place, the message will
  680. Xbe sent to the terminal with the least idle time (unless a specific
  681. Xterminal is requested via
  682. X.BR \-t .)
  683. XIf you are sending a message to yourself, the current terminal will
  684. Xonly receive a message if you explicitly state it as the destination
  685. Xterminal (This is useful if a friend is logged under your userid and
  686. Xyou wish to send them a message.)
  687. X.PP
  688. XYou can exclude a user from transmitting a message to you by adding
  689. Xthem to your exclude list (by using the
  690. X.B \-e
  691. Xcommand line option.)
  692. X.PP
  693. XAuto-reply messages are returned to you depending upon the conditions
  694. Xin which the message was received.
  695. XThey are:
  696. X.TP
  697. X.B gone
  698. XThe auto-reply for when the recipient isn't logged on.
  699. X.TP
  700. X.B idle
  701. XThe auto-reply for when you are idle more than 5 minutes (overrides the
  702. X.B yes
  703. Xmessage.)
  704. X.TP
  705. X.B no
  706. XThe auto-reply for when the message didn't get through.
  707. X.TP
  708. X.B yes
  709. XThe auto-reply for when the message was successfully sent.
  710. X(Useful for when you are working or you're temporarily busy, and want
  711. Xto let the message to still get through.)
  712. X.TP
  713. X.B exclude
  714. XThe auto-reply message to people you've excluded.
  715. X.PP
  716. XBy default,
  717. X.I to
  718. Xuses your name from the
  719. X.B /etc/passwd
  720. Xfile.
  721. XThis is overridden (in ascending order) by the environment variable
  722. X.BR NAME ,
  723. Xthe environment variable
  724. X.BR PSEUDONYM ,
  725. Xand finally, the
  726. X.B \-p
  727. Xcommand line option.
  728. X.PP
  729. XIf you have your messages disabled, and you are sending a message to a user
  730. Xother than yourself, you will receive a warning telling you that the the
  731. Xrecipient can't respond.
  732. X.SH OPTIONS
  733. X.I to
  734. Xaccepts the following options (in any combination):
  735. X.TP
  736. X.BI \-a " alias userid"
  737. XDefine an alias,
  738. X.I alias
  739. Xfor the user
  740. X.IR "userid" .
  741. X.TP
  742. X.B \-b
  743. XBeep the recipient (with an ASCII BELL character.)
  744. X.TP
  745. X.BI \-e " userid"
  746. XAdd
  747. X.I userid
  748. Xto the list of people you've excluded from sending you messages.
  749. X.TP
  750. X.B \-h
  751. XDisplay a usage and help page.
  752. X.TP
  753. X.B \-l
  754. XList all the aliases that you have defined.
  755. X.TP
  756. X.B \-r
  757. XDisplay some status about
  758. X.IR to ,
  759. Xincluding: mesg status, current name, current terminal, yes auto-reply,
  760. Xno auto-reply, gone auto-reply, and last user.
  761. X.TP
  762. X.BI \-t " term"
  763. XForce the message to be sent to the terminal
  764. X.IR "term" .
  765. XIt will only be sent if the recipient is currently using that terminal.
  766. X.TP
  767. X.BI \-u " alias"
  768. XRemove 
  769. X.I alias
  770. Xfrom your alias list.
  771. X.TP
  772. X.BI "\-n, \-y"
  773. XSet the
  774. X.B mesg
  775. Xstatus to off or on respectivly.
  776. XThis performs the same purpose as
  777. X.IR "mesg" (1).
  778. X.TP
  779. X.BI \-P " pseudonym"
  780. XSets your pseudonym.
  781. X.TP
  782. X.BI \-Y " yesmess"
  783. XSets your auto-reply message for when a message gets through successfully.
  784. X.TP
  785. X.BI \-I " idlemess"
  786. XSets your auto-reply message for when a message gets through
  787. Xsuccessfully and the recipient (you) has been idle for more than
  788. Xfive minutes.
  789. X.TP
  790. X.BI \-N " nomess"
  791. XSets your auto-reply message for when a transmission is unsuccessful.
  792. X.TP
  793. X.BI \-G " gonemess"
  794. XSets your auto-reply message for when you aren't logged on.
  795. X.TP
  796. X.BI \-X " excludemess"
  797. XSets your auto-reply message to send to a person who you've excluded.
  798. X.TP
  799. X.B \-V
  800. XDisplay the usage and copyright information.
  801. X.SH ENVIRONMENT
  802. X.TP 12
  803. X.B PSEUDONYM
  804. XName to display when sending messages and auto-replies.
  805. X.TP
  806. X.B NAME
  807. XUsed if
  808. X.B PSEUDONYM
  809. Xisn't defined.
  810. X.SH FILES
  811. X.PD 0
  812. X.TP 20
  813. X.B $\s-1HOME\s0/.torc
  814. X.TP 20
  815. X.B /etc/utmp
  816. X.TP 20
  817. X.B /etc/passwd
  818. X.PD
  819. X.PP
  820. XThe
  821. X.B .torc
  822. Xfile is an ASCII file, which may be directly edited rather than using
  823. Xthe command line options (although the author doesn't recommend this
  824. Xtechnique.)
  825. XEach line has the following format:
  826. X.br
  827. X\- A single character type specifier (case insensitive, but shown
  828. Xwith case here for mnemonic reference with the command line options.)
  829. X.br
  830. X\- A single space
  831. X.br
  832. X\- The arguments to the command.
  833. X.PP
  834. XThe following characters are valid as type specifiers:
  835. X.TP 3
  836. X.B \&.
  837. XThe last person to whom you sent a message.
  838. X.TP
  839. X.B :
  840. XThe tty of the last person to whom you sent a message.
  841. X.TP
  842. X.B Y
  843. XThe
  844. X.I yes
  845. Xauto-reply.
  846. X.TP
  847. X.B N
  848. XThe
  849. X.I no
  850. Xauto-reply.
  851. X.TP
  852. X.B G
  853. XThe
  854. X.I gone
  855. Xauto-reply.
  856. X.TP
  857. X.B I
  858. XThe
  859. X.I idle
  860. Xauto-reply.
  861. X.TP
  862. X.B X
  863. XThe
  864. X.I exclude
  865. Xauto-reply.
  866. X.TP
  867. X.B P
  868. XThe pseudonym which is printed in the auto-reply.
  869. X.TP
  870. X.B a
  871. XAn alias. This takes the format of
  872. X.IR "alias userid" ,
  873. Xwith whitespace separating the two elements
  874. X.TP
  875. X.B e
  876. XAn excluded user.
  877. X.PP
  878. XAn unknown specifier or illegal line will be silently ignored by
  879. X.IR "to" .
  880. X.SH SEE ALSO
  881. X.IR "mesg" (1),
  882. X.IR "utmp" (5),
  883. X.IR "talk" (1),
  884. X.IR "write" (1).
  885. X.SH LIMITATIONS
  886. XThe maximum length of a userid is 8 characters.
  887. XThe maximum length of an alias is 16 characters.
  888. XThe maximum length of an auto-reply, pseudonym, or message is 256 characters.
  889. XAny non-ASCII, or control characters in the message will be replaced with
  890. Xa
  891. X.RB \` ? \'\&.
  892. X.PP
  893. X.I to
  894. Xcan only send an auto-reply message to another user if that user has
  895. Xworld read access (\fI\-rw\-r\-\-r\-\-\fP) to your
  896. X.I .torc
  897. Xfile, and at least search access (\fIdrwx\-\-x\-\-x\fP)
  898. Xto your home directory.
  899. X.PP
  900. XThe message that you send appears on the command line, and thus, can
  901. Xbe read (for a short time), by the use of commands such as
  902. X.IR "ps" (1).
  903. XIf you want to send top secret or personal messages, you shouldn't
  904. Xbe using electronic media!
  905. X.SH HISTORY
  906. X.I to
  907. Xwas inspired by (and is upwardly compatible with) a program written
  908. Xby Steve Riehm [Romulis].
  909. XSteve's version was based on one by Simon Burge [Snark].
  910. X.PP
  911. XFor their inspiration, ideas and bug reports, thanks must go to:
  912. X.TS
  913. Xcenter;
  914. Xl l.
  915. XAndrew Vanderstock    <rxkajv@minyos.xx.rmit.oz.au>
  916. XCraig Humphrey    <Craig.Humphrey@comp.vuw.ac.nz>
  917. XJohn DuBois    <spcecdt@armory.com>
  918. XKeith    <basil@cs.odu.edu>
  919. XKen Weaverling    <weave@pima.dtcc.edu>
  920. XMarc Boschma    <s861298@minyos.xx.rmit.oz.au>
  921. XSteve Riehm    <ln-smr@pki-nbg.philips.de>
  922. XWillem Kasdorp    <wkasdo@nikhefk.nikhef.nl>
  923. X.TE
  924. X.SH AUTHOR
  925. XLuke Mewburn, <lm@rmit.edu.au>.
  926. X.SH VERSION
  927. XThis manual documents
  928. X.I to
  929. Xversion 3.3.1, 931223.
  930. END_OF_FILE
  931.   if test 8063 -ne `wc -c <'casu-3.3/TO.rof'`; then
  932.     echo shar: \"'casu-3.3/TO.rof'\" unpacked with wrong size!
  933.   fi
  934.   # end of 'casu-3.3/TO.rof'
  935. fi
  936. if test -f 'casu-3.3/casu.h' -a "${1}" != "-c" ; then 
  937.   echo shar: Will not clobber existing file \"'casu-3.3/casu.h'\"
  938. else
  939.   echo shar: Extracting \"'casu-3.3/casu.h'\" \(11418 characters\)
  940.   sed "s/^X//" >'casu-3.3/casu.h' <<'END_OF_FILE'
  941. X/*
  942. X *  CaSU - communications & status utilities.
  943. X *  Copyright (C) 1992, 1993 Luke Mewburn <lm@rmit.edu.au>
  944. X *    incorporating:
  945. X *       flon - lists your friends who are logged on.
  946. X *       to - send a short message to a friend
  947. X *
  948. X *  This program is free software; you can redistribute it and/or modify
  949. X *  it under the terms of the GNU General Public License as published by
  950. X *  the Free Software Foundation; either version 2 of the License, or
  951. X *  (at your option) any later version.
  952. X *  
  953. X *  This program is distributed in the hope that it will be useful,
  954. X *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  955. X *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  956. X *  GNU General Public License for more details.
  957. X *  
  958. X *  You should have received a copy of the GNU General Public License
  959. X *  along with this program; if not, write to the Free Software
  960. X *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  961. X *
  962. X */
  963. X
  964. X
  965. X#include "patchlevel.h"        /* for VERSION */
  966. X
  967. X
  968. X#if STDC_HEADERS
  969. X#   define __PROT(prototype)    prototype
  970. X    typedef void *        voidptr;
  971. X#else
  972. X#   define __PROT(prototype)    ()
  973. X    typedef char *        voidptr;
  974. X#endif /* STDC_HEADERS */
  975. X
  976. X
  977. X#include <stdio.h>
  978. X#include <sys/types.h>
  979. X#include <sys/param.h>
  980. X#include <sys/stat.h>
  981. X#include <sys/time.h>
  982. X#if HAVE_UNISTD_H
  983. X#   include <unistd.h>
  984. X#endif /* HAVE_UNISTD_H */
  985. X#if HAVE_STDLIB_H || STDC_HEADERS
  986. X#   include <stdlib.h>
  987. X#else  /* !HAVE_STDLIB_H && !STDC_HEADERS */
  988. X#   if !MALLOC_DECL
  989. X    extern void     free    __PROT((voidptr));
  990. X    extern voidptr     malloc    __PROT((size_t));
  991. X    extern voidptr     calloc    __PROT((size_t, size_t));
  992. X#   endif /* !MALLOC_DECL */
  993. X#endif  /* !HAVE_STDLIB_H && !STDC_HEADERS */
  994. X#include <string.h>
  995. X#include <ctype.h>
  996. X#include <fcntl.h>
  997. X#include <errno.h>
  998. X#include <pwd.h>
  999. X#include <limits.h>
  1000. X#if HAVE_PATHS_H
  1001. X#   include <paths.h>        /* for _PATH_DEV */
  1002. X#endif /* HAVE_PATHS_H */
  1003. X#if NEED_NETDB_H
  1004. X#   include <netdb.h>
  1005. X#endif /* NEED_NETDB_H */
  1006. X#if HAVE_UNAME && HAVE_SYS_UTSNAME_H
  1007. X#   include <sys/utsname.h>
  1008. X    extern int        uname        __PROT((struct utsname *));
  1009. X#endif
  1010. X#if HAVE_GETHOSTNAME && !GETHOSTNAME_DECL
  1011. X    extern int        gethostname    __PROT((char *, size_t));
  1012. X#endif /* HAVE_GETHOSTNAME && !GETHOSTNAME_DECL */
  1013. X
  1014. X#ifndef MAXPATHLEN
  1015. X#   ifdef PATH_MAX
  1016. X#    define MAXPATHLEN    PATH_MAX
  1017. X#   else
  1018. X#    define MAXPATHLEN    256
  1019. X#   endif
  1020. X#endif
  1021. X
  1022. X#ifndef MAXHOSTNAMELEN
  1023. X#   define MAXHOSTNAMELEN    256
  1024. X#endif
  1025. X
  1026. X#if HAVE_UTMPX_H
  1027. X#   include <utmpx.h>            /* assume includes <utmp.h> */
  1028. X#   define PATH_UTMP        UTMPX_FILE
  1029. X#   define getutent        getutxent
  1030. X#   define endutent        endutxent
  1031. X    typedef struct utmpx    utmp_s;
  1032. X#   define UT_TIME        ut_tv.tv_sec
  1033. X#else /* !HAVE_UTMPX_H */
  1034. X#   include <utmp.h>
  1035. X#   define UT_TIME        ut_time
  1036. X    typedef struct utmp        utmp_s;
  1037. X#endif /* !HAVE_UTMPX_H */
  1038. X#ifndef PATH_UTMP            /* don'cha love standards? */
  1039. X#   ifdef _PATH_UTMP
  1040. X#       define PATH_UTMP _PATH_UTMP
  1041. X#   else
  1042. X#    ifdef UTMP_FILE
  1043. X#        define PATH_UTMP UTMP_FILE
  1044. X#    else
  1045. X#        define PATH_UTMP "/etc/utmp"
  1046. X#    endif
  1047. X#   endif
  1048. X#endif
  1049. X
  1050. X#ifndef _PATH_PASSWD
  1051. X#   define _PATH_PASSWD    "/etc/passwd"
  1052. X#endif
  1053. X
  1054. X
  1055. Xextern utmp_s Kludge;
  1056. X#ifndef UT_NAMESIZE
  1057. X#   define UT_NAMESIZE    sizeof(Kludge.ut_name)
  1058. X#endif
  1059. X
  1060. X#ifndef UT_HOSTSIZE
  1061. X#   if HAVE_UT_HOST
  1062. X#    define UT_HOSTSIZE    sizeof(Kludge.ut_host)
  1063. X#   else
  1064. X#    define UT_HOSTSIZE    UT_NAMESIZE
  1065. X#   endif
  1066. X#endif /* not UT_HOSTSIZE */
  1067. X
  1068. X#ifndef UT_LINESIZE
  1069. X#   define UT_LINESIZE    sizeof(Kludge.ut_line)
  1070. X#endif
  1071. X
  1072. X        /* SYS V utmp format */
  1073. X#if HAVE_UT_TYPE
  1074. X#   define NULL_UTMP_ENTRY(x)    ((x)->ut_type != USER_PROCESS \
  1075. X                || (x)->ut_name[0] == '\0')
  1076. X#else
  1077. X        /* BSD utmp format */
  1078. X#   define NULL_UTMP_ENTRY(x)    ((x)->ut_name[0] == '\0')
  1079. X#endif
  1080. X
  1081. X
  1082. Xextern    char    *optarg;
  1083. Xextern    int    optind,    opterr, errno;
  1084. X
  1085. Xextern char *sys_errlist[];
  1086. X
  1087. X#if !HAVE_STRERROR
  1088. X#   define strerror(x)    sys_errlist[x]
  1089. X#endif
  1090. X
  1091. X
  1092. X#ifndef _PATH_DEV
  1093. X#    define _PATH_DEV    "/dev/"
  1094. X#endif /* _PATH_DEV */
  1095. X
  1096. X#define    MINIDLE        300    /* 5 mins; flon: for `...', to: for idlereply */
  1097. X#define    MAXIDLE        6000    /* 100 mins */
  1098. X#define ONEDAY        60*60*24
  1099. X#define IDLE_MULTIPLY    60    /* default unit for -p & -P is minutes */
  1100. X#define NUM_SPECIFIERS    12    /* number of specifier types (%args) in -o */
  1101. X#define ALIASLEN    16    /* len of `to' alias */
  1102. X#define LINESIZ        256    /* nice figure */
  1103. X#define BELL        7
  1104. X
  1105. X#define STRuser        "USER"
  1106. X#define    STRhome        "HOME"
  1107. X#define    STRflon        "FLON"
  1108. X#define STRsep        "\014\n\r\t "
  1109. X#define STReoln        "\014\n\r"
  1110. X#define STRtorc        "/.torc"
  1111. X#define    STRdotfriends    ".friends"
  1112. X#define STRformat    "%-u | %p | %12l | %i | %t | %2mTalk"
  1113. X#define STRyes        "On"
  1114. X#define STRno        "No"
  1115. X
  1116. X#define PWsep        ":"
  1117. X#define PWGCOSsep    ":,"
  1118. X#define PWeoln        STReoln
  1119. X
  1120. X#define    WHO_PROG    "who"
  1121. X#define WHO_NULLTTY    "tty??"
  1122. X#define WHO_AM_I_FMT    "%.*s  %.7s  %.12s\n"
  1123. X#if HAVE_UT_HOST
  1124. X#   define WHO_FORMAT    "%u %7t %12l %.34b"
  1125. X#else
  1126. X#   define WHO_FORMAT    "%u %7t %12l"
  1127. X#endif
  1128. X
  1129. X#if TTY_RESTRICTED
  1130. X#   define MESGS_ON    020
  1131. X#else
  1132. X#   define MESGS_ON    022        /* mask if messages are on */
  1133. X#endif
  1134. X
  1135. X
  1136. Xenum            /* flon flags */
  1137. X{
  1138. X    NO_HEADER=    (1<<0),    /* don't want header */
  1139. X    NO_TAILER=    (1<<1),    /* don't want tailer */
  1140. X    ONE_ONLY=    (1<<2),    /* remove duplicates */
  1141. X    ALL_ON=    (1<<3),    /* list all on */
  1142. X    NO_IDLE=    (1<<4),    /* remove idle entries */
  1143. X    BEST_NAME=    (1<<5),    /* print real name if no pseudonym */
  1144. X    NEED_STAT=    (1<<6),    /* need to stat() the ttys */
  1145. X    NEED_FFILE=    (1<<7),    /* need to load ~/.friends */
  1146. X    NEED_PASSWD=(1<<8),    /* need to load /etc/passwd */
  1147. X    BLANKF=    (1<<9),    /* field is to be blanked */
  1148. X    NO_MATES=    (1<<10),/* exclude friends */
  1149. X    /* expansion room */
  1150. X    ERROR_OPT=    (1<<14),/* error somewhere */
  1151. X    COPYLEFT=    (1<<15)    /* display copyleft: always must be after ERROR_OPT */
  1152. X};
  1153. X
  1154. Xenum            /* to flags */
  1155. X{
  1156. X    DEBUG=        (1<<0),
  1157. X    BEEP=        (1<<1),
  1158. X    LISTALIAS=        (1<<2),
  1159. X    STATUS=        (1<<3),
  1160. X    MESG_N=        (1<<4),
  1161. X    MESG_Y=        (1<<5),
  1162. X    HELP=        (1<<6),
  1163. X    LISTVERSION=    (1<<7),
  1164. X    ERROR=        (1<<8),
  1165. X    DB_MOD=        (1<<9),
  1166. X    PSEUDO_MOD=        (1<<10)
  1167. X};
  1168. X
  1169. Xenum            /* contains printdat cmd info */
  1170. X{
  1171. X    MAX_WIDTH =    0x00FF,    /* max val of an 8 bit unsigned entity */
  1172. X    C_WIDMASK =    0x00FF,    /* mask for widths */
  1173. X    C_NULL =    0x0100,    /* empty space */
  1174. X    C_USER =    0x0200,    /* username */
  1175. X    C_PSEUDO =    0x0300,    /* pseudonym */
  1176. X    C_REAL =    0x0400,    /* real name */
  1177. X    C_COUNT =    0x0500,    /* # times on */
  1178. X    C_X =    0x0600,    /* an 'x' */
  1179. X    C_LOGIN =    0x0700,    /* login time */
  1180. X    C_IDLE =    0x0800,    /* idle time */
  1181. X    C_TTY =    0x0900,    /* terminal */
  1182. X    C_MESG =    0x0A00,    /* mesg status */
  1183. X    C_AVAIL =    0x0B00,    /* availability */
  1184. X    C_HOST =    0x0C00,    /* remote host */
  1185. X    C_HOSTBRK =    0x0D00, /* remote host (in parenthesis) */
  1186. X    C_CMDMASK =    0x3F00,    /* mask for cmds */
  1187. X    C_VARIENT =    0x4000,    /* varient width */
  1188. X    C_RIGHT =    0x8000    /* right align */
  1189. X};
  1190. X
  1191. X
  1192. Xtypedef struct        /* flon: name/pseudonym pair struct */
  1193. X{
  1194. X    char name[UT_NAMESIZE+1];
  1195. X    char *pseudo;
  1196. X} frend;
  1197. X
  1198. Xtypedef struct        /* relevant info from passwd db */
  1199. X{
  1200. X    char *    username;    /* user name */
  1201. X    uid_t    uid;        /* uid */
  1202. X    char *    gcos;        /* real name */
  1203. X} upwd;
  1204. X
  1205. Xtypedef struct alist_S    /* to: linked list of alias/username for */
  1206. X{
  1207. X    char        userid[ UT_NAMESIZE + 1 ];
  1208. X    char        alias[ ALIASLEN + 1 ];    /* [0] == 0 if exclude entry */
  1209. X                        /* otherwise, it's an alias */
  1210. X    struct alist_S    *next;
  1211. X} alist;
  1212. X
  1213. Xtypedef struct        /* to: stores all info from ~/.torc for src & dest */
  1214. X{            /*    an entry is unused if [0] == 0 */
  1215. X    char    userid[ UT_NAMESIZE + 1];    /* username */
  1216. X    char    name[ LINESIZ + 1 ];        /* realname or pseudo */
  1217. X    char    homedir[ MAXPATHLEN + 1 ];    /* $HOME */
  1218. X    char    dotuser[ UT_NAMESIZE + 1 ];    /* last user `.user' */
  1219. X    char    dottty[ UT_LINESIZE + 1 ];    /* last user's tty  */
  1220. X    char    yes[ LINESIZ + 1 ];        /* `yes' autoreply */
  1221. X    char    no[ LINESIZ + 1 ];        /* `no' autoreply */
  1222. X    char    gone[ LINESIZ + 1 ];        /* `gone' autoreply */
  1223. X    char    idle[ LINESIZ + 1 ];        /* `idle' autoreply */
  1224. X    char    exclude[ LINESIZ + 1 ];        /* `exclude' autoreply */
  1225. X    char     message[ LINESIZ + 1 ];        /* actual message to send */
  1226. X    alist *    aliases;            /* linked list of aliases */
  1227. X    char *    tty;                /* pointer to tty name */
  1228. X} user_t;
  1229. X
  1230. X
  1231. X
  1232. X#ifdef _MAIN_            /* only declare storage once for globals */
  1233. X#   define GLOBAL
  1234. X#else
  1235. X#   define GLOBAL    extern
  1236. X#endif
  1237. X
  1238. XGLOBAL int    flags;            /* various flags */
  1239. XGLOBAL char *    progname;        /* basename of this invocation */
  1240. XGLOBAL int    min_idle, max_idle;    /* minimum & maximum idle cutouts */
  1241. XGLOBAL struct                /* print buffer for flon */
  1242. X    {
  1243. X    int    *cmds;            /*     command array */
  1244. X    char    *form;            /*     format/template array */
  1245. X    char    *buf;            /*     temp buffer */
  1246. X    } printdat;
  1247. X
  1248. XGLOBAL frend *    friends_list;        /* dynamic array of friends */
  1249. XGLOBAL int    friends_count;        /* size of friends_list */
  1250. X
  1251. XGLOBAL char *    utmp_file;        /* name of UTMP file to use */
  1252. XGLOBAL utmp_s *    utmp_list;        /* dynamic array of UTMP entries */
  1253. XGLOBAL int    utmp_count;        /* size of utmp_list */
  1254. X
  1255. XGLOBAL upwd *    pw_list;        /* dynamic array of upwd entries */
  1256. XGLOBAL int    pw_count;        /* size of pw_list */
  1257. X
  1258. X
  1259. X
  1260. X/*
  1261. X *    library & system call prototypes
  1262. X */
  1263. X
  1264. Xextern int    atoi        __PROT((const char *));
  1265. Xextern int    chmod        __PROT((const char *, mode_t));
  1266. Xextern int    close        __PROT((int));
  1267. Xextern char    *ctime        __PROT((const time_t *));
  1268. Xextern void    exit        __PROT((int));
  1269. Xextern int    fstat        __PROT((int, struct stat *));
  1270. Xextern char    *getenv        __PROT((const char *));
  1271. Xextern void    nqsort        __PROT((void *, size_t, size_t, int (*)()));
  1272. Xextern void    *nbsearch    __PROT((const void *, const void *,
  1273. X                    size_t, size_t, int (*)()));
  1274. X#if !OPEN_DECL
  1275. X    extern int    open        __PROT((const char *, int, ...));
  1276. X#endif /* !OPEN_DECL */
  1277. X#if !READ_DECL
  1278. X    extern int    read        __PROT((int, void *, unsigned));
  1279. X#endif /* !READ_DECL */
  1280. Xextern int    stat        __PROT((const char *, struct stat *));
  1281. Xextern char    *strcat        __PROT((char *, const char *));
  1282. Xextern int    strcmp        __PROT((const char *, const char *));
  1283. Xextern int    strncmp        __PROT((const char *, const char *, size_t));
  1284. Xextern size_t    strlen        __PROT((const char *));
  1285. Xextern time_t    time        __PROT((time_t *));
  1286. Xextern char    *getlogin    __PROT((void));
  1287. Xextern char    *strncpy    __PROT((char *, const char *, size_t));
  1288. Xextern char    *ttyname    __PROT((int));
  1289. Xextern uid_t    getuid        __PROT((void));
  1290. Xextern gid_t    getgid        __PROT((void));
  1291. Xextern int    setgid        __PROT((gid_t));
  1292. Xextern int    getopt        __PROT((int, char * const *, const char *));
  1293. Xextern utmp_s    *getutent    __PROT((void));
  1294. Xextern void    endutent    __PROT((void));
  1295. Xextern struct passwd  *getpwuid    __PROT((uid_t));
  1296. Xextern struct passwd  *getpwnam    __PROT((const char *));
  1297. X#ifndef toupper            /* damn #defines in non __STDC__ ... */
  1298. X    extern int    toupper        __PROT((int));
  1299. X    extern int    tolower        __PROT((int));
  1300. X#endif
  1301. X
  1302. X
  1303. X/*
  1304. X *    local prototypes
  1305. X */
  1306. X
  1307. X    /* main.c */
  1308. Xvoid    who_main        __PROT((int, char *[]));
  1309. X    /* init.c */
  1310. Xvoid    add_envopt        __PROT((int *, char **[], char *));
  1311. Xvoid    parse_options        __PROT((int, int, char *[], char **,
  1312. X                    char **, char **, char **));
  1313. Xvoid    parse_format        __PROT((char *));
  1314. X    /* getfile.c */
  1315. Xint    compare_utmp        __PROT((const void *, const void *));
  1316. Xint    compare_friends        __PROT((const void *, const void *));
  1317. Xint    compare_users        __PROT((const void *, const void *));
  1318. Xvoid    get_utmp        __PROT((int));
  1319. Xvoid    get_friends        __PROT((char *));
  1320. Xvoid    get_passwd        __PROT((char *));
  1321. X    /* print.c */
  1322. Xvoid    print_output        __PROT((char *, char *));
  1323. Xvoid    who_am_I        __PROT((void));
  1324. X    /* various.c */
  1325. Xvoid    errmesg            __PROT((char *, char *));
  1326. Xvoid    errexit            __PROT((char *, char *));
  1327. Xchar    *get_username        __PROT((void));
  1328. Xchar    *convert_realname    __PROT((char *, char *, int));
  1329. Xchar    *strnc0py        __PROT((char *, char *, size_t));
  1330. END_OF_FILE
  1331.   if test 11418 -ne `wc -c <'casu-3.3/casu.h'`; then
  1332.     echo shar: \"'casu-3.3/casu.h'\" unpacked with wrong size!
  1333.   fi
  1334.   # end of 'casu-3.3/casu.h'
  1335. fi
  1336. if test -f 'casu-3.3/fileio.c' -a "${1}" != "-c" ; then 
  1337.   echo shar: Will not clobber existing file \"'casu-3.3/fileio.c'\"
  1338. else
  1339.   echo shar: Extracting \"'casu-3.3/fileio.c'\" \(9762 characters\)
  1340.   sed "s/^X//" >'casu-3.3/fileio.c' <<'END_OF_FILE'
  1341. X/*
  1342. X *  CaSU - communications & status utilities.
  1343. X *  Copyright (C) 1992, 1993 Luke Mewburn <lm@rmit.edu.au>
  1344. X *    incorporating:
  1345. X *       flon - lists your friends who are logged on.
  1346. X *       to - send a short message to a friend
  1347. X *
  1348. X *  This program is free software; you can redistribute it and/or modify
  1349. X *  it under the terms of the GNU General Public License as published by
  1350. X *  the Free Software Foundation; either version 2 of the License, or
  1351. X *  (at your option) any later version.
  1352. X *  
  1353. X *  This program is distributed in the hope that it will be useful,
  1354. X *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  1355. X *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1356. X *  GNU General Public License for more details.
  1357. X *  
  1358. X *  You should have received a copy of the GNU General Public License
  1359. X *  along with this program; if not, write to the Free Software
  1360. X *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1361. X *
  1362. X */
  1363. X
  1364. X#include "casu.h"
  1365. X
  1366. X/*
  1367. X *    compare_utmp
  1368. X */
  1369. X
  1370. Xint
  1371. Xcompare_utmp(entry1, entry2)
  1372. X    const void *entry1, *entry2;
  1373. X{
  1374. X    /*
  1375. X     * first, weight the null umtp entries so that they get
  1376. X     * moved to the higher end of the list.
  1377. X     */
  1378. X
  1379. X    if (   NULL_UTMP_ENTRY((utmp_s *) entry1)
  1380. X    && NULL_UTMP_ENTRY((utmp_s *) entry2))
  1381. X        return 0;
  1382. X    if (NULL_UTMP_ENTRY((utmp_s *) entry1))
  1383. X        return 1;
  1384. X    if (NULL_UTMP_ENTRY((utmp_s *) entry2))
  1385. X        return -1;
  1386. X    /* otherwise, just return with normal comparison values. */
  1387. X    return(strncmp(( (utmp_s *) entry1)->ut_name,
  1388. X            ((utmp_s *) entry2)->ut_name, UT_NAMESIZE));
  1389. X} /* compare_utmp */
  1390. X
  1391. X
  1392. X/*
  1393. X *    compare_friends
  1394. X */
  1395. X
  1396. Xint
  1397. Xcompare_friends(entry1, entry2)
  1398. X    const void *entry1, *entry2;
  1399. X{
  1400. X    /* just compare the name fields of the friends entry. */
  1401. X    return (strcmp(((frend *) entry1)->name, ((frend *) entry2)->name));
  1402. X} /* compare_friends */
  1403. X
  1404. X
  1405. X/*
  1406. X *    compare_users
  1407. X */
  1408. X
  1409. Xint
  1410. Xcompare_users(entry1, entry2)
  1411. X    const void *entry1, *entry2;
  1412. X{
  1413. X    /* just compare the username fields */
  1414. X    return (strcmp(((upwd *) entry1)->username, ((upwd *) entry2)->username));
  1415. X} /* compare_users */
  1416. X
  1417. X
  1418. X/*
  1419. X *    get_utmp
  1420. X */
  1421. X
  1422. Xvoid
  1423. Xget_utmp(sort_required)
  1424. X    int sort_required;
  1425. X{
  1426. X    struct stat    statbuf;
  1427. X    int        utmp_fd;
  1428. X    long    filesiz;
  1429. X
  1430. X    /* prepare to read file into large chunk of memory */
  1431. X    if ((utmp_fd = open(utmp_file, O_RDONLY, 0)) == -1)
  1432. X    errexit(strerror(errno), utmp_file);
  1433. X    if (fstat(utmp_fd, &statbuf)== -1)
  1434. X    errexit(strerror(errno), utmp_file);
  1435. X    filesiz=(long) statbuf.st_size;
  1436. X    if ((utmp_list = (utmp_s *) malloc(filesiz+1)) == NULL)
  1437. X    errexit(strerror(errno), NULL);
  1438. X
  1439. X    /* read in the utmp file in one chunk */
  1440. X    if ((filesiz=read(utmp_fd, (char *) utmp_list, statbuf.st_size))==-1)
  1441. X    errexit(strerror(errno), utmp_file);
  1442. X
  1443. X    /* terminate the list, and close the file. */
  1444. X    ((char *) utmp_list)[filesiz]='\0';
  1445. X    if (close(utmp_fd) == -1)
  1446. X    errexit(strerror(errno), utmp_file);
  1447. X
  1448. X    /* sort the file, and set utmp_count to the # of valid entries */
  1449. X    filesiz /= sizeof(utmp_s);     /* num entries in list */
  1450. X    if (sort_required)
  1451. X    {
  1452. X    nqsort(utmp_list, filesiz, sizeof(utmp_s), compare_utmp);
  1453. X    for (utmp_count=0;
  1454. X         !(NULL_UTMP_ENTRY(&utmp_list[utmp_count]));
  1455. X         utmp_count++)
  1456. X        if (utmp_count >= filesiz)
  1457. X            break;
  1458. X    }
  1459. X    else
  1460. X    utmp_count = filesiz;
  1461. X} /* get_utmp */
  1462. X
  1463. X
  1464. X
  1465. X/*
  1466. X *    get_friends
  1467. X */
  1468. X
  1469. Xvoid
  1470. Xget_friends(frfile)
  1471. X    char *frfile;
  1472. X{
  1473. X    char    *tfb, *ffbufr, f_path[MAXPATHLEN], *envhome;
  1474. X    struct stat    stbufr;
  1475. X    int        loop, ffd;
  1476. X    long    filesiz;
  1477. X
  1478. X    f_path[0]='\0';
  1479. X    /*
  1480. X     * If frfile is not null, assume this is a user specified
  1481. X     * friends file, otherwise, get $HOME/.friends
  1482. X     */
  1483. X    if (frfile == NULL)
  1484. X    {
  1485. X        /* XXX: maybe this could use pwent->pw_dir, not $HOME */
  1486. X    if ((envhome=getenv(STRhome)) == NULL)
  1487. X        errexit("Undefined variable", "HOME");
  1488. X    strcat(f_path, envhome);
  1489. X    strcat(f_path, "/");
  1490. X    frfile = STRdotfriends;
  1491. X    }
  1492. X
  1493. X    /* dump out if the resultant path will be too long. */
  1494. X    if ((int)strlen(f_path) + (int)strlen(frfile) >= MAXPATHLEN)
  1495. X        errexit("Path too long", frfile);
  1496. X    strcat(f_path, frfile);
  1497. X
  1498. X    /*
  1499. X     * open and fstat the file, and malloc ram for the entire
  1500. X     * thing. Note, I use the open()/fstat() combination instead of
  1501. X     * the stat()/open() one, because once I have a file descriptor
  1502. X     * to the file, it can't be unlinked on me
  1503. X     */
  1504. X    if ((ffd = open(f_path, O_RDONLY, 0)) == -1)
  1505. X        if (errno == ENOENT)
  1506. X    {
  1507. X            friends_list=NULL;
  1508. X        flags |= ALL_ON;
  1509. X            return;
  1510. X        }
  1511. X    else
  1512. X        errexit(strerror(errno), f_path);
  1513. X    if (fstat(ffd, &stbufr)== -1)
  1514. X    errexit(strerror(errno), f_path);
  1515. X    filesiz=(long) stbufr.st_size;
  1516. X    ffbufr = (char *) malloc(sizeof(char) * (filesiz+1));
  1517. X    if (ffbufr == NULL)
  1518. X    errexit(strerror(errno), NULL);
  1519. X    if ((filesiz=read(ffd, ffbufr, stbufr.st_size))==-1)
  1520. X    errexit(strerror(errno), f_path);
  1521. X
  1522. X    /* nul terminate and close the file. */
  1523. X    (ffbufr)[filesiz]='\0';
  1524. X    if (close(ffd) == -1)
  1525. X    errexit(strerror(errno), f_path);
  1526. X
  1527. X    friends_count = 0;
  1528. X    tfb=ffbufr;
  1529. X
  1530. X    /*
  1531. X     * break up the friends file into alternating
  1532. X     * nul terminated names and pseudonyms.
  1533. X     */
  1534. X    while (1)
  1535. X    {
  1536. X        /* find the start of the name (skipping CR and spaces) */
  1537. X        tfb += strspn(tfb, STRsep);
  1538. X    if ( tfb >= &ffbufr[filesiz] )
  1539. X        break;        /* exit if off end of buffer */
  1540. X    /*  for now, ignore NULs in friends file
  1541. X        if (!(*tfb))
  1542. X            break;
  1543. X    */
  1544. X        tfb += strcspn(tfb, STRsep);
  1545. X        /* got end of name. If no trailing pseudo, error occurs */
  1546. X        if ( !( *tfb ) || ( tfb >= &ffbufr[filesiz] ) )
  1547. X            errexit("Invalid format of friends file", NULL);
  1548. X        *tfb++ = '\0';        /* ok, got name.... */
  1549. X
  1550. X        /* find start of pseudonym, skipping all white space */
  1551. X        tfb += strspn(tfb, STRsep);
  1552. X        if ( !( *tfb ) || ( tfb > &ffbufr[filesiz] ) )
  1553. X            errexit("Invalid format of friends file", NULL);
  1554. X        /*
  1555. X         * get \n terminated pseudonym (spaces are allowed in
  1556. X         * pseudonyms...), and nul terminate it. increment
  1557. X         * friends counter.
  1558. X         */
  1559. X        tfb += strcspn(tfb, STReoln);
  1560. X        if (!(*tfb))
  1561. X        break;
  1562. X        *tfb++ = '\0';            /* got pseudo */
  1563. X        friends_count++;
  1564. X    }
  1565. X
  1566. X    /*
  1567. X     * return memory if the friends file has no friends in it.
  1568. X     * (they could have a 5K file of whitespaces ... :-)
  1569. X     */
  1570. X    if (!friends_count)
  1571. X    {
  1572. X        free(ffbufr);
  1573. X        return;
  1574. X    }
  1575. X
  1576. X    /* create the list of frend entries, and assign all the pointers */
  1577. X    friends_list = (frend *) malloc (friends_count * sizeof(frend));
  1578. X    if (friends_list == NULL)
  1579. X    errexit(strerror(errno), NULL);
  1580. X
  1581. X    tfb=ffbufr;
  1582. X    for (loop=0; loop <friends_count; loop++)
  1583. X    {
  1584. X        tfb += strspn(tfb, STRsep);
  1585. X        if (!(*tfb))
  1586. X            break;
  1587. X        strnc0py(friends_list[loop].name, tfb, UT_NAMESIZE);
  1588. X    while ( *tfb )
  1589. X        tfb++;
  1590. X        tfb++;
  1591. X
  1592. X        tfb += strspn(tfb, STRsep);
  1593. X        friends_list[loop].pseudo = tfb;
  1594. X    while ( *tfb )
  1595. X        tfb++;
  1596. X        tfb++;
  1597. X    }
  1598. X    /* sort the friends list, and return. */
  1599. X    nqsort(friends_list, friends_count, sizeof(frend), compare_friends);
  1600. X} /* get_friends() */
  1601. X
  1602. X
  1603. X#if !USE_GETPWENT
  1604. X/*
  1605. X *    get_passwd
  1606. X */
  1607. X
  1608. Xvoid
  1609. Xget_passwd(pwfile)
  1610. X    char *pwfile;
  1611. X{
  1612. X    char    *pwbufr, *tfb;
  1613. X    int        pwfd, loop;
  1614. X    long    filesiz;
  1615. X    struct stat stbufr;
  1616. X
  1617. X    /*
  1618. X     * open and fstat the file, and malloc ram for the entire
  1619. X     * thing. Note, I use the open()/fstat() combination instead of
  1620. X     * the stat()/open() one, because once I have a file descriptor
  1621. X     * to the file, it can't be unlinked on me
  1622. X     */
  1623. X    if ((pwfd = open(pwfile, O_RDONLY, 0)) == -1)
  1624. X    errexit(strerror(errno), pwfile);
  1625. X    if (fstat(pwfd, &stbufr)== -1)
  1626. X    errexit(strerror(errno), pwfile);
  1627. X    filesiz=(long) stbufr.st_size;
  1628. X    if ((pwbufr = (char *) malloc(filesiz+1)) == NULL)
  1629. X    errexit(strerror(errno), pwfile);
  1630. X    if ((filesiz=read(pwfd, pwbufr, stbufr.st_size))==-1)
  1631. X    errexit(strerror(errno), pwfile);
  1632. X
  1633. X    (pwbufr)[filesiz]='\0';
  1634. X    if (close(pwfd) == -1)
  1635. X    errexit(strerror(errno), pwfile);
  1636. X
  1637. X    tfb=pwbufr;
  1638. X    pw_count = 0;
  1639. X
  1640. X    /*
  1641. X     * break up the passwd file into alternating
  1642. X     * nul terminated usernames, uid's, and realnames
  1643. X     */
  1644. X
  1645. X    while (1)
  1646. X    {
  1647. X        /* find end of username */
  1648. X    tfb += strcspn(tfb, PWsep);
  1649. X        *tfb = '\0';    /* ok, got name.... */
  1650. X    if ( ++tfb > &pwbufr[filesiz])
  1651. X        break;
  1652. X
  1653. X        /* skip password */
  1654. X    tfb += strcspn(tfb, PWsep) + 1;
  1655. X
  1656. X        /* find end of uid */
  1657. X    tfb += strcspn(tfb, PWsep);
  1658. X        *tfb = '\0';    /* ok, got uid.... */
  1659. X    if ( ++tfb > &pwbufr[filesiz])
  1660. X        break;
  1661. X
  1662. X        /* skip gid */
  1663. X    tfb += strcspn(tfb, PWsep) + 1;
  1664. X
  1665. X        /* find end of 1st part of GCOS (i.e, real name) */
  1666. X    tfb += strcspn(tfb, PWGCOSsep);
  1667. X        *tfb = '\0';    /* ok, got name.... */
  1668. X    if ( ++tfb > &pwbufr[filesiz])
  1669. X        break;
  1670. X
  1671. X        tfb += strcspn(tfb, PWeoln);
  1672. X        *tfb = '\0';    /* ok, got end of line */
  1673. X    if ( ++tfb > &pwbufr[filesiz] )
  1674. X        break;
  1675. X        pw_count++;
  1676. X    }
  1677. X
  1678. X    /* create the list of upwd entries, and assign all the pointers */
  1679. X    pw_list = (upwd *) malloc (pw_count * sizeof(upwd));
  1680. X    if (pw_list == NULL)
  1681. X    errexit(strerror(errno), NULL);
  1682. X
  1683. X    tfb=pwbufr;
  1684. X    for (loop=0; loop <pw_count; loop++)
  1685. X    {
  1686. X    pw_list[loop].username=tfb;    /* get start of username */
  1687. X        while ( *tfb )
  1688. X            tfb++;
  1689. X        tfb++;                /* at password */
  1690. X
  1691. X        tfb += strcspn(tfb, PWsep) + 1;    /* at uid */
  1692. X
  1693. X        pw_list[loop].uid = (uid_t) atoi(tfb);    /* get uid */
  1694. X        while ( *tfb )
  1695. X            tfb++;
  1696. X        tfb++;                /* at gid */
  1697. X
  1698. X    tfb += strcspn(tfb, PWsep) + 1;    /* at gcos */
  1699. X
  1700. X                    /* get real name */
  1701. X    pw_list[loop].gcos = tfb;
  1702. X        while ( *tfb )
  1703. X            tfb++;
  1704. X        tfb++;                /* at end of realname */
  1705. X
  1706. X        while ( *tfb )
  1707. X            tfb++;
  1708. X        tfb++;                /* at end of line */
  1709. X    }
  1710. X
  1711. X    /* sort the password file on username */
  1712. X    nqsort(pw_list, pw_count, sizeof(upwd), compare_users);
  1713. X} /* get_passwd() */
  1714. X
  1715. X#endif /* USE_GETPWENT */
  1716. END_OF_FILE
  1717.   if test 9762 -ne `wc -c <'casu-3.3/fileio.c'`; then
  1718.     echo shar: \"'casu-3.3/fileio.c'\" unpacked with wrong size!
  1719.   fi
  1720.   # end of 'casu-3.3/fileio.c'
  1721. fi
  1722. if test -f 'casu-3.3/print.c' -a "${1}" != "-c" ; then 
  1723.   echo shar: Will not clobber existing file \"'casu-3.3/print.c'\"
  1724. else
  1725.   echo shar: Extracting \"'casu-3.3/print.c'\" \(10086 characters\)
  1726.   sed "s/^X//" >'casu-3.3/print.c' <<'END_OF_FILE'
  1727. X/*
  1728. X *  CaSU - communications & status utilities.
  1729. X *  Copyright (C) 1992, 1993 Luke Mewburn <lm@rmit.edu.au>
  1730. X *    incorporating:
  1731. X *       flon - lists your friends who are logged on.
  1732. X *       to - send a short message to a friend
  1733. X *
  1734. X *  This program is free software; you can redistribute it and/or modify
  1735. X *  it under the terms of the GNU General Public License as published by
  1736. X *  the Free Software Foundation; either version 2 of the License, or
  1737. X *  (at your option) any later version.
  1738. X *  
  1739. X *  This program is distributed in the hope that it will be useful,
  1740. X *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  1741. X *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1742. X *  GNU General Public License for more details.
  1743. X *  
  1744. X *  You should have received a copy of the GNU General Public License
  1745. X *  along with this program; if not, write to the Free Software
  1746. X *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1747. X *
  1748. X */
  1749. X
  1750. X#include "casu.h"
  1751. X
  1752. X/*
  1753. X *    print_output
  1754. X *
  1755. X * print the output according to the command and template buffer.
  1756. X */
  1757. X
  1758. Xvoid
  1759. Xprint_output(yes_str, no_str)
  1760. X    char *yes_str, *no_str;
  1761. X{
  1762. X    static char    term[sizeof(_PATH_DEV) + UT_LINESIZE] = _PATH_DEV;
  1763. X    char    *myname;
  1764. X    time_t    today;
  1765. X    int        entlp;
  1766. X    int        me_on;
  1767. X    int        offset, width;
  1768. X
  1769. X    static struct one_ent
  1770. X    {
  1771. X    int    on;        /* times this person on */
  1772. X    int    avail;        /* if any term has mesg y */
  1773. X    int    stres;        /* result of stat for this tty */
  1774. X    int    mesg;        /* mesg of cur ent */
  1775. X    time_t    idle, login;     /* idle & login of cur ent */
  1776. X    char    *tty;        /* tty of cur ent */
  1777. X    char    *host;        /* remote host */
  1778. X    char    *name;        /* name of user */
  1779. X    int    valid;        /* is this entry valid */
  1780. X    } cur_ent, null_ent;
  1781. X
  1782. X
  1783. X    me_on = 0;
  1784. X    today=time(NULL);
  1785. X    if (!(flags & NO_HEADER))
  1786. X    {
  1787. X        printf("\
  1788. X                Fast Lon v%-5.5s  %s\
  1789. X             -----------------------------------------------\n\
  1790. X", VERSION, ctime(&today) );
  1791. X    }
  1792. X    myname = NULL;
  1793. X    if (!(flags & NO_TAILER))
  1794. X    myname=get_username();
  1795. X
  1796. X    for (entlp=0; entlp <utmp_count; entlp++)
  1797. X    {
  1798. X    int        comlp, fpos;
  1799. X    frend        *curfrend, tmpfrend;
  1800. X    struct stat    stbufr;
  1801. X
  1802. X    if (NULL_UTMP_ENTRY(&utmp_list[entlp]))
  1803. X        continue;        /* for who emulation - skip null entries */
  1804. X
  1805. X        if (!(flags & NO_TAILER) && (myname != NULL))
  1806. X    {
  1807. X        if (strncmp(utmp_list[entlp].ut_name, myname, UT_NAMESIZE) == 0)
  1808. X        me_on++;
  1809. X    }
  1810. X
  1811. X        if (friends_list != NULL)
  1812. X        {
  1813. X        strnc0py(tmpfrend.name, utmp_list[entlp].ut_name, UT_NAMESIZE);
  1814. X        curfrend = nbsearch(&tmpfrend, friends_list, friends_count,
  1815. X                sizeof(frend), compare_friends);
  1816. X        if (   ((!(flags & ALL_ON)) && (curfrend == NULL))
  1817. X        || (curfrend && (flags & NO_MATES)))
  1818. X        {
  1819. X        cur_ent = null_ent;    /* previous info isn't valid anymore */
  1820. X        continue;
  1821. X        }
  1822. X        }
  1823. X        else
  1824. X        curfrend = NULL;
  1825. X
  1826. X        if (flags & NEED_STAT)
  1827. X        {
  1828. X        strcpy(term + sizeof(_PATH_DEV) - 1, utmp_list[entlp].ut_line);
  1829. X        cur_ent.stres=stat(term, &stbufr);
  1830. X        }
  1831. X    else
  1832. X        cur_ent.stres= -1;    /* fool the code to skip the stat stuff */
  1833. X
  1834. X        if (entlp < utmp_count-1)        /* at least 1 to go */
  1835. X    {
  1836. X        if (strncmp(utmp_list[entlp].ut_name,
  1837. X            utmp_list[entlp+1].ut_name, UT_NAMESIZE) == 0)
  1838. X        {
  1839. X        if (cur_ent.stres != -1)
  1840. X        {
  1841. X            time_t idle = today - stbufr.st_atime;
  1842. X            /* if not valid, or idle < least_idle */
  1843. X            if ((! cur_ent.valid) || (idle < cur_ent.idle))
  1844. X            {
  1845. X            cur_ent.idle=    idle;
  1846. X            cur_ent.tty=    utmp_list[entlp].ut_line;
  1847. X            cur_ent.login=    utmp_list[entlp].UT_TIME;
  1848. X            cur_ent.name=    utmp_list[entlp].ut_name;
  1849. X#ifdef HAVE_UT_HOST
  1850. X            cur_ent.host=    utmp_list[entlp].ut_host;
  1851. X#endif
  1852. X            cur_ent.mesg=    (stbufr.st_mode & MESGS_ON);
  1853. X            cur_ent.valid++;
  1854. X            }
  1855. X        }
  1856. X        cur_ent.on++;
  1857. X        if (stbufr.st_mode & MESGS_ON)
  1858. X            cur_ent.avail++;
  1859. X        if (flags & ONE_ONLY)        /* skip multiple entries */
  1860. X            continue;
  1861. X        }
  1862. X    }
  1863. X    if (cur_ent.stres != -1)
  1864. X    {
  1865. X        /* get valid info for last entry of a user */
  1866. X        time_t idle = today - stbufr.st_atime;
  1867. X
  1868. X        if ((! cur_ent.valid) || (idle < cur_ent.idle))
  1869. X        {
  1870. X        cur_ent.idle= idle;
  1871. X        cur_ent.tty=  utmp_list[entlp].ut_line;
  1872. X        cur_ent.login=utmp_list[entlp].UT_TIME;
  1873. X        cur_ent.name= utmp_list[entlp].ut_name;
  1874. X#ifdef HAVE_UT_HOST
  1875. X        cur_ent.host= utmp_list[entlp].ut_host;
  1876. X#endif
  1877. X        cur_ent.mesg= (stbufr.st_mode & MESGS_ON);
  1878. X        cur_ent.valid++;
  1879. X        }
  1880. X        if (stbufr.st_mode & MESGS_ON)
  1881. X        cur_ent.avail++;
  1882. X        if (flags & NO_IDLE)
  1883. X        if (cur_ent.idle >= max_idle)
  1884. X        {
  1885. X            cur_ent = null_ent;
  1886. X            continue;    /* don't print entry if idle limit exceeded */
  1887. X        }
  1888. X    }
  1889. X    else
  1890. X    {
  1891. X        cur_ent.tty=  utmp_list[entlp].ut_line;
  1892. X        cur_ent.login=utmp_list[entlp].UT_TIME;
  1893. X        cur_ent.name= utmp_list[entlp].ut_name;
  1894. X#ifdef HAVE_UT_HOST
  1895. X        cur_ent.host= utmp_list[entlp].ut_host;
  1896. X#endif
  1897. X    }
  1898. X
  1899. X        offset=fpos=0;
  1900. X        for (comlp=0; printdat.cmds[comlp]; comlp++)
  1901. X        {
  1902. X        char tmpbuf[UT_HOSTSIZE + 2 + 1], *outs;
  1903. X        int    len, tmpwid;
  1904. X
  1905. X
  1906. X        outs = NULL;
  1907. X        width=printdat.cmds[comlp];
  1908. X        tmpwid=width & C_WIDMASK;
  1909. X        switch (printdat.cmds[comlp] & C_CMDMASK)
  1910. X        {
  1911. X        case C_NULL:
  1912. X            outs = &printdat.form[fpos];
  1913. X            break;
  1914. X        case C_USER:
  1915. X            strnc0py(tmpbuf, cur_ent.name, UT_NAMESIZE);
  1916. X            outs = tmpbuf;
  1917. X            break;
  1918. X        case C_PSEUDO:
  1919. X            if (curfrend != NULL)
  1920. X            {
  1921. X            outs = curfrend->pseudo;
  1922. X            break;
  1923. X            }
  1924. X            if ((flags & BEST_NAME) == 0)
  1925. X            break;    /* don't fall thru if 'best' mode off */
  1926. X        case C_REAL:
  1927. X            { 
  1928. X#if USE_GETPWENT
  1929. X            struct passwd *curupwd;
  1930. X            strnc0py(tmpfrend.name, cur_ent.name, UT_NAMESIZE);
  1931. X            curupwd = getpwnam(tmpfrend.name);
  1932. X            if (curupwd != NULL)
  1933. X                outs = convert_realname(curupwd->pw_gecos,
  1934. X                            curupwd->pw_name,
  1935. X                            curupwd->pw_uid);
  1936. X#else /* !USE_GETPWENT */
  1937. X#   if 0    /* lsearch */
  1938. X            int  i;
  1939. X            for (i=0; i<pw_count; i++)
  1940. X                if (strncmp(pw_list[i].username, cur_ent.name,
  1941. X                    UT_NAMESIZE) ==0)
  1942. X                break;
  1943. X            if (i != pw_count)
  1944. X                outs = convert_realname(pw_list[i].gcos,
  1945. X                            pw_list[i].username,
  1946. X                            pw_list[i].uid);
  1947. X#   else    /* nbsearch */
  1948. X            upwd *curp, tmpp;
  1949. X            strnc0py(tmpfrend.name, cur_ent.name, UT_NAMESIZE);
  1950. X            tmpp.username = tmpfrend.name;
  1951. X            curp = nbsearch(&tmpp, pw_list, pw_count, sizeof(upwd),
  1952. X                    compare_users);
  1953. X            if (curp)
  1954. X                outs = convert_realname(curp->gcos,
  1955. X                            curp->username,
  1956. X                            curp->uid);
  1957. X#   endif
  1958. X#endif /* !USE_GETPWENT */
  1959. X            }
  1960. X            break;
  1961. X        case C_COUNT:
  1962. X            if (!cur_ent.on)
  1963. X            break;
  1964. X            sprintf(tmpbuf, "%-d", ++cur_ent.on);
  1965. X            outs = tmpbuf;
  1966. X            break;
  1967. X        case C_X:
  1968. X            tmpbuf[0] = cur_ent.on ? 'x' : ' ';
  1969. X            tmpbuf[1] = '\0';
  1970. X            outs = tmpbuf;
  1971. X            break;
  1972. X        case C_LOGIN:
  1973. X            outs = 4 + ctime(&cur_ent.login);
  1974. X            break;
  1975. X        case C_IDLE:
  1976. X            if (cur_ent.stres == -1)    /* print nothing if stat died */
  1977. X            break;
  1978. X            if (cur_ent.idle >= MAXIDLE)
  1979. X            outs = " >>> ";
  1980. X            else
  1981. X            if (cur_ent.idle < min_idle)
  1982. X                outs = " ... ";
  1983. X            else
  1984. X            {
  1985. X                sprintf(tmpbuf, "%02d:%02d",
  1986. X                    (int) (cur_ent.idle / 60),
  1987. X                    (int) (cur_ent.idle % 60));
  1988. X                outs = tmpbuf;
  1989. X            }
  1990. X            break;
  1991. X        case C_TTY:
  1992. X            outs = cur_ent.tty;
  1993. X            break;
  1994. X        case C_MESG:
  1995. X            if (cur_ent.stres == -1)     /* print nothing if stat died */
  1996. X            break;
  1997. X            outs = cur_ent.mesg ? yes_str : no_str;
  1998. X            break;
  1999. X        case C_AVAIL:
  2000. X            if (cur_ent.stres == -1)     /* print nothing if stat died */
  2001. X            break;
  2002. X            outs = cur_ent.avail ? yes_str : no_str;
  2003. X            break;
  2004. X#ifdef HAVE_UT_HOST
  2005. X        case C_HOST:
  2006. X            strnc0py(tmpbuf, cur_ent.host, UT_HOSTSIZE);
  2007. X            outs = tmpbuf;
  2008. X            break;
  2009. X        case C_HOSTBRK:
  2010. X            if (cur_ent.host[0] == '\0')
  2011. X            break;
  2012. X            tmpbuf[0] = '(';
  2013. X            strnc0py(tmpbuf + 1, cur_ent.host, UT_HOSTSIZE);
  2014. X            if (strlen(tmpbuf) >= tmpwid)
  2015. X            tmpbuf[tmpwid - 1] = '\0';
  2016. X            strcat(tmpbuf, ")");
  2017. X            outs=tmpbuf;
  2018. X            break;
  2019. X#endif /* HAVE_UT_HOST */
  2020. X        default:
  2021. X            break;
  2022. X        } /* switch */
  2023. X        if (outs == NULL)
  2024. X        len = 0;
  2025. X        else
  2026. X        {
  2027. X        len=strlen(outs);
  2028. X        if (len>=tmpwid)            /* need to truncate */
  2029. X        {
  2030. X            strncpy(&printdat.buf[offset], outs, tmpwid);
  2031. X            len = tmpwid;
  2032. X        }
  2033. X        else if (width & C_RIGHT)        /* right align */
  2034. X        {
  2035. X            tmpwid-= len;
  2036. X            strncpy(&printdat.buf[offset+tmpwid], outs, len);
  2037. X            len = 0;
  2038. X        }
  2039. X        else                    /* left align */
  2040. X            strncpy(&printdat.buf[offset], outs, len);
  2041. X        }
  2042. X        if (width & C_VARIENT)            /* varient width */
  2043. X        {
  2044. X        width &= ~C_WIDMASK;
  2045. X        width += len & C_WIDMASK;
  2046. X        }
  2047. X        else
  2048. X        {
  2049. X        int lp;
  2050. X        for (lp = len; lp < tmpwid; lp++)    /* clear unused areas */
  2051. X            printdat.buf[offset+lp] = ' ';
  2052. X        }
  2053. X        offset += width & C_WIDMASK;
  2054. X        fpos += printdat.cmds[comlp] & C_WIDMASK;
  2055. X        }
  2056. X    printdat.buf[offset] = '\0';
  2057. X        puts(printdat.buf);
  2058. X    cur_ent = null_ent;    /* previous info isn't valid anymore */
  2059. X    }
  2060. X    if (!(flags & NO_TAILER))
  2061. X    {
  2062. X        switch (me_on)
  2063. X        {
  2064. X        case 0:
  2065. X#if 0
  2066. X            puts("\nYou technically aren't logged on.");
  2067. X#else
  2068. X        puts("\nYou're not logged on.");
  2069. X#endif
  2070. X            break;
  2071. X        case 1:
  2072. X            puts("\nYou are logged on once.");
  2073. X            break;
  2074. X        case 2:
  2075. X            puts("\nYou are logged on twice.");
  2076. X            break;
  2077. X        default:
  2078. X            printf("\nYou are logged on %d times.\n", me_on);
  2079. X            break;
  2080. X        }
  2081. X        if (utmp_count == 1)
  2082. X        puts("You are the only person logged on.");
  2083. X        else
  2084. X        printf("There are %d users logged on.\n", utmp_count);
  2085. X    }
  2086. X} /* print_output */
  2087. X
  2088. X
  2089. X/*
  2090. X *    who_am_I
  2091. X *
  2092. X * Emulates 'who am I'.
  2093. X */
  2094. X
  2095. Xvoid
  2096. Xwho_am_I()
  2097. X{
  2098. X    char    *tty, *tmptty;
  2099. X    int        slp;
  2100. X    time_t  ttytime;
  2101. X
  2102. X    if ((tty = ttyname(0)) == NULL)    /* who am I < somefile */
  2103. X    {
  2104. X    ttytime=time(NULL);
  2105. X    tty=WHO_NULLTTY;
  2106. X    }
  2107. X    else                /* just who am I */
  2108. X    {
  2109. X    tmptty=strrchr(tty, '/');
  2110. X    if (tmptty != NULL)
  2111. X        tty = tmptty + 1;
  2112. X    
  2113. X        /* search for user on tty */
  2114. X    for (slp=0; slp <utmp_count; slp++)
  2115. X    {
  2116. X        if (NULL_UTMP_ENTRY(&utmp_list[slp]))
  2117. X        continue;
  2118. X        if (strncmp(utmp_list[slp].ut_line, tty, UT_LINESIZE) == 0)
  2119. X        break;
  2120. X    }
  2121. X
  2122. X    if (slp == utmp_count)
  2123. X        errexit("not found in utmp file", tty);
  2124. X    ttytime=utmp_list[slp].UT_TIME;
  2125. X    }
  2126. X    
  2127. X    printf(WHO_AM_I_FMT, (int) UT_NAMESIZE, get_username(),
  2128. X        tty, 4 + ctime(&ttytime));
  2129. X} /* who_am_I */
  2130. END_OF_FILE
  2131.   if test 10086 -ne `wc -c <'casu-3.3/print.c'`; then
  2132.     echo shar: \"'casu-3.3/print.c'\" unpacked with wrong size!
  2133.   fi
  2134.   # end of 'casu-3.3/print.c'
  2135. fi
  2136. echo shar: End of archive 3 \(of 4\).
  2137. cp /dev/null ark3isdone
  2138. MISSING=""
  2139. for I in 1 2 3 4 ; do
  2140.     if test ! -f ark${I}isdone ; then
  2141.     MISSING="${MISSING} ${I}"
  2142.     fi
  2143. done
  2144. if test "${MISSING}" = "" ; then
  2145.     echo You have unpacked all 4 archives.
  2146.     rm -f ark[1-9]isdone
  2147. else
  2148.     echo You still must unpack the following archives:
  2149.     echo "        " ${MISSING}
  2150. fi
  2151. exit 0
  2152. exit 0 # Just in case...
  2153.