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*50613Sbostic static char sccsid[] = "@(#)lprint.c 5.16 (Berkeley) 07/27/91"; 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> 21*50613Sbostic #include <db.h> 2250596Sbostic #include <pwd.h> 2350596Sbostic #include <utmp.h> 24*50613Sbostic #include <errno.h> 2550596Sbostic #include <unistd.h> 2637660Sbostic #include <stdio.h> 2738901Sbostic #include <ctype.h> 2850596Sbostic #include <string.h> 2943857Sbostic #include <paths.h> 3037660Sbostic #include "finger.h" 3137660Sbostic 3237660Sbostic #define LINE_LEN 80 3337660Sbostic #define TAB_LEN 8 /* 8 spaces between tabs */ 3450595Sbostic #define _PATH_FORWARD ".forward" 3537660Sbostic #define _PATH_PLAN ".plan" 3637660Sbostic #define _PATH_PROJECT ".project" 3737660Sbostic 3850596Sbostic static int demi_print __P((char *, int)); 3950596Sbostic static void lprint __P((PERSON *)); 4050596Sbostic static int show_text __P((char *, char *, char *)); 4150596Sbostic static void vputc __P((int)); 4250596Sbostic 4350596Sbostic void 4437660Sbostic lflag_print() 4537660Sbostic { 4637660Sbostic extern int pplan; 4737660Sbostic register PERSON *pn; 48*50613Sbostic register int sflag, r; 49*50613Sbostic DBT data, key; 5037660Sbostic 51*50613Sbostic for (sflag = R_FIRST;; sflag = R_NEXT) { 52*50613Sbostic r = (*db->seq)(db, &key, &data, sflag); 53*50613Sbostic if (r == -1) 54*50613Sbostic err("db seq: %s", strerror(errno)); 55*50613Sbostic if (r == 1) 56*50613Sbostic break; 57*50613Sbostic pn = *(PERSON **)data.data; 58*50613Sbostic if (sflag != R_FIRST) 59*50613Sbostic putchar('\n'); 6037660Sbostic lprint(pn); 6137660Sbostic if (!pplan) { 6250595Sbostic (void)show_text(pn->dir, 6350595Sbostic _PATH_FORWARD, "Mail forwarded to"); 6450595Sbostic (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 6550595Sbostic if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 6637660Sbostic (void)printf("No Plan.\n"); 6737660Sbostic } 6837660Sbostic } 6937660Sbostic } 7037660Sbostic 7150596Sbostic static void 7237660Sbostic lprint(pn) 7337660Sbostic register PERSON *pn; 7437660Sbostic { 7537660Sbostic extern time_t now; 7637660Sbostic register struct tm *delta; 7737664Sedward register WHERE *w; 7837660Sbostic register int cpr, len, maxlen; 7942919Sbostic struct tm *tp; 8037660Sbostic int oddfield; 8150596Sbostic char *t, *tzn; 8237660Sbostic 8337660Sbostic /* 8437660Sbostic * long format -- 8537660Sbostic * login name 8637660Sbostic * real name 8737660Sbostic * home directory 8837660Sbostic * shell 8937660Sbostic * office, office phone, home phone if available 9037660Sbostic */ 9137660Sbostic (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", 9237660Sbostic pn->name, pn->realname, pn->dir); 9337660Sbostic (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); 9437660Sbostic 9537660Sbostic /* 9637660Sbostic * try and print office, office phone, and home phone on one line; 9737660Sbostic * if that fails, do line filling so it looks nice. 9837660Sbostic */ 9937660Sbostic #define OFFICE_TAG "Office" 10037660Sbostic #define OFFICE_PHONE_TAG "Office Phone" 10137660Sbostic oddfield = 0; 10237660Sbostic if (pn->office && pn->officephone && 10337660Sbostic strlen(pn->office) + strlen(pn->officephone) + 10437660Sbostic sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { 10550595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", 10650595Sbostic OFFICE_TAG, pn->office, prphone(pn->officephone)); 10737660Sbostic oddfield = demi_print(tbuf, oddfield); 10837660Sbostic } else { 10937660Sbostic if (pn->office) { 11050595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 11150595Sbostic OFFICE_TAG, pn->office); 11237660Sbostic oddfield = demi_print(tbuf, oddfield); 11337660Sbostic } 11437660Sbostic if (pn->officephone) { 11550595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 11650595Sbostic OFFICE_PHONE_TAG, prphone(pn->officephone)); 11737660Sbostic oddfield = demi_print(tbuf, oddfield); 11837660Sbostic } 11937660Sbostic } 12037660Sbostic if (pn->homephone) { 12150595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", 12238052Sbostic prphone(pn->homephone)); 12337660Sbostic oddfield = demi_print(tbuf, oddfield); 12437660Sbostic } 12537660Sbostic if (oddfield) 12637660Sbostic putchar('\n'); 12737660Sbostic 12837660Sbostic /* 12937664Sedward * long format con't: * if logged in 13037660Sbostic * terminal 13137660Sbostic * idle time 13237660Sbostic * if messages allowed 13337660Sbostic * where logged in from 13437664Sedward * if not logged in 13537664Sedward * when last logged in 13637660Sbostic */ 13737664Sedward /* find out longest device name for this user for formatting */ 13837775Sbostic for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) 13937664Sedward if ((len = strlen(w->tty)) > maxlen) 14037664Sedward maxlen = len; 14137664Sedward /* find rest of entries for user */ 14237664Sedward for (w = pn->whead; w != NULL; w = w->next) { 14337664Sedward switch (w->info) { 14437664Sedward case LOGGEDIN: 14542919Sbostic tp = localtime(&w->loginat); 14642919Sbostic t = asctime(tp); 14742919Sbostic tzn = tp->tm_zone; 14845455Sbostic cpr = printf("On since %.16s (%s) on %s", 14942919Sbostic t, tzn, w->tty); 15037660Sbostic /* 15137660Sbostic * idle time is tough; if have one, print a comma, 15237660Sbostic * then spaces to pad out the device name, then the 15337660Sbostic * idle time. Follow with a comma if a remote login. 15437660Sbostic */ 15537664Sedward delta = gmtime(&w->idletime); 15637660Sbostic if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 15737660Sbostic cpr += printf("%-*s idle ", 15837664Sedward maxlen - strlen(w->tty) + 1, ","); 15937660Sbostic if (delta->tm_yday > 0) { 16037660Sbostic cpr += printf("%d day%s ", 16137660Sbostic delta->tm_yday, 16237660Sbostic delta->tm_yday == 1 ? "" : "s"); 16337660Sbostic } 16437660Sbostic cpr += printf("%d:%02d", 16537660Sbostic delta->tm_hour, delta->tm_min); 16637664Sedward if (*w->host) { 16737660Sbostic putchar(','); 16837660Sbostic ++cpr; 16937660Sbostic } 17037660Sbostic } 17137664Sedward if (!w->writable) 17237660Sbostic cpr += printf(" (messages off)"); 17337664Sedward break; 17437664Sedward case LASTLOG: 17537664Sedward if (w->loginat == 0) { 17637664Sedward (void)printf("Never logged in."); 17737664Sedward break; 17837660Sbostic } 17942919Sbostic tp = localtime(&w->loginat); 18042919Sbostic t = asctime(tp); 18142919Sbostic tzn = tp->tm_zone; 18237664Sedward if (now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2) 18345455Sbostic cpr = 18445455Sbostic printf("Last login %.16s %.4s (%s) on %s", 18542919Sbostic t, t + 20, tzn, w->tty); 18637664Sedward else 18745455Sbostic cpr = printf("Last login %.16s (%s) on %s", 18842919Sbostic t, tzn, w->tty); 18937664Sedward break; 19037660Sbostic } 19137664Sedward if (*w->host) { 19237664Sedward if (LINE_LEN < (cpr + 6 + strlen(w->host))) 19337660Sbostic (void)printf("\n "); 19437664Sedward (void)printf(" from %s", w->host); 19537660Sbostic } 19637660Sbostic putchar('\n'); 19737660Sbostic } 19837660Sbostic } 19937660Sbostic 20050596Sbostic static int 20137660Sbostic demi_print(str, oddfield) 20237660Sbostic char *str; 20337660Sbostic int oddfield; 20437660Sbostic { 20537660Sbostic static int lenlast; 20637660Sbostic int lenthis, maxlen; 20737660Sbostic 20837660Sbostic lenthis = strlen(str); 20937660Sbostic if (oddfield) { 21037660Sbostic /* 21137660Sbostic * We left off on an odd number of fields. If we haven't 21237660Sbostic * crossed the midpoint of the screen, and we have room for 21337660Sbostic * the next field, print it on the same line; otherwise, 21437660Sbostic * print it on a new line. 21537660Sbostic * 21637660Sbostic * Note: we insist on having the right hand fields start 21737660Sbostic * no less than 5 tabs out. 21837660Sbostic */ 21937660Sbostic maxlen = 5 * TAB_LEN; 22037660Sbostic if (maxlen < lenlast) 22137660Sbostic maxlen = lenlast; 22237660Sbostic if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 22337660Sbostic lenthis) <= LINE_LEN) { 22437660Sbostic while(lenlast < (4 * TAB_LEN)) { 22537660Sbostic putchar('\t'); 22637660Sbostic lenlast += TAB_LEN; 22737660Sbostic } 22837660Sbostic (void)printf("\t%s\n", str); /* force one tab */ 22937660Sbostic } else { 23037660Sbostic (void)printf("\n%s", str); /* go to next line */ 23137660Sbostic oddfield = !oddfield; /* this'll be undone below */ 23237660Sbostic } 23337660Sbostic } else 23437660Sbostic (void)printf("%s", str); 23537660Sbostic oddfield = !oddfield; /* toggle odd/even marker */ 23637660Sbostic lenlast = lenthis; 23737660Sbostic return(oddfield); 23837660Sbostic } 23937660Sbostic 24050596Sbostic static 24137660Sbostic show_text(directory, file_name, header) 24237660Sbostic char *directory, *file_name, *header; 24337660Sbostic { 24450595Sbostic struct stat sb; 24539241Sedward register FILE *fp; 24650595Sbostic register int ch, cnt, lastc; 24750595Sbostic register char *p; 24850595Sbostic int fd, nr; 24937660Sbostic 25050595Sbostic (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); 25150595Sbostic if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || 25250595Sbostic sb.st_size == 0) 25337660Sbostic return(0); 25450595Sbostic 25550595Sbostic /* If short enough, and no newlines, show it on a single line.*/ 25650595Sbostic if (sb.st_size <= LINE_LEN - strlen(header) - 5) { 25750595Sbostic nr = read(fd, tbuf, sizeof(tbuf)); 25850595Sbostic if (nr <= 0) { 25950595Sbostic (void)close(fd); 26050595Sbostic return(0); 26150595Sbostic } 26250595Sbostic for (p = tbuf, cnt = nr; cnt--; ++p) 26350595Sbostic if (*p == '\n') 26450595Sbostic break; 26550595Sbostic if (cnt <= 1) { 26650595Sbostic (void)printf("%s: ", header); 26750595Sbostic for (p = tbuf, cnt = nr; cnt--; ++p) 26850595Sbostic vputc(lastc = *p); 26950595Sbostic if (lastc != '\n') 27050595Sbostic (void)putchar('\n'); 27150595Sbostic (void)close(fd); 27250595Sbostic return(1); 27350595Sbostic } 27450595Sbostic else 27550595Sbostic (void)lseek(fd, 0L, SEEK_SET); 27650595Sbostic } 27750595Sbostic if ((fp = fdopen(fd, "r")) == NULL) 27850595Sbostic return(0); 27950595Sbostic (void)printf("%s:\n", header); 28039241Sedward while ((ch = getc(fp)) != EOF) 28139241Sedward vputc(lastc = ch); 28239241Sedward if (lastc != '\n') 28338901Sbostic (void)putchar('\n'); 28439241Sedward (void)fclose(fp); 28537660Sbostic return(1); 28637660Sbostic } 28738901Sbostic 28850596Sbostic static void 28938901Sbostic vputc(ch) 29038901Sbostic register int ch; 29138901Sbostic { 29238901Sbostic int meta; 29338901Sbostic 29438901Sbostic if (!isascii(ch)) { 29538901Sbostic (void)putchar('M'); 29638901Sbostic (void)putchar('-'); 29738901Sbostic ch = toascii(ch); 29838901Sbostic meta = 1; 29938901Sbostic } else 30038901Sbostic meta = 0; 30138912Sbostic if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) 30238901Sbostic (void)putchar(ch); 30338901Sbostic else { 30438901Sbostic (void)putchar('^'); 30538901Sbostic (void)putchar(ch == '\177' ? '?' : ch | 0100); 30638901Sbostic } 30738901Sbostic } 308