xref: /csrg-svn/usr.bin/finger/finger.c (revision 50596)
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*50596Sbostic static char sccsid[] = "@(#)finger.c	5.23 (Berkeley) 07/27/91";
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*50596Sbostic #include <fcntl.h>
36*50596Sbostic #include <time.h>
37*50596Sbostic #include <pwd.h>
38*50596Sbostic #include <utmp.h>
39*50596Sbostic #include <errno.h>
4037629Sbostic #include <stdio.h>
41*50596Sbostic #include <stdlib.h>
42*50596Sbostic #include <string.h>
4337659Sbostic #include "finger.h"
441014Sbill 
4537659Sbostic time_t now;
46*50596Sbostic int entries, lflag, mflag, pplan, sflag;
4737659Sbostic char tbuf[1024];
48*50596Sbostic PERSON *phead, *ptail, *htab[HSIZE];
491014Sbill 
50*50596Sbostic static void loginlist __P((void));
51*50596Sbostic static void userlist __P((int, char **));
52*50596Sbostic 
5318606Sedward main(argc, argv)
5418606Sedward 	int argc;
5537659Sbostic 	char **argv;
5618606Sedward {
5737659Sbostic 	int ch;
581014Sbill 
5937659Sbostic 	while ((ch = getopt(argc, argv, "lmps")) != EOF)
6037659Sbostic 		switch(ch) {
6137659Sbostic 		case 'l':
6237659Sbostic 			lflag = 1;		/* long format */
6337659Sbostic 			break;
6437659Sbostic 		case 'm':
6537659Sbostic 			mflag = 1;		/* force exact match of names */
6637659Sbostic 			break;
6737659Sbostic 		case 'p':
6837659Sbostic 			pplan = 1;		/* don't show .plan/.project */
6937659Sbostic 			break;
7037659Sbostic 		case 's':
7137659Sbostic 			sflag = 1;		/* short format */
7237659Sbostic 			break;
7337659Sbostic 		case '?':
7437659Sbostic 		default:
7537659Sbostic 			(void)fprintf(stderr,
7637659Sbostic 			    "usage: finger [-lmps] [login ...]\n");
7737659Sbostic 			exit(1);
7837659Sbostic 		}
7937659Sbostic 	argc -= optind;
8037659Sbostic 	argv += optind;
8137659Sbostic 
8237659Sbostic 	(void)time(&now);
8337659Sbostic 	setpassent(1);
8437659Sbostic 	if (!*argv) {
8537659Sbostic 		/*
8637659Sbostic 		 * Assign explicit "small" format if no names given and -l
8737659Sbostic 		 * not selected.  Force the -s BEFORE we get names so proper
8837659Sbostic 		 * screening will be done.
8937659Sbostic 		 */
9037659Sbostic 		if (!lflag)
9137659Sbostic 			sflag = 1;	/* if -l not explicit, force -s */
9237659Sbostic 		loginlist();
9337664Sedward 		if (entries == 0)
9437659Sbostic 			(void)printf("No one logged on.\n");
9537659Sbostic 	} else {
9638586Sedward 		userlist(argc, argv);
9737659Sbostic 		/*
9837659Sbostic 		 * Assign explicit "large" format if names given and -s not
9937659Sbostic 		 * explicitly stated.  Force the -l AFTER we get names so any
10037659Sbostic 		 * remote finger attempts specified won't be mishandled.
10137659Sbostic 		 */
10237659Sbostic 		if (!sflag)
10337659Sbostic 			lflag = 1;	/* if -s not explicit, force -l */
10437659Sbostic 	}
10537664Sedward 	if (entries != 0) {
10637659Sbostic 		if (lflag)
10737659Sbostic 			lflag_print();
10837659Sbostic 		else
10937659Sbostic 			sflag_print();
11037659Sbostic 	}
11118606Sedward 	exit(0);
11218606Sedward }
1131014Sbill 
114*50596Sbostic static void
11537659Sbostic loginlist()
1161014Sbill {
11737659Sbostic 	register PERSON *pn;
11837659Sbostic 	struct passwd *pw;
11937664Sedward 	struct utmp user;
12037664Sedward 	char name[UT_NAMESIZE + 1];
1211014Sbill 
122*50596Sbostic 	if (!freopen(_PATH_UTMP, "r", stdin))
123*50596Sbostic 		err("%s: %s", _PATH_UTMP, strerror(errno));
12437659Sbostic 	name[UT_NAMESIZE] = NULL;
12538901Sbostic 	while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
12637659Sbostic 		if (!user.ut_name[0])
12718606Sedward 			continue;
12837664Sedward 		if ((pn = find_person(user.ut_name)) == NULL) {
12937664Sedward 			bcopy(user.ut_name, name, UT_NAMESIZE);
13037664Sedward 			if ((pw = getpwnam(name)) == NULL)
13137664Sedward 				continue;
13237664Sedward 			pn = enter_person(pw);
1331014Sbill 		}
13437664Sedward 		enter_where(&user, pn);
13518606Sedward 	}
13637664Sedward 	for (pn = phead; lflag && pn != NULL; pn = pn->next)
13737664Sedward 		enter_lastlog(pn);
13818606Sedward }
1391014Sbill 
140*50596Sbostic static void
14138586Sedward userlist(argc, argv)
142*50596Sbostic 	register int argc;
14338586Sedward 	register char **argv;
14418606Sedward {
145*50596Sbostic 	register int i;
14637664Sedward 	register PERSON *pn;
14744639Sedward 	PERSON *nethead, **nettail;
14837664Sedward 	struct utmp user;
14937664Sedward 	struct passwd *pw;
15038586Sedward 	int dolocal, *used;
1511014Sbill 
152*50596Sbostic 	if (!(used = calloc((u_int)argc, (u_int)sizeof(int))))
153*50596Sbostic 		err("%s", strerror(errno));
15438586Sedward 
15537659Sbostic 	/* pull out all network requests */
15644639Sedward 	for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) {
15738586Sedward 		if (!index(argv[i], '@')) {
15837659Sbostic 			dolocal = 1;
15918606Sedward 			continue;
16016469Ssam 		}
16137664Sedward 		pn = palloc();
16244639Sedward 		*nettail = pn;
16344639Sedward 		nettail = &pn->next;
16438586Sedward 		pn->name = argv[i];
16538586Sedward 		used[i] = -1;
16618606Sedward 	}
16744639Sedward 	*nettail = NULL;
16837659Sbostic 
16937659Sbostic 	if (!dolocal)
17037659Sbostic 		goto net;
17137659Sbostic 
17218606Sedward 	/*
17337659Sbostic 	 * traverse the list of possible login names and check the login name
17437664Sedward 	 * and real name against the name specified by the user.
17518606Sedward 	 */
17637996Sbostic 	if (mflag) {
17738586Sedward 		for (i = 0; i < argc; i++)
17838586Sedward 			if (used[i] >= 0 && (pw = getpwnam(argv[i]))) {
17937996Sbostic 				enter_person(pw);
18038586Sedward 				used[i] = 1;
18137996Sbostic 			}
18237996Sbostic 	} else while (pw = getpwent())
18338586Sedward 		for (i = 0; i < argc; i++)
18438586Sedward 			if (used[i] >= 0 &&
18538586Sedward 			    (!strcasecmp(pw->pw_name, argv[i]) ||
18638586Sedward 			    match(pw, argv[i]))) {
18737996Sbostic 				enter_person(pw);
18838586Sedward 				used[i] = 1;
18937996Sbostic 			}
19037659Sbostic 
19137659Sbostic 	/* list errors */
19238586Sedward 	for (i = 0; i < argc; i++)
19338586Sedward 		if (!used[i])
19437659Sbostic 			(void)fprintf(stderr,
19538586Sedward 			    "finger: %s: no such user.\n", argv[i]);
19637659Sbostic 
19737659Sbostic 	/* handle network requests */
19837659Sbostic net:	for (pn = nethead; pn; pn = pn->next) {
19937659Sbostic 		netfinger(pn->name);
20037659Sbostic 		if (pn->next || entries)
20137659Sbostic 			putchar('\n');
2021014Sbill 	}
2031014Sbill 
20437664Sedward 	if (entries == 0)
20537659Sbostic 		return;
2061014Sbill 
20718606Sedward 	/*
20837659Sbostic 	 * Scan thru the list of users currently logged in, saving
20937659Sbostic 	 * appropriate data whenever a match occurs.
21018606Sedward 	 */
211*50596Sbostic 	if (!freopen(_PATH_UTMP, "r", stdin))
212*50596Sbostic 		err("%s: %s", _PATH_UTMP, strerror(errno));
21338901Sbostic 	while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
21437659Sbostic 		if (!user.ut_name[0])
21518606Sedward 			continue;
21637664Sedward 		if ((pn = find_person(user.ut_name)) == NULL)
21737664Sedward 			continue;
21837664Sedward 		enter_where(&user, pn);
21918606Sedward 	}
22037664Sedward 	for (pn = phead; pn != NULL; pn = pn->next)
22137664Sedward 		enter_lastlog(pn);
2221014Sbill }
223