121554Sdist /* 237659Sbostic * Copyright (c) 1989 The Regents of the University of California. 335627Sbostic * All rights reserved. 435627Sbostic * 540027Sbostic * This code is derived from software contributed to Berkeley by 640027Sbostic * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 740027Sbostic * 842731Sbostic * %sccs.include.redist.c% 921554Sdist */ 1021554Sdist 1113619Ssam #ifndef lint 1221554Sdist char copyright[] = 1337659Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 1421554Sdist All rights reserved.\n"; 1535627Sbostic #endif /* not lint */ 161014Sbill 1721554Sdist #ifndef lint 18*50596Sbostic static char sccsid[] = "@(#)finger.c 5.23 (Berkeley) 07/27/91"; 1935627Sbostic #endif /* not lint */ 2021554Sdist 2118606Sedward /* 2237659Sbostic * Finger prints out information about users. It is not portable since 2337659Sbostic * certain fields (e.g. the full user name, office, and phone numbers) are 2437659Sbostic * extracted from the gecos field of the passwd file which other UNIXes 2537659Sbostic * may not have or may use for other things. 261014Sbill * 2737659Sbostic * There are currently two output formats; the short format is one line 2837659Sbostic * per user and displays login name, tty, login time, real name, idle time, 2937659Sbostic * and office location/phone number. The long format gives the same 3037659Sbostic * information (in a more legible format) as well as home directory, shell, 3137659Sbostic * mail info, and .plan/.project files. 321014Sbill */ 331014Sbill 3437659Sbostic #include <sys/param.h> 35*50596Sbostic #include <fcntl.h> 36*50596Sbostic #include <time.h> 37*50596Sbostic #include <pwd.h> 38*50596Sbostic #include <utmp.h> 39*50596Sbostic #include <errno.h> 4037629Sbostic #include <stdio.h> 41*50596Sbostic #include <stdlib.h> 42*50596Sbostic #include <string.h> 4337659Sbostic #include "finger.h" 441014Sbill 4537659Sbostic time_t now; 46*50596Sbostic int entries, lflag, mflag, pplan, sflag; 4737659Sbostic char tbuf[1024]; 48*50596Sbostic PERSON *phead, *ptail, *htab[HSIZE]; 491014Sbill 50*50596Sbostic static void loginlist __P((void)); 51*50596Sbostic static void userlist __P((int, char **)); 52*50596Sbostic 5318606Sedward main(argc, argv) 5418606Sedward int argc; 5537659Sbostic char **argv; 5618606Sedward { 5737659Sbostic int ch; 581014Sbill 5937659Sbostic while ((ch = getopt(argc, argv, "lmps")) != EOF) 6037659Sbostic switch(ch) { 6137659Sbostic case 'l': 6237659Sbostic lflag = 1; /* long format */ 6337659Sbostic break; 6437659Sbostic case 'm': 6537659Sbostic mflag = 1; /* force exact match of names */ 6637659Sbostic break; 6737659Sbostic case 'p': 6837659Sbostic pplan = 1; /* don't show .plan/.project */ 6937659Sbostic break; 7037659Sbostic case 's': 7137659Sbostic sflag = 1; /* short format */ 7237659Sbostic break; 7337659Sbostic case '?': 7437659Sbostic default: 7537659Sbostic (void)fprintf(stderr, 7637659Sbostic "usage: finger [-lmps] [login ...]\n"); 7737659Sbostic exit(1); 7837659Sbostic } 7937659Sbostic argc -= optind; 8037659Sbostic argv += optind; 8137659Sbostic 8237659Sbostic (void)time(&now); 8337659Sbostic setpassent(1); 8437659Sbostic if (!*argv) { 8537659Sbostic /* 8637659Sbostic * Assign explicit "small" format if no names given and -l 8737659Sbostic * not selected. Force the -s BEFORE we get names so proper 8837659Sbostic * screening will be done. 8937659Sbostic */ 9037659Sbostic if (!lflag) 9137659Sbostic sflag = 1; /* if -l not explicit, force -s */ 9237659Sbostic loginlist(); 9337664Sedward if (entries == 0) 9437659Sbostic (void)printf("No one logged on.\n"); 9537659Sbostic } else { 9638586Sedward userlist(argc, argv); 9737659Sbostic /* 9837659Sbostic * Assign explicit "large" format if names given and -s not 9937659Sbostic * explicitly stated. Force the -l AFTER we get names so any 10037659Sbostic * remote finger attempts specified won't be mishandled. 10137659Sbostic */ 10237659Sbostic if (!sflag) 10337659Sbostic lflag = 1; /* if -s not explicit, force -l */ 10437659Sbostic } 10537664Sedward if (entries != 0) { 10637659Sbostic if (lflag) 10737659Sbostic lflag_print(); 10837659Sbostic else 10937659Sbostic sflag_print(); 11037659Sbostic } 11118606Sedward exit(0); 11218606Sedward } 1131014Sbill 114*50596Sbostic static void 11537659Sbostic loginlist() 1161014Sbill { 11737659Sbostic register PERSON *pn; 11837659Sbostic struct passwd *pw; 11937664Sedward struct utmp user; 12037664Sedward char name[UT_NAMESIZE + 1]; 1211014Sbill 122*50596Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) 123*50596Sbostic err("%s: %s", _PATH_UTMP, strerror(errno)); 12437659Sbostic name[UT_NAMESIZE] = NULL; 12538901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 12637659Sbostic if (!user.ut_name[0]) 12718606Sedward continue; 12837664Sedward if ((pn = find_person(user.ut_name)) == NULL) { 12937664Sedward bcopy(user.ut_name, name, UT_NAMESIZE); 13037664Sedward if ((pw = getpwnam(name)) == NULL) 13137664Sedward continue; 13237664Sedward pn = enter_person(pw); 1331014Sbill } 13437664Sedward enter_where(&user, pn); 13518606Sedward } 13637664Sedward for (pn = phead; lflag && pn != NULL; pn = pn->next) 13737664Sedward enter_lastlog(pn); 13818606Sedward } 1391014Sbill 140*50596Sbostic static void 14138586Sedward userlist(argc, argv) 142*50596Sbostic register int argc; 14338586Sedward register char **argv; 14418606Sedward { 145*50596Sbostic register int i; 14637664Sedward register PERSON *pn; 14744639Sedward PERSON *nethead, **nettail; 14837664Sedward struct utmp user; 14937664Sedward struct passwd *pw; 15038586Sedward int dolocal, *used; 1511014Sbill 152*50596Sbostic if (!(used = calloc((u_int)argc, (u_int)sizeof(int)))) 153*50596Sbostic err("%s", strerror(errno)); 15438586Sedward 15537659Sbostic /* pull out all network requests */ 15644639Sedward for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) { 15738586Sedward if (!index(argv[i], '@')) { 15837659Sbostic dolocal = 1; 15918606Sedward continue; 16016469Ssam } 16137664Sedward pn = palloc(); 16244639Sedward *nettail = pn; 16344639Sedward nettail = &pn->next; 16438586Sedward pn->name = argv[i]; 16538586Sedward used[i] = -1; 16618606Sedward } 16744639Sedward *nettail = NULL; 16837659Sbostic 16937659Sbostic if (!dolocal) 17037659Sbostic goto net; 17137659Sbostic 17218606Sedward /* 17337659Sbostic * traverse the list of possible login names and check the login name 17437664Sedward * and real name against the name specified by the user. 17518606Sedward */ 17637996Sbostic if (mflag) { 17738586Sedward for (i = 0; i < argc; i++) 17838586Sedward if (used[i] >= 0 && (pw = getpwnam(argv[i]))) { 17937996Sbostic enter_person(pw); 18038586Sedward used[i] = 1; 18137996Sbostic } 18237996Sbostic } else while (pw = getpwent()) 18338586Sedward for (i = 0; i < argc; i++) 18438586Sedward if (used[i] >= 0 && 18538586Sedward (!strcasecmp(pw->pw_name, argv[i]) || 18638586Sedward match(pw, argv[i]))) { 18737996Sbostic enter_person(pw); 18838586Sedward used[i] = 1; 18937996Sbostic } 19037659Sbostic 19137659Sbostic /* list errors */ 19238586Sedward for (i = 0; i < argc; i++) 19338586Sedward if (!used[i]) 19437659Sbostic (void)fprintf(stderr, 19538586Sedward "finger: %s: no such user.\n", argv[i]); 19637659Sbostic 19737659Sbostic /* handle network requests */ 19837659Sbostic net: for (pn = nethead; pn; pn = pn->next) { 19937659Sbostic netfinger(pn->name); 20037659Sbostic if (pn->next || entries) 20137659Sbostic putchar('\n'); 2021014Sbill } 2031014Sbill 20437664Sedward if (entries == 0) 20537659Sbostic return; 2061014Sbill 20718606Sedward /* 20837659Sbostic * Scan thru the list of users currently logged in, saving 20937659Sbostic * appropriate data whenever a match occurs. 21018606Sedward */ 211*50596Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) 212*50596Sbostic err("%s: %s", _PATH_UTMP, strerror(errno)); 21338901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 21437659Sbostic if (!user.ut_name[0]) 21518606Sedward continue; 21637664Sedward if ((pn = find_person(user.ut_name)) == NULL) 21737664Sedward continue; 21837664Sedward enter_where(&user, pn); 21918606Sedward } 22037664Sedward for (pn = phead; pn != NULL; pn = pn->next) 22137664Sedward enter_lastlog(pn); 2221014Sbill } 223