|
|
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: if (s[len - 1] == 'Z') {
794: fonebuf[0] = ' ';
795: fonebuf[1] = 'x';
796: for (i = 2; ; i++) {
797: if (*s == 'Z')
798: break;
799: fonebuf[i] = *s++;
800: }
801: for (i = i; i <= 7; i++)
802: fonebuf[i] = ' ';
803: fonebuf[8] = NULL;
804: return( strsave( &fonebuf[0] ) );
805: }
806: switch( len ) {
807:
808: case 4:
809: fonebuf[ 0 ] = ' ';
810: fonebuf[ 1 ] = 'x';
811: fonebuf[ 2 ] = '2';
812: fonebuf[ 3 ] = '-';
813: for( i = 0; i <= 3; i++ ) {
814: fonebuf[ 4 + i ] = *s++;
815: }
816: fonebuf[ 8 ] = NULL;
817: return( strsave( &fonebuf[0] ) );
818: break;
819:
820: case 7:
821: for( i = 0; i <= 2; i++ ) {
822: fonebuf[ i ] = *s++;
823: }
824: fonebuf[ 3 ] = '-';
825: for( i = 0; i <= 3; i++ ) {
826: fonebuf[ 4 + i ] = *s++;
827: }
828: fonebuf[ 8 ] = NULL;
829: return( strsave( &fonebuf[0] ) );
830: break;
831:
832: case 10:
833: for( i = 0; i <= 2; i++ ) {
834: fonebuf[ i ] = *s++;
835: }
836: fonebuf[ 3 ] = '-';
837: for( i = 0; i <= 2; i++ ) {
838: fonebuf[ 4 + i ] = *s++;
839: }
840: fonebuf[ 7 ] = '-';
841: for( i = 0; i <= 3; i++ ) {
842: fonebuf[ 8 + i ] = *s++;
843: }
844: fonebuf[ 12 ] = NULL;
845: return( strsave( &fonebuf[0] ) );
846: break;
847:
848: default:
849: fprintf( stderr, "finger: error in phone numbering\n" );
850: return( strsave(s) );
851: break;
852: }
853: }
854:
855:
856: /* decode the information in the gecos field of /etc/passwd
857: * another hacky section of code, but given the format the stuff is in...
858: */
859:
860: decode( pers )
861:
862: struct person *pers;
863:
864: {
865: struct passwd *pwdt = pers->pwd;
866: char buffer[ 256 ], *bp, *gp, *lp;
867: char *phone();
868: int len;
869: int i;
870:
871: pers->realname = NULLSTR;
872: pers->office = NULLSTR;
873: pers->officephone = NULLSTR;
874: pers->homephone = NULLSTR;
875: pers->random = NULLSTR;
876: if( pwdt != NILPWD ) {
877: gp = pwdt->pw_gecos;
878: bp = &buffer[ 0 ];
879: if( *gp == ASTERISK ) {
880: gp++;
881: }
882: while( (*gp != NULL) && (*gp != COMMA) ) { /* name */
883: if( *gp == SAMENAME ) {
884: lp = pwdt->pw_name;
885: *bp++ = CAPITALIZE(*lp++);
886: while( *lp != NULL ) {
887: *bp++ = *lp++;
888: }
889: }
890: else {
891: *bp++ = *gp;
892: }
893: gp++;
894: }
895: *bp = NULL;
896: pers->realname = malloc( strlen( &buffer[0] ) + 1 );
897: strcpy( pers->realname, &buffer[0] );
898: if( *gp++ == COMMA ) { /* office, supposedly */
899: bp = &buffer[ 0 ];
900: while( (*gp != NULL) && (*gp != COMMA) )
901: *bp++ = *gp++;
902: *bp = NULL;
903: len = strlen( &buffer[0] );
904: if( buffer[ len - 1 ] == CORY ) {
905: strcpy( &buffer[ len - 1 ], " Cory" );
906: pers->office = malloc( len + 5 );
907: strcpy( pers->office, &buffer[0] );
908: }
909: else {
910: if( buffer[ len - 1 ] == EVANS ) {
911: strcpy( &buffer[ len - 1 ], " Evans" );
912: pers->office = malloc( len + 6 );
913: strcpy( pers->office, &buffer[0] );
914: }
915: else {
916: if( buffer[ len - 1 ] == 'L' ) {
917: strcpy( &buffer[ len - 1 ], " LBL" );
918: pers->office = malloc( len + 4 );
919: strcpy( pers->office, &buffer[0] );
920: }
921: else {
922: if( buffer[ len - 1 ] == 'Q' ) {
923: pers->office = malloc( 10 );
924: for (i = 0; i < len - 1; i++)
925: pers->office[8 - i] = buffer[ len-i-2 ];
926: for (i = 0; i <= 9 - len; i++)
927: pers->office[i] = ' ';
928: pers->office[9] = NULL;
929: }
930: else {
931: if( len == 4 || buffer[ len - 1 ] == 'Z' ) {
932: pers->officephone = phone(&buffer[0], len);
933: }
934: else {
935: if( (len == 7) || (len == 10) ) {
936: pers->homephone = phone(&buffer[0],len);
937: }
938: else {
939: pers->random = malloc( len + 1 );
940: strcpy( pers->random, &buffer[0] );
941: }
942: }
943: }
944: }
945: }
946: }
947: if( *gp++ == COMMA ) { /* office phone, theoretically */
948: bp = &buffer[ 0 ];
949: while( (*gp != NULL) && (*gp != COMMA) )
950: *bp++ = *gp++;
951: *bp = NULL;
952: len = strlen( &buffer[0] );
953: if( (len != 4) && (buffer[ len - 1] != 'Z') ) {
954: if( (len == 7) || (len == 10) ) {
955: pers->homephone = phone( &buffer[0], len );
956: }
957: else {
958: pers->random = malloc( len + 1 );
959: strcpy( pers->random, &buffer[0] );
960: }
961: }
962: else {
963: pers->officephone = phone( &buffer[0], len );
964: }
965: if( *gp++ == COMMA ) { /* home phone?? */
966: bp = &buffer[ 0 ];
967: while( (*gp != NULL) && (*gp != COMMA) )
968: *bp++ = *gp++;
969: *bp = NULL;
970: len = strlen( &buffer[0] );
971: if( (len == 7) || (len == 10) ) {
972: if( *pers->homephone != NULL ) {
973: pers->officephone = pers->homephone;
974: }
975: pers->homephone = phone( &buffer[0], len );
976: }
977: else {
978: pers->random = malloc( strlen( &buffer[0] ) + 1 );
979: strcpy( pers->random, &buffer[0] );
980: }
981: }
982: }
983: }
984: if( pers->loggedin == 0 ) {
985: findwhen( pers );
986: }
987: else {
988: findidle( pers );
989: }
990: }
991: }
992:
993:
994: /* find the last log in of a user by checking the LASTLOG file.
995: * the entry is indexed by the uid, so this can only be done if
996: * the uid is known (which it isn't in quick mode)
997: */
998:
999: fwopen()
1000: {
1001: if( ( lf = open(LASTLOG, 0) ) >= 0 ) {
1002: llopenerr = 0;
1003: }
1004: else {
1005: fprintf( stderr, "finger: lastlog open error\n" );
1006: llopenerr = 1;
1007: }
1008: }
1009:
1010:
1011: findwhen( pers )
1012:
1013: struct person *pers;
1014: {
1015: struct passwd *pwdt = pers->pwd;
1016: struct lastlog ll;
1017: int llsize = sizeof ll;
1018: int i;
1019:
1020: if( !llopenerr ) {
1021: lseek( lf, pwdt->pw_uid*llsize, 0 );
1022: if ((i = read( lf, (char *) &ll, llsize )) == llsize) {
1023: for( i = 0; i < LMAX; i++ ) {
1024: pers->tty[ i ] = ll.ll_line[ i ];
1025: }
1026: pers->tty[ LMAX ] = NULL;
1027: pers->loginat = ll.ll_time;
1028: }
1029: else {
1030: if (i != 0)
1031: fprintf(stderr, "finger: lastlog read error\n");
1032: pers->tty[ 0 ] = NULL;
1033: pers->loginat = 0L;
1034: }
1035: }
1036: else {
1037: pers->tty[ 0 ] = NULL;
1038: pers->loginat = 0L;
1039: }
1040: }
1041:
1042:
1043: fwclose()
1044: {
1045: if( !llopenerr ) {
1046: close( lf );
1047: }
1048: }
1049:
1050:
1051: /* find the idle time of a user by doing a stat on /dev/histty,
1052: * where histty has been gotten from USERLOG, supposedly.
1053: */
1054:
1055: findidle( pers )
1056:
1057: struct person *pers;
1058: {
1059: struct stat ttystatus;
1060: struct passwd *pwdt = pers->pwd;
1061: char buffer[ 20 ];
1062: char *TTY = "/dev/";
1063: int TTYLEN = strlen( TTY );
1064: int i;
1065:
1066: strcpy( &buffer[0], TTY );
1067: i = 0;
1068: do {
1069: buffer[ TTYLEN + i ] = pers->tty[ i ];
1070: } while( ++i <= LMAX );
1071: if( stat( &buffer[0], &ttystatus ) >= 0 ) {
1072: time( &tloc );
1073: if( tloc < ttystatus.st_atime ) {
1074: pers->idletime = 0L;
1075: }
1076: else {
1077: pers->idletime = tloc - ttystatus.st_atime;
1078: }
1079: if( (ttystatus.st_mode & TALKABLE) == TALKABLE ) {
1080: pers->writeable = 1;
1081: }
1082: else {
1083: pers->writeable = 0;
1084: }
1085: }
1086: else {
1087: fprintf( stderr, "finger: error STATing %s\n", &buffer[0] );
1088: exit( 4 );
1089: }
1090: }
1091:
1092:
1093: /* print idle time in short format; this program always prints 4 characters;
1094: * if the idle time is zero, it prints 4 blanks.
1095: */
1096:
1097: stimeprint( dt )
1098:
1099: long *dt;
1100: {
1101: struct tm *gmtime();
1102: struct tm *delta;
1103:
1104: delta = gmtime( dt );
1105: if( delta->tm_yday == 0 ) {
1106: if( delta->tm_hour == 0 ) {
1107: if( delta->tm_min >= 10 ) {
1108: printf( " %2.2d ", delta->tm_min );
1109: }
1110: else {
1111: if( delta->tm_min == 0 ) {
1112: printf( " " );
1113: }
1114: else {
1115: printf( " %1.1d ", delta->tm_min );
1116: }
1117: }
1118: }
1119: else {
1120: if( delta->tm_hour >= 10 ) {
1121: printf( "%3.3d:", delta->tm_hour );
1122: }
1123: else {
1124: printf( "%1.1d:%02.2d", delta->tm_hour, delta->tm_min );
1125: }
1126: }
1127: }
1128: else {
1129: printf( "%3dd", delta->tm_yday );
1130: }
1131: }
1132:
1133:
1134: /* print idle time in long format with care being taken not to pluralize
1135: * 1 minutes or 1 hours or 1 days.
1136: */
1137:
1138: ltimeprint( dt )
1139:
1140: long *dt;
1141: {
1142: struct tm *gmtime();
1143: struct tm *delta;
1144: int printed = 1;
1145:
1146: delta = gmtime( dt );
1147: if( delta->tm_yday == 0 ) {
1148: if( delta->tm_hour == 0 ) {
1149: if( delta->tm_min >= 10 ) {
1150: printf( "%2d minutes", delta->tm_min );
1151: }
1152: else {
1153: if( delta->tm_min == 0 ) {
1154: if( delta->tm_sec > 10 ) {
1155: printf( "%2d seconds", delta->tm_sec );
1156: }
1157: else {
1158: printed = 0;
1159: }
1160: }
1161: else {
1162: if( delta->tm_min == 1 ) {
1163: if( delta->tm_sec == 1 ) {
1164: printf( "%1d minute %1d second",
1165: delta->tm_min, delta->tm_sec );
1166: }
1167: else {
1168: printf( "%1d minute %d seconds",
1169: delta->tm_min, delta->tm_sec );
1170: }
1171: }
1172: else {
1173: if( delta->tm_sec == 1 ) {
1174: printf( "%1d minutes %1d second",
1175: delta->tm_min, delta->tm_sec );
1176: }
1177: else {
1178: printf( "%1d minutes %d seconds",
1179: delta->tm_min, delta->tm_sec );
1180: }
1181: }
1182: }
1183: }
1184: }
1185: else {
1186: if( delta->tm_hour >= 10 ) {
1187: printf( "%2d hours", delta->tm_hour );
1188: }
1189: else {
1190: if( delta->tm_hour == 1 ) {
1191: if( delta->tm_min == 1 ) {
1192: printf( "%1d hour %1d minute",
1193: delta->tm_hour, delta->tm_min );
1194: }
1195: else {
1196: printf( "%1d hour %2d minutes",
1197: delta->tm_hour, delta->tm_min );
1198: }
1199: }
1200: else {
1201: if( delta->tm_min == 1 ) {
1202: printf( "%1d hours %1d minute",
1203: delta->tm_hour, delta->tm_min );
1204: }
1205: else {
1206: printf( "%1d hours %2d minutes",
1207: delta->tm_hour, delta->tm_min );
1208: }
1209: }
1210: }
1211: }
1212: }
1213: else {
1214: if( delta->tm_yday >= 10 ) {
1215: printf( "%2d days", delta->tm_yday );
1216: }
1217: else {
1218: if( delta->tm_yday == 1 ) {
1219: if( delta->tm_hour == 1 ) {
1220: printf( "%1d day %1d hour",
1221: delta->tm_yday, delta->tm_hour );
1222: }
1223: else {
1224: printf( "%1d day %2d hours",
1225: delta->tm_yday, delta->tm_hour );
1226: }
1227: }
1228: else {
1229: if( delta->tm_hour == 1 ) {
1230: printf( "%1d days %1d hour",
1231: delta->tm_yday, delta->tm_hour );
1232: }
1233: else {
1234: printf( "%1d days %2d hours",
1235: delta->tm_yday, delta->tm_hour );
1236: }
1237: }
1238: }
1239: }
1240: return( printed );
1241: }
1242:
1243:
1244: matchcmp( gname, login, given )
1245:
1246: char *gname;
1247: char *login;
1248: char *given;
1249: {
1250: char buffer[ 20 ];
1251: char c;
1252: int flag, i, unfound;
1253:
1254: if( !match ) {
1255: return( 0 );
1256: }
1257: else {
1258: if( namecmp( login, given ) ) {
1259: return( 1 );
1260: }
1261: else if (*gname == '\0')
1262: return (0);
1263: else {
1264: if( *gname == ASTERISK ) {
1265: gname++;
1266: }
1267: flag = 1;
1268: i = 0;
1269: unfound = 1;
1270: while( unfound ) {
1271: if( flag ) {
1272: c = *gname++;
1273: if( c == SAMENAME ) {
1274: flag = 0;
1275: c = *login++;
1276: }
1277: else {
1278: unfound = (*gname != COMMA) && (*gname != NULL);
1279: }
1280: }
1281: else {
1282: c = *login++;
1283: if( c == NULL ) {
1284: if( (*gname == COMMA) || (*gname == NULL) ) {
1285: break;
1286: }
1287: else {
1288: flag = 1;
1289: continue;
1290: }
1291: }
1292: }
1293: if( c == BLANK ) {
1294: buffer[i++] = NULL;
1295: if( namecmp( buffer, given ) ) {
1296: return( 1 );
1297: }
1298: i = 0;
1299: flag = 1;
1300: }
1301: else {
1302: buffer[ i++ ] = c;
1303: }
1304: }
1305: buffer[i++] = NULL;
1306: if( namecmp( buffer, given ) ) {
1307: return( 1 );
1308: }
1309: else {
1310: return( 0 );
1311: }
1312: }
1313: }
1314: }
1315:
1316:
1317: namecmp( name1, name2 )
1318:
1319: char *name1;
1320: char *name2;
1321: {
1322: char c1, c2;
1323:
1324: c1 = *name1;
1325: if( (('A' <= c1) && (c1 <= 'Z')) || (('a' <= c1) && (c1 <= 'z')) ) {
1326: c1 = CAPITALIZE( c1 );
1327: }
1328: c2 = *name2;
1329: if( (('A' <= c2) && (c2 <= 'Z')) || (('a' <= c2) && (c2 <= 'z')) ) {
1330: c2 = CAPITALIZE( c2 );
1331: }
1332: while( c1 == c2 ) {
1333: if( c1 == NULL ) {
1334: return( 1 );
1335: }
1336: c1 = *++name1;
1337: if( (('A'<=c1) && (c1<='Z')) || (('a'<=c1) && (c1<='z')) ) {
1338: c1 = CAPITALIZE( c1 );
1339: }
1340: c2 = *++name2;
1341: if( (('A'<=c2) && (c2<='Z')) || (('a'<=c2) && (c2<='z')) ) {
1342: c2 = CAPITALIZE( c2 );
1343: }
1344: }
1345: if( *name1 == NULL ) {
1346: while( ('0' <= *name2) && (*name2 <= '9') ) {
1347: name2++;
1348: }
1349: if( *name2 == NULL ) {
1350: return( 1 );
1351: }
1352: }
1353: else {
1354: if( *name2 == NULL ) {
1355: while( ('0' <= *name1) && (*name1 <= '9') ) {
1356: name1++;
1357: }
1358: if( *name1 == NULL ) {
1359: return( 1 );
1360: }
1361: }
1362: }
1363: return( 0 );
1364: }
1365:
1366:
1367: char *strsave( s )
1368:
1369: char *s;
1370: {
1371: char *malloc();
1372: char *p;
1373:
1374: p = malloc( strlen( s ) + 1 );
1375: strcpy( p, s );
1376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.