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