137660Sbostic /* 237660Sbostic * Copyright (c) 1989 The Regents of the University of California. 337660Sbostic * All rights reserved. 437660Sbostic * 540027Sbostic * This code is derived from software contributed to Berkeley by 640027Sbostic * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 740027Sbostic * 842731Sbostic * %sccs.include.redist.c% 937660Sbostic */ 1037660Sbostic 1137660Sbostic #ifndef lint 12*50596Sbostic static char sccsid[] = "@(#)lprint.c 5.15 (Berkeley) 07/27/91"; 1337660Sbostic #endif /* not lint */ 1437660Sbostic 1537660Sbostic #include <sys/types.h> 1637660Sbostic #include <sys/stat.h> 1737660Sbostic #include <sys/time.h> 18*50596Sbostic #include <fcntl.h> 19*50596Sbostic #include <time.h> 2037660Sbostic #include <tzfile.h> 21*50596Sbostic #include <pwd.h> 22*50596Sbostic #include <utmp.h> 23*50596Sbostic #include <unistd.h> 2437660Sbostic #include <stdio.h> 2538901Sbostic #include <ctype.h> 26*50596Sbostic #include <string.h> 2743857Sbostic #include <paths.h> 2837660Sbostic #include "finger.h" 2937660Sbostic 3037660Sbostic #define LINE_LEN 80 3137660Sbostic #define TAB_LEN 8 /* 8 spaces between tabs */ 3250595Sbostic #define _PATH_FORWARD ".forward" 3337660Sbostic #define _PATH_PLAN ".plan" 3437660Sbostic #define _PATH_PROJECT ".project" 3537660Sbostic 36*50596Sbostic static int demi_print __P((char *, int)); 37*50596Sbostic static void lprint __P((PERSON *)); 38*50596Sbostic static int show_text __P((char *, char *, char *)); 39*50596Sbostic static void vputc __P((int)); 40*50596Sbostic 41*50596Sbostic void 4237660Sbostic lflag_print() 4337660Sbostic { 4437660Sbostic extern int pplan; 4537660Sbostic register PERSON *pn; 4637660Sbostic 4737664Sedward for (pn = phead;;) { 4837660Sbostic lprint(pn); 4937660Sbostic if (!pplan) { 5050595Sbostic (void)show_text(pn->dir, 5150595Sbostic _PATH_FORWARD, "Mail forwarded to"); 5250595Sbostic (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 5350595Sbostic if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 5437660Sbostic (void)printf("No Plan.\n"); 5537660Sbostic } 5637660Sbostic if (!(pn = pn->next)) 5737660Sbostic break; 5837660Sbostic putchar('\n'); 5937660Sbostic } 6037660Sbostic } 6137660Sbostic 62*50596Sbostic static void 6337660Sbostic lprint(pn) 6437660Sbostic register PERSON *pn; 6537660Sbostic { 6637660Sbostic extern time_t now; 6737660Sbostic register struct tm *delta; 6837664Sedward register WHERE *w; 6937660Sbostic register int cpr, len, maxlen; 7042919Sbostic struct tm *tp; 7137660Sbostic int oddfield; 72*50596Sbostic char *t, *tzn; 7337660Sbostic 7437660Sbostic /* 7537660Sbostic * long format -- 7637660Sbostic * login name 7737660Sbostic * real name 7837660Sbostic * home directory 7937660Sbostic * shell 8037660Sbostic * office, office phone, home phone if available 8137660Sbostic */ 8237660Sbostic (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", 8337660Sbostic pn->name, pn->realname, pn->dir); 8437660Sbostic (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); 8537660Sbostic 8637660Sbostic /* 8737660Sbostic * try and print office, office phone, and home phone on one line; 8837660Sbostic * if that fails, do line filling so it looks nice. 8937660Sbostic */ 9037660Sbostic #define OFFICE_TAG "Office" 9137660Sbostic #define OFFICE_PHONE_TAG "Office Phone" 9237660Sbostic oddfield = 0; 9337660Sbostic if (pn->office && pn->officephone && 9437660Sbostic strlen(pn->office) + strlen(pn->officephone) + 9537660Sbostic sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { 9650595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", 9750595Sbostic OFFICE_TAG, pn->office, prphone(pn->officephone)); 9837660Sbostic oddfield = demi_print(tbuf, oddfield); 9937660Sbostic } else { 10037660Sbostic if (pn->office) { 10150595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 10250595Sbostic OFFICE_TAG, pn->office); 10337660Sbostic oddfield = demi_print(tbuf, oddfield); 10437660Sbostic } 10537660Sbostic if (pn->officephone) { 10650595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 10750595Sbostic OFFICE_PHONE_TAG, prphone(pn->officephone)); 10837660Sbostic oddfield = demi_print(tbuf, oddfield); 10937660Sbostic } 11037660Sbostic } 11137660Sbostic if (pn->homephone) { 11250595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", 11338052Sbostic prphone(pn->homephone)); 11437660Sbostic oddfield = demi_print(tbuf, oddfield); 11537660Sbostic } 11637660Sbostic if (oddfield) 11737660Sbostic putchar('\n'); 11837660Sbostic 11937660Sbostic /* 12037664Sedward * long format con't: * if logged in 12137660Sbostic * terminal 12237660Sbostic * idle time 12337660Sbostic * if messages allowed 12437660Sbostic * where logged in from 12537664Sedward * if not logged in 12637664Sedward * when last logged in 12737660Sbostic */ 12837664Sedward /* find out longest device name for this user for formatting */ 12937775Sbostic for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) 13037664Sedward if ((len = strlen(w->tty)) > maxlen) 13137664Sedward maxlen = len; 13237664Sedward /* find rest of entries for user */ 13337664Sedward for (w = pn->whead; w != NULL; w = w->next) { 13437664Sedward switch (w->info) { 13537664Sedward case LOGGEDIN: 13642919Sbostic tp = localtime(&w->loginat); 13742919Sbostic t = asctime(tp); 13842919Sbostic tzn = tp->tm_zone; 13945455Sbostic cpr = printf("On since %.16s (%s) on %s", 14042919Sbostic t, tzn, w->tty); 14137660Sbostic /* 14237660Sbostic * idle time is tough; if have one, print a comma, 14337660Sbostic * then spaces to pad out the device name, then the 14437660Sbostic * idle time. Follow with a comma if a remote login. 14537660Sbostic */ 14637664Sedward delta = gmtime(&w->idletime); 14737660Sbostic if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 14837660Sbostic cpr += printf("%-*s idle ", 14937664Sedward maxlen - strlen(w->tty) + 1, ","); 15037660Sbostic if (delta->tm_yday > 0) { 15137660Sbostic cpr += printf("%d day%s ", 15237660Sbostic delta->tm_yday, 15337660Sbostic delta->tm_yday == 1 ? "" : "s"); 15437660Sbostic } 15537660Sbostic cpr += printf("%d:%02d", 15637660Sbostic delta->tm_hour, delta->tm_min); 15737664Sedward if (*w->host) { 15837660Sbostic putchar(','); 15937660Sbostic ++cpr; 16037660Sbostic } 16137660Sbostic } 16237664Sedward if (!w->writable) 16337660Sbostic cpr += printf(" (messages off)"); 16437664Sedward break; 16537664Sedward case LASTLOG: 16637664Sedward if (w->loginat == 0) { 16737664Sedward (void)printf("Never logged in."); 16837664Sedward break; 16937660Sbostic } 17042919Sbostic tp = localtime(&w->loginat); 17142919Sbostic t = asctime(tp); 17242919Sbostic tzn = tp->tm_zone; 17337664Sedward if (now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2) 17445455Sbostic cpr = 17545455Sbostic printf("Last login %.16s %.4s (%s) on %s", 17642919Sbostic t, t + 20, tzn, w->tty); 17737664Sedward else 17845455Sbostic cpr = printf("Last login %.16s (%s) on %s", 17942919Sbostic t, tzn, w->tty); 18037664Sedward break; 18137660Sbostic } 18237664Sedward if (*w->host) { 18337664Sedward if (LINE_LEN < (cpr + 6 + strlen(w->host))) 18437660Sbostic (void)printf("\n "); 18537664Sedward (void)printf(" from %s", w->host); 18637660Sbostic } 18737660Sbostic putchar('\n'); 18837660Sbostic } 18937660Sbostic } 19037660Sbostic 191*50596Sbostic static int 19237660Sbostic demi_print(str, oddfield) 19337660Sbostic char *str; 19437660Sbostic int oddfield; 19537660Sbostic { 19637660Sbostic static int lenlast; 19737660Sbostic int lenthis, maxlen; 19837660Sbostic 19937660Sbostic lenthis = strlen(str); 20037660Sbostic if (oddfield) { 20137660Sbostic /* 20237660Sbostic * We left off on an odd number of fields. If we haven't 20337660Sbostic * crossed the midpoint of the screen, and we have room for 20437660Sbostic * the next field, print it on the same line; otherwise, 20537660Sbostic * print it on a new line. 20637660Sbostic * 20737660Sbostic * Note: we insist on having the right hand fields start 20837660Sbostic * no less than 5 tabs out. 20937660Sbostic */ 21037660Sbostic maxlen = 5 * TAB_LEN; 21137660Sbostic if (maxlen < lenlast) 21237660Sbostic maxlen = lenlast; 21337660Sbostic if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 21437660Sbostic lenthis) <= LINE_LEN) { 21537660Sbostic while(lenlast < (4 * TAB_LEN)) { 21637660Sbostic putchar('\t'); 21737660Sbostic lenlast += TAB_LEN; 21837660Sbostic } 21937660Sbostic (void)printf("\t%s\n", str); /* force one tab */ 22037660Sbostic } else { 22137660Sbostic (void)printf("\n%s", str); /* go to next line */ 22237660Sbostic oddfield = !oddfield; /* this'll be undone below */ 22337660Sbostic } 22437660Sbostic } else 22537660Sbostic (void)printf("%s", str); 22637660Sbostic oddfield = !oddfield; /* toggle odd/even marker */ 22737660Sbostic lenlast = lenthis; 22837660Sbostic return(oddfield); 22937660Sbostic } 23037660Sbostic 231*50596Sbostic static 23237660Sbostic show_text(directory, file_name, header) 23337660Sbostic char *directory, *file_name, *header; 23437660Sbostic { 23550595Sbostic struct stat sb; 23639241Sedward register FILE *fp; 23750595Sbostic register int ch, cnt, lastc; 23850595Sbostic register char *p; 23950595Sbostic int fd, nr; 24037660Sbostic 24150595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); 24250595Sbostic if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || 24350595Sbostic sb.st_size == 0) 24437660Sbostic return(0); 24550595Sbostic 24650595Sbostic /* If short enough, and no newlines, show it on a single line.*/ 24750595Sbostic if (sb.st_size <= LINE_LEN - strlen(header) - 5) { 24850595Sbostic nr = read(fd, tbuf, sizeof(tbuf)); 24950595Sbostic if (nr <= 0) { 25050595Sbostic (void)close(fd); 25150595Sbostic return(0); 25250595Sbostic } 25350595Sbostic for (p = tbuf, cnt = nr; cnt--; ++p) 25450595Sbostic if (*p == '\n') 25550595Sbostic break; 25650595Sbostic if (cnt <= 1) { 25750595Sbostic (void)printf("%s: ", header); 25850595Sbostic for (p = tbuf, cnt = nr; cnt--; ++p) 25950595Sbostic vputc(lastc = *p); 26050595Sbostic if (lastc != '\n') 26150595Sbostic (void)putchar('\n'); 26250595Sbostic (void)close(fd); 26350595Sbostic return(1); 26450595Sbostic } 26550595Sbostic else 26650595Sbostic (void)lseek(fd, 0L, SEEK_SET); 26750595Sbostic } 26850595Sbostic if ((fp = fdopen(fd, "r")) == NULL) 26950595Sbostic return(0); 27050595Sbostic (void)printf("%s:\n", header); 27139241Sedward while ((ch = getc(fp)) != EOF) 27239241Sedward vputc(lastc = ch); 27339241Sedward if (lastc != '\n') 27438901Sbostic (void)putchar('\n'); 27539241Sedward (void)fclose(fp); 27637660Sbostic return(1); 27737660Sbostic } 27838901Sbostic 279*50596Sbostic static void 28038901Sbostic vputc(ch) 28138901Sbostic register int ch; 28238901Sbostic { 28338901Sbostic int meta; 28438901Sbostic 28538901Sbostic if (!isascii(ch)) { 28638901Sbostic (void)putchar('M'); 28738901Sbostic (void)putchar('-'); 28838901Sbostic ch = toascii(ch); 28938901Sbostic meta = 1; 29038901Sbostic } else 29138901Sbostic meta = 0; 29238912Sbostic if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) 29338901Sbostic (void)putchar(ch); 29438901Sbostic else { 29538901Sbostic (void)putchar('^'); 29638901Sbostic (void)putchar(ch == '\177' ? '?' : ch | 0100); 29738901Sbostic } 29838901Sbostic } 299