pci: don't do sanity check for missing pci bus, the check can misfire.
[minix.git] / commands / simple / finger.c
bloba1ce1fdd33504ef895058f5b4204787314cacb55
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 <minix/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 int main (int argc, char *argv[]);
131 static void doall(void);
132 static void donames(char **args);
133 static void print(void);
134 static void fwopen(void);
135 static void decode(struct person *pers);
136 static void fwclose(void);
137 static int netfinger (char *name);
138 static int matchcmp (char *gname, char *login, char *given);
139 static void quickprint (struct person *pers);
140 static void shortprint (struct person *pers);
141 static void personprint (struct person *pers);
142 static int AlreadyPrinted(int uid);
143 static int AnyMail (char *name);
144 static struct passwd *pwdcopy(struct passwd *pfrom);
145 static void findidle (struct person *pers);
146 static int ltimeprint (char *dt, long *before, char *after);
147 static void stimeprint (long *dt);
148 static void findwhen (struct person *pers);
149 static int namecmp (char *name1, char *name2);
151 main(argc, argv)
152 int argc;
153 register char **argv;
155 register char *s;
157 prog_name= argv[0];
159 /* parse command line for (optional) arguments */
160 while (*++argv && **argv == COMMAND)
161 for (s = *argv + 1; *s; s++)
162 switch (*s) {
163 case 'b':
164 unbrief = 0;
165 break;
166 case 'f':
167 header = 0;
168 break;
169 case 'h':
170 hack = 0;
171 break;
172 case 'i':
173 idle = 1;
174 unquick = 0;
175 break;
176 case 'l':
177 large = 1;
178 break;
179 case 'm':
180 match = 0;
181 break;
182 case 'p':
183 plan = 0;
184 break;
185 case 'q':
186 unquick = 0;
187 break;
188 case 's':
189 small = 1;
190 break;
191 case 'w':
192 wide = 0;
193 break;
194 default:
195 fprintf(stderr, "Usage: finger [-bfhilmpqsw] [login1 [login2 ...] ]\n");
196 exit(1);
198 if (unquick || idle)
199 time(&tloc);
201 * *argv == 0 means no names given
203 if (*argv == 0)
204 doall();
205 else
206 donames(argv);
207 if (person1)
208 print();
209 exit(0);
212 static void doall()
214 register struct person *p;
215 register struct passwd *pw;
216 int uf;
217 char name[NMAX + 1];
219 unshort = large;
220 if ((uf = open(USERLOG, 0)) < 0) {
221 fprintf(stderr, "finger: error opening %s\n", USERLOG);
222 exit(2);
224 if (unquick) {
225 setpwent();
226 fwopen();
228 while (read(uf, (char *)&user, sizeof user) == sizeof user) {
229 if (user.ut_name[0] == 0)
230 continue;
231 if (person1 == 0)
232 p = person1 = (struct person *) malloc(sizeof *p);
233 else {
234 p->link = (struct person *) malloc(sizeof *p);
235 p = p->link;
237 bcopy(user.ut_name, name, NMAX);
238 name[NMAX] = 0;
239 bcopy(user.ut_line, p->tty, LMAX);
240 p->tty[LMAX] = 0;
241 bcopy(user.ut_host, p->host, HMAX);
242 p->host[HMAX] = 0;
243 p->loginat = user.ut_time;
244 p->pwd = 0;
245 p->loggedin = 1;
246 p->where = NULL;
247 if (unquick && (pw = getpwnam(name))) {
248 p->pwd = pwdcopy(pw);
249 decode(p);
250 p->name = p->pwd->pw_name;
251 } else
252 p->name = strcpy(malloc(strlen(name) + 1), name);
254 if (unquick) {
255 fwclose();
256 endpwent();
258 close(uf);
259 if (person1 == 0) {
260 printf("No one logged on\n");
261 return;
263 p->link = 0;
266 static void donames(argv)
267 char **argv;
269 register struct person *p;
270 register struct passwd *pw;
271 int uf;
274 * get names from command line and check to see if they're
275 * logged in
277 unshort = !small;
278 for (; *argv != 0; argv++) {
279 if (netfinger(*argv))
280 continue;
281 if (person1 == 0)
282 p = person1 = (struct person *) malloc(sizeof *p);
283 else {
284 p->link = (struct person *) malloc(sizeof *p);
285 p = p->link;
287 p->name = *argv;
288 p->loggedin = 0;
289 p->original = 1;
290 p->pwd = 0;
292 if (person1 == 0)
293 return;
294 p->link = 0;
296 * if we are doing it, read /etc/passwd for the useful info
298 if (unquick) {
299 setpwent();
300 if (!match) {
301 for (p = person1; p != 0; p = p->link)
302 if (pw = getpwnam(p->name))
303 p->pwd = pwdcopy(pw);
304 } else while ((pw = getpwent()) != 0) {
305 for (p = person1; p != 0; p = p->link) {
306 if (!p->original)
307 continue;
308 if (strcmp(p->name, pw->pw_name) != 0 &&
309 !matchcmp(pw->pw_gecos, pw->pw_name, p->name))
310 continue;
311 if (p->pwd == 0)
312 p->pwd = pwdcopy(pw);
313 else {
314 struct person *new;
316 * handle multiple login names, insert
317 * new "duplicate" entry behind
319 new = (struct person *)
320 malloc(sizeof *new);
321 new->pwd = pwdcopy(pw);
322 new->name = p->name;
323 new->original = 1;
324 new->loggedin = 0;
325 new->link = p->link;
326 p->original = 0;
327 p->link = new;
328 p = new;
332 endpwent();
334 /* Now get login information */
335 if ((uf = open(USERLOG, 0)) < 0) {
336 fprintf(stderr, "finger: error opening %s\n", USERLOG);
337 exit(2);
339 while (read(uf, (char *)&user, sizeof user) == sizeof user) {
340 if (*user.ut_name == 0)
341 continue;
342 for (p = person1; p != 0; p = p->link) {
343 if (p->loggedin == 2)
344 continue;
345 if (strncmp(p->pwd ? p->pwd->pw_name : p->name,
346 user.ut_name, NMAX) != 0)
347 continue;
348 if (p->loggedin == 0) {
349 bcopy(user.ut_line, p->tty, LMAX);
350 p->tty[LMAX] = 0;
351 bcopy(user.ut_host, p->host, HMAX);
352 p->host[HMAX] = 0;
353 p->loginat = user.ut_time;
354 p->loggedin = 1;
355 } else { /* p->loggedin == 1 */
356 struct person *new;
357 new = (struct person *) malloc(sizeof *new);
358 new->name = p->name;
359 bcopy(user.ut_line, new->tty, LMAX);
360 new->tty[LMAX] = 0;
361 bcopy(user.ut_host, new->host, HMAX);
362 new->host[HMAX] = 0;
363 new->loginat = user.ut_time;
364 new->pwd = p->pwd;
365 new->loggedin = 1;
366 new->original = 0;
367 new->link = p->link;
368 p->loggedin = 2;
369 p->link = new;
370 p = new;
374 close(uf);
375 if (unquick) {
376 fwopen();
377 for (p = person1; p != 0; p = p->link)
378 decode(p);
379 fwclose();
383 static void print()
385 register FILE *fp;
386 register struct person *p;
387 register char *s;
388 register c;
391 * print out what we got
393 if (header) {
394 if (unquick) {
395 if (!unshort)
396 if (wide)
397 printf("Login Name TTY Idle When Where\n");
398 else
399 printf("Login TTY Idle When Where\n");
400 } else {
401 printf("Login TTY When");
402 if (idle)
403 printf(" Idle");
404 putchar('\n');
407 for (p = person1; p != 0; p = p->link) {
408 if (!unquick) {
409 quickprint(p);
410 continue;
412 if (!unshort) {
413 shortprint(p);
414 continue;
416 personprint(p);
417 if (p->pwd != 0 && !AlreadyPrinted(p->pwd->pw_uid)) {
418 AnyMail(p->pwd->pw_name);
419 if (hack) {
420 s = malloc(strlen(p->pwd->pw_dir) +
421 sizeof PROJ);
422 strcpy(s, p->pwd->pw_dir);
423 strcat(s, PROJ);
424 if ((fp = fopen(s, "r")) != 0) {
425 printf("Project: ");
426 while ((c = getc(fp)) != EOF) {
427 if (c == '\n')
428 break;
429 if (isprint(c) || isspace(c))
430 putchar(c);
431 else
432 putchar(c ^ 100);
434 fclose(fp);
435 putchar('\n');
437 free(s);
439 if (plan) {
440 s = malloc(strlen(p->pwd->pw_dir) +
441 sizeof PLAN);
442 strcpy(s, p->pwd->pw_dir);
443 strcat(s, PLAN);
444 if ((fp = fopen(s, "r")) == 0) {
445 if (!NONOTHING) printf("No Plan.\n");
446 } else {
447 printf("Plan:\n");
448 while ((c = getc(fp)) != EOF)
449 if (isprint(c) || isspace(c))
450 putchar(c);
451 else
452 putchar(c ^ 100);
453 fclose(fp);
455 free(s);
458 if (p->link != 0)
459 putchar('\n');
464 * Duplicate a pwd entry.
465 * Note: Only the useful things (what the program currently uses) are copied.
467 static struct passwd *
468 pwdcopy(pfrom)
469 register struct passwd *pfrom;
471 register struct passwd *pto;
473 pto = (struct passwd *) malloc(sizeof *pto);
474 #define savestr(s) strcpy(malloc(strlen(s) + 1), s)
475 pto->pw_name = savestr(pfrom->pw_name);
476 pto->pw_uid = pfrom->pw_uid;
477 pto->pw_gecos = savestr(pfrom->pw_gecos);
478 pto->pw_dir = savestr(pfrom->pw_dir);
479 pto->pw_shell = savestr(pfrom->pw_shell);
480 #undef savestr
481 return pto;
485 * print out information on quick format giving just name, tty, login time
486 * and idle time if idle is set.
488 static void quickprint(pers)
489 register struct person *pers;
491 printf("%-*.*s ", NMAX, NMAX, pers->name);
492 if (pers->loggedin) {
493 if (idle) {
494 findidle(pers);
495 printf("%c%-*s %-16.16s", pers->writable ? ' ' : '*',
496 LMAX, pers->tty, ctime(&pers->loginat));
497 ltimeprint(" ", &pers->idletime, "");
498 } else
499 printf(" %-*s %-16.16s", LMAX,
500 pers->tty, ctime(&pers->loginat));
501 putchar('\n');
502 } else
503 printf(" Not Logged In\n");
507 * print out information in short format, giving login name, full name,
508 * tty, idle time, login time, and host.
510 static void shortprint(pers)
511 register struct person *pers;
513 char *p;
514 char dialup;
516 if (pers->pwd == 0) {
517 printf("%-15s ???\n", pers->name);
518 return;
520 printf("%-*s", NMAX, pers->pwd->pw_name);
521 dialup = 0;
522 if (wide) {
523 if (pers->realname)
524 printf(" %-20.20s", pers->realname);
525 else
526 printf(" ??? ");
528 putchar(' ');
529 if (pers->loggedin && !pers->writable)
530 putchar('*');
531 else
532 putchar(' ');
533 if (*pers->tty) {
534 if (pers->tty[0] == 't' && pers->tty[1] == 't' &&
535 pers->tty[2] == 'y') {
536 if (pers->tty[3] == 'd' && pers->loggedin)
537 dialup = 1;
538 printf("%-2.2s ", pers->tty + 3);
539 } else
540 printf("%-2.2s ", pers->tty);
541 } else
542 printf(" ");
543 p = ctime(&pers->loginat);
544 if (pers->loggedin) {
545 stimeprint(&pers->idletime);
546 printf(" %3.3s %-5.5s ", p, p + 11);
547 } else if (pers->loginat == 0)
548 printf(" < . . . . >");
549 else if (tloc - pers->loginat >= 180L * 24 * 60 * 60)
550 printf(" <%-6.6s, %-4.4s>", p + 4, p + 20);
551 else
552 printf(" <%-12.12s>", p + 4);
553 if (pers->host[0])
554 printf(" %-20.20s", pers->host);
555 putchar('\n');
560 * print out a person in long format giving all possible information.
561 * directory and shell are inhibited if unbrief is clear.
563 static void
564 personprint(pers)
565 register struct person *pers;
567 if (pers->pwd == 0) {
568 printf("Login name: %-10s\t\t\tIn real life: ???\n",
569 pers->name);
570 return;
572 printf("Login name: %-10s", pers->pwd->pw_name);
573 if (pers->loggedin && !pers->writable)
574 printf(" (messages off) ");
575 else
576 printf(" ");
577 if (pers->realname)
578 printf("In real life: %s", pers->realname);
579 if (unbrief) {
580 printf("\nDirectory: %-25s", pers->pwd->pw_dir);
581 if (*pers->pwd->pw_shell)
582 printf("\tShell: %-s", pers->pwd->pw_shell);
584 if (pers->loggedin) {
585 register char *ep = ctime(&pers->loginat);
586 if (*pers->host) {
587 printf("\nOn since %15.15s on %s from %s",
588 &ep[4], pers->tty, pers->host);
589 ltimeprint("\n", &pers->idletime, " Idle Time");
590 } else {
591 printf("\nOn since %15.15s on %-*s",
592 &ep[4], LMAX, pers->tty);
593 ltimeprint("\t", &pers->idletime, " Idle Time");
595 } else if (pers->loginat == 0) {
596 if (lf >= 0) printf("\nNever logged in.");
597 } else if (tloc - pers->loginat > 180L * 24 * 60 * 60) {
598 register char *ep = ctime(&pers->loginat);
599 printf("\nLast login %10.10s, %4.4s on %s",
600 ep, ep+20, pers->tty);
601 if (*pers->host)
602 printf(" from %s", pers->host);
603 } else {
604 register char *ep = ctime(&pers->loginat);
605 printf("\nLast login %16.16s on %s", ep, pers->tty);
606 if (*pers->host)
607 printf(" from %s", pers->host);
609 putchar('\n');
614 * decode the information in the gecos field of /etc/passwd
616 static void
617 decode(pers)
618 register struct person *pers;
620 char buffer[256];
621 register char *bp, *gp, *lp;
622 int len;
624 pers->realname = 0;
625 if (pers->pwd == 0)
626 return;
627 gp = pers->pwd->pw_gecos;
628 bp = buffer;
629 if (*gp == ASTERISK)
630 gp++;
631 while (*gp && *gp != COMMA) /* name */
632 if (*gp == SAMENAME) {
633 lp = pers->pwd->pw_name;
634 if (islower(*lp))
635 *bp++ = toupper(*lp++);
636 while (*bp++ = *lp++)
638 bp--;
639 gp++;
640 } else
641 *bp++ = *gp++;
642 *bp++ = 0;
643 if ((len = bp - buffer) > 1)
644 pers->realname = strcpy(malloc(len), buffer);
645 if (pers->loggedin)
646 findidle(pers);
647 else
648 findwhen(pers);
652 * find the last log in of a user by checking the LASTLOG file.
653 * the entry is indexed by the uid, so this can only be done if
654 * the uid is known (which it isn't in quick mode)
657 static void
658 fwopen()
660 if ((lf = open(LASTLOG, 0)) < 0) {
661 if (errno == ENOENT) return;
662 fprintf(stderr, "finger: %s open error\n", LASTLOG);
666 static void
667 findwhen(pers)
668 register struct person *pers;
670 struct utmp ll;
671 #define ll_line ut_line
672 #define ll_host ut_host
673 #define ll_time ut_time
675 int i;
677 if (lf >= 0) {
678 lseek(lf, (long)pers->pwd->pw_uid * sizeof ll, 0);
679 if ((i = read(lf, (char *)&ll, sizeof ll)) == sizeof ll) {
680 bcopy(ll.ll_line, pers->tty, LMAX);
681 pers->tty[LMAX] = 0;
682 bcopy(ll.ll_host, pers->host, HMAX);
683 pers->host[HMAX] = 0;
684 pers->loginat = ll.ll_time;
685 } else {
686 if (i != 0)
687 fprintf(stderr, "finger: %s read error\n",
688 LASTLOG);
689 pers->tty[0] = 0;
690 pers->host[0] = 0;
691 pers->loginat = 0L;
693 } else {
694 pers->tty[0] = 0;
695 pers->host[0] = 0;
696 pers->loginat = 0L;
700 static void fwclose()
702 if (lf >= 0)
703 close(lf);
707 * find the idle time of a user by doing a stat on /dev/tty??,
708 * where tty?? has been gotten from USERLOG, supposedly.
710 static void
711 findidle(pers)
712 register struct person *pers;
714 struct stat ttystatus;
715 static char buffer[20] = "/dev/";
716 long t;
717 #define TTYLEN 5
719 strcpy(buffer + TTYLEN, pers->tty);
720 buffer[TTYLEN+LMAX] = 0;
721 if (stat(buffer, &ttystatus) < 0) {
722 fprintf(stderr, "finger: Can't stat %s\n", buffer);
723 exit(4);
725 time(&t);
726 if (t < ttystatus.st_atime)
727 pers->idletime = 0L;
728 else
729 pers->idletime = t - ttystatus.st_atime;
730 pers->writable = (ttystatus.st_mode & TALKABLE) == TALKABLE;
734 * print idle time in short format; this program always prints 4 characters;
735 * if the idle time is zero, it prints 4 blanks.
737 static void
738 stimeprint(dt)
739 long *dt;
741 register struct tm *delta;
743 delta = gmtime(dt);
744 if (delta->tm_yday == 0)
745 if (delta->tm_hour == 0)
746 if (delta->tm_min == 0)
747 printf(" ");
748 else
749 printf(" %2d", delta->tm_min);
750 else
751 if (delta->tm_hour >= 10)
752 printf("%3d:", delta->tm_hour);
753 else
754 printf("%1d:%02d",
755 delta->tm_hour, delta->tm_min);
756 else
757 printf("%3dd", delta->tm_yday);
761 * print idle time in long format with care being taken not to pluralize
762 * 1 minutes or 1 hours or 1 days.
763 * print "prefix" first.
765 static int
766 ltimeprint(before, dt, after)
767 long *dt;
768 char *before, *after;
770 register struct tm *delta;
772 delta = gmtime(dt);
773 if (delta->tm_yday == 0 && delta->tm_hour == 0 && delta->tm_min == 0 &&
774 delta->tm_sec <= 10)
775 return (0);
776 printf("%s", before);
777 if (delta->tm_yday >= 10)
778 printf("%d days", delta->tm_yday);
779 else if (delta->tm_yday > 0)
780 printf("%d day%s %d hour%s",
781 delta->tm_yday, delta->tm_yday == 1 ? "" : "s",
782 delta->tm_hour, delta->tm_hour == 1 ? "" : "s");
783 else
784 if (delta->tm_hour >= 10)
785 printf("%d hours", delta->tm_hour);
786 else if (delta->tm_hour > 0)
787 printf("%d hour%s %d minute%s",
788 delta->tm_hour, delta->tm_hour == 1 ? "" : "s",
789 delta->tm_min, delta->tm_min == 1 ? "" : "s");
790 else
791 if (delta->tm_min >= 10)
792 printf("%2d minutes", delta->tm_min);
793 else if (delta->tm_min == 0)
794 printf("%2d seconds", delta->tm_sec);
795 else
796 printf("%d minute%s %d second%s",
797 delta->tm_min,
798 delta->tm_min == 1 ? "" : "s",
799 delta->tm_sec,
800 delta->tm_sec == 1 ? "" : "s");
801 printf("%s", after);
804 static int
805 matchcmp(gname, login, given)
806 register char *gname;
807 char *login;
808 char *given;
810 char buffer[100];
811 register char *bp, *lp;
812 register c;
814 if (*gname == ASTERISK)
815 gname++;
816 lp = 0;
817 bp = buffer;
818 for (;;)
819 switch (c = *gname++) {
820 case SAMENAME:
821 for (lp = login; bp < buffer + sizeof buffer
822 && (*bp++ = *lp++);)
824 bp--;
825 break;
826 case ' ':
827 case COMMA:
828 case '\0':
829 *bp = 0;
830 if (namecmp(buffer, given))
831 return (1);
832 if (c == COMMA || c == 0)
833 return (0);
834 bp = buffer;
835 break;
836 default:
837 if (bp < buffer + sizeof buffer)
838 *bp++ = c;
840 /*NOTREACHED*/
843 static int
844 namecmp(name1, name2)
845 register char *name1, *name2;
847 register c1, c2;
849 for (;;) {
850 c1 = *name1++;
851 if (islower(c1))
852 c1 = toupper(c1);
853 c2 = *name2++;
854 if (islower(c2))
855 c2 = toupper(c2);
856 if (c1 != c2)
857 break;
858 if (c1 == 0)
859 return (1);
861 if (!c1) {
862 for (name2--; isdigit(*name2); name2++)
864 if (*name2 == 0)
865 return (1);
866 } else if (!c2) {
867 for (name1--; isdigit(*name1); name1++)
869 if (*name2 == 0)
870 return (1);
872 return (0);
875 #if NONET
876 static int
877 netfinger(name)
878 char *name;
880 return 0;
882 #else
883 static int
884 netfinger(name)
885 char *name;
887 char *host;
888 struct hostent *hp;
889 int s, result;
890 #if !_MINIX
891 char *rindex();
892 #endif
893 register FILE *f;
894 register int c;
895 register int lastc;
896 nwio_tcpconf_t tcpconf;
897 nwio_tcpcl_t tcpconnopt;
898 char *tcp_device;
900 if (name == NULL)
901 return (0);
902 host = rindex(name, '@');
903 if (host == NULL)
904 return (0);
905 *host++ = 0;
906 hp = gethostbyname(host);
907 if (hp == NULL) {
908 static struct hostent def;
909 static ipaddr_t defaddr;
910 static char namebuf[128];
912 defaddr = inet_addr(host);
913 if (defaddr == -1) {
914 printf("unknown host: %s\n", host);
915 return (1);
917 strcpy(namebuf, host);
918 def.h_name = namebuf;
919 def.h_addr = (char *)&defaddr;
920 def.h_length = sizeof (ipaddr_t);
921 def.h_addrtype = AF_INET;
922 def.h_aliases = 0;
923 hp = &def;
925 printf("[%s] ", hp->h_name);
926 fflush(stdout);
928 tcp_device= getenv("TCP_DEVICE");
929 if (tcp_device == NULL)
930 tcp_device= TCP_DEVICE;
931 s= open (tcp_device, O_RDWR);
932 if (s == -1)
934 fprintf(stderr, "%s: unable to open %s (%s)\n",
935 prog_name, tcp_device, strerror(errno));
936 exit(1);
938 tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
939 tcpconf.nwtc_remaddr= *(ipaddr_t *)hp->h_addr;
940 tcpconf.nwtc_remport= htons(TCPPORT_FINGER);
942 result= ioctl (s, NWIOSTCPCONF, &tcpconf);
943 if (result<0)
945 fprintf(stderr, "%s\n", strerror(errno));
946 exit(1);
949 tcpconnopt.nwtcl_flags= 0;
953 result= ioctl (s, NWIOTCPCONN, &tcpconnopt);
954 if (result<0 && errno== EAGAIN)
956 fprintf(stderr, "got EAGAIN error, sleeping 2s\n");
957 sleep(2);
959 } while (result<0 && errno == EAGAIN);
960 if (result<0)
962 fprintf(stderr, "%s\n", strerror(errno));
963 exit(1);
965 printf("\r\n");
966 if (large) write(s, "/W ", 3);
967 write(s, name, strlen(name));
968 write(s, "\r\n", 2);
969 f = fdopen(s, "r");
970 while ((c = getc(f)) != EOF) {
972 switch(c) {
973 case 0210:
974 case 0211:
975 case 0212:
976 case 0214:
977 c -= 0200;
978 break;
979 case 0215:
980 c = '\n';
981 break;
984 c &= ~0200;
985 if (c == '\r')
987 c= getc(f) & ~0200;
988 if (c == '\012')
990 lastc= c;
991 putchar('\n');
992 continue;
994 else
995 putchar('\r');
997 lastc = c;
998 if (isprint(c) || isspace(c))
999 putchar(c);
1000 else
1001 putchar(c ^ 100);
1003 if (lastc != '\n')
1004 putchar('\n');
1005 (void)fclose(f);
1006 return (1);
1008 #endif
1011 * AnyMail - takes a username (string pointer thereto), and
1012 * prints on standard output whether there is any unread mail,
1013 * and if so, how old it is. (JCM@Shasta 15 March 80)
1015 #define preamble "/usr/spool/mail/" /* mailboxes are there */
1016 static int
1017 AnyMail(name)
1018 char *name;
1020 struct stat buf; /* space for file status buffer */
1021 char *mbxdir = preamble; /* string with path preamble */
1022 char *mbxpath; /* space for entire pathname */
1024 #if !_MINIX
1025 char *ctime(); /* convert longword time to ascii */
1026 #endif
1027 char *timestr;
1029 mbxpath = malloc(strlen(name) + strlen(preamble) + 1);
1031 strcpy(mbxpath, mbxdir); /* copy preamble into path name */
1032 strcat(mbxpath, name); /* concatenate user name to path */
1034 if (stat(mbxpath, &buf) == -1 || buf.st_size == 0) {
1035 /* Mailbox is empty or nonexistent */
1036 if (!NONOTHING) printf("No unread mail\n");
1037 } else {
1038 if (buf.st_mtime == buf.st_atime) {
1039 /* There is something in the mailbox, but we can't really
1040 * be sure whether it is mail held there by the user
1041 * or a (single) new message that was placed in a newly
1042 * recreated mailbox, so we punt and call it "unread mail."
1044 printf("Unread mail since ");
1045 printf(ctime(&buf.st_mtime));
1046 } else {
1047 /* New mail has definitely arrived since the last time
1048 * mail was read. mtime is the time the most recent
1049 * message arrived; atime is either the time the oldest
1050 * unread message arrived, or the last time the mail
1051 * was read.
1053 printf("New mail received ");
1054 timestr = ctime(&buf.st_mtime); /* time last modified */
1055 timestr[24] = '\0'; /* suppress newline (ugh) */
1056 printf(timestr);
1057 printf(";\n unread since ");
1058 printf(ctime(&buf.st_atime)); /* time last accessed */
1062 free(mbxpath);
1066 * return true iff we've already printed project/plan for this uid;
1067 * if not, enter this uid into table (so this function has a side-effect.)
1069 #define PPMAX 200 /* assume no more than 200 logged-in users */
1070 int PlanPrinted[PPMAX+1];
1071 int PPIndex = 0; /* index of next unused table entry */
1073 static int
1074 AlreadyPrinted(uid)
1075 int uid;
1077 int i = 0;
1079 while (i++ < PPIndex) {
1080 if (PlanPrinted[i] == uid)
1081 return(1);
1083 if (i < PPMAX) {
1084 PlanPrinted[i] = uid;
1085 PPIndex++;
1087 return(0);