121554Sdist /* 237659Sbostic * Copyright (c) 1989 The Regents of the University of California. 335627Sbostic * All rights reserved. 435627Sbostic * 535627Sbostic * Redistribution and use in source and binary forms are permitted 635627Sbostic * provided that the above copyright notice and this paragraph are 735627Sbostic * duplicated in all such forms and that any documentation, 835627Sbostic * advertising materials, and other materials related to such 935627Sbostic * distribution and use acknowledge that the software was developed 1035627Sbostic * by the University of California, Berkeley. The name of the 1135627Sbostic * University may not be used to endorse or promote products derived 1235627Sbostic * from this software without specific prior written permission. 1335627Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1435627Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537659Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621554Sdist */ 1721554Sdist 1813619Ssam #ifndef lint 1921554Sdist char copyright[] = 2037659Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 2121554Sdist All rights reserved.\n"; 2235627Sbostic #endif /* not lint */ 231014Sbill 2421554Sdist #ifndef lint 25*37996Sbostic static char sccsid[] = "@(#)finger.c 5.16 (Berkeley) 05/11/89"; 2635627Sbostic #endif /* not lint */ 2721554Sdist 2818606Sedward /* 2937659Sbostic * Finger prints out information about users. It is not portable since 3037659Sbostic * certain fields (e.g. the full user name, office, and phone numbers) are 3137659Sbostic * extracted from the gecos field of the passwd file which other UNIXes 3237659Sbostic * may not have or may use for other things. 331014Sbill * 3437659Sbostic * There are currently two output formats; the short format is one line 3537659Sbostic * per user and displays login name, tty, login time, real name, idle time, 3637659Sbostic * and office location/phone number. The long format gives the same 3737659Sbostic * information (in a more legible format) as well as home directory, shell, 3837659Sbostic * mail info, and .plan/.project files. 391014Sbill */ 401014Sbill 4137659Sbostic #include <sys/param.h> 4237659Sbostic #include <sys/file.h> 4337629Sbostic #include <stdio.h> 4437659Sbostic #include "finger.h" 4537629Sbostic #include "pathnames.h" 461014Sbill 4737659Sbostic time_t now; 4837664Sedward int lflag, sflag, mflag, pplan; 4937659Sbostic char tbuf[1024]; 501014Sbill 5118606Sedward main(argc, argv) 5218606Sedward int argc; 5337659Sbostic char **argv; 5418606Sedward { 5537659Sbostic extern int optind; 5637659Sbostic int ch; 5737659Sbostic time_t time(); 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 { 9637659Sbostic userlist(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 11437659Sbostic loginlist() 1151014Sbill { 11637659Sbostic register PERSON *pn; 11737659Sbostic register int fd; 11837659Sbostic struct passwd *pw; 11937664Sedward struct utmp user; 12037664Sedward char name[UT_NAMESIZE + 1]; 1211014Sbill 12237659Sbostic if ((fd = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 12337659Sbostic (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); 12418606Sedward exit(2); 1251014Sbill } 12637659Sbostic name[UT_NAMESIZE] = NULL; 12737664Sedward while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) { 12837659Sbostic if (!user.ut_name[0]) 12918606Sedward continue; 13037664Sedward if ((pn = find_person(user.ut_name)) == NULL) { 13137664Sedward bcopy(user.ut_name, name, UT_NAMESIZE); 13237664Sedward if ((pw = getpwnam(name)) == NULL) 13337664Sedward continue; 13437664Sedward pn = enter_person(pw); 1351014Sbill } 13637664Sedward enter_where(&user, pn); 13718606Sedward } 13837659Sbostic (void)close(fd); 13937664Sedward for (pn = phead; lflag && pn != NULL; pn = pn->next) 14037664Sedward enter_lastlog(pn); 14118606Sedward } 1421014Sbill 14337659Sbostic #define ARGIGNORE (char *)0x01 144*37996Sbostic 14537659Sbostic userlist(argv) 14618606Sedward char **argv; 14718606Sedward { 14837664Sedward register char **ap; 14937664Sedward register PERSON *pn; 15037664Sedward PERSON *nethead; 15137664Sedward struct utmp user; 15237664Sedward struct passwd *pw; 153*37996Sbostic int fd, dolocal, *used, *index(); 1541014Sbill 15537659Sbostic /* pull out all network requests */ 156*37996Sbostic for (ap = argv, dolocal = 0, nethead = NULL; *ap; ap++) { 15737664Sedward if (!index(*ap, '@')) { 15837659Sbostic dolocal = 1; 15918606Sedward continue; 16016469Ssam } 16137664Sedward pn = palloc(); 16237659Sbostic pn->next = nethead; 16337659Sbostic nethead = pn; 16437664Sedward pn->name = *ap; 16537664Sedward *ap = ARGIGNORE; 16618606Sedward } 16737659Sbostic 16837659Sbostic if (!dolocal) 16937659Sbostic goto net; 17037659Sbostic 171*37996Sbostic if (!(used = (int *)calloc((u_int)(ap - argv), (u_int)sizeof(int)))) { 172*37996Sbostic (void)fprintf(stderr, "finger: out of space.\n"); 173*37996Sbostic exit(1); 174*37996Sbostic } 175*37996Sbostic 17618606Sedward /* 17737659Sbostic * traverse the list of possible login names and check the login name 17837664Sedward * and real name against the name specified by the user. 17918606Sedward */ 180*37996Sbostic if (mflag) { 181*37996Sbostic for (ap = argv; *ap; ap++) 182*37996Sbostic if (*ap != ARGIGNORE && (pw = getpwnam(*ap))) { 183*37996Sbostic enter_person(pw); 184*37996Sbostic used[ap - argv] = 1; 185*37996Sbostic } 186*37996Sbostic } else while (pw = getpwent()) 187*37996Sbostic for (ap = argv; *ap; ap++) 188*37996Sbostic if (*ap != ARGIGNORE && 189*37996Sbostic (!strcasecmp(pw->pw_name, *ap) || match(pw, *ap))) { 190*37996Sbostic enter_person(pw); 191*37996Sbostic used[ap - argv] = 1; 192*37996Sbostic } 19337659Sbostic 19437659Sbostic /* list errors */ 195*37996Sbostic for (ap = argv; *ap; ap++) 196*37996Sbostic if (*ap != ARGIGNORE && !used[ap - argv]) 19737659Sbostic (void)fprintf(stderr, 19837664Sedward "finger: %s: no such user.\n", *ap); 19937659Sbostic 20037659Sbostic /* handle network requests */ 20137659Sbostic net: for (pn = nethead; pn; pn = pn->next) { 20237659Sbostic netfinger(pn->name); 20337659Sbostic if (pn->next || entries) 20437659Sbostic putchar('\n'); 2051014Sbill } 2061014Sbill 20737664Sedward if (entries == 0) 20837659Sbostic return; 2091014Sbill 21018606Sedward /* 21137659Sbostic * Scan thru the list of users currently logged in, saving 21237659Sbostic * appropriate data whenever a match occurs. 21318606Sedward */ 21437659Sbostic if ((fd = open(_PATH_UTMP, O_RDONLY, 0)) < 0) { 21537659Sbostic (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP); 21637659Sbostic exit(1); 21718606Sedward } 21837659Sbostic while (read(fd, (char *)&user, sizeof(user)) == sizeof(user)) { 21937659Sbostic if (!user.ut_name[0]) 22018606Sedward continue; 22137664Sedward if ((pn = find_person(user.ut_name)) == NULL) 22237664Sedward continue; 22337664Sedward enter_where(&user, pn); 22418606Sedward } 22537659Sbostic (void)close(fd); 22637664Sedward for (pn = phead; pn != NULL; pn = pn->next) 22737664Sedward enter_lastlog(pn); 2281014Sbill } 229