lprint.c revision 9994
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 381590Srgrimesstatic char sccsid[] = "@(#)lprint.c 8.1 (Berkeley) 6/6/93"; 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> 471590Srgrimes#include <pwd.h> 481590Srgrimes#include <utmp.h> 491590Srgrimes#include <errno.h> 501590Srgrimes#include <unistd.h> 511590Srgrimes#include <stdio.h> 521590Srgrimes#include <ctype.h> 531590Srgrimes#include <string.h> 541590Srgrimes#include <paths.h> 551590Srgrimes#include "finger.h" 561590Srgrimes 571590Srgrimes#define LINE_LEN 80 581590Srgrimes#define TAB_LEN 8 /* 8 spaces between tabs */ 591590Srgrimes#define _PATH_FORWARD ".forward" 601590Srgrimes#define _PATH_PLAN ".plan" 611590Srgrimes#define _PATH_PROJECT ".project" 621590Srgrimes 631590Srgrimesstatic int demi_print __P((char *, int)); 641590Srgrimesstatic void lprint __P((PERSON *)); 651590Srgrimesstatic int show_text __P((char *, char *, char *)); 661590Srgrimesstatic void vputc __P((int)); 671590Srgrimes 681590Srgrimesvoid 691590Srgrimeslflag_print() 701590Srgrimes{ 711590Srgrimes extern int pplan; 721590Srgrimes register PERSON *pn; 731590Srgrimes register int sflag, r; 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) 791590Srgrimes err("db seq: %s", strerror(errno)); 801590Srgrimes if (r == 1) 811590Srgrimes break; 821590Srgrimes pn = *(PERSON **)data.data; 831590Srgrimes if (sflag != R_FIRST) 841590Srgrimes putchar('\n'); 851590Srgrimes lprint(pn); 861590Srgrimes if (!pplan) { 871590Srgrimes (void)show_text(pn->dir, 881590Srgrimes _PATH_FORWARD, "Mail forwarded to"); 891590Srgrimes (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 901590Srgrimes if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 911590Srgrimes (void)printf("No Plan.\n"); 921590Srgrimes } 931590Srgrimes } 941590Srgrimes} 951590Srgrimes 961590Srgrimesstatic void 971590Srgrimeslprint(pn) 981590Srgrimes register PERSON *pn; 991590Srgrimes{ 1001590Srgrimes extern time_t now; 1011590Srgrimes register struct tm *delta; 1021590Srgrimes register WHERE *w; 1031590Srgrimes register int cpr, len, maxlen; 1041590Srgrimes struct tm *tp; 1051590Srgrimes int oddfield; 1069993Sache char *tzn; 1079993Sache char t[80]; 1081590Srgrimes 1091590Srgrimes /* 1101590Srgrimes * long format -- 1111590Srgrimes * login name 1121590Srgrimes * real name 1131590Srgrimes * home directory 1141590Srgrimes * shell 1151590Srgrimes * office, office phone, home phone if available 1162537Spst * mail status 1171590Srgrimes */ 1181590Srgrimes (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", 1191590Srgrimes pn->name, pn->realname, pn->dir); 1201590Srgrimes (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); 1211590Srgrimes 1221590Srgrimes /* 1231590Srgrimes * try and print office, office phone, and home phone on one line; 1241590Srgrimes * if that fails, do line filling so it looks nice. 1251590Srgrimes */ 1261590Srgrimes#define OFFICE_TAG "Office" 1271590Srgrimes#define OFFICE_PHONE_TAG "Office Phone" 1281590Srgrimes oddfield = 0; 1291590Srgrimes if (pn->office && pn->officephone && 1301590Srgrimes strlen(pn->office) + strlen(pn->officephone) + 1311590Srgrimes sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { 1321590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", 1331590Srgrimes OFFICE_TAG, pn->office, prphone(pn->officephone)); 1341590Srgrimes oddfield = demi_print(tbuf, oddfield); 1351590Srgrimes } else { 1361590Srgrimes if (pn->office) { 1371590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 1381590Srgrimes OFFICE_TAG, pn->office); 1391590Srgrimes oddfield = demi_print(tbuf, oddfield); 1401590Srgrimes } 1411590Srgrimes if (pn->officephone) { 1421590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 1431590Srgrimes OFFICE_PHONE_TAG, prphone(pn->officephone)); 1441590Srgrimes oddfield = demi_print(tbuf, oddfield); 1451590Srgrimes } 1461590Srgrimes } 1471590Srgrimes if (pn->homephone) { 1481590Srgrimes (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", 1491590Srgrimes prphone(pn->homephone)); 1501590Srgrimes oddfield = demi_print(tbuf, oddfield); 1511590Srgrimes } 1521590Srgrimes if (oddfield) 1531590Srgrimes putchar('\n'); 1541590Srgrimes 1551590Srgrimes /* 1562537Spst * long format con't: 1572537Spst * if logged in 1581590Srgrimes * terminal 1591590Srgrimes * idle time 1601590Srgrimes * if messages allowed 1611590Srgrimes * where logged in from 1621590Srgrimes * if not logged in 1631590Srgrimes * when last logged in 1641590Srgrimes */ 1651590Srgrimes /* find out longest device name for this user for formatting */ 1661590Srgrimes for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) 1671590Srgrimes if ((len = strlen(w->tty)) > maxlen) 1681590Srgrimes maxlen = len; 1691590Srgrimes /* find rest of entries for user */ 1701590Srgrimes for (w = pn->whead; w != NULL; w = w->next) { 1711590Srgrimes switch (w->info) { 1721590Srgrimes case LOGGEDIN: 1731590Srgrimes tp = localtime(&w->loginat); 1749993Sache strftime(t, sizeof(t), "%c", tp); 1751590Srgrimes tzn = tp->tm_zone; 1761590Srgrimes cpr = printf("On since %.16s (%s) on %s", 1771590Srgrimes t, tzn, w->tty); 1781590Srgrimes /* 1791590Srgrimes * idle time is tough; if have one, print a comma, 1801590Srgrimes * then spaces to pad out the device name, then the 1811590Srgrimes * idle time. Follow with a comma if a remote login. 1821590Srgrimes */ 1831590Srgrimes delta = gmtime(&w->idletime); 1841590Srgrimes if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 1851590Srgrimes cpr += printf("%-*s idle ", 1861590Srgrimes maxlen - strlen(w->tty) + 1, ","); 1871590Srgrimes if (delta->tm_yday > 0) { 1881590Srgrimes cpr += printf("%d day%s ", 1891590Srgrimes delta->tm_yday, 1901590Srgrimes delta->tm_yday == 1 ? "" : "s"); 1911590Srgrimes } 1921590Srgrimes cpr += printf("%d:%02d", 1931590Srgrimes delta->tm_hour, delta->tm_min); 1941590Srgrimes if (*w->host) { 1951590Srgrimes putchar(','); 1961590Srgrimes ++cpr; 1971590Srgrimes } 1981590Srgrimes } 1991590Srgrimes if (!w->writable) 2001590Srgrimes cpr += printf(" (messages off)"); 2011590Srgrimes break; 2021590Srgrimes case LASTLOG: 2031590Srgrimes if (w->loginat == 0) { 2041590Srgrimes (void)printf("Never logged in."); 2051590Srgrimes break; 2061590Srgrimes } 2071590Srgrimes tp = localtime(&w->loginat); 2089993Sache strftime(t, sizeof(t), "%c", tp); 2091590Srgrimes tzn = tp->tm_zone; 2109987Swollman if (now - w->loginat > 86400 * 365 / 2) 2111590Srgrimes cpr = 2121590Srgrimes printf("Last login %.16s %.4s (%s) on %s", 2131590Srgrimes t, t + 20, tzn, w->tty); 2141590Srgrimes else 2151590Srgrimes cpr = printf("Last login %.16s (%s) on %s", 2161590Srgrimes t, tzn, w->tty); 2171590Srgrimes break; 2181590Srgrimes } 2191590Srgrimes if (*w->host) { 2201590Srgrimes if (LINE_LEN < (cpr + 6 + strlen(w->host))) 2211590Srgrimes (void)printf("\n "); 2221590Srgrimes (void)printf(" from %s", w->host); 2231590Srgrimes } 2241590Srgrimes putchar('\n'); 2251590Srgrimes } 2262537Spst if (pn->mailrecv == -1) 2272537Spst printf("No Mail.\n"); 2282537Spst else if (pn->mailrecv > pn->mailread) { 2292537Spst tp = localtime(&pn->mailrecv); 2309993Sache strftime(t, sizeof(t), "%c", tp); 2312537Spst tzn = tp->tm_zone; 2322537Spst printf("New mail received %.16s %.4s (%s)\n", t, t + 20, tzn); 2332537Spst tp = localtime(&pn->mailread); 2349993Sache strftime(t, sizeof(t), "%c", tp); 2352537Spst tzn = tp->tm_zone; 2362537Spst printf(" Unread since %.16s %.4s (%s)\n", t, t + 20, tzn); 2372537Spst } else { 2382537Spst tp = localtime(&pn->mailread); 2399993Sache strftime(t, sizeof(t), "%c", tp); 2402537Spst tzn = tp->tm_zone; 2412537Spst printf("Mail last read %.16s %.4s (%s)\n", t, t + 20, tzn); 2422537Spst } 2431590Srgrimes} 2441590Srgrimes 2451590Srgrimesstatic int 2461590Srgrimesdemi_print(str, oddfield) 2471590Srgrimes char *str; 2481590Srgrimes int oddfield; 2491590Srgrimes{ 2501590Srgrimes static int lenlast; 2511590Srgrimes int lenthis, maxlen; 2521590Srgrimes 2531590Srgrimes lenthis = strlen(str); 2541590Srgrimes if (oddfield) { 2551590Srgrimes /* 2561590Srgrimes * We left off on an odd number of fields. If we haven't 2571590Srgrimes * crossed the midpoint of the screen, and we have room for 2581590Srgrimes * the next field, print it on the same line; otherwise, 2591590Srgrimes * print it on a new line. 2601590Srgrimes * 2611590Srgrimes * Note: we insist on having the right hand fields start 2621590Srgrimes * no less than 5 tabs out. 2631590Srgrimes */ 2641590Srgrimes maxlen = 5 * TAB_LEN; 2651590Srgrimes if (maxlen < lenlast) 2661590Srgrimes maxlen = lenlast; 2671590Srgrimes if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 2681590Srgrimes lenthis) <= LINE_LEN) { 2691590Srgrimes while(lenlast < (4 * TAB_LEN)) { 2701590Srgrimes putchar('\t'); 2711590Srgrimes lenlast += TAB_LEN; 2721590Srgrimes } 2731590Srgrimes (void)printf("\t%s\n", str); /* force one tab */ 2741590Srgrimes } else { 2751590Srgrimes (void)printf("\n%s", str); /* go to next line */ 2761590Srgrimes oddfield = !oddfield; /* this'll be undone below */ 2771590Srgrimes } 2781590Srgrimes } else 2791590Srgrimes (void)printf("%s", str); 2801590Srgrimes oddfield = !oddfield; /* toggle odd/even marker */ 2811590Srgrimes lenlast = lenthis; 2821590Srgrimes return(oddfield); 2831590Srgrimes} 2841590Srgrimes 2851590Srgrimesstatic int 2861590Srgrimesshow_text(directory, file_name, header) 2871590Srgrimes char *directory, *file_name, *header; 2881590Srgrimes{ 2891590Srgrimes struct stat sb; 2901590Srgrimes register FILE *fp; 2911590Srgrimes register int ch, cnt, lastc; 2921590Srgrimes register char *p; 2931590Srgrimes int fd, nr; 2941590Srgrimes 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) { 3111590Srgrimes (void)printf("%s: ", header); 3121590Srgrimes for (p = tbuf, cnt = nr; cnt--; ++p) 3131590Srgrimes vputc(lastc = *p); 3141590Srgrimes if (lastc != '\n') 3151590Srgrimes (void)putchar('\n'); 3161590Srgrimes (void)close(fd); 3171590Srgrimes return(1); 3181590Srgrimes } 3191590Srgrimes else 3201590Srgrimes (void)lseek(fd, 0L, SEEK_SET); 3211590Srgrimes } 3221590Srgrimes if ((fp = fdopen(fd, "r")) == NULL) 3231590Srgrimes return(0); 3241590Srgrimes (void)printf("%s:\n", header); 3251590Srgrimes while ((ch = getc(fp)) != EOF) 3261590Srgrimes vputc(lastc = ch); 3271590Srgrimes if (lastc != '\n') 3281590Srgrimes (void)putchar('\n'); 3291590Srgrimes (void)fclose(fp); 3301590Srgrimes return(1); 3311590Srgrimes} 3321590Srgrimes 3331590Srgrimesstatic void 3341590Srgrimesvputc(ch) 3351590Srgrimes register int ch; 3361590Srgrimes{ 3371590Srgrimes int meta; 3381590Srgrimes 3399994Sache if (!isprint(ch) && !isascii(ch)) { 3401590Srgrimes (void)putchar('M'); 3411590Srgrimes (void)putchar('-'); 3421590Srgrimes ch = toascii(ch); 3431590Srgrimes meta = 1; 3441590Srgrimes } else 3451590Srgrimes meta = 0; 3461590Srgrimes if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) 3471590Srgrimes (void)putchar(ch); 3481590Srgrimes else { 3491590Srgrimes (void)putchar('^'); 3501590Srgrimes (void)putchar(ch == '\177' ? '?' : ch | 0100); 3511590Srgrimes } 3521590Srgrimes} 353