113619Ssam #ifndef lint 2*16469Ssam static char *sccsid = "@(#)finger.c 4.6 (Berkeley) 05/11/84"; 313619Ssam #endif 41014Sbill 51014Sbill /* This is a finger program. It prints out useful information about users 61014Sbill * by digging it up from various system files. It is not very portable 71014Sbill * because the most useful parts of the information (the full user name, 81014Sbill * office, and phone numbers) are all stored in the VAX-unused gecos field 91014Sbill * of /etc/passwd, which, unfortunately, other UNIXes use for other things. 101014Sbill * 111014Sbill * There are three output formats, all of which give login name, teletype 121014Sbill * line number, and login time. The short output format is reminiscent 131014Sbill * of finger on ITS, and gives one line of information per user containing 141014Sbill * in addition to the minimum basic requirements (MBR), the full name of 151014Sbill * the user, his idle time and office location and phone number. The 161014Sbill * quick style output is UNIX who-like, giving only name, teletype and 171014Sbill * login time. Finally, the long style output give the same information 181014Sbill * as the short (in more legible format), the home directory and shell 191014Sbill * of the user, and, if it exits, a copy of the file .plan in the users 201014Sbill * home directory. Finger may be called with or without a list of people 211014Sbill * to finger -- if no list is given, all the people currently logged in 221014Sbill * are fingered. 231014Sbill * 241014Sbill * The program is validly called by one of the following: 251014Sbill * 261014Sbill * finger {short form list of users} 271014Sbill * finger -l {long form list of users} 281014Sbill * finger -b {briefer long form list of users} 291014Sbill * finger -q {quick list of users} 301014Sbill * finger -i {quick list of users with idle times} 311014Sbill * finger namelist {long format list of specified users} 321014Sbill * finger -s namelist {short format list of specified users} 331014Sbill * finger -w namelist {narrow short format list of specified users} 341014Sbill * 351014Sbill * where 'namelist' is a list of users login names. 361014Sbill * The other options can all be given after one '-', or each can have its 371014Sbill * own '-'. The -f option disables the printing of headers for short and 381014Sbill * quick outputs. The -b option briefens long format outputs. The -p 391014Sbill * option turns off plans for long format outputs. 401014Sbill */ 411014Sbill 421014Sbill #include <sys/types.h> 431014Sbill #include <sys/stat.h> 441014Sbill #include <sgtty.h> 451014Sbill #include <utmp.h> 461014Sbill #include <signal.h> 471014Sbill #include <pwd.h> 481014Sbill #include <stdio.h> 491014Sbill #include <lastlog.h> 5013619Ssam #include <sys/time.h> 51*16469Ssam #include <sys/socket.h> 52*16469Ssam #include <netinet/in.h> 53*16469Ssam #include <netdb.h> 541014Sbill 551014Sbill struct utmp utmp; /* for sizeof */ 561014Sbill #define NMAX sizeof(utmp.ut_name) 571014Sbill #define LMAX sizeof(utmp.ut_line) 581014Sbill 591014Sbill #define ASTERISK '*' /* ignore this in real name */ 601014Sbill #define BLANK ' ' /* blank character (i.e. space) */ 611014Sbill #define CAPITALIZE 0137& /* capitalize character macro */ 621014Sbill #define COMMA ',' /* separator in pw_gecos field */ 631014Sbill #define COMMAND '-' /* command line flag char */ 641014Sbill #define CORY 'C' /* cory hall office */ 651014Sbill #define EVANS 'E' /* evans hall office */ 661014Sbill #define LINEBREAK 012 /* line feed */ 671014Sbill #define NULLSTR "" /* the null string, opposed to NULL */ 681014Sbill #define SAMENAME '&' /* repeat login name in real name */ 691014Sbill #define TALKABLE 0222 /* tty is writeable if 222 mode */ 701014Sbill 711014Sbill struct person { /* one for each person fingered */ 721014Sbill char name[NMAX+1]; /* login name */ 731014Sbill char tty[LMAX+1]; /* NULL terminated tty line */ 741014Sbill long loginat; /* time of login (possibly last) */ 751014Sbill long idletime; /* how long idle (if logged in) */ 761014Sbill short int loggedin; /* flag for being logged in */ 771014Sbill short int writeable; /* flag for tty being writeable */ 781014Sbill char *realname; /* pointer to full name */ 791014Sbill char *office; /* pointer to office name */ 801014Sbill char *officephone; /* pointer to office phone no. */ 811014Sbill char *homephone; /* pointer to home phone no. */ 821014Sbill char *random; /* for any random stuff in pw_gecos */ 831014Sbill struct passwd *pwd; /* structure of /etc/passwd stuff */ 841014Sbill struct person *link; /* link to next person */ 851014Sbill }; 861014Sbill 871014Sbill struct passwd *NILPWD = 0; 881014Sbill struct person *NILPERS = 0; 891014Sbill 901014Sbill int persize = sizeof( struct person ); 911014Sbill int pwdsize = sizeof( struct passwd ); 921014Sbill 931014Sbill char LASTLOG[] = "/usr/adm/lastlog"; /* last login info */ 941014Sbill char USERLOG[] = "/etc/utmp"; /* who is logged in */ 951014Sbill char outbuf[BUFSIZ]; /* output buffer */ 961014Sbill char *ctime(); 971014Sbill 981014Sbill int unbrief = 1; /* -b option default */ 991014Sbill int header = 1; /* -f option default */ 1001014Sbill int hack = 1; /* -h option default */ 1011014Sbill int idle = 0; /* -i option default */ 1021014Sbill int large = 0; /* -l option default */ 1031014Sbill int match = 1; /* -m option default */ 1041014Sbill int plan = 1; /* -p option default */ 1051014Sbill int unquick = 1; /* -q option default */ 1061014Sbill int small = 0; /* -s option default */ 1071014Sbill int wide = 1; /* -w option default */ 1081014Sbill 1091014Sbill int lf; 1101014Sbill int llopenerr; 1111014Sbill 1121014Sbill long tloc; /* current time */ 1131014Sbill 1141014Sbill 1151014Sbill 1161014Sbill main( argc, argv ) 1171014Sbill 1181014Sbill int argc; 1191014Sbill char *argv[]; 1201014Sbill 1211014Sbill { 1221014Sbill FILE *fp, *fopen(); /* for plans */ 1231014Sbill struct passwd *getpwent(); /* read /etc/passwd */ 1241014Sbill struct person *person1, *p, *pend; /* people */ 1251014Sbill struct passwd *pw; /* temporary */ 1261014Sbill struct utmp user; /* ditto */ 1271014Sbill char *malloc(); 1281014Sbill char *s, *pn, *ln; 1291014Sbill char c; 1301014Sbill char *PLAN = "/.plan"; /* what plan file is */ 1311014Sbill char *PROJ = "/.project"; /* what project file */ 1321014Sbill int PLANLEN = strlen( PLAN ); 1331014Sbill int PROJLEN = strlen( PROJ ); 1341014Sbill int numnames = 0; 1351014Sbill int orgnumnames; 1361014Sbill int uf; 1371014Sbill int usize = sizeof user; 1381014Sbill int unshort; 1391014Sbill int i, j; 1401014Sbill int fngrlogin; 1411014Sbill 1421014Sbill setbuf( stdout, outbuf ); /* buffer output */ 1431014Sbill 1441014Sbill /* parse command line for (optional) arguments */ 1451014Sbill 1461014Sbill i = 1; 1471014Sbill if( strcmp( *argv, "sh" ) ) { 1481014Sbill fngrlogin = 0; 1491014Sbill while( i++ < argc && (*++argv)[0] == COMMAND ) { 1501014Sbill for( s = argv[0] + 1; *s != NULL; s++ ) { 1511014Sbill switch (*s) { 1521014Sbill 1531014Sbill case 'b': 1541014Sbill unbrief = 0; 1551014Sbill break; 1561014Sbill 1571014Sbill case 'f': 1581014Sbill header = 0; 1591014Sbill break; 1601014Sbill 1611014Sbill case 'h': 1621014Sbill hack = 0; 1631014Sbill break; 1641014Sbill 1651014Sbill case 'i': 1661014Sbill idle = 1; 1671014Sbill unquick = 0; 1681014Sbill break; 1691014Sbill 1701014Sbill case 'l': 1711014Sbill large = 1; 1721014Sbill break; 1731014Sbill 1741014Sbill case 'm': 1751014Sbill match = 0; 1761014Sbill break; 1771014Sbill 1781014Sbill case 'p': 1791014Sbill plan = 0; 1801014Sbill break; 1811014Sbill 1821014Sbill case 'q': 1831014Sbill unquick = 0; 1841014Sbill break; 1851014Sbill 1861014Sbill case 's': 1871014Sbill small = 1; 1881014Sbill break; 1891014Sbill 1901014Sbill case 'w': 1911014Sbill wide = 0; 1921014Sbill break; 1931014Sbill 1941014Sbill default: 1951014Sbill fprintf( stderr, "finger: Usage -- 'finger [-bfhilmpqsw] [login1 [login2 ...] ]'\n" ); 1961014Sbill exit( 1 ); 1971014Sbill } 1981014Sbill } 1991014Sbill } 2001014Sbill } 2011014Sbill else { 2021014Sbill fngrlogin = 1; 2031014Sbill } 2041014Sbill if( unquick ) { 2051014Sbill time( &tloc ); 2061014Sbill } 2071014Sbill else { 2081014Sbill if( idle ) { 2091014Sbill time( &tloc ); 2101014Sbill } 2111014Sbill } 2121014Sbill 2131014Sbill /* i > argc means no login names given so get them by reading USERLOG */ 2141014Sbill 2151014Sbill if( (i > argc) || fngrlogin ) { 2161014Sbill unshort = large; 2171014Sbill if( ( uf = open(USERLOG, 0) ) >= 0 ) { 2181014Sbill user.ut_name[0] = NULL; 2191014Sbill while( user.ut_name[0] == NULL ) { 2201014Sbill if( read( uf, (char *) &user, usize ) != usize ) { 221*16469Ssam printf( "No one logged on\n" ); 2221014Sbill exit( 0 ); 2231014Sbill } 2241014Sbill } 2251014Sbill person1 = (struct person *) malloc( persize ); 2261014Sbill for( j = 0; j < NMAX; j++ ) { 2271014Sbill person1->tty[j] = user.ut_line[j]; 2281014Sbill person1->name[j] = user.ut_name[j]; 2291014Sbill } 2301014Sbill person1->name[NMAX] = NULL; 2311014Sbill person1->tty[NMAX] = NULL; 2321014Sbill person1->loginat = user.ut_time; 2331014Sbill person1->pwd = NILPWD; 2341014Sbill person1->loggedin = 1; 2351014Sbill numnames++; 2361014Sbill p = person1; 2371014Sbill while( read( uf, (char *) &user, usize ) == usize ) { 2381014Sbill if( user.ut_name[0] == NULL ) continue; 2391014Sbill p->link = (struct person *) malloc( persize ); 2401014Sbill p = p->link; 2411014Sbill for( j = 0; j < NMAX; j++ ) { 2421014Sbill p->tty[j] = user.ut_line[j]; 2431014Sbill p->name[j] = user.ut_name[j]; 2441014Sbill } 2451014Sbill p->name[NMAX] = NULL; 2461014Sbill p->tty[NMAX] = NULL; 2471014Sbill p->loginat = user.ut_time; 2481014Sbill p->pwd = NILPWD; 2491014Sbill p->loggedin = 1; 2501014Sbill numnames++; 2511014Sbill } 2521014Sbill p->link = NILPERS; 2531014Sbill close( uf ); 2541014Sbill } 2551014Sbill else { 2561014Sbill fprintf( stderr, "finger: error opening %s\n", USERLOG ); 2571014Sbill exit( 2 ); 2581014Sbill } 2591014Sbill 2601014Sbill /* if we are doing it, read /etc/passwd for the useful info */ 2611014Sbill 2621014Sbill if( unquick ) { 2631014Sbill setpwent(); 2641014Sbill fwopen(); 2651014Sbill i = numnames; 2661014Sbill while( ( (pw = getpwent()) != NILPWD ) && ( i > 0 ) ) { 2671014Sbill p = person1; 2681014Sbill do { 2691014Sbill if( p->pwd == NILPWD ) { 2701014Sbill if( strcmp( p->name, pw->pw_name ) == 0 ) { 2711014Sbill p->pwd = (struct passwd *) malloc( pwdsize ); 2721014Sbill pwdcopy( p->pwd, pw ); 2731014Sbill decode( p ); 2741014Sbill i--; 2751014Sbill } 2761014Sbill } 2771014Sbill p = p->link; 2781014Sbill } while( p != NILPERS ); 2791014Sbill } 2801014Sbill fwclose(); 2811014Sbill endpwent(); 2821014Sbill } 2831014Sbill } 2841014Sbill 2851014Sbill /* get names from command line and check to see if they're logged in */ 2861014Sbill 2871014Sbill else { 2881014Sbill unshort = ( small == 1 ? 0 : 1 ); 289*16469Ssam while (i <= argc && netfinger(*argv)) { 290*16469Ssam i++; 291*16469Ssam argv++; 292*16469Ssam } 293*16469Ssam if (i++ > argc) 294*16469Ssam exit(0); 2951014Sbill person1 = (struct person *) malloc( persize ); 2961014Sbill strcpy( person1->name, (argv++)[ 0 ] ); 2971014Sbill person1->loggedin = 0; 2981014Sbill person1->pwd = NILPWD; 2991014Sbill numnames++; 3001014Sbill p = person1; 3011014Sbill while( i++ <= argc ) { 302*16469Ssam if (netfinger(*argv)) { 303*16469Ssam argv++; 304*16469Ssam continue; 305*16469Ssam } 3061014Sbill p->link = (struct person *) malloc( persize ); 3071014Sbill p = p->link; 3081014Sbill strcpy( p->name, (argv++)[ 0 ] ); 3091014Sbill p->loggedin = 0; 3101014Sbill p->pwd = NILPWD; 3111014Sbill numnames++; 3121014Sbill } 3131014Sbill p->link = NILPERS; 3141014Sbill pend = p; 3151014Sbill 3161014Sbill /* if we are doing it, read /etc/passwd for the useful info */ 3171014Sbill 3181014Sbill orgnumnames = numnames; 3191014Sbill if( unquick ) { 3201014Sbill setpwent(); 3211014Sbill while( ( pw = getpwent() ) != NILPWD ) { 3221014Sbill p = person1; 3231014Sbill i = 0; 3241014Sbill do { 3251014Sbill if( strcmp( p->name, pw->pw_name ) == 0 || 3261014Sbill matchcmp( pw->pw_gecos, pw->pw_name, p->name ) ) { 3271014Sbill if( p->pwd == NILPWD ) { 3281014Sbill p->pwd = (struct passwd *) malloc( pwdsize ); 3291014Sbill pwdcopy( p->pwd, pw ); 3301014Sbill } 3311014Sbill else { /* handle multiple logins -- append new 3321014Sbill "duplicate" entry to end of list */ 3331014Sbill pend->link = (struct person *) malloc(persize); 3341014Sbill pend = pend->link; 3351014Sbill pend->link = NILPERS; 3361014Sbill strcpy( pend->name, p->name ); 3371014Sbill pend->pwd = (struct passwd *) malloc(pwdsize); 3381014Sbill pwdcopy( pend->pwd, pw ); 3391014Sbill numnames++; 3401014Sbill } 3411014Sbill } 3421014Sbill p = p->link; 3431014Sbill } while( ++i < orgnumnames ); 3441014Sbill } 3451014Sbill endpwent(); 3461014Sbill } 3471014Sbill 3481014Sbill /* Now get login information */ 3491014Sbill 3501014Sbill if( ( uf = open(USERLOG, 0) ) >= 0 ) { 3511014Sbill while( read( uf, (char *) &user, usize ) == usize ) { 3521014Sbill if( user.ut_name[0] == NULL ) continue; 3531014Sbill p = person1; 3541014Sbill do { 3551014Sbill pw = p->pwd; 3561014Sbill if( pw == NILPWD ) { 3571014Sbill i = ( strcmp( p->name, user.ut_name ) ? 0 : NMAX ); 3581014Sbill } 3591014Sbill else { 3601014Sbill i = 0; 3611014Sbill while( (i < NMAX) && 3621014Sbill ( pw->pw_name[i] == user.ut_name[i]) ) { 3631014Sbill if( pw->pw_name[i] == NULL ) { 3641014Sbill i = NMAX; 3651014Sbill break; 3661014Sbill } 3671014Sbill i++; 3681014Sbill } 3691014Sbill } 3701014Sbill if( i == NMAX ) { 3711014Sbill if( p->loggedin == 1 ) { 3721014Sbill pend->link = (struct person *) malloc(persize); 3731014Sbill pend = pend->link; 3741014Sbill pend->link = NILPERS; 3751014Sbill strcpy( pend->name, p->name ); 3761014Sbill for( j = 0; j < NMAX; j++ ) { 3771014Sbill pend->tty[j] = user.ut_line[j]; 3781014Sbill } 3791014Sbill pend->tty[ NMAX ] = NULL; 3801014Sbill pend->loginat = user.ut_time; 3811014Sbill pend->loggedin = 2; 3821014Sbill if( pw == NILPWD ) { 3831014Sbill pend ->pwd = NILPWD; 3841014Sbill } 3851014Sbill else { 3861014Sbill pend->pwd = (struct passwd *) malloc(pwdsize); 3871014Sbill pwdcopy( pend->pwd, pw ); 3881014Sbill } 3891014Sbill numnames++; 3901014Sbill } 3911014Sbill else { 3921014Sbill if( p->loggedin != 2 ) { 3931014Sbill for( j = 0; j < NMAX; j++ ) { 3941014Sbill p->tty[j] = user.ut_line[j]; 3951014Sbill } 3961014Sbill p->tty[ NMAX ] = NULL; 3971014Sbill p->loginat = user.ut_time; 3981014Sbill p->loggedin = 1; 3991014Sbill } 4001014Sbill } 4011014Sbill } 4021014Sbill p = p->link; 4031014Sbill } while( p != NILPERS ); 4041014Sbill } 4051014Sbill fwopen(); 4061014Sbill p = person1; 4071014Sbill while( p != NILPERS ) { 4081014Sbill if( p->loggedin == 2 ) { 4091014Sbill p->loggedin = 1; 4101014Sbill } 4111014Sbill decode( p ); 4121014Sbill p = p->link; 4131014Sbill } 4141014Sbill fwclose(); 4151014Sbill close( uf ); 4161014Sbill } 4171014Sbill else { 4181014Sbill fprintf( stderr, "finger: error opening %s\n", USERLOG ); 4191014Sbill exit( 2 ); 4201014Sbill } 4211014Sbill } 4221014Sbill 4231014Sbill /* print out what we got */ 4241014Sbill 4251014Sbill if( header ) { 4261014Sbill if( unquick ) { 4271014Sbill if( !unshort ) { 4281014Sbill if( wide ) { 4291014Sbill printf( 4301014Sbill "Login Name TTY Idle When Office\n" ); 4311014Sbill } 4321014Sbill else { 4331014Sbill printf( 4341014Sbill "Login TTY Idle When Office\n" ); 4351014Sbill } 4361014Sbill } 4371014Sbill } 4381014Sbill else { 4391014Sbill printf( "Login TTY When" ); 4401014Sbill if( idle ) { 4411014Sbill printf( " Idle" ); 4421014Sbill } 4431014Sbill printf( "\n" ); 4441014Sbill } 4451014Sbill } 4461014Sbill p = person1; 4471014Sbill do { 4481014Sbill if( unquick ) { 4491014Sbill if( unshort ) { 4501014Sbill personprint( p ); 4511014Sbill if( p->pwd != NILPWD ) { 4521014Sbill if( hack ) { 4531014Sbill s = malloc(strlen((p->pwd)->pw_dir) + PROJLEN + 1 ); 4541014Sbill strcpy( s, (p->pwd)->pw_dir ); 4551014Sbill strcat( s, PROJ ); 4561014Sbill if( ( fp = fopen( s, "r") ) != NULL ) { 4571014Sbill printf( "Project: " ); 4581014Sbill while( ( c = getc(fp) ) != EOF ) { 4591014Sbill if( c == LINEBREAK ) { 4601014Sbill break; 4611014Sbill } 4621014Sbill putc( c, stdout ); 4631014Sbill } 4641014Sbill fclose( fp ); 4651014Sbill printf( "\n" ); 4661014Sbill } 4671014Sbill } 4681014Sbill if( plan ) { 4691014Sbill s = malloc( strlen( (p->pwd)->pw_dir ) + PLANLEN + 1 ); 4701014Sbill strcpy( s, (p->pwd)->pw_dir ); 4711014Sbill strcat( s, PLAN ); 4721014Sbill if( ( fp = fopen( s, "r") ) == NULL ) { 4731014Sbill printf( "No Plan.\n" ); 4741014Sbill } 4751014Sbill else { 4761014Sbill printf( "Plan:\n" ); 4771014Sbill while( ( c = getc(fp) ) != EOF ) { 4781014Sbill putc( c, stdout ); 4791014Sbill } 4801014Sbill fclose( fp ); 4811014Sbill } 4821014Sbill } 4831014Sbill } 4841014Sbill if( p->link != NILPERS ) { 4851014Sbill printf( "\n" ); 4861014Sbill } 4871014Sbill } 4881014Sbill else { 4891014Sbill shortprint( p ); 4901014Sbill } 4911014Sbill } 4921014Sbill else { 4931014Sbill quickprint( p ); 4941014Sbill } 4951014Sbill p = p->link; 4961014Sbill } while( p != NILPERS ); 4971014Sbill exit(0); 4981014Sbill } 4991014Sbill 5001014Sbill 5011014Sbill /* given a pointer to a pwd (pfrom) copy it to another one, allocating 5021014Sbill * space for all the stuff in it. Note: Only the useful (what the 5031014Sbill * program currently uses) things are copied. 5041014Sbill */ 5051014Sbill 5061014Sbill pwdcopy( pto, pfrom ) /* copy relevant fields only */ 5071014Sbill 5081014Sbill struct passwd *pto, *pfrom; 5091014Sbill { 5101014Sbill pto->pw_name = malloc( strlen( pfrom->pw_name ) + 1 ); 5111014Sbill strcpy( pto->pw_name, pfrom->pw_name ); 5121014Sbill pto->pw_uid = pfrom->pw_uid; 5131014Sbill pto->pw_gecos = malloc( strlen( pfrom->pw_gecos ) + 1 ); 5141014Sbill strcpy( pto->pw_gecos, pfrom->pw_gecos ); 5151014Sbill pto->pw_dir = malloc( strlen( pfrom->pw_dir ) + 1 ); 5161014Sbill strcpy( pto->pw_dir, pfrom->pw_dir ); 5171014Sbill pto->pw_shell = malloc( strlen( pfrom->pw_shell ) + 1 ); 5181014Sbill strcpy( pto->pw_shell, pfrom->pw_shell ); 5191014Sbill } 5201014Sbill 5211014Sbill 5221014Sbill /* print out information on quick format giving just name, tty, login time 5231014Sbill * and idle time if idle is set. 5241014Sbill */ 5251014Sbill 5261014Sbill quickprint( pers ) 5271014Sbill 5281014Sbill struct person *pers; 5291014Sbill { 5301014Sbill int idleprinted; 5311014Sbill 5321014Sbill printf( "%-*.*s", NMAX, NMAX, pers->name ); 5331014Sbill printf( " " ); 5341014Sbill if( pers->loggedin ) { 5351014Sbill if( idle ) { 5361014Sbill findidle( pers ); 5371014Sbill if( pers->writeable ) { 5381014Sbill printf( " %-*.*s %-16.16s", LMAX, LMAX, 5391014Sbill pers->tty, ctime( &pers->loginat ) ); 5401014Sbill } 5411014Sbill else { 5421014Sbill printf( "*%-*.*s %-16.16s", LMAX, LMAX, 5431014Sbill pers->tty, ctime( &pers->loginat ) ); 5441014Sbill } 5451014Sbill printf( " " ); 5461014Sbill idleprinted = ltimeprint( &pers->idletime ); 5471014Sbill } 5481014Sbill else { 5491014Sbill printf( " %-*.*s %-16.16s", LMAX, LMAX, 5501014Sbill pers->tty, ctime( &pers->loginat ) ); 5511014Sbill } 5521014Sbill } 5531014Sbill else { 5541014Sbill printf( " Not Logged In" ); 5551014Sbill } 5561014Sbill printf( "\n" ); 5571014Sbill } 5581014Sbill 5591014Sbill 5601014Sbill /* print out information in short format, giving login name, full name, 5611014Sbill * tty, idle time, login time, office location and phone. 5621014Sbill */ 5631014Sbill 5641014Sbill shortprint( pers ) 5651014Sbill 5661014Sbill struct person *pers; 5671014Sbill 5681014Sbill { 5691014Sbill struct passwd *pwdt = pers->pwd; 5701014Sbill char buf[ 26 ]; 5711014Sbill int i, len, offset, dialup; 5721014Sbill 5731014Sbill if( pwdt == NILPWD ) { 5741014Sbill printf( "%-*.*s", NMAX, NMAX, pers->name ); 5751014Sbill printf( " ???\n" ); 5761014Sbill return; 5771014Sbill } 5781014Sbill printf( "%-*.*s", NMAX, NMAX, pwdt->pw_name ); 5791014Sbill dialup = 0; 5801014Sbill if( wide ) { 5811014Sbill if( strlen( pers->realname ) > 0 ) { 5821014Sbill printf( " %-20.20s", pers->realname ); 5831014Sbill } 5841014Sbill else { 5851014Sbill printf( " ??? " ); 5861014Sbill } 5871014Sbill } 5881014Sbill if( pers->loggedin ) { 5891014Sbill if( pers->writeable ) { 5901014Sbill printf( " " ); 5911014Sbill } 5921014Sbill else { 5931014Sbill printf( " *" ); 5941014Sbill } 5951014Sbill } 5961014Sbill else { 5971014Sbill printf( " " ); 5981014Sbill } 5991014Sbill if( strlen( pers->tty ) > 0 ) { 6001014Sbill strcpy( buf, pers->tty ); 6011014Sbill if( (buf[0] == 't') && (buf[1] == 't') && (buf[2] == 'y') ) { 6021014Sbill offset = 3; 6031014Sbill for( i = 0; i < 2; i++ ) { 6041014Sbill buf[i] = buf[i + offset]; 6051014Sbill } 6061014Sbill } 6071014Sbill if( (buf[0] == 'd') && pers->loggedin ) { 6081014Sbill dialup = 1; 6091014Sbill } 6101014Sbill printf( "%-2.2s ", buf ); 6111014Sbill } 6121014Sbill else { 6131014Sbill printf( " " ); 6141014Sbill } 6158842Smckusick strcpy(buf, ctime(&pers->loginat)); 6161014Sbill if( pers->loggedin ) { 6171014Sbill stimeprint( &pers->idletime ); 6181014Sbill offset = 7; 6191014Sbill for( i = 4; i < 19; i++ ) { 6201014Sbill buf[i] = buf[i + offset]; 6211014Sbill } 6221014Sbill printf( " %-9.9s ", buf ); 6231014Sbill } 6248842Smckusick else if (pers->loginat == 0) 6258842Smckusick printf(" < . . . . >"); 6268842Smckusick else if (tloc - pers->loginat >= 180 * 24 * 60 * 60) 6278842Smckusick printf( " <%-6.6s, %-4.4s>", buf+4, buf+20 ); 6288842Smckusick else 6298842Smckusick printf(" <%-12.12s>", buf+4); 6301014Sbill len = strlen( pers->homephone ); 6311014Sbill if( dialup && (len > 0) ) { 6321014Sbill if( len == 8 ) { 6331014Sbill printf( " " ); 6341014Sbill } 6351014Sbill else { 6361014Sbill if( len == 12 ) { 6371014Sbill printf( " " ); 6381014Sbill } 6391014Sbill else { 6401014Sbill for( i = 1; i <= 21 - len; i++ ) { 6411014Sbill printf( " " ); 6421014Sbill } 6431014Sbill } 6441014Sbill } 6451014Sbill printf( "%s", pers->homephone ); 6461014Sbill } 6471014Sbill else { 6481014Sbill if( strlen( pers->office ) > 0 ) { 6491014Sbill printf( " %-11.11s", pers->office ); 6501014Sbill if( strlen( pers->officephone ) > 0 ) { 6511014Sbill printf( " %8.8s", pers->officephone ); 6521014Sbill } 6531014Sbill else { 6541014Sbill if( len == 8 ) { 6551014Sbill printf( " %8.8s", pers->homephone ); 6561014Sbill } 6571014Sbill } 6581014Sbill } 6591014Sbill else { 6601014Sbill if( strlen( pers->officephone ) > 0 ) { 6611014Sbill printf( " %8.8s", pers->officephone ); 6621014Sbill } 6631014Sbill else { 6641014Sbill if( len == 8 ) { 6651014Sbill printf( " %8.8s", pers->homephone ); 6661014Sbill } 6671014Sbill else { 6681014Sbill if( len == 12 ) { 6691014Sbill printf( " %12.12s", pers->homephone ); 6701014Sbill } 6711014Sbill } 6721014Sbill } 6731014Sbill } 6741014Sbill } 6751014Sbill printf( "\n" ); 6761014Sbill } 6771014Sbill 6781014Sbill 6791014Sbill /* print out a person in long format giving all possible information. 6801014Sbill * directory and shell are inhibited if unbrief is clear. 6811014Sbill */ 6821014Sbill 6831014Sbill personprint( pers ) 6841014Sbill 6851014Sbill struct person *pers; 6861014Sbill { 6871014Sbill struct passwd *pwdt = pers->pwd; 6881014Sbill int idleprinted; 6891014Sbill 6901014Sbill if( pwdt == NILPWD ) { 6911014Sbill printf( "Login name: %-10s", pers->name ); 6921014Sbill printf( " " ); 6931014Sbill printf( "In real life: ???\n"); 6941014Sbill return; 6951014Sbill } 6961014Sbill printf( "Login name: %-10s", pwdt->pw_name ); 6971014Sbill if( pers->loggedin ) { 6981014Sbill if( pers->writeable ) { 6991014Sbill printf( " " ); 7001014Sbill } 7011014Sbill else { 7021014Sbill printf( " (messages off) " ); 7031014Sbill } 7041014Sbill } 7051014Sbill else { 7061014Sbill printf( " " ); 7071014Sbill } 7081014Sbill if( strlen( pers->realname ) > 0 ) { 7091014Sbill printf( "In real life: %-s", pers->realname ); 7101014Sbill } 7111014Sbill if( strlen( pers->office ) > 0 ) { 7121014Sbill printf( "\nOffice: %-.11s", pers->office ); 7131014Sbill if( strlen( pers->officephone ) > 0 ) { 7141014Sbill printf( ", %s", pers->officephone ); 7151014Sbill if( strlen( pers->homephone ) > 0 ) { 7161014Sbill printf( " Home phone: %s", pers->homephone ); 7171014Sbill } 7181014Sbill else { 7191014Sbill if( strlen( pers->random ) > 0 ) { 7201014Sbill printf( " %s", pers->random ); 7211014Sbill } 7221014Sbill } 7231014Sbill } 7241014Sbill else { 7251014Sbill if( strlen( pers->homephone ) > 0 ) { 7261014Sbill printf(" Home phone: %s",pers->homephone); 7271014Sbill } 7281014Sbill if( strlen( pers->random ) > 0 ) { 7291014Sbill printf( " %s", pers->random ); 7301014Sbill } 7311014Sbill } 7321014Sbill } 7331014Sbill else { 7341014Sbill if( strlen( pers->officephone ) > 0 ) { 7351014Sbill printf( "\nPhone: %s", pers->officephone ); 7361014Sbill if( strlen( pers->homephone ) > 0 ) { 7371014Sbill printf( "\n, %s", pers->homephone ); 7381014Sbill if( strlen( pers->random ) > 0 ) { 7391014Sbill printf( ", %s", pers->random ); 7401014Sbill } 7411014Sbill } 7421014Sbill else { 7431014Sbill if( strlen( pers->random ) > 0 ) { 7441014Sbill printf( "\n, %s", pers->random ); 7451014Sbill } 7461014Sbill } 7471014Sbill } 7481014Sbill else { 7491014Sbill if( strlen( pers->homephone ) > 0 ) { 7501014Sbill printf( "\nPhone: %s", pers->homephone ); 7511014Sbill if( strlen( pers->random ) > 0 ) { 7521014Sbill printf( ", %s", pers->random ); 7531014Sbill } 7541014Sbill } 7551014Sbill else { 7561014Sbill if( strlen( pers->random ) > 0 ) { 7571014Sbill printf( "\n%s", pers->random ); 7581014Sbill } 7591014Sbill } 7601014Sbill } 7611014Sbill } 7621014Sbill if( unbrief ) { 7631014Sbill printf( "\n" ); 7641014Sbill printf( "Directory: %-25s", pwdt->pw_dir ); 7651014Sbill if( strlen( pwdt->pw_shell ) > 0 ) { 7661014Sbill printf( " Shell: %-s", pwdt->pw_shell ); 7671014Sbill } 7681014Sbill } 7691014Sbill if( pers->loggedin ) { 7701014Sbill register char *ep = ctime( &pers->loginat ); 7711014Sbill printf("\nOn since %15.15s on %-*.*s ", &ep[4], LMAX, LMAX, pers->tty ); 7721014Sbill idleprinted = ltimeprint( &pers->idletime ); 7731014Sbill if( idleprinted ) { 7741014Sbill printf( " Idle Time" ); 7751014Sbill } 7761014Sbill } 7778842Smckusick else if (pers->loginat == 0) 7788842Smckusick printf("\nNever logged in."); 7798842Smckusick else if (tloc - pers->loginat > 180 * 24 * 60 * 60) { 7808842Smckusick register char *ep = ctime( &pers->loginat ); 7818842Smckusick printf("\nLast login %10.10s, %4.4s on %.*s", ep, ep+20, LMAX, pers->tty); 7828842Smckusick } 7831014Sbill else { 7841014Sbill register char *ep = ctime( &pers->loginat ); 7851014Sbill printf("\nLast login %16.16s on %.*s", ep, LMAX, pers->tty ); 7861014Sbill } 7871014Sbill printf( "\n" ); 7881014Sbill } 7891014Sbill 7901014Sbill 7911014Sbill /* 7921014Sbill * very hacky section of code to format phone numbers. filled with 7931014Sbill * magic constants like 4, 7 and 10. 7941014Sbill */ 7951014Sbill 7961014Sbill char *phone( s, len ) 7971014Sbill 7981014Sbill char *s; 7991014Sbill int len; 8001014Sbill { 8011014Sbill char *strsave(); 8021014Sbill char fonebuf[ 15 ]; 8031014Sbill int i; 8041014Sbill 8051014Sbill switch( len ) { 8061014Sbill 8071014Sbill case 4: 8081014Sbill fonebuf[ 0 ] = ' '; 8091014Sbill fonebuf[ 1 ] = 'x'; 8101014Sbill fonebuf[ 2 ] = '2'; 8111014Sbill fonebuf[ 3 ] = '-'; 8121014Sbill for( i = 0; i <= 3; i++ ) { 8131014Sbill fonebuf[ 4 + i ] = *s++; 8141014Sbill } 8151014Sbill fonebuf[ 8 ] = NULL; 8161014Sbill return( strsave( &fonebuf[0] ) ); 8171014Sbill break; 8181014Sbill 8191014Sbill case 7: 8201014Sbill for( i = 0; i <= 2; i++ ) { 8211014Sbill fonebuf[ i ] = *s++; 8221014Sbill } 8231014Sbill fonebuf[ 3 ] = '-'; 8241014Sbill for( i = 0; i <= 3; i++ ) { 8251014Sbill fonebuf[ 4 + i ] = *s++; 8261014Sbill } 8271014Sbill fonebuf[ 8 ] = NULL; 8281014Sbill return( strsave( &fonebuf[0] ) ); 8291014Sbill break; 8301014Sbill 8311014Sbill case 10: 8321014Sbill for( i = 0; i <= 2; i++ ) { 8331014Sbill fonebuf[ i ] = *s++; 8341014Sbill } 8351014Sbill fonebuf[ 3 ] = '-'; 8361014Sbill for( i = 0; i <= 2; i++ ) { 8371014Sbill fonebuf[ 4 + i ] = *s++; 8381014Sbill } 8391014Sbill fonebuf[ 7 ] = '-'; 8401014Sbill for( i = 0; i <= 3; i++ ) { 8411014Sbill fonebuf[ 8 + i ] = *s++; 8421014Sbill } 8431014Sbill fonebuf[ 12 ] = NULL; 8441014Sbill return( strsave( &fonebuf[0] ) ); 8451014Sbill break; 8461014Sbill 8471014Sbill default: 8481014Sbill fprintf( stderr, "finger: error in phone numbering\n" ); 8491014Sbill return( strsave(s) ); 8501014Sbill break; 8511014Sbill } 8521014Sbill } 8531014Sbill 8541014Sbill 8551014Sbill /* decode the information in the gecos field of /etc/passwd 8561014Sbill * another hacky section of code, but given the format the stuff is in... 8571014Sbill */ 8581014Sbill 8591014Sbill decode( pers ) 8601014Sbill 8611014Sbill struct person *pers; 8621014Sbill 8631014Sbill { 8641014Sbill struct passwd *pwdt = pers->pwd; 86515001Sralph char buffer[ 256 ], *bp, *gp, *lp; 8661014Sbill char *phone(); 8671014Sbill int alldigits; 8681014Sbill int len; 8691014Sbill int i; 8701014Sbill 8711014Sbill pers->realname = NULLSTR; 8721014Sbill pers->office = NULLSTR; 8731014Sbill pers->officephone = NULLSTR; 8741014Sbill pers->homephone = NULLSTR; 8751014Sbill pers->random = NULLSTR; 8761014Sbill if( pwdt != NILPWD ) { 8771014Sbill gp = pwdt->pw_gecos; 8781014Sbill bp = &buffer[ 0 ]; 8791014Sbill if( *gp == ASTERISK ) { 8801014Sbill gp++; 8811014Sbill } 8821014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { /* name */ 8831014Sbill if( *gp == SAMENAME ) { 8841014Sbill lp = pwdt->pw_name; 8851014Sbill *bp++ = CAPITALIZE(*lp++); 8861014Sbill while( *lp != NULL ) { 8871014Sbill *bp++ = *lp++; 8881014Sbill } 8891014Sbill } 8901014Sbill else { 8911014Sbill *bp++ = *gp; 8921014Sbill } 8931014Sbill gp++; 8941014Sbill } 8951014Sbill *bp = NULL; 8961014Sbill pers->realname = malloc( strlen( &buffer[0] ) + 1 ); 8971014Sbill strcpy( pers->realname, &buffer[0] ); 8981014Sbill if( *gp++ == COMMA ) { /* office, supposedly */ 8991014Sbill alldigits = 1; 9001014Sbill bp = &buffer[ 0 ]; 9011014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { 9021014Sbill *bp = *gp++; 9031014Sbill alldigits = alldigits && ('0' <= *bp) && (*bp <= '9'); 9041014Sbill bp++; 9051014Sbill } 9061014Sbill *bp = NULL; 9071014Sbill len = strlen( &buffer[0] ); 9081014Sbill if( buffer[ len - 1 ] == CORY ) { 9091014Sbill strcpy( &buffer[ len - 1 ], " Cory" ); 9101014Sbill pers->office = malloc( len + 5 ); 9111014Sbill strcpy( pers->office, &buffer[0] ); 9121014Sbill } 9131014Sbill else { 9141014Sbill if( buffer[ len - 1 ] == EVANS ) { 9151014Sbill strcpy( &buffer[ len - 1 ], " Evans" ); 9161014Sbill pers->office = malloc( len + 6 ); 9171014Sbill strcpy( pers->office, &buffer[0] ); 9181014Sbill } 9191014Sbill else { 9201014Sbill if( buffer[ len - 1 ] == 'L' ) { 9211014Sbill strcpy( &buffer[ len - 1 ], " LBL" ); 9221014Sbill pers->office = malloc( len + 4 ); 9231014Sbill strcpy( pers->office, &buffer[0] ); 9241014Sbill } 9251014Sbill else { 9261014Sbill if( alldigits ) { 9271014Sbill if( len == 4 ) { 9281014Sbill pers->officephone = phone(&buffer[0], len); 9291014Sbill } 9301014Sbill else { 9311014Sbill if( (len == 7) || (len == 10) ) { 9321014Sbill pers->homephone = phone(&buffer[0],len); 9331014Sbill } 9341014Sbill } 9351014Sbill } 9361014Sbill else { 9371014Sbill pers->random = malloc( len + 1 ); 9381014Sbill strcpy( pers->random, &buffer[0] ); 9391014Sbill } 9401014Sbill } 9411014Sbill } 9421014Sbill } 9431014Sbill if( *gp++ == COMMA ) { /* office phone, theoretically */ 9441014Sbill bp = &buffer[ 0 ]; 9451014Sbill alldigits = 1; 9461014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { 9471014Sbill *bp = *gp++; 9481014Sbill alldigits = alldigits && ('0' <= *bp) && (*bp <= '9'); 9491014Sbill bp++; 9501014Sbill } 9511014Sbill *bp = NULL; 9521014Sbill len = strlen( &buffer[0] ); 9531014Sbill if( alldigits ) { 9541014Sbill if( len != 4 ) { 9551014Sbill if( (len == 7) || (len == 10) ) { 9561014Sbill pers->homephone = phone( &buffer[0], len ); 9571014Sbill } 9581014Sbill else { 9591014Sbill pers->random = malloc( len + 1 ); 9601014Sbill strcpy( pers->random, &buffer[0] ); 9611014Sbill } 9621014Sbill } 9631014Sbill else { 9641014Sbill pers->officephone = phone( &buffer[0], len ); 9651014Sbill } 9661014Sbill } 9671014Sbill else { 9681014Sbill pers->random = malloc( len + 1 ); 9691014Sbill strcpy( pers->random, &buffer[0] ); 9701014Sbill } 9711014Sbill if( *gp++ == COMMA ) { /* home phone?? */ 9721014Sbill bp = &buffer[ 0 ]; 9731014Sbill alldigits = 1; 9741014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { 9751014Sbill *bp = *gp++; 9761014Sbill alldigits = alldigits && ('0' <= *bp) && 9771014Sbill (*bp <= '9'); 9781014Sbill bp++; 9791014Sbill } 9801014Sbill *bp = NULL; 9811014Sbill len = strlen( &buffer[0] ); 9821014Sbill if( alldigits && ( (len == 7) || (len == 10) ) ) { 9831014Sbill if( *pers->homephone != NULL ) { 9841014Sbill pers->officephone = pers->homephone; 9851014Sbill } 9861014Sbill pers->homephone = phone( &buffer[0], len ); 9871014Sbill } 9881014Sbill else { 9891014Sbill pers->random = malloc( strlen( &buffer[0] ) + 1 ); 9901014Sbill strcpy( pers->random, &buffer[0] ); 9911014Sbill } 9921014Sbill } 9931014Sbill } 9941014Sbill } 9951014Sbill if( pers->loggedin == 0 ) { 9961014Sbill findwhen( pers ); 9971014Sbill } 9981014Sbill else { 9991014Sbill findidle( pers ); 10001014Sbill } 10011014Sbill } 10021014Sbill } 10031014Sbill 10041014Sbill 10051014Sbill /* find the last log in of a user by checking the LASTLOG file. 10061014Sbill * the entry is indexed by the uid, so this can only be done if 10071014Sbill * the uid is known (which it isn't in quick mode) 10081014Sbill */ 10091014Sbill 10101014Sbill fwopen() 10111014Sbill { 10121014Sbill if( ( lf = open(LASTLOG, 0) ) >= 0 ) { 10131014Sbill llopenerr = 0; 10141014Sbill } 10151014Sbill else { 10161014Sbill fprintf( stderr, "finger: lastlog open error\n" ); 10171014Sbill llopenerr = 1; 10181014Sbill } 10191014Sbill } 10201014Sbill 10211014Sbill 10221014Sbill findwhen( pers ) 10231014Sbill 10241014Sbill struct person *pers; 10251014Sbill { 10261014Sbill struct passwd *pwdt = pers->pwd; 10271014Sbill struct lastlog ll; 10281014Sbill int llsize = sizeof ll; 10291014Sbill int i; 10301014Sbill 10311014Sbill if( !llopenerr ) { 10321014Sbill lseek( lf, pwdt->pw_uid*llsize, 0 ); 10338842Smckusick if ((i = read( lf, (char *) &ll, llsize )) == llsize) { 10341014Sbill for( i = 0; i < LMAX; i++ ) { 10351014Sbill pers->tty[ i ] = ll.ll_line[ i ]; 10361014Sbill } 10371014Sbill pers->tty[ LMAX ] = NULL; 10381014Sbill pers->loginat = ll.ll_time; 10391014Sbill } 10401014Sbill else { 10418842Smckusick if (i != 0) 10428842Smckusick fprintf(stderr, "finger: lastlog read error\n"); 10431014Sbill pers->tty[ 0 ] = NULL; 10441014Sbill pers->loginat = 0L; 10451014Sbill } 10461014Sbill } 10471014Sbill else { 10481014Sbill pers->tty[ 0 ] = NULL; 10491014Sbill pers->loginat = 0L; 10501014Sbill } 10511014Sbill } 10521014Sbill 10531014Sbill 10541014Sbill fwclose() 10551014Sbill { 10561014Sbill if( !llopenerr ) { 10571014Sbill close( lf ); 10581014Sbill } 10591014Sbill } 10601014Sbill 10611014Sbill 10621014Sbill /* find the idle time of a user by doing a stat on /dev/histty, 10631014Sbill * where histty has been gotten from USERLOG, supposedly. 10641014Sbill */ 10651014Sbill 10661014Sbill findidle( pers ) 10671014Sbill 10681014Sbill struct person *pers; 10691014Sbill { 10701014Sbill struct stat ttystatus; 10711014Sbill struct passwd *pwdt = pers->pwd; 10721014Sbill char buffer[ 20 ]; 10731014Sbill char *TTY = "/dev/"; 10741014Sbill int TTYLEN = strlen( TTY ); 10751014Sbill int i; 10761014Sbill 10771014Sbill strcpy( &buffer[0], TTY ); 10781014Sbill i = 0; 10791014Sbill do { 10801014Sbill buffer[ TTYLEN + i ] = pers->tty[ i ]; 10811014Sbill } while( ++i <= LMAX ); 10821014Sbill if( stat( &buffer[0], &ttystatus ) >= 0 ) { 10831014Sbill time( &tloc ); 10841014Sbill if( tloc < ttystatus.st_atime ) { 10851014Sbill pers->idletime = 0L; 10861014Sbill } 10871014Sbill else { 10881014Sbill pers->idletime = tloc - ttystatus.st_atime; 10891014Sbill } 10901014Sbill if( (ttystatus.st_mode & TALKABLE) == TALKABLE ) { 10911014Sbill pers->writeable = 1; 10921014Sbill } 10931014Sbill else { 10941014Sbill pers->writeable = 0; 10951014Sbill } 10961014Sbill } 10971014Sbill else { 10981014Sbill fprintf( stderr, "finger: error STATing %s\n", &buffer[0] ); 10991014Sbill exit( 4 ); 11001014Sbill } 11011014Sbill } 11021014Sbill 11031014Sbill 11041014Sbill /* print idle time in short format; this program always prints 4 characters; 11051014Sbill * if the idle time is zero, it prints 4 blanks. 11061014Sbill */ 11071014Sbill 11081014Sbill stimeprint( dt ) 11091014Sbill 11101014Sbill long *dt; 11111014Sbill { 11121014Sbill struct tm *gmtime(); 11131014Sbill struct tm *delta; 11141014Sbill 11151014Sbill delta = gmtime( dt ); 11161014Sbill if( delta->tm_yday == 0 ) { 11171014Sbill if( delta->tm_hour == 0 ) { 11181014Sbill if( delta->tm_min >= 10 ) { 11191014Sbill printf( " %2.2d ", delta->tm_min ); 11201014Sbill } 11211014Sbill else { 11221014Sbill if( delta->tm_min == 0 ) { 11231014Sbill printf( " " ); 11241014Sbill } 11251014Sbill else { 11261014Sbill printf( " %1.1d ", delta->tm_min ); 11271014Sbill } 11281014Sbill } 11291014Sbill } 11301014Sbill else { 11311014Sbill if( delta->tm_hour >= 10 ) { 11321014Sbill printf( "%3.3d:", delta->tm_hour ); 11331014Sbill } 11341014Sbill else { 11351014Sbill printf( "%1.1d:%02.2d", delta->tm_hour, delta->tm_min ); 11361014Sbill } 11371014Sbill } 11381014Sbill } 11391014Sbill else { 11401014Sbill printf( "%3dd", delta->tm_yday ); 11411014Sbill } 11421014Sbill } 11431014Sbill 11441014Sbill 11451014Sbill /* print idle time in long format with care being taken not to pluralize 11461014Sbill * 1 minutes or 1 hours or 1 days. 11471014Sbill */ 11481014Sbill 11491014Sbill ltimeprint( dt ) 11501014Sbill 11511014Sbill long *dt; 11521014Sbill { 11531014Sbill struct tm *gmtime(); 11541014Sbill struct tm *delta; 11551014Sbill int printed = 1; 11561014Sbill 11571014Sbill delta = gmtime( dt ); 11581014Sbill if( delta->tm_yday == 0 ) { 11591014Sbill if( delta->tm_hour == 0 ) { 11601014Sbill if( delta->tm_min >= 10 ) { 11611014Sbill printf( "%2d minutes", delta->tm_min ); 11621014Sbill } 11631014Sbill else { 11641014Sbill if( delta->tm_min == 0 ) { 11651014Sbill if( delta->tm_sec > 10 ) { 11661014Sbill printf( "%2d seconds", delta->tm_sec ); 11671014Sbill } 11681014Sbill else { 11691014Sbill printed = 0; 11701014Sbill } 11711014Sbill } 11721014Sbill else { 11731014Sbill if( delta->tm_min == 1 ) { 11741014Sbill if( delta->tm_sec == 1 ) { 11751014Sbill printf( "%1d minute %1d second", 11761014Sbill delta->tm_min, delta->tm_sec ); 11771014Sbill } 11781014Sbill else { 11791014Sbill printf( "%1d minute %d seconds", 11801014Sbill delta->tm_min, delta->tm_sec ); 11811014Sbill } 11821014Sbill } 11831014Sbill else { 11841014Sbill if( delta->tm_sec == 1 ) { 11851014Sbill printf( "%1d minutes %1d second", 11861014Sbill delta->tm_min, delta->tm_sec ); 11871014Sbill } 11881014Sbill else { 11891014Sbill printf( "%1d minutes %d seconds", 11901014Sbill delta->tm_min, delta->tm_sec ); 11911014Sbill } 11921014Sbill } 11931014Sbill } 11941014Sbill } 11951014Sbill } 11961014Sbill else { 11971014Sbill if( delta->tm_hour >= 10 ) { 11981014Sbill printf( "%2d hours", delta->tm_hour ); 11991014Sbill } 12001014Sbill else { 12011014Sbill if( delta->tm_hour == 1 ) { 12021014Sbill if( delta->tm_min == 1 ) { 12031014Sbill printf( "%1d hour %1d minute", 12041014Sbill delta->tm_hour, delta->tm_min ); 12051014Sbill } 12061014Sbill else { 12071014Sbill printf( "%1d hour %2d minutes", 12081014Sbill delta->tm_hour, delta->tm_min ); 12091014Sbill } 12101014Sbill } 12111014Sbill else { 12121014Sbill if( delta->tm_min == 1 ) { 12131014Sbill printf( "%1d hours %1d minute", 12141014Sbill delta->tm_hour, delta->tm_min ); 12151014Sbill } 12161014Sbill else { 12171014Sbill printf( "%1d hours %2d minutes", 12181014Sbill delta->tm_hour, delta->tm_min ); 12191014Sbill } 12201014Sbill } 12211014Sbill } 12221014Sbill } 12231014Sbill } 12241014Sbill else { 12251014Sbill if( delta->tm_yday >= 10 ) { 12261014Sbill printf( "%2d days", delta->tm_yday ); 12271014Sbill } 12281014Sbill else { 12291014Sbill if( delta->tm_yday == 1 ) { 12301014Sbill if( delta->tm_hour == 1 ) { 12311014Sbill printf( "%1d day %1d hour", 12321014Sbill delta->tm_yday, delta->tm_hour ); 12331014Sbill } 12341014Sbill else { 12351014Sbill printf( "%1d day %2d hours", 12361014Sbill delta->tm_yday, delta->tm_hour ); 12371014Sbill } 12381014Sbill } 12391014Sbill else { 12401014Sbill if( delta->tm_hour == 1 ) { 12411014Sbill printf( "%1d days %1d hour", 12421014Sbill delta->tm_yday, delta->tm_hour ); 12431014Sbill } 12441014Sbill else { 12451014Sbill printf( "%1d days %2d hours", 12461014Sbill delta->tm_yday, delta->tm_hour ); 12471014Sbill } 12481014Sbill } 12491014Sbill } 12501014Sbill } 12511014Sbill return( printed ); 12521014Sbill } 12531014Sbill 12541014Sbill 12551014Sbill matchcmp( gname, login, given ) 12561014Sbill 12571014Sbill char *gname; 12581014Sbill char *login; 12591014Sbill char *given; 12601014Sbill { 12611014Sbill char buffer[ 20 ]; 12621014Sbill char c; 12631014Sbill int flag, i, unfound; 12641014Sbill 12651014Sbill if( !match ) { 12661014Sbill return( 0 ); 12671014Sbill } 12681014Sbill else { 12691014Sbill if( namecmp( login, given ) ) { 12701014Sbill return( 1 ); 12711014Sbill } 12729623Sshannon else if (*gname == '\0') 12739623Sshannon return (0); 12741014Sbill else { 12751014Sbill if( *gname == ASTERISK ) { 12761014Sbill gname++; 12771014Sbill } 12781014Sbill flag = 1; 12791014Sbill i = 0; 12801014Sbill unfound = 1; 12811014Sbill while( unfound ) { 12821014Sbill if( flag ) { 12831014Sbill c = *gname++; 12841014Sbill if( c == SAMENAME ) { 12851014Sbill flag = 0; 12861014Sbill c = *login++; 12871014Sbill } 12881014Sbill else { 12891014Sbill unfound = (*gname != COMMA) && (*gname != NULL); 12901014Sbill } 12911014Sbill } 12921014Sbill else { 12931014Sbill c = *login++; 12941014Sbill if( c == NULL ) { 12951014Sbill if( (*gname == COMMA) || (*gname == NULL) ) { 12961014Sbill break; 12971014Sbill } 12981014Sbill else { 12991014Sbill flag = 1; 13001014Sbill continue; 13011014Sbill } 13021014Sbill } 13031014Sbill } 13041014Sbill if( c == BLANK ) { 13051014Sbill buffer[i++] = NULL; 13061014Sbill if( namecmp( buffer, given ) ) { 13071014Sbill return( 1 ); 13081014Sbill } 13091014Sbill i = 0; 13101014Sbill flag = 1; 13111014Sbill } 13121014Sbill else { 13131014Sbill buffer[ i++ ] = c; 13141014Sbill } 13151014Sbill } 13161014Sbill buffer[i++] = NULL; 13171014Sbill if( namecmp( buffer, given ) ) { 13181014Sbill return( 1 ); 13191014Sbill } 13201014Sbill else { 13211014Sbill return( 0 ); 13221014Sbill } 13231014Sbill } 13241014Sbill } 13251014Sbill } 13261014Sbill 13271014Sbill 13281014Sbill namecmp( name1, name2 ) 13291014Sbill 13301014Sbill char *name1; 13311014Sbill char *name2; 13321014Sbill { 13331014Sbill char c1, c2; 13341014Sbill 13351014Sbill c1 = *name1; 13361014Sbill if( (('A' <= c1) && (c1 <= 'Z')) || (('a' <= c1) && (c1 <= 'z')) ) { 13371014Sbill c1 = CAPITALIZE( c1 ); 13381014Sbill } 13391014Sbill c2 = *name2; 13401014Sbill if( (('A' <= c2) && (c2 <= 'Z')) || (('a' <= c2) && (c2 <= 'z')) ) { 13411014Sbill c2 = CAPITALIZE( c2 ); 13421014Sbill } 13431014Sbill while( c1 == c2 ) { 13441014Sbill if( c1 == NULL ) { 13451014Sbill return( 1 ); 13461014Sbill } 13471014Sbill c1 = *++name1; 13481014Sbill if( (('A'<=c1) && (c1<='Z')) || (('a'<=c1) && (c1<='z')) ) { 13491014Sbill c1 = CAPITALIZE( c1 ); 13501014Sbill } 13511014Sbill c2 = *++name2; 13521014Sbill if( (('A'<=c2) && (c2<='Z')) || (('a'<=c2) && (c2<='z')) ) { 13531014Sbill c2 = CAPITALIZE( c2 ); 13541014Sbill } 13551014Sbill } 13561014Sbill if( *name1 == NULL ) { 13571014Sbill while( ('0' <= *name2) && (*name2 <= '9') ) { 13581014Sbill name2++; 13591014Sbill } 13601014Sbill if( *name2 == NULL ) { 13611014Sbill return( 1 ); 13621014Sbill } 13631014Sbill } 13641014Sbill else { 13651014Sbill if( *name2 == NULL ) { 13661014Sbill while( ('0' <= *name1) && (*name1 <= '9') ) { 13671014Sbill name1++; 13681014Sbill } 13691014Sbill if( *name1 == NULL ) { 13701014Sbill return( 1 ); 13711014Sbill } 13721014Sbill } 13731014Sbill } 13741014Sbill return( 0 ); 13751014Sbill } 13761014Sbill 13771014Sbill 13781014Sbill char *strsave( s ) 13791014Sbill 13801014Sbill char *s; 13811014Sbill { 13821014Sbill char *malloc(); 13831014Sbill char *p; 13841014Sbill 13851014Sbill p = malloc( strlen( s ) + 1 ); 13861014Sbill strcpy( p, s ); 13871014Sbill } 1388*16469Ssam 1389*16469Ssam netfinger(name) 1390*16469Ssam char *name; 1391*16469Ssam { 1392*16469Ssam char *host; 1393*16469Ssam char fname[100]; 1394*16469Ssam struct hostent *hp; 1395*16469Ssam struct servent *sp; 1396*16469Ssam struct sockaddr_in sin; 1397*16469Ssam int s; 1398*16469Ssam char *rindex(); 1399*16469Ssam register FILE *f; 1400*16469Ssam register int c; 1401*16469Ssam register int lastc; 1402*16469Ssam 1403*16469Ssam if (name == NULL) 1404*16469Ssam return(0); 1405*16469Ssam host = rindex(name, '@'); 1406*16469Ssam if (host == NULL) 1407*16469Ssam return(0); 1408*16469Ssam *host++ = 0; 1409*16469Ssam hp = gethostbyname(host); 1410*16469Ssam if (hp == NULL) { 1411*16469Ssam static struct hostent def; 1412*16469Ssam static struct in_addr defaddr; 1413*16469Ssam static char namebuf[128]; 1414*16469Ssam int inet_addr(); 1415*16469Ssam 1416*16469Ssam defaddr.s_addr = inet_addr(host); 1417*16469Ssam if (defaddr.s_addr == -1) { 1418*16469Ssam printf("unknown host: %s\n", host); 1419*16469Ssam return(1); 1420*16469Ssam } 1421*16469Ssam strcpy(namebuf, host); 1422*16469Ssam def.h_name = namebuf; 1423*16469Ssam def.h_addr = (char *)&defaddr; 1424*16469Ssam def.h_length = sizeof (struct in_addr); 1425*16469Ssam def.h_addrtype = AF_INET; 1426*16469Ssam def.h_aliases = 0; 1427*16469Ssam hp = &def; 1428*16469Ssam } 1429*16469Ssam printf("[%s]", hp->h_name); 1430*16469Ssam sp = getservbyname("finger", "tcp"); 1431*16469Ssam if (sp == 0) { 1432*16469Ssam printf("tcp/finger: unknown service\n"); 1433*16469Ssam return(1); 1434*16469Ssam } 1435*16469Ssam sin.sin_family = hp->h_addrtype; 1436*16469Ssam bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length); 1437*16469Ssam sin.sin_port = sp->s_port; 1438*16469Ssam s = socket(hp->h_addrtype, SOCK_STREAM, 0); 1439*16469Ssam if (s < 0) { 1440*16469Ssam fflush(stdout); 1441*16469Ssam perror("socket"); 1442*16469Ssam return(1); 1443*16469Ssam } 1444*16469Ssam if (connect(s, (char *)&sin, sizeof (sin)) < 0) { 1445*16469Ssam fflush(stdout); 1446*16469Ssam perror("connect"); 1447*16469Ssam close(s); 1448*16469Ssam return(1); 1449*16469Ssam } 1450*16469Ssam printf("\n"); 1451*16469Ssam if (large) write(s, "/W ", 3); 1452*16469Ssam write(s, name, strlen(name)); 1453*16469Ssam write(s, "\r\n", 2); 1454*16469Ssam f = fdopen(s, "r"); 1455*16469Ssam while ((c = getc(f)) != EOF) { 1456*16469Ssam switch(c) { 1457*16469Ssam case 0210: 1458*16469Ssam case 0211: 1459*16469Ssam case 0212: 1460*16469Ssam case 0214: 1461*16469Ssam c -= 0200; 1462*16469Ssam break; 1463*16469Ssam case 0215: 1464*16469Ssam c = '\n'; 1465*16469Ssam break; 1466*16469Ssam } 1467*16469Ssam putchar(lastc = c); 1468*16469Ssam } 1469*16469Ssam if (lastc != '\n') 1470*16469Ssam putchar('\n'); 1471*16469Ssam return(1); 1472*16469Ssam } 1473