lprint.c revision 23971
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 3823693Speterstatic char sccsid[] = "@(#)lprint.c 8.3 (Berkeley) 4/28/95"; 391590Srgrimes#endif /* not lint */ 401590Srgrimes 411590Srgrimes#include <sys/types.h> 421590Srgrimes#include <sys/stat.h> 431590Srgrimes#include <sys/time.h> 441590Srgrimes#include <fcntl.h> 451590Srgrimes#include <time.h> 461590Srgrimes#include <db.h> 4723693Speter#include <err.h> 481590Srgrimes#include <pwd.h> 491590Srgrimes#include <utmp.h> 501590Srgrimes#include <errno.h> 511590Srgrimes#include <unistd.h> 521590Srgrimes#include <stdio.h> 531590Srgrimes#include <ctype.h> 541590Srgrimes#include <string.h> 551590Srgrimes#include <paths.h> 561590Srgrimes#include "finger.h" 571590Srgrimes 581590Srgrimes#define LINE_LEN 80 591590Srgrimes#define TAB_LEN 8 /* 8 spaces between tabs */ 601590Srgrimes#define _PATH_FORWARD ".forward" 611590Srgrimes#define _PATH_PLAN ".plan" 621590Srgrimes#define _PATH_PROJECT ".project" 631590Srgrimes 641590Srgrimesstatic int demi_print __P((char *, int)); 651590Srgrimesstatic void lprint __P((PERSON *)); 661590Srgrimesstatic int show_text __P((char *, char *, char *)); 671590Srgrimesstatic void vputc __P((int)); 681590Srgrimes 691590Srgrimesvoid 701590Srgrimeslflag_print() 711590Srgrimes{ 721590Srgrimes extern int pplan; 731590Srgrimes register PERSON *pn; 741590Srgrimes register int sflag, r; 7523693Speter PERSON *tmp; 761590Srgrimes DBT data, key; 771590Srgrimes 781590Srgrimes for (sflag = R_FIRST;; sflag = R_NEXT) { 791590Srgrimes r = (*db->seq)(db, &key, &data, sflag); 801590Srgrimes if (r == -1) 8123693Speter err(1, "db seq"); 821590Srgrimes if (r == 1) 831590Srgrimes break; 8423693Speter memmove(&tmp, data.data, sizeof tmp); 8523693Speter pn = tmp; 861590Srgrimes if (sflag != R_FIRST) 871590Srgrimes putchar('\n'); 881590Srgrimes lprint(pn); 891590Srgrimes if (!pplan) { 901590Srgrimes (void)show_text(pn->dir, 911590Srgrimes _PATH_FORWARD, "Mail forwarded to"); 921590Srgrimes (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 931590Srgrimes if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 941590Srgrimes (void)printf("No Plan.\n"); 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) { 1741590Srgrimes switch (w->info) { 1751590Srgrimes case LOGGEDIN: 1761590Srgrimes tp = localtime(&w->loginat); 1779993Sache strftime(t, sizeof(t), "%c", tp); 1781590Srgrimes tzn = tp->tm_zone; 1791590Srgrimes cpr = printf("On since %.16s (%s) on %s", 1801590Srgrimes t, tzn, w->tty); 1811590Srgrimes /* 1821590Srgrimes * idle time is tough; if have one, print a comma, 1831590Srgrimes * then spaces to pad out the device name, then the 1841590Srgrimes * idle time. Follow with a comma if a remote login. 1851590Srgrimes */ 1861590Srgrimes delta = gmtime(&w->idletime); 1871590Srgrimes if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 1881590Srgrimes cpr += printf("%-*s idle ", 1891590Srgrimes maxlen - strlen(w->tty) + 1, ","); 1901590Srgrimes if (delta->tm_yday > 0) { 1911590Srgrimes cpr += printf("%d day%s ", 1921590Srgrimes delta->tm_yday, 1931590Srgrimes delta->tm_yday == 1 ? "" : "s"); 1941590Srgrimes } 1951590Srgrimes cpr += printf("%d:%02d", 1961590Srgrimes delta->tm_hour, delta->tm_min); 1971590Srgrimes if (*w->host) { 1981590Srgrimes putchar(','); 1991590Srgrimes ++cpr; 2001590Srgrimes } 2011590Srgrimes } 2021590Srgrimes if (!w->writable) 2031590Srgrimes cpr += printf(" (messages off)"); 2041590Srgrimes break; 2051590Srgrimes case LASTLOG: 2061590Srgrimes if (w->loginat == 0) { 2071590Srgrimes (void)printf("Never logged in."); 2081590Srgrimes break; 2091590Srgrimes } 2101590Srgrimes tp = localtime(&w->loginat); 2119993Sache strftime(t, sizeof(t), "%c", tp); 2121590Srgrimes tzn = tp->tm_zone; 2139987Swollman if (now - w->loginat > 86400 * 365 / 2) 2141590Srgrimes cpr = 2151590Srgrimes printf("Last login %.16s %.4s (%s) on %s", 2161590Srgrimes t, t + 20, tzn, w->tty); 2171590Srgrimes else 2181590Srgrimes cpr = printf("Last login %.16s (%s) on %s", 2191590Srgrimes t, tzn, w->tty); 2201590Srgrimes break; 2211590Srgrimes } 2221590Srgrimes if (*w->host) { 2231590Srgrimes if (LINE_LEN < (cpr + 6 + strlen(w->host))) 2241590Srgrimes (void)printf("\n "); 2251590Srgrimes (void)printf(" from %s", w->host); 2261590Srgrimes } 2271590Srgrimes putchar('\n'); 2281590Srgrimes } 2292537Spst if (pn->mailrecv == -1) 2302537Spst printf("No Mail.\n"); 2312537Spst else if (pn->mailrecv > pn->mailread) { 2322537Spst tp = localtime(&pn->mailrecv); 2339993Sache strftime(t, sizeof(t), "%c", tp); 2342537Spst tzn = tp->tm_zone; 2352537Spst printf("New mail received %.16s %.4s (%s)\n", t, t + 20, tzn); 2362537Spst tp = localtime(&pn->mailread); 2379993Sache strftime(t, sizeof(t), "%c", tp); 2382537Spst tzn = tp->tm_zone; 2392537Spst printf(" Unread since %.16s %.4s (%s)\n", t, t + 20, tzn); 2402537Spst } else { 2412537Spst tp = localtime(&pn->mailread); 2429993Sache strftime(t, sizeof(t), "%c", tp); 2432537Spst tzn = tp->tm_zone; 2442537Spst printf("Mail last read %.16s %.4s (%s)\n", t, t + 20, tzn); 2452537Spst } 2461590Srgrimes} 2471590Srgrimes 2481590Srgrimesstatic int 2491590Srgrimesdemi_print(str, oddfield) 2501590Srgrimes char *str; 2511590Srgrimes int oddfield; 2521590Srgrimes{ 2531590Srgrimes static int lenlast; 2541590Srgrimes int lenthis, maxlen; 2551590Srgrimes 2561590Srgrimes lenthis = strlen(str); 2571590Srgrimes if (oddfield) { 2581590Srgrimes /* 2591590Srgrimes * We left off on an odd number of fields. If we haven't 2601590Srgrimes * crossed the midpoint of the screen, and we have room for 2611590Srgrimes * the next field, print it on the same line; otherwise, 2621590Srgrimes * print it on a new line. 2631590Srgrimes * 2641590Srgrimes * Note: we insist on having the right hand fields start 2651590Srgrimes * no less than 5 tabs out. 2661590Srgrimes */ 2671590Srgrimes maxlen = 5 * TAB_LEN; 2681590Srgrimes if (maxlen < lenlast) 2691590Srgrimes maxlen = lenlast; 2701590Srgrimes if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 2711590Srgrimes lenthis) <= LINE_LEN) { 2721590Srgrimes while(lenlast < (4 * TAB_LEN)) { 2731590Srgrimes putchar('\t'); 2741590Srgrimes lenlast += TAB_LEN; 2751590Srgrimes } 2761590Srgrimes (void)printf("\t%s\n", str); /* force one tab */ 2771590Srgrimes } else { 2781590Srgrimes (void)printf("\n%s", str); /* go to next line */ 2791590Srgrimes oddfield = !oddfield; /* this'll be undone below */ 2801590Srgrimes } 2811590Srgrimes } else 2821590Srgrimes (void)printf("%s", str); 2831590Srgrimes oddfield = !oddfield; /* toggle odd/even marker */ 2841590Srgrimes lenlast = lenthis; 2851590Srgrimes return(oddfield); 2861590Srgrimes} 2871590Srgrimes 2881590Srgrimesstatic int 2891590Srgrimesshow_text(directory, file_name, header) 2901590Srgrimes char *directory, *file_name, *header; 2911590Srgrimes{ 2921590Srgrimes struct stat sb; 2931590Srgrimes register FILE *fp; 2941590Srgrimes register int ch, cnt, lastc; 2951590Srgrimes register char *p; 2961590Srgrimes int fd, nr; 2971590Srgrimes 2981590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); 2991590Srgrimes if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || 3001590Srgrimes sb.st_size == 0) 3011590Srgrimes return(0); 3021590Srgrimes 3031590Srgrimes /* If short enough, and no newlines, show it on a single line.*/ 3041590Srgrimes if (sb.st_size <= LINE_LEN - strlen(header) - 5) { 3051590Srgrimes nr = read(fd, tbuf, sizeof(tbuf)); 3061590Srgrimes if (nr <= 0) { 3071590Srgrimes (void)close(fd); 3081590Srgrimes return(0); 3091590Srgrimes } 3101590Srgrimes for (p = tbuf, cnt = nr; cnt--; ++p) 3111590Srgrimes if (*p == '\n') 3121590Srgrimes break; 3131590Srgrimes if (cnt <= 1) { 3141590Srgrimes (void)printf("%s: ", header); 3151590Srgrimes for (p = tbuf, cnt = nr; cnt--; ++p) 31623971Sache if (*p != '\r') 31723971Sache vputc(lastc = *p); 3181590Srgrimes if (lastc != '\n') 3191590Srgrimes (void)putchar('\n'); 3201590Srgrimes (void)close(fd); 3211590Srgrimes return(1); 3221590Srgrimes } 3231590Srgrimes else 3241590Srgrimes (void)lseek(fd, 0L, SEEK_SET); 3251590Srgrimes } 3261590Srgrimes if ((fp = fdopen(fd, "r")) == NULL) 3271590Srgrimes return(0); 3281590Srgrimes (void)printf("%s:\n", header); 3291590Srgrimes while ((ch = getc(fp)) != EOF) 33023971Sache if (ch != '\r') 33123971Sache vputc(lastc = ch); 3321590Srgrimes if (lastc != '\n') 3331590Srgrimes (void)putchar('\n'); 3341590Srgrimes (void)fclose(fp); 3351590Srgrimes return(1); 3361590Srgrimes} 3371590Srgrimes 3381590Srgrimesstatic void 3391590Srgrimesvputc(ch) 3401590Srgrimes register int ch; 3411590Srgrimes{ 3421590Srgrimes int meta; 3431590Srgrimes 3449994Sache if (!isprint(ch) && !isascii(ch)) { 3451590Srgrimes (void)putchar('M'); 3461590Srgrimes (void)putchar('-'); 3471590Srgrimes ch = toascii(ch); 3481590Srgrimes meta = 1; 3491590Srgrimes } else 3501590Srgrimes meta = 0; 3511590Srgrimes if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) 3521590Srgrimes (void)putchar(ch); 3531590Srgrimes else { 3541590Srgrimes (void)putchar('^'); 3551590Srgrimes (void)putchar(ch == '\177' ? '?' : ch | 0100); 3561590Srgrimes } 3571590Srgrimes} 358