SYSENTER/SYSCALL support
[minix.git] / commands / finger / finger.c
blob9d92e6643d153596b416bef25e64e207afaf1dae
1 /*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
7 #ifndef lint
8 static char sccsid[] = "@(#)finger.c 1.1 87/12/21 SMI"; /* from 5.8 3/13/86 */
9 #endif /* not lint */
12 * This is a finger program. It prints out useful information about users
13 * by digging it up from various system files.
15 * There are three output formats, all of which give login name, teletype
16 * line number, and login time. The short output format is reminiscent
17 * of finger on ITS, and gives one line of information per user containing
18 * in addition to the minimum basic requirements (MBR), the full name of
19 * the user, his idle time and location. The
20 * quick style output is UNIX who-like, giving only name, teletype and
21 * login time. Finally, the long style output give the same information
22 * as the short (in more legible format), the home directory and shell
23 * of the user, and, if it exits, a copy of the file .plan in the users
24 * home directory. Finger may be called with or without a list of people
25 * to finger -- if no list is given, all the people currently logged in
26 * are fingered.
28 * The program is validly called by one of the following:
30 * finger {short form list of users}
31 * finger -l {long form list of users}
32 * finger -b {briefer long form list of users}
33 * finger -q {quick list of users}
34 * finger -i {quick list of users with idle times}
35 * finger namelist {long format list of specified users}
36 * finger -s namelist {short format list of specified users}
37 * finger -w namelist {narrow short format list of specified users}
39 * where 'namelist' is a list of users login names.
40 * The other options can all be given after one '-', or each can have its
41 * own '-'. The -f option disables the printing of headers for short and
42 * quick outputs. The -b option briefens long format outputs. The -p
43 * option turns off plans for long format outputs.
46 #include <sys/types.h>
47 #include <ctype.h>
48 #include <errno.h>
49 #include <fcntl.h>
50 #include <pwd.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <time.h>
55 #include <unistd.h>
56 #include <utmp.h>
57 #include <sys/ioctl.h>
58 #include <sys/stat.h>
59 #include <net/gen/in.h>
60 #include <net/gen/inet.h>
61 #include <net/gen/netdb.h>
62 #include <net/gen/socket.h>
63 #include <net/gen/tcp.h>
64 #include <net/gen/tcp_hdr.h>
65 #include <net/gen/tcp_io.h>
66 #include <net/hton.h>
67 #include <net/netlib.h>
69 #define NONOTHING 1 /* don't say "No plan", or "No mail" */
71 #define NONET 0
73 #define ASTERISK '*' /* ignore this in real name */
74 #define COMMA ',' /* separator in pw_gecos field */
75 #define COMMAND '-' /* command line flag char */
76 #define SAMENAME '&' /* repeat login name in real name */
77 #define TALKABLE 0220 /* tty is writable if this mode */
79 struct utmp user;
80 #define NMAX sizeof(user.ut_name)
81 #define LMAX sizeof(user.ut_line)
82 #define HMAX sizeof(user.ut_host)
84 struct person { /* one for each person fingered */
85 char *name; /* name */
86 char tty[LMAX+1]; /* null terminated tty line */
87 char host[HMAX+1]; /* null terminated remote host name */
88 long loginat; /* time of (last) login */
89 long idletime; /* how long idle (if logged in) */
90 char *realname; /* pointer to full name */
91 struct passwd *pwd; /* structure of /etc/passwd stuff */
92 char loggedin; /* person is logged in */
93 char writable; /* tty is writable */
94 char original; /* this is not a duplicate entry */
95 struct person *link; /* link to next person */
96 char *where; /* terminal location */
97 char hostt[HMAX+1]; /* login host */
100 #include <paths.h>
102 char LASTLOG[] = _PATH_LASTLOG; /* last login info */
103 char USERLOG[] = _PATH_UTMP; /* who is logged in */
104 char PLAN[] = "/.plan"; /* what plan file is */
105 char PROJ[] = "/.project"; /* what project file */
107 int unbrief = 1; /* -b option default */
108 int header = 1; /* -f option default */
109 int hack = 1; /* -h option default */
110 int idle = 0; /* -i option default */
111 int large = 0; /* -l option default */
112 int match = 1; /* -m option default */
113 int plan = 1; /* -p option default */
114 int unquick = 1; /* -q option default */
115 int small = 0; /* -s option default */
116 int wide = 1; /* -w option default */
118 int unshort;
119 int lf; /* LASTLOG file descriptor */
120 struct person *person1; /* list of people */
121 long tloc; /* current time */
123 #if !_MINIX
124 char *strcpy();
125 char *ctime();
126 #endif
128 char *prog_name;
130 #ifdef __NBSD_LIBC
131 /* Already defined in stdio.h */
132 #undef fwopen
133 #define fwopen finger_fwopen
134 #endif
136 int main (int argc, char *argv[]);
137 static void doall(void);
138 static void donames(char **args);
139 static void print(void);
140 static void fwopen(void);
141 static void decode(struct person *pers);
142 static void fwclose(void);
143 static int netfinger (char *name);
144 static int matchcmp (char *gname, char *login, char *given);
145 static void quickprint (struct person *pers);
146 static void shortprint (struct person *pers);
147 static void personprint (struct person *pers);
148 static int AlreadyPrinted(int uid);
149 static int AnyMail (char *name);
150 static struct passwd *pwdcopy(struct passwd *pfrom);
151 static void findidle (struct person *pers);
152 static int ltimeprint (char *dt, long *before, char *after);
153 static void stimeprint (long *dt);
154 static void findwhen (struct person *pers);
155 static int namecmp (char *name1, char *name2);
157 main(argc, argv)
158 int argc;
159 register char **argv;
161 register char *s;
163 prog_name= argv[0];
165 /* parse command line for (optional) arguments */
166 while (*++argv && **argv == COMMAND)
167 for (s = *argv + 1; *s; s++)
168 switch (*s) {
169 case 'b':
170 unbrief = 0;
171 break;
172 case 'f':
173 header = 0;
174 break;
175 case 'h':
176 hack = 0;
177 break;
178 case 'i':
179 idle = 1;
180 unquick = 0;
181 break;
182 case 'l':
183 large = 1;
184 break;
185 case 'm':
186 match = 0;
187 break;
188 case 'p':
189 plan = 0;
190 break;
191 case 'q':
192 unquick = 0;
193 break;
194 case 's':
195 small = 1;
196 break;
197 case 'w':
198 wide = 0;
199 break;
200 default:
201 fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n");
202 exit(1);
204 if (unquick || idle)
205 time(&tloc);
207 * *argv == 0 means no names given
209 if (*argv == 0)
210 doall();
211 else
212 donames(argv);
213 if (person1)
214 print();
215 exit(0);
218 static void doall()
220 register struct person *p;
221 register struct passwd *pw;
222 int uf;
223 char name[NMAX + 1];
225 unshort = large;
226 if ((uf = open(USERLOG, 0)) < 0) {
227 fprintf(stderr, "finger: error opening %s\n", USERLOG);
228 exit(2);
230 if (unquick) {
231 setpwent();
232 fwopen();
234 while (read(uf, (char *)&user, sizeof user) == sizeof user) {
235 if (user.ut_name[0] == 0)
236 continue;
237 if (person1 == 0)
238 p = person1 = (struct person *) malloc(sizeof *p);
239 else {
240 p->link = (struct person *) malloc(sizeof *p);
241 p = p->link;
243 bcopy(user.ut_name, name, NMAX);
244 name[NMAX] = 0;
245 bcopy(user.ut_line, p->tty, LMAX);
246 p->tty[LMAX] = 0;
247 bcopy(user.ut_host, p->host, HMAX);
248 p->host[HMAX] = 0;
249 p->loginat = user.ut_time;
250 p->pwd = 0;
251 p->loggedin = 1;
252 p->where = NULL;
253 if (unquick && (pw = getpwnam(name))) {
254 p->pwd = pwdcopy(pw);
255 decode(p);
256 p->name = p->pwd->pw_name;
257 } else
258 p->name = strcpy(malloc(strlen(name) + 1), name);
260 if (unquick) {
261 fwclose();
262 endpwent();
264 close(uf);
265 if (person1 == 0) {
266 printf("No one logged on\n");
267 return;
269 p->link = 0;
272 static void donames(argv)
273 char **argv;
275 register struct person *p;
276 register struct passwd *pw;
277 int uf;
280 * get names from command line and check to see if they're
281 * logged in
283 unshort = !small;
284 for (; *argv != 0; argv++) {
285 if (netfinger(*argv))
286 continue;
287 if (person1 == 0)
288 p = person1 = (struct person *) malloc(sizeof *p);
289 else {
290 p->link = (struct person *) malloc(sizeof *p);
291 p = p->link;
293 p->name = *argv;
294 p->loggedin = 0;
295 p->original = 1;
296 p->pwd = 0;
298 if (person1 == 0)
299 return;
300 p->link = 0;
302 * if we are doing it, read /etc/passwd for the useful info
304 if (unquick) {
305 setpwent();
306 if (!match) {
307 for (p = person1; p != 0; p = p->link)
308 if (pw = getpwnam(p->name))
309 p->pwd = pwdcopy(pw);
310 } else while ((pw = getpwent()) != 0) {
311 for (p = person1; p != 0; p = p->link) {
312 if (!p->original)
313 continue;
314 if (strcmp(p->name, pw->pw_name) != 0 &&
315 !matchcmp(pw->pw_gecos, pw->pw_name, p->name))
316 continue;
317 if (p->pwd == 0)
318 p->pwd = pwdcopy(pw);
319 else {
320 struct person *new;
322 * handle multiple login names, insert
323 * new "duplicate" entry behind
325 new = (struct person *)
326 malloc(sizeof *new);
327 new->pwd = pwdcopy(pw);
328 new->name = p->name;
329 new->original = 1;
330 new->loggedin = 0;
331 new->link = p->link;
332 p->original = 0;
333 p->link = new;
334 p = new;
338 endpwent();
340 /* Now get login information */
341 if ((uf = open(USERLOG, 0)) < 0) {
342 fprintf(stderr, "finger: error opening %s\n", USERLOG);
343 exit(2);
345 while (read(uf, (char *)&user, sizeof user) == sizeof user) {
346 if (*user.ut_name == 0)
347 continue;
348 for (p = person1; p != 0; p = p->link) {
349 if (p->loggedin == 2)
350 continue;
351 if (strncmp(p->pwd ? p->pwd->pw_name : p->name,
352 user.ut_name, NMAX) != 0)
353 continue;
354 if (p->loggedin == 0) {
355 bcopy(user.ut_line, p->tty, LMAX);
356 p->tty[LMAX] = 0;
357 bcopy(user.ut_host, p->host, HMAX);
358 p->host[HMAX] = 0;
359 p->loginat = user.ut_time;
360 p->loggedin = 1;
361 } else { /* p->loggedin == 1 */
362 struct person *new;
363 new = (struct person *) malloc(sizeof *new);
364 new->name = p->name;
365 bcopy(user.ut_line, new->tty, LMAX);
366 new->tty[LMAX] = 0;
367 bcopy(user.ut_host, new->host, HMAX);
368 new->host[HMAX] = 0;
369 new->loginat = user.ut_time;
370 new->pwd = p->pwd;
371 new->loggedin = 1;
372 new->original = 0;
373 new->link = p->link;
374 p->loggedin = 2;
375 p->link = new;
376 p = new;
380 close(uf);
381 if (unquick) {
382 fwopen();
383 for (p = person1; p != 0; p = p->link)
384 decode(p);
385 fwclose();
389 static void print()
391 register FILE *fp;
392 register struct person *p;
393 register char *s;
394 register c;
397 * print out what we got
399 if (header) {
400 if (unquick) {
401 if (!unshort)
402 if (wide)
403 printf("Login Name TTY Idle When Where\n");
404 else
405 printf("Login TTY Idle When Where\n");
406 } else {
407 printf("Login TTY When");
408 if (idle)
409 printf(" Idle");
410 putchar('\n');
413 for (p = person1; p != 0; p = p->link) {
414 if (!unquick) {
415 quickprint(p);
416 continue;
418 if (!unshort) {
419 shortprint(p);
420 continue;
422 personprint(p);
423 if (p->pwd != 0 && !AlreadyPrinted(p->pwd->pw_uid)) {
424 AnyMail(p->pwd->pw_name);
425 if (hack) {
426 s = malloc(strlen(p->pwd->pw_dir) +
427 sizeof PROJ);
428 strcpy(s, p->pwd->pw_dir);
429 strcat(s, PROJ);
430 if ((fp = fopen(s, "r")) != 0) {
431 printf("Project: ");
432 while ((c = getc(fp)) != EOF) {
433 if (c == '\n')
434 break;
435 if (isprint(c) || isspace(c))
436 putchar(c);
437 else
438 putchar(c ^ 100);
440 fclose(fp);
441 putchar('\n');
443 free(s);
445 if (plan) {
446 s = malloc(strlen(p->pwd->pw_dir) +
447 sizeof PLAN);
448 strcpy(s, p->pwd->pw_dir);
449 strcat(s, PLAN);
450 if ((fp = fopen(s, "r")) == 0) {
451 if (!NONOTHING) printf("No Plan.\n");
452 } else {
453 printf("Plan:\n");
454 while ((c = getc(fp)) != EOF)
455 if (isprint(c) || isspace(c))
456 putchar(c);
457 else
458 putchar(c ^ 100);
459 fclose(fp);
461 free(s);
464 if (p->link != 0)
465 putchar('\n');
470 * Duplicate a pwd entry.
471 * Note: Only the useful things (what the program currently uses) are copied.
473 static struct passwd *
474 pwdcopy(pfrom)
475 register struct passwd *pfrom;
477 register struct passwd *pto;
479 pto = (struct passwd *) malloc(sizeof *pto);
480 #define savestr(s) strcpy(malloc(strlen(s) + 1), s)
481 pto->pw_name = savestr(pfrom->pw_name);
482 pto->pw_uid = pfrom->pw_uid;
483 pto->pw_gecos = savestr(pfrom->pw_gecos);
484 pto->pw_dir = savestr(pfrom->pw_dir);
485 pto->pw_shell = savestr(pfrom->pw_shell);
486 #undef savestr
487 return pto;
491 * print out information on quick format giving just name, tty, login time
492 * and idle time if idle is set.
494 static void quickprint(pers)
495 register struct person *pers;
497 printf("%-*.*s ", NMAX, NMAX, pers->name);
498 if (pers->loggedin) {
499 if (idle) {
500 findidle(pers);
501 printf("%c%-*s %-16.16s", pers->writable ? ' ' : '*',
502 LMAX, pers->tty, ctime(&pers->loginat));
503 ltimeprint(" ", &pers->idletime, "");
504 } else
505 printf(" %-*s %-16.16s", LMAX,
506 pers->tty, ctime(&pers->loginat));
507 putchar('\n');
508 } else
509 printf(" Not Logged In\n");
513 * print out information in short format, giving login name, full name,
514 * tty, idle time, login time, and host.
516 static void shortprint(pers)
517 register struct person *pers;
519 char *p;
520 char dialup;
522 if (pers->pwd == 0) {
523 printf("%-15s ???\n", pers->name);
524 return;
526 printf("%-*s", NMAX, pers->pwd->pw_name);
527 dialup = 0;
528 if (wide) {
529 if (pers->realname)
530 printf(" %-20.20s", pers->realname);
531 else
532 printf(" ??? ");
534 putchar(' ');
535 if (pers->loggedin && !pers->writable)
536 putchar('*');
537 else
538 putchar(' ');
539 if (*pers->tty) {
540 if (pers->tty[0] == 't' && pers->tty[1] == 't' &&
541 pers->tty[2] == 'y') {
542 if (pers->tty[3] == 'd' && pers->loggedin)
543 dialup = 1;
544 printf("%-2.2s ", pers->tty + 3);
545 } else
546 printf("%-2.2s ", pers->tty);
547 } else
548 printf(" ");
549 p = ctime(&pers->loginat);
550 if (pers->loggedin) {
551 stimeprint(&pers->idletime);
552 printf(" %3.3s %-5.5s ", p, p + 11);
553 } else if (pers->loginat == 0)
554 printf(" < . . . . >");
555 else if (tloc - pers->loginat >= 180L * 24 * 60 * 60)
556 printf(" <%-6.6s, %-4.4s>", p + 4, p + 20);
557 else
558 printf(" <%-12.12s>", p + 4);
559 if (pers->host[0])
560 printf(" %-20.20s", pers->host);
561 putchar('\n');
566 * print out a person in long format giving all possible information.
567 * directory and shell are inhibited if unbrief is clear.
569 static void
570 personprint(pers)
571 register struct person *pers;
573 if (pers->pwd == 0) {
574 printf("Login name: %-10s\t\t\tIn real life: ???\n",
575 pers->name);
576 return;
578 printf("Login name: %-10s", pers->pwd->pw_name);
579 if (pers->loggedin && !pers->writable)
580 printf(" (messages off) ");
581 else
582 printf(" ");
583 if (pers->realname)
584 printf("In real life: %s", pers->realname);
585 if (unbrief) {
586 printf("\nDirectory: %-25s", pers->pwd->pw_dir);
587 if (*pers->pwd->pw_shell)
588 printf("\tShell: %-s", pers->pwd->pw_shell);
590 if (pers->loggedin) {
591 register char *ep = ctime(&pers->loginat);
592 if (*pers->host) {
593 printf("\nOn since %15.15s on %s from %s",
594 &ep[4], pers->tty, pers->host);
595 ltimeprint("\n", &pers->idletime, " Idle Time");
596 } else {
597 printf("\nOn since %15.15s on %-*s",
598 &ep[4], LMAX, pers->tty);
599 ltimeprint("\t", &pers->idletime, " Idle Time");
601 } else if (pers->loginat == 0) {
602 if (lf >= 0) printf("\nNever logged in.");
603 } else if (tloc - pers->loginat > 180L * 24 * 60 * 60) {
604 register char *ep = ctime(&pers->loginat);
605 printf("\nLast login %10.10s, %4.4s on %s",
606 ep, ep+20, pers->tty);
607 if (*pers->host)
608 printf(" from %s", pers->host);
609 } else {
610 register char *ep = ctime(&pers->loginat);
611 printf("\nLast login %16.16s on %s", ep, pers->tty);
612 if (*pers->host)
613 printf(" from %s", pers->host);
615 putchar('\n');
620 * decode the information in the gecos field of /etc/passwd
622 static void
623 decode(pers)
624 register struct person *pers;
626 char buffer[256];
627 register char *bp, *gp, *lp;
628 int len;
630 pers->realname = 0;
631 if (pers->pwd == 0)
632 return;
633 gp = pers->pwd->pw_gecos;
634 bp = buffer;
635 if (*gp == ASTERISK)
636 gp++;
637 while (*gp && *gp != COMMA) /* name */
638 if (*gp == SAMENAME) {
639 lp = pers->pwd->pw_name;
640 if (islower(*lp))
641 *bp++ = toupper(*lp++);
642 while (*bp++ = *lp++)
644 bp--;
645 gp++;
646 } else
647 *bp++ = *gp++;
648 *bp++ = 0;
649 if ((len = bp - buffer) > 1)
650 pers->realname = strcpy(malloc(len), buffer);
651 if (pers->loggedin)
652 findidle(pers);
653 else
654 findwhen(pers);
658 * find the last log in of a user by checking the LASTLOG file.
659 * the entry is indexed by the uid, so this can only be done if
660 * the uid is known (which it isn't in quick mode)
663 static void
664 fwopen()
666 if ((lf = open(LASTLOG, 0)) < 0) {
667 if (errno == ENOENT) return;
668 fprintf(stderr, "finger: %s open error\n", LASTLOG);
672 static void
673 findwhen(pers)
674 register struct person *pers;
676 struct utmp ll;
677 #define ll_line ut_line
678 #define ll_host ut_host
679 #define ll_time ut_time
681 int i;
683 if (lf >= 0) {
684 lseek(lf, (long)pers->pwd->pw_uid * sizeof ll, 0);
685 if ((i = read(lf, (char *)&ll, sizeof ll)) == sizeof ll) {
686 bcopy(ll.ll_line, pers->tty, LMAX);
687 pers->tty[LMAX] = 0;
688 bcopy(ll.ll_host, pers->host, HMAX);
689 pers->host[HMAX] = 0;
690 pers->loginat = ll.ll_time;
691 } else {
692 if (i != 0)
693 fprintf(stderr, "finger: %s read error\n",
694 LASTLOG);
695 pers->tty[0] = 0;
696 pers->host[0] = 0;
697 pers->loginat = 0L;
699 } else {
700 pers->tty[0] = 0;
701 pers->host[0] = 0;
702 pers->loginat = 0L;
706 static void fwclose()
708 if (lf >= 0)
709 close(lf);
713 * find the idle time of a user by doing a stat on /dev/tty??,
714 * where tty?? has been gotten from USERLOG, supposedly.
716 static void
717 findidle(pers)
718 register struct person *pers;
720 struct stat ttystatus;
721 static char buffer[20] = "/dev/";
722 long t;
723 #define TTYLEN 5
725 strcpy(buffer + TTYLEN, pers->tty);
726 buffer[TTYLEN+LMAX] = 0;
727 if (stat(buffer, &ttystatus) < 0) {
728 fprintf(stderr, "finger: Can't stat %s\n", buffer);
729 exit(4);
731 time(&t);
732 if (t < ttystatus.st_atime)
733 pers->idletime = 0L;
734 else
735 pers->idletime = t - ttystatus.st_atime;
736 pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE;
740 * print idle time in short format; this program always prints 4 characters;
741 * if the idle time is zero, it prints 4 blanks.
743 static void
744 stimeprint(dt)
745 long *dt;
747 register struct tm *delta;
749 delta = gmtime(dt);
750 if (delta->tm_yday == 0)
751 if (delta->tm_hour == 0)
752 if (delta->tm_min == 0)
753 printf(" ");
754 else
755 printf(" %2d", delta->tm_min);
756 else
757 if (delta->tm_hour >= 10)
758 printf("%3d:", delta->tm_hour);
759 else
760 printf("%1d:%02d",
761 delta->tm_hour, delta->tm_min);
762 else
763 printf("%3dd", delta->tm_yday);
767 * print idle time in long format with care being taken not to pluralize
768 * 1 minutes or 1 hours or 1 days.
769 * print "prefix" first.
771 static int
772 ltimeprint(before, dt, after)
773 long *dt;
774 char *before, *after;
776 register struct tm *delta;
778 delta = gmtime(dt);
779 if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 &&
780 delta->tm_sec <= 10)
781 return (0);
782 printf("%s", before);
783 if (delta->tm_yday >= 10)
784 printf("%d days", delta->tm_yday);
785 else if (delta->tm_yday > 0)
786 printf("%d day%s %d hour%s",
787 delta->tm_yday, delta->tm_yday == 1 ? "" : "s",
788 delta->tm_hour, delta->tm_hour == 1 ? "" : "s");
789 else
790 if (delta->tm_hour >= 10)
791 printf("%d hours", delta->tm_hour);
792 else if (delta->tm_hour > 0)
793 printf("%d hour%s %d minute%s",
794 delta->tm_hour, delta->tm_hour == 1 ? "" : "s",
795 delta->tm_min, delta->tm_min == 1 ? "" : "s");
796 else
797 if (delta->tm_min >= 10)
798 printf("%2d minutes", delta->tm_min);
799 else if (delta->tm_min == 0)
800 printf("%2d seconds", delta->tm_sec);
801 else
802 printf("%d minute%s %d second%s",
803 delta->tm_min,
804 delta->tm_min == 1 ? "" : "s",
805 delta->tm_sec,
806 delta->tm_sec == 1 ? "" : "s");
807 printf("%s", after);
810 static int
811 matchcmp(gname, login, given)
812 register char *gname;
813 char *login;
814 char *given;
816 char buffer[100];
817 register char *bp, *lp;
818 register c;
820 if (*gname == ASTERISK)
821 gname++;
822 lp = 0;
823 bp = buffer;
824 for (;;)
825 switch (c = *gname++) {
826 case SAMENAME:
827 for (lp = login; bp < buffer + sizeof buffer
828 && (*bp++ = *lp++);)
830 bp--;
831 break;
832 case ' ':
833 case COMMA:
834 case '\0':
835 *bp = 0;
836 if (namecmp(buffer, given))
837 return (1);
838 if (c == COMMA || c == 0)
839 return (0);
840 bp = buffer;
841 break;
842 default:
843 if (bp < buffer + sizeof buffer)
844 *bp++ = c;
846 /*NOTREACHED*/
849 static int
850 namecmp(name1, name2)
851 register char *name1, *name2;
853 register c1, c2;
855 for (;;) {
856 c1 = *name1++;
857 if (islower(c1))
858 c1 = toupper(c1);
859 c2 = *name2++;
860 if (islower(c2))
861 c2 = toupper(c2);
862 if (c1 != c2)
863 break;
864 if (c1 == 0)
865 return (1);
867 if (!c1) {
868 for (name2--; isdigit(*name2); name2++)
870 if (*name2 == 0)
871 return (1);
872 } else if (!c2) {
873 for (name1--; isdigit(*name1); name1++)
875 if (*name2 == 0)
876 return (1);
878 return (0);
881 #if NONET
882 static int
883 netfinger(name)
884 char *name;
886 return 0;
888 #else
889 static int
890 netfinger(name)
891 char *name;
893 char *host;
894 struct hostent *hp;
895 int s, result;
896 #if !_MINIX
897 char *rindex();
898 #endif
899 register FILE *f;
900 register int c;
901 register int lastc;
902 nwio_tcpconf_t tcpconf;
903 nwio_tcpcl_t tcpconnopt;
904 char *tcp_device;
906 if (name == NULL)
907 return (0);
908 host = rindex(name, '@');
909 if (host == NULL)
910 return (0);
911 *host++ = 0;
912 hp = gethostbyname(host);
913 if (hp == NULL) {
914 static struct hostent def;
915 static ipaddr_t defaddr;
916 static char namebuf[128];
918 defaddr = inet_addr(host);
919 if (defaddr == -1) {
920 printf("unknown host: %s\n", host);
921 return (1);
923 strcpy(namebuf, host);
924 def.h_name = namebuf;
925 def.h_addr = (char *)&defaddr;
926 def.h_length = sizeof (ipaddr_t);
927 def.h_addrtype = AF_INET;
928 def.h_aliases = 0;
929 hp = &def;
931 printf("[%s] ", hp->h_name);
932 fflush(stdout);
934 tcp_device= getenv("TCP_DEVICE");
935 if (tcp_device == NULL)
936 tcp_device= TCP_DEVICE;
937 s= open (tcp_device, O_RDWR);
938 if (s == -1)
940 fprintf(stderr, "%s: unable to open %s (%s)\n",
941 prog_name, tcp_device, strerror(errno));
942 exit(1);
944 tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
945 tcpconf.nwtc_remaddr= *(ipaddr_t *)hp->h_addr;
946 tcpconf.nwtc_remport= htons(TCPPORT_FINGER);
948 result= ioctl (s, NWIOSTCPCONF, &tcpconf);
949 if (result<0)
951 fprintf(stderr, "%s\n", strerror(errno));
952 exit(1);
955 tcpconnopt.nwtcl_flags= 0;
959 result= ioctl (s, NWIOTCPCONN, &tcpconnopt);
960 if (result<0 && errno== EAGAIN)
962 fprintf(stderr, "got EAGAIN error, sleeping 2s\n");
963 sleep(2);
965 } while (result<0 && errno == EAGAIN);
966 if (result<0)
968 fprintf(stderr, "%s\n", strerror(errno));
969 exit(1);
971 printf("\r\n");
972 if (large) write(s, "/W ", 3);
973 write(s, name, strlen(name));
974 write(s, "\r\n", 2);
975 f = fdopen(s, "r");
976 while ((c = getc(f)) != EOF) {
978 switch(c) {
979 case 0210:
980 case 0211:
981 case 0212:
982 case 0214:
983 c -= 0200;
984 break;
985 case 0215:
986 c = '\n';
987 break;
990 c &= ~0200;
991 if (c == '\r')
993 c= getc(f) & ~0200;
994 if (c == '\012')
996 lastc= c;
997 putchar('\n');
998 continue;
1000 else
1001 putchar('\r');
1003 lastc = c;
1004 if (isprint(c) || isspace(c))
1005 putchar(c);
1006 else
1007 putchar(c ^ 100);
1009 if (lastc != '\n')
1010 putchar('\n');
1011 (void)fclose(f);
1012 return (1);
1014 #endif
1017 * AnyMail - takes a username (string pointer thereto), and
1018 * prints on standard output whether there is any unread mail,
1019 * and if so, how old it is. (JCM@Shasta 15 March 80)
1021 #define preamble "/usr/spool/mail/" /* mailboxes are there */
1022 static int
1023 AnyMail(name)
1024 char *name;
1026 struct stat buf; /* space for file status buffer */
1027 char *mbxdir = preamble; /* string with path preamble */
1028 char *mbxpath; /* space for entire pathname */
1030 #if !_MINIX
1031 char *ctime(); /* convert longword time to ascii */
1032 #endif
1033 char *timestr;
1035 mbxpath = malloc(strlen(name) + strlen(preamble) + 1);
1037 strcpy(mbxpath, mbxdir); /* copy preamble into path name */
1038 strcat(mbxpath, name); /* concatenate user name to path */
1040 if (stat(mbxpath, &buf) == -1 || buf.st_size == 0) {
1041 /* Mailbox is empty or nonexistent */
1042 if (!NONOTHING) printf("No unread mail\n");
1043 } else {
1044 if (buf.st_mtime == buf.st_atime) {
1045 /* There is something in the mailbox, but we can't really
1046 * be sure whether it is mail held there by the user
1047 * or a (single) new message that was placed in a newly
1048 * recreated mailbox, so we punt and call it "unread mail."
1050 printf("Unread mail since ");
1051 printf(ctime(&buf.st_mtime));
1052 } else {
1053 /* New mail has definitely arrived since the last time
1054 * mail was read. mtime is the time the most recent
1055 * message arrived; atime is either the time the oldest
1056 * unread message arrived, or the last time the mail
1057 * was read.
1059 printf("New mail received ");
1060 timestr = ctime(&buf.st_mtime); /* time last modified */
1061 timestr[24] = '\0'; /* suppress newline (ugh) */
1062 printf(timestr);
1063 printf(";\n unread since ");
1064 printf(ctime(&buf.st_atime)); /* time last accessed */
1068 free(mbxpath);
1072 * return true iff we've already printed project/plan for this uid;
1073 * if not, enter this uid into table (so this function has a side-effect.)
1075 #define PPMAX 200 /* assume no more than 200 logged-in users */
1076 int PlanPrinted[PPMAX+1];
1077 int PPIndex = 0; /* index of next unused table entry */
1079 static int
1080 AlreadyPrinted(uid)
1081 int uid;
1083 int i = 0;
1085 while (i++ < PPIndex) {
1086 if (PlanPrinted[i] == uid)
1087 return(1);
1089 if (i < PPMAX) {
1090 PlanPrinted[i] = uid;
1091 PPIndex++;
1093 return(0);