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