1*1014Sbill static char *sccsid = "@(#)finger.c 4.1 (Berkeley) 10/01/80"; 2*1014Sbill 3*1014Sbill /* This is a finger program. It prints out useful information about users 4*1014Sbill * by digging it up from various system files. It is not very portable 5*1014Sbill * because the most useful parts of the information (the full user name, 6*1014Sbill * office, and phone numbers) are all stored in the VAX-unused gecos field 7*1014Sbill * of /etc/passwd, which, unfortunately, other UNIXes use for other things. 8*1014Sbill * 9*1014Sbill * There are three output formats, all of which give login name, teletype 10*1014Sbill * line number, and login time. The short output format is reminiscent 11*1014Sbill * of finger on ITS, and gives one line of information per user containing 12*1014Sbill * in addition to the minimum basic requirements (MBR), the full name of 13*1014Sbill * the user, his idle time and office location and phone number. The 14*1014Sbill * quick style output is UNIX who-like, giving only name, teletype and 15*1014Sbill * login time. Finally, the long style output give the same information 16*1014Sbill * as the short (in more legible format), the home directory and shell 17*1014Sbill * of the user, and, if it exits, a copy of the file .plan in the users 18*1014Sbill * home directory. Finger may be called with or without a list of people 19*1014Sbill * to finger -- if no list is given, all the people currently logged in 20*1014Sbill * are fingered. 21*1014Sbill * 22*1014Sbill * The program is validly called by one of the following: 23*1014Sbill * 24*1014Sbill * finger {short form list of users} 25*1014Sbill * finger -l {long form list of users} 26*1014Sbill * finger -b {briefer long form list of users} 27*1014Sbill * finger -q {quick list of users} 28*1014Sbill * finger -i {quick list of users with idle times} 29*1014Sbill * finger namelist {long format list of specified users} 30*1014Sbill * finger -s namelist {short format list of specified users} 31*1014Sbill * finger -w namelist {narrow short format list of specified users} 32*1014Sbill * 33*1014Sbill * where 'namelist' is a list of users login names. 34*1014Sbill * The other options can all be given after one '-', or each can have its 35*1014Sbill * own '-'. The -f option disables the printing of headers for short and 36*1014Sbill * quick outputs. The -b option briefens long format outputs. The -p 37*1014Sbill * option turns off plans for long format outputs. 38*1014Sbill */ 39*1014Sbill 40*1014Sbill #include <sys/types.h> 41*1014Sbill #include <sys/stat.h> 42*1014Sbill #include <sgtty.h> 43*1014Sbill #include <utmp.h> 44*1014Sbill #include <signal.h> 45*1014Sbill #include <pwd.h> 46*1014Sbill #include <stdio.h> 47*1014Sbill #include <sccs.h> 48*1014Sbill #include <lastlog.h> 49*1014Sbill #include <time.h> 50*1014Sbill 51*1014Sbill struct utmp utmp; /* for sizeof */ 52*1014Sbill #define NMAX sizeof(utmp.ut_name) 53*1014Sbill #define LMAX sizeof(utmp.ut_line) 54*1014Sbill 55*1014Sbill #define ASTERISK '*' /* ignore this in real name */ 56*1014Sbill #define BLANK ' ' /* blank character (i.e. space) */ 57*1014Sbill #define CAPITALIZE 0137& /* capitalize character macro */ 58*1014Sbill #define COMMA ',' /* separator in pw_gecos field */ 59*1014Sbill #define COMMAND '-' /* command line flag char */ 60*1014Sbill #define CORY 'C' /* cory hall office */ 61*1014Sbill #define EVANS 'E' /* evans hall office */ 62*1014Sbill #define LINEBREAK 012 /* line feed */ 63*1014Sbill #define NULLSTR "" /* the null string, opposed to NULL */ 64*1014Sbill #define SAMENAME '&' /* repeat login name in real name */ 65*1014Sbill #define TALKABLE 0222 /* tty is writeable if 222 mode */ 66*1014Sbill 67*1014Sbill struct person { /* one for each person fingered */ 68*1014Sbill char name[NMAX+1]; /* login name */ 69*1014Sbill char tty[LMAX+1]; /* NULL terminated tty line */ 70*1014Sbill long loginat; /* time of login (possibly last) */ 71*1014Sbill long idletime; /* how long idle (if logged in) */ 72*1014Sbill short int loggedin; /* flag for being logged in */ 73*1014Sbill short int writeable; /* flag for tty being writeable */ 74*1014Sbill char *realname; /* pointer to full name */ 75*1014Sbill char *office; /* pointer to office name */ 76*1014Sbill char *officephone; /* pointer to office phone no. */ 77*1014Sbill char *homephone; /* pointer to home phone no. */ 78*1014Sbill char *random; /* for any random stuff in pw_gecos */ 79*1014Sbill struct passwd *pwd; /* structure of /etc/passwd stuff */ 80*1014Sbill struct person *link; /* link to next person */ 81*1014Sbill }; 82*1014Sbill 83*1014Sbill struct passwd *NILPWD = 0; 84*1014Sbill struct person *NILPERS = 0; 85*1014Sbill 86*1014Sbill int persize = sizeof( struct person ); 87*1014Sbill int pwdsize = sizeof( struct passwd ); 88*1014Sbill 89*1014Sbill char LASTLOG[] = "/usr/adm/lastlog"; /* last login info */ 90*1014Sbill char USERLOG[] = "/etc/utmp"; /* who is logged in */ 91*1014Sbill char outbuf[BUFSIZ]; /* output buffer */ 92*1014Sbill char *ctime(); 93*1014Sbill 94*1014Sbill int unbrief = 1; /* -b option default */ 95*1014Sbill int header = 1; /* -f option default */ 96*1014Sbill int hack = 1; /* -h option default */ 97*1014Sbill int idle = 0; /* -i option default */ 98*1014Sbill int large = 0; /* -l option default */ 99*1014Sbill int match = 1; /* -m option default */ 100*1014Sbill int plan = 1; /* -p option default */ 101*1014Sbill int unquick = 1; /* -q option default */ 102*1014Sbill int small = 0; /* -s option default */ 103*1014Sbill int wide = 1; /* -w option default */ 104*1014Sbill 105*1014Sbill int lf; 106*1014Sbill int llopenerr; 107*1014Sbill 108*1014Sbill long tloc; /* current time */ 109*1014Sbill 110*1014Sbill 111*1014Sbill 112*1014Sbill main( argc, argv ) 113*1014Sbill 114*1014Sbill int argc; 115*1014Sbill char *argv[]; 116*1014Sbill 117*1014Sbill { 118*1014Sbill FILE *fp, *fopen(); /* for plans */ 119*1014Sbill struct passwd *getpwent(); /* read /etc/passwd */ 120*1014Sbill struct person *person1, *p, *pend; /* people */ 121*1014Sbill struct passwd *pw; /* temporary */ 122*1014Sbill struct utmp user; /* ditto */ 123*1014Sbill char *malloc(); 124*1014Sbill char *s, *pn, *ln; 125*1014Sbill char c; 126*1014Sbill char *PLAN = "/.plan"; /* what plan file is */ 127*1014Sbill char *PROJ = "/.project"; /* what project file */ 128*1014Sbill int PLANLEN = strlen( PLAN ); 129*1014Sbill int PROJLEN = strlen( PROJ ); 130*1014Sbill int numnames = 0; 131*1014Sbill int orgnumnames; 132*1014Sbill int uf; 133*1014Sbill int usize = sizeof user; 134*1014Sbill int unshort; 135*1014Sbill int i, j; 136*1014Sbill int fngrlogin; 137*1014Sbill 138*1014Sbill setbuf( stdout, outbuf ); /* buffer output */ 139*1014Sbill 140*1014Sbill /* parse command line for (optional) arguments */ 141*1014Sbill 142*1014Sbill i = 1; 143*1014Sbill if( strcmp( *argv, "sh" ) ) { 144*1014Sbill fngrlogin = 0; 145*1014Sbill while( i++ < argc && (*++argv)[0] == COMMAND ) { 146*1014Sbill for( s = argv[0] + 1; *s != NULL; s++ ) { 147*1014Sbill switch (*s) { 148*1014Sbill 149*1014Sbill case 'b': 150*1014Sbill unbrief = 0; 151*1014Sbill break; 152*1014Sbill 153*1014Sbill case 'f': 154*1014Sbill header = 0; 155*1014Sbill break; 156*1014Sbill 157*1014Sbill case 'h': 158*1014Sbill hack = 0; 159*1014Sbill break; 160*1014Sbill 161*1014Sbill case 'i': 162*1014Sbill idle = 1; 163*1014Sbill unquick = 0; 164*1014Sbill break; 165*1014Sbill 166*1014Sbill case 'l': 167*1014Sbill large = 1; 168*1014Sbill break; 169*1014Sbill 170*1014Sbill case 'm': 171*1014Sbill match = 0; 172*1014Sbill break; 173*1014Sbill 174*1014Sbill case 'p': 175*1014Sbill plan = 0; 176*1014Sbill break; 177*1014Sbill 178*1014Sbill case 'q': 179*1014Sbill unquick = 0; 180*1014Sbill break; 181*1014Sbill 182*1014Sbill case 's': 183*1014Sbill small = 1; 184*1014Sbill break; 185*1014Sbill 186*1014Sbill case 'w': 187*1014Sbill wide = 0; 188*1014Sbill break; 189*1014Sbill 190*1014Sbill default: 191*1014Sbill fprintf( stderr, "finger: Usage -- 'finger [-bfhilmpqsw] [login1 [login2 ...] ]'\n" ); 192*1014Sbill exit( 1 ); 193*1014Sbill } 194*1014Sbill } 195*1014Sbill } 196*1014Sbill } 197*1014Sbill else { 198*1014Sbill fngrlogin = 1; 199*1014Sbill } 200*1014Sbill if( unquick ) { 201*1014Sbill time( &tloc ); 202*1014Sbill } 203*1014Sbill else { 204*1014Sbill if( idle ) { 205*1014Sbill time( &tloc ); 206*1014Sbill } 207*1014Sbill } 208*1014Sbill 209*1014Sbill /* i > argc means no login names given so get them by reading USERLOG */ 210*1014Sbill 211*1014Sbill if( (i > argc) || fngrlogin ) { 212*1014Sbill unshort = large; 213*1014Sbill if( ( uf = open(USERLOG, 0) ) >= 0 ) { 214*1014Sbill user.ut_name[0] = NULL; 215*1014Sbill while( user.ut_name[0] == NULL ) { 216*1014Sbill if( read( uf, (char *) &user, usize ) != usize ) { 217*1014Sbill printf( "\nNo one logged on\n" ); 218*1014Sbill exit( 0 ); 219*1014Sbill } 220*1014Sbill } 221*1014Sbill person1 = (struct person *) malloc( persize ); 222*1014Sbill for( j = 0; j < NMAX; j++ ) { 223*1014Sbill person1->tty[j] = user.ut_line[j]; 224*1014Sbill person1->name[j] = user.ut_name[j]; 225*1014Sbill } 226*1014Sbill person1->name[NMAX] = NULL; 227*1014Sbill person1->tty[NMAX] = NULL; 228*1014Sbill person1->loginat = user.ut_time; 229*1014Sbill person1->pwd = NILPWD; 230*1014Sbill person1->loggedin = 1; 231*1014Sbill numnames++; 232*1014Sbill p = person1; 233*1014Sbill while( read( uf, (char *) &user, usize ) == usize ) { 234*1014Sbill if( user.ut_name[0] == NULL ) continue; 235*1014Sbill p->link = (struct person *) malloc( persize ); 236*1014Sbill p = p->link; 237*1014Sbill for( j = 0; j < NMAX; j++ ) { 238*1014Sbill p->tty[j] = user.ut_line[j]; 239*1014Sbill p->name[j] = user.ut_name[j]; 240*1014Sbill } 241*1014Sbill p->name[NMAX] = NULL; 242*1014Sbill p->tty[NMAX] = NULL; 243*1014Sbill p->loginat = user.ut_time; 244*1014Sbill p->pwd = NILPWD; 245*1014Sbill p->loggedin = 1; 246*1014Sbill numnames++; 247*1014Sbill } 248*1014Sbill p->link = NILPERS; 249*1014Sbill close( uf ); 250*1014Sbill } 251*1014Sbill else { 252*1014Sbill fprintf( stderr, "finger: error opening %s\n", USERLOG ); 253*1014Sbill exit( 2 ); 254*1014Sbill } 255*1014Sbill 256*1014Sbill /* if we are doing it, read /etc/passwd for the useful info */ 257*1014Sbill 258*1014Sbill if( unquick ) { 259*1014Sbill setpwent(); 260*1014Sbill fwopen(); 261*1014Sbill i = numnames; 262*1014Sbill while( ( (pw = getpwent()) != NILPWD ) && ( i > 0 ) ) { 263*1014Sbill p = person1; 264*1014Sbill do { 265*1014Sbill if( p->pwd == NILPWD ) { 266*1014Sbill if( strcmp( p->name, pw->pw_name ) == 0 ) { 267*1014Sbill p->pwd = (struct passwd *) malloc( pwdsize ); 268*1014Sbill pwdcopy( p->pwd, pw ); 269*1014Sbill decode( p ); 270*1014Sbill i--; 271*1014Sbill } 272*1014Sbill } 273*1014Sbill p = p->link; 274*1014Sbill } while( p != NILPERS ); 275*1014Sbill } 276*1014Sbill fwclose(); 277*1014Sbill endpwent(); 278*1014Sbill } 279*1014Sbill } 280*1014Sbill 281*1014Sbill /* get names from command line and check to see if they're logged in */ 282*1014Sbill 283*1014Sbill else { 284*1014Sbill unshort = ( small == 1 ? 0 : 1 ); 285*1014Sbill i++; 286*1014Sbill person1 = (struct person *) malloc( persize ); 287*1014Sbill strcpy( person1->name, (argv++)[ 0 ] ); 288*1014Sbill person1->loggedin = 0; 289*1014Sbill person1->pwd = NILPWD; 290*1014Sbill numnames++; 291*1014Sbill p = person1; 292*1014Sbill while( i++ <= argc ) { 293*1014Sbill p->link = (struct person *) malloc( persize ); 294*1014Sbill p = p->link; 295*1014Sbill strcpy( p->name, (argv++)[ 0 ] ); 296*1014Sbill p->loggedin = 0; 297*1014Sbill p->pwd = NILPWD; 298*1014Sbill numnames++; 299*1014Sbill } 300*1014Sbill p->link = NILPERS; 301*1014Sbill pend = p; 302*1014Sbill 303*1014Sbill /* if we are doing it, read /etc/passwd for the useful info */ 304*1014Sbill 305*1014Sbill orgnumnames = numnames; 306*1014Sbill if( unquick ) { 307*1014Sbill setpwent(); 308*1014Sbill while( ( pw = getpwent() ) != NILPWD ) { 309*1014Sbill p = person1; 310*1014Sbill i = 0; 311*1014Sbill do { 312*1014Sbill if( strcmp( p->name, pw->pw_name ) == 0 || 313*1014Sbill matchcmp( pw->pw_gecos, pw->pw_name, p->name ) ) { 314*1014Sbill if( p->pwd == NILPWD ) { 315*1014Sbill p->pwd = (struct passwd *) malloc( pwdsize ); 316*1014Sbill pwdcopy( p->pwd, pw ); 317*1014Sbill } 318*1014Sbill else { /* handle multiple logins -- append new 319*1014Sbill "duplicate" entry to end of list */ 320*1014Sbill pend->link = (struct person *) malloc(persize); 321*1014Sbill pend = pend->link; 322*1014Sbill pend->link = NILPERS; 323*1014Sbill strcpy( pend->name, p->name ); 324*1014Sbill pend->pwd = (struct passwd *) malloc(pwdsize); 325*1014Sbill pwdcopy( pend->pwd, pw ); 326*1014Sbill numnames++; 327*1014Sbill } 328*1014Sbill } 329*1014Sbill p = p->link; 330*1014Sbill } while( ++i < orgnumnames ); 331*1014Sbill } 332*1014Sbill endpwent(); 333*1014Sbill } 334*1014Sbill 335*1014Sbill /* Now get login information */ 336*1014Sbill 337*1014Sbill if( ( uf = open(USERLOG, 0) ) >= 0 ) { 338*1014Sbill while( read( uf, (char *) &user, usize ) == usize ) { 339*1014Sbill if( user.ut_name[0] == NULL ) continue; 340*1014Sbill p = person1; 341*1014Sbill do { 342*1014Sbill pw = p->pwd; 343*1014Sbill if( pw == NILPWD ) { 344*1014Sbill i = ( strcmp( p->name, user.ut_name ) ? 0 : NMAX ); 345*1014Sbill } 346*1014Sbill else { 347*1014Sbill i = 0; 348*1014Sbill while( (i < NMAX) && 349*1014Sbill ( pw->pw_name[i] == user.ut_name[i]) ) { 350*1014Sbill if( pw->pw_name[i] == NULL ) { 351*1014Sbill i = NMAX; 352*1014Sbill break; 353*1014Sbill } 354*1014Sbill i++; 355*1014Sbill } 356*1014Sbill } 357*1014Sbill if( i == NMAX ) { 358*1014Sbill if( p->loggedin == 1 ) { 359*1014Sbill pend->link = (struct person *) malloc(persize); 360*1014Sbill pend = pend->link; 361*1014Sbill pend->link = NILPERS; 362*1014Sbill strcpy( pend->name, p->name ); 363*1014Sbill for( j = 0; j < NMAX; j++ ) { 364*1014Sbill pend->tty[j] = user.ut_line[j]; 365*1014Sbill } 366*1014Sbill pend->tty[ NMAX ] = NULL; 367*1014Sbill pend->loginat = user.ut_time; 368*1014Sbill pend->loggedin = 2; 369*1014Sbill if( pw == NILPWD ) { 370*1014Sbill pend ->pwd = NILPWD; 371*1014Sbill } 372*1014Sbill else { 373*1014Sbill pend->pwd = (struct passwd *) malloc(pwdsize); 374*1014Sbill pwdcopy( pend->pwd, pw ); 375*1014Sbill } 376*1014Sbill numnames++; 377*1014Sbill } 378*1014Sbill else { 379*1014Sbill if( p->loggedin != 2 ) { 380*1014Sbill for( j = 0; j < NMAX; j++ ) { 381*1014Sbill p->tty[j] = user.ut_line[j]; 382*1014Sbill } 383*1014Sbill p->tty[ NMAX ] = NULL; 384*1014Sbill p->loginat = user.ut_time; 385*1014Sbill p->loggedin = 1; 386*1014Sbill } 387*1014Sbill } 388*1014Sbill } 389*1014Sbill p = p->link; 390*1014Sbill } while( p != NILPERS ); 391*1014Sbill } 392*1014Sbill fwopen(); 393*1014Sbill p = person1; 394*1014Sbill while( p != NILPERS ) { 395*1014Sbill if( p->loggedin == 2 ) { 396*1014Sbill p->loggedin = 1; 397*1014Sbill } 398*1014Sbill decode( p ); 399*1014Sbill p = p->link; 400*1014Sbill } 401*1014Sbill fwclose(); 402*1014Sbill close( uf ); 403*1014Sbill } 404*1014Sbill else { 405*1014Sbill fprintf( stderr, "finger: error opening %s\n", USERLOG ); 406*1014Sbill exit( 2 ); 407*1014Sbill } 408*1014Sbill } 409*1014Sbill 410*1014Sbill /* print out what we got */ 411*1014Sbill 412*1014Sbill if( header ) { 413*1014Sbill if( unquick ) { 414*1014Sbill if( !unshort ) { 415*1014Sbill if( wide ) { 416*1014Sbill printf( 417*1014Sbill "Login Name TTY Idle When Office\n" ); 418*1014Sbill } 419*1014Sbill else { 420*1014Sbill printf( 421*1014Sbill "Login TTY Idle When Office\n" ); 422*1014Sbill } 423*1014Sbill } 424*1014Sbill } 425*1014Sbill else { 426*1014Sbill printf( "Login TTY When" ); 427*1014Sbill if( idle ) { 428*1014Sbill printf( " Idle" ); 429*1014Sbill } 430*1014Sbill printf( "\n" ); 431*1014Sbill } 432*1014Sbill } 433*1014Sbill p = person1; 434*1014Sbill do { 435*1014Sbill if( unquick ) { 436*1014Sbill if( unshort ) { 437*1014Sbill personprint( p ); 438*1014Sbill if( p->pwd != NILPWD ) { 439*1014Sbill if( hack ) { 440*1014Sbill s = malloc(strlen((p->pwd)->pw_dir) + PROJLEN + 1 ); 441*1014Sbill strcpy( s, (p->pwd)->pw_dir ); 442*1014Sbill strcat( s, PROJ ); 443*1014Sbill if( ( fp = fopen( s, "r") ) != NULL ) { 444*1014Sbill printf( "Project: " ); 445*1014Sbill while( ( c = getc(fp) ) != EOF ) { 446*1014Sbill if( c == LINEBREAK ) { 447*1014Sbill break; 448*1014Sbill } 449*1014Sbill putc( c, stdout ); 450*1014Sbill } 451*1014Sbill fclose( fp ); 452*1014Sbill printf( "\n" ); 453*1014Sbill } 454*1014Sbill } 455*1014Sbill if( plan ) { 456*1014Sbill s = malloc( strlen( (p->pwd)->pw_dir ) + PLANLEN + 1 ); 457*1014Sbill strcpy( s, (p->pwd)->pw_dir ); 458*1014Sbill strcat( s, PLAN ); 459*1014Sbill if( ( fp = fopen( s, "r") ) == NULL ) { 460*1014Sbill printf( "No Plan.\n" ); 461*1014Sbill } 462*1014Sbill else { 463*1014Sbill printf( "Plan:\n" ); 464*1014Sbill while( ( c = getc(fp) ) != EOF ) { 465*1014Sbill putc( c, stdout ); 466*1014Sbill } 467*1014Sbill fclose( fp ); 468*1014Sbill } 469*1014Sbill } 470*1014Sbill } 471*1014Sbill if( p->link != NILPERS ) { 472*1014Sbill printf( "\n" ); 473*1014Sbill } 474*1014Sbill } 475*1014Sbill else { 476*1014Sbill shortprint( p ); 477*1014Sbill } 478*1014Sbill } 479*1014Sbill else { 480*1014Sbill quickprint( p ); 481*1014Sbill } 482*1014Sbill p = p->link; 483*1014Sbill } while( p != NILPERS ); 484*1014Sbill exit(0); 485*1014Sbill } 486*1014Sbill 487*1014Sbill 488*1014Sbill /* given a pointer to a pwd (pfrom) copy it to another one, allocating 489*1014Sbill * space for all the stuff in it. Note: Only the useful (what the 490*1014Sbill * program currently uses) things are copied. 491*1014Sbill */ 492*1014Sbill 493*1014Sbill pwdcopy( pto, pfrom ) /* copy relevant fields only */ 494*1014Sbill 495*1014Sbill struct passwd *pto, *pfrom; 496*1014Sbill { 497*1014Sbill pto->pw_name = malloc( strlen( pfrom->pw_name ) + 1 ); 498*1014Sbill strcpy( pto->pw_name, pfrom->pw_name ); 499*1014Sbill pto->pw_uid = pfrom->pw_uid; 500*1014Sbill pto->pw_gecos = malloc( strlen( pfrom->pw_gecos ) + 1 ); 501*1014Sbill strcpy( pto->pw_gecos, pfrom->pw_gecos ); 502*1014Sbill pto->pw_dir = malloc( strlen( pfrom->pw_dir ) + 1 ); 503*1014Sbill strcpy( pto->pw_dir, pfrom->pw_dir ); 504*1014Sbill pto->pw_shell = malloc( strlen( pfrom->pw_shell ) + 1 ); 505*1014Sbill strcpy( pto->pw_shell, pfrom->pw_shell ); 506*1014Sbill } 507*1014Sbill 508*1014Sbill 509*1014Sbill /* print out information on quick format giving just name, tty, login time 510*1014Sbill * and idle time if idle is set. 511*1014Sbill */ 512*1014Sbill 513*1014Sbill quickprint( pers ) 514*1014Sbill 515*1014Sbill struct person *pers; 516*1014Sbill { 517*1014Sbill int idleprinted; 518*1014Sbill 519*1014Sbill printf( "%-*.*s", NMAX, NMAX, pers->name ); 520*1014Sbill printf( " " ); 521*1014Sbill if( pers->loggedin ) { 522*1014Sbill if( idle ) { 523*1014Sbill findidle( pers ); 524*1014Sbill if( pers->writeable ) { 525*1014Sbill printf( " %-*.*s %-16.16s", LMAX, LMAX, 526*1014Sbill pers->tty, ctime( &pers->loginat ) ); 527*1014Sbill } 528*1014Sbill else { 529*1014Sbill printf( "*%-*.*s %-16.16s", LMAX, LMAX, 530*1014Sbill pers->tty, ctime( &pers->loginat ) ); 531*1014Sbill } 532*1014Sbill printf( " " ); 533*1014Sbill idleprinted = ltimeprint( &pers->idletime ); 534*1014Sbill } 535*1014Sbill else { 536*1014Sbill printf( " %-*.*s %-16.16s", LMAX, LMAX, 537*1014Sbill pers->tty, ctime( &pers->loginat ) ); 538*1014Sbill } 539*1014Sbill } 540*1014Sbill else { 541*1014Sbill printf( " Not Logged In" ); 542*1014Sbill } 543*1014Sbill printf( "\n" ); 544*1014Sbill } 545*1014Sbill 546*1014Sbill 547*1014Sbill /* print out information in short format, giving login name, full name, 548*1014Sbill * tty, idle time, login time, office location and phone. 549*1014Sbill */ 550*1014Sbill 551*1014Sbill shortprint( pers ) 552*1014Sbill 553*1014Sbill struct person *pers; 554*1014Sbill 555*1014Sbill { 556*1014Sbill struct passwd *pwdt = pers->pwd; 557*1014Sbill char buf[ 26 ]; 558*1014Sbill int i, len, offset, dialup; 559*1014Sbill 560*1014Sbill if( pwdt == NILPWD ) { 561*1014Sbill printf( "%-*.*s", NMAX, NMAX, pers->name ); 562*1014Sbill printf( " ???\n" ); 563*1014Sbill return; 564*1014Sbill } 565*1014Sbill printf( "%-*.*s", NMAX, NMAX, pwdt->pw_name ); 566*1014Sbill dialup = 0; 567*1014Sbill if( wide ) { 568*1014Sbill if( strlen( pers->realname ) > 0 ) { 569*1014Sbill printf( " %-20.20s", pers->realname ); 570*1014Sbill } 571*1014Sbill else { 572*1014Sbill printf( " ??? " ); 573*1014Sbill } 574*1014Sbill } 575*1014Sbill if( pers->loggedin ) { 576*1014Sbill if( pers->writeable ) { 577*1014Sbill printf( " " ); 578*1014Sbill } 579*1014Sbill else { 580*1014Sbill printf( " *" ); 581*1014Sbill } 582*1014Sbill } 583*1014Sbill else { 584*1014Sbill printf( " " ); 585*1014Sbill } 586*1014Sbill if( strlen( pers->tty ) > 0 ) { 587*1014Sbill strcpy( buf, pers->tty ); 588*1014Sbill if( (buf[0] == 't') && (buf[1] == 't') && (buf[2] == 'y') ) { 589*1014Sbill offset = 3; 590*1014Sbill for( i = 0; i < 2; i++ ) { 591*1014Sbill buf[i] = buf[i + offset]; 592*1014Sbill } 593*1014Sbill } 594*1014Sbill if( (buf[0] == 'd') && pers->loggedin ) { 595*1014Sbill dialup = 1; 596*1014Sbill } 597*1014Sbill printf( "%-2.2s ", buf ); 598*1014Sbill } 599*1014Sbill else { 600*1014Sbill printf( " " ); 601*1014Sbill } 602*1014Sbill strcpy( buf, ctime( &pers->loginat ) ); 603*1014Sbill if( pers->loggedin ) { 604*1014Sbill stimeprint( &pers->idletime ); 605*1014Sbill offset = 7; 606*1014Sbill for( i = 4; i < 19; i++ ) { 607*1014Sbill buf[i] = buf[i + offset]; 608*1014Sbill } 609*1014Sbill printf( " %-9.9s ", buf ); 610*1014Sbill } 611*1014Sbill else { 612*1014Sbill printf( " " ); 613*1014Sbill offset = 4; 614*1014Sbill for( i = 0; i <22; i++ ) { 615*1014Sbill buf[i] = buf[i + offset]; 616*1014Sbill } 617*1014Sbill printf( "<%-12.12s>", buf ); 618*1014Sbill } 619*1014Sbill len = strlen( pers->homephone ); 620*1014Sbill if( dialup && (len > 0) ) { 621*1014Sbill if( len == 8 ) { 622*1014Sbill printf( " " ); 623*1014Sbill } 624*1014Sbill else { 625*1014Sbill if( len == 12 ) { 626*1014Sbill printf( " " ); 627*1014Sbill } 628*1014Sbill else { 629*1014Sbill for( i = 1; i <= 21 - len; i++ ) { 630*1014Sbill printf( " " ); 631*1014Sbill } 632*1014Sbill } 633*1014Sbill } 634*1014Sbill printf( "%s", pers->homephone ); 635*1014Sbill } 636*1014Sbill else { 637*1014Sbill if( strlen( pers->office ) > 0 ) { 638*1014Sbill printf( " %-11.11s", pers->office ); 639*1014Sbill if( strlen( pers->officephone ) > 0 ) { 640*1014Sbill printf( " %8.8s", pers->officephone ); 641*1014Sbill } 642*1014Sbill else { 643*1014Sbill if( len == 8 ) { 644*1014Sbill printf( " %8.8s", pers->homephone ); 645*1014Sbill } 646*1014Sbill } 647*1014Sbill } 648*1014Sbill else { 649*1014Sbill if( strlen( pers->officephone ) > 0 ) { 650*1014Sbill printf( " %8.8s", pers->officephone ); 651*1014Sbill } 652*1014Sbill else { 653*1014Sbill if( len == 8 ) { 654*1014Sbill printf( " %8.8s", pers->homephone ); 655*1014Sbill } 656*1014Sbill else { 657*1014Sbill if( len == 12 ) { 658*1014Sbill printf( " %12.12s", pers->homephone ); 659*1014Sbill } 660*1014Sbill } 661*1014Sbill } 662*1014Sbill } 663*1014Sbill } 664*1014Sbill printf( "\n" ); 665*1014Sbill } 666*1014Sbill 667*1014Sbill 668*1014Sbill /* print out a person in long format giving all possible information. 669*1014Sbill * directory and shell are inhibited if unbrief is clear. 670*1014Sbill */ 671*1014Sbill 672*1014Sbill personprint( pers ) 673*1014Sbill 674*1014Sbill struct person *pers; 675*1014Sbill { 676*1014Sbill struct passwd *pwdt = pers->pwd; 677*1014Sbill int idleprinted; 678*1014Sbill 679*1014Sbill if( pwdt == NILPWD ) { 680*1014Sbill printf( "Login name: %-10s", pers->name ); 681*1014Sbill printf( " " ); 682*1014Sbill printf( "In real life: ???\n"); 683*1014Sbill return; 684*1014Sbill } 685*1014Sbill printf( "Login name: %-10s", pwdt->pw_name ); 686*1014Sbill if( pers->loggedin ) { 687*1014Sbill if( pers->writeable ) { 688*1014Sbill printf( " " ); 689*1014Sbill } 690*1014Sbill else { 691*1014Sbill printf( " (messages off) " ); 692*1014Sbill } 693*1014Sbill } 694*1014Sbill else { 695*1014Sbill printf( " " ); 696*1014Sbill } 697*1014Sbill if( strlen( pers->realname ) > 0 ) { 698*1014Sbill printf( "In real life: %-s", pers->realname ); 699*1014Sbill } 700*1014Sbill if( strlen( pers->office ) > 0 ) { 701*1014Sbill printf( "\nOffice: %-.11s", pers->office ); 702*1014Sbill if( strlen( pers->officephone ) > 0 ) { 703*1014Sbill printf( ", %s", pers->officephone ); 704*1014Sbill if( strlen( pers->homephone ) > 0 ) { 705*1014Sbill printf( " Home phone: %s", pers->homephone ); 706*1014Sbill } 707*1014Sbill else { 708*1014Sbill if( strlen( pers->random ) > 0 ) { 709*1014Sbill printf( " %s", pers->random ); 710*1014Sbill } 711*1014Sbill } 712*1014Sbill } 713*1014Sbill else { 714*1014Sbill if( strlen( pers->homephone ) > 0 ) { 715*1014Sbill printf(" Home phone: %s",pers->homephone); 716*1014Sbill } 717*1014Sbill if( strlen( pers->random ) > 0 ) { 718*1014Sbill printf( " %s", pers->random ); 719*1014Sbill } 720*1014Sbill } 721*1014Sbill } 722*1014Sbill else { 723*1014Sbill if( strlen( pers->officephone ) > 0 ) { 724*1014Sbill printf( "\nPhone: %s", pers->officephone ); 725*1014Sbill if( strlen( pers->homephone ) > 0 ) { 726*1014Sbill printf( "\n, %s", pers->homephone ); 727*1014Sbill if( strlen( pers->random ) > 0 ) { 728*1014Sbill printf( ", %s", pers->random ); 729*1014Sbill } 730*1014Sbill } 731*1014Sbill else { 732*1014Sbill if( strlen( pers->random ) > 0 ) { 733*1014Sbill printf( "\n, %s", pers->random ); 734*1014Sbill } 735*1014Sbill } 736*1014Sbill } 737*1014Sbill else { 738*1014Sbill if( strlen( pers->homephone ) > 0 ) { 739*1014Sbill printf( "\nPhone: %s", pers->homephone ); 740*1014Sbill if( strlen( pers->random ) > 0 ) { 741*1014Sbill printf( ", %s", pers->random ); 742*1014Sbill } 743*1014Sbill } 744*1014Sbill else { 745*1014Sbill if( strlen( pers->random ) > 0 ) { 746*1014Sbill printf( "\n%s", pers->random ); 747*1014Sbill } 748*1014Sbill } 749*1014Sbill } 750*1014Sbill } 751*1014Sbill if( unbrief ) { 752*1014Sbill printf( "\n" ); 753*1014Sbill printf( "Directory: %-25s", pwdt->pw_dir ); 754*1014Sbill if( strlen( pwdt->pw_shell ) > 0 ) { 755*1014Sbill printf( " Shell: %-s", pwdt->pw_shell ); 756*1014Sbill } 757*1014Sbill } 758*1014Sbill if( pers->loggedin ) { 759*1014Sbill register char *ep = ctime( &pers->loginat ); 760*1014Sbill printf("\nOn since %15.15s on %-*.*s ", &ep[4], LMAX, LMAX, pers->tty ); 761*1014Sbill idleprinted = ltimeprint( &pers->idletime ); 762*1014Sbill if( idleprinted ) { 763*1014Sbill printf( " Idle Time" ); 764*1014Sbill } 765*1014Sbill } 766*1014Sbill else { 767*1014Sbill register char *ep = ctime( &pers->loginat ); 768*1014Sbill printf("\nLast login %16.16s on %.*s", ep, LMAX, pers->tty ); 769*1014Sbill } 770*1014Sbill printf( "\n" ); 771*1014Sbill } 772*1014Sbill 773*1014Sbill 774*1014Sbill /* 775*1014Sbill * very hacky section of code to format phone numbers. filled with 776*1014Sbill * magic constants like 4, 7 and 10. 777*1014Sbill */ 778*1014Sbill 779*1014Sbill char *phone( s, len ) 780*1014Sbill 781*1014Sbill char *s; 782*1014Sbill int len; 783*1014Sbill { 784*1014Sbill char *strsave(); 785*1014Sbill char fonebuf[ 15 ]; 786*1014Sbill int i; 787*1014Sbill 788*1014Sbill switch( len ) { 789*1014Sbill 790*1014Sbill case 4: 791*1014Sbill fonebuf[ 0 ] = ' '; 792*1014Sbill fonebuf[ 1 ] = 'x'; 793*1014Sbill fonebuf[ 2 ] = '2'; 794*1014Sbill fonebuf[ 3 ] = '-'; 795*1014Sbill for( i = 0; i <= 3; i++ ) { 796*1014Sbill fonebuf[ 4 + i ] = *s++; 797*1014Sbill } 798*1014Sbill fonebuf[ 8 ] = NULL; 799*1014Sbill return( strsave( &fonebuf[0] ) ); 800*1014Sbill break; 801*1014Sbill 802*1014Sbill case 7: 803*1014Sbill for( i = 0; i <= 2; i++ ) { 804*1014Sbill fonebuf[ i ] = *s++; 805*1014Sbill } 806*1014Sbill fonebuf[ 3 ] = '-'; 807*1014Sbill for( i = 0; i <= 3; i++ ) { 808*1014Sbill fonebuf[ 4 + i ] = *s++; 809*1014Sbill } 810*1014Sbill fonebuf[ 8 ] = NULL; 811*1014Sbill return( strsave( &fonebuf[0] ) ); 812*1014Sbill break; 813*1014Sbill 814*1014Sbill case 10: 815*1014Sbill for( i = 0; i <= 2; i++ ) { 816*1014Sbill fonebuf[ i ] = *s++; 817*1014Sbill } 818*1014Sbill fonebuf[ 3 ] = '-'; 819*1014Sbill for( i = 0; i <= 2; i++ ) { 820*1014Sbill fonebuf[ 4 + i ] = *s++; 821*1014Sbill } 822*1014Sbill fonebuf[ 7 ] = '-'; 823*1014Sbill for( i = 0; i <= 3; i++ ) { 824*1014Sbill fonebuf[ 8 + i ] = *s++; 825*1014Sbill } 826*1014Sbill fonebuf[ 12 ] = NULL; 827*1014Sbill return( strsave( &fonebuf[0] ) ); 828*1014Sbill break; 829*1014Sbill 830*1014Sbill default: 831*1014Sbill fprintf( stderr, "finger: error in phone numbering\n" ); 832*1014Sbill return( strsave(s) ); 833*1014Sbill break; 834*1014Sbill } 835*1014Sbill } 836*1014Sbill 837*1014Sbill 838*1014Sbill /* decode the information in the gecos field of /etc/passwd 839*1014Sbill * another hacky section of code, but given the format the stuff is in... 840*1014Sbill */ 841*1014Sbill 842*1014Sbill decode( pers ) 843*1014Sbill 844*1014Sbill struct person *pers; 845*1014Sbill 846*1014Sbill { 847*1014Sbill struct passwd *pwdt = pers->pwd; 848*1014Sbill char buffer[ 40 ], *bp, *gp, *lp; 849*1014Sbill char *phone(); 850*1014Sbill int alldigits; 851*1014Sbill int len; 852*1014Sbill int i; 853*1014Sbill 854*1014Sbill pers->realname = NULLSTR; 855*1014Sbill pers->office = NULLSTR; 856*1014Sbill pers->officephone = NULLSTR; 857*1014Sbill pers->homephone = NULLSTR; 858*1014Sbill pers->random = NULLSTR; 859*1014Sbill if( pwdt != NILPWD ) { 860*1014Sbill gp = pwdt->pw_gecos; 861*1014Sbill bp = &buffer[ 0 ]; 862*1014Sbill if( *gp == ASTERISK ) { 863*1014Sbill gp++; 864*1014Sbill } 865*1014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { /* name */ 866*1014Sbill if( *gp == SAMENAME ) { 867*1014Sbill lp = pwdt->pw_name; 868*1014Sbill *bp++ = CAPITALIZE(*lp++); 869*1014Sbill while( *lp != NULL ) { 870*1014Sbill *bp++ = *lp++; 871*1014Sbill } 872*1014Sbill } 873*1014Sbill else { 874*1014Sbill *bp++ = *gp; 875*1014Sbill } 876*1014Sbill gp++; 877*1014Sbill } 878*1014Sbill *bp = NULL; 879*1014Sbill pers->realname = malloc( strlen( &buffer[0] ) + 1 ); 880*1014Sbill strcpy( pers->realname, &buffer[0] ); 881*1014Sbill if( *gp++ == COMMA ) { /* office, supposedly */ 882*1014Sbill alldigits = 1; 883*1014Sbill bp = &buffer[ 0 ]; 884*1014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { 885*1014Sbill *bp = *gp++; 886*1014Sbill alldigits = alldigits && ('0' <= *bp) && (*bp <= '9'); 887*1014Sbill bp++; 888*1014Sbill } 889*1014Sbill *bp = NULL; 890*1014Sbill len = strlen( &buffer[0] ); 891*1014Sbill if( buffer[ len - 1 ] == CORY ) { 892*1014Sbill strcpy( &buffer[ len - 1 ], " Cory" ); 893*1014Sbill pers->office = malloc( len + 5 ); 894*1014Sbill strcpy( pers->office, &buffer[0] ); 895*1014Sbill } 896*1014Sbill else { 897*1014Sbill if( buffer[ len - 1 ] == EVANS ) { 898*1014Sbill strcpy( &buffer[ len - 1 ], " Evans" ); 899*1014Sbill pers->office = malloc( len + 6 ); 900*1014Sbill strcpy( pers->office, &buffer[0] ); 901*1014Sbill } 902*1014Sbill else { 903*1014Sbill if( buffer[ len - 1 ] == 'L' ) { 904*1014Sbill strcpy( &buffer[ len - 1 ], " LBL" ); 905*1014Sbill pers->office = malloc( len + 4 ); 906*1014Sbill strcpy( pers->office, &buffer[0] ); 907*1014Sbill } 908*1014Sbill else { 909*1014Sbill if( alldigits ) { 910*1014Sbill if( len == 4 ) { 911*1014Sbill pers->officephone = phone(&buffer[0], len); 912*1014Sbill } 913*1014Sbill else { 914*1014Sbill if( (len == 7) || (len == 10) ) { 915*1014Sbill pers->homephone = phone(&buffer[0],len); 916*1014Sbill } 917*1014Sbill } 918*1014Sbill } 919*1014Sbill else { 920*1014Sbill pers->random = malloc( len + 1 ); 921*1014Sbill strcpy( pers->random, &buffer[0] ); 922*1014Sbill } 923*1014Sbill } 924*1014Sbill } 925*1014Sbill } 926*1014Sbill if( *gp++ == COMMA ) { /* office phone, theoretically */ 927*1014Sbill bp = &buffer[ 0 ]; 928*1014Sbill alldigits = 1; 929*1014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { 930*1014Sbill *bp = *gp++; 931*1014Sbill alldigits = alldigits && ('0' <= *bp) && (*bp <= '9'); 932*1014Sbill bp++; 933*1014Sbill } 934*1014Sbill *bp = NULL; 935*1014Sbill len = strlen( &buffer[0] ); 936*1014Sbill if( alldigits ) { 937*1014Sbill if( len != 4 ) { 938*1014Sbill if( (len == 7) || (len == 10) ) { 939*1014Sbill pers->homephone = phone( &buffer[0], len ); 940*1014Sbill } 941*1014Sbill else { 942*1014Sbill pers->random = malloc( len + 1 ); 943*1014Sbill strcpy( pers->random, &buffer[0] ); 944*1014Sbill } 945*1014Sbill } 946*1014Sbill else { 947*1014Sbill pers->officephone = phone( &buffer[0], len ); 948*1014Sbill } 949*1014Sbill } 950*1014Sbill else { 951*1014Sbill pers->random = malloc( len + 1 ); 952*1014Sbill strcpy( pers->random, &buffer[0] ); 953*1014Sbill } 954*1014Sbill if( *gp++ == COMMA ) { /* home phone?? */ 955*1014Sbill bp = &buffer[ 0 ]; 956*1014Sbill alldigits = 1; 957*1014Sbill while( (*gp != NULL) && (*gp != COMMA) ) { 958*1014Sbill *bp = *gp++; 959*1014Sbill alldigits = alldigits && ('0' <= *bp) && 960*1014Sbill (*bp <= '9'); 961*1014Sbill bp++; 962*1014Sbill } 963*1014Sbill *bp = NULL; 964*1014Sbill len = strlen( &buffer[0] ); 965*1014Sbill if( alldigits && ( (len == 7) || (len == 10) ) ) { 966*1014Sbill if( *pers->homephone != NULL ) { 967*1014Sbill pers->officephone = pers->homephone; 968*1014Sbill } 969*1014Sbill pers->homephone = phone( &buffer[0], len ); 970*1014Sbill } 971*1014Sbill else { 972*1014Sbill pers->random = malloc( strlen( &buffer[0] ) + 1 ); 973*1014Sbill strcpy( pers->random, &buffer[0] ); 974*1014Sbill } 975*1014Sbill } 976*1014Sbill } 977*1014Sbill } 978*1014Sbill if( pers->loggedin == 0 ) { 979*1014Sbill findwhen( pers ); 980*1014Sbill } 981*1014Sbill else { 982*1014Sbill findidle( pers ); 983*1014Sbill } 984*1014Sbill } 985*1014Sbill } 986*1014Sbill 987*1014Sbill 988*1014Sbill /* find the last log in of a user by checking the LASTLOG file. 989*1014Sbill * the entry is indexed by the uid, so this can only be done if 990*1014Sbill * the uid is known (which it isn't in quick mode) 991*1014Sbill */ 992*1014Sbill 993*1014Sbill fwopen() 994*1014Sbill { 995*1014Sbill if( ( lf = open(LASTLOG, 0) ) >= 0 ) { 996*1014Sbill llopenerr = 0; 997*1014Sbill } 998*1014Sbill else { 999*1014Sbill fprintf( stderr, "finger: lastlog open error\n" ); 1000*1014Sbill llopenerr = 1; 1001*1014Sbill } 1002*1014Sbill } 1003*1014Sbill 1004*1014Sbill 1005*1014Sbill findwhen( pers ) 1006*1014Sbill 1007*1014Sbill struct person *pers; 1008*1014Sbill { 1009*1014Sbill struct passwd *pwdt = pers->pwd; 1010*1014Sbill struct lastlog ll; 1011*1014Sbill int llsize = sizeof ll; 1012*1014Sbill int i; 1013*1014Sbill 1014*1014Sbill if( !llopenerr ) { 1015*1014Sbill lseek( lf, pwdt->pw_uid*llsize, 0 ); 1016*1014Sbill if( read( lf, (char *) &ll, llsize ) == llsize ) { 1017*1014Sbill for( i = 0; i < LMAX; i++ ) { 1018*1014Sbill pers->tty[ i ] = ll.ll_line[ i ]; 1019*1014Sbill } 1020*1014Sbill pers->tty[ LMAX ] = NULL; 1021*1014Sbill pers->loginat = ll.ll_time; 1022*1014Sbill } 1023*1014Sbill else { 1024*1014Sbill fprintf( stderr, "finger: lastlog read error\n" ); 1025*1014Sbill pers->tty[ 0 ] = NULL; 1026*1014Sbill pers->loginat = 0L; 1027*1014Sbill } 1028*1014Sbill } 1029*1014Sbill else { 1030*1014Sbill pers->tty[ 0 ] = NULL; 1031*1014Sbill pers->loginat = 0L; 1032*1014Sbill } 1033*1014Sbill } 1034*1014Sbill 1035*1014Sbill 1036*1014Sbill fwclose() 1037*1014Sbill { 1038*1014Sbill if( !llopenerr ) { 1039*1014Sbill close( lf ); 1040*1014Sbill } 1041*1014Sbill } 1042*1014Sbill 1043*1014Sbill 1044*1014Sbill /* find the idle time of a user by doing a stat on /dev/histty, 1045*1014Sbill * where histty has been gotten from USERLOG, supposedly. 1046*1014Sbill */ 1047*1014Sbill 1048*1014Sbill findidle( pers ) 1049*1014Sbill 1050*1014Sbill struct person *pers; 1051*1014Sbill { 1052*1014Sbill struct stat ttystatus; 1053*1014Sbill struct passwd *pwdt = pers->pwd; 1054*1014Sbill char buffer[ 20 ]; 1055*1014Sbill char *TTY = "/dev/"; 1056*1014Sbill int TTYLEN = strlen( TTY ); 1057*1014Sbill int i; 1058*1014Sbill 1059*1014Sbill strcpy( &buffer[0], TTY ); 1060*1014Sbill i = 0; 1061*1014Sbill do { 1062*1014Sbill buffer[ TTYLEN + i ] = pers->tty[ i ]; 1063*1014Sbill } while( ++i <= LMAX ); 1064*1014Sbill if( stat( &buffer[0], &ttystatus ) >= 0 ) { 1065*1014Sbill time( &tloc ); 1066*1014Sbill if( tloc < ttystatus.st_atime ) { 1067*1014Sbill pers->idletime = 0L; 1068*1014Sbill } 1069*1014Sbill else { 1070*1014Sbill pers->idletime = tloc - ttystatus.st_atime; 1071*1014Sbill } 1072*1014Sbill if( (ttystatus.st_mode & TALKABLE) == TALKABLE ) { 1073*1014Sbill pers->writeable = 1; 1074*1014Sbill } 1075*1014Sbill else { 1076*1014Sbill pers->writeable = 0; 1077*1014Sbill } 1078*1014Sbill } 1079*1014Sbill else { 1080*1014Sbill fprintf( stderr, "finger: error STATing %s\n", &buffer[0] ); 1081*1014Sbill exit( 4 ); 1082*1014Sbill } 1083*1014Sbill } 1084*1014Sbill 1085*1014Sbill 1086*1014Sbill /* print idle time in short format; this program always prints 4 characters; 1087*1014Sbill * if the idle time is zero, it prints 4 blanks. 1088*1014Sbill */ 1089*1014Sbill 1090*1014Sbill stimeprint( dt ) 1091*1014Sbill 1092*1014Sbill long *dt; 1093*1014Sbill { 1094*1014Sbill struct tm *gmtime(); 1095*1014Sbill struct tm *delta; 1096*1014Sbill 1097*1014Sbill delta = gmtime( dt ); 1098*1014Sbill if( delta->tm_yday == 0 ) { 1099*1014Sbill if( delta->tm_hour == 0 ) { 1100*1014Sbill if( delta->tm_min >= 10 ) { 1101*1014Sbill printf( " %2.2d ", delta->tm_min ); 1102*1014Sbill } 1103*1014Sbill else { 1104*1014Sbill if( delta->tm_min == 0 ) { 1105*1014Sbill printf( " " ); 1106*1014Sbill } 1107*1014Sbill else { 1108*1014Sbill printf( " %1.1d ", delta->tm_min ); 1109*1014Sbill } 1110*1014Sbill } 1111*1014Sbill } 1112*1014Sbill else { 1113*1014Sbill if( delta->tm_hour >= 10 ) { 1114*1014Sbill printf( "%3.3d:", delta->tm_hour ); 1115*1014Sbill } 1116*1014Sbill else { 1117*1014Sbill printf( "%1.1d:%02.2d", delta->tm_hour, delta->tm_min ); 1118*1014Sbill } 1119*1014Sbill } 1120*1014Sbill } 1121*1014Sbill else { 1122*1014Sbill printf( "%3dd", delta->tm_yday ); 1123*1014Sbill } 1124*1014Sbill } 1125*1014Sbill 1126*1014Sbill 1127*1014Sbill /* print idle time in long format with care being taken not to pluralize 1128*1014Sbill * 1 minutes or 1 hours or 1 days. 1129*1014Sbill */ 1130*1014Sbill 1131*1014Sbill ltimeprint( dt ) 1132*1014Sbill 1133*1014Sbill long *dt; 1134*1014Sbill { 1135*1014Sbill struct tm *gmtime(); 1136*1014Sbill struct tm *delta; 1137*1014Sbill int printed = 1; 1138*1014Sbill 1139*1014Sbill delta = gmtime( dt ); 1140*1014Sbill if( delta->tm_yday == 0 ) { 1141*1014Sbill if( delta->tm_hour == 0 ) { 1142*1014Sbill if( delta->tm_min >= 10 ) { 1143*1014Sbill printf( "%2d minutes", delta->tm_min ); 1144*1014Sbill } 1145*1014Sbill else { 1146*1014Sbill if( delta->tm_min == 0 ) { 1147*1014Sbill if( delta->tm_sec > 10 ) { 1148*1014Sbill printf( "%2d seconds", delta->tm_sec ); 1149*1014Sbill } 1150*1014Sbill else { 1151*1014Sbill printed = 0; 1152*1014Sbill } 1153*1014Sbill } 1154*1014Sbill else { 1155*1014Sbill if( delta->tm_min == 1 ) { 1156*1014Sbill if( delta->tm_sec == 1 ) { 1157*1014Sbill printf( "%1d minute %1d second", 1158*1014Sbill delta->tm_min, delta->tm_sec ); 1159*1014Sbill } 1160*1014Sbill else { 1161*1014Sbill printf( "%1d minute %d seconds", 1162*1014Sbill delta->tm_min, delta->tm_sec ); 1163*1014Sbill } 1164*1014Sbill } 1165*1014Sbill else { 1166*1014Sbill if( delta->tm_sec == 1 ) { 1167*1014Sbill printf( "%1d minutes %1d second", 1168*1014Sbill delta->tm_min, delta->tm_sec ); 1169*1014Sbill } 1170*1014Sbill else { 1171*1014Sbill printf( "%1d minutes %d seconds", 1172*1014Sbill delta->tm_min, delta->tm_sec ); 1173*1014Sbill } 1174*1014Sbill } 1175*1014Sbill } 1176*1014Sbill } 1177*1014Sbill } 1178*1014Sbill else { 1179*1014Sbill if( delta->tm_hour >= 10 ) { 1180*1014Sbill printf( "%2d hours", delta->tm_hour ); 1181*1014Sbill } 1182*1014Sbill else { 1183*1014Sbill if( delta->tm_hour == 1 ) { 1184*1014Sbill if( delta->tm_min == 1 ) { 1185*1014Sbill printf( "%1d hour %1d minute", 1186*1014Sbill delta->tm_hour, delta->tm_min ); 1187*1014Sbill } 1188*1014Sbill else { 1189*1014Sbill printf( "%1d hour %2d minutes", 1190*1014Sbill delta->tm_hour, delta->tm_min ); 1191*1014Sbill } 1192*1014Sbill } 1193*1014Sbill else { 1194*1014Sbill if( delta->tm_min == 1 ) { 1195*1014Sbill printf( "%1d hours %1d minute", 1196*1014Sbill delta->tm_hour, delta->tm_min ); 1197*1014Sbill } 1198*1014Sbill else { 1199*1014Sbill printf( "%1d hours %2d minutes", 1200*1014Sbill delta->tm_hour, delta->tm_min ); 1201*1014Sbill } 1202*1014Sbill } 1203*1014Sbill } 1204*1014Sbill } 1205*1014Sbill } 1206*1014Sbill else { 1207*1014Sbill if( delta->tm_yday >= 10 ) { 1208*1014Sbill printf( "%2d days", delta->tm_yday ); 1209*1014Sbill } 1210*1014Sbill else { 1211*1014Sbill if( delta->tm_yday == 1 ) { 1212*1014Sbill if( delta->tm_hour == 1 ) { 1213*1014Sbill printf( "%1d day %1d hour", 1214*1014Sbill delta->tm_yday, delta->tm_hour ); 1215*1014Sbill } 1216*1014Sbill else { 1217*1014Sbill printf( "%1d day %2d hours", 1218*1014Sbill delta->tm_yday, delta->tm_hour ); 1219*1014Sbill } 1220*1014Sbill } 1221*1014Sbill else { 1222*1014Sbill if( delta->tm_hour == 1 ) { 1223*1014Sbill printf( "%1d days %1d hour", 1224*1014Sbill delta->tm_yday, delta->tm_hour ); 1225*1014Sbill } 1226*1014Sbill else { 1227*1014Sbill printf( "%1d days %2d hours", 1228*1014Sbill delta->tm_yday, delta->tm_hour ); 1229*1014Sbill } 1230*1014Sbill } 1231*1014Sbill } 1232*1014Sbill } 1233*1014Sbill return( printed ); 1234*1014Sbill } 1235*1014Sbill 1236*1014Sbill 1237*1014Sbill matchcmp( gname, login, given ) 1238*1014Sbill 1239*1014Sbill char *gname; 1240*1014Sbill char *login; 1241*1014Sbill char *given; 1242*1014Sbill { 1243*1014Sbill char buffer[ 20 ]; 1244*1014Sbill char c; 1245*1014Sbill int flag, i, unfound; 1246*1014Sbill 1247*1014Sbill if( !match ) { 1248*1014Sbill return( 0 ); 1249*1014Sbill } 1250*1014Sbill else { 1251*1014Sbill if( namecmp( login, given ) ) { 1252*1014Sbill return( 1 ); 1253*1014Sbill } 1254*1014Sbill else { 1255*1014Sbill if( *gname == ASTERISK ) { 1256*1014Sbill gname++; 1257*1014Sbill } 1258*1014Sbill flag = 1; 1259*1014Sbill i = 0; 1260*1014Sbill unfound = 1; 1261*1014Sbill while( unfound ) { 1262*1014Sbill if( flag ) { 1263*1014Sbill c = *gname++; 1264*1014Sbill if( c == SAMENAME ) { 1265*1014Sbill flag = 0; 1266*1014Sbill c = *login++; 1267*1014Sbill } 1268*1014Sbill else { 1269*1014Sbill unfound = (*gname != COMMA) && (*gname != NULL); 1270*1014Sbill } 1271*1014Sbill } 1272*1014Sbill else { 1273*1014Sbill c = *login++; 1274*1014Sbill if( c == NULL ) { 1275*1014Sbill if( (*gname == COMMA) || (*gname == NULL) ) { 1276*1014Sbill break; 1277*1014Sbill } 1278*1014Sbill else { 1279*1014Sbill flag = 1; 1280*1014Sbill continue; 1281*1014Sbill } 1282*1014Sbill } 1283*1014Sbill } 1284*1014Sbill if( c == BLANK ) { 1285*1014Sbill buffer[i++] = NULL; 1286*1014Sbill if( namecmp( buffer, given ) ) { 1287*1014Sbill return( 1 ); 1288*1014Sbill } 1289*1014Sbill i = 0; 1290*1014Sbill flag = 1; 1291*1014Sbill } 1292*1014Sbill else { 1293*1014Sbill buffer[ i++ ] = c; 1294*1014Sbill } 1295*1014Sbill } 1296*1014Sbill buffer[i++] = NULL; 1297*1014Sbill if( namecmp( buffer, given ) ) { 1298*1014Sbill return( 1 ); 1299*1014Sbill } 1300*1014Sbill else { 1301*1014Sbill return( 0 ); 1302*1014Sbill } 1303*1014Sbill } 1304*1014Sbill } 1305*1014Sbill } 1306*1014Sbill 1307*1014Sbill 1308*1014Sbill namecmp( name1, name2 ) 1309*1014Sbill 1310*1014Sbill char *name1; 1311*1014Sbill char *name2; 1312*1014Sbill { 1313*1014Sbill char c1, c2; 1314*1014Sbill 1315*1014Sbill c1 = *name1; 1316*1014Sbill if( (('A' <= c1) && (c1 <= 'Z')) || (('a' <= c1) && (c1 <= 'z')) ) { 1317*1014Sbill c1 = CAPITALIZE( c1 ); 1318*1014Sbill } 1319*1014Sbill c2 = *name2; 1320*1014Sbill if( (('A' <= c2) && (c2 <= 'Z')) || (('a' <= c2) && (c2 <= 'z')) ) { 1321*1014Sbill c2 = CAPITALIZE( c2 ); 1322*1014Sbill } 1323*1014Sbill while( c1 == c2 ) { 1324*1014Sbill if( c1 == NULL ) { 1325*1014Sbill return( 1 ); 1326*1014Sbill } 1327*1014Sbill c1 = *++name1; 1328*1014Sbill if( (('A'<=c1) && (c1<='Z')) || (('a'<=c1) && (c1<='z')) ) { 1329*1014Sbill c1 = CAPITALIZE( c1 ); 1330*1014Sbill } 1331*1014Sbill c2 = *++name2; 1332*1014Sbill if( (('A'<=c2) && (c2<='Z')) || (('a'<=c2) && (c2<='z')) ) { 1333*1014Sbill c2 = CAPITALIZE( c2 ); 1334*1014Sbill } 1335*1014Sbill } 1336*1014Sbill if( *name1 == NULL ) { 1337*1014Sbill while( ('0' <= *name2) && (*name2 <= '9') ) { 1338*1014Sbill name2++; 1339*1014Sbill } 1340*1014Sbill if( *name2 == NULL ) { 1341*1014Sbill return( 1 ); 1342*1014Sbill } 1343*1014Sbill } 1344*1014Sbill else { 1345*1014Sbill if( *name2 == NULL ) { 1346*1014Sbill while( ('0' <= *name1) && (*name1 <= '9') ) { 1347*1014Sbill name1++; 1348*1014Sbill } 1349*1014Sbill if( *name1 == NULL ) { 1350*1014Sbill return( 1 ); 1351*1014Sbill } 1352*1014Sbill } 1353*1014Sbill } 1354*1014Sbill return( 0 ); 1355*1014Sbill } 1356*1014Sbill 1357*1014Sbill 1358*1014Sbill char *strsave( s ) 1359*1014Sbill 1360*1014Sbill char *s; 1361*1014Sbill { 1362*1014Sbill char *malloc(); 1363*1014Sbill char *p; 1364*1014Sbill 1365*1014Sbill p = malloc( strlen( s ) + 1 ); 1366*1014Sbill strcpy( p, s ); 1367*1014Sbill } 1368