Annotation of src/usr.bin/finger/finger.c, Revision 1.6
1.6 ! millert 1: /* $OpenBSD: finger.c,v 1.5 1997/01/15 23:42:28 millert Exp $ */
1.2 deraadt 2:
1.1 deraadt 3: /*
4: * Copyright (c) 1989 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: */
38:
39: /*
40: * Mail status reporting added 931007 by Luke Mewburn, <zak@rmit.edu.au>.
41: */
42:
43: #ifndef lint
44: char copyright[] =
45: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
46: All rights reserved.\n";
47: #endif /* not lint */
48:
49: #ifndef lint
50: /*static char sccsid[] = "from: @(#)finger.c 5.22 (Berkeley) 6/29/90";*/
1.6 ! millert 51: static char rcsid[] = "$OpenBSD: finger.c,v 1.5 1997/01/15 23:42:28 millert Exp $";
1.1 deraadt 52: #endif /* not lint */
53:
54: /*
55: * Finger prints out information about users. It is not portable since
56: * certain fields (e.g. the full user name, office, and phone numbers) are
57: * extracted from the gecos field of the passwd file which other UNIXes
58: * may not have or may use for other things.
59: *
60: * There are currently two output formats; the short format is one line
61: * per user and displays login name, tty, login time, real name, idle time,
62: * and office location/phone number. The long format gives the same
63: * information (in a more legible format) as well as home directory, shell,
64: * mail info, and .plan/.project files.
65: */
66:
67: #include <sys/param.h>
68: #include <sys/file.h>
69: #include <stdio.h>
70: #include <stdlib.h>
71: #include "finger.h"
72:
73: time_t now;
1.4 downsj 74: int lflag, sflag, mflag, pplan, Mflag;
1.1 deraadt 75: char tbuf[1024];
76:
1.3 deraadt 77: int loginlist __P((void));
78: void userlist __P((int, char **));
79:
80: int
1.1 deraadt 81: main(argc, argv)
82: int argc;
83: char **argv;
84: {
85: extern int optind;
86: int ch;
1.4 downsj 87: char domain[256];
1.1 deraadt 88: time_t time();
89:
1.5 millert 90: while ((ch = getopt(argc, argv, "lmMps")) != -1)
1.1 deraadt 91: switch(ch) {
92: case 'l':
93: lflag = 1; /* long format */
94: break;
95: case 'm':
96: mflag = 1; /* force exact match of names */
97: break;
1.4 downsj 98: case 'M':
99: Mflag = 1; /* allow name matching */
100: break;
1.1 deraadt 101: case 'p':
102: pplan = 1; /* don't show .plan/.project */
103: break;
104: case 's':
105: sflag = 1; /* short format */
106: break;
107: case '?':
108: default:
109: (void)fprintf(stderr,
1.4 downsj 110: "usage: finger [-lmMps] [login ...]\n");
1.1 deraadt 111: exit(1);
112: }
113: argc -= optind;
114: argv += optind;
115:
1.4 downsj 116: /* if a domainname is set, increment mflag. */
117: if ((getdomainname(&domain, sizeof(domain)) == 0) && domain[0])
118: mflag++;
119:
1.1 deraadt 120: (void)time(&now);
121: setpassent(1);
122: if (!*argv) {
123: /*
124: * Assign explicit "small" format if no names given and -l
125: * not selected. Force the -s BEFORE we get names so proper
126: * screening will be done.
127: */
128: if (!lflag)
129: sflag = 1; /* if -l not explicit, force -s */
130: loginlist();
131: if (entries == 0)
132: (void)printf("No one logged on.\n");
133: } else {
134: userlist(argc, argv);
135: /*
136: * Assign explicit "large" format if names given and -s not
137: * explicitly stated. Force the -l AFTER we get names so any
138: * remote finger attempts specified won't be mishandled.
139: */
140: if (!sflag)
141: lflag = 1; /* if -s not explicit, force -l */
142: }
143: if (entries != 0) {
144: if (lflag)
145: lflag_print();
146: else
147: sflag_print();
148: }
149: exit(0);
150: }
151:
1.3 deraadt 152: int
1.1 deraadt 153: loginlist()
154: {
155: register PERSON *pn;
156: struct passwd *pw;
157: struct utmp user;
158: char name[UT_NAMESIZE + 1];
159:
160: if (!freopen(_PATH_UTMP, "r", stdin)) {
161: (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP);
162: exit(2);
163: }
164: name[UT_NAMESIZE] = NULL;
165: while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
166: if (!user.ut_name[0])
167: continue;
168: if ((pn = find_person(user.ut_name)) == NULL) {
169: bcopy(user.ut_name, name, UT_NAMESIZE);
170: if ((pw = getpwnam(name)) == NULL)
171: continue;
172: pn = enter_person(pw);
173: }
174: enter_where(&user, pn);
175: }
176: for (pn = phead; lflag && pn != NULL; pn = pn->next)
177: enter_lastlog(pn);
178: }
179:
1.3 deraadt 180: void
1.1 deraadt 181: userlist(argc, argv)
182: register argc;
183: register char **argv;
184: {
185: register i;
186: register PERSON *pn;
187: PERSON *nethead, **nettail;
188: struct utmp user;
189: struct passwd *pw;
190: int dolocal, *used;
191:
192: if (!(used = (int *)calloc((u_int)argc, (u_int)sizeof(int)))) {
193: (void)fprintf(stderr, "finger: out of space.\n");
194: exit(1);
195: }
196:
197: /* pull out all network requests */
198: for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) {
1.6 ! millert 199: if (!strchr(argv[i], '@')) {
1.1 deraadt 200: dolocal = 1;
201: continue;
202: }
203: pn = palloc();
204: *nettail = pn;
205: nettail = &pn->next;
206: pn->name = argv[i];
207: used[i] = -1;
208: }
209: *nettail = NULL;
210:
211: if (!dolocal)
212: goto net;
213:
214: /*
215: * traverse the list of possible login names and check the login name
216: * and real name against the name specified by the user.
217: */
1.4 downsj 218: if ((mflag - Mflag) > 0) {
1.1 deraadt 219: for (i = 0; i < argc; i++)
220: if (used[i] >= 0 && (pw = getpwnam(argv[i]))) {
221: enter_person(pw);
222: used[i] = 1;
223: }
224: } else while (pw = getpwent())
225: for (i = 0; i < argc; i++)
226: if (used[i] >= 0 &&
227: (!strcasecmp(pw->pw_name, argv[i]) ||
228: match(pw, argv[i]))) {
229: enter_person(pw);
230: used[i] = 1;
231: }
232:
233: /* list errors */
234: for (i = 0; i < argc; i++)
235: if (!used[i])
236: (void)fprintf(stderr,
237: "finger: %s: no such user.\n", argv[i]);
238:
239: /* handle network requests */
240: net: for (pn = nethead; pn; pn = pn->next) {
241: netfinger(pn->name);
242: if (pn->next || entries)
243: putchar('\n');
244: }
245:
246: if (entries == 0)
247: return;
248:
249: /*
250: * Scan thru the list of users currently logged in, saving
251: * appropriate data whenever a match occurs.
252: */
253: if (!freopen(_PATH_UTMP, "r", stdin)) {
254: (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP);
255: exit(1);
256: }
257: while (fread((char *)&user, sizeof(user), 1, stdin) == 1) {
258: if (!user.ut_name[0])
259: continue;
260: if ((pn = find_person(user.ut_name)) == NULL)
261: continue;
262: enter_where(&user, pn);
263: }
264: for (pn = phead; pn != NULL; pn = pn->next)
265: enter_lastlog(pn);
266: }