spirit@uxe.cso.uiuc.edu (11/29/89)
Hello, Anybody have "finger" running on their HP9000/800 series? I was going to set it up on ours, but I couldn't find a "fingerd" for the /etc/inetd.conf entry. Is this service NOT supported by HP??? ADVthanksANCE, John Kemp -------------------------------------- University of Illinois Department of Atmospheric Sciences kemp@uiatma.atmos.uiuc.edu --------------------------------------
irf@kuling.UUCP (Bo Thide') (11/29/89)
In article <47500018@uxe.cso.uiuc.edu> spirit@uxe.cso.uiuc.edu writes: >Hello, > > Anybody have "finger" running on their HP9000/800 series? >I was going to set it up on ours, but I couldn't find a "fingerd" >for the /etc/inetd.conf entry. Is this service NOT supported by >HP??? We have "finger" running on all our HP9000/300 and 800 series workstations. It is shipped with HP-UX. Since "finger" is included in the manual I don't see why it shouldn't be supported by HP. Of course, there is still problems with phone numbers having non-US format in the GCOS field but that may perhaps be considered as a minor nuisance. ^ Bo Thide'-------------------------------------------------------------- | | Swedish Institute of Space Physics, S-755 91 Uppsala, Sweden |I| [In Swedish: Institutet f|r RymdFysik, Uppsalaavdelningen (IRFU)] |R| Phone: (+46) 18-403000. Telex: 76036 (IRFUPP S). Fax: (+46) 18-403100 /|F|\ INTERNET: bt@irfu.se UUCP: ...!uunet!sunic!irfu!bt ~~U~~ -----------------------------------------------------------------sm5dfw
tml@hemuli.atk.vtt.fi (Tor Lillqvist) (11/30/89)
In article <1275@kuling.UUCP> irf@kuling.UUCP (Bo Thide') writes: >We have "finger" running on all our HP9000/300 and 800 series workstations. >It is shipped with HP-UX. Since "finger" is included in the manual I >don't see why it shouldn't be supported by HP. Of course, there is still >problems with phone numbers having non-US format in the GCOS field but >that may perhaps be considered as a minor nuisance. Yes, but the finger HP ships is a *local-host only* version. The program that usually is known as "finger" is able to contact finger daemons on remote hosts. In fact, that is what it usually is used for. After all, normally you see the users on your local machine each day and can ask them face-to-face what (.)plans they have and what (.)projects they are involved in. -- Tor Lillqvist, VTT/ATK
kim@kannel.lut.fi (Kimmo Suominen) (11/30/89)
Here's a fingerd that works fine for me. The port number for /etc/services is finger 79/tcp # Networked finger and an entry in /etc/inetd.conf might look like finger stream tcp nowait guest /usr/local/lib/fingerd fingerd This is the code, enjoy. Watch out for the signature. --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- /* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)fingerd.c 5.3 (Berkeley) 11/3/88"; #endif /* not lint */ /* * Finger server. */ #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <ctype.h> main(argc, argv) int argc; char *argv[]; { register char *sp; char line[512]; struct sockaddr_in sin; int i, p[2], pid, status; FILE *fp; char *av[4]; i = sizeof (sin); if (getpeername(0, &sin, &i) < 0) fatal(argv[0], "getpeername"); if (fgets(line, sizeof(line), stdin) == NULL) exit(1); sp = line; av[0] = "finger"; for (i = 1;;) { while (isspace(*sp)) sp++; if (!*sp) break; if (*sp == '/' && (sp[1] == 'W' || sp[1] == 'w')) { sp += 2; av[i++] = "-l"; } if (*sp && !isspace(*sp)) { av[i++] = sp; while (*sp && !isspace(*sp)) sp++; *sp = '\0'; } } av[i] = 0; if (pipe(p) < 0) fatal(argv[0], "pipe"); if ((pid = fork()) == 0) { close(p[0]); if (p[1] != 1) { dup2(p[1], 1); close(p[1]); } #ifdef hpux execv("/usr/local/bin/finger", av); #else execv("/usr/ucb/finger", av); #endif _exit(1); } if (pid == -1) fatal(argv[0], "fork"); close(p[1]); if ((fp = fdopen(p[0], "r")) == NULL) fatal(argv[0], "fdopen"); while ((i = getc(fp)) != EOF) { if (i == '\n') putchar('\r'); putchar(i); } fclose(fp); while ((i = wait(&status)) != pid && i != -1) ; return(0); } fatal(prog, s) char *prog, *s; { fprintf(stderr, "%s: ", prog); perror(s); exit(1); } --- CUT AGAIN --- CUT AGAIN --- CUT AGAIN --- CUT AGAIN --- CUT AGAIN --- Regards Kim -- ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ( Kimmo Suominen ! Lappeenranta U of Technology ! kim@kannel.lut.fi ) ( "That's what I think" ! Computing Centre * Finland ! Funet: KUULA::KIM ) ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
saaf@joker.optics.rochester.edu (Lennart Saaf) (12/01/89)
In article <KIM.89Nov29150646@kannel.lut.fi> kim@kannel.lut.fi (Kimmo Suominen) writes: > Here's a fingerd that works fine for me. Thank you! It works like a charm. I had to make one small change on our system because of the chunk of code below. > #ifdef hpux > execv("/usr/local/bin/finger", av); > #else > execv("/usr/ucb/finger", av); > #endif "hpux" was not defined in fingerd.c or any any of the include files (as far as I could tell). In addition, our finger is in /bin. So I replaced the above with: execv("/bin/finger", av); With this done, I can now finger my HP from another machine. But, of course, the HP can't finger other machines. Does anyone have a finger.c (not fingerd.c) that has this capability? Perhaps the finger you have in /usr/local/bin, Kimmo? Len -- ------------------------------------------------------------------------ | Len Saaf, The Institute of Optics, Univ. of Rochester, Rochester, NY | | Internet: saaf@joker.optics.rochester.edu Bitnet: SAAF@UOROPT | ------------------------------------------------------------------------
frank@tardis.ircc.ohio-state.EDU (Frank G. Fiamingo) (12/02/89)
Len Saaf writes: > But, of >course, the HP can't finger other machines. Does anyone have a >finger.c (not fingerd.c) that has this capability? ... Yes, I have one that I ftp'ed from hemuli.atk.vtt.fi. They advertised it as a port of the BSD source to HP-UX. And it is. I found that it installed quite easily on an HP840, and I then made a few minor changes to have it check a user's mailbox for unread mail. I can e-mail you a copy if you'd like. ------------------------------------------ Frank Fiamingo, Instruction and Research Computer Center of the Ohio State University frank@hpuxa.ircc.ohio-state.edu ------------------------------------------
bd@hp-ses.SDE.HP.COM (Bob Desinger) (12/04/89)
> "hpux" was not defined in fingerd.c or any any of the include files > (as far as I could tell). It's not in any header file, but it is defined in /lib/cpp, the C preprocessor. So you get it "for free." Another similar symbol defined this way is hp9000s800. On a Series 300 you get hp9000s300 defined. This way you can get the right version: code for any HP-UX (both 800 and 300), just for the 800, or just for the 300. Other vendors tend to define symbols for their machines too. Sun uses "sun" and the VAX uses "vax". -- bd
tml@hemuli.atk.vtt.fi (Tor Lillqvist) (12/04/89)
In article <KIM.89Dec4101011@kannel.lut.fi> kim@kannel.lut.fi (Kimmo Suominen) writes: >it does show your last login CORRECTLY. The one in hemuli shows actually your >"first login". Oops, I never noticed that... Thanks. Here is a patch to your version that fixes the followig feature: If you say "finger matti" and you have several users with real first name Matti, you will see only one of them. Now it compares the login name when deciding which session to show for a user. *** finger.c Mon Dec 4 14:54:01 1989 --- newfnger.c Mon Dec 4 14:51:02 1989 *************** *** 442,457 **** quickprint(p); continue; } if (!unshort) { shortprint(p); continue; } - #define min(a,b) ((a) < (b) ? (a) : (b)) - for (q = person1, minidle = (((unsigned)~0)>>1); q != 0; q = q->link) - if (!strcmp(q->name, p->name)) - minidle = min(minidle, q->idletime); - if (p->idletime > minidle) - continue; personprint(p); if (p->pwd != 0) { if (hack) { --- 442,461 ---- quickprint(p); continue; } + #define min(a,b) ((a) < (b) ? (a) : (b)) + if (p->pwd) { + for (q = person1, minidle = (((unsigned)~0)>>1); + q != 0; q = q->link) + if (q->pwd != 0 + && !strcmp(q->pwd->pw_name, p->pwd->pw_name)) + minidle = min(minidle, q->idletime); + if (p->idletime > minidle) + continue; + } if (!unshort) { shortprint(p); continue; } personprint(p); if (p->pwd != 0) { if (hack) { -- Tor Lillqvist, VTT/ATK
kim@kannel.lut.fi (Kimmo Suominen) (12/04/89)
I thought a few minutes later that you would propablu need this too. They are both originally from hemuli.atk.vtt.fi, but I've made some changes. Use -DBSD43 when you compile this. Add the resolver library if you want to (if you have it). Watch out for the signature and other comments in the end. --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- CUT HERE --- /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)finger.c 5.8 (Berkeley) 3/13/86"; #endif not lint /* * This is a finger program. It prints out useful information about users * by digging it up from various system files. It is not very portable * because the most useful parts of the information (the full user name, * office, and phone numbers) are all stored in the VAX-unused gecos field * of /etc/passwd, which, unfortunately, other UNIXes use for other things. * * There are three output formats, all of which give login name, teletype * line number, and login time. The short output format is reminiscent * of finger on ITS, and gives one line of information per user containing * in addition to the minimum basic requirements (MBR), the full name of * the user, his idle time and office location and phone number. The * quick style output is UNIX who-like, giving only name, teletype and * login time. Finally, the long style output give the same information * as the short (in more legible format), the home directory and shell * of the user, and, if it exits, a copy of the file .plan in the users * home directory. Finger may be called with or without a list of people * to finger -- if no list is given, all the people currently logged in * are fingered. * * The program is validly called by one of the following: * * finger {short form list of users} * finger -l {long form list of users} * finger -b {briefer long form list of users} * finger -q {quick list of users} * finger -i {quick list of users with idle times} * finger namelist {long format list of specified users} * finger -s namelist {short format list of specified users} * finger -w namelist {narrow short format list of specified users} * * where 'namelist' is a list of users login names. * The other options can all be given after one '-', or each can have its * own '-'. The -f option disables the printing of headers for short and * quick outputs. The -b option briefens long format outputs. The -p * option turns off plans for long format outputs. */ /* * Change by pst@anise.acc.com (Paul Traina): show only one instance * of a user on long displays. */ /* * Changed to read wtmp backwards by raussi@kannel.lut.fi (Heikki Raussi). */ /* * Added organization and cleaned up output. */ #include <sys/types.h> #include <sys/stat.h> #include <utmp.h> #include <sys/signal.h> #include <pwd.h> #include <stdio.h> #include <string.h> #if BSD #include <lastlog.h> #endif #include <ctype.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define bcopy(s,d,n) memcpy(d,s,n) #define index(s,c) strchr(s,c) #define rindex(s,c) strrchr(s,c) #define ASTERISK '*' /* ignore this in real name */ #define COMMA ',' /* separator in pw_gecos field */ #define COMMAND '-' /* command line flag char */ #if UCB #define CORY 'C' /* cory hall office */ #define EVANS 'E' /* evans hall office */ #endif #define SAMENAME '&' /* repeat login name in real name */ #define TALKABLE 0220 /* tty is writable if 220 mode */ #define ORGANIZATION "Lappeenranta University of Technology, Computing Centre, Finland\n\n" struct utmp user; #define NMAX sizeof(user.ut_name) #define LMAX sizeof(user.ut_line) #if BSD #define HMAX sizeof(user.ut_host) #endif struct person { /* one for each person fingered */ char *name; /* name */ char tty[LMAX+1]; /* null terminated tty line */ #if BSD char host[HMAX+1]; /* null terminated remote host name */ #endif long loginat; /* time of (last) login */ long idletime; /* how long idle (if logged in) */ char *realname; /* pointer to full name */ char *office; /* pointer to office name */ char *officephone; /* pointer to office phone no. */ char *homephone; /* pointer to home phone no. */ char *random; /* for any random stuff in pw_gecos */ struct passwd *pwd; /* structure of /etc/passwd stuff */ char loggedin; /* person is logged in */ char writable; /* tty is writable */ char original; /* this is not a duplicate entry */ struct person *link; /* link to next person */ }; #if BSD char LASTLOG[] = "/usr/adm/lastlog"; /* last login info */ #endif char USERLOG[] = "/etc/utmp"; /* who is logged in */ char PLAN[] = "/.plan"; /* what plan file is */ char PROJ[] = "/.project"; /* what project file */ int unbrief = 1; /* -b option default */ int header = 1; /* -f option default */ int hack = 1; /* -h option default */ int idle = 0; /* -i option default */ int large = 0; /* -l option default */ int match = 1; /* -m option default */ int plan = 1; /* -p option default */ int unquick = 1; /* -q option default */ int small = 0; /* -s option default */ int wide = 1; /* -w option default */ int unshort; #if BSD int lf; /* LASTLOG file descriptor */ #endif struct person *person1; /* list of people */ long tloc; /* current time */ struct passwd *pwdcopy(); char *strcpy(); char *malloc(); char *ctime(); int fdwt; /* hege */ main(argc, argv) int argc; register char **argv; { FILE *fp; register char *s; /* parse command line for (optional) arguments */ while (*++argv && **argv == COMMAND) for (s = *argv + 1; *s; s++) switch (*s) { case 'b': unbrief = 0; break; case 'f': header = 0; break; case 'h': hack = 0; break; case 'i': idle = 1; unquick = 0; break; case 'l': large = 1; break; case 'm': match = 0; break; case 'p': plan = 0; break; case 'q': unquick = 0; break; case 's': small = 1; break; case 'w': wide = 0; break; default: fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n"); exit(1); } if (unquick || idle) time(&tloc); /* * *argv == 0 means no names given */ if (*argv == 0) doall(); else donames(argv); if (person1) print(); exit(0); } doall() { register struct person *p; register struct passwd *pw; int uf; char name[NMAX + 1]; unshort = large; if ((uf = open(USERLOG, 0)) < 0) { fprintf(stderr, "finger: error opening %s\n", USERLOG); exit(2); } if (unquick) { #if BSD extern _pw_stayopen; #endif setpwent(); #if BSD _pw_stayopen = 1; #endif fwopen(); } while (read(uf, (char *)&user, sizeof user) == sizeof user) { if (user.ut_name[0] == 0) continue; #if !BSD if (user.ut_type != USER_PROCESS) continue; #endif if (person1 == 0) p = person1 = (struct person *) malloc(sizeof *p); else { p->link = (struct person *) malloc(sizeof *p); p = p->link; } bcopy(user.ut_name, name, NMAX); name[NMAX] = 0; bcopy(user.ut_line, p->tty, LMAX); p->tty[LMAX] = 0; #if BSD bcopy(user.ut_host, p->host, HMAX); p->host[HMAX] = 0; #endif p->loginat = user.ut_time; p->pwd = 0; p->loggedin = 1; if (unquick && (pw = getpwnam(name))) { p->pwd = pwdcopy(pw); decode(p); p->name = p->pwd->pw_name; } else p->name = strcpy(malloc(strlen(name) + 1), name); } if (unquick) { fwclose(); endpwent(); } close(uf); if (person1 == 0) { printf("No one logged on\n"); return; } p->link = 0; } donames(argv) char **argv; { register struct person *p; register struct passwd *pw; int uf; /* * get names from command line and check to see if they're * logged in */ unshort = !small; for (; *argv != 0; argv++) { if (netfinger(*argv)) continue; if (person1 == 0) p = person1 = (struct person *) malloc(sizeof *p); else { p->link = (struct person *) malloc(sizeof *p); p = p->link; } p->name = *argv; p->loggedin = 0; p->original = 1; p->pwd = 0; } if (person1 == 0) return; p->link = 0; /* * if we are doing it, read /etc/passwd for the useful info */ if (unquick) { setpwent(); if (!match) { #if BSD extern _pw_stayopen; _pw_stayopen = 1; #endif for (p = person1; p != 0; p = p->link) if (pw = getpwnam(p->name)) p->pwd = pwdcopy(pw); } else while ((pw = getpwent()) != 0) { for (p = person1; p != 0; p = p->link) { if (!p->original) continue; if (strcmp(p->name, pw->pw_name) != 0 && !matchcmp(pw->pw_gecos, pw->pw_name, p->name)) continue; if (p->pwd == 0) p->pwd = pwdcopy(pw); else { struct person *new; /* * handle multiple login names, insert * new "duplicate" entry behind */ new = (struct person *) malloc(sizeof *new); new->pwd = pwdcopy(pw); new->name = p->name; new->original = 1; new->loggedin = 0; new->link = p->link; p->original = 0; p->link = new; p = new; } } } endpwent(); } /* Now get login information */ if ((uf = open(USERLOG, 0)) < 0) { fprintf(stderr, "finger: error opening %s\n", USERLOG); exit(2); } while (read(uf, (char *)&user, sizeof user) == sizeof user) { if (*user.ut_name == 0) continue; #if !BSD if (user.ut_type != USER_PROCESS) continue; #endif for (p = person1; p != 0; p = p->link) { if (p->loggedin == 2) continue; if (strncmp(p->pwd ? p->pwd->pw_name : p->name, user.ut_name, NMAX) != 0) continue; if (p->loggedin == 0) { bcopy(user.ut_line, p->tty, LMAX); p->tty[LMAX] = 0; #if BSD bcopy(user.ut_host, p->host, HMAX); p->host[HMAX] = 0; #endif p->loginat = user.ut_time; p->loggedin = 1; } else { /* p->loggedin == 1 */ struct person *new; new = (struct person *) malloc(sizeof *new); new->name = p->name; bcopy(user.ut_line, new->tty, LMAX); new->tty[LMAX] = 0; #if BSD bcopy(user.ut_host, new->host, HMAX); new->host[HMAX] = 0; #endif new->loginat = user.ut_time; new->pwd = p->pwd; new->loggedin = 1; new->original = 0; new->link = p->link; p->loggedin = 2; p->link = new; p = new; } } } close(uf); if (unquick) { fwopen(); for (p = person1; p != 0; p = p->link) decode(p); fwclose(); } } print() { register FILE *fp; register struct person *p, *q; register char *s; register c; register long minidle; /* * print out what we got */ if (header) { printf(ORGANIZATION); /* kim */ if (unquick) { if (!unshort) if (wide) printf("Login Name TTY Idle When Office\n"); else printf("Login TTY Idle When Office\n"); } else { printf("Login TTY When"); if (idle) printf(" Idle"); putchar('\n'); } } for (p = person1; p != 0; p = p->link) { if (!unquick) { quickprint(p); continue; } if (!unshort) { shortprint(p); continue; } #define min(a,b) ((a) < (b) ? (a) : (b)) for (q = person1, minidle = (((unsigned)~0)>>1); q != 0; q = q->link) if (!strcmp(q->name, p->name)) minidle = min(minidle, q->idletime); if (p->idletime > minidle) continue; personprint(p); if (p->pwd != 0) { if (hack) { s = malloc(strlen(p->pwd->pw_dir) + sizeof PROJ); strcpy(s, p->pwd->pw_dir); strcat(s, PROJ); if ((fp = fopen(s, "r")) != 0) { printf("Project: "); while ((c = getc(fp)) != EOF) { if (c == '\n') break; if (isprint(c) || isspace(c)) putchar(c); else putchar('?'); } fclose(fp); putchar('\n'); } free(s); } if (plan) { s = malloc(strlen(p->pwd->pw_dir) + sizeof PLAN); strcpy(s, p->pwd->pw_dir); strcat(s, PLAN); if ((fp = fopen(s, "r")) == 0) printf("No Plan.\n"); else { printf("Plan:\n"); while ((c = getc(fp)) != EOF) if (isprint(c) || isspace(c)) putchar(c); else putchar('?'); fclose(fp); } free(s); } } if (p->link != 0) putchar('\n'); } } /* * Duplicate a pwd entry. * Note: Only the useful things (what the program currently uses) are copied. */ struct passwd * pwdcopy(pfrom) register struct passwd *pfrom; { register struct passwd *pto; pto = (struct passwd *) malloc(sizeof *pto); #define savestr(s) strcpy(malloc(strlen(s) + 1), s) pto->pw_name = savestr(pfrom->pw_name); pto->pw_uid = pfrom->pw_uid; pto->pw_gecos = savestr(pfrom->pw_gecos); pto->pw_dir = savestr(pfrom->pw_dir); pto->pw_shell = savestr(pfrom->pw_shell); #undef savestr return pto; } /* * print out information on quick format giving just name, tty, login time * and idle time if idle is set. */ quickprint(pers) register struct person *pers; { printf("%-*.*s ", NMAX, NMAX, pers->name); if (pers->loggedin) { if (idle) { findidle(pers); printf("%c%-*s %-16.16s", pers->writable ? ' ' : '*', LMAX, pers->tty, ctime(&pers->loginat)); ltimeprint(" ", &pers->idletime, ""); } else printf(" %-*s %-16.16s", LMAX, pers->tty, ctime(&pers->loginat)); putchar('\n'); } else printf(" Not Logged In\n"); } /* * print out information in short format, giving login name, full name, * tty, idle time, login time, office location and phone. */ shortprint(pers) register struct person *pers; { char *p; char dialup; if (pers->pwd == 0) { printf("%-15s ???\n", pers->name); return; } printf("%-*s", NMAX, pers->pwd->pw_name); dialup = 0; if (wide) { if (pers->realname) printf(" %-20.20s", pers->realname); else printf(" ??? "); } putchar(' '); if (pers->loggedin && !pers->writable) putchar('*'); else putchar(' '); if (*pers->tty) { if (pers->tty[0] == 't' && pers->tty[1] == 't' && pers->tty[2] == 'y') { if (pers->tty[3] == 'd' && pers->loggedin) dialup = 1; printf("%-3.3s ", pers->tty + 3); } else printf("%-3.3s ", pers->tty); } else printf(" "); p = ctime(&pers->loginat); if (pers->loggedin) { stimeprint(&pers->idletime); printf(" %3.3s %-5.5s ", p, p + 11); } else if (pers->loginat == 0) printf(" < . . . . >"); else if (tloc - pers->loginat >= 180 * 24 * 60 * 60) printf(" <%-6.6s, %-4.4s>", p + 4, p + 20); else printf(" <%-12.12s>", p + 4); if (dialup && pers->homephone) printf(" %20s", pers->homephone); else { if (pers->office) printf(" %-11.11s", pers->office); else if (pers->officephone || pers->homephone) printf(" "); if (pers->officephone) printf(" %s", pers->officephone); else if (pers->homephone) printf(" %s", pers->homephone); } putchar('\n'); } /* * print out a person in long format giving all possible information. * directory and shell are inhibited if unbrief is clear. */ personprint(pers) register struct person *pers; { if (pers->pwd == 0) { printf("Login name: %-10s\t\t\tIn real life: ???\n", pers->name); return; } printf("Login name: %-10s", pers->pwd->pw_name); if (pers->loggedin && !pers->writable) printf("\t(messages off)\t"); else printf("\t\t\t"); if (pers->realname) printf("In real life: %s", pers->realname); if (pers->office) { printf("\nOffice: %-.11s", pers->office); if (pers->officephone) { printf(", %s", pers->officephone); if (pers->homephone) printf("\t\t\tHome phone: %s", pers->homephone); else if (pers->random) printf("\t\t\t%s", pers->random); } else if (pers->homephone) printf("\t\t\t\tHome phone: %s", pers->homephone); else if (pers->random) printf("\t\t\t\t%s", pers->random); } else if (pers->officephone) { printf("\nPhone: %s", pers->officephone); if (pers->homephone) printf(", %s", pers->homephone); if (pers->random) printf(", %s", pers->random); } else if (pers->homephone) { printf("\nPhone: %s", pers->homephone); if (pers->random) printf(", %s", pers->random); } else if (pers->random) printf("\n%s", pers->random); if (unbrief) { printf("\nDirectory: %-25s", pers->pwd->pw_dir); if (*pers->pwd->pw_shell) printf("\tShell: %-s", pers->pwd->pw_shell); } if (pers->loggedin) { register char *ep = ctime(&pers->loginat); #if BSD if (*pers->host) { printf("\nOn since %15.15s on %s from %s", &ep[4], pers->tty, pers->host); ltimeprint("\n", &pers->idletime, " Idle Time"); } else #endif { printf("\nOn since %15.15s on %-*s", &ep[4], LMAX, pers->tty); ltimeprint("", &pers->idletime, " Idle Time"); } } else if (pers->loginat == 0) printf("\nNever logged in."); else if (tloc - pers->loginat > 180 * 24 * 60 * 60) { register char *ep = ctime(&pers->loginat); printf("\nLast login %10.10s, %4.4s on %s", ep, ep+20, pers->tty); #if BSD if (*pers->host) printf(" from %s", pers->host); #endif } else { register char *ep = ctime(&pers->loginat); printf("\nLast login %16.16s on %s", ep, pers->tty); #if BSD if (*pers->host) printf(" from %s", pers->host); #endif } putchar('\n'); } /* * very hacky section of code to format phone numbers. filled with * magic constants like 4, 7 and 10. */ char * phone(s, len, alldigits) register char *s; int len; char alldigits; { char fonebuf[15]; register char *p = fonebuf; register i; #if BSD if (!alldigits) #endif return (strcpy(malloc(len + 1), s)); #if BSD switch (len) { case 4: *p++ = ' '; *p++ = 'x'; *p++ = '2'; *p++ = '-'; for (i = 0; i < 4; i++) *p++ = *s++; break; case 5: *p++ = ' '; *p++ = 'x'; *p++ = *s++; *p++ = '-'; for (i = 0; i < 4; i++) *p++ = *s++; break; case 7: for (i = 0; i < 3; i++) *p++ = *s++; *p++ = '-'; for (i = 0; i < 4; i++) *p++ = *s++; break; case 10: for (i = 0; i < 3; i++) *p++ = *s++; *p++ = '-'; for (i = 0; i < 3; i++) *p++ = *s++; *p++ = '-'; for (i = 0; i < 4; i++) *p++ = *s++; break; case 0: return 0; default: return (strcpy(malloc(len + 1), s)); } *p++ = 0; return (strcpy(malloc(p - fonebuf), fonebuf)); #endif } /* * decode the information in the gecos field of /etc/passwd */ decode(pers) register struct person *pers; { char buffer[256]; register char *bp, *gp, *lp; int alldigits; int hasspace; int len; pers->realname = 0; pers->office = 0; pers->officephone = 0; pers->homephone = 0; pers->random = 0; if (pers->pwd == 0) return; gp = pers->pwd->pw_gecos; bp = buffer; if (*gp == ASTERISK) gp++; while (*gp && *gp != COMMA) /* name */ if (*gp == SAMENAME) { lp = pers->pwd->pw_name; if (islower(*lp)) *bp++ = toupper(*lp++); while (*bp++ = *lp++) ; bp--; gp++; } else *bp++ = *gp++; *bp++ = 0; if ((len = bp - buffer) > 1) pers->realname = strcpy(malloc(len), buffer); if (*gp == COMMA) { /* office */ gp++; hasspace = 0; bp = buffer; while (*gp && *gp != COMMA) { *bp = *gp++; if (*bp == ' ') hasspace = 1; /* leave 5 for Cory and Evans expansion */ if (bp < buffer + sizeof buffer - 6) bp++; } *bp = 0; len = bp - buffer; bp--; /* point to last character */ if (hasspace || len == 0) len++; #if UCB else if (*bp == CORY) { strcpy(bp, " Cory"); len += 5; } else if (*bp == EVANS) { strcpy(bp, " Evans"); len += 6; } #endif else len++; if (len > 1) pers->office = strcpy(malloc(len), buffer); } if (*gp == COMMA) { /* office phone */ gp++; bp = buffer; alldigits = 1; while (*gp && *gp != COMMA) { *bp = *gp++; if (!isdigit(*bp)) alldigits = 0; if (bp < buffer + sizeof buffer - 1) bp++; } *bp = 0; pers->officephone = phone(buffer, bp - buffer, alldigits); } if (*gp == COMMA) { /* home phone */ gp++; bp = buffer; alldigits = 1; while (*gp && *gp != COMMA) { *bp = *gp++; if (!isdigit(*bp)) alldigits = 0; if (bp < buffer + sizeof buffer - 1) bp++; } *bp = 0; pers->homephone = phone(buffer, bp - buffer, alldigits); } if (pers->loggedin) findidle(pers); else findwhen(pers); } /* * find the last log in of a user by checking the LASTLOG file. * the entry is indexed by the uid, so this can only be done if * the uid is known (which it isn't in quick mode) */ fwopen() { #if BSD if ((lf = open(LASTLOG, 0)) < 0) fprintf(stderr, "finger: %s open error\n", LASTLOG); #else fdwt=open(WTMP_FILE,0); /* Hege */ #endif } findwhen(pers) register struct person *pers; { #if BSD struct lastlog ll; int i; if (lf >= 0) { lseek(lf, (long)pers->pwd->pw_uid * sizeof ll, 0); if ((i = read(lf, (char *)&ll, sizeof ll)) == sizeof ll) { bcopy(ll.ll_line, pers->tty, LMAX); pers->tty[LMAX] = 0; bcopy(ll.ll_host, pers->host, HMAX); pers->host[HMAX] = 0; pers->loginat = ll.ll_time; } else { if (i != 0) fprintf(stderr, "finger: %s read error\n", LASTLOG); pers->tty[0] = 0; pers->host[0] = 0; pers->loginat = 0L; } } else { pers->tty[0] = 0; pers->host[0] = 0; pers->loginat = 0L; } #else /* Hege */ struct utmp *wtmp; int done=1,ok=0; wtmp=(struct utmp *)malloc(sizeof(struct utmp)); if(lseek(fdwt,0l,2)==-1) done=0; while(done && (lseek(fdwt,(long)(sizeof(struct utmp)*-1),1)>0)) { done=read(fdwt,wtmp,sizeof(struct utmp)); wtmp->ut_user[8]='\0'; if(!strcmp(pers->name,wtmp->ut_user) && wtmp->ut_type==USER_PROCESS){ done=0; ok=1; } if(lseek(fdwt,(long)(sizeof(struct utmp)*-1),1)<0) done=0; } if (ok) { memcpy(pers->tty, wtmp->ut_line, LMAX); pers->tty[LMAX] = 0; pers->loginat = wtmp->ut_time; } else { pers->tty[0] = 0; pers->loginat = 0L; } #endif } fwclose() { #if BSD if (lf >= 0) close(lf); #else close(fdwt); /* Hege */ #endif } /* * find the idle time of a user by doing a stat on /dev/tty??, * where tty?? has been gotten from USERLOG, supposedly. */ findidle(pers) register struct person *pers; { struct stat ttystatus; static char buffer[20] = "/dev/"; long t; #define TTYLEN 5 strcpy(buffer + TTYLEN, pers->tty); buffer[TTYLEN+LMAX] = 0; if (stat(buffer, &ttystatus) < 0) { fprintf(stderr, "finger: Can't stat %s\n", buffer); exit(4); } time(&t); if (t < ttystatus.st_atime) pers->idletime = 0L; else pers->idletime = t - ttystatus.st_atime; pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE; } /* * print idle time in short format; this program always prints 4 characters; * if the idle time is zero, it prints 4 blanks. */ stimeprint(dt) long *dt; { register struct tm *delta; delta = gmtime(dt); if (delta->tm_yday == 0) if (delta->tm_hour == 0) if (delta->tm_min == 0) printf(" "); else printf(" %2d", delta->tm_min); else if (delta->tm_hour >= 10) printf("%3d:", delta->tm_hour); else printf("%1d:%02d", delta->tm_hour, delta->tm_min); else printf("%3dd", delta->tm_yday); } /* * print idle time in long format with care being taken not to pluralize * 1 minutes or 1 hours or 1 days. * print "prefix" first. */ ltimeprint(before, dt, after) long *dt; char *before, *after; { register struct tm *delta; delta = gmtime(dt); if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 && delta->tm_sec <= 10) return (0); printf("%s", before); if (delta->tm_yday >= 10) printf("%d days", delta->tm_yday); else if (delta->tm_yday > 0) printf("%d day%s %d hour%s", delta->tm_yday, delta->tm_yday == 1 ? "" : "s", delta->tm_hour, delta->tm_hour == 1 ? "" : "s"); else if (delta->tm_hour >= 10) printf("%d hours", delta->tm_hour); else if (delta->tm_hour > 0) printf("%d hour%s %d minute%s", delta->tm_hour, delta->tm_hour == 1 ? "" : "s", delta->tm_min, delta->tm_min == 1 ? "" : "s"); else if (delta->tm_min >= 10) printf("%2d minutes", delta->tm_min); else if (delta->tm_min == 0) printf("%2d seconds", delta->tm_sec); else printf("%d minute%s %d second%s", delta->tm_min, delta->tm_min == 1 ? "" : "s", delta->tm_sec, delta->tm_sec == 1 ? "" : "s"); printf("%s", after); } matchcmp(gname, login, given) register char *gname; char *login; char *given; { char buffer[100]; register char *bp, *lp; register c; if (*gname == ASTERISK) gname++; lp = 0; bp = buffer; for (;;) switch (c = *gname++) { case SAMENAME: for (lp = login; bp < buffer + sizeof buffer && (*bp++ = *lp++);) ; bp--; break; case ' ': case COMMA: case '\0': *bp = 0; if (namecmp(buffer, given)) return (1); if (c == COMMA || c == 0) return (0); bp = buffer; break; default: if (bp < buffer + sizeof buffer) *bp++ = c; } /*NOTREACHED*/ } namecmp(name1, name2) register char *name1, *name2; { register c1, c2; for (;;) { c1 = *name1++; if (islower(c1)) c1 = toupper(c1); c2 = *name2++; if (islower(c2)) c2 = toupper(c2); if (c1 != c2) break; if (c1 == 0) return (1); } if (!c1) { for (name2--; isdigit(*name2); name2++) ; if (*name2 == 0) return (1); } else if (!c2) { for (name1--; isdigit(*name1); name1++) ; if (*name2 == 0) return (1); } return (0); } netfinger(name) char *name; { char *host; char fname[100]; struct hostent *hp; struct servent *sp; struct sockaddr_in sin; int s; register FILE *f; register int c; register int lastc; if (name == NULL) return (0); host = rindex(name, '@'); if (host == NULL) return (0); *host++ = 0; hp = gethostbyname(host); if (hp == NULL) { static struct hostent def; static struct in_addr defaddr; #if BSD43 static char *alist[1]; #endif static char namebuf[128]; defaddr.s_addr = inet_addr(host); if (defaddr.s_addr == -1) { printf("unknown host: %s\n", host); return (1); } strcpy(namebuf, host); def.h_name = namebuf; #if BSD43 def.h_addr_list = alist; #endif def.h_addr = (char *)&defaddr; def.h_length = sizeof (struct in_addr); def.h_addrtype = AF_INET; def.h_aliases = 0; hp = &def; } printf("[%s]", hp->h_name); sp = getservbyname("finger", "tcp"); if (sp == 0) { printf("tcp/finger: unknown service\n"); return (1); } sin.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); sin.sin_port = sp->s_port; s = socket(hp->h_addrtype, SOCK_STREAM, 0); if (s < 0) { fflush(stdout); perror("socket"); return (1); } if (connect(s, (char *)&sin, sizeof (sin)) < 0) { fflush(stdout); perror("connect"); close(s); return (1); } printf("\n"); if (large) write(s, "/W ", 3); write(s, name, strlen(name)); write(s, "\r\n", 2); f = fdopen(s, "r"); while ((c = getc(f)) != EOF) { switch(c) { case 0210: case 0211: case 0212: case 0214: c -= 0200; break; case 0215: c = '\n'; break; } lastc = c; if (isprint(c) || isspace(c)) putchar(c); else putchar('?'); } if (lastc != '\n') putchar('\n'); (void)fclose(f); return (1); } --- CUT AGAIN --- CUT AGAIN --- CUT AGAIN --- CUT AGAIN --- CUT AGAIN --- This will get you along. It doesn't check mail (yet, I'm working on it), but it does show your last login CORRECTLY. The one in hemuli shows actually your "first login". If there's interest, I'll post or e-mail the improved version with mail checking. Kim -- ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ( Kimmo Suominen ! Lappeenranta U of Technology ! kim@kannel.lut.fi ) ( "That's what I think" ! Computing Centre * Finland ! Funet: KUULA::KIM ) ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
kim@kannel.lut.fi (Kimmo Suominen) (12/05/89)
Thanks, Tor. I had forgot about that - I've delegated it to another person. Now I'll try to come up with the version supporting mail checking real soon. Kim -- ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ( Kimmo Suominen ! Lappeenranta U of Technology ! kim@kannel.lut.fi ) ( "That's what I think" ! Computing Centre * Finland ! Funet: KUULA::KIM ) ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''