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. 7: * 8: * Redistribution and use in source and binary forms are permitted 9: * provided that the above copyright notice and this paragraph are 10: * duplicated in all such forms and that any documentation, 11: * advertising materials, and other materials related to such 12: * distribution and use acknowledge that the software was developed 13: * by the University of California, Berkeley. The name of the 14: * University may not be used to endorse or promote products derived 15: * from this software without specific prior written permission. 16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19: */ 20: 21: #ifndef lint 22: char copyright[] = 23: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 24: All rights reserved.\n"; 25: #endif /* not lint */ 26: 27: #ifndef lint 28: static char sccsid[] = "@(#)finger.c 5.19 (Berkeley) 2/7/90"; 29: #endif /* not lint */ 30: 31: /* 32: * Finger prints out information about users. It is not portable since 33: * certain fields (e.g. the full user name, office, and phone numbers) are 34: * extracted from the gecos field of the passwd file which other UNIXes 35: * may not have or may use for other things. 36: * 37: * There are currently two output formats; the short format is one line 38: * per user and displays login name, tty, login time, real name, idle time, 39: * and office location/phone number. The long format gives the same 40: * information (in a more legible format) as well as home directory, shell, 41: * mail info, and .plan/.project files. 42: */ 43: 44: #include <sys/param.h> 45: #include <sys/file.h> 46: #include <stdio.h> 47: #include "finger.h" 48: #include "pathnames.h" 49: 50: time_t now; 51: int lflag, sflag, mflag, pplan; 52: char tbuf[1024]; 53: 54: main(argc, argv) 55: int argc; 56: char **argv; 57: { 58: extern int optind; 59: int ch; 60: time_t time(); 61: 62: while ((ch = getopt(argc, argv, "lmps")) != EOF) 63: switch(ch) { 64: case 'l': 65: lflag = 1; /* long format */ 66: break; 67: case 'm': 68: mflag = 1; /* force exact match of names */ 69: break; 70: case 'p': 71: pplan = 1; /* don't show .plan/.project */ 72: break; 73: case 's': 74: sflag = 1; /* short format */ 75: break; 76: case '?': 77: default: 78: (void)fprintf(stderr, 79: "usage: finger [-lmps] [login ...]\n"); 80: exit(1); 81: } 82: argc -= optind; 83: argv += optind; 84: 85: (void)time(&now); 86: setpassent(1); 87: if (!*argv) { 88: /* 89: * Assign explicit "small" format if no names given and -l 90: * not selected. Force the -s BEFORE we get names so proper 91: * screening will be done. 92: */ 93: if (!lflag) 94: sflag = 1; /* if -l not explicit, force -s */ 95: loginlist(); 96: if (entries == 0) 97: (void)printf("No one logged on.\n"); 98: } else { 99: userlist(argc, argv); 100: /* 101: * Assign explicit "large" format if names given and -s not 102: * explicitly stated. Force the -l AFTER we get names so any 103: * remote finger attempts specified won't be mishandled. 104: */ 105: if (!sflag) 106: lflag = 1; /* if -s not explicit, force -l */ 107: } 108: if (entries != 0) { 109: if (lflag) 110: lflag_print(); 111: else 112: sflag_print(); 113: } 114: exit(0); 115: } 116: 117: loginlist() 118: { 119: register PERSON *pn; 120: struct passwd *pw; 121: struct utmp user; 122: char name[UT_NAMESIZE + 1]; 123: 124: if (!freopen(_PATH_UTMP, "r", stdin)) { 125: (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); 126: exit(2); 127: } 128: name[UT_NAMESIZE] = NULL; 129: while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 130: if (!user.ut_name[0]) 131: continue; 132: if ((pn = find_person(user.ut_name)) == NULL) { 133: bcopy(user.ut_name, name, UT_NAMESIZE); 134: if ((pw = getpwnam(name)) == NULL) 135: continue; 136: pn = enter_person(pw); 137: } 138: enter_where(&user, pn); 139: } 140: for (pn = phead; lflag && pn != NULL; pn = pn->next) 141: enter_lastlog(pn); 142: } 143: 144: userlist(argc, argv) 145: register argc; 146: register char **argv; 147: { 148: register i; 149: register PERSON *pn; 150: PERSON *nethead; 151: struct utmp user; 152: struct passwd *pw; 153: int dolocal, *used; 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 (!freopen(_PATH_UTMP, "r", stdin)) { 217: (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP); 218: exit(1); 219: } 220: while (fread((char *)&user, sizeof(user), 1, stdin) == 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: for (pn = phead; pn != NULL; pn = pn->next) 228: enter_lastlog(pn); 229: }