xref: /csrg-svn/usr.bin/finger/finger.c (revision 69236)
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