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*69236Sbostic static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 05/04/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>
35*69236Sbostic
36*69236Sbostic #include <db.h>
37*69236Sbostic #include <err.h>
38*69236Sbostic #include <errno.h>
3950596Sbostic #include <fcntl.h>
4050596Sbostic #include <pwd.h>
4137629Sbostic #include <stdio.h>
4250596Sbostic #include <stdlib.h>
4350596Sbostic #include <string.h>
44*69236Sbostic #include <time.h>
45*69236Sbostic #include <unistd.h>
46*69236Sbostic #include <utmp.h>
47*69236Sbostic
4837659Sbostic #include "finger.h"
491014Sbill
5050613Sbostic DB *db;
5137659Sbostic time_t now;
5250596Sbostic int entries, lflag, mflag, pplan, sflag;
5337659Sbostic char tbuf[1024];
541014Sbill
5550596Sbostic static void loginlist __P((void));
5650596Sbostic static void userlist __P((int, char **));
5750596Sbostic
5869101Sbostic int
main(argc,argv)5918606Sedward main(argc, argv)
6018606Sedward int argc;
6137659Sbostic char **argv;
6218606Sedward {
6337659Sbostic int ch;
641014Sbill
6537659Sbostic while ((ch = getopt(argc, argv, "lmps")) != EOF)
6637659Sbostic switch(ch) {
6737659Sbostic case 'l':
6837659Sbostic lflag = 1; /* long format */
6937659Sbostic break;
7037659Sbostic case 'm':
7137659Sbostic mflag = 1; /* force exact match of names */
7237659Sbostic break;
7337659Sbostic case 'p':
7437659Sbostic pplan = 1; /* don't show .plan/.project */
7537659Sbostic break;
7637659Sbostic case 's':
7737659Sbostic sflag = 1; /* short format */
7837659Sbostic break;
7937659Sbostic case '?':
8037659Sbostic default:
8137659Sbostic (void)fprintf(stderr,
8237659Sbostic "usage: finger [-lmps] [login ...]\n");
8337659Sbostic exit(1);
8437659Sbostic }
8537659Sbostic argc -= optind;
8637659Sbostic argv += optind;
8737659Sbostic
8837659Sbostic (void)time(&now);
8937659Sbostic setpassent(1);
9037659Sbostic if (!*argv) {
9137659Sbostic /*
9237659Sbostic * Assign explicit "small" format if no names given and -l
9337659Sbostic * not selected. Force the -s BEFORE we get names so proper
9437659Sbostic * screening will be done.
9537659Sbostic */
9637659Sbostic if (!lflag)
9737659Sbostic sflag = 1; /* if -l not explicit, force -s */
9837659Sbostic loginlist();
9937664Sedward if (entries == 0)
10037659Sbostic (void)printf("No one logged on.\n");
10137659Sbostic } else {
10238586Sedward userlist(argc, argv);
10337659Sbostic /*
10437659Sbostic * Assign explicit "large" format if names given and -s not
10537659Sbostic * explicitly stated. Force the -l AFTER we get names so any
10637659Sbostic * remote finger attempts specified won't be mishandled.
10737659Sbostic */
10837659Sbostic if (!sflag)
10937659Sbostic lflag = 1; /* if -s not explicit, force -l */
11037659Sbostic }
11150613Sbostic if (entries)
11237659Sbostic if (lflag)
11337659Sbostic lflag_print();
11437659Sbostic else
11537659Sbostic sflag_print();
11669101Sbostic return (0);
11718606Sedward }
1181014Sbill
11950596Sbostic static void
loginlist()12037659Sbostic loginlist()
1211014Sbill {
12237659Sbostic register PERSON *pn;
12350613Sbostic DBT data, key;
12437659Sbostic struct passwd *pw;
12537664Sedward struct utmp user;
12650613Sbostic int r, sflag;
12737664Sedward char name[UT_NAMESIZE + 1];
1281014Sbill
12950596Sbostic if (!freopen(_PATH_UTMP, "r", stdin))
13069101Sbostic err(1, "%s", _PATH_UTMP);
13137659Sbostic name[UT_NAMESIZE] = NULL;
13238901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
13337659Sbostic if (!user.ut_name[0])
13418606Sedward continue;
13537664Sedward if ((pn = find_person(user.ut_name)) == NULL) {
13637664Sedward bcopy(user.ut_name, name, UT_NAMESIZE);
13737664Sedward if ((pw = getpwnam(name)) == NULL)
13837664Sedward continue;
13937664Sedward pn = enter_person(pw);
1401014Sbill }
14137664Sedward enter_where(&user, pn);
14218606Sedward }
14350613Sbostic if (db && lflag)
14450613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) {
14569101Sbostic PERSON *tmp;
14669101Sbostic
14750613Sbostic r = (*db->seq)(db, &key, &data, sflag);
14850613Sbostic if (r == -1)
14969101Sbostic err(1, "db seq");
15050613Sbostic if (r == 1)
15150613Sbostic break;
15269102Sbostic memmove(&tmp, data.data, sizeof tmp);
15369101Sbostic enter_lastlog(tmp);
15450613Sbostic }
15518606Sedward }
1561014Sbill
15750596Sbostic static void
userlist(argc,argv)15838586Sedward userlist(argc, argv)
15950596Sbostic register int argc;
16038586Sedward register char **argv;
16118606Sedward {
16237664Sedward register PERSON *pn;
16350613Sbostic DBT data, key;
16437664Sedward struct utmp user;
16537664Sedward struct passwd *pw;
16650613Sbostic int r, sflag, *used, *ip;
16750613Sbostic char **ap, **nargv, **np, **p;
1681014Sbill
16964681Spendry if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL ||
17050613Sbostic (used = calloc(argc, sizeof(int))) == NULL)
17169101Sbostic err(1, NULL);
17238586Sedward
17350613Sbostic /* Pull out all network requests. */
17450613Sbostic for (ap = p = argv, np = nargv; *p; ++p)
17550613Sbostic if (index(*p, '@'))
17650613Sbostic *np++ = *p;
17750613Sbostic else
17850613Sbostic *ap++ = *p;
17937659Sbostic
18050613Sbostic *np++ = NULL;
18150613Sbostic *ap++ = NULL;
18250613Sbostic
18350613Sbostic if (!*argv)
18437659Sbostic goto net;
18537659Sbostic
18618606Sedward /*
18750613Sbostic * Traverse the list of possible login names and check the login name
18837664Sedward * and real name against the name specified by the user.
18918606Sedward */
19050613Sbostic if (mflag)
19150613Sbostic for (p = argv; *p; ++p)
19269101Sbostic if ((pw = getpwnam(*p)) != NULL)
19337996Sbostic enter_person(pw);
19450613Sbostic else
19550613Sbostic (void)fprintf(stderr,
19650613Sbostic "finger: %s: no such user\n", *p);
19750613Sbostic else {
19869101Sbostic while ((pw = getpwent()) != NULL)
19950613Sbostic for (p = argv, ip = used; *p; ++p, ++ip)
20052851Sbostic if (match(pw, *p)) {
20150613Sbostic enter_person(pw);
20250613Sbostic *ip = 1;
20350613Sbostic }
20450613Sbostic for (p = argv, ip = used; *p; ++p, ++ip)
20550613Sbostic if (!*ip)
20650613Sbostic (void)fprintf(stderr,
20750613Sbostic "finger: %s: no such user\n", *p);
20850613Sbostic }
20937659Sbostic
21050613Sbostic /* Handle network requests. */
21150613Sbostic net: for (p = nargv; *p;)
21250613Sbostic netfinger(*p++);
21337659Sbostic
21437664Sedward if (entries == 0)
21537659Sbostic return;
2161014Sbill
21718606Sedward /*
21837659Sbostic * Scan thru the list of users currently logged in, saving
21937659Sbostic * appropriate data whenever a match occurs.
22018606Sedward */
22150596Sbostic if (!freopen(_PATH_UTMP, "r", stdin))
22269101Sbostic err(1, "%s", _PATH_UTMP);
22338901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
22437659Sbostic if (!user.ut_name[0])
22518606Sedward continue;
22637664Sedward if ((pn = find_person(user.ut_name)) == NULL)
22737664Sedward continue;
22837664Sedward enter_where(&user, pn);
22918606Sedward }
23050613Sbostic if (db)
23150613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) {
23269101Sbostic PERSON *tmp;
23369101Sbostic
23450613Sbostic r = (*db->seq)(db, &key, &data, sflag);
23550613Sbostic if (r == -1)
23669101Sbostic err(1, "db seq");
23750613Sbostic if (r == 1)
23850613Sbostic break;
23969102Sbostic memmove(&tmp, data.data, sizeof tmp);
24069101Sbostic enter_lastlog(tmp);
24150613Sbostic }
2421014Sbill }
243