121554Sdist /* 237659Sbostic * Copyright (c) 1989 The Regents of the University of California. 335627Sbostic * All rights reserved. 435627Sbostic * 540027Sbostic * This code is derived from software contributed to Berkeley by 640027Sbostic * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 740027Sbostic * 842731Sbostic * %sccs.include.redist.c% 921554Sdist */ 1021554Sdist 1113619Ssam #ifndef lint 1221554Sdist char copyright[] = 1337659Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 1421554Sdist All rights reserved.\n"; 1535627Sbostic #endif /* not lint */ 161014Sbill 1721554Sdist #ifndef lint 18*52851Sbostic static char sccsid[] = "@(#)finger.c 5.25 (Berkeley) 03/06/92"; 1935627Sbostic #endif /* not lint */ 2021554Sdist 2118606Sedward /* 2237659Sbostic * Finger prints out information about users. It is not portable since 2337659Sbostic * certain fields (e.g. the full user name, office, and phone numbers) are 2437659Sbostic * extracted from the gecos field of the passwd file which other UNIXes 2537659Sbostic * may not have or may use for other things. 261014Sbill * 2737659Sbostic * There are currently two output formats; the short format is one line 2837659Sbostic * per user and displays login name, tty, login time, real name, idle time, 2937659Sbostic * and office location/phone number. The long format gives the same 3037659Sbostic * information (in a more legible format) as well as home directory, shell, 3137659Sbostic * mail info, and .plan/.project files. 321014Sbill */ 331014Sbill 3437659Sbostic #include <sys/param.h> 3550596Sbostic #include <fcntl.h> 3650596Sbostic #include <time.h> 3750596Sbostic #include <pwd.h> 3850596Sbostic #include <utmp.h> 3950596Sbostic #include <errno.h> 4037629Sbostic #include <stdio.h> 4150596Sbostic #include <stdlib.h> 4250596Sbostic #include <string.h> 4350613Sbostic #include <db.h> 4437659Sbostic #include "finger.h" 451014Sbill 4650613Sbostic DB *db; 4737659Sbostic time_t now; 4850596Sbostic int entries, lflag, mflag, pplan, sflag; 4937659Sbostic char tbuf[1024]; 501014Sbill 5150596Sbostic static void loginlist __P((void)); 5250596Sbostic static void userlist __P((int, char **)); 5350596Sbostic 5418606Sedward main(argc, argv) 5518606Sedward int argc; 5637659Sbostic char **argv; 5718606Sedward { 5837659Sbostic int ch; 591014Sbill 6037659Sbostic while ((ch = getopt(argc, argv, "lmps")) != EOF) 6137659Sbostic switch(ch) { 6237659Sbostic case 'l': 6337659Sbostic lflag = 1; /* long format */ 6437659Sbostic break; 6537659Sbostic case 'm': 6637659Sbostic mflag = 1; /* force exact match of names */ 6737659Sbostic break; 6837659Sbostic case 'p': 6937659Sbostic pplan = 1; /* don't show .plan/.project */ 7037659Sbostic break; 7137659Sbostic case 's': 7237659Sbostic sflag = 1; /* short format */ 7337659Sbostic break; 7437659Sbostic case '?': 7537659Sbostic default: 7637659Sbostic (void)fprintf(stderr, 7737659Sbostic "usage: finger [-lmps] [login ...]\n"); 7837659Sbostic exit(1); 7937659Sbostic } 8037659Sbostic argc -= optind; 8137659Sbostic argv += optind; 8237659Sbostic 8337659Sbostic (void)time(&now); 8437659Sbostic setpassent(1); 8537659Sbostic if (!*argv) { 8637659Sbostic /* 8737659Sbostic * Assign explicit "small" format if no names given and -l 8837659Sbostic * not selected. Force the -s BEFORE we get names so proper 8937659Sbostic * screening will be done. 9037659Sbostic */ 9137659Sbostic if (!lflag) 9237659Sbostic sflag = 1; /* if -l not explicit, force -s */ 9337659Sbostic loginlist(); 9437664Sedward if (entries == 0) 9537659Sbostic (void)printf("No one logged on.\n"); 9637659Sbostic } else { 9738586Sedward userlist(argc, argv); 9837659Sbostic /* 9937659Sbostic * Assign explicit "large" format if names given and -s not 10037659Sbostic * explicitly stated. Force the -l AFTER we get names so any 10137659Sbostic * remote finger attempts specified won't be mishandled. 10237659Sbostic */ 10337659Sbostic if (!sflag) 10437659Sbostic lflag = 1; /* if -s not explicit, force -l */ 10537659Sbostic } 10650613Sbostic if (entries) 10737659Sbostic if (lflag) 10837659Sbostic lflag_print(); 10937659Sbostic else 11037659Sbostic sflag_print(); 11118606Sedward exit(0); 11218606Sedward } 1131014Sbill 11450596Sbostic static void 11537659Sbostic loginlist() 1161014Sbill { 11737659Sbostic register PERSON *pn; 11850613Sbostic DBT data, key; 11937659Sbostic struct passwd *pw; 12037664Sedward struct utmp user; 12150613Sbostic int r, sflag; 12237664Sedward char name[UT_NAMESIZE + 1]; 1231014Sbill 12450596Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) 12550596Sbostic err("%s: %s", _PATH_UTMP, strerror(errno)); 12637659Sbostic name[UT_NAMESIZE] = NULL; 12738901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 12837659Sbostic if (!user.ut_name[0]) 12918606Sedward continue; 13037664Sedward if ((pn = find_person(user.ut_name)) == NULL) { 13137664Sedward bcopy(user.ut_name, name, UT_NAMESIZE); 13237664Sedward if ((pw = getpwnam(name)) == NULL) 13337664Sedward continue; 13437664Sedward pn = enter_person(pw); 1351014Sbill } 13637664Sedward enter_where(&user, pn); 13718606Sedward } 13850613Sbostic if (db && lflag) 13950613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) { 14050613Sbostic r = (*db->seq)(db, &key, &data, sflag); 14150613Sbostic if (r == -1) 14250613Sbostic err("db seq: %s", strerror(errno)); 14350613Sbostic if (r == 1) 14450613Sbostic break; 14550613Sbostic enter_lastlog(*(PERSON **)data.data); 14650613Sbostic } 14718606Sedward } 1481014Sbill 14950596Sbostic static void 15038586Sedward userlist(argc, argv) 15150596Sbostic register int argc; 15238586Sedward register char **argv; 15318606Sedward { 15437664Sedward register PERSON *pn; 15550613Sbostic DBT data, key; 15637664Sedward struct utmp user; 15737664Sedward struct passwd *pw; 15850613Sbostic int r, sflag, *used, *ip; 15950613Sbostic char **ap, **nargv, **np, **p; 1601014Sbill 16150613Sbostic if ((nargv = malloc(argc * sizeof(char *))) == NULL || 16250613Sbostic (used = calloc(argc, sizeof(int))) == NULL) 16350596Sbostic err("%s", strerror(errno)); 16438586Sedward 16550613Sbostic /* Pull out all network requests. */ 16650613Sbostic for (ap = p = argv, np = nargv; *p; ++p) 16750613Sbostic if (index(*p, '@')) 16850613Sbostic *np++ = *p; 16950613Sbostic else 17050613Sbostic *ap++ = *p; 17137659Sbostic 17250613Sbostic *np++ = NULL; 17350613Sbostic *ap++ = NULL; 17450613Sbostic 17550613Sbostic if (!*argv) 17637659Sbostic goto net; 17737659Sbostic 17818606Sedward /* 17950613Sbostic * Traverse the list of possible login names and check the login name 18037664Sedward * and real name against the name specified by the user. 18118606Sedward */ 18250613Sbostic if (mflag) 18350613Sbostic for (p = argv; *p; ++p) 18450613Sbostic if (pw = getpwnam(*p)) 18537996Sbostic enter_person(pw); 18650613Sbostic else 18750613Sbostic (void)fprintf(stderr, 18850613Sbostic "finger: %s: no such user\n", *p); 18950613Sbostic else { 19050613Sbostic while (pw = getpwent()) 19150613Sbostic for (p = argv, ip = used; *p; ++p, ++ip) 192*52851Sbostic if (match(pw, *p)) { 19350613Sbostic enter_person(pw); 19450613Sbostic *ip = 1; 19550613Sbostic } 19650613Sbostic for (p = argv, ip = used; *p; ++p, ++ip) 19750613Sbostic if (!*ip) 19850613Sbostic (void)fprintf(stderr, 19950613Sbostic "finger: %s: no such user\n", *p); 20050613Sbostic } 20137659Sbostic 20250613Sbostic /* Handle network requests. */ 20350613Sbostic net: for (p = nargv; *p;) 20450613Sbostic netfinger(*p++); 20537659Sbostic 20637664Sedward if (entries == 0) 20737659Sbostic return; 2081014Sbill 20918606Sedward /* 21037659Sbostic * Scan thru the list of users currently logged in, saving 21137659Sbostic * appropriate data whenever a match occurs. 21218606Sedward */ 21350596Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) 21450596Sbostic err("%s: %s", _PATH_UTMP, strerror(errno)); 21538901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 21637659Sbostic if (!user.ut_name[0]) 21718606Sedward continue; 21837664Sedward if ((pn = find_person(user.ut_name)) == NULL) 21937664Sedward continue; 22037664Sedward enter_where(&user, pn); 22118606Sedward } 22250613Sbostic if (db) 22350613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) { 22450613Sbostic r = (*db->seq)(db, &key, &data, sflag); 22550613Sbostic if (r == -1) 22650613Sbostic err("db seq: %s", strerror(errno)); 22750613Sbostic if (r == 1) 22850613Sbostic break; 22950613Sbostic enter_lastlog(*(PERSON **)data.data); 23050613Sbostic } 2311014Sbill } 232