Commit | Line | Data |
---|---|---|
bcf953e4 WJ |
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 | #ifndef lint | |
38 | char copyright[] = | |
39 | "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ | |
40 | All rights reserved.\n"; | |
41 | #endif /* not lint */ | |
42 | ||
43 | #ifndef lint | |
44 | static char sccsid[] = "@(#)finger.c 5.22 (Berkeley) 6/29/90"; | |
45 | #endif /* not lint */ | |
46 | ||
47 | /* | |
48 | * Finger prints out information about users. It is not portable since | |
49 | * certain fields (e.g. the full user name, office, and phone numbers) are | |
50 | * extracted from the gecos field of the passwd file which other UNIXes | |
51 | * may not have or may use for other things. | |
52 | * | |
53 | * There are currently two output formats; the short format is one line | |
54 | * per user and displays login name, tty, login time, real name, idle time, | |
55 | * and office location/phone number. The long format gives the same | |
56 | * information (in a more legible format) as well as home directory, shell, | |
57 | * mail info, and .plan/.project files. | |
58 | */ | |
59 | ||
60 | #include <sys/param.h> | |
61 | #include <sys/file.h> | |
62 | #include <stdio.h> | |
63 | #include "finger.h" | |
64 | ||
65 | time_t now; | |
66 | int lflag, sflag, mflag, pplan; | |
67 | char tbuf[1024]; | |
68 | ||
69 | main(argc, argv) | |
70 | int argc; | |
71 | char **argv; | |
72 | { | |
73 | extern int optind; | |
74 | int ch; | |
75 | time_t time(); | |
76 | ||
77 | while ((ch = getopt(argc, argv, "lmps")) != EOF) | |
78 | switch(ch) { | |
79 | case 'l': | |
80 | lflag = 1; /* long format */ | |
81 | break; | |
82 | case 'm': | |
83 | mflag = 1; /* force exact match of names */ | |
84 | break; | |
85 | case 'p': | |
86 | pplan = 1; /* don't show .plan/.project */ | |
87 | break; | |
88 | case 's': | |
89 | sflag = 1; /* short format */ | |
90 | break; | |
91 | case '?': | |
92 | default: | |
93 | (void)fprintf(stderr, | |
94 | "usage: finger [-lmps] [login ...]\n"); | |
95 | exit(1); | |
96 | } | |
97 | argc -= optind; | |
98 | argv += optind; | |
99 | ||
100 | (void)time(&now); | |
101 | setpassent(1); | |
102 | if (!*argv) { | |
103 | /* | |
104 | * Assign explicit "small" format if no names given and -l | |
105 | * not selected. Force the -s BEFORE we get names so proper | |
106 | * screening will be done. | |
107 | */ | |
108 | if (!lflag) | |
109 | sflag = 1; /* if -l not explicit, force -s */ | |
110 | loginlist(); | |
111 | if (entries == 0) | |
112 | (void)printf("No one logged on.\n"); | |
113 | } else { | |
114 | userlist(argc, argv); | |
115 | /* | |
116 | * Assign explicit "large" format if names given and -s not | |
117 | * explicitly stated. Force the -l AFTER we get names so any | |
118 | * remote finger attempts specified won't be mishandled. | |
119 | */ | |
120 | if (!sflag) | |
121 | lflag = 1; /* if -s not explicit, force -l */ | |
122 | } | |
123 | if (entries != 0) { | |
124 | if (lflag) | |
125 | lflag_print(); | |
126 | else | |
127 | sflag_print(); | |
128 | } | |
129 | exit(0); | |
130 | } | |
131 | ||
132 | loginlist() | |
133 | { | |
134 | register PERSON *pn; | |
135 | struct passwd *pw; | |
136 | struct utmp user; | |
137 | char name[UT_NAMESIZE + 1]; | |
138 | ||
139 | if (!freopen(_PATH_UTMP, "r", stdin)) { | |
140 | (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); | |
141 | exit(2); | |
142 | } | |
143 | name[UT_NAMESIZE] = NULL; | |
144 | while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { | |
145 | if (!user.ut_name[0]) | |
146 | continue; | |
147 | if ((pn = find_person(user.ut_name)) == NULL) { | |
148 | bcopy(user.ut_name, name, UT_NAMESIZE); | |
149 | if ((pw = getpwnam(name)) == NULL) | |
150 | continue; | |
151 | pn = enter_person(pw); | |
152 | } | |
153 | enter_where(&user, pn); | |
154 | } | |
155 | for (pn = phead; lflag && pn != NULL; pn = pn->next) | |
156 | enter_lastlog(pn); | |
157 | } | |
158 | ||
159 | userlist(argc, argv) | |
160 | register argc; | |
161 | register char **argv; | |
162 | { | |
163 | register i; | |
164 | register PERSON *pn; | |
165 | PERSON *nethead, **nettail; | |
166 | struct utmp user; | |
167 | struct passwd *pw; | |
168 | int dolocal, *used; | |
169 | char *index(); | |
170 | ||
171 | if (!(used = (int *)calloc((u_int)argc, (u_int)sizeof(int)))) { | |
172 | (void)fprintf(stderr, "finger: out of space.\n"); | |
173 | exit(1); | |
174 | } | |
175 | ||
176 | /* pull out all network requests */ | |
177 | for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) { | |
178 | if (!index(argv[i], '@')) { | |
179 | dolocal = 1; | |
180 | continue; | |
181 | } | |
182 | pn = palloc(); | |
183 | *nettail = pn; | |
184 | nettail = &pn->next; | |
185 | pn->name = argv[i]; | |
186 | used[i] = -1; | |
187 | } | |
188 | *nettail = NULL; | |
189 | ||
190 | if (!dolocal) | |
191 | goto net; | |
192 | ||
193 | /* | |
194 | * traverse the list of possible login names and check the login name | |
195 | * and real name against the name specified by the user. | |
196 | */ | |
197 | if (mflag) { | |
198 | for (i = 0; i < argc; i++) | |
199 | if (used[i] >= 0 && (pw = getpwnam(argv[i]))) { | |
200 | enter_person(pw); | |
201 | used[i] = 1; | |
202 | } | |
203 | } else while (pw = getpwent()) | |
204 | for (i = 0; i < argc; i++) | |
205 | if (used[i] >= 0 && | |
206 | (!strcasecmp(pw->pw_name, argv[i]) || | |
207 | match(pw, argv[i]))) { | |
208 | enter_person(pw); | |
209 | used[i] = 1; | |
210 | } | |
211 | ||
212 | /* list errors */ | |
213 | for (i = 0; i < argc; i++) | |
214 | if (!used[i]) | |
215 | (void)fprintf(stderr, | |
216 | "finger: %s: no such user.\n", argv[i]); | |
217 | ||
218 | /* handle network requests */ | |
219 | net: for (pn = nethead; pn; pn = pn->next) { | |
220 | netfinger(pn->name); | |
221 | if (pn->next || entries) | |
222 | putchar('\n'); | |
223 | } | |
224 | ||
225 | if (entries == 0) | |
226 | return; | |
227 | ||
228 | /* | |
229 | * Scan thru the list of users currently logged in, saving | |
230 | * appropriate data whenever a match occurs. | |
231 | */ | |
232 | if (!freopen(_PATH_UTMP, "r", stdin)) { | |
233 | (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP); | |
234 | exit(1); | |
235 | } | |
236 | while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { | |
237 | if (!user.ut_name[0]) | |
238 | continue; | |
239 | if ((pn = find_person(user.ut_name)) == NULL) | |
240 | continue; | |
241 | enter_where(&user, pn); | |
242 | } | |
243 | for (pn = phead; pn != NULL; pn = pn->next) | |
244 | enter_lastlog(pn); | |
245 | } |