137660Sbostic /* 261995Sbostic * Copyright (c) 1989, 1993 361995Sbostic * The Regents of the University of California. 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*69101Sbostic static char sccsid[] = "@(#)lprint.c 8.2 (Berkeley) 04/28/95"; 1337660Sbostic #endif /* not lint */ 1437660Sbostic 1537660Sbostic #include <sys/types.h> 1637660Sbostic #include <sys/stat.h> 1737660Sbostic #include <sys/time.h> 1850596Sbostic #include <fcntl.h> 1950596Sbostic #include <time.h> 2037660Sbostic #include <tzfile.h> 2150613Sbostic #include <db.h> 22*69101Sbostic #include <err.h> 2350596Sbostic #include <pwd.h> 2450596Sbostic #include <utmp.h> 2550613Sbostic #include <errno.h> 2650596Sbostic #include <unistd.h> 2737660Sbostic #include <stdio.h> 2838901Sbostic #include <ctype.h> 2950596Sbostic #include <string.h> 3043857Sbostic #include <paths.h> 3137660Sbostic #include "finger.h" 3237660Sbostic 3337660Sbostic #define LINE_LEN 80 3437660Sbostic #define TAB_LEN 8 /* 8 spaces between tabs */ 3550595Sbostic #define _PATH_FORWARD ".forward" 3637660Sbostic #define _PATH_PLAN ".plan" 3737660Sbostic #define _PATH_PROJECT ".project" 3837660Sbostic 3950596Sbostic static int demi_print __P((char *, int)); 4050596Sbostic static void lprint __P((PERSON *)); 4150596Sbostic static int show_text __P((char *, char *, char *)); 4250596Sbostic static void vputc __P((int)); 4350596Sbostic 4450596Sbostic void 4537660Sbostic lflag_print() 4637660Sbostic { 4737660Sbostic extern int pplan; 4837660Sbostic register PERSON *pn; 4950613Sbostic register int sflag, r; 50*69101Sbostic PERSON *tmp; 5150613Sbostic DBT data, key; 5237660Sbostic 5350613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) { 5450613Sbostic r = (*db->seq)(db, &key, &data, sflag); 5550613Sbostic if (r == -1) 56*69101Sbostic err(1, "db seq"); 5750613Sbostic if (r == 1) 5850613Sbostic break; 59*69101Sbostic memcpy(&tmp, data.data, sizeof tmp); 60*69101Sbostic pn = tmp; 6150613Sbostic if (sflag != R_FIRST) 6250613Sbostic putchar('\n'); 6337660Sbostic lprint(pn); 6437660Sbostic if (!pplan) { 6550595Sbostic (void)show_text(pn->dir, 6650595Sbostic _PATH_FORWARD, "Mail forwarded to"); 6750595Sbostic (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 6850595Sbostic if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 6937660Sbostic (void)printf("No Plan.\n"); 7037660Sbostic } 7137660Sbostic } 7237660Sbostic } 7337660Sbostic 7450596Sbostic static void 7537660Sbostic lprint(pn) 7637660Sbostic register PERSON *pn; 7737660Sbostic { 7837660Sbostic extern time_t now; 7937660Sbostic register struct tm *delta; 8037664Sedward register WHERE *w; 8137660Sbostic register int cpr, len, maxlen; 8242919Sbostic struct tm *tp; 8337660Sbostic int oddfield; 8450596Sbostic char *t, *tzn; 8537660Sbostic 8637660Sbostic /* 8737660Sbostic * long format -- 8837660Sbostic * login name 8937660Sbostic * real name 9037660Sbostic * home directory 9137660Sbostic * shell 9237660Sbostic * office, office phone, home phone if available 9337660Sbostic */ 9437660Sbostic (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", 9537660Sbostic pn->name, pn->realname, pn->dir); 9637660Sbostic (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); 9737660Sbostic 9837660Sbostic /* 9937660Sbostic * try and print office, office phone, and home phone on one line; 10037660Sbostic * if that fails, do line filling so it looks nice. 10137660Sbostic */ 10237660Sbostic #define OFFICE_TAG "Office" 10337660Sbostic #define OFFICE_PHONE_TAG "Office Phone" 10437660Sbostic oddfield = 0; 10537660Sbostic if (pn->office && pn->officephone && 10637660Sbostic strlen(pn->office) + strlen(pn->officephone) + 10737660Sbostic sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { 10850595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", 10950595Sbostic OFFICE_TAG, pn->office, prphone(pn->officephone)); 11037660Sbostic oddfield = demi_print(tbuf, oddfield); 11137660Sbostic } else { 11237660Sbostic if (pn->office) { 11350595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 11450595Sbostic OFFICE_TAG, pn->office); 11537660Sbostic oddfield = demi_print(tbuf, oddfield); 11637660Sbostic } 11737660Sbostic if (pn->officephone) { 11850595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 11950595Sbostic OFFICE_PHONE_TAG, prphone(pn->officephone)); 12037660Sbostic oddfield = demi_print(tbuf, oddfield); 12137660Sbostic } 12237660Sbostic } 12337660Sbostic if (pn->homephone) { 12450595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", 12538052Sbostic prphone(pn->homephone)); 12637660Sbostic oddfield = demi_print(tbuf, oddfield); 12737660Sbostic } 12837660Sbostic if (oddfield) 12937660Sbostic putchar('\n'); 13037660Sbostic 13137660Sbostic /* 13237664Sedward * long format con't: * if logged in 13337660Sbostic * terminal 13437660Sbostic * idle time 13537660Sbostic * if messages allowed 13637660Sbostic * where logged in from 13737664Sedward * if not logged in 13837664Sedward * when last logged in 13937660Sbostic */ 14037664Sedward /* find out longest device name for this user for formatting */ 14137775Sbostic for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) 14237664Sedward if ((len = strlen(w->tty)) > maxlen) 14337664Sedward maxlen = len; 14437664Sedward /* find rest of entries for user */ 14537664Sedward for (w = pn->whead; w != NULL; w = w->next) { 14637664Sedward switch (w->info) { 14737664Sedward case LOGGEDIN: 14842919Sbostic tp = localtime(&w->loginat); 14942919Sbostic t = asctime(tp); 15042919Sbostic tzn = tp->tm_zone; 15145455Sbostic cpr = printf("On since %.16s (%s) on %s", 15242919Sbostic t, tzn, w->tty); 15337660Sbostic /* 15437660Sbostic * idle time is tough; if have one, print a comma, 15537660Sbostic * then spaces to pad out the device name, then the 15637660Sbostic * idle time. Follow with a comma if a remote login. 15737660Sbostic */ 15837664Sedward delta = gmtime(&w->idletime); 15937660Sbostic if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 16037660Sbostic cpr += printf("%-*s idle ", 16137664Sedward maxlen - strlen(w->tty) + 1, ","); 16237660Sbostic if (delta->tm_yday > 0) { 16337660Sbostic cpr += printf("%d day%s ", 16437660Sbostic delta->tm_yday, 16537660Sbostic delta->tm_yday == 1 ? "" : "s"); 16637660Sbostic } 16737660Sbostic cpr += printf("%d:%02d", 16837660Sbostic delta->tm_hour, delta->tm_min); 16937664Sedward if (*w->host) { 17037660Sbostic putchar(','); 17137660Sbostic ++cpr; 17237660Sbostic } 17337660Sbostic } 17437664Sedward if (!w->writable) 17537660Sbostic cpr += printf(" (messages off)"); 17637664Sedward break; 17737664Sedward case LASTLOG: 17837664Sedward if (w->loginat == 0) { 17937664Sedward (void)printf("Never logged in."); 18037664Sedward break; 18137660Sbostic } 18242919Sbostic tp = localtime(&w->loginat); 18342919Sbostic t = asctime(tp); 18442919Sbostic tzn = tp->tm_zone; 18537664Sedward if (now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2) 18645455Sbostic cpr = 18745455Sbostic printf("Last login %.16s %.4s (%s) on %s", 18842919Sbostic t, t + 20, tzn, w->tty); 18937664Sedward else 19045455Sbostic cpr = printf("Last login %.16s (%s) on %s", 19142919Sbostic t, tzn, w->tty); 19237664Sedward break; 19337660Sbostic } 19437664Sedward if (*w->host) { 19537664Sedward if (LINE_LEN < (cpr + 6 + strlen(w->host))) 19637660Sbostic (void)printf("\n "); 19737664Sedward (void)printf(" from %s", w->host); 19837660Sbostic } 19937660Sbostic putchar('\n'); 20037660Sbostic } 20137660Sbostic } 20237660Sbostic 20350596Sbostic static int 20437660Sbostic demi_print(str, oddfield) 20537660Sbostic char *str; 20637660Sbostic int oddfield; 20737660Sbostic { 20837660Sbostic static int lenlast; 20937660Sbostic int lenthis, maxlen; 21037660Sbostic 21137660Sbostic lenthis = strlen(str); 21237660Sbostic if (oddfield) { 21337660Sbostic /* 21437660Sbostic * We left off on an odd number of fields. If we haven't 21537660Sbostic * crossed the midpoint of the screen, and we have room for 21637660Sbostic * the next field, print it on the same line; otherwise, 21737660Sbostic * print it on a new line. 21837660Sbostic * 21937660Sbostic * Note: we insist on having the right hand fields start 22037660Sbostic * no less than 5 tabs out. 22137660Sbostic */ 22237660Sbostic maxlen = 5 * TAB_LEN; 22337660Sbostic if (maxlen < lenlast) 22437660Sbostic maxlen = lenlast; 22537660Sbostic if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 22637660Sbostic lenthis) <= LINE_LEN) { 22737660Sbostic while(lenlast < (4 * TAB_LEN)) { 22837660Sbostic putchar('\t'); 22937660Sbostic lenlast += TAB_LEN; 23037660Sbostic } 23137660Sbostic (void)printf("\t%s\n", str); /* force one tab */ 23237660Sbostic } else { 23337660Sbostic (void)printf("\n%s", str); /* go to next line */ 23437660Sbostic oddfield = !oddfield; /* this'll be undone below */ 23537660Sbostic } 23637660Sbostic } else 23737660Sbostic (void)printf("%s", str); 23837660Sbostic oddfield = !oddfield; /* toggle odd/even marker */ 23937660Sbostic lenlast = lenthis; 24037660Sbostic return(oddfield); 24137660Sbostic } 24237660Sbostic 24351422Sbostic static int 24437660Sbostic show_text(directory, file_name, header) 24537660Sbostic char *directory, *file_name, *header; 24637660Sbostic { 24750595Sbostic struct stat sb; 24839241Sedward register FILE *fp; 24950595Sbostic register int ch, cnt, lastc; 25050595Sbostic register char *p; 25150595Sbostic int fd, nr; 25237660Sbostic 25350595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); 25450595Sbostic if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || 25550595Sbostic sb.st_size == 0) 25637660Sbostic return(0); 25750595Sbostic 25850595Sbostic /* If short enough, and no newlines, show it on a single line.*/ 25950595Sbostic if (sb.st_size <= LINE_LEN - strlen(header) - 5) { 26050595Sbostic nr = read(fd, tbuf, sizeof(tbuf)); 26150595Sbostic if (nr <= 0) { 26250595Sbostic (void)close(fd); 26350595Sbostic return(0); 26450595Sbostic } 26550595Sbostic for (p = tbuf, cnt = nr; cnt--; ++p) 26650595Sbostic if (*p == '\n') 26750595Sbostic break; 26850595Sbostic if (cnt <= 1) { 26950595Sbostic (void)printf("%s: ", header); 27050595Sbostic for (p = tbuf, cnt = nr; cnt--; ++p) 27150595Sbostic vputc(lastc = *p); 27250595Sbostic if (lastc != '\n') 27350595Sbostic (void)putchar('\n'); 27450595Sbostic (void)close(fd); 27550595Sbostic return(1); 27650595Sbostic } 27750595Sbostic else 27850595Sbostic (void)lseek(fd, 0L, SEEK_SET); 27950595Sbostic } 28050595Sbostic if ((fp = fdopen(fd, "r")) == NULL) 28150595Sbostic return(0); 28250595Sbostic (void)printf("%s:\n", header); 28339241Sedward while ((ch = getc(fp)) != EOF) 28439241Sedward vputc(lastc = ch); 28539241Sedward if (lastc != '\n') 28638901Sbostic (void)putchar('\n'); 28739241Sedward (void)fclose(fp); 28837660Sbostic return(1); 28937660Sbostic } 29038901Sbostic 29150596Sbostic static void 29238901Sbostic vputc(ch) 29338901Sbostic register int ch; 29438901Sbostic { 29538901Sbostic int meta; 29638901Sbostic 29738901Sbostic if (!isascii(ch)) { 29838901Sbostic (void)putchar('M'); 29938901Sbostic (void)putchar('-'); 30038901Sbostic ch = toascii(ch); 30138901Sbostic meta = 1; 30238901Sbostic } else 30338901Sbostic meta = 0; 30438912Sbostic if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) 30538901Sbostic (void)putchar(ch); 30638901Sbostic else { 30738901Sbostic (void)putchar('^'); 30838901Sbostic (void)putchar(ch == '\177' ? '?' : ch | 0100); 30938901Sbostic } 31038901Sbostic } 311