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