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.20 (Berkeley) 06/01/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 #include "pathnames.h" 39 40 time_t now; 41 int lflag, sflag, mflag, pplan; 42 char tbuf[1024]; 43 44 main(argc, argv) 45 int argc; 46 char **argv; 47 { 48 extern int optind; 49 int ch; 50 time_t time(); 51 52 while ((ch = getopt(argc, argv, "lmps")) != EOF) 53 switch(ch) { 54 case 'l': 55 lflag = 1; /* long format */ 56 break; 57 case 'm': 58 mflag = 1; /* force exact match of names */ 59 break; 60 case 'p': 61 pplan = 1; /* don't show .plan/.project */ 62 break; 63 case 's': 64 sflag = 1; /* short format */ 65 break; 66 case '?': 67 default: 68 (void)fprintf(stderr, 69 "usage: finger [-lmps] [login ...]\n"); 70 exit(1); 71 } 72 argc -= optind; 73 argv += optind; 74 75 (void)time(&now); 76 setpassent(1); 77 if (!*argv) { 78 /* 79 * Assign explicit "small" format if no names given and -l 80 * not selected. Force the -s BEFORE we get names so proper 81 * screening will be done. 82 */ 83 if (!lflag) 84 sflag = 1; /* if -l not explicit, force -s */ 85 loginlist(); 86 if (entries == 0) 87 (void)printf("No one logged on.\n"); 88 } else { 89 userlist(argc, argv); 90 /* 91 * Assign explicit "large" format if names given and -s not 92 * explicitly stated. Force the -l AFTER we get names so any 93 * remote finger attempts specified won't be mishandled. 94 */ 95 if (!sflag) 96 lflag = 1; /* if -s not explicit, force -l */ 97 } 98 if (entries != 0) { 99 if (lflag) 100 lflag_print(); 101 else 102 sflag_print(); 103 } 104 exit(0); 105 } 106 107 loginlist() 108 { 109 register PERSON *pn; 110 struct passwd *pw; 111 struct utmp user; 112 char name[UT_NAMESIZE + 1]; 113 114 if (!freopen(_PATH_UTMP, "r", stdin)) { 115 (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); 116 exit(2); 117 } 118 name[UT_NAMESIZE] = NULL; 119 while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 120 if (!user.ut_name[0]) 121 continue; 122 if ((pn = find_person(user.ut_name)) == NULL) { 123 bcopy(user.ut_name, name, UT_NAMESIZE); 124 if ((pw = getpwnam(name)) == NULL) 125 continue; 126 pn = enter_person(pw); 127 } 128 enter_where(&user, pn); 129 } 130 for (pn = phead; lflag && pn != NULL; pn = pn->next) 131 enter_lastlog(pn); 132 } 133 134 userlist(argc, argv) 135 register argc; 136 register char **argv; 137 { 138 register i; 139 register PERSON *pn; 140 PERSON *nethead; 141 struct utmp user; 142 struct passwd *pw; 143 int dolocal, *used; 144 char *index(); 145 146 if (!(used = (int *)calloc((u_int)argc, (u_int)sizeof(int)))) { 147 (void)fprintf(stderr, "finger: out of space.\n"); 148 exit(1); 149 } 150 151 /* pull out all network requests */ 152 for (i = 0, dolocal = 0, nethead = NULL; i < argc; i++) { 153 if (!index(argv[i], '@')) { 154 dolocal = 1; 155 continue; 156 } 157 pn = palloc(); 158 pn->next = nethead; 159 nethead = pn; 160 pn->name = argv[i]; 161 used[i] = -1; 162 } 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