Newsgroups: comp.sources.unix From: perseant@u.washington.edu (Konrad Schroder) Subject: v28i120: hand-1.70 - a bunch of fingers working together, Part01/03 Message-id: <1.777869799.9794@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: perseant@u.washington.edu (Konrad Schroder) Posting-Number: Volume 28, Issue 120 Archive-Name: hand-1.70/part01 Here is hand, a bunch of fingers working together (but a bit more than finger @foo &; finger @bar &; ...). Both a README and manual page are included. Konrad Schroder perseant@u.washington.edu #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'ChangeLog' <<'END_OF_FILE' XWed Jul 27 15:25:00 1994 Konrad Schroder (perseant@mead1) X X 1.70 X Added --port option to deal with ill-administered machines. Fixed X a couple of header-related bugs Adrian pointed out to me, and #ifdeffed X the getdtablesize() in main.c; it compiles how under Solaris 2.3. X XTue Jun 14 16:13:33 1994 Konrad Schroder (perseant@saul1) X X Added --login-command and --logout-command to emulate the behaviour of X ncemrsoft's ison(1). Fixed a bug in the the parsing routine that X caused it not to be able to correctly locate the user's tty unless X they had messages turned off. Attempted to fix the "too many open X descriptors" bug by closing all descriptors numbered higher than 2 X each time h_main is run (a big kluge). Made {add,del}-{user,host} X interactive if no host/user is specified. Added individual host flags X to the .hand file (the environment is interpreted first, then the .hand X file, then the command-line args). TODO: Release to X comp.sources.unix (again). Look into revamping the entire thing to X use select(2) instead of fork(2), as suggested by wiml. X XFri May 27 17:09:49 1994 Konrad Schroder (perseant@stein3.u.washington.edu) X X 1.61 X Fixed the startup portion of hand (in handarg.c) to check for EOF. X Twiddled glovei.c to direct the installer to the Makefile instead of X site.h (which no longer exists) for where to put COPYING and HELP. X XMon Jan 31 22:32:48 1994 Konrad Schr{\o}der (perseant@stein) X X 1.60 X Added time zone corrections (-T option) and host-correction (-O X option); revamped the hostname() function from handtcp.c so that it X *always* gives you an IP number; modified the host fields of the data X file (now called .hand) to be colon-separated, for ease of adding later X fields. Made the query_create "do you wish to have a .hand file" X business only happen if the user is on a tty. Added glove to the X distribution, as a beta. X X 1.50 X Wrote wrist, and modified hand --watch to work with it. It's a quick X hack, but sort of neat, if you're into that sort of thing. X X 1.47 X Posted to comp.sources.unix; fixed some problems with --add-h. X X 1.46 X Added a warning when invoking "hand --add-host" on a host with more than X one IP number. Thinking about posting the source to comp.sources.unix; X Once I do that, these minor changes will have to be in patch form. X X 1.45 X Noticed a potential bug in the argument handling routine, removed it. X X 1.44 X Fixed a bug in the --watch option, so stupid it shames me to even mention X it (so I won't). X X 1.43 X Added --watch option. Fixed bugs in --add-* introduced in 1.42. Hand X now modifies its argument string when fingering, to display "finger X @host", as a debugging aid. X X 1.42 X Switched to using GNU getopt_long for option parsing. This allows long X options to be abbreviated, but does not allow options to have more X than one argument. X X 1.41 X Fixed a bug that would cause hand to core dump when it was passed a file X which did not exist and whose name was not ~/.addresses.dat. X X 1.40 X Added interactive mode. Curses is a real pain in the neck, especially X since it doesn't seem to work properly. X X 1.38 X Modified hand to accept multiple users with the same username; X for example, if johnd@u.washington.edu and johnd@cco.caltech.edu X are different friends, X X johnd@*.caltech.edu John Doe X johnd@*.washington.edu John Drew X X will find John Doe at Caltech and John Drew at the UW, instead of X simply ignoring the second entry after sorting the address file. X X 1.37 X Added the ! qualifier to the host qualifier; now "user@!host" X is an acceptible username, so you don't have to do X X user@host1,host2,host3,host4,host5,host6,host7 X X when what you really want is X X user@!host8 X X 1.36 X Added --add and --del options. It is now possible to use X hand and not have to know any editor. X X 1.35 X Fixed a bug in the data reading routine within finger() that would X cause hand to hang indefinitely for a machine that connected but would X not answer the finger request. Actually this is a re-fix--I had X thought that this problem was fixed before 1.20. X X 1.35 X Fixed a bug in the data reading routine within finger() that would X cause hand to hang indefinitely for a machine that connected but would X not answer the finger request. Actually this is a re-fix--I had X thought that this problem was fixed before 1.20. X X 1.34 X Fixed a bug in separate that would cause the message "No one logged in" X not to be printed if someone were logged in, but too idle to show up. X The default idle setting is now +no-idle, at the suggestion of X hackerb9@u.washington.edu (Ben Wong). X X 1.32 X Fixed a bug in parse that would cause the parser to sort more X lines than there were, if the finger daemon sent imbedded blank X lines. Now any lines following imbedded blank lines will X be ignored. X X 1.31 X Fixed the "not enough files" problem with the no-fork option. X Removed one data-to-file-to-data pass, and replaced it with a X pointer pass. X X 1.3b X First revision data. Added better file deletion capabilities. X Using pipes now to save the redirected I/O problem (which somehow X worked in v. < 1.2.4 anyway!). Removed CPU limiting option. Re- X wrote separation routine so as to be more workable and efficient. X Added option negation for all options. Added -o (once-only?) option. X Added usage list for incorrect options. Re-wrote parse() so as to X recognize more forms of finger output (notably GNU finger and various X flavors of VMS). X END_OF_FILE if test 5584 -ne `wc -c <'ChangeLog'`; then echo shar: \"'ChangeLog'\" unpacked with wrong size! fi # end of 'ChangeLog' fi if test -f 'HELP' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'HELP'\" else echo shar: Extracting \"'HELP'\" \(7701 characters\) sed "s/^X//" >'HELP' <<'END_OF_FILE' X ::: to quit this display, type 'q'. Hit space for more. ::: X XWelcome to Hand --interactive. X XThe purpose of interactive hand, as of regular hand, is to make Xinter-personal communications as easy as possible. While regular hand Xis very good for telling whether anyone you know is logged in, it does Xnot help you at all in trying to talk to them. Interactive hand does. X XThe main menu X XWhen you first call up interactive hand, you will see somewhere near the Xbottom of your screen a menu that looks like this: X XCommands: (C)opyright info, (d)omain, (h)and, (o)ptions, (q)uit, X (s)end message, (t)alk, (W)arranty info X (q)uit hand, ? = view help file X XIf you're reading this, you've figured out that typing '?' will call up Xthis help file. Similarly, typing 'C' will call up the terms of the Xliscence under which hand is provided, and 'W' will explain in Xexcruciating detail that there is no warranty for hand, since it's free. X XTyping 'q' or 'x' will end the session. X XThe other things that you can do from the main menu are the following: X Xdomain (d) get information on a particular host. The standard X program for this, Berkeley nslookup, isn't too hot about X providing lots of information, but there are better ones X around that you can use instead, by setting it in the options X menu (more on that later). If you have selected a host, 'd' X will give you information about that host; if you have not X selected a host, 'd' will prompt you for a hostname, and then X provide information about *that* host. If you have selected X more than one host, the results are unpredictable; this should X be fixed before the program is released, however. X Xhand (h) run hand in a window. This is how you select hosts, X people, and people@hosts. When hand runs, it will output in X list form, as though you had run "hand -L". When it has X finished, a the window will show the top of the list (if it is X a large one) and in the left margin, pointing at the first X entry in the list, will appear an index, represented by a X greater-than symbol, '>'. Hitting return (or space) will X select the entry that the index is pointing at; when an entry is X selected, a plus sign, '+', will appear in the margin, to the X right of the index. Unselect in the same way, by pressing X return (or space). The cursor controls will move the index up X or down through the list, scrolling the window if necessary; X failing that, the control-P and control-N characters will move X the index up and down, respectively. X Xoptions (o) set options for interactive hand. This is how to set the X finger timeout, maximum idle time, address file, and various X commands. It is described in more detail below under "options X menu". X Xsend (s) send a message to someone on your own host. Pressing 's' X will call up the send command, typically "write", to talk to X someone who is logged in on your host. As with the domain X command, the results are unpredictable if more than one person X is selected, and the send will fail if the person(s) that you X have selected are not on your host. The standard UNIX write X command will not accept more than one user at a time, and will X not send messages to another host. X Xtalk (t) talk to a person or persons. Typing 't' will invoke a X talk session between you and whomever you have selected out of X the list. If your talk supports multiple-user conferencing X (e.g. YTalk) then all users that you have selected will be X included in the conversation. Again, the standard Berkeley X Talk is not the best thing around; but the better talk X programs are freely available. X XThe options menu X XWhen you enter the options menu by typing 'o' at the main menu prompt, Xyou will see a display similar to the following: X XOptions: X automatically run hand: NO X idle time maximum: 60 minutes X TCP timeout (for fingers): 15 seconds X one report for multiple logins: YES X file name: /f0/perseant/.addresses.dat X talk command: talk X send command: write X nameserver-lookup command: nslookup X XSome of these options are not as clear as others, so following is a Xdescription of them all. The options are set by typing the first Xletter of their name, also listed near the bottom of the screen in a Xmenu. Options whose value is boolean (yes/no) are merely toggled; they Xwill not prompt for a value, but simply change their value and return Xyou to the menu prompt. All the other options, when selected, will prompt Xfor a string; you can then enter a string of one or more characters to Xset the option, or simply type return to leave the option as it was. X XTo save the options as they appear, so that those options are used every Xtime you run hand interactive, type '>'; if you err in entering an Xoption, type '<' to load the last-saved set of options; and to return to Xthe main menu, type 'q' or 'x'. X XDescriptions of options: X Xautomatically run hand: (YES or NO) When you first invoke interactive X hand, you have to hit 'h' in order to get a list X of people who are currently logged in. If this X option is set to YES, this will be done X automatically whenever you begin a session. To X change this option setting, type 'a'. X Xidle time maximum: (1-LONG_MAX minutes) This specifies, in minutes, X how long a user must be idle before he is X considered "not logged in"; i.e., if he is idle X longer than this amount he will not show up on X the display. To completely disable this option, X and display everyone, no matter how long they X have been idle, enter 0 as the new idle maximum; X 0 will be converted into a very large number X (LONG_MAX) before it is displayed above, so if X you see something other than 0 when you think it X ought to be 0, don't worry. X XTCP timeout: (1-60 seconds) This determines how long a host X should be waited for, when hand asks it for X information, before hand considers it to X be down. The default timeout for UNIX finger is X 60 seconds; the default for hand is a much more X reasonable 15 seconds. If you are getting X messages about hosts "timing out on read", X increasing this parameter may help. Setting it X too large, however, will cause hand to wait for X an unacceptable amount of time if a host is X actually down. As with idle time, setting TCP X timeout to zero will cause it to take on a very X large value (INT_MAX). Due to the limitations X of TCP, however, all values greater than 59 are X the same, so INT_MAX is equivalent to 60. X Xone report for multiple logins: (YES or NO) If this option is set "yes", X users who are logged in a number of times to the X same host will only be reported once, with the X least idle time of any of their terminals. If X this option is set "no", then no matter how many X times a user is logged in to a single host at X one time, each login will be reported X individually. If there are people on your list X who use X, "yes" is the recommended setting. X Xfile name: The name of the file that contains the user and X host lists that hand is to use when searching, X typically ~/.addresses.dat (although the '~' X will be expanded to a full pathname). X Xtalk command: The name of the command to be used when talk is X to be invoked from the main menu. The default X is talk, i.e. Berkeley Talk, unless another talk X program is standard on your system. X Xsend command: The name of the command to be invoked to send a X message to another user on your own host--'s' X from the main menu--, typically write. X Xnameserver-lookup command: The name of the command to be used when X "domain" is to be invoked from the main menu. X The default is Berkeley nslookup. END_OF_FILE if test 7701 -ne `wc -c <'HELP'`; then echo shar: \"'HELP'\" unpacked with wrong size! fi # end of 'HELP' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(951 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X COPYING 2 X ChangeLog 1 X HELP 1 X MANIFEST 1 This shipping list X Makefile.in 1 X README 1 X config.h.in 1 X configure 3 X getopt.c 2 X getopt.h 1 X glovcurs.h 1 X hand.1 1 X hand.h 1 X handarg.c 2 X handarg.h 1 X handi.c 1 X handsort.c 3 X handsort.h 1 X handstr.c 1 X handstr.h 1 X handtcp.c 2 X handtcp.h 1 X main.c 3 X parse.c 1 X parse.h 1 X wrist.1 1 X wrist.c 1 END_OF_FILE if test 951 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'Makefile.in' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile.in'\" else echo shar: Extracting \"'Makefile.in'\" \(3154 characters\) sed "s/^X//" >'Makefile.in' <<'END_OF_FILE' X# X# Makefile for Unix hand X# Xprefix= /usr/local Xexec_prefix= $(prefix) Xbinprefix= Xmanprefix= Xbindir= $(exec_prefix)/bin Xlibdir= $(exec_prefix)/lib Xmandir= $(prefix)/man/man1 Xmanext= 1 X XCC= @CC@ XINSTALL= @INSTALL@ XINSTALL_PROGRAM=@INSTALL_PROGRAM@ XINSTALL_DATA=@INSTALL_DATA@ XCFLAGS= -O XLDFLAGS= -O @LIBS@ XDEFS= @DEFS@ XSHELL= /bin/sh X XSHARESRC= main.c handarg.c handtcp.c handstr.c parse.c handsort.c getopt.c XHANDSRC= handi.c XGLOVESRC= glovei.c glovcurs.c XWRISTSRC= wrist.c XSHAREOBJ= $(SHARESRC:.c=.o) XHANDOBJ= $(HANDSRC:.c=.o) XGLOVEOBJ= $(GLOVESRC:.c=.o) XWRISTOBJ= $(WRISTSRC:.c=.o) XALLOBJ= $(SHAREOBJ) $(HANDOBJ) $(GLOVEOBJ) $(WRISTOBJ) XHDRS= hand.h handarg.h handtcp.h handsort.h handstr.h parse.h \ X getopt.h glovcurs.h XDISTFILES=$(HANDSRC) $(SHARESRC) Makefile.in configure COPYING HELP README \ X $(HDRS) $(WRISTSRC) ChangeLog hand.1 wrist.1 config.h.in #$(GLOVESRC) X Xall: hand X X$(ALLOBJ): hand.h config.h X Xconfig.h: X sh configure X Xwrist: $(WRISTOBJ) getopt.o X $(CC) -o wrist $(WRISTOBJ) getopt.o $(LDFLAGS) X size wrist X Xhand: $(SHAREOBJ) $(HANDOBJ) X $(CC) -o hand $(HANDOBJ) $(SHAREOBJ) $(LDFLAGS) X size hand X Xglove: $(SHAREOBJ) $(GLOVEOBJ) X $(CC) -o glove $(GLOVEOBJ) $(SHAREOBJ) $(LDFLAGS) -lcurses -ltermcap X size glove X X.c.o: X $(CC) -c $(CFLAGS) $(DEFS) $*.c X Xinstall: X $(INSTALL_PROGRAM) hand $(bindir)/$(binprefix)hand X# $(INSTALL_PROGRAM) glove $(bindir)/$(binprefix)glove X# $(INSTALL_PROGRAM) wrist $(bindir)/$(binprefix)wrist X $(INSTALL_DATA) hand.1 $(mandir)/$(manprefix)hand.$(manext) X# $(INSTALL_DATA) wrist.1 $(mandir)/$(manprefix)wrist.$(manext) X Xdeinstall: X rm $(bindir)/$(binprefix)hand X# rm $(bindir)/$(binprefix)glove X# rm $(bindir)/$(binprefix)wrist X rm $(mandir)/$(manprefix)hand.$(manext) X# rm $(mandir)/$(manprefix)wrist.$(manext) X Xdepend: X makedepend -- $(CFLAGS) -- $(ALLSRC) X Xdist: knrdist X Xansidist: X echo hand-`sed -e '/HAND_VERSION/!d' \ X -e 's/[^"]*"\([0-9.]*[ab]*\)".*/\1/' -e q hand.h` > .fname X rm -rf `cat .fname` X mkdir `cat .fname`-ansi X -ln $(DISTFILES) `cat .fname`-ansi X for file in $(DISTFILES); do \ X test -r `cat .fname`-ansi/$$file || cp -p $$file `cat .fname`-ansi; \ X done X /bin/tar chf `cat .fname`-ansi.tar `cat .fname`-ansi X compress `cat .fname`-ansi.tar X rm -rf `cat .fname`-ansi .fname X Xknrdist: X sh configure X echo hand-`sed -e '/HAND_VERSION/!d' \ X -e 's/[^"]*"\([0-9.]*[ab]*\)".*/\1/' -e q hand.h` > .fname X rm -rf `cat .fname` X mkdir `cat .fname` X cp $(DISTFILES) config.h `cat .fname` X cd `cat .fname`; unprotoize -c -DRESOURCE_DIR=\"\" *.c; rm config.h *.save X /bin/tar chf `cat .fname`.tar `cat .fname` X compress `cat .fname`.tar X rm -rf `cat .fname` .fname X Xshar: X sh configure X echo hand-`sed -e '/HAND_VERSION/!d' \ X -e 's/[^"]*"\([0-9.]*[ab]*\)".*/\1/' -e q hand.h` > .fname X rm -rf `cat .fname` X mkdir `cat .fname` X cp $(DISTFILES) config.h `cat .fname` X cd `cat .fname`; unprotoize -c -DRESOURCE_DIR=\"\" *.c; rm config.h *.save X cd `cat .fname`; shar -o ../`cat ../.fname`.shar * X rm -rf `cat .fname` .fname X Xclean: X rm -f $(ALLOBJ) hand core config.status config.h *~ X Xquota: X rm -f $(ALLOBJ) X# X# DO NOT DELETE THIS LINE -- make depend depends on it. END_OF_FILE if test 3154 -ne `wc -c <'Makefile.in'`; then echo shar: \"'Makefile.in'\" unpacked with wrong size! fi # end of 'Makefile.in' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(3574 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XREADME file for Hand 1.70 : last updated Wednesday 22 June 1994. X XWhat: Find out if anyone you know is on, anywhere you care to look. X XHow: Hand, in essence, is "a bunch of fingers". It will read its list X of usernames and hostnames from a file, typically ~/.hand . The X output of the hosts' fingerds will be compared against the user X list, and any matches will be reported. That's the basic idea, X anyway. It's actually somewhat more complicated. (Witness the X 3000+ lines of code!) X XWhy: Hand was developed primarily because I have seen a lot of people do X extremely inefficient things to try and find out whether any of X their friends are logged in; the most common that I have seen is X for a user to invoke "users" on a machine with a current X population of 250+; another good one is someone who habitually X fingers, say, seven or eight people on four or five sites. Tcsh's X builtin recognizer (and others that I have seen) is good, but X doesn't traverse the network; so, I decided to write my own that X will. X XInstallation: X as a Normal User (~/bin) X X example% configure --prefix=$HOME X example% make X example% make wrist #only if you want wrist X example% make install X X as Root (/usr/local/bin) X X example% sh configure X example% make X example% make install X X Hand is known to compile cleanly on the following systems: X X BSD flavored: X NetBSD 0.9 (Clone '386) X NeXTstep 2.1 (NeXT '030) X NeXTstep 3.0 (NeXT '040) X SunOS 3.5 (Sun '020) X SunOS 4.1.1 (Sun sparc) X POSIX compliant: X AIX 3.2 (IBM rs6000) X Linux 1.0 (Clone '386) X OSF/1 2.0 (DEC alpha) X Solaris 2.3 (Sun SPARC) X SunOS 4.1.3 (Sun SPARC) X Ultrix 4.2 (DEC mips) X System V flavored: X Dynix/PTX 3.2 (Symmetry sequent) X XNew as of this version: X X The --port option was added, for those rare machines with a X non-standard (possibly user-driven) finger port. X X Per-host flags in the .hand file (--port is one that you'd want on X a per-host basis; another might be --timeout). X X --obey-host is now the default, after experiencing GNU finger up X close. X X --login-command and --logout-command flags will now perform commands X for you whenever someone logs in or out (for use with the --watch X option). X X --add-host and --add-user, if given no options, will now start an X interactive host/user-addition process that's also used by hand to X start you off if you don't have a .hand file. X X Will now compile on older Unices, or at least sun2's (BSD 4.2). X X Watch is shipped with this version as a beta, but glove is not X (changes to hand would have required re-writing portions of glove, X which I'm not supporting). X XWarranty and Copyright: X Hand comes with NO WARRANTY of any kind. It is copyright (c) X 1992, 1993, 1994 Konrad Schroder, but is released under the GNU X General Public License, so feel free to share: see the file X COPYING for details. X X However: X X So long as I have access to a network-connected Unix system, I X will attempt to fix any and all bugs that are sent to me, so long X as the bug-reporter provides me with enough information ("hand X didn't work, why not" is a complaint, not a bug report). X X Konrad Schroder X perseant@u.washington.edu END_OF_FILE if test 3574 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'config.h.in' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'config.h.in'\" else echo shar: Extracting \"'config.h.in'\" \(1732 characters\) sed "s/^X//" >'config.h.in' <<'END_OF_FILE' X/* config.h.in. Generated automatically from configure.in by autoheader. */ X X#ifndef CONFIG_H_ X#define CONFIG_H_ X X/* This is the ONLY thing in this file that should have to be modified Xby hand. */ X#define MAX_FORKS 10 X X/* Define if processes need to be screened against USER_PROCESS */ X#undef HAVE_USER_PROCESS X X/* Define if on AIX 3. X System headers sometimes define this. X We just want to avoid a redefinition error message. */ X#ifndef _ALL_SOURCE X#undef _ALL_SOURCE X#endif X X/* Define to empty if the keyword does not work. */ X#undef const X X/* Define if you have unistd.h. */ X#undef HAVE_UNISTD_H X X/* define if you have stdlib.h. */ X#undef HAVE_STDLIB_H X X/* Define if you need to in order for stat and other things to work. */ X#undef _POSIX_SOURCE X X/* Define as the return type of signal handlers (int or void). */ X#undef RETSIGTYPE X X/* Define if the setvbuf function takes the buffering type as its second X argument and the buffer pointer as the third, as on System V X before release 3. */ X#undef SETVBUF_REVERSED X X/* Define if you have the ANSI C header files. */ X#undef STDC_HEADERS X X/* Define if you have the header file. */ X#undef HAVE_STRING_H X X/* define if you have strcasecmp(). */ X#undef HAVE_STRCASECMP X X/* define if you have strncasecmp(). */ X#undef HAVE_STRNCASECMP X X/* define if you have tzset(). */ X#undef HAVE_TZSET X X/* define to have the return type of wait */ X#undef UNION_WAIT X X/* define if you have difftime(3) */ X#undef HAVE_DIFFTIME X X/* define if you have getdtablesize(2). If not, X * calls to getdtablesize() will be replaced by "32". */ X#undef HAVE_GETDTABLESIZE X X/* For glove---the resources directory */ X#undef RESOURCE_DIR X X/* end of header file */ X X#endif /* CONFIG_H_ */ END_OF_FILE if test 1732 -ne `wc -c <'config.h.in'`; then echo shar: \"'config.h.in'\" unpacked with wrong size! fi # end of 'config.h.in' fi if test -f 'getopt.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getopt.h'\" else echo shar: Extracting \"'getopt.h'\" \(3963 characters\) sed "s/^X//" >'getopt.h' <<'END_OF_FILE' X/* Declarations for getopt. X Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. X X This program is free software; you can redistribute it and/or modify it X under the terms of the GNU General Public License as published by the X Free Software Foundation; either version 2, or (at your option) any X later version. X X This program is distributed in the hope that it will be useful, X but WITHOUT ANY WARRANTY; without even the implied warranty of X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X GNU General Public License for more details. X X You should have received a copy of the GNU General Public License X along with this program; if not, write to the Free Software X Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ X X#ifndef _GETOPT_H X#define _GETOPT_H 1 X X#ifdef __cplusplus Xextern "C" { X#endif X X/* For communication from `getopt' to the caller. X When `getopt' finds an option that takes an argument, X the argument value is returned here. X Also, when `ordering' is RETURN_IN_ORDER, X each non-option ARGV-element is returned here. */ X Xextern char *optarg; X X/* Index in ARGV of the next element to be scanned. X This is used for communication to and from the caller X and for communication between successive calls to `getopt'. X X On entry to `getopt', zero means this is the first call; initialize. X X When `getopt' returns EOF, this is the index of the first of the X non-option elements that the caller should itself scan. X X Otherwise, `optind' communicates from one call to the next X how much of ARGV has been scanned so far. */ X Xextern int optind; X X/* Callers store zero here to inhibit the error message `getopt' prints X for unrecognized options. */ X Xextern int opterr; X X/* Describe the long-named options requested by the application. X The LONOPTIONS argument to getopt_long or getopt_lononly is a vector X of `struct g_option' terminated by an element containing a name which is X zero. X X The field `has_arg' is: X no_argument (or 0) if the option does not take an argument, X required_argument (or 1) if the option requires an argument, X optional_argument (or 2) if the option takes an optional argument. X X If the field `flag' is not NULL, it points to a variable that is set X to the value given in the field `val' when the option is found, but X left unchanged if the option is not found. X X To have a long-named option do something other than set an `int' to X a compiled-in constant, such as set a value from `optarg', set the X option's `flag' field to zero and its `val' field to a nonzero X value (the equivalent single-letter option character, if there is X one). For long options that have a zero `flag' field, `getopt' X returns the contents of the `val' field. */ X Xstruct g_option X{ X#if __STDC__ X const char *name; X#else X char *name; X#endif X /* has_arg can't be an enum because some compilers complain about X type mismatches in all the code that assumes it is an int. */ X int has_arg; X int *flag; X int val; X}; X X/* Names for the values of the `has_arg' field of `struct g_option'. */ X Xenum _argtype X{ X no_argument, X required_argument, X optional_argument X}; X X#if __STDC__ X#if defined(__GNU_LIBRARY__) X/* Many other libraries have conflicting prototypes for getopt, with X differences in the consts, in stdlib.h. To avoid compilation X errors, only prototype getopt for the GNU C library. */ Xextern int getopt (int argc, char *const *argv, const char *shortopts); X#else /* not __GNU_LIBRARY__ */ Xextern int getopt (); X#endif /* not __GNU_LIBRARY__ */ Xextern int getopt_long (); Xextern int getopt_lononly (); X X/* Internal only. Users should not call this directly. */ Xextern int _getopt_internal (); X#else /* not __STDC__ */ Xextern int getopt (); Xextern int getopt_long (); Xextern int getopt_lononly (); X Xextern int _getopt_internal (); X#endif /* not __STDC__ */ X X#ifdef __cplusplus X} X#endif X X#endif /* _GETOPT_H */ END_OF_FILE if test 3963 -ne `wc -c <'getopt.h'`; then echo shar: \"'getopt.h'\" unpacked with wrong size! fi # end of 'getopt.h' fi if test -f 'glovcurs.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'glovcurs.h'\" else echo shar: Extracting \"'glovcurs.h'\" \(1408 characters\) sed "s/^X//" >'glovcurs.h' <<'END_OF_FILE' X/* X * G L O V C U R S . H - Curses routines for gloved hand. X */ X X/* X * Copyright (C) 1993 Konrad Schroder. X * X * Gloved hand is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * Gloved hand is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with gloved hand; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#ifndef HANDCURSES_H_ X# define HANDCURSES_H_ X X#include X#include X X#ifdef OLDUNIX X# define cbreak() crmode() X# define nocbreak() nocrmode() X#endif X X#define wsgets(S,N,W) wgets((S),(N),(W)); while(isspace((S)[strlen(S)-1]))\ X (S)[strlen(S)-1]='\0' Xstruct winent { X int linec; X int colc; X char data[1]; X}; X Xchar *wgets(char *, int, WINDOW *); Xint wsystem(int, int, char *); Xint bigwsystem(char *); Xstruct winent *pushscr(void); Xvoid popscr(struct winent *); Xvoid h_clear(int,int); X X#endif /* HANDCURSES_H_ */ END_OF_FILE if test 1408 -ne `wc -c <'glovcurs.h'`; then echo shar: \"'glovcurs.h'\" unpacked with wrong size! fi # end of 'glovcurs.h' fi if test -f 'hand.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hand.1'\" else echo shar: Extracting \"'hand.1'\" \(9695 characters\) sed "s/^X//" >'hand.1' <<'END_OF_FILE' X.TH hand 1 X.SH Name Xhand \- report logged in associates by username X.SH Synopsis X.B hand X.B [\-[n]DFHLoqw] X.B [\-hlsv] X.B [\-f X.IB filename ] X.B [\-i X.IB idle\-max ] X.B [\-t X.IB timeout ] X.B [\-\-file X.IB filename ] X.B [\-\-here] [\-\-home] [\-\-[no\-]beep] [\-\-[no\-]idle X.IB idle\-max ] X.B [\-\-[no\-]list] X.B [\-\-login\-command=\fIcommand\fB] [\-\-logout\-command=\fIcommand\fB] X.B [\-\-[no\-]header] [\-\-[no\-]fork] X.B [\-\-[no\-]obey\-host\-field] X.B [\-\-[no\-]once\-only] [\-\-[no\-]quiet] X.B [\-\-[no\-]silent] X.B [\-\-[no\-]timeout X.IB timeout ] X.B [\-\-[no\-]timezone-correction X.B [\-\-verbose] [\-\-[no-\]watch] [\-\-[no\-]what] X.B [\fIuser ...\fB] [@\fIhost ...\fB] [\fIuser\fB@\fIhost ...\fB] X X.B hand \-\-add-user X.B [\fIlogin name\fB [\fIusername\fB]] X X.B hand \-\-add-host [\fIhost name\fB X.B [\fIinformal host name\fB]] X X.B hand \-\-del-user [\fIlogin name\fB] X X.B hand \-\-del-host [\fIhost name\fB] X.SH Description X.NXR "hand command" X.NXR "associates" "reporting" X.NXR "finger" "w" X.B Hand Xcompares the lists of users logged in to the network hosts specified in Xthe data file (\fI~/.hand\fR by default) to the list of Xusernames in that file, and reports any agreement. If invoked with the X\-\-add or \-\-del options, however, \fBhand\fR will instead manipulate Xthe address file (see \-\-add and \-\-del below). X XIf \fBhand\fR is invoked with a list of usernames and/or a list of Xhostnames as arguments, such lists will supercede the corresponding Xlists in the data file. X XIn the data file, host sites need not be alphabetized, although user Xentries must be alphabetized by username. (Numerals come before any Xletter.) The search for a particular user can be restricted by following his Xlogin name with an @, followed by a comma-separated list of hosts. XIf a user's name is followed by ``@\fIhost\fR'' Xhe will be looked for only at hosts beginning with \fIhost\fR, and if the Xsearch is to be performed only on systems in a particular domain, X``user@*.\fIdomain\fR'' will restrict searching to \fIdomain\fR. XIf \fIhost\fR is preceded by an exclamation mark (!), the search will be Xrestricted to hosts other than \fIhost\fR. X XNote that since this applies to command\-line arguments as well as to entries Xin the data file, there is a considerable difference between the constructions X``user @host'' and ``user@host'', and neither usage is equivalent to the Xsame usage of \fBfinger\fR(1). X XThe format for host entries in the data file is X X.nf X [:nick-name][:hours east of Greenwich][:per-host flags] X.fi X Xand that for user entries X X.nf X [nick-name] X.fi X XThe character # is used to begin comments, which last until the end of the Xline; if preceded with \\, however, # is prevented this special Xmeaning. X.PP XFor example: X X.nf X HOST LIST X #128.95.48.32:Byron:-8: X 128.95.136.13:Hardy:-8: X 128.95.136.1:Milton:-8: X 140.142.52.11:Carson:-8: X 128.95.56.201:Michael (ACC NeXT \\# 1):-8:--obey-host --quiet X lighthouse.caltech.edu:Lighthouse:-8: X david.wheaton.edu:David:-6: X # X PSEUDONYM LIST X Dump@max,lighthouse David X Dump@!max,!lighthouse Don X Ender Wolfe #This is a comment X JPitera@*.caltech.edu Jed X Keeper@lighthouse Steve X Nuitari Alex X Xibalba@*.caltech.edu Steve X.fi X.PP XThe following options are interpreted by \fBhand\fR. Short options, Xi.e. those preceded by a ``\-'', if they do not take arguments, can be Xnegated by prefixing an ``n'', e.g. ``\-nF'' to mean ``not \-F''. XLikewise, long options, i.e. those preceded by a ``\-\-'', can be Xnegated by inserting a ``no\-'' following the ``\-\-'', e.g. X``\-\-no\-fork'' for ``not \-\-fork''. All options can be negated in Xthis way except as indicated. Also, long options can be abbreviated to Xany unique substring; for example, ``\-\-add\-h'' for ``\-\-add\-host''. X.LP XFor backward compatibility, long options can also be specified with `+' Xinstead of `\-\-'. X.TP X\-\-add\-host \fIhost\-name nick\-name\fR XAdds the line X X.nf X \fIhost\-name:nick\-name:n:\fR X.fi X Xto the host section of the specified address file, where \fIn\fR is the Xtimezone of \fIhost\-name\fR. If \fIhost\-name\fR is omitted, hand will Xgo into an interactive host addition mode. X.TP X-\-add\-user \fIlogin\-name nick\-name\fR XAdds the line X X.nf X \fIlogin-name nick-name\fR X.fi X Xto the users section of the specified address file. If X\fIlogin\-name\fR is omitted, hand will enter an interactive user Xaddition mode. X XAfter the new information has been added to the file, the corresponding Xsection will be sorted and checked for redundancies, with an effort to Xkeep comments intact and correctly placed. The user list is sorted Xalphabetically, the host list by IP address. X.TP X\-\-beep XBeep whenever someone logs in or out; to be used with the \-\-watch Xoption. \-\-beep is the default. X.TP X\-C, \-\-copyright XDisplay copyright information. X.TP X\-\-del\-user \fIname\fR, \-\-del\-host \fIname\fR XDeletes \fIname\fR from the corresponding section of the address file. X.TP X\-F, \-\-fork XUse parallel rather than linear processing. While -nF almost guarantees Xslower real\-time performance, it is generally \fInice\fRr (see Bugs below). X.TP X\-f \fIfile, \fR\-\-file \fIfile\fR (Non-negatable) XRead data from X.I file.\ XThe default is ~/.hand. X.TP X\-h, \-\-here, \-\-home (Non-negatable) XFind users only at the host on which \fBhand\fR is being run, Xunless more hosts are specified by @\fIhost\fR. Same as @\-. X.TP X\-H, \-\-header XDo not suppress output of the header. This is the default. X.TP X\-i \fIidle-max\fR, \-\-idle \fIidle-max\fR XTreat users idle more than \fIidle\-max\fR minutes as though they were not Xlogged in. If \fIidle\-max\fR is equal to zero, users will be reported Xno matter how long they have been idle. The default is \-i0. X.TP X\-L, \-\-list XOutput data in list format, as w(1). Default is complete sentence format. X.TP X\-\-login\-command=\fIcommand\fR X(For use with the \fB\-\-watch\fR option.) Execute \fIcommand\fR Xthrough the shell whenever a user logs in. Before it is executed, the Xfollowing substitutions will be performed: X.nf X This: Becomes: X %% A literal '%'. X %h The host name. X %i The user's idle time, in minutes. X %m The word "finger" (for compatibility reasons). X %t The user's TTY, if known. X %u The user name. X %U The user's nickname. X.fi X.TP X\-\-logout\-command=\fIcommand\fR X(For use with the \fB\-\-watch\fR option.) Execute \fIcommand\fR Xthrough the shell whenever a user logs out. Substitutions are made for % Xstrings as given above. X.TP X\-o, \-\-once\-only XReports only the least idle of any occurrences of a given user on a given Xmachine. -o is the default. X.TP X\-O, \-\-obey\-host\-field XShows the host that is given in the finger information rather than that Xin the address file, if the finger daemon gives output in the form X X.nf X User Real Name Idle TTY Host Office X perseant Konrad Schroder 0:08 *p1 barbarbar X.fi X Xindicating that perseant is logged in to barbarbar, rather than Xwherever it was that you fingered. X.TP X\-q, \-\-quiet, \-\-silent XReport only fatal errors. In particular, ``connection timed out'' and X``timeout on read'' errors are silenced. X.TP X\-t \fItimeout\fR, \-\-timeout \fItimeout\fR XSpecifies the maximum time, in seconds, that a remote host is Xallowed to connect before \fBhand\fR times out. Default is 10. If X\fItimeout\fR is equal to zero, the TCP protocol maximum of 60 will be used. X.TP X\-T, \-\-timezone\-correction XAttempt to compensate for different timezones when reporting login times. X.TP X\-u, \-\-usage XGives a short usage guide for \fBhand\fR, which is also seen if an option is Xpassed to \fBhand\fR that it does not recognize. X.TP X\-V, \-\-version XPrint the version number and exit. X.TP X\-v, \-\-verbose (Non-negatable) XIncrement the verbosity to give debugging information. The typical user will Xnot want to make use of this option. X.TP X\-\-watch XIf invoked with \-\-watch, \fBhand\fR will run continuously, reporting Xwhenever any user on the user list logs into or out of any host on the host Xlist. If \fBhand\fR is also invoked with \-\-list, lines will be of the form X``+user@host (User Name)'' or ``-user@host (User Name)''. The stdout Xstream is line buffered, so that filters can make use of the login Xinformation as it occurs. X.TP X\-w, \-\-what XMust be used in combination with \-h (\-\-home, \-\-here). Use the output of X.IR w (1) Xfor the local system rather than reading directly from the utmp file. X.LP XFor convenience, the environment variable \fIHAND\fR may be set with one or Xmore options, which will be read by \fBhand\fR as though they appeared on the Xcommand line. The order of precedence of the flags is this: the options Xspecified in the environment variable have the lowest precedence; those Xspecified in the .hand file (per-host) have a higher precedence; and Xthose typed on the command line override the others. X X.SH Bugs X XIf your site and a site that you are fingering differ as to whether it Xis Daylight Savings Time or not, the login time may be an hour off if Xthe \-T option is used. X XThere should be a way to enter timezone and flag information for a host Xfrom the interactive add-host prompt. X XThat the equivalent of ``finger jane@apple john@orange'' is ``hand jane@apple X@apple john@orange @orange'' is counter\-intuitive. X X.SH Author XKonrad Schroder X.SH Files X.PN /etc/utmp Xwho file X.PN ~/.hand Xdefault data file X.SH See Also Xfinger(1), rusers(1), rwho(1), tcp(3), users(1), w(1), who(1). END_OF_FILE if test 9695 -ne `wc -c <'hand.1'`; then echo shar: \"'hand.1'\" unpacked with wrong size! fi # end of 'hand.1' fi if test -f 'hand.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'hand.h'\" else echo shar: Extracting \"'hand.h'\" \(4020 characters\) sed "s/^X//" >'hand.h' <<'END_OF_FILE' X/* X * X * H A N D . H X * X */ X X/* X * Copyright (C) 1992 Konrad Schroder. X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#ifndef HAND_H_ X#define HAND_H_ X X#include X#include "config.h" X X#if HAVE_UNISTD_H X# include X#endif X X#if HAVE_STDC_HEADERS X# include X#endif X X#define HAND_VERSION "1.70" X#define GLOVE_VERSION "0.1.7 (alpha)" X#define DATE "Fri 22 July 1994" X X#if !defined HAVE_DIFFTIME X# define difftime(A,B) ((A)-(B)) /* This isn't the way it *should* be */ X#endif /* but it's portable and it works. */ X X#define NMAX 20 /* max length for login, when, what */ X#define ML 512 /* the maximum line size */ X#define DEFAULT_FINGER_PORT 79 /* the standard Unix finger port */ X Xstruct File X{ char name[ML]; X FILE *fp; }; X Xstruct hname X{ char ascii[ML]; X char true[ML]; X char flags[ML]; X char dot[32]; X int timezone; X int st; }; X Xstruct Option X{ int header ; /* header only if set */ X int error ; /* report only fatal errors */ X int what ; /* use w(1) for localhost */ X int fxfmt ; /* fixed format output */ X int version ; /* report version date */ X int footer ; /* end with a \n if set */ X int once_only ; /* no matter how many shells */ X int localhost ; /* check - against localhost */ X int fork ; /* how many forks allowed */ X int verbose ; /* debugging level */ X int timeout ; /* TCP timeout (seconds) */ X int timezone ; /* Make timezone corrections */ X int nobeep ; /* suppress beeping */ X int watch ; /* Watch for login/logout */ X int idle_max ; /* max "active" idle (minutes)*/ X int host ; /* allow replacement of host by finger "host" */ X int port ; /* alternate finger port */ X int fix ; /* fix warnings in address file? */ X X char incommand[ML]; /* command for login (watch) */ X char outcommand[ML]; /* command for logout (watch) */ X X /* interactive options */ X int auto_hand ; /* run hand to start in interactive mode */ X char chars[4] ; /* unselected, selected, index */ X int user_level ; /* 0 for novice, 1 for expert */ X X#ifdef NODIST X /* local */ X int log; /* log; username (1) or "Anonymous" (0) */ X#endif X X}; X Xstruct Process X{ int pid; X int ret_val; X int pipe[3]; }; X Xstruct User X{ X char name[NMAX]; X char tty[NMAX]; X char when[NMAX]; X char what[NMAX]; X char host[NMAX]; X char line[ML]; X char true[ML]; X int idle; X int flags; }; X Xstruct Friend X{ X char name[NMAX]; X char true[ML]; X char where[ML]; }; X X#define HF_SELECTED 32 X#define HF_HOST 16 X#define HF_TTY 8 X#define HF_IDLE 4 X#define HF_WHEN 2 X#define HF_WHAT 1 X X/* unlink and remember */ X#define delete(F) unlink((F).name); (F).name[0]='\0' X X#ifndef INT_MAX X# define INT_MAX 32767 X#endif X Xchar *fgetl(); Xvoid add_to_new_list(); Xvoid difference(); Xvoid hand_match_out(); Xvoid errout(); Xvoid flush_dead_fetus(); X#endif /* !defined HAND_H_ */ END_OF_FILE if test 4020 -ne `wc -c <'hand.h'`; then echo shar: \"'hand.h'\" unpacked with wrong size! fi # end of 'hand.h' fi if test -f 'handarg.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'handarg.h'\" else echo shar: Extracting \"'handarg.h'\" \(864 characters\) sed "s/^X//" >'handarg.h' <<'END_OF_FILE' X/* X * Copyright (C) 1992 Konrad Schroder. X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#ifndef HANDARG_H_ X#define HANDARG_H_ X Xchar **strarg(); Xint gethandopt(); X X#endif /* !defined HANDARG_H_ */ END_OF_FILE if test 864 -ne `wc -c <'handarg.h'`; then echo shar: \"'handarg.h'\" unpacked with wrong size! fi # end of 'handarg.h' fi if test -f 'handi.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'handi.c'\" else echo shar: Extracting \"'handi.c'\" \(10528 characters\) sed "s/^X//" >'handi.c' <<'END_OF_FILE' X/* X * H A N D I . C - Interface routines for hand. X */ X X/* X * Copyright (C) 1993 Konrad Schroder. X * X * Hand is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * Hand is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with hand; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#include "hand.h" /* needed here for ifdef's below */ X#include X#include X#include X#include X#include X#include X#include X#include X#if HAVE_UNISTD_H X# include X#endif X#if HAVE_STDLIB_H X# include X#endif X#include "handarg.h" X Xextern struct Option option; Xextern struct File tmp[4]; Xextern char *tmpdir, runninghost[]; Xextern jmp_buf hither; Xextern int ppid, mypid, my_timezone, is_dst; X Xextern int h_main(); Xextern void abrt(); X Xextern char **global_argv, **global_envv, home[]; X Xstruct User *new_list=NULL, *old_list=NULL; Xint nlistc=0, olistc=0; Xchar program_name[]="hand"; X X/* X * This is main(), the entry point for hand. All it does is set up the X * options from the argument list, and call h_main (in main.c). X */ X Xint main(argc, argv) X int argc; X char **argv; X{ X int nusr; X char fn[ML], *wusr; X time_t tym; X struct tm ltm, gtm; X X /* X * Initial setup. X * Figure out a good temporary directory, and remember it. X * Set up the signal handler for SIGINT. X * Get the local host name, and trim any trailing domain. X */ X X tmp[2].name[0]='\0'; X X /* wusr used here as a temporary variable */ X gethostname(runninghost,64); X if((wusr=(char *)strchr(runninghost,'.'))!=NULL) X *wusr='\0'; X X if(access(tmpdir="/usr/tmp",W_OK|R_OK)==0) X ; X else if(access(tmpdir="/tmp",W_OK|R_OK)==0) X ; X else if(access(tmpdir=".",W_OK|R_OK)==0) X ; X else X { X errout(program_name, "no temporary filesystem available.\n",""); X flush_dead_fetus(); X } X X strcpy(home,(char *)getenv("HOME")); X X /* set the jump for return from the SIGINT handler */ X X if(setjmp(hither)) X { X /* These instructions only get called if hand is interrupted. */ X X signal(SIGINT,SIG_IGN); X signal(SIGHUP,SIG_IGN); X X if(ppid==mypid) /* print the message only if the parent */ X printf("\rAbort!\nHave a nice day.\n"); X flush_dead_fetus(); X } X X /* X * Figure out the timezone, in a system-independent way. X */ X X#ifdef HAVE_TZSET X tzset(); X#endif X time(&tym); X memcpy(<m,localtime(&tym),sizeof(struct tm)); X memcpy(>m,gmtime(&tym),sizeof(struct tm)); X my_timezone = ltm.tm_hour-gtm.tm_hour; X is_dst = ltm.tm_isdst; X if(my_timezone > 12) /* +12 or -12? */ X my_timezone = my_timezone-24; /* which exists? */ X X#if 0 /* won't compile on some machines */ X if(option.verbose) X { X printf("Local (%s) time is %u:%u, Greenwich Mean Time is %u:%u;\n", X tzname[1], ltm.tm_hour, ltm.tm_min, X gtm.tm_hour, gtm.tm_min), X printf("so my timezone is: %d hours east of Greenwich (right now)\n", X my_timezone); X } X#endif X X /* X * Environment variable HAND and argument handling. We read the X * HAND variable as an argv list first, then the provided argv. X * Later, we may be re-doing this with a host-dependent argv in-between. X */ X X set_defaults(fn); X if(gethandopt((global_envv=strarg(argv,(char *)getenv("HAND"))), X fn,&tmp[2],&wusr,&nusr)<0) X exit(1); X if(gethandopt((global_argv=argv), fn, &tmp[2], &wusr, &nusr)<0) X exit(1); X X if(option.version) X { X printf("%s version %s (%s)\n",program_name,HAND_VERSION,DATE); X printf("Compilation options:\n"); X#if NODIST X printf("NODIST "); X#endif X#if HAVE_CONFIG_H X printf("HAVE_CONFIG_H "); X#endif X#if HAVE_USER_PROCESS X printf("HAVE_USER_PROCESS "); X#endif X#if UTMP_FILE X printf("UTMP_FILE=%s",UTMP_FILE); X#endif X putchar('\n'); X exit(0); X } X if(option.verbose) X { X printf("%d: options:\n",mypid); X printf("\theader: %d\n\terror: %d\n", X option.header, option.error); X printf("\twhat: %d\n\tfxfmt: %d\n\tfork: %d\n", X option.what, option.fxfmt, option.fork); X printf("\tversion: %d\n\tfooter: %d\n\tonce_only: %d\n", X option.version, option.footer, option.once_only); X printf("\tlocalhost: %d\n\ttimezone: %d\n", X option.localhost, option.timezone); X printf("\twatch: %d\n\thost: %d\n", X option.watch, option.host); X printf("\ttimeout: %d\n\tidle_max: %ld\n", X option.timeout, option.idle_max); X } X if(option.watch) X { X option.header=option.footer=0; X#if 0 X setlinebuf(stdout); X#else X setvbuf(stdout,NULL,_IOLBF,BUFSIZ); X#endif X for(;;) X { X h_main(nusr, wusr, fn, stdout); X sleep(option.watch*60); X } X } X else X return h_main(nusr, wusr, fn, stdout); X} X Xvoid add_to_new_list(friend) X struct User *friend; X{ X new_list = (struct User *)realloc(new_list, X sizeof(struct User)*(nlistc+1)); X new_list[nlistc] = *friend; X new_list[nlistc].flags &= ~HF_SELECTED; X nlistc++; X X return; X} X Xvoid hand_match_out(proc, friend, fd) X int proc; X struct User friend; X int fd; X{ X char s[ML]; X X if(option.watch && !option.fork) X { X add_to_new_list(&friend); X return; X } X else if(option.fork) X write(fd,(void *)&friend,sizeof(friend)); X else X printf("%s",friend.line); X X return; X} X Xchar *strfmatch(s, fmt, user) X char *s; X char *fmt; X struct User *user; X{ X char *cp, *sp; X X for(cp=fmt,sp=s;*cp;cp++,sp++) X { X if(*cp != '%') X *sp = *cp; X else X { X switch(*++cp) X { X case '%': X *sp='%'; X break; X case 'h': X strcpy(sp,user->host); X sp += strlen(user->host)-1; X break; X case 'i': X sprintf(sp,"%d",user->idle); X sp = sp+strlen(sp)-1; X break; X case 'm': X strcpy(sp,"finger"); X sp += 5; X break; X case 't': X strcpy(sp,user->tty); X sp += strlen(user->tty)-1; X break; X case 'u': X strcpy(sp,user->name); X sp += strlen(user->name)-1; X break; X case 'U': X strcpy(sp,user->true); X sp += strlen(user->true)-1; X break; X } X } X } X *sp='\0'; X if(option.verbose) X printf("strfmatch returning %s for %s\n",s,fmt); X return s; X} X Xvoid difference() X{ X int should_beep=0, i, j, match; X char s[ML]; X X /* X * Since both of these lists should be reasonably small, neither X * of them are alphebetized in any way. Thus, each has to be completely X * searched. However, since both of these lists are to be held in X * memory, the search should be reasonably quick. X */ X X if(option.verbose) X { X for(i=0;i'handsort.h' <<'END_OF_FILE' X/* X * H A N D S O R T . H - Header for handsort.c X */ X X/* X * Copyright (C) 1992 Konrad Schroder. X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X#ifndef HANDSORT_H_ X#define HANDSORT_H_ X Xint hsort(); Xvoid checkhosts(); Xvoid adduser(); Xvoid addhost(); Xvoid deluser(); Xvoid delhost(); X X#endif /* defined HANDSORT_H_ */ END_OF_FILE if test 987 -ne `wc -c <'handsort.h'`; then echo shar: \"'handsort.h'\" unpacked with wrong size! fi # end of 'handsort.h' fi if test -f 'handstr.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'handstr.c'\" else echo shar: Extracting \"'handstr.c'\" \(6623 characters\) sed "s/^X//" >'handstr.c' <<'END_OF_FILE' X/* X * X * H A N D S T R . C - character string manipulation functions for hand X * X */ X X/* X * Copyright (C) 1992 Konrad Schroder. X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#include "hand.h" /* needed here for ifdef's below */ X#if HAVE_STRING_H X# include X#else X# include X#endif X#include X#include X Xint noctrl(s) X char *s; /* remove all control characters from s */ X{ X int i,j=0; X X for(i=0;s[i]!='\0';i++) X { X if((isprint(s[i])||s[i]=='\n')&& s[i]!='\r') X { X s[j]=s[i]; X j++; X } X } X s[j]='\0'; X return j; X} X Xint is_blank_str(s) X char *s; /* returns 1 if s is totally blank, 0 otherwise. */ X{ X while(*s ==' ' || *s == '\t' || *s == '\r' || *s == '\n') X s++; X return (*s=='\0'); X} X X/* X * nonewlines() removes newlines from its argument and replaces tabs with X * (single) spaces. X */ X Xint nonewlines(s) X char *s; X{ X int i,j=0; X X for(i=0;s[i]!='\0';i++) X { X if(isprint(s[i]) && s[i]!='\n' && s[i]!='\t') X { X s[j]=s[i]; X j++; X } X else if(s[i]=='\t') X { X s[j]=' '; X j++; X } X } X s[j]='\0'; X return j; X} X X/* X * incasestr(s,t,n) returns the index of the last occurrence of string t in X * string s after index n; it is case-insensitive. X */ X Xint incasestr(s, t, n) X char *s; X char *t; X int n; X{ X int i,j,k,sl,tl; X X if( (tl=strlen(t)) > (sl=strlen(s)) ) X return -1; X if( (tl>sl) && strcasecmp(s,t) ) X { X return -1; X } X k = -1; X for( i=sl; i >= n; i--) X { X for(j=0; ((isupper(s[i+j])?tolower(s[i+j]):s[i+j]) == X (isupper(t[j])?tolower(t[j]):t[j])) X && (t[j] != '\0') X && (s[i+j] != '\0'); j++) X ; X if (t[j] == '\0') X k = i; X } X return k; X} X X#if HAVE_STDC_HEADERS X #define instr(A,B,N) (strstr((A)+(N),(B))-(A)) X#else X Xint instr(s, t, n) X char *s; X char *t; X int n; /* case-sensitive version of incasestr */ X{ X int i,j,k,sl,tl; X X if( (tl=strlen(t)) > (sl=strlen(s)) ) X return -1; X if( (tl>sl) && strcmp(s,t) ) X { X return -1; X } X k = -1; X for(i = sl; i >= n; i--) X { X for(j=0; s[i+j] == t[j] && t[j] != '\0' && s[i+j] != '\0'; j++) X ; X if (t[j] == '\0') X k = i; X } X return k; X} X#endif X Xint lowercase(s) X char *s; /* Self-explanatory. */ X{ X int i,j=0; X X for(i=0; s[i]!='\0'; i++) X { X if(isupper(s[i])) X { X s[i] = tolower(s[i]); X j++; X } X } X return j; X} X X/* X * truecase() converts its argument to all lowercase, except letters that X * appear after non-alphabetic characters, and the first character, which X * are returned uppercase. X */ X Xvoid truecase(s) X char *s; X{ X int i; X X lowercase(s); X if(islower(*s)) X *s = toupper(*s); X for(i=1;*(s+i)!='\0';i++) X if(!isalpha(*(s+i-1))) X if(islower(*(s+i))) X *(s+i) = toupper(*(s+i)); X return; X} X X/* X * endcmp(s,t) returns zero if the tails of t and s are equal, e.g. if t is X * equal to "xyz" and s "abcxyz", or if t is "abcxyz" and s "cxyz", but not X * if t is "axyz" and s "cxyz". It returns greater than zero if the tail X * of s is greater than that of t, less if less. Its comparisons are case- X * insensitive. X */ X Xint endcmp(s, t) X char *s; X char *t; X{ X int i,j,k; X char sji, tki; X X j=strlen(s); X k=strlen(t); X for(i=0; i<=j && i<=k; i++) X { X sji = (isupper(*(s+j-i))?tolower(*(s+j-i)):*(s+j-i)); X tki = (islower(*(t+k-i))?tolower(*(t+k-i)):*(t+k-i)); X if(sji < tki) X return -1; X else if(tki < sji) X return 1; X } X return 0; X} X Xchar *no_tilde(s) X char *s; X{ X char t[ML], *u; X struct passwd *pass; X X if(!strchr(s,'~')) X return s; X X t[0]='\0'; X u=(char *)strtok(s,"/"); X do { X if(!strchr(u,'~')) X { X strcat(t,u); X strcat(t,"/"); X } X else X { X if(u[1]=='\0') X { X strcat(t,(char *)getenv("HOME")); X strcat(t,"/"); X } X else X { X pass = getpwnam(u+1); X if(pass==NULL) X { X strcat(t,"?"); X fprintf(stderr,"hand: getpwnam returned NULL for %s\n", X u); X } X else X strcat(t,pass->pw_dir); X strcat(t,"/"); X } X } X u=(char *)strtok(NULL,"/\n"); X } while(u!=NULL); X t[strlen(t)-1]='\0'; /* kill trailing '/' */ X strcpy(s,t); X return s; X} X X#ifndef HAVE_STRCASECMP X Xint strcasecmp(s, t) Xchar *s, *t; X{ X char cs, ct; X X while(*s && *t) X { X cs=(isalpha(*s)&&isupper(*s)?tolower(*s):*s); X ct=(isalpha(*t)&&isupper(*t)?tolower(*t):*t); X if(cs!=ct) X return cs-ct; X s++; X t++; X } X return *s-*t; X} X X#endif X X#ifndef HAVE_STRNCASECMP Xint strncasecmp(s, t, n) Xchar *s, *t; Xint n; X{ X int i; X char cs, ct; X X for(i=0;i'handstr.h' <<'END_OF_FILE' X/* X * Copyright (C) 1992 Konrad Schroder. X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#ifndef HANDSTR_H_ X#define HANDSTR_H_ X Xint endcmp(); Xint incasestr(); Xint is_blank_str(); X#ifdef ALLOW_PTR_SUB X# define instr(A,B,N) (strstr((A)+(N),(B))-(A)) X#else X int instr(); X#endif Xvoid lowercase(); Xvoid noctrl(); Xvoid nonewlines(); Xvoid truecase(); Xchar *no_tilde(); X X#endif /* !defined HANDSTR_H_ */ END_OF_FILE if test 1067 -ne `wc -c <'handstr.h'`; then echo shar: \"'handstr.h'\" unpacked with wrong size! fi # end of 'handstr.h' fi if test -f 'handtcp.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'handtcp.h'\" else echo shar: Extracting \"'handtcp.h'\" \(954 characters\) sed "s/^X//" >'handtcp.h' <<'END_OF_FILE' X/* X * Copyright (C) 1992 Konrad Schroder. X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#ifndef HANDTCP_H_ X#define HANDTCP_H_ X X#include "hand.h" X Xint finger(); Xstruct hname hostname(); Xstruct User **t_finger(); Xint tcp_open(); Xint w_finger(); X X#endif /* !defined HANDTCP_H_ */ END_OF_FILE if test 954 -ne `wc -c <'handtcp.h'`; then echo shar: \"'handtcp.h'\" unpacked with wrong size! fi # end of 'handtcp.h' fi if test -f 'parse.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'parse.c'\" else echo shar: Extracting \"'parse.c'\" \(10021 characters\) sed "s/^X//" >'parse.c' <<'END_OF_FILE' X/* X * Copyright (C) 1992, 1993 Konrad Schroder. X * X * Hand is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * Hand is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with hand; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#include "hand.h" /* needed here for ifdef's below */ X#include X#if HAVE_STRING_H X# include X#else X# include X#endif X#include X#include X#include "handstr.h" X#define OUTSZ 64 X Xextern int mypid; Xextern char *tmpdir, *sys_errlist[]; Xextern struct Option option; X Xstatic int sUcasecmp(p1, p2) X void *p1; X void *p2; X{ X struct User *q1, *q2; X X q1= *(void **)p1; q2= *(void **)p2; X return strcasecmp(q1->name, q2->name); X} X Xint ctoi(c) X char c; /* returns 9 from '9', 1 from '1', etc. in a portable way */ X{ X#ifndef STUPID X return c-'0'; X#else X switch(c) X { X case '1': X return 1; X case '2': X return 2; X case '3': X return 3; X case '4': X return 4; X case '5': X return 5; X case '6': X return 6; X case '7': X return 7; X case '8': X return 8; X case '9': X return 9; X case '0': X return 0; X default: /* not a digit at all */ X return -1; X } X#endif X} X X/* X * g_col(template_string, n) returns the last column beginning < n if X * sgn is zero, or <= n if sgn != 0. X */ X Xunsigned int g_col(s, n, sgn) X char *s; X int n; X int sgn; X{ X if(n<0) X return n; X X if(sgn==0) X { X if(n>0 && s[n]==' ') X n--; X } X while(n>0 && s[n]!=' ') X n--; X return (n ? n+1 : 0); X} X X/* X * Given a list of lines, determine where columns are based on where spaces X * are. X */ X Xchar *find_columns(line, size) X char **line; X int size; X{ X static char *ret_val; X int i, j; X X ret_val = (char *)malloc(size * sizeof(char)); X memset(ret_val, ' ', size); X X for(i=0;line[i]!=NULL;i++) X { X for(j=0;line[i][j]!='\0';j++) X { X if(line[i][j]!=' ') X if( ++ret_val[j] > 126 ) X ret_val[j]=126; X } X } X X for(j=0;ret_val[j+1]!='\0';j++) X if(ret_val[j]==' ' && ret_val[j+1]==' ') X ret_val[j]='~'; X X return ret_val; X} X X/* X * parse(&infile) reads raw finger output from infile, parses it, and X * returns the parsed lines, in the form of a struct User *. X */ Xstruct User **parse(infile) X struct File *infile; X{ X int i, j, k, n=0, flags; X int user_pos, subsys_pos, idle_pos, when_pos, tty_pos, host_pos; X int linec=0; X char s[ML], *st, *templ_line, **line; X struct User **user; X int idle; X X if((infile->fp = fopen(infile->name,"r"))==NULL) X { X errout("parse",sys_errlist[errno],infile->name); X fclose(infile->fp); X unlink(infile->name); X return NULL; X } X while((st=fgets(s,ML,infile->fp))!=NULL) /* read off preheader */ X { X if(incasestr(s,"login",0)>=0 || incasestr(s,"user",0)>=0) X { X if(!(incasestr(s,"Terminal",0)<0 && incasestr(s,"idle",0)<0)) X break; X } X } X X if(st==NULL) X { X fclose(infile->fp); X unlink(infile->name); X return NULL; /* there weren't any people! */ X } X X /* count up users and allocate memory */ X while(fgets(s,ML,infile->fp)!=NULL && !is_blank_str(s)) X linec++; X user=(struct User **)malloc((linec+1)*sizeof(struct User *)); X line=(char **)malloc((linec+1)*sizeof(char *)); X for(i=0;i<=linec;i++) X { X user[i]=(struct User *)malloc(sizeof(struct User)); X line[i]=(char *)malloc(ML*sizeof(char)); X } X line[linec]=NULL; X if(option.verbose>1) X printf("%d - %d users\n",mypid,linec); X rewind(infile->fp); X while((st=fgets(s,ML,infile->fp))!=NULL) /* read off preheader again */ X { X i=0; X if(incasestr(s,"login",0)>=0 || incasestr(s,"user",0)>=0) X { X if(!(incasestr(s,"Terminal",0)<0 && incasestr(s,"idle",0)<0)) X break; X } X } X for(i=0;ifp); X } X fclose(infile->fp); X unlink(infile->name); X X line[linec]=NULL; X templ_line = find_columns(line, ML); X X /* get column values here */ X X user_pos = incasestr(s,"login",0); X if(user_pos<0) X user_pos = incasestr(s,"user",0); X user_pos=g_col(templ_line,user_pos,0); X X when_pos = incasestr(s,"when",0); X when_pos=g_col(templ_line,when_pos,0); X X subsys_pos= g_col(templ_line,incasestr(s,"subsys",0),0); X idle_pos = g_col(templ_line,incasestr(s,"idle",0),1); X tty_pos = g_col(templ_line,incasestr(s,"tty",0)+1,0); X host_pos = g_col(templ_line,incasestr(s,"host",0),0); X X if(option.verbose>1) X printf("%d Got template string:\n%75.75s\n",mypid,templ_line); X X flags = (idle_pos>0 ? HF_IDLE : 0) X + (when_pos>0 ? HF_WHEN : 0) X + (subsys_pos>0 ? HF_WHAT : 0) X + (tty_pos>0 ? HF_TTY : 0) X + (host_pos>0 ? HF_HOST : 0); X X if(option.verbose>1) X fprintf(stderr,"%d flags: %s, %s, %s, %s, %s\n", mypid, X flags&HF_IDLE? "HF_IDLE" : "", X flags&HF_WHEN? "HF_WHEN" : "", X flags&HF_WHAT? "HF_WHAT" : "", X flags&HF_TTY? "HF_TTY" : "", X flags&HF_HOST? "HF_HOST" : "" ); X X for(n=0;line[n]!=NULL && !is_blank_str(line[n]); n++) X { X if(option.verbose>2) X printf("%d - %s\n",mypid,line[n]); X if(n>linec) X { X printf("This is impossible!\n"); X break; X } X X k=0; X /* username field */ X j=user_pos; X while(line[n][j] && !isspace(line[n][j]) && k < NMAX) X { X user[n]->name[k++] = line[n][j++]; X } X user[n]->name[k]='\0'; X X X /* TTY field */ X k=0; X if((j=tty_pos)>0) X { X while(line[n][j]==' ') /* not everyone has their mesg n */ X j++; X while(line[n][j] && !isspace(line[n][j])) X user[n]->tty[k++]=line[n][j++]; X } X user[n]->tty[k]='\0'; X X /* Host field */ X k=0; X if((j=host_pos)>0) X { X while(line[n][j]==' ') X j++; X while(line[n][j] && !isspace(line[n][j])) X user[n]->host[k++]=line[n][j++]; X } X user[n]->host[k]='\0'; X X /* idle field */ X X idle=0; X if((j=idle_pos)>0) X { X if(templ_line[j]==' ') X j++; X while(line[n][j]==' ' && templ_line[j]!=' ') X j++; X if(templ_line[j]!='\0' && templ_line[j]!=' ') X { X while(!isspace(templ_line[j])) X { X if(line[n][j]=='m' || line[n][j]=='M' X || line[n][j]==' ') X ; X else if(isdigit(line[n][j])) X idle = idle*10+ctoi(line[n][j]); X else if(line[n][j]=='h' || line[n][j]=='H' X || line[n][j]==':') X { X idle *= 60; X break; X } X else if(line[n][j]=='d' || line[n][j]=='D') X { X idle *= (60*24); /* minutes per day */ X break; X } X else if(line[n][j]=='w' || line[n][j]=='W') X { X idle *= (60*24*7); /* minutes per week */ X break; X } X else X break; X j++; X } X } X } X user[n]->idle=idle; X X /* when field */ X X k=0; X if((j=when_pos)>0) X { X /* copy two words (e.g. "Fri 15:32") */ X while(line[n][j] && !isspace(line[n][j])) X user[n]->when[k++]=line[n][j++]; X while(isspace(line[n][j])) X user[n]->when[k++]=line[n][j++]; X while(line[n][j] && !isspace(line[n][j])) X user[n]->when[k++]=line[n][j++]; X } X user[n]->when[k]='\0'; X X X /* what field */ X X k=0; X if((j=subsys_pos)>0) X { X while(line[n][j] && !isspace(line[n][j])) X user[n]->what[k++]=line[n][j++]; X if(j==subsys_pos) X user[n]->what[k++]=' '; X } X user[n]->what[k]='\0'; X user[n]->flags=flags; X } X X for(i=0;iname[0]='|'; X user[linec]->name[1]='\0'; X return user; X} END_OF_FILE if test 10021 -ne `wc -c <'parse.c'`; then echo shar: \"'parse.c'\" unpacked with wrong size! fi # end of 'parse.c' fi if test -f 'parse.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'parse.h'\" else echo shar: Extracting \"'parse.h'\" \(843 characters\) sed "s/^X//" >'parse.h' <<'END_OF_FILE' X/* X * Copyright (C) 1992 Konrad Schroder. X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 1, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program; if not, write to the Free Software X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X */ X X#ifndef _PARSE_H_ X#define _PARSE_H_ X X#include "hand.h" X Xstruct User **parse(); X X#endif END_OF_FILE if test 843 -ne `wc -c <'parse.h'`; then echo shar: \"'parse.h'\" unpacked with wrong size! fi # end of 'parse.h' fi if test -f 'wrist.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'wrist.1'\" else echo shar: Extracting \"'wrist.1'\" \(1578 characters\) sed "s/^X//" >'wrist.1' <<'END_OF_FILE' X.TH wrist 1 X.SH Name Xwrist \- hand add-on hack X.SH Synopsis X.B wrist [\-a \fIhoriz\fBx\fIvert\fB] X.B [\-s \fIsize\fB] [\-o \fIvert-offset\fB] X.SH Description X.NXR "wrist command" X.NXR "associates" "reporting" X.NXR "hand" "X" X.B Wrist Xtakes the output of \fBhand --list --watch\fR and passes its results to X\fBxv\fR to display on an X-terminal. Specifically, wrist looks first Xfor ~user/.face.* (where * is one of tiff, gif, xbm), then for X~/lib/hand/bitmaps/user.*, then for ~/lib/hand/bitmaps/nobody.*, and Xdisplays the first match it finds. X X.PP XThe following options are interpreted by \fBwrist\fR. X.TP X\-a, \-\-arrangement XExpects an argument of the form \fIvert\fRx\fIhoriz\fR, which will be Xthe dimension of the array as displayed on the screen. The default is X6x8. X.TP X\-o, \-\-offset XExpects a numeric argument, which will be the number of pixels to insert Xbetween rows (but not columns) of faces to accommodate window managers' Xtitle bars. The default is 0. X.TP X\-s, \-\-size XThe size of the individual faces, in pixels. The default is 100. X X.SH Bugs X XYou must have xv 3.00 (or higher) in your path or nothing will happen. X XWrist should display the hosts that the user is logged into, as well as Xthe username. X XThere should be a better way of getting a person's face than keeping a Xhoard of them (especially for off-site users). Perhaps a multimedia X.plan could be implemented in a release version. X XXV should not be necessary. X X.SH Author XKonrad Schroder X.SH Files X.br X\fI~/lib/hand/bitmaps/user.???, ~user/.face.???\fR user's face X.SH See Also Xhand(1) END_OF_FILE if test 1578 -ne `wc -c <'wrist.1'`; then echo shar: \"'wrist.1'\" unpacked with wrong size! fi # end of 'wrist.1' fi if test -f 'wrist.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'wrist.c'\" else echo shar: Extracting \"'wrist.c'\" \(7419 characters\) sed "s/^X//" >'wrist.c' <<'END_OF_FILE' X#include X#include X#include X#include X#include X#include X#include "getopt.h" X X#define ML 1024 X Xstruct user_host { X char user[ML]; X char host[ML]; X struct user_host *next; X}; X Xstruct face { X char user[ML]; X int occupied; X}; X Xstruct Option { X unsigned int size; X unsigned int hsize; X unsigned int vsize; X unsigned int v_offset; X}; X Xstruct Option option; Xstruct user_host head; Xstruct face **faces; Xchar *home; Xchar *valid_terms[] = { X "tiff", X "xbm", X "gif", X "" X }; X Xstruct g_option long_option_array[] = { X {"size", 0, NULL, 's'}, X {"arangement", 0, NULL, 'a'}, X {"offset", 0, NULL, 'o'} X}; X Xvoid lowercase(s) X char *s; X{ X while(*s) X { X if(isupper(*s)) X *s=tolower(*s); X s++; X } X return; X} X Xvoid test_my_tty() X{ X struct stat ttyst; X X stat(ttyname(1),&ttyst); X if(ttyst.st_uid != getuid()) /* we don't own the tty */ X { X exit(1); X } X} X Xint delete_face(user) X char *user; X{ X int i, j; X X for(i=0;ipw_dir; X for(i=0;valid_terms[i][0]!='\0';i++) X { X sprintf(ret_val,"%s/.face.%s", X hishome, valid_terms[i]); X if(access(ret_val,0)==0) X { X found=1; X break; X } X } X } X if(!found) X { X for(i=0;valid_terms[i][0]!='\0';i++) X { X sprintf(ret_val,"%s/lib/hand/bitmaps/%s.%s",home,userathost,valid_terms[i]); X if(access(ret_val,0)==0) X { X found=1; X break; X } X } X } X if(!found) X ret_val[0]='\0'; X return ret_val; X} X Xint display_face(user, host) X char *user; X char *host; X{ X char s[ML]; X char bitmap[ML], geoms[ML]; X int xpos, ypos; X int i, found, pid; X X if(strcpy(bitmap,find_user_face(user,host)),bitmap[0]=='\0') X strcpy(bitmap,find_user_face(user,"")); X X /* no image to find, use generic "nobody" image */ X X if(bitmap[0]=='\0') X { X found=0; X for(i=0;valid_terms[i][0]!='\0';i++) X { X sprintf(bitmap,"%s/lib/hand/bitmaps/nobody.%s", X home,valid_terms[i]); X if(access(bitmap,0)==0) X { X found=1; X break; X } X } X if(!found) X bitmap[0]='\0'; X } X X /* finally give up on searching for an image */ X if(!bitmap[0]) X return 0; X X /* now we've got an image, find a hole to display it in */ X X for(xpos=0;xposnext) X if(strcmp(user,cur->user)==0) X return 1; X return 0; X} X Xvoid add_user(user, host) X char *user; X char *host; X{ X struct user_host *cur, *prev; X X if(search_user(user)==0) X display_face(user,host); X X for(cur=head.next,prev=&head;cur!=NULL;prev=cur,cur=cur->next) X if(strcmp(user,cur->user)==0 X && strcmp(host, cur->host)==0) X return; X X prev->next=(struct user_host*)malloc(sizeof(struct user_host)); X cur=prev->next; X strcpy(cur->user,user); X strcpy(cur->host,host); X cur->next=NULL; X X return; X} X Xvoid del_user(user, host) X char *user; X char *host; X{ X struct user_host *cur, *prev; X X for(cur=head.next,prev=&head;cur!=NULL;prev=cur,cur=cur->next) X if(strcmp(user,cur->user)==0 X && strcmp(host, cur->host)==0) X { X prev->next=cur->next; X free(cur); X } X X if(search_user(user)==0) X delete_face(user); X X return; X} X Xint main(argc, argv) X int argc; X char **argv; X{ X int i,j,k,g_opt_index; X char s[ML]; X char c, *u, *h; X X if(getenv("DISPLAY")==NULL) X { X printf("I think you want to set your DISPLAY variable first.\n"); X exit(0); X } X X head.next=NULL; X home = getenv("HOME"); X X option.hsize=8; X option.vsize=6; X option.size=100; X option.v_offset=20; X X while((c=getopt_long(argc, argv, "a:o:s:", long_option_array, X &g_opt_index))!=EOF) X { X switch(c) X { X case 0: X break; X case 'a': /* array size, vertical x horizontal */ X sscanf(optarg,"%dx%d",&option.vsize,&option.hsize); X if(option.hsize<1 || option.vsize<1) X { X fprintf(stderr,"bad array size.\n"); X exit(-1); X } X break; X case 'o': X sscanf(optarg,"%d",&option.v_offset); X break; X case 's': /* individual size */ X sscanf(optarg,"%d",&option.size); X if(option.size<5) X { X fprintf(stderr,"too small.\n"); X exit(-1); X } X break; X default: X fprintf(stderr,"unknown option letter: %c\n",c); X exit(-1); X } X } X X faces = (struct face **)malloc(option.hsize*sizeof(struct face *)); X for(i=0;i