xref: /csrg-svn/usr.bin/finger/finger.c (revision 37664)
121554Sdist /*
237659Sbostic  * Copyright (c) 1989 The Regents of the University of California.
335627Sbostic  * All rights reserved.
435627Sbostic  *
537659Sbostic  * This code is derived from software contributed to Berkeley by
637659Sbostic  * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
737659Sbostic  *
835627Sbostic  * Redistribution and use in source and binary forms are permitted
935627Sbostic  * provided that the above copyright notice and this paragraph are
1035627Sbostic  * duplicated in all such forms and that any documentation,
1135627Sbostic  * advertising materials, and other materials related to such
1235627Sbostic  * distribution and use acknowledge that the software was developed
1335627Sbostic  * by the University of California, Berkeley.  The name of the
1435627Sbostic  * University may not be used to endorse or promote products derived
1535627Sbostic  * from this software without specific prior written permission.
1635627Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1735627Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1837659Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1921554Sdist  */
2021554Sdist 
2113619Ssam #ifndef lint
2221554Sdist char copyright[] =
2337659Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
2421554Sdist  All rights reserved.\n";
2535627Sbostic #endif /* not lint */
261014Sbill 
2721554Sdist #ifndef lint
28*37664Sedward static char sccsid[] = "@(#)finger.c	5.14 (Berkeley) 05/07/89";
2935627Sbostic #endif /* not lint */
3021554Sdist 
3118606Sedward /*
3237659Sbostic  * Finger prints out information about users.  It is not portable since
3337659Sbostic  * certain fields (e.g. the full user name, office, and phone numbers) are
3437659Sbostic  * extracted from the gecos field of the passwd file which other UNIXes
3537659Sbostic  * may not have or may use for other things.
361014Sbill  *
3737659Sbostic  * There are currently two output formats; the short format is one line
3837659Sbostic  * per user and displays login name, tty, login time, real name, idle time,
3937659Sbostic  * and office location/phone number.  The long format gives the same
4037659Sbostic  * information (in a more legible format) as well as home directory, shell,
4137659Sbostic  * mail info, and .plan/.project files.
421014Sbill  */
431014Sbill 
4437659Sbostic #include <sys/param.h>
4537659Sbostic #include <sys/file.h>
4637629Sbostic #include <stdio.h>
4737659Sbostic #include "finger.h"
4837629Sbostic #include "pathnames.h"
491014Sbill 
5037659Sbostic time_t now;
51*37664Sedward int lflag, sflag, mflag, pplan;
5237659Sbostic char tbuf[1024];
531014Sbill 
5418606Sedward main(argc, argv)
5518606Sedward 	int argc;
5637659Sbostic 	char **argv;
5718606Sedward {
5837659Sbostic 	extern int optind;
5937659Sbostic 	int ch;
6037659Sbostic 	time_t time();
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();
96*37664Sedward 		if (entries == 0)
9737659Sbostic 			(void)printf("No one logged on.\n");
9837659Sbostic 	} else {
9937659Sbostic 		userlist(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 	}
108*37664Sedward 	if (entries != 0) {
10937659Sbostic 		if (lflag)
11037659Sbostic 			lflag_print();
11137659Sbostic 		else
11237659Sbostic 			sflag_print();
11337659Sbostic 	}
11418606Sedward 	exit(0);
11518606Sedward }
1161014Sbill 
11737659Sbostic loginlist()
1181014Sbill {
11937659Sbostic 	register PERSON *pn;
12037659Sbostic 	register int fd;
12137659Sbostic 	struct passwd *pw;
122*37664Sedward 	struct utmp user;
123*37664Sedward 	char name[UT_NAMESIZE + 1];
1241014Sbill 
12537659Sbostic 	if ((fd = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
12637659Sbostic 		(void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP);
12718606Sedward 		exit(2);
1281014Sbill 	}
12937659Sbostic 	name[UT_NAMESIZE] = NULL;
130*37664Sedward 	while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) {
13137659Sbostic 		if (!user.ut_name[0])
13218606Sedward 			continue;
133*37664Sedward 		if ((pn = find_person(user.ut_name)) == NULL) {
134*37664Sedward 			bcopy(user.ut_name, name, UT_NAMESIZE);
135*37664Sedward 			if ((pw = getpwnam(name)) == NULL)
136*37664Sedward 				continue;
137*37664Sedward 			pn = enter_person(pw);
1381014Sbill 		}
139*37664Sedward 		enter_where(&user, pn);
14018606Sedward 	}
14137659Sbostic 	(void)close(fd);
142*37664Sedward 	for (pn = phead; lflag && pn != NULL; pn = pn->next)
143*37664Sedward 		enter_lastlog(pn);
14418606Sedward }
1451014Sbill 
14637659Sbostic #define	ARGIGNORE	(char *)0x01
14737659Sbostic userlist(argv)
14818606Sedward 	char **argv;
14918606Sedward {
150*37664Sedward 	register char **ap;
151*37664Sedward 	register PERSON *pn;
152*37664Sedward 	PERSON *nethead;
153*37664Sedward 	struct utmp user;
154*37664Sedward 	struct passwd *pw;
155*37664Sedward 	int fd, dolocal, *index();
1561014Sbill 
15737659Sbostic 	/* pull out all network requests */
158*37664Sedward 	for (ap = argv, dolocal = 0, nethead = NULL; *ap != NULL; ap++) {
159*37664Sedward 		if (!index(*ap, '@')) {
16037659Sbostic 			dolocal = 1;
16118606Sedward 			continue;
16216469Ssam 		}
163*37664Sedward 		pn = palloc();
16437659Sbostic 		pn->next = nethead;
16537659Sbostic 		nethead = pn;
166*37664Sedward 		pn->name = *ap;
167*37664Sedward 		*ap = ARGIGNORE;
16818606Sedward 	}
16937659Sbostic 
17037659Sbostic 	if (!dolocal)
17137659Sbostic 		goto net;
17237659Sbostic 
17318606Sedward 	/*
17437659Sbostic 	 * traverse the list of possible login names and check the login name
175*37664Sedward 	 * and real name against the name specified by the user.
17618606Sedward 	 */
177*37664Sedward 	if (mflag)
178*37664Sedward 		for (ap = argv; *ap != NULL; ap++) {
179*37664Sedward 			if (*ap == ARGIGNORE)
18018606Sedward 				continue;
181*37664Sedward 			if ((pw = getpwnam(*ap)) == NULL)
18218606Sedward 				continue;
183*37664Sedward 			enter_person(pw);
184*37664Sedward 			*ap = ARGIGNORE;
185*37664Sedward 		}
186*37664Sedward 	else while (pw = getpwent())
187*37664Sedward 		for (ap = argv; *ap != NULL; ap++) {
188*37664Sedward 			if (*ap == ARGIGNORE)
189*37664Sedward 				continue;
190*37664Sedward 			if (strcasecmp(pw->pw_name, *ap) && !match(pw, *ap))
191*37664Sedward 				continue;
192*37664Sedward 			enter_person(pw);
193*37664Sedward 			*ap = ARGIGNORE;
19437659Sbostic 			/* don't break, may be listed multiple times */
1951014Sbill 		}
19637659Sbostic 
19737659Sbostic 	/* list errors */
198*37664Sedward 	for (ap = argv; *ap != NULL; ap++)
199*37664Sedward 		if (*ap != ARGIGNORE)
20037659Sbostic 			(void)fprintf(stderr,
201*37664Sedward 			    "finger: %s: no such user.\n", *ap);
20237659Sbostic 
20337659Sbostic 	/* handle network requests */
20437659Sbostic net:	for (pn = nethead; pn; pn = pn->next) {
20537659Sbostic 		netfinger(pn->name);
20637659Sbostic 		if (pn->next || entries)
20737659Sbostic 			putchar('\n');
2081014Sbill 	}
2091014Sbill 
210*37664Sedward 	if (entries == 0)
21137659Sbostic 		return;
2121014Sbill 
21318606Sedward 	/*
21437659Sbostic 	 * Scan thru the list of users currently logged in, saving
21537659Sbostic 	 * appropriate data whenever a match occurs.
21618606Sedward 	 */
21737659Sbostic 	if ((fd = open(_PATH_UTMP, O_RDONLY, 0)) < 0) {
21837659Sbostic 		(void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP);
21937659Sbostic 		exit(1);
22018606Sedward 	}
22137659Sbostic 	while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) {
22237659Sbostic 		if (!user.ut_name[0])
22318606Sedward 			continue;
224*37664Sedward 		if ((pn = find_person(user.ut_name)) == NULL)
225*37664Sedward 			continue;
226*37664Sedward 		enter_where(&user, pn);
22718606Sedward 	}
22837659Sbostic 	(void)close(fd);
229*37664Sedward 	for (pn = phead; pn != NULL; pn = pn->next)
230*37664Sedward 		enter_lastlog(pn);
2311014Sbill }
232