Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.bin / finger / finger.c
blobcad4194c4db725184d5192c06dc8e550244704ad
1 /* $NetBSD: finger.c,v 1.28 2008/07/21 14:19:22 lukem Exp $ */
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
36 * Luke Mewburn <lukem@NetBSD.org> added the following on 961121:
37 * - mail status ("No Mail", "Mail read:...", or "New Mail ...,
38 * Unread since ...".)
39 * - 4 digit phone extensions (3210 is printed as x3210.)
40 * - host/office toggling in short format with -h & -o.
41 * - short day names (`Tue' printed instead of `Jun 21' if the
42 * login time is < 6 days.
45 #include <sys/cdefs.h>
46 #ifndef lint
47 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\
48 The Regents of the University of California. All rights reserved.");
49 #endif /* not lint */
51 #ifndef lint
52 #if 0
53 static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 5/4/95";
54 #else
55 __RCSID("$NetBSD: finger.c,v 1.28 2008/07/21 14:19:22 lukem Exp $");
56 #endif
57 #endif /* not lint */
60 * Finger prints out information about users. It is not portable since
61 * certain fields (e.g. the full user name, office, and phone numbers) are
62 * extracted from the gecos field of the passwd file which other UNIXes
63 * may not have or may use for other things.
65 * There are currently two output formats; the short format is one line
66 * per user and displays login name, tty, login time, real name, idle time,
67 * and either remote host information (default) or office location/phone
68 * number, depending on if -h or -o is used respectively.
69 * The long format gives the same information (in a more legible format) as
70 * well as home directory, shell, mail info, and .plan/.project files.
73 #include <sys/param.h>
75 #include <db.h>
76 #include <err.h>
77 #include <errno.h>
78 #include <fcntl.h>
79 #include <pwd.h>
80 #include <stdio.h>
81 #include <stdlib.h>
82 #include <string.h>
83 #include <time.h>
84 #include <unistd.h>
86 #include <locale.h>
87 #include <langinfo.h>
89 #include "utmpentry.h"
91 #include "finger.h"
92 #include "extern.h"
94 DB *db;
95 time_t now;
96 int entries, gflag, lflag, mflag, oflag, sflag, eightflag, pplan;
97 char tbuf[1024];
98 struct utmpentry *ehead;
100 static void loginlist(void);
101 static void userlist(int, char **);
102 int main(int, char **);
105 main(int argc, char **argv)
107 int ch;
109 /* Allow user's locale settings to affect character output. */
110 setlocale(LC_CTYPE, "");
113 * Reset back to the C locale, unless we are using a known
114 * single-byte 8-bit locale.
116 if (strncmp(nl_langinfo(CODESET), "ISO8859-", 8))
117 setlocale(LC_CTYPE, "C");
119 oflag = 1; /* default to old "office" behavior */
121 while ((ch = getopt(argc, argv, "lmpshog8")) != -1)
122 switch(ch) {
123 case 'l':
124 lflag = 1; /* long format */
125 break;
126 case 'm':
127 mflag = 1; /* force exact match of names */
128 break;
129 case 'p':
130 pplan = 1; /* don't show .plan/.project */
131 break;
132 case 's':
133 sflag = 1; /* short format */
134 break;
135 case 'h':
136 oflag = 0; /* remote host info */
137 break;
138 case 'o':
139 oflag = 1; /* office info */
140 break;
141 case 'g':
142 gflag = 1; /* no gecos info, besides name */
143 break;
144 case '8':
145 eightflag = 1; /* 8-bit pass-through */
146 break;
147 case '?':
148 default:
149 (void)fprintf(stderr,
150 "usage: finger [-lmpshog8] [login ...]\n");
151 exit(1);
153 argc -= optind;
154 argv += optind;
156 (void)time(&now);
157 setpassent(1);
158 entries = getutentries(NULL, &ehead);
159 if (argc == 0) {
161 * Assign explicit "small" format if no names given and -l
162 * not selected. Force the -s BEFORE we get names so proper
163 * screening will be done.
165 if (!lflag)
166 sflag = 1; /* if -l not explicit, force -s */
167 loginlist();
168 if (entries == 0)
169 (void)printf("No one logged on.\n");
170 } else {
171 userlist(argc, argv);
173 * Assign explicit "large" format if names given and -s not
174 * explicitly stated. Force the -l AFTER we get names so any
175 * remote finger attempts specified won't be mishandled.
177 if (!sflag)
178 lflag = 1; /* if -s not explicit, force -l */
180 if (entries) {
181 if (lflag)
182 lflag_print();
183 else
184 sflag_print();
186 return (0);
189 static void
190 loginlist(void)
192 PERSON *pn;
193 DBT data, key;
194 struct passwd *pw;
195 int r, seqflag;
196 struct utmpentry *ep;
198 for (ep = ehead; ep; ep = ep->next) {
199 if ((pn = find_person(ep->name)) == NULL) {
200 if ((pw = getpwnam(ep->name)) == NULL)
201 continue;
202 pn = enter_person(pw);
204 enter_where(ep, pn);
206 if (db && lflag)
207 for (seqflag = R_FIRST;; seqflag = R_NEXT) {
208 PERSON *tmp;
210 r = (*db->seq)(db, &key, &data, seqflag);
211 if (r == -1)
212 err(1, "db seq");
213 if (r == 1)
214 break;
215 memmove(&tmp, data.data, sizeof tmp);
216 enter_lastlog(tmp);
220 static void
221 userlist(int argc, char **argv)
223 PERSON *pn;
224 DBT data, key;
225 struct passwd *pw;
226 int r, seqflag, *used, *ip;
227 char **ap, **nargv, **np, **p;
228 struct utmpentry *ep;
230 if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL ||
231 (used = calloc(argc, sizeof(int))) == NULL)
232 err(1, NULL);
234 /* Pull out all network requests. */
235 for (ap = p = argv, np = nargv; *p; ++p)
236 if (strchr(*p, '@'))
237 *np++ = *p;
238 else
239 *ap++ = *p;
241 *np++ = NULL;
242 *ap++ = NULL;
244 if (!*argv)
245 goto net;
248 * Traverse the list of possible login names and check the login name
249 * and real name against the name specified by the user.
251 if (mflag) {
252 for (p = argv; *p; ++p)
253 if ((pw = getpwnam(*p)) != NULL)
254 enter_person(pw);
255 else
256 warnx("%s: no such user", *p);
257 } else {
258 while ((pw = getpwent()) != NULL)
259 for (p = argv, ip = used; *p; ++p, ++ip)
260 if (match(pw, *p)) {
261 enter_person(pw);
262 *ip = 1;
264 for (p = argv, ip = used; *p; ++p, ++ip)
265 if (!*ip)
266 warnx("%s: no such user", *p);
269 /* Handle network requests. */
270 net:
271 for (p = nargv; *p;)
272 netfinger(*p++);
274 if (entries == 0)
275 goto done;
278 * Scan thru the list of users currently logged in, saving
279 * appropriate data whenever a match occurs.
281 for (ep = ehead; ep; ep = ep->next) {
282 if ((pn = find_person(ep->name)) == NULL)
283 continue;
284 enter_where(ep, pn);
286 if (db != NULL)
287 for (seqflag = R_FIRST;; seqflag = R_NEXT) {
288 PERSON *tmp;
290 r = (*db->seq)(db, &key, &data, seqflag);
291 if (r == -1)
292 err(1, "db seq");
293 if (r == 1)
294 break;
295 memmove(&tmp, data.data, sizeof tmp);
296 enter_lastlog(tmp);
298 done:
299 free(nargv);
300 free(used);