121554Sdist /* 261995Sbostic * Copyright (c) 1989, 1993 361995Sbostic * The Regents of the University of California. 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 1261995Sbostic static char copyright[] = 1361995Sbostic "@(#) Copyright (c) 1989, 1993\n\ 1461995Sbostic The Regents of the University of California. All rights reserved.\n"; 1535627Sbostic #endif /* not lint */ 161014Sbill 1721554Sdist #ifndef lint 18*69102Sbostic static char sccsid[] = "@(#)finger.c 8.4 (Berkeley) 04/28/95"; 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> 4469101Sbostic #include <err.h> 4537659Sbostic #include "finger.h" 461014Sbill 4750613Sbostic DB *db; 4837659Sbostic time_t now; 4950596Sbostic int entries, lflag, mflag, pplan, sflag; 5037659Sbostic char tbuf[1024]; 511014Sbill 5250596Sbostic static void loginlist __P((void)); 5350596Sbostic static void userlist __P((int, char **)); 5450596Sbostic 5569101Sbostic int 5618606Sedward main(argc, argv) 5718606Sedward int argc; 5837659Sbostic char **argv; 5918606Sedward { 6037659Sbostic int ch; 611014Sbill 6237659Sbostic while ((ch = getopt(argc, argv, "lmps")) != EOF) 6337659Sbostic switch(ch) { 6437659Sbostic case 'l': 6537659Sbostic lflag = 1; /* long format */ 6637659Sbostic break; 6737659Sbostic case 'm': 6837659Sbostic mflag = 1; /* force exact match of names */ 6937659Sbostic break; 7037659Sbostic case 'p': 7137659Sbostic pplan = 1; /* don't show .plan/.project */ 7237659Sbostic break; 7337659Sbostic case 's': 7437659Sbostic sflag = 1; /* short format */ 7537659Sbostic break; 7637659Sbostic case '?': 7737659Sbostic default: 7837659Sbostic (void)fprintf(stderr, 7937659Sbostic "usage: finger [-lmps] [login ...]\n"); 8037659Sbostic exit(1); 8137659Sbostic } 8237659Sbostic argc -= optind; 8337659Sbostic argv += optind; 8437659Sbostic 8537659Sbostic (void)time(&now); 8637659Sbostic setpassent(1); 8737659Sbostic if (!*argv) { 8837659Sbostic /* 8937659Sbostic * Assign explicit "small" format if no names given and -l 9037659Sbostic * not selected. Force the -s BEFORE we get names so proper 9137659Sbostic * screening will be done. 9237659Sbostic */ 9337659Sbostic if (!lflag) 9437659Sbostic sflag = 1; /* if -l not explicit, force -s */ 9537659Sbostic loginlist(); 9637664Sedward if (entries == 0) 9737659Sbostic (void)printf("No one logged on.\n"); 9837659Sbostic } else { 9938586Sedward userlist(argc, argv); 10037659Sbostic /* 10137659Sbostic * Assign explicit "large" format if names given and -s not 10237659Sbostic * explicitly stated. Force the -l AFTER we get names so any 10337659Sbostic * remote finger attempts specified won't be mishandled. 10437659Sbostic */ 10537659Sbostic if (!sflag) 10637659Sbostic lflag = 1; /* if -s not explicit, force -l */ 10737659Sbostic } 10850613Sbostic if (entries) 10937659Sbostic if (lflag) 11037659Sbostic lflag_print(); 11137659Sbostic else 11237659Sbostic sflag_print(); 11369101Sbostic return (0); 11418606Sedward } 1151014Sbill 11650596Sbostic static void 11737659Sbostic loginlist() 1181014Sbill { 11937659Sbostic register PERSON *pn; 12050613Sbostic DBT data, key; 12137659Sbostic struct passwd *pw; 12237664Sedward struct utmp user; 12350613Sbostic int r, sflag; 12437664Sedward char name[UT_NAMESIZE + 1]; 1251014Sbill 12650596Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) 12769101Sbostic err(1, "%s", _PATH_UTMP); 12837659Sbostic name[UT_NAMESIZE] = NULL; 12938901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 13037659Sbostic if (!user.ut_name[0]) 13118606Sedward continue; 13237664Sedward if ((pn = find_person(user.ut_name)) == NULL) { 13337664Sedward bcopy(user.ut_name, name, UT_NAMESIZE); 13437664Sedward if ((pw = getpwnam(name)) == NULL) 13537664Sedward continue; 13637664Sedward pn = enter_person(pw); 1371014Sbill } 13837664Sedward enter_where(&user, pn); 13918606Sedward } 14050613Sbostic if (db && lflag) 14150613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) { 14269101Sbostic PERSON *tmp; 14369101Sbostic 14450613Sbostic r = (*db->seq)(db, &key, &data, sflag); 14550613Sbostic if (r == -1) 14669101Sbostic err(1, "db seq"); 14750613Sbostic if (r == 1) 14850613Sbostic break; 149*69102Sbostic memmove(&tmp, data.data, sizeof tmp); 15069101Sbostic enter_lastlog(tmp); 15150613Sbostic } 15218606Sedward } 1531014Sbill 15450596Sbostic static void 15538586Sedward userlist(argc, argv) 15650596Sbostic register int argc; 15738586Sedward register char **argv; 15818606Sedward { 15937664Sedward register PERSON *pn; 16050613Sbostic DBT data, key; 16137664Sedward struct utmp user; 16237664Sedward struct passwd *pw; 16350613Sbostic int r, sflag, *used, *ip; 16450613Sbostic char **ap, **nargv, **np, **p; 1651014Sbill 16664681Spendry if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL || 16750613Sbostic (used = calloc(argc, sizeof(int))) == NULL) 16869101Sbostic err(1, NULL); 16938586Sedward 17050613Sbostic /* Pull out all network requests. */ 17150613Sbostic for (ap = p = argv, np = nargv; *p; ++p) 17250613Sbostic if (index(*p, '@')) 17350613Sbostic *np++ = *p; 17450613Sbostic else 17550613Sbostic *ap++ = *p; 17637659Sbostic 17750613Sbostic *np++ = NULL; 17850613Sbostic *ap++ = NULL; 17950613Sbostic 18050613Sbostic if (!*argv) 18137659Sbostic goto net; 18237659Sbostic 18318606Sedward /* 18450613Sbostic * Traverse the list of possible login names and check the login name 18537664Sedward * and real name against the name specified by the user. 18618606Sedward */ 18750613Sbostic if (mflag) 18850613Sbostic for (p = argv; *p; ++p) 18969101Sbostic if ((pw = getpwnam(*p)) != NULL) 19037996Sbostic enter_person(pw); 19150613Sbostic else 19250613Sbostic (void)fprintf(stderr, 19350613Sbostic "finger: %s: no such user\n", *p); 19450613Sbostic else { 19569101Sbostic while ((pw = getpwent()) != NULL) 19650613Sbostic for (p = argv, ip = used; *p; ++p, ++ip) 19752851Sbostic if (match(pw, *p)) { 19850613Sbostic enter_person(pw); 19950613Sbostic *ip = 1; 20050613Sbostic } 20150613Sbostic for (p = argv, ip = used; *p; ++p, ++ip) 20250613Sbostic if (!*ip) 20350613Sbostic (void)fprintf(stderr, 20450613Sbostic "finger: %s: no such user\n", *p); 20550613Sbostic } 20637659Sbostic 20750613Sbostic /* Handle network requests. */ 20850613Sbostic net: for (p = nargv; *p;) 20950613Sbostic netfinger(*p++); 21037659Sbostic 21137664Sedward if (entries == 0) 21237659Sbostic return; 2131014Sbill 21418606Sedward /* 21537659Sbostic * Scan thru the list of users currently logged in, saving 21637659Sbostic * appropriate data whenever a match occurs. 21718606Sedward */ 21850596Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) 21969101Sbostic err(1, "%s", _PATH_UTMP); 22038901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 22137659Sbostic if (!user.ut_name[0]) 22218606Sedward continue; 22337664Sedward if ((pn = find_person(user.ut_name)) == NULL) 22437664Sedward continue; 22537664Sedward enter_where(&user, pn); 22618606Sedward } 22750613Sbostic if (db) 22850613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) { 22969101Sbostic PERSON *tmp; 23069101Sbostic 23150613Sbostic r = (*db->seq)(db, &key, &data, sflag); 23250613Sbostic if (r == -1) 23369101Sbostic err(1, "db seq"); 23450613Sbostic if (r == 1) 23550613Sbostic break; 236*69102Sbostic memmove(&tmp, data.data, sizeof tmp); 23769101Sbostic enter_lastlog(tmp); 23850613Sbostic } 2391014Sbill } 240