lprint.c revision 72109
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1989, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 3. All advertising materials mentioning features or use of this software 171590Srgrimes * must display the following acknowledgement: 181590Srgrimes * This product includes software developed by the University of 191590Srgrimes * California, Berkeley and its contributors. 201590Srgrimes * 4. Neither the name of the University nor the names of its contributors 211590Srgrimes * may be used to endorse or promote products derived from this software 221590Srgrimes * without specific prior written permission. 231590Srgrimes * 241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341590Srgrimes * SUCH DAMAGE. 351590Srgrimes */ 361590Srgrimes 371590Srgrimes#ifndef lint 3827169Scharnier#if 0 3923693Speterstatic char sccsid[] = "@(#)lprint.c 8.3 (Berkeley) 4/28/95"; 4072109Scharnier#endif 4127169Scharnierstatic const char rcsid[] = 4250477Speter "$FreeBSD: head/usr.bin/finger/lprint.c 72109 2001-02-06 20:13:48Z charnier $"; 431590Srgrimes#endif /* not lint */ 441590Srgrimes 451590Srgrimes#include <sys/stat.h> 4672109Scharnier#include <ctype.h> 471590Srgrimes#include <db.h> 4823693Speter#include <err.h> 4972109Scharnier#include <fcntl.h> 5072109Scharnier#include <paths.h> 511590Srgrimes#include <pwd.h> 521590Srgrimes#include <stdio.h> 531590Srgrimes#include <string.h> 5472109Scharnier#include <unistd.h> 5572109Scharnier#include <utmp.h> 561590Srgrimes#include "finger.h" 5765064Sbrian#include "pathnames.h" 5865064Sbrian#include "extern.h" 591590Srgrimes 601590Srgrimes#define LINE_LEN 80 611590Srgrimes#define TAB_LEN 8 /* 8 spaces between tabs */ 621590Srgrimes 631590Srgrimesstatic int demi_print __P((char *, int)); 641590Srgrimesstatic void lprint __P((PERSON *)); 6538164Sachestatic void vputc __P((unsigned char)); 661590Srgrimes 671590Srgrimesvoid 681590Srgrimeslflag_print() 691590Srgrimes{ 701590Srgrimes extern int pplan; 711590Srgrimes register PERSON *pn; 721590Srgrimes register int sflag, r; 7323693Speter PERSON *tmp; 741590Srgrimes DBT data, key; 751590Srgrimes 761590Srgrimes for (sflag = R_FIRST;; sflag = R_NEXT) { 771590Srgrimes r = (*db->seq)(db, &key, &data, sflag); 781590Srgrimes if (r == -1) 7923693Speter err(1, "db seq"); 801590Srgrimes if (r == 1) 811590Srgrimes break; 8223693Speter memmove(&tmp, data.data, sizeof tmp); 8323693Speter pn = tmp; 841590Srgrimes if (sflag != R_FIRST) 851590Srgrimes putchar('\n'); 861590Srgrimes lprint(pn); 871590Srgrimes if (!pplan) { 881590Srgrimes (void)show_text(pn->dir, 891590Srgrimes _PATH_FORWARD, "Mail forwarded to"); 901590Srgrimes (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 911590Srgrimes if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 921590Srgrimes (void)printf("No Plan.\n"); 9370474Sdes (void)show_text(pn->dir, 9470655Sdes _PATH_PUBKEY, "Public key"); 951590Srgrimes } 961590Srgrimes } 971590Srgrimes} 981590Srgrimes 991590Srgrimesstatic void 1001590Srgrimeslprint(pn) 1011590Srgrimes register PERSON *pn; 1021590Srgrimes{ 1031590Srgrimes extern time_t now; 1041590Srgrimes register struct tm *delta; 1051590Srgrimes register WHERE *w; 1061590Srgrimes register int cpr, len, maxlen; 1071590Srgrimes struct tm *tp; 1081590Srgrimes int oddfield; 1099993Sache char *tzn; 1109993Sache char t[80]; 1111590Srgrimes 1121590Srgrimes /* 1131590Srgrimes * long format -- 1141590Srgrimes * login name 1151590Srgrimes * real name 1161590Srgrimes * home directory 1171590Srgrimes * shell 1181590Srgrimes * office, office phone, home phone if available 1192537Spst * mail status 1201590Srgrimes */ 1211590Srgrimes (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", 1221590Srgrimes pn->name, pn->realname, pn->dir); 1231590Srgrimes (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); 1241590Srgrimes 1251590Srgrimes /* 1261590Srgrimes * try and print office, office phone, and home phone on one line; 1271590Srgrimes * if that fails, do line filling so it looks nice. 1281590Srgrimes */ 1291590Srgrimes#define OFFICE_TAG "Office" 1301590Srgrimes#define OFFICE_PHONE_TAG "Office Phone" 1311590Srgrimes oddfield = 0; 1321590Srgrimes if (pn->office && pn->officephone && 1331590Srgrimes strlen(pn->office) + strlen(pn->officephone) + 1341590Srgrimes sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { 1351590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", 1361590Srgrimes OFFICE_TAG, pn->office, prphone(pn->officephone)); 1371590Srgrimes oddfield = demi_print(tbuf, oddfield); 1381590Srgrimes } else { 1391590Srgrimes if (pn->office) { 1401590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 1411590Srgrimes OFFICE_TAG, pn->office); 1421590Srgrimes oddfield = demi_print(tbuf, oddfield); 1431590Srgrimes } 1441590Srgrimes if (pn->officephone) { 1451590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 1461590Srgrimes OFFICE_PHONE_TAG, prphone(pn->officephone)); 1471590Srgrimes oddfield = demi_print(tbuf, oddfield); 1481590Srgrimes } 1491590Srgrimes } 1501590Srgrimes if (pn->homephone) { 1511590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", 1521590Srgrimes prphone(pn->homephone)); 1531590Srgrimes oddfield = demi_print(tbuf, oddfield); 1541590Srgrimes } 1551590Srgrimes if (oddfield) 1561590Srgrimes putchar('\n'); 1571590Srgrimes 1581590Srgrimes /* 1592537Spst * long format con't: 1602537Spst * if logged in 1611590Srgrimes * terminal 1621590Srgrimes * idle time 1631590Srgrimes * if messages allowed 1641590Srgrimes * where logged in from 1651590Srgrimes * if not logged in 1661590Srgrimes * when last logged in 1671590Srgrimes */ 1681590Srgrimes /* find out longest device name for this user for formatting */ 1691590Srgrimes for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) 1701590Srgrimes if ((len = strlen(w->tty)) > maxlen) 1711590Srgrimes maxlen = len; 1721590Srgrimes /* find rest of entries for user */ 1731590Srgrimes for (w = pn->whead; w != NULL; w = w->next) { 17467467Sru if (w->info == LOGGEDIN) { 1751590Srgrimes tp = localtime(&w->loginat); 1769993Sache strftime(t, sizeof(t), "%c", tp); 1771590Srgrimes tzn = tp->tm_zone; 1781590Srgrimes cpr = printf("On since %.16s (%s) on %s", 1791590Srgrimes t, tzn, w->tty); 1801590Srgrimes /* 1811590Srgrimes * idle time is tough; if have one, print a comma, 1821590Srgrimes * then spaces to pad out the device name, then the 1831590Srgrimes * idle time. Follow with a comma if a remote login. 1841590Srgrimes */ 1851590Srgrimes delta = gmtime(&w->idletime); 1861590Srgrimes if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 1871590Srgrimes cpr += printf("%-*s idle ", 1881590Srgrimes maxlen - strlen(w->tty) + 1, ","); 1891590Srgrimes if (delta->tm_yday > 0) { 1901590Srgrimes cpr += printf("%d day%s ", 1911590Srgrimes delta->tm_yday, 1921590Srgrimes delta->tm_yday == 1 ? "" : "s"); 1931590Srgrimes } 1941590Srgrimes cpr += printf("%d:%02d", 1951590Srgrimes delta->tm_hour, delta->tm_min); 1961590Srgrimes if (*w->host) { 1971590Srgrimes putchar(','); 1981590Srgrimes ++cpr; 1991590Srgrimes } 2001590Srgrimes } 2011590Srgrimes if (!w->writable) 2021590Srgrimes cpr += printf(" (messages off)"); 20367467Sru } else if (w->loginat == 0) { 20467467Sru cpr = printf("Never logged in."); 20567467Sru } else { 2061590Srgrimes tp = localtime(&w->loginat); 2079993Sache strftime(t, sizeof(t), "%c", tp); 2081590Srgrimes tzn = tp->tm_zone; 2099987Swollman if (now - w->loginat > 86400 * 365 / 2) 2101590Srgrimes cpr = 2111590Srgrimes printf("Last login %.16s %.4s (%s) on %s", 2121590Srgrimes t, t + 20, tzn, w->tty); 2131590Srgrimes else 2141590Srgrimes cpr = printf("Last login %.16s (%s) on %s", 2151590Srgrimes t, tzn, w->tty); 2161590Srgrimes } 2171590Srgrimes if (*w->host) { 2181590Srgrimes if (LINE_LEN < (cpr + 6 + strlen(w->host))) 2191590Srgrimes (void)printf("\n "); 2201590Srgrimes (void)printf(" from %s", w->host); 2211590Srgrimes } 2221590Srgrimes putchar('\n'); 2231590Srgrimes } 2242537Spst if (pn->mailrecv == -1) 2252537Spst printf("No Mail.\n"); 2262537Spst else if (pn->mailrecv > pn->mailread) { 2272537Spst tp = localtime(&pn->mailrecv); 2289993Sache strftime(t, sizeof(t), "%c", tp); 2292537Spst tzn = tp->tm_zone; 2302537Spst printf("New mail received %.16s %.4s (%s)\n", t, t + 20, tzn); 2312537Spst tp = localtime(&pn->mailread); 2329993Sache strftime(t, sizeof(t), "%c", tp); 2332537Spst tzn = tp->tm_zone; 2342537Spst printf(" Unread since %.16s %.4s (%s)\n", t, t + 20, tzn); 2352537Spst } else { 2362537Spst tp = localtime(&pn->mailread); 2379993Sache strftime(t, sizeof(t), "%c", tp); 2382537Spst tzn = tp->tm_zone; 2392537Spst printf("Mail last read %.16s %.4s (%s)\n", t, t + 20, tzn); 2402537Spst } 2411590Srgrimes} 2421590Srgrimes 2431590Srgrimesstatic int 2441590Srgrimesdemi_print(str, oddfield) 2451590Srgrimes char *str; 2461590Srgrimes int oddfield; 2471590Srgrimes{ 2481590Srgrimes static int lenlast; 2491590Srgrimes int lenthis, maxlen; 2501590Srgrimes 2511590Srgrimes lenthis = strlen(str); 2521590Srgrimes if (oddfield) { 2531590Srgrimes /* 2541590Srgrimes * We left off on an odd number of fields. If we haven't 2551590Srgrimes * crossed the midpoint of the screen, and we have room for 2561590Srgrimes * the next field, print it on the same line; otherwise, 2571590Srgrimes * print it on a new line. 2581590Srgrimes * 2591590Srgrimes * Note: we insist on having the right hand fields start 2601590Srgrimes * no less than 5 tabs out. 2611590Srgrimes */ 2621590Srgrimes maxlen = 5 * TAB_LEN; 2631590Srgrimes if (maxlen < lenlast) 2641590Srgrimes maxlen = lenlast; 2651590Srgrimes if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 2661590Srgrimes lenthis) <= LINE_LEN) { 2671590Srgrimes while(lenlast < (4 * TAB_LEN)) { 2681590Srgrimes putchar('\t'); 2691590Srgrimes lenlast += TAB_LEN; 2701590Srgrimes } 2711590Srgrimes (void)printf("\t%s\n", str); /* force one tab */ 2721590Srgrimes } else { 2731590Srgrimes (void)printf("\n%s", str); /* go to next line */ 2741590Srgrimes oddfield = !oddfield; /* this'll be undone below */ 2751590Srgrimes } 2761590Srgrimes } else 2771590Srgrimes (void)printf("%s", str); 2781590Srgrimes oddfield = !oddfield; /* toggle odd/even marker */ 2791590Srgrimes lenlast = lenthis; 2801590Srgrimes return(oddfield); 2811590Srgrimes} 2821590Srgrimes 28365064Sbrianint 2841590Srgrimesshow_text(directory, file_name, header) 2851590Srgrimes char *directory, *file_name, *header; 2861590Srgrimes{ 2871590Srgrimes struct stat sb; 2881590Srgrimes register FILE *fp; 28938164Sache register int ch, cnt; 29038164Sache register char *p, lastc; 2911590Srgrimes int fd, nr; 2921590Srgrimes 29367467Sru lastc = '\0'; 29467467Sru 2951590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); 2961590Srgrimes if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || 2971590Srgrimes sb.st_size == 0) 2981590Srgrimes return(0); 2991590Srgrimes 3001590Srgrimes /* If short enough, and no newlines, show it on a single line.*/ 3011590Srgrimes if (sb.st_size <= LINE_LEN - strlen(header) - 5) { 3021590Srgrimes nr = read(fd, tbuf, sizeof(tbuf)); 3031590Srgrimes if (nr <= 0) { 3041590Srgrimes (void)close(fd); 3051590Srgrimes return(0); 3061590Srgrimes } 3071590Srgrimes for (p = tbuf, cnt = nr; cnt--; ++p) 3081590Srgrimes if (*p == '\n') 3091590Srgrimes break; 3101590Srgrimes if (cnt <= 1) { 31165064Sbrian if (*header != '\0') 31265064Sbrian (void)printf("%s: ", header); 3131590Srgrimes for (p = tbuf, cnt = nr; cnt--; ++p) 31423971Sache if (*p != '\r') 31523971Sache vputc(lastc = *p); 3161590Srgrimes if (lastc != '\n') 3171590Srgrimes (void)putchar('\n'); 3181590Srgrimes (void)close(fd); 3191590Srgrimes return(1); 3201590Srgrimes } 3211590Srgrimes else 3221590Srgrimes (void)lseek(fd, 0L, SEEK_SET); 3231590Srgrimes } 3241590Srgrimes if ((fp = fdopen(fd, "r")) == NULL) 3251590Srgrimes return(0); 32665064Sbrian if (*header != '\0') 32765064Sbrian (void)printf("%s:\n", header); 3281590Srgrimes while ((ch = getc(fp)) != EOF) 32923971Sache if (ch != '\r') 33023971Sache vputc(lastc = ch); 3311590Srgrimes if (lastc != '\n') 3321590Srgrimes (void)putchar('\n'); 3331590Srgrimes (void)fclose(fp); 3341590Srgrimes return(1); 3351590Srgrimes} 3361590Srgrimes 3371590Srgrimesstatic void 3381590Srgrimesvputc(ch) 33938164Sache register unsigned char ch; 3401590Srgrimes{ 3411590Srgrimes int meta; 3421590Srgrimes 3439994Sache if (!isprint(ch) && !isascii(ch)) { 3441590Srgrimes (void)putchar('M'); 3451590Srgrimes (void)putchar('-'); 3461590Srgrimes ch = toascii(ch); 3471590Srgrimes meta = 1; 3481590Srgrimes } else 3491590Srgrimes meta = 0; 35067467Sru if (isprint(ch) || (!meta && (ch == ' ' || ch == '\t' || ch == '\n'))) 3511590Srgrimes (void)putchar(ch); 3521590Srgrimes else { 3531590Srgrimes (void)putchar('^'); 3541590Srgrimes (void)putchar(ch == '\177' ? '?' : ch | 0100); 3551590Srgrimes } 3561590Srgrimes} 357