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