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