121554Sdist /* 237659Sbostic * Copyright (c) 1989 The Regents of the University of California. 335627Sbostic * All rights reserved. 435627Sbostic * 537659Sbostic * This code is derived from software contributed to Berkeley by 637659Sbostic * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 737659Sbostic * 835627Sbostic * Redistribution and use in source and binary forms are permitted 935627Sbostic * provided that the above copyright notice and this paragraph are 1035627Sbostic * duplicated in all such forms and that any documentation, 1135627Sbostic * advertising materials, and other materials related to such 1235627Sbostic * distribution and use acknowledge that the software was developed 1335627Sbostic * by the University of California, Berkeley. The name of the 1435627Sbostic * University may not be used to endorse or promote products derived 1535627Sbostic * from this software without specific prior written permission. 1635627Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1735627Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1837659Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1921554Sdist */ 2021554Sdist 2113619Ssam #ifndef lint 2221554Sdist char copyright[] = 2337659Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 2421554Sdist All rights reserved.\n"; 2535627Sbostic #endif /* not lint */ 261014Sbill 2721554Sdist #ifndef lint 28*37664Sedward static char sccsid[] = "@(#)finger.c 5.14 (Berkeley) 05/07/89"; 2935627Sbostic #endif /* not lint */ 3021554Sdist 3118606Sedward /* 3237659Sbostic * Finger prints out information about users. It is not portable since 3337659Sbostic * certain fields (e.g. the full user name, office, and phone numbers) are 3437659Sbostic * extracted from the gecos field of the passwd file which other UNIXes 3537659Sbostic * may not have or may use for other things. 361014Sbill * 3737659Sbostic * There are currently two output formats; the short format is one line 3837659Sbostic * per user and displays login name, tty, login time, real name, idle time, 3937659Sbostic * and office location/phone number. The long format gives the same 4037659Sbostic * information (in a more legible format) as well as home directory, shell, 4137659Sbostic * mail info, and .plan/.project files. 421014Sbill */ 431014Sbill 4437659Sbostic #include <sys/param.h> 4537659Sbostic #include <sys/file.h> 4637629Sbostic #include <stdio.h> 4737659Sbostic #include "finger.h" 4837629Sbostic #include "pathnames.h" 491014Sbill 5037659Sbostic time_t now; 51*37664Sedward int lflag, sflag, mflag, pplan; 5237659Sbostic char tbuf[1024]; 531014Sbill 5418606Sedward main(argc, argv) 5518606Sedward int argc; 5637659Sbostic char **argv; 5718606Sedward { 5837659Sbostic extern int optind; 5937659Sbostic int ch; 6037659Sbostic time_t time(); 611014Sbill 6237659Sbostic while ((ch = getopt(argc, argv, "lmps")) != EOF) 6337659Sbostic switch(ch) { 6437659Sbostic case 'l': 6537659Sbostic lflag = 1; /* long format */ 6637659Sbostic break; 6737659Sbostic case 'm': 6837659Sbostic mflag = 1; /* force exact match of names */ 6937659Sbostic break; 7037659Sbostic case 'p': 7137659Sbostic pplan = 1; /* don't show .plan/.project */ 7237659Sbostic break; 7337659Sbostic case 's': 7437659Sbostic sflag = 1; /* short format */ 7537659Sbostic break; 7637659Sbostic case '?': 7737659Sbostic default: 7837659Sbostic (void)fprintf(stderr, 7937659Sbostic "usage: finger [-lmps] [login ...]\n"); 8037659Sbostic exit(1); 8137659Sbostic } 8237659Sbostic argc -= optind; 8337659Sbostic argv += optind; 8437659Sbostic 8537659Sbostic (void)time(&now); 8637659Sbostic setpassent(1); 8737659Sbostic if (!*argv) { 8837659Sbostic /* 8937659Sbostic * Assign explicit "small" format if no names given and -l 9037659Sbostic * not selected. Force the -s BEFORE we get names so proper 9137659Sbostic * screening will be done. 9237659Sbostic */ 9337659Sbostic if (!lflag) 9437659Sbostic sflag = 1; /* if -l not explicit, force -s */ 9537659Sbostic loginlist(); 96*37664Sedward if (entries == 0) 9737659Sbostic (void)printf("No one logged on.\n"); 9837659Sbostic } else { 9937659Sbostic userlist(argv); 10037659Sbostic /* 10137659Sbostic * Assign explicit "large" format if names given and -s not 10237659Sbostic * explicitly stated. Force the -l AFTER we get names so any 10337659Sbostic * remote finger attempts specified won't be mishandled. 10437659Sbostic */ 10537659Sbostic if (!sflag) 10637659Sbostic lflag = 1; /* if -s not explicit, force -l */ 10737659Sbostic } 108*37664Sedward if (entries != 0) { 10937659Sbostic if (lflag) 11037659Sbostic lflag_print(); 11137659Sbostic else 11237659Sbostic sflag_print(); 11337659Sbostic } 11418606Sedward exit(0); 11518606Sedward } 1161014Sbill 11737659Sbostic loginlist() 1181014Sbill { 11937659Sbostic register PERSON *pn; 12037659Sbostic register int fd; 12137659Sbostic struct passwd *pw; 122*37664Sedward struct utmp user; 123*37664Sedward char name[UT_NAMESIZE + 1]; 1241014Sbill 12537659Sbostic if ((fd = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 12637659Sbostic (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); 12718606Sedward exit(2); 1281014Sbill } 12937659Sbostic name[UT_NAMESIZE] = NULL; 130*37664Sedward while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) { 13137659Sbostic if (!user.ut_name[0]) 13218606Sedward continue; 133*37664Sedward if ((pn = find_person(user.ut_name)) == NULL) { 134*37664Sedward bcopy(user.ut_name, name, UT_NAMESIZE); 135*37664Sedward if ((pw = getpwnam(name)) == NULL) 136*37664Sedward continue; 137*37664Sedward pn = enter_person(pw); 1381014Sbill } 139*37664Sedward enter_where(&user, pn); 14018606Sedward } 14137659Sbostic (void)close(fd); 142*37664Sedward for (pn = phead; lflag && pn != NULL; pn = pn->next) 143*37664Sedward enter_lastlog(pn); 14418606Sedward } 1451014Sbill 14637659Sbostic #define ARGIGNORE (char *)0x01 14737659Sbostic userlist(argv) 14818606Sedward char **argv; 14918606Sedward { 150*37664Sedward register char **ap; 151*37664Sedward register PERSON *pn; 152*37664Sedward PERSON *nethead; 153*37664Sedward struct utmp user; 154*37664Sedward struct passwd *pw; 155*37664Sedward int fd, dolocal, *index(); 1561014Sbill 15737659Sbostic /* pull out all network requests */ 158*37664Sedward for (ap = argv, dolocal = 0, nethead = NULL; *ap != NULL; ap++) { 159*37664Sedward if (!index(*ap, '@')) { 16037659Sbostic dolocal = 1; 16118606Sedward continue; 16216469Ssam } 163*37664Sedward pn = palloc(); 16437659Sbostic pn->next = nethead; 16537659Sbostic nethead = pn; 166*37664Sedward pn->name = *ap; 167*37664Sedward *ap = ARGIGNORE; 16818606Sedward } 16937659Sbostic 17037659Sbostic if (!dolocal) 17137659Sbostic goto net; 17237659Sbostic 17318606Sedward /* 17437659Sbostic * traverse the list of possible login names and check the login name 175*37664Sedward * and real name against the name specified by the user. 17618606Sedward */ 177*37664Sedward if (mflag) 178*37664Sedward for (ap = argv; *ap != NULL; ap++) { 179*37664Sedward if (*ap == ARGIGNORE) 18018606Sedward continue; 181*37664Sedward if ((pw = getpwnam(*ap)) == NULL) 18218606Sedward continue; 183*37664Sedward enter_person(pw); 184*37664Sedward *ap = ARGIGNORE; 185*37664Sedward } 186*37664Sedward else while (pw = getpwent()) 187*37664Sedward for (ap = argv; *ap != NULL; ap++) { 188*37664Sedward if (*ap == ARGIGNORE) 189*37664Sedward continue; 190*37664Sedward if (strcasecmp(pw->pw_name, *ap) && !match(pw, *ap)) 191*37664Sedward continue; 192*37664Sedward enter_person(pw); 193*37664Sedward *ap = ARGIGNORE; 19437659Sbostic /* don't break, may be listed multiple times */ 1951014Sbill } 19637659Sbostic 19737659Sbostic /* list errors */ 198*37664Sedward for (ap = argv; *ap != NULL; ap++) 199*37664Sedward if (*ap != ARGIGNORE) 20037659Sbostic (void)fprintf(stderr, 201*37664Sedward "finger: %s: no such user.\n", *ap); 20237659Sbostic 20337659Sbostic /* handle network requests */ 20437659Sbostic net: for (pn = nethead; pn; pn = pn->next) { 20537659Sbostic netfinger(pn->name); 20637659Sbostic if (pn->next || entries) 20737659Sbostic putchar('\n'); 2081014Sbill } 2091014Sbill 210*37664Sedward if (entries == 0) 21137659Sbostic return; 2121014Sbill 21318606Sedward /* 21437659Sbostic * Scan thru the list of users currently logged in, saving 21537659Sbostic * appropriate data whenever a match occurs. 21618606Sedward */ 21737659Sbostic if ((fd = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 21837659Sbostic (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP); 21937659Sbostic exit(1); 22018606Sedward } 22137659Sbostic while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) { 22237659Sbostic if (!user.ut_name[0]) 22318606Sedward continue; 224*37664Sedward if ((pn = find_person(user.ut_name)) == NULL) 225*37664Sedward continue; 226*37664Sedward enter_where(&user, pn); 22718606Sedward } 22837659Sbostic (void)close(fd); 229*37664Sedward for (pn = phead; pn != NULL; pn = pn->next) 230*37664Sedward enter_lastlog(pn); 2311014Sbill } 232