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@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.4 1994/12/24 16:33:46 cgd 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 <stdlib.h> 69 #include "finger.h" 70 71 time_t now; 72 int lflag, sflag, mflag, pplan; 73 char tbuf[1024]; 74 75 main(argc, argv) 76 int argc; 77 char **argv; 78 { 79 extern int optind; 80 int ch; 81 time_t time(); 82 83 while ((ch = getopt(argc, argv, "lmps")) != EOF) 84 switch(ch) { 85 case 'l': 86 lflag = 1; /* long format */ 87 break; 88 case 'm': 89 mflag = 1; /* force exact match of names */ 90 break; 91 case 'p': 92 pplan = 1; /* don't show .plan/.project */ 93 break; 94 case 's': 95 sflag = 1; /* short format */ 96 break; 97 case '?': 98 default: 99 (void)fprintf(stderr, 100 "usage: finger [-lmps] [login ...]\n"); 101 exit(1); 102 } 103 argc -= optind; 104 argv += optind; 105 106 (void)time(&now); 107 setpassent(1); 108 if (!*argv) { 109 /* 110 * Assign explicit "small" format if no names given and -l 111 * not selected. Force the -s BEFORE we get names so proper 112 * screening will be done. 113 */ 114 if (!lflag) 115 sflag = 1; /* if -l not explicit, force -s */ 116 loginlist(); 117 if (entries == 0) 118 (void)printf("No one logged on.\n"); 119 } else { 120 userlist(argc, argv); 121 /* 122 * Assign explicit "large" format if names given and -s not 123 * explicitly stated. Force the -l AFTER we get names so any 124 * remote finger attempts specified won't be mishandled. 125 */ 126 if (!sflag) 127 lflag = 1; /* if -s not explicit, force -l */ 128 } 129 if (entries != 0) { 130 if (lflag) 131 lflag_print(); 132 else 133 sflag_print(); 134 } 135 exit(0); 136 } 137 138 loginlist() 139 { 140 register PERSON *pn; 141 struct passwd *pw; 142 struct utmp user; 143 char name[UT_NAMESIZE + 1]; 144 145 if (!freopen(_PATH_UTMP, "r", stdin)) { 146 (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); 147 exit(2); 148 } 149 name[UT_NAMESIZE] = NULL; 150 while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 151 if (!user.ut_name[0]) 152 continue; 153 if ((pn = find_person(user.ut_name)) == NULL) { 154 bcopy(user.ut_name, name, UT_NAMESIZE); 155 if ((pw = getpwnam(name)) == NULL) 156 continue; 157 pn = enter_person(pw); 158 } 159 enter_where(&user, pn); 160 } 161 for (pn = phead; lflag && pn != NULL; pn = pn->next) 162 enter_lastlog(pn); 163 } 164 165 userlist(argc, argv) 166 register argc; 167 register char **argv; 168 { 169 register i; 170 register PERSON *pn; 171 PERSON *nethead, **nettail; 172 struct utmp user; 173 struct passwd *pw; 174 int dolocal, *used; 175 char *index(); 176 177 if (!(used = (int *)calloc((u_int)argc, (u_int)sizeof(int)))) { 178 (void)fprintf(stderr, "finger: out of space.\n"); 179 exit(1); 180 } 181 182 /* pull out all network requests */ 183 for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) { 184 if (!index(argv[i], '@')) { 185 dolocal = 1; 186 continue; 187 } 188 pn = palloc(); 189 *nettail = pn; 190 nettail = &pn->next; 191 pn->name = argv[i]; 192 used[i] = -1; 193 } 194 *nettail = NULL; 195 196 if (!dolocal) 197 goto net; 198 199 /* 200 * traverse the list of possible login names and check the login name 201 * and real name against the name specified by the user. 202 */ 203 if (mflag) { 204 for (i = 0; i < argc; i++) 205 if (used[i] >= 0 && (pw = getpwnam(argv[i]))) { 206 enter_person(pw); 207 used[i] = 1; 208 } 209 } else while (pw = getpwent()) 210 for (i = 0; i < argc; i++) 211 if (used[i] >= 0 && 212 (!strcasecmp(pw->pw_name, argv[i]) || 213 match(pw, argv[i]))) { 214 enter_person(pw); 215 used[i] = 1; 216 } 217 218 /* list errors */ 219 for (i = 0; i < argc; i++) 220 if (!used[i]) 221 (void)fprintf(stderr, 222 "finger: %s: no such user.\n", argv[i]); 223 224 /* handle network requests */ 225 net: for (pn = nethead; pn; pn = pn->next) { 226 netfinger(pn->name); 227 if (pn->next || entries) 228 putchar('\n'); 229 } 230 231 if (entries == 0) 232 return; 233 234 /* 235 * Scan thru the list of users currently logged in, saving 236 * appropriate data whenever a match occurs. 237 */ 238 if (!freopen(_PATH_UTMP, "r", stdin)) { 239 (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP); 240 exit(1); 241 } 242 while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 243 if (!user.ut_name[0]) 244 continue; 245 if ((pn = find_person(user.ut_name)) == NULL) 246 continue; 247 enter_where(&user, pn); 248 } 249 for (pn = phead; pn != NULL; pn = pn->next) 250 enter_lastlog(pn); 251 } 252