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*44639Sedward static char sccsid[] = "@(#)finger.c 5.22 (Berkeley) 06/29/90"; 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> 3537659Sbostic #include <sys/file.h> 3637629Sbostic #include <stdio.h> 3737659Sbostic #include "finger.h" 381014Sbill 3937659Sbostic time_t now; 4037664Sedward int lflag, sflag, mflag, pplan; 4137659Sbostic char tbuf[1024]; 421014Sbill 4318606Sedward main(argc, argv) 4418606Sedward int argc; 4537659Sbostic char **argv; 4618606Sedward { 4737659Sbostic extern int optind; 4837659Sbostic int ch; 4937659Sbostic time_t time(); 501014Sbill 5137659Sbostic while ((ch = getopt(argc, argv, "lmps")) != EOF) 5237659Sbostic switch(ch) { 5337659Sbostic case 'l': 5437659Sbostic lflag = 1; /* long format */ 5537659Sbostic break; 5637659Sbostic case 'm': 5737659Sbostic mflag = 1; /* force exact match of names */ 5837659Sbostic break; 5937659Sbostic case 'p': 6037659Sbostic pplan = 1; /* don't show .plan/.project */ 6137659Sbostic break; 6237659Sbostic case 's': 6337659Sbostic sflag = 1; /* short format */ 6437659Sbostic break; 6537659Sbostic case '?': 6637659Sbostic default: 6737659Sbostic (void)fprintf(stderr, 6837659Sbostic "usage: finger [-lmps] [login ...]\n"); 6937659Sbostic exit(1); 7037659Sbostic } 7137659Sbostic argc -= optind; 7237659Sbostic argv += optind; 7337659Sbostic 7437659Sbostic (void)time(&now); 7537659Sbostic setpassent(1); 7637659Sbostic if (!*argv) { 7737659Sbostic /* 7837659Sbostic * Assign explicit "small" format if no names given and -l 7937659Sbostic * not selected. Force the -s BEFORE we get names so proper 8037659Sbostic * screening will be done. 8137659Sbostic */ 8237659Sbostic if (!lflag) 8337659Sbostic sflag = 1; /* if -l not explicit, force -s */ 8437659Sbostic loginlist(); 8537664Sedward if (entries == 0) 8637659Sbostic (void)printf("No one logged on.\n"); 8737659Sbostic } else { 8838586Sedward userlist(argc, argv); 8937659Sbostic /* 9037659Sbostic * Assign explicit "large" format if names given and -s not 9137659Sbostic * explicitly stated. Force the -l AFTER we get names so any 9237659Sbostic * remote finger attempts specified won't be mishandled. 9337659Sbostic */ 9437659Sbostic if (!sflag) 9537659Sbostic lflag = 1; /* if -s not explicit, force -l */ 9637659Sbostic } 9737664Sedward if (entries != 0) { 9837659Sbostic if (lflag) 9937659Sbostic lflag_print(); 10037659Sbostic else 10137659Sbostic sflag_print(); 10237659Sbostic } 10318606Sedward exit(0); 10418606Sedward } 1051014Sbill 10637659Sbostic loginlist() 1071014Sbill { 10837659Sbostic register PERSON *pn; 10937659Sbostic struct passwd *pw; 11037664Sedward struct utmp user; 11137664Sedward char name[UT_NAMESIZE + 1]; 1121014Sbill 11338901Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) { 11437659Sbostic (void)fprintf(stderr, "finger: can't read %s.\n", _PATH_UTMP); 11518606Sedward exit(2); 1161014Sbill } 11737659Sbostic name[UT_NAMESIZE] = NULL; 11838901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 11937659Sbostic if (!user.ut_name[0]) 12018606Sedward continue; 12137664Sedward if ((pn = find_person(user.ut_name)) == NULL) { 12237664Sedward bcopy(user.ut_name, name, UT_NAMESIZE); 12337664Sedward if ((pw = getpwnam(name)) == NULL) 12437664Sedward continue; 12537664Sedward pn = enter_person(pw); 1261014Sbill } 12737664Sedward enter_where(&user, pn); 12818606Sedward } 12937664Sedward for (pn = phead; lflag && pn != NULL; pn = pn->next) 13037664Sedward enter_lastlog(pn); 13118606Sedward } 1321014Sbill 13338586Sedward userlist(argc, argv) 13438586Sedward register argc; 13538586Sedward register char **argv; 13618606Sedward { 13738586Sedward register i; 13837664Sedward register PERSON *pn; 139*44639Sedward PERSON *nethead, **nettail; 14037664Sedward struct utmp user; 14137664Sedward struct passwd *pw; 14238586Sedward int dolocal, *used; 14338586Sedward char *index(); 1441014Sbill 14538586Sedward if (!(used = (int *)calloc((u_int)argc, (u_int)sizeof(int)))) { 14638586Sedward (void)fprintf(stderr, "finger: out of space.\n"); 14738586Sedward exit(1); 14838586Sedward } 14938586Sedward 15037659Sbostic /* pull out all network requests */ 151*44639Sedward for (i = 0, dolocal = 0, nettail = &nethead; i < argc; i++) { 15238586Sedward if (!index(argv[i], '@')) { 15337659Sbostic dolocal = 1; 15418606Sedward continue; 15516469Ssam } 15637664Sedward pn = palloc(); 157*44639Sedward *nettail = pn; 158*44639Sedward nettail = &pn->next; 15938586Sedward pn->name = argv[i]; 16038586Sedward used[i] = -1; 16118606Sedward } 162*44639Sedward *nettail = NULL; 16337659Sbostic 16437659Sbostic if (!dolocal) 16537659Sbostic goto net; 16637659Sbostic 16718606Sedward /* 16837659Sbostic * traverse the list of possible login names and check the login name 16937664Sedward * and real name against the name specified by the user. 17018606Sedward */ 17137996Sbostic if (mflag) { 17238586Sedward for (i = 0; i < argc; i++) 17338586Sedward if (used[i] >= 0 && (pw = getpwnam(argv[i]))) { 17437996Sbostic enter_person(pw); 17538586Sedward used[i] = 1; 17637996Sbostic } 17737996Sbostic } else while (pw = getpwent()) 17838586Sedward for (i = 0; i < argc; i++) 17938586Sedward if (used[i] >= 0 && 18038586Sedward (!strcasecmp(pw->pw_name, argv[i]) || 18138586Sedward match(pw, argv[i]))) { 18237996Sbostic enter_person(pw); 18338586Sedward used[i] = 1; 18437996Sbostic } 18537659Sbostic 18637659Sbostic /* list errors */ 18738586Sedward for (i = 0; i < argc; i++) 18838586Sedward if (!used[i]) 18937659Sbostic (void)fprintf(stderr, 19038586Sedward "finger: %s: no such user.\n", argv[i]); 19137659Sbostic 19237659Sbostic /* handle network requests */ 19337659Sbostic net: for (pn = nethead; pn; pn = pn->next) { 19437659Sbostic netfinger(pn->name); 19537659Sbostic if (pn->next || entries) 19637659Sbostic putchar('\n'); 1971014Sbill } 1981014Sbill 19937664Sedward if (entries == 0) 20037659Sbostic return; 2011014Sbill 20218606Sedward /* 20337659Sbostic * Scan thru the list of users currently logged in, saving 20437659Sbostic * appropriate data whenever a match occurs. 20518606Sedward */ 20638901Sbostic if (!freopen(_PATH_UTMP, "r", stdin)) { 20737659Sbostic (void)fprintf( stderr, "finger: can't read %s.\n", _PATH_UTMP); 20837659Sbostic exit(1); 20918606Sedward } 21038901Sbostic while (fread((char *)&user, sizeof(user), 1, stdin) == 1) { 21137659Sbostic if (!user.ut_name[0]) 21218606Sedward continue; 21337664Sedward if ((pn = find_person(user.ut_name)) == NULL) 21437664Sedward continue; 21537664Sedward enter_where(&user, pn); 21618606Sedward } 21737664Sedward for (pn = phead; pn != NULL; pn = pn->next) 21837664Sedward enter_lastlog(pn); 2191014Sbill } 220