diff options
author | KatolaZ <katolaz@freaknet.org> | 2019-02-08 05:13:11 +0000 |
---|---|---|
committer | KatolaZ <katolaz@freaknet.org> | 2019-02-08 05:13:11 +0000 |
commit | 172540a4a29fa4c0c5f0431bb5bf5b3d08ec92c0 (patch) | |
tree | ac15b0b8ae60a42ffe04b3fd37cf2fbc97b2ddd6 /finger |
New upstream version 0.17upstream
Diffstat (limited to 'finger')
-rw-r--r-- | finger/.cvsignore | 1 | ||||
-rw-r--r-- | finger/Makefile | 18 | ||||
-rw-r--r-- | finger/display.c | 179 | ||||
-rw-r--r-- | finger/finger.1 | 194 | ||||
-rw-r--r-- | finger/finger.c | 334 | ||||
-rw-r--r-- | finger/finger.h | 119 | ||||
-rw-r--r-- | finger/lprint.c | 361 | ||||
-rw-r--r-- | finger/net.c | 155 | ||||
-rw-r--r-- | finger/sprint.c | 172 | ||||
-rw-r--r-- | finger/util.c | 418 |
10 files changed, 1951 insertions, 0 deletions
diff --git a/finger/.cvsignore b/finger/.cvsignore new file mode 100644 index 0000000..f9a4475 --- /dev/null +++ b/finger/.cvsignore @@ -0,0 +1 @@ +finger diff --git a/finger/Makefile b/finger/Makefile new file mode 100644 index 0000000..bec7322 --- /dev/null +++ b/finger/Makefile @@ -0,0 +1,18 @@ +all: finger + +include ../MCONFIG +include ../MRULES + +finger: finger.o lprint.o net.o sprint.o util.o display.o + $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ + +finger.o lprint.o net.o sprint.o util.o display.o: finger.h +finger.o: ../version.h + +install: finger + install -s -m$(BINMODE) finger $(INSTALLROOT)$(BINDIR) + install -m$(MANMODE) finger.1 $(INSTALLROOT)$(MANDIR)/man1 + +clean: + rm -f *.o finger + diff --git a/finger/display.c b/finger/display.c new file mode 100644 index 0000000..dd33c43 --- /dev/null +++ b/finger/display.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <termios.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include "finger.h" + +int +getscreenwidth(void) +{ + +#if defined(TIOCGWINSZ) + struct winsize ws; + if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 || ws.ws_col==0) { + return 80; + } + return ws.ws_col; + +#elif defined(TIOCGSIZE) + struct ttysize ts; + if (ioctl(STDIN_FILENO, TIOCGSIZE, &ts) < 0 || ts.ts_cols==0) { + return 80; + } + return ts.ts_cols; + +#else + const char *e = getenv("COLUMNS"); + int col = e ? atoi(e) : 0; + if (col==0) col = 80; + return col; +#endif +} + +int +is8bit(void) +{ + static int cache=-1; + struct termios tios; + if (cache>=0) return cache; + + if (tcgetattr(STDIN_FILENO, &tios)<0) { + /* assume 8-bit; it's 1999 now, not 1972 */ + cache = 1; + } + else { + cache = (tios.c_cflag & CSIZE)==CS8; + } + return cache; +} + +/************/ + +static int send_crs=0; + +void +set_crmode(void) +{ + send_crs = 1; +} + +static +void +fxputc(FILE *f, int ch) +{ + /* drop any sign */ + ch = ch&0xff; + + /* on 7-bit terminals, strip high bit */ + if (!is8bit()) ch &= 0x7f; + + /* + * Assume anything that isn't a control character is printable. + * We can't count on locale stuff to tell us what's printable + * because we might be looking at someone who uses different + * locale settings or is on the other side of the planet. So, + * strip 0-31, 127, 128-159, and 255. Note that not stripping + * 128-159 is asking for trouble, as 155 (M-esc) is interpreted + * as esc-[ by most terminals. Hopefully this won't break anyone's + * charset. + * + * It would be nice if we could set the terminal to display in the + * right charset, but we have no way to know what it is. feh. + */ + + if (((ch&0x7f) >= 32 && (ch&0x7f) != 0x7f) || ch=='\t') { + putc(ch, f); + return; + } + + if (ch=='\n') { + if (send_crs) putc('\r', f); + putc('\n', f); + return; + } + + if (ch&0x80) { + putc('M', f); + putc('-', f); + ch &= 0x7f; + } + + putc('^', f); + if (ch==0x7f) putc('?', f); + else putc(ch+'@', f); +} + +void +xputc(int ch) +{ + fxputc(stdout, ch); +} + +static void fxputs(FILE *f, const char *buf) { + int i; + for (i=0; buf[i]; i++) fxputc(f, buf[i]); +} + +int xprintf(const char *fmt, ...) { + char buf[1024]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + fxputs(stdout, buf); + + return strlen(buf); +} + +int eprintf(const char *fmt, ...) { + char buf[1024]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + fxputs(stderr, buf); + + return strlen(buf); +} diff --git a/finger/finger.1 b/finger/finger.1 new file mode 100644 index 0000000..553af04 --- /dev/null +++ b/finger/finger.1 @@ -0,0 +1,194 @@ +.\" Copyright (c) 1989, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)finger.1 6.14 (Berkeley) 7/27/91 +.\" $Id: finger.1,v 1.18 2000/07/30 23:56:57 dholland Exp $ +.\" +.Dd August 15, 1999 +.Dt FINGER 1 +.Os "Linux NetKit (0.17)" +.Sh NAME +.Nm finger +.Nd user information lookup program +.Sh SYNOPSIS +.Nm finger +.Op Fl lmsp +.Op Ar user ... +.Op Ar user@host ... +.Sh DESCRIPTION +The +.Nm finger +displays information about the system users. +.Pp +Options are: +.Bl -tag -width flag +.It Fl s +.Nm Finger +displays the user's login name, real name, terminal name and write +status (as a ``*'' after the terminal name if write permission is +denied), idle time, login time, office location and office phone +number. +.Pp +Login time is displayed as month, day, hours and minutes, unless +more than six months ago, in which case the year is displayed rather +than the hours and minutes. +.Pp +Unknown devices as well as nonexistent idle and login times are +displayed as single asterisks. +.Pp +.It Fl l +Produces a multi-line format displaying all of the information +described for the +.Fl s +option as well as the user's home directory, home phone number, login +shell, mail status, and the contents of the files +.Dq Pa .plan , +.Dq Pa .project , +.Dq Pa .pgpkey +and +.Dq Pa .forward +from the user's home directory. +.Pp +Phone numbers specified as eleven digits are printed as ``+N-NNN-NNN-NNNN''. +Numbers specified as ten or seven digits are printed as the appropriate +subset of that string. +Numbers specified as five digits are printed as ``xN-NNNN''. +Numbers specified as four digits are printed as ``xNNNN''. +.Pp +If write permission is denied to the device, the phrase ``(messages off)'' +is appended to the line containing the device name. +One entry per user is displayed with the +.Fl l +option; if a user is logged on multiple times, terminal information +is repeated once per login. +.Pp +Mail status is shown as ``No Mail.'' if there is no mail at all, +``Mail last read DDD MMM ## HH:MM YYYY (TZ)'' if the person has looked +at their mailbox since new mail arriving, or ``New mail received ...'', +`` Unread since ...'' if they have new mail. +.Pp +.It Fl p +Prevents +the +.Fl l +option of +.Nm finger +from displaying the contents of the +.Dq Pa .plan , +.Dq Pa .project +and +.Dq Pa .pgpkey +files. +.It Fl m +Prevent matching of +.Ar user +names. +.Ar User +is usually a login name; however, matching will also be done on the +users' real names, unless the +.Fl m +option is supplied. +All name matching performed by +.Nm finger +is case insensitive. +.El +.Pp +If no options are specified, +.Nm finger +defaults to the +.Fl l +style output if operands are provided, otherwise to the +.Fl s +style. +Note that some fields may be missing, in either format, if information +is not available for them. +.Pp +If no arguments are specified, +.Nm finger +will print an entry for each user currently logged into the system. +.Pp +.Nm Finger +may be used to look up users on a remote machine. +The format is to specify a +.Ar user +as +.Dq Li user@host , +or +.Dq Li @host , +where the default output +format for the former is the +.Fl l +style, and the default output format for the latter is the +.Fl s +style. +The +.Fl l +option is the only option that may be passed to a remote machine. +.Pp +If standard output is a socket, +.Nm finger +will emit a carriage return (^M) before every linefeed (^J). This is +for processing remote finger requests when invoked by +.Xr fingerd 8 . +.Sh FILES +.Bl -tag -width mmmmmmmmmmmmmmm +.It Pa ~/.nofinger +If finger finds this file in a user's home directory, it will, for +finger requests originating outside the local host, firmly deny the +existence of that user. For this to work, the finger program, as +started by +.Xr fingerd 8 , +must be able to see the +.Pa .nofinger +file. This generally means that the home directory containing the file +must have the other-users-execute bit set (o+w). See +.Xr chmod 1 . +If you use this feature for privacy, please test it with ``finger +@localhost'' before relying on it, just in case. +.It ~/.plan +.It ~/.project +.It ~/.pgp +These files are printed as part of a long-format request. The +.Pa .project +file is limited to one line; the +.Pa .plan +file may be arbitrarily long. +.El +.Sh SEE ALSO +.Xr chfn 1 , +.Xr passwd 1 , +.Xr w 1 , +.Xr who 1 +.Sh HISTORY +The +.Nm finger +command appeared in +.Bx 3.0 . diff --git a/finger/finger.c b/finger/finger.c new file mode 100644 index 0000000..94c3ec0 --- /dev/null +++ b/finger/finger.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Mail status reporting added 931007 by Luke Mewburn, <zak@rmit.edu.au>. + */ + +char copyright[] = + "@(#) Copyright (c) 1989 The Regents of the University of California.\n" + "All rights reserved.\n"; + +/* + * from: @(#)finger.c 5.22 (Berkeley) 6/29/90 + */ +char finger_rcsid[] = \ + "$Id: finger.c,v 1.15 1999/12/18 16:41:51 dholland Exp $"; + +/* + * Finger prints out information about users. It is not portable since + * certain fields (e.g. the full user name, office, and phone numbers) are + * extracted from the gecos field of the passwd file which other UNIXes + * may not have or may use for other things. (This is not really true any + * more, btw.) + * + * There are currently two output formats; the short format is one line + * per user and displays login name, tty, login time, real name, idle time, + * and office location/phone number. The long format gives the same + * information (in a more legible format) as well as home directory, shell, + * mail info, and .plan/.project files. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <time.h> +#include <getopt.h> +#include "finger.h" +#include "../version.h" + +static void loginlist(void); +static void userlist(int argc, char *argv[]); + +int lflag, pplan; +static int sflag, mflag; +static int enable_nofinger; + +time_t now; +char tbuf[TBUFLEN]; + +PERSON *phead, *ptail; /* the linked list of all people */ +int entries; /* number of people */ + + +int main(int argc, char *argv[]) { + int ch; + struct sockaddr_in sin; + socklen_t slen = sizeof(sin); + + while ((ch = getopt(argc, argv, "lmps")) != EOF) { + switch(ch) { + case 'l': + lflag = 1; /* long format */ + break; + case 'm': + mflag = 1; /* do exact match of names */ + break; + case 'p': + pplan = 1; /* don't show .plan/.project */ + break; + case 's': + sflag = 1; /* short format */ + break; + case '?': + case 'h': + default: + eprintf("usage: finger [-lmps] [login ...]\n"); + return 1; + } + } + argc -= optind; + argv += optind; + + if (getsockname(STDOUT_FILENO, (struct sockaddr *)&sin, &slen)==0) { + /* + * stdout is a socket. must be a network finger request, + * so emit CRs with our LFs at the ends of lines. + */ + set_crmode(); + + /* + * Also, enable .nofinger processing. + */ + enable_nofinger = 1; + } + + /* + * Also check stdin for nofinger processing, because of older + * fingerds that make stdout a pipe for CRLF handling. + */ + if (getsockname(STDIN_FILENO, (struct sockaddr *)&sin, &slen)==0) { + enable_nofinger = 1; + } + + time(&now); + + setpwent(); + + if (!*argv) { + /* + * Assign explicit "small" format if no names given and -l + * not selected. Force the -s BEFORE we get names so proper + * screening will be done. + */ + if (!lflag) { + sflag = 1; /* if -l not explicit, force -s */ + } + loginlist(); + if (entries == 0) { + xprintf("No one logged on.\n"); + } + } + else { + userlist(argc, argv); + /* + * Assign explicit "large" format if names given and -s not + * explicitly stated. Force the -l AFTER we get names so any + * remote finger attempts specified won't be mishandled. + */ + if (!sflag) + lflag = 1; /* if -s not explicit, force -l */ + } + if (entries != 0) { + if (lflag) lflag_print(); + else sflag_print(); + } + return 0; +} + +/* Returns 1 if .nofinger is found and enable_nofinger is set. */ +static +int +check_nofinger(struct passwd *pw) +{ + if (enable_nofinger) { + char path[PATH_MAX]; + struct stat tripe; + snprintf(path, sizeof(path), "%s/.nofinger", pw->pw_dir); + if (stat(path, &tripe)==0) { + return 1; + } + } + return 0; +} + +static void +loginlist(void) +{ + PERSON *pn; + struct passwd *pw; + struct utmp *uptr; + char name[UT_NAMESIZE + 1]; + + name[UT_NAMESIZE] = '\0'; + + /* + * if (!freopen(_PATH_UTMP, "r", stdin)) { + * fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); + * exit(2); + * } + */ + setutent(); + while ((uptr = getutent())!=NULL) { + if (!uptr->ut_name[0]) + continue; +#ifdef USER_PROCESS + if (uptr->ut_type != USER_PROCESS) continue; +#endif + if ((pn = find_person(uptr->ut_name)) == NULL) { + memcpy(name, uptr->ut_name, UT_NAMESIZE); + if ((pw = getpwnam(name)) == NULL) + continue; + if (check_nofinger(pw)) + continue; + pn = enter_person(pw); + } + enter_where(uptr, pn); + } + for (pn = phead; lflag && pn != NULL; pn = pn->next) + enter_lastlog(pn); + endutent(); +} + + +static void do_local(int argc, char *argv[], int *used) { + int i; + struct passwd *pw; + + /* + * traverse the list of possible login names and check the login name + * and real name against the name specified by the user. + */ + if (mflag) { + for (i = 0; i < argc; i++) + if (used[i] >= 0 && (pw = getpwnam(argv[i]))) { + if (!check_nofinger(pw)) { + enter_person(pw); + used[i] = 1; + } + } + } else for (pw = getpwent(); pw; pw = getpwent()) + for (i = 0; i < argc; i++) + if (used[i] >= 0 && + (!strcasecmp(pw->pw_name, argv[i]) || + match(pw, argv[i]))) { + if (!check_nofinger(pw)) { + enter_person(pw); + used[i] = 1; + } + } + + /* list errors */ + for (i = 0; i < argc; i++) + if (!used[i]) + (void)eprintf("finger: %s: no such user.\n", argv[i]); + +} + +static void +userlist(int argc, char *argv[]) +{ + int i; + PERSON *pn; + PERSON *nethead, **nettail; + struct utmp *uptr; + int dolocal, *used; + + used = calloc(argc, sizeof(int)); + if (!used) { + eprintf("finger: out of space.\n"); + exit(1); + } + + /* pull out all network requests */ + for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) { + if (!strchr(argv[i], '@')) { + dolocal = 1; + continue; + } + pn = palloc(); + *nettail = pn; + nettail = &pn->next; + pn->name = argv[i]; + used[i] = -1; + } + *nettail = NULL; + + if (dolocal) do_local(argc, argv, used); + + /* handle network requests */ + for (pn = nethead; pn; pn = pn->next) { + netfinger(pn->name); + if (pn->next || entries) + xputc('\n'); + } + + if (entries == 0) + return; + + /* + * Scan thru the list of users currently logged in, saving + * appropriate data whenever a match occurs. + */ + /* + * if (!freopen(_PATH_UTMP, "r", stdin)) { + * (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP); + * exit(1); + * } + */ + setutent(); + while ((uptr = getutent())!=NULL) { + if (!uptr->ut_name[0]) + continue; +#ifdef USER_PROCESS + if (uptr->ut_type != USER_PROCESS) continue; +#endif + if ((pn = find_person(uptr->ut_name)) == NULL) { + continue; + } + enter_where(uptr, pn); + } + for (pn = phead; pn != NULL; pn = pn->next) { + enter_lastlog(pn); + } + endutent(); +} diff --git a/finger/finger.h b/finger/finger.h new file mode 100644 index 0000000..bad5244 --- /dev/null +++ b/finger/finger.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)finger.h 5.5 (Berkeley) 6/1/90 + * $Id: finger.h,v 1.7 1999/09/14 10:51:11 dholland Exp $ + */ + +#include <pwd.h> +#include <utmp.h> + +/* + * All unique persons are linked in a list headed by "head" and linkd + * by the "next" field, as well as kept in a hash table. + */ + +typedef struct person { + struct person *next; /* link to next person */ + struct person *hlink; /* link to next person in hash bucket */ + uid_t uid; /* user id */ + char *dir; /* user's home directory */ + char *homephone; /* pointer to home phone no. */ + char *name; /* login name */ + char *office; /* pointer to office name */ + char *officephone; /* pointer to office phone no. */ + char *realname; /* pointer to full name */ + char *shell; /* user's shell */ + time_t mailread; /* last time mail was read */ + time_t mailrecv; /* last time mail was read */ + struct where *whead, *wtail; /* list of where he is or has been */ +} PERSON; + +enum status { LASTLOG, LOGGEDIN }; + +typedef struct where { + struct where *next; /* next place he is or has been */ + enum status info; /* type/status of request */ + short writable; /* tty is writable */ + time_t loginat; /* time of (last) login */ + time_t idletime; /* how long idle (if logged in) */ + char tty[UT_LINESIZE+1]; /* null terminated tty line */ + char host[UT_HOSTSIZE+1]; /* null terminated remote host name */ +} WHERE; + +extern PERSON *phead, *ptail; /* the linked list of all people */ + +extern int entries; /* number of people */ + +#define TBUFLEN 1024 +extern char tbuf[TBUFLEN]; /* temp buffer for anybody */ + +extern time_t now; +extern int lflag, pplan; + +PERSON *enter_person(struct passwd *); +PERSON *find_person(const char *name); +PERSON *palloc(void); +WHERE *walloc(PERSON *); +void lflag_print(void); +void sflag_print(void); +void enter_where(struct utmp *ut, PERSON *pn); +void enter_lastlog(PERSON *pn); +int match(struct passwd *pw, const char *user); +void netfinger(const char *name); +const char *prphone(const char *num); + +#ifndef DAYSPERNYEAR +#define DAYSPERNYEAR 365 +#endif + +#ifndef SECSPERDAY +#define SECSPERDAY (60 * 60 * 24) +#endif + +/* turn on crnl translation on output */ +void set_crmode(void); + +/* Display, masking control characters and possibly doing crnl translation */ +void xputc(int ch); +void xputs(const char *buf); +int xprintf(const char *fmt, ...); + +/* Send to stderr, possibly doing crnl translation */ +int eprintf(const char *fmt, ...); + +/* terminal inquiries */ +int is8bit(void); +int getscreenwidth(void); diff --git a/finger/lprint.c b/finger/lprint.c new file mode 100644 index 0000000..8b9069c --- /dev/null +++ b/finger/lprint.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * from: @(#)lprint.c 5.13 (Berkeley) 10/31/90 + */ +char lprint_rcsid[] = + "$Id: lprint.c,v 1.11 1999/09/14 10:51:11 dholland Exp $"; + +#include <stdio.h> +#include <ctype.h> +#include <paths.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/time.h> +#include "finger.h" + +static void lprint(PERSON *pn); +static int demi_print(char *str, int oddfield); +static int show_text(const char *directory, const char *file_name, + const char *header); + +#define LINE_LEN 80 +#define TAB_LEN 8 /* 8 spaces between tabs */ +#define _PATH_FORWARD ".forward" +#define _PATH_PLAN ".plan" +#define _PATH_PROJECT ".project" +#define _PATH_PGPKEY ".pgpkey" + +void +lflag_print(void) +{ + register PERSON *pn = phead; + while (1) { + lprint(pn); + if (!pplan) { + show_text(pn->dir, _PATH_PGPKEY, "PGP key:\n"); + show_text(pn->dir, _PATH_PROJECT, "Project:\n"); + if (!show_text(pn->dir, _PATH_PLAN, "Plan:\n")) { + xprintf("No Plan.\n"); + } + } + if (!(pn = pn->next)) + break; + xputc('\n'); + } +} + +static void +lprint(PERSON *pn) +{ + struct tm *delta, *tp; + WHERE *w; + int cpr, len, maxlen; + int oddfield; + char timebuf[128]; + + /* + * long format -- + * login name + * real name + * home directory + * shell + * office, office phone, home phone if available + */ + xprintf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", + pn->name, pn->realname, pn->dir); + xprintf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); + + /* + * try and print office, office phone, and home phone on one line; + * if that fails, do line filling so it looks nice. + */ +#define OFFICE_TAG "Office" +#define OFFICE_PHONE_TAG "Office Phone" + oddfield = 0; + if (pn->office && pn->officephone && + strlen(pn->office) + strlen(pn->officephone) + + sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) + { + snprintf(tbuf, TBUFLEN, "%s: %s, %s", OFFICE_TAG, pn->office, + prphone(pn->officephone)); + oddfield = demi_print(tbuf, oddfield); + } + else { + if (pn->office) { + snprintf(tbuf, TBUFLEN, "%s: %s", OFFICE_TAG, + pn->office); + oddfield = demi_print(tbuf, oddfield); + } + if (pn->officephone) { + snprintf(tbuf, TBUFLEN, "%s: %s", OFFICE_PHONE_TAG, + prphone(pn->officephone)); + oddfield = demi_print(tbuf, oddfield); + } + } + if (pn->homephone) { + snprintf(tbuf, TBUFLEN, "%s: %s", "Home Phone", + prphone(pn->homephone)); + oddfield = demi_print(tbuf, oddfield); + } + if (oddfield) xputc('\n'); + + /* + * long format con't: * if logged in + * terminal + * idle time + * if messages allowed + * where logged in from + * if not logged in + * when last logged in + */ + /* find out longest device name for this user for formatting */ + for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) + if ((len = strlen(w->tty)) > maxlen) + maxlen = len; + /* find rest of entries for user */ + for (w = pn->whead; w != NULL; w = w->next) { + switch (w->info) { + case LOGGEDIN: + tp = localtime(&w->loginat); + /* + * t = asctime(tp); + * tzset(); + * tzn = tzname[daylight]; + * cpr = printf("On since %.16s (%s) on %s", + * t, tzn, w->tty); + */ + strftime(timebuf, sizeof(timebuf), + "%a %b %e %R (%Z)", tp); + cpr = xprintf("On since %s on %s", timebuf, w->tty); + if (*w->host) { + cpr += xprintf(" from %s", w->host); + } + /* + * idle time is tough; if have one, print a comma, + * then spaces to pad out the device name, then the + * idle time. Follow with a comma if a remote login. + */ + delta = gmtime(&w->idletime); + if (delta->tm_yday || delta->tm_hour + || delta->tm_min || delta->tm_sec) { + if (*w->host) + xputc('\n'); + cpr += xprintf("%-*s", + (int) (maxlen - strlen(w->tty) + 3), ""); + if (delta->tm_yday > 0) { + cpr += xprintf("%d day%s ", + delta->tm_yday, + delta->tm_yday == 1 ? "" : "s"); + } + if (delta->tm_hour > 0) { + cpr += xprintf("%d hour%s ", + delta->tm_hour, + delta->tm_hour == 1 ? "" : "s"); + } + if ((delta->tm_min > 0) && !delta->tm_yday) { + cpr += xprintf("%d minute%s ", + delta->tm_min, + delta->tm_min == 1 ? "" : "s"); + } + if ((delta->tm_sec > 0) && !delta->tm_yday + && !delta->tm_hour) { + cpr += xprintf("%d second%s ", + delta->tm_sec, + delta->tm_sec == 1 ? "" : "s"); + } + cpr += xprintf("idle"); + } + if (!w->writable) { + if (delta->tm_yday || delta->tm_hour + || delta->tm_min || delta->tm_sec) + cpr += xprintf("\n "); + cpr += xprintf(" (messages off)"); + } + break; + case LASTLOG: + if (w->loginat == 0) { + (void)xprintf("Never logged in."); + break; + } + tp = localtime(&w->loginat); + /* + * t = asctime(tp); + * tzset(); + * tzn = tzname[daylight]; + * if(now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2) + * cpr = + * printf("Last login %.16s %.4s (%s) on %s", + * t, t + 20, tzn, w->tty); + * else + * cpr = printf("Last login %.16s (%s) on %s", + * t, tzn, w->tty); + */ + if (now - w->loginat < SECSPERDAY * DAYSPERNYEAR / 2) { + strftime(timebuf, sizeof(timebuf), + "%a %b %e %R (%Z)", tp); + } + else { + strftime(timebuf, sizeof(timebuf), + "%a %b %e %R %Y (%Z)", tp); + } + cpr = xprintf("Last login %s on %s", timebuf, w->tty); + if (*w->host) { + cpr += xprintf(" from %s", w->host); + } + break; + } + xputc('\n'); + } + + /* If the user forwards mail elsewhere, tell us about it */ + show_text(pn->dir, _PATH_FORWARD, "Mail forwarded to "); + + /* Print the standard mailbox information. */ + if (pn->mailrecv == -1) + xprintf("No mail.\n"); + else if (pn->mailrecv > pn->mailread) { + tp = localtime(&pn->mailrecv); + /* + * t = asctime(tp); + * tzset(); + * tzn = tzname[daylight]; + * printf("New mail received %.16s %.4s (%s)\n", t, + * t + 20, tzn); + */ + strftime(timebuf, sizeof(timebuf), + "%a %b %e %R %Y (%Z)", tp); + xprintf("New mail received %s\n", timebuf); + tp = localtime(&pn->mailread); + /* + * t = asctime(tp); + * tzset(); + * tzn = tzname[daylight]; + * printf(" Unread since %.16s %.4s (%s)\n", t, + * t + 20, tzn); + */ + strftime(timebuf, sizeof(timebuf), + "%a %b %e %R %Y (%Z)", tp); + xprintf(" Unread since %s\n", timebuf); + } else { + tp = localtime(&pn->mailread); + /* + * t = asctime(tp); + * tzset(); + * tzn = tzname[daylight]; + * printf("Mail last read %.16s %.4s (%s)\n", t, + * t + 20, tzn); + */ + strftime(timebuf, sizeof(timebuf), + "%a %b %e %R %Y (%Z)", tp); + xprintf("Mail last read %s\n", timebuf); + } +} + +static int +demi_print(char *str, int oddfield) +{ + static int lenlast; + int lenthis, maxlen; + + lenthis = strlen(str); + if (oddfield) { + /* + * We left off on an odd number of fields. If we haven't + * crossed the midpoint of the screen, and we have room for + * the next field, print it on the same line; otherwise, + * print it on a new line. + * + * Note: we insist on having the right hand fields start + * no less than 5 tabs out. + */ + maxlen = 5 * TAB_LEN; + if (maxlen < lenlast) + maxlen = lenlast; + if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + + lenthis) <= LINE_LEN) { + while(lenlast < (4 * TAB_LEN)) { + xputc('\t'); + lenlast += TAB_LEN; + } + (void)xprintf("\t%s\n", str); /* force one tab */ + } else { + (void)xprintf("\n%s", str); /* go to next line */ + oddfield = !oddfield; /* this'll be undone below */ + } + } else + (void)xprintf("%s", str); + oddfield = !oddfield; /* toggle odd/even marker */ + lenlast = lenthis; + return(oddfield); +} + +static int +show_text(const char *directory, const char *file_name, const char *header) +{ + int ch, lastc = 0, fd; + FILE *fp; + struct stat sbuf1, sbuf2; + + snprintf(tbuf, TBUFLEN, "%s/%s", directory, file_name); + + if (lstat(tbuf, &sbuf1) || !S_ISREG(sbuf1.st_mode)) return 0; + fd = open(tbuf, O_RDONLY); + if (fd<0) return 0; + if (fstat(fd, &sbuf2)) { close(fd); return 0; } + /* if we didn't get the same file both times, bail */ + if (sbuf1.st_dev!=sbuf2.st_dev || sbuf1.st_ino!=sbuf2.st_ino) { + close(fd); + return 0; + } + fp = fdopen(fd, "r"); + if (fp == NULL) { close(fd); return 0; } + + xprintf("%s", header); + while ((ch = getc(fp)) != EOF) { + xputc(ch); + lastc = ch; + } + if (lastc != '\n') xputc('\n'); + + fclose(fp); + return 1; +} + diff --git a/finger/net.c b/finger/net.c new file mode 100644 index 0000000..d6169fa --- /dev/null +++ b/finger/net.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)net.c 5.5 (Berkeley) 6/1/90";*/ +char net_rcsid[] = "$Id: net.c,v 1.9 1999/09/14 10:51:11 dholland Exp $"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> +#include <ctype.h> +#include "finger.h" + +void netfinger(const char *name) { + register FILE *fp; + struct in_addr defaddr; + register int c, sawret, ateol; + struct hostent *hp, def; + struct servent *sp; + struct sockaddr_in sn; + int s; + char *alist[1], *host; + + host = strrchr(name, '@'); + if (!host) return; + *host++ = '\0'; + + memset(&sn, 0, sizeof(sn)); + + sp = getservbyname("finger", "tcp"); + if (!sp) { + eprintf("finger: tcp/finger: unknown service\n"); + return; + } + sn.sin_port = sp->s_port; + + hp = gethostbyname(host); + if (!hp) { + if (!inet_aton(host, &defaddr)) { + eprintf("finger: unknown host: %s\n", host); + return; + } + def.h_name = host; + def.h_addr_list = alist; + def.h_addr = (char *)&defaddr; + def.h_length = sizeof(struct in_addr); + def.h_addrtype = AF_INET; + def.h_aliases = 0; + hp = &def; + } + sn.sin_family = hp->h_addrtype; + if (hp->h_length > (int)sizeof(sn.sin_addr)) { + hp->h_length = sizeof(sn.sin_addr); + } + memcpy(&sn.sin_addr, hp->h_addr, hp->h_length); + + if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { + eprintf("finger: socket: %s\n", strerror(errno)); + return; + } + + /* print hostname before connecting, in case it takes a while */ + xprintf("[%s]\n", hp->h_name); + if (connect(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) { + eprintf("finger: connect: %s\n", strerror(errno)); + close(s); + return; + } + + /* -l flag for remote fingerd */ + if (lflag) write(s, "/W ", 3); + + /* send the name followed by <CR><LF> */ + write(s, name, strlen(name)); + write(s, "\r\n", 2); + + /* + * Read from the remote system; once we're connected, we assume some + * data. If none arrives, we hang until the user interrupts. + * + * If we see a <CR> or a <CR> with the high bit set, treat it as + * a newline; if followed by a newline character, only output one + * newline. + * + * Text is sent to xputc() for printability analysis. + */ + fp = fdopen(s, "r"); + if (!fp) { + eprintf("finger: fdopen: %s\n", strerror(errno)); + close(s); + return; + } + + sawret = 0; + ateol = 1; + while ((c = getc(fp)) != EOF) { + c &= 0xff; + if (c == ('\r'|0x80) || c == ('\n'|0x80)) c &= 0x7f; + if (c == '\r') { + sawret = ateol = 1; + xputc('\n'); + } + else if (sawret && c == '\n') { + sawret = 0; + /* don't print */ + } + else { + if (c == '\n') ateol = 1; + sawret = 0; + xputc(c); + } + } + if (!ateol) xputc('\n'); + fclose(fp); +} diff --git a/finger/sprint.c b/finger/sprint.c new file mode 100644 index 0000000..cc86080 --- /dev/null +++ b/finger/sprint.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)sprint.c 5.8 (Berkeley) 12/4/90";*/ +char sprint_rcsid[] = "$Id: sprint.c,v 1.10 1999/12/12 18:59:33 dholland Exp $"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "finger.h" + +static void stimeprint(WHERE *w); +static int psort(const void *a, const void *b); +static PERSON **sort(void); + +void sflag_print(void) { + register PERSON *pn; + register WHERE *w; + register char *p; + PERSON **list; + int maxlname, maxrname, space, cnt; + + list = sort(); + /* + * short format -- + * login name + * real name + * terminal name + * if terminal writeable (add an '*' to the terminal name + * if not) + * if logged in show idle time and day logged in, else + * show last login date and time. If > 6 moths, + * show year instead of time. + * office location + * office phone + */ + + maxlname = maxrname = sizeof("Login "); + for (cnt = 0; cnt < entries; ++cnt) { + int l; + pn = list[cnt]; + l = pn->name ? strlen(pn->name) : 1; + if (l > maxlname) maxlname = l; + l = pn->realname ? strlen(pn->realname) : 1; + if (l > maxrname) maxrname = l; + } + /* prevent screen overflow */ + space = getscreenwidth() - 50; + if (maxlname + maxrname > space) maxrname = space - maxlname; + + /* add a space if there's room */ + if (maxlname + maxrname < space-2) { maxlname++; maxrname++; } + + (void)xprintf("%-*s %-*s %s\n", maxlname, "Login", maxrname, + "Name", " Tty Idle Login Time Office Office Phone"); + for (cnt = 0; cnt < entries; ++cnt) { + pn = list[cnt]; + for (w = pn->whead; w != NULL; w = w->next) { + (void)xprintf("%-*.*s %-*.*s ", maxlname, maxlname, + pn->name, maxrname, maxrname, + pn->realname ? pn->realname : ""); + if (!w->loginat) { + (void)xprintf(" * * No logins "); + goto office; + } + (void)xputc(w->info == LOGGEDIN && !w->writable ? + '*' : ' '); + if (*w->tty) + (void)xprintf("%-7.7s ", w->tty); + else + (void)xprintf(" "); + if (w->info == LOGGEDIN) { + stimeprint(w); + (void)xprintf(" "); + } else + (void)xprintf(" * "); + p = ctime(&w->loginat); + (void)xprintf("%.6s", p + 4); + if (now - w->loginat >= SECSPERDAY * DAYSPERNYEAR / 2) + (void)xprintf(" %.4s", p + 20); + else + (void)xprintf(" %.5s", p + 11); +office: + if (w->host[0] != '\0') { + xprintf(" (%s)", w->host); + } else { + if (pn->office) + (void)xprintf(" %-10.10s", pn->office); + else if (pn->officephone) + (void)xprintf(" %-10.10s", " "); + if (pn->officephone) + (void)xprintf(" %-.14s", + prphone(pn->officephone)); + } + xputc('\n'); + } + } +} + +static PERSON **sort(void) { + register PERSON *pn, **lp; + PERSON **list; + + if (!(list = (PERSON **)malloc((u_int)(entries * sizeof(PERSON *))))) { + eprintf("finger: Out of space.\n"); + exit(1); + } + for (lp = list, pn = phead; pn != NULL; pn = pn->next) + *lp++ = pn; + (void)qsort(list, entries, sizeof(PERSON *), psort); + return(list); +} + +static int psort(const void *a, const void *b) { + const PERSON *const *p = (const PERSON *const *)a; + const PERSON *const *t = (const PERSON *const *)b; + return(strcmp((*p)->name, (*t)->name)); +} + +static void stimeprint(WHERE *w) { + register struct tm *delta; + + delta = gmtime(&w->idletime); + if (!delta->tm_yday) + if (!delta->tm_hour) + if (!delta->tm_min) + (void)xprintf(" "); + else + (void)xprintf("%5d", delta->tm_min); + else + (void)xprintf("%2d:%02d", + delta->tm_hour, delta->tm_min); + else + (void)xprintf("%4dd", delta->tm_yday); +} diff --git a/finger/util.c b/finger/util.c new file mode 100644 index 0000000..d0498a7 --- /dev/null +++ b/finger/util.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)util.c 5.14 (Berkeley) 1/17/91";*/ +char util_rcsid[] = "$Id: util.c,v 1.18 1999/09/28 22:53:58 netbug Exp $"; +#endif /* not lint */ + +#include <sys/types.h> +/* #include <sys/param.h> <--- unused? */ +#include <sys/stat.h> +#include <sys/file.h> +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <paths.h> +#include <errno.h> +#include <lastlog.h> +#include <unistd.h> +#include <stdlib.h> +#include "finger.h" + +#define HBITS 8 /* number of bits in hash code */ +#define HSIZE (1 << 8) /* hash table size */ +#define HMASK (HSIZE - 1) /* hash code mask */ +static PERSON *htab[HSIZE]; /* the buckets */ + +static int hash(const char *name); + +static void find_idle_and_ttywrite(register WHERE *w) { + struct stat sb; + + /* No device for X console. Utmp entry by XDM login (":0"). */ + if (w->tty[0] == ':') { + w->idletime = 0; /* would be nice to have it emit ??? */ + w->writable = 0; + return; + } + snprintf(tbuf, TBUFLEN, "%s/%s", _PATH_DEV, w->tty); + if (stat(tbuf, &sb) < 0) { + eprintf("finger: %s: %s\n", tbuf, strerror(errno)); + return; + } + w->idletime = now < sb.st_atime ? 0 : now - sb.st_atime; + +#define TALKABLE 0220 /* tty is writable if 220 mode */ + w->writable = ((sb.st_mode & TALKABLE) == TALKABLE); +} + +static void userinfo(PERSON *pn, struct passwd *pw) { + char *p; + struct stat sb; + char *bp; + char *rname; + int i, j, ct; + char *fields[4]; + int nfields; + + pn->uid = pw->pw_uid; + pn->name = strdup(pw->pw_name); + pn->dir = strdup(pw->pw_dir); + pn->shell = strdup(pw->pw_shell); + + /* make a private copy of gecos to munge */ + strncpy(tbuf, pw->pw_gecos, TBUFLEN); + tbuf[TBUFLEN-1] = 0; /* ensure null termination */ + bp = tbuf; + + /* why do we skip asterisks!?!? */ + if (*bp == '*') ++bp; + + /* + * fields[0] -> real name + * fields[1] -> office + * fields[2] -> officephone + * fields[3] -> homephone + */ + nfields = 0; + for (p = strtok(bp, ","); p; p = strtok(NULL, ",")) { + if (*p==0) p = NULL; // skip empties + if (nfields < 4) fields[nfields++] = p; + } + while (nfields<4) fields[nfields++] = NULL; + + if (fields[0]) { + /* + * Ampersands in gecos get replaced by the capitalized login + * name. This is a major nuisance and whoever thought it up + * should be shot. + */ + p = fields[0]; + + /* First, count the number of ampersands. */ + for (ct=i=0; p[i]; i++) if (p[i]=='&') ct++; + + /* This tells us how much space we need to copy the name. */ + rname = malloc(strlen(p) + ct*strlen(pw->pw_name) + 1); + if (!rname) { + eprintf("finger: Out of space.\n"); + exit(1); + } + + /* Now, do it */ + for (i=j=0; p[i]; i++) { + if (p[i]=='&') { + strcpy(rname + j, pw->pw_name); + if (islower(rname[j])) { + rname[j] = toupper(rname[j]); + } + j += strlen(pw->pw_name); + } + else { + rname[j++] = p[i]; + } + } + rname[j] = 0; + + pn->realname = rname; + } + + pn->office = fields[1] ? strdup(fields[1]) : NULL; + pn->officephone = fields[2] ? strdup(fields[2]) : NULL; + pn->homephone = fields[3] ? strdup(fields[3]) : NULL; + + pn->mailrecv = -1; /* -1 == not_valid */ + pn->mailread = -1; /* -1 == not_valid */ + + snprintf(tbuf, TBUFLEN, "%s/%s", _PATH_MAILDIR, pw->pw_name); + if (stat(tbuf, &sb) < 0) { + if (errno != ENOENT) { + eprintf("finger: %s: %s\n", tbuf, strerror(errno)); + return; + } + } + else if (sb.st_size != 0) { + pn->mailrecv = sb.st_mtime; + pn->mailread = sb.st_atime; + } +} + +int +match(struct passwd *pw, const char *user) +{ + char *p; + int i, j, ct, rv=0; + char *rname; + + strncpy(tbuf, pw->pw_gecos, TBUFLEN); + tbuf[TBUFLEN-1] = 0; /* guarantee null termination */ + p = tbuf; + + /* why do we skip asterisks!?!? */ + if (*p == '*') ++p; + + /* truncate the uninteresting stuff off the end of gecos */ + p = strtok(p, ","); + if (!p) return 0; + + /* + * Ampersands get replaced by the login name. + */ + + /* First, count the number of ampersands. */ + for (ct=i=0; p[i]; i++) if (p[i]=='&') ct++; + + /* This tells us how much space we need to copy the name. */ + rname = malloc(strlen(p) + ct*strlen(pw->pw_name) + 1); + if (!rname) { + eprintf("finger: Out of space.\n"); + exit(1); + } + + /* Now, do it */ + for (i=j=0; p[i]; i++) { + if (p[i]=='&') { + strcpy(rname + j, pw->pw_name); + if (islower(rname[j])) rname[j] = toupper(rname[j]); + j += strlen(pw->pw_name); + } + else { + rname[j++] = p[i]; + } + } + rname[j] = 0; + + for (p = strtok(rname, "\t "); p && !rv; p = strtok(NULL, "\t ")) { + if (!strcasecmp(p, user)) + rv = 1; + } + free(rname); + + return rv; +} + +static int get_lastlog(int fd, uid_t uid, struct lastlog *ll) { + loff_t pos; + if (fd == -1) return -1; + pos = (long)uid * sizeof(*ll); + if (lseek(fd, pos, L_SET) != pos) return -1; + if (read(fd, ll, sizeof(*ll)) != sizeof(*ll)) return -1; + return 0; +} + +void enter_lastlog(PERSON *pn) { + static int opened = 0, fd = -1; + + WHERE *w; + struct lastlog ll; + int doit = 0; + + /* some systems may not maintain lastlog, don't report errors. */ + if (!opened) { + fd = open(_PATH_LASTLOG, O_RDONLY, 0); + opened = 1; + } + if (get_lastlog(fd, pn->uid, &ll)) { + /* as if never logged in */ + ll.ll_line[0] = ll.ll_host[0] = '\0'; + ll.ll_time = 0; + } + + if ((w = pn->whead) == NULL) + doit = 1; + else if (ll.ll_time != 0) { + /* if last login is earlier than some current login */ + for (; !doit && w != NULL; w = w->next) + if (w->info == LOGGEDIN && w->loginat < ll.ll_time) + doit = 1; + /* + * and if it's not any of the current logins + * can't use time comparison because there may be a small + * discrepency since login calls time() twice + */ + for (w = pn->whead; doit && w != NULL; w = w->next) + if (w->info == LOGGEDIN && + strncmp(w->tty, ll.ll_line, UT_LINESIZE) == 0) + doit = 0; + } + if (doit) { + w = walloc(pn); + w->info = LASTLOG; + bcopy(ll.ll_line, w->tty, UT_LINESIZE); + w->tty[UT_LINESIZE] = 0; + bcopy(ll.ll_host, w->host, UT_HOSTSIZE); + w->host[UT_HOSTSIZE] = 0; + w->loginat = ll.ll_time; + } +} + +void enter_where(struct utmp *ut, PERSON *pn) { + register WHERE *w = walloc(pn); + + w->info = LOGGEDIN; + bcopy(ut->ut_line, w->tty, UT_LINESIZE); + w->tty[UT_LINESIZE] = 0; + bcopy(ut->ut_host, w->host, UT_HOSTSIZE); + w->host[UT_HOSTSIZE] = 0; + w->loginat = ut->ut_time; + find_idle_and_ttywrite(w); +} + +PERSON * enter_person(struct passwd *pw) { + register PERSON *pn, **pp; + + for (pp = htab + hash(pw->pw_name); + *pp != NULL && strcmp((*pp)->name, pw->pw_name) != 0; + pp = &(*pp)->hlink) + ; + if ((pn = *pp) == NULL) { + pn = palloc(); + entries++; + if (phead == NULL) + phead = ptail = pn; + else { + ptail->next = pn; + ptail = pn; + } + pn->next = NULL; + pn->hlink = NULL; + *pp = pn; + userinfo(pn, pw); + pn->whead = NULL; + } + return(pn); +} + +PERSON *find_person(const char *name) { + register PERSON *pn; + + /* name may be only UT_NAMESIZE long and not terminated */ + for (pn = htab[hash(name)]; + pn != NULL && strncmp(pn->name, name, UT_NAMESIZE) != 0; + pn = pn->hlink) + ; + return(pn); +} + +static int hash(const char *name) { + register int h, i; + + h = 0; + /* name may be only UT_NAMESIZE long and not terminated */ + for (i = UT_NAMESIZE; --i >= 0 && *name;) + h = ((h << 2 | h >> (HBITS - 2)) ^ *name++) & HMASK; + return(h); +} + +PERSON *palloc(void) { + PERSON *p; + + if ((p = (PERSON *)malloc((u_int) sizeof(PERSON))) == NULL) { + eprintf("finger: Out of space.\n"); + exit(1); + } + return(p); +} + +WHERE * +walloc(PERSON *pn) +{ + register WHERE *w; + + if ((w = (WHERE *)malloc((u_int) sizeof(WHERE))) == NULL) { + eprintf("finger: Out of space.\n"); + exit(1); + } + if (pn->whead == NULL) + pn->whead = pn->wtail = w; + else { + pn->wtail->next = w; + pn->wtail = w; + } + w->next = NULL; + return(w); +} + +const char * +prphone(const char *num) +{ + char *p; + const char *q; + int len; + static char pbuf[15]; + + /* don't touch anything if the user has their own formatting */ + for (q = num; *q; ++q) + if (!isdigit(*q)) + return(num); + len = q - num; + p = pbuf; + switch(len) { + case 11: /* +0-123-456-7890 */ + *p++ = '+'; + *p++ = *num++; + *p++ = '-'; + /* FALLTHROUGH */ + case 10: /* 012-345-6789 */ + *p++ = *num++; + *p++ = *num++; + *p++ = *num++; + *p++ = '-'; + /* FALLTHROUGH */ + case 7: /* 012-3456 */ + *p++ = *num++; + *p++ = *num++; + *p++ = *num++; + break; + case 5: /* x0-1234 */ + case 4: /* x1234 */ + *p++ = 'x'; + *p++ = *num++; + break; + default: + return num; + } + if (len != 4) { + *p++ = '-'; + *p++ = *num++; + } + *p++ = *num++; + *p++ = *num++; + *p++ = *num++; + *p = '\0'; + return(pbuf); +} |