1 /* $NetBSD: finger.c,v 1.21 2002/09/12 01:31:41 kim Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. 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 * Luke Mewburn <lukem@netbsd.org> added the following on 961121: 41 * - mail status ("No Mail", "Mail read:...", or "New Mail ..., 42 * Unread since ...".) 43 * - 4 digit phone extensions (3210 is printed as x3210.) 44 * - host/office toggling in short format with -h & -o. 45 * - short day names (`Tue' printed instead of `Jun 21' if the 46 * login time is < 6 days. 47 */ 48 49 #include <sys/cdefs.h> 50 #ifndef lint 51 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ 52 The Regents of the University of California. All rights reserved.\n"); 53 #endif /* not lint */ 54 55 #ifndef lint 56 #if 0 57 static char sccsid[] = "@(#)finger.c 8.5 (Berkeley) 5/4/95"; 58 #else 59 __RCSID("$NetBSD: finger.c,v 1.21 2002/09/12 01:31:41 kim Exp $"); 60 #endif 61 #endif /* not lint */ 62 63 /* 64 * Finger prints out information about users. It is not portable since 65 * certain fields (e.g. the full user name, office, and phone numbers) are 66 * extracted from the gecos field of the passwd file which other UNIXes 67 * may not have or may use for other things. 68 * 69 * There are currently two output formats; the short format is one line 70 * per user and displays login name, tty, login time, real name, idle time, 71 * and either remote host information (default) or office location/phone 72 * number, depending on if -h or -o is used respectively. 73 * The long format gives the same information (in a more legible format) as 74 * well as home directory, shell, mail info, and .plan/.project files. 75 */ 76 77 #include <sys/param.h> 78 79 #include <db.h> 80 #include <err.h> 81 #include <errno.h> 82 #include <fcntl.h> 83 #include <pwd.h> 84 #include <stdio.h> 85 #include <stdlib.h> 86 #include <string.h> 87 #include <time.h> 88 #include <unistd.h> 89 90 #include <locale.h> 91 #include <langinfo.h> 92 93 #include "utmpentry.h" 94 95 #include "finger.h" 96 #include "extern.h" 97 98 DB *db; 99 time_t now; 100 int entries, gflag, lflag, mflag, oflag, sflag, eightflag, pplan; 101 char tbuf[1024]; 102 struct utmpentry *ehead; 103 104 static void loginlist __P((void)); 105 static void userlist __P((int, char **)); 106 int main __P((int, char **)); 107 108 int 109 main(argc, argv) 110 int argc; 111 char **argv; 112 { 113 int ch; 114 115 /* Allow user's locale settings to affect character output. */ 116 (void *) setlocale(LC_CTYPE, ""); 117 118 /* 119 * Reset back to the C locale, unless we are using a known 120 * single-byte 8-bit locale. 121 */ 122 if (strncmp(nl_langinfo(CODESET), "ISO8859-", 8)) 123 (void *) setlocale(LC_CTYPE, "C"); 124 125 oflag = 1; /* default to old "office" behavior */ 126 127 while ((ch = getopt(argc, argv, "lmpshog8")) != -1) 128 switch(ch) { 129 case 'l': 130 lflag = 1; /* long format */ 131 break; 132 case 'm': 133 mflag = 1; /* force exact match of names */ 134 break; 135 case 'p': 136 pplan = 1; /* don't show .plan/.project */ 137 break; 138 case 's': 139 sflag = 1; /* short format */ 140 break; 141 case 'h': 142 oflag = 0; /* remote host info */ 143 break; 144 case 'o': 145 oflag = 1; /* office info */ 146 break; 147 case 'g': 148 gflag = 1; /* no gecos info, besides name */ 149 break; 150 case '8': 151 eightflag = 1; /* 8-bit pass-through */ 152 break; 153 case '?': 154 default: 155 (void)fprintf(stderr, 156 "usage: finger [-lmpshog8] [login ...]\n"); 157 exit(1); 158 } 159 argc -= optind; 160 argv += optind; 161 162 (void)time(&now); 163 setpassent(1); 164 entries = getutentries(NULL, &ehead); 165 if (argc == 0) { 166 /* 167 * Assign explicit "small" format if no names given and -l 168 * not selected. Force the -s BEFORE we get names so proper 169 * screening will be done. 170 */ 171 if (!lflag) 172 sflag = 1; /* if -l not explicit, force -s */ 173 loginlist(); 174 if (entries == 0) 175 (void)printf("No one logged on.\n"); 176 } else { 177 userlist(argc, argv); 178 /* 179 * Assign explicit "large" format if names given and -s not 180 * explicitly stated. Force the -l AFTER we get names so any 181 * remote finger attempts specified won't be mishandled. 182 */ 183 if (!sflag) 184 lflag = 1; /* if -s not explicit, force -l */ 185 } 186 if (entries) { 187 if (lflag) 188 lflag_print(); 189 else 190 sflag_print(); 191 } 192 return (0); 193 } 194 195 static void 196 loginlist() 197 { 198 PERSON *pn; 199 DBT data, key; 200 struct passwd *pw; 201 int r, sflag; 202 struct utmpentry *ep; 203 204 for (ep = ehead; ep; ep = ep->next) { 205 if ((pn = find_person(ep->name)) == NULL) { 206 if ((pw = getpwnam(ep->name)) == NULL) 207 continue; 208 pn = enter_person(pw); 209 } 210 enter_where(ep, pn); 211 } 212 if (db && lflag) 213 for (sflag = R_FIRST;; sflag = R_NEXT) { 214 PERSON *tmp; 215 216 r = (*db->seq)(db, &key, &data, sflag); 217 if (r == -1) 218 err(1, "db seq"); 219 if (r == 1) 220 break; 221 memmove(&tmp, data.data, sizeof tmp); 222 enter_lastlog(tmp); 223 } 224 } 225 226 static void 227 userlist(argc, argv) 228 int argc; 229 char **argv; 230 { 231 register PERSON *pn; 232 DBT data, key; 233 struct passwd *pw; 234 int r, sflag, *used, *ip; 235 char **ap, **nargv, **np, **p; 236 struct utmpentry *ep; 237 238 if ((nargv = malloc((argc+1) * sizeof(char *))) == NULL || 239 (used = calloc(argc, sizeof(int))) == NULL) 240 err(1, NULL); 241 242 /* Pull out all network requests. */ 243 for (ap = p = argv, np = nargv; *p; ++p) 244 if (strchr(*p, '@')) 245 *np++ = *p; 246 else 247 *ap++ = *p; 248 249 *np++ = NULL; 250 *ap++ = NULL; 251 252 if (!*argv) 253 goto net; 254 255 /* 256 * Traverse the list of possible login names and check the login name 257 * and real name against the name specified by the user. 258 */ 259 if (mflag) { 260 for (p = argv; *p; ++p) 261 if ((pw = getpwnam(*p)) != NULL) 262 enter_person(pw); 263 else 264 (void)fprintf(stderr, 265 "finger: %s: no such user\n", *p); 266 } else { 267 while ((pw = getpwent()) != NULL) 268 for (p = argv, ip = used; *p; ++p, ++ip) 269 if (match(pw, *p)) { 270 enter_person(pw); 271 *ip = 1; 272 } 273 for (p = argv, ip = used; *p; ++p, ++ip) 274 if (!*ip) 275 (void)fprintf(stderr, 276 "finger: %s: no such user\n", *p); 277 } 278 279 /* Handle network requests. */ 280 net: 281 for (p = nargv; *p;) 282 netfinger(*p++); 283 284 if (entries == 0) 285 return; 286 287 /* 288 * Scan thru the list of users currently logged in, saving 289 * appropriate data whenever a match occurs. 290 */ 291 for (ep = ehead; ep; ep = ep->next) { 292 if ((pn = find_person(ep->name)) == NULL) 293 continue; 294 enter_where(ep, pn); 295 } 296 if (db != NULL) 297 for (sflag = R_FIRST;; sflag = R_NEXT) { 298 PERSON *tmp; 299 300 r = (*db->seq)(db, &key, &data, sflag); 301 if (r == -1) 302 err(1, "db seq"); 303 if (r == 1) 304 break; 305 memmove(&tmp, data.data, sizeof tmp); 306 enter_lastlog(tmp); 307 } 308 } 309 310