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