lprint.c revision 9994
197952Sdougb/* 297952Sdougb * Copyright (c) 1989, 1993 397952Sdougb * The Regents of the University of California. All rights reserved. 497952Sdougb * 597952Sdougb * This code is derived from software contributed to Berkeley by 697952Sdougb * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 797952Sdougb * 897952Sdougb * Redistribution and use in source and binary forms, with or without 997952Sdougb * modification, are permitted provided that the following conditions 1097952Sdougb * are met: 1197952Sdougb * 1. Redistributions of source code must retain the above copyright 1297952Sdougb * notice, this list of conditions and the following disclaimer. 1397952Sdougb * 2. Redistributions in binary form must reproduce the above copyright 1497952Sdougb * notice, this list of conditions and the following disclaimer in the 1597952Sdougb * documentation and/or other materials provided with the distribution. 1697952Sdougb * 3. All advertising materials mentioning features or use of this software 1797952Sdougb * must display the following acknowledgement: 1897952Sdougb * This product includes software developed by the University of 1997952Sdougb * California, Berkeley and its contributors. 2097952Sdougb * 4. Neither the name of the University nor the names of its contributors 2197952Sdougb * may be used to endorse or promote products derived from this software 2297952Sdougb * without specific prior written permission. 2397952Sdougb * 2497952Sdougb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2597952Sdougb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2697952Sdougb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2797952Sdougb * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2897952Sdougb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2997952Sdougb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30114924Sdougb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31101773Sdougb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3297952Sdougb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33218535Sdougb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34216343Sdougb * SUCH DAMAGE. 3597952Sdougb */ 36101773Sdougb 3797952Sdougb#ifndef lint 38101773Sdougbstatic char sccsid[] = "@(#)lprint.c 8.1 (Berkeley) 6/6/93"; 39101773Sdougb#endif /* not lint */ 40120836Sdougb 41120836Sdougb#include <sys/types.h> 42120836Sdougb#include <sys/stat.h> 43120836Sdougb#include <sys/time.h> 44120836Sdougb#include <fcntl.h> 45120836Sdougb#include <time.h> 46120836Sdougb#include <db.h> 47120836Sdougb#include <pwd.h> 48120836Sdougb#include <utmp.h> 49120836Sdougb#include <errno.h> 50188498Sed#include <unistd.h> 51101897Sdougb#include <stdio.h> 5297952Sdougb#include <ctype.h> 53101773Sdougb#include <string.h> 54101773Sdougb#include <paths.h> 5597952Sdougb#include "finger.h" 56216196Sdougb 57101773Sdougb#define LINE_LEN 80 58101897Sdougb#define TAB_LEN 8 /* 8 spaces between tabs */ 59188498Sed#define _PATH_FORWARD ".forward" 60101773Sdougb#define _PATH_PLAN ".plan" 6197952Sdougb#define _PATH_PROJECT ".project" 6297952Sdougb 63101773Sdougbstatic int demi_print __P((char *, int)); 64101773Sdougbstatic void lprint __P((PERSON *)); 65101773Sdougbstatic int show_text __P((char *, char *, char *)); 6697952Sdougbstatic void vputc __P((int)); 67120836Sdougb 68120836Sdougbvoid 69120836Sdougblflag_print() 70120836Sdougb{ 71120836Sdougb extern int pplan; 72120836Sdougb register PERSON *pn; 73120836Sdougb register int sflag, r; 74120836Sdougb DBT data, key; 75120836Sdougb 76120836Sdougb for (sflag = R_FIRST;; sflag = R_NEXT) { 77120836Sdougb r = (*db->seq)(db, &key, &data, sflag); 78120836Sdougb if (r == -1) 79120836Sdougb err("db seq: %s", strerror(errno)); 80120836Sdougb if (r == 1) 81120836Sdougb break; 82120836Sdougb pn = *(PERSON **)data.data; 83120836Sdougb if (sflag != R_FIRST) 84120836Sdougb putchar('\n'); 85120836Sdougb lprint(pn); 86120836Sdougb if (!pplan) { 87120836Sdougb (void)show_text(pn->dir, 88120836Sdougb _PATH_FORWARD, "Mail forwarded to"); 89120836Sdougb (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 90120836Sdougb if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 91120836Sdougb (void)printf("No Plan.\n"); 92120836Sdougb } 9397952Sdougb } 94120836Sdougb} 95120836Sdougb 96120836Sdougbstatic void 97120836Sdougblprint(pn) 9897952Sdougb register PERSON *pn; 9997952Sdougb{ 10097952Sdougb extern time_t now; 10197952Sdougb register struct tm *delta; 10297952Sdougb register WHERE *w; 103120836Sdougb register int cpr, len, maxlen; 104120836Sdougb struct tm *tp; 10597952Sdougb int oddfield; 10697952Sdougb char *tzn; 10797952Sdougb char t[80]; 108188481Smaxim 10997952Sdougb /* 11097952Sdougb * long format -- 11197952Sdougb * login name 11297952Sdougb * real name 11397952Sdougb * home directory 11497952Sdougb * shell 11597952Sdougb * office, office phone, home phone if available 11697952Sdougb * mail status 11797952Sdougb */ 11897952Sdougb (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", 11997952Sdougb pn->name, pn->realname, pn->dir); 12097952Sdougb (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); 12197952Sdougb 12297952Sdougb /* 12397952Sdougb * try and print office, office phone, and home phone on one line; 12497952Sdougb * if that fails, do line filling so it looks nice. 12597952Sdougb */ 12697952Sdougb#define OFFICE_TAG "Office" 12797952Sdougb#define OFFICE_PHONE_TAG "Office Phone" 12897952Sdougb oddfield = 0; 12997952Sdougb if (pn->office && pn->officephone && 13097952Sdougb strlen(pn->office) + strlen(pn->officephone) + 13197952Sdougb sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { 13297952Sdougb (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", 13397952Sdougb OFFICE_TAG, pn->office, prphone(pn->officephone)); 13497952Sdougb oddfield = demi_print(tbuf, oddfield); 13597952Sdougb } else { 13697952Sdougb if (pn->office) { 13797952Sdougb (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 13897952Sdougb OFFICE_TAG, pn->office); 13997952Sdougb oddfield = demi_print(tbuf, oddfield); 14097952Sdougb } 14197952Sdougb if (pn->officephone) { 14297952Sdougb (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 14397952Sdougb OFFICE_PHONE_TAG, prphone(pn->officephone)); 14497952Sdougb oddfield = demi_print(tbuf, oddfield); 14597952Sdougb } 146101773Sdougb } 147101773Sdougb if (pn->homephone) { 148101773Sdougb (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", 149101773Sdougb prphone(pn->homephone)); 150101773Sdougb oddfield = demi_print(tbuf, oddfield); 151101773Sdougb } 152101773Sdougb if (oddfield) 15397952Sdougb putchar('\n'); 15497952Sdougb 15597952Sdougb /* 15697952Sdougb * long format con't: 157216203Sdougb * if logged in 15897952Sdougb * terminal 15997952Sdougb * idle time 16097952Sdougb * if messages allowed 16197952Sdougb * where logged in from 16297952Sdougb * if not logged in 16397952Sdougb * when last logged in 16497952Sdougb */ 16597952Sdougb /* find out longest device name for this user for formatting */ 16697952Sdougb for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) 16797952Sdougb if ((len = strlen(w->tty)) > maxlen) 168114924Sdougb maxlen = len; 16997952Sdougb /* find rest of entries for user */ 17097952Sdougb for (w = pn->whead; w != NULL; w = w->next) { 17197952Sdougb switch (w->info) { 17297952Sdougb case LOGGEDIN: 17397952Sdougb tp = localtime(&w->loginat); 17497952Sdougb strftime(t, sizeof(t), "%c", tp); 17597952Sdougb tzn = tp->tm_zone; 17697952Sdougb cpr = printf("On since %.16s (%s) on %s", 17797952Sdougb t, tzn, w->tty); 17897952Sdougb /* 179101773Sdougb * idle time is tough; if have one, print a comma, 18097952Sdougb * then spaces to pad out the device name, then the 181216206Sdougb * idle time. Follow with a comma if a remote login. 18297952Sdougb */ 18397952Sdougb delta = gmtime(&w->idletime); 18497952Sdougb if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 18597952Sdougb cpr += printf("%-*s idle ", 18697952Sdougb maxlen - strlen(w->tty) + 1, ","); 18797952Sdougb if (delta->tm_yday > 0) { 188207153Sjilles cpr += printf("%d day%s ", 189207153Sjilles delta->tm_yday, 190207153Sjilles delta->tm_yday == 1 ? "" : "s"); 19197952Sdougb } 192241737Sed cpr += printf("%d:%02d", 193241737Sed delta->tm_hour, delta->tm_min); 19497952Sdougb if (*w->host) { 195101773Sdougb putchar(','); 19697952Sdougb ++cpr; 197101773Sdougb } 198101773Sdougb } 19997952Sdougb if (!w->writable) 20097952Sdougb cpr += printf(" (messages off)"); 20197952Sdougb break; 20297952Sdougb case LASTLOG: 20397952Sdougb if (w->loginat == 0) { 20497952Sdougb (void)printf("Never logged in."); 205101773Sdougb break; 206101773Sdougb } 207216205Sdougb tp = localtime(&w->loginat); 208188498Sed strftime(t, sizeof(t), "%c", tp); 209188498Sed tzn = tp->tm_zone; 21097952Sdougb if (now - w->loginat > 86400 * 365 / 2) 211101773Sdougb cpr = 21297952Sdougb printf("Last login %.16s %.4s (%s) on %s", 21397952Sdougb t, t + 20, tzn, w->tty); 21497952Sdougb else 21597952Sdougb cpr = printf("Last login %.16s (%s) on %s", 216101773Sdougb t, tzn, w->tty); 217101773Sdougb break; 21897952Sdougb } 21997952Sdougb if (*w->host) { 22097952Sdougb if (LINE_LEN < (cpr + 6 + strlen(w->host))) 221101773Sdougb (void)printf("\n "); 222101773Sdougb (void)printf(" from %s", w->host); 223216203Sdougb } 224216203Sdougb putchar('\n'); 225101773Sdougb } 226101773Sdougb if (pn->mailrecv == -1) 227101773Sdougb printf("No Mail.\n"); 228101773Sdougb else if (pn->mailrecv > pn->mailread) { 229101773Sdougb tp = localtime(&pn->mailrecv); 230216343Sdougb strftime(t, sizeof(t), "%c", tp); 231216343Sdougb tzn = tp->tm_zone; 232101773Sdougb printf("New mail received %.16s %.4s (%s)\n", t, t + 20, tzn); 233101773Sdougb tp = localtime(&pn->mailread); 234101773Sdougb strftime(t, sizeof(t), "%c", tp); 23597952Sdougb tzn = tp->tm_zone; 23697952Sdougb printf(" Unread since %.16s %.4s (%s)\n", t, t + 20, tzn); 23797952Sdougb } else { 23897952Sdougb tp = localtime(&pn->mailread); 23997952Sdougb strftime(t, sizeof(t), "%c", tp); 24097952Sdougb tzn = tp->tm_zone; 24197952Sdougb printf("Mail last read %.16s %.4s (%s)\n", t, t + 20, tzn); 24297952Sdougb } 24397952Sdougb} 24497952Sdougb 245101773Sdougbstatic int 246101773Sdougbdemi_print(str, oddfield) 247101773Sdougb char *str; 24897952Sdougb int oddfield; 249216203Sdougb{ 250216203Sdougb static int lenlast; 251216203Sdougb int lenthis, maxlen; 252216203Sdougb 25397952Sdougb lenthis = strlen(str); 25497952Sdougb if (oddfield) { 25597952Sdougb /* 25697952Sdougb * We left off on an odd number of fields. If we haven't 25797952Sdougb * crossed the midpoint of the screen, and we have room for 25897952Sdougb * the next field, print it on the same line; otherwise, 25997952Sdougb * print it on a new line. 26097952Sdougb * 26197952Sdougb * Note: we insist on having the right hand fields start 26297952Sdougb * no less than 5 tabs out. 26397952Sdougb */ 26497952Sdougb maxlen = 5 * TAB_LEN; 26597952Sdougb if (maxlen < lenlast) 26697952Sdougb maxlen = lenlast; 26797952Sdougb if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 268101773Sdougb lenthis) <= LINE_LEN) { 26997952Sdougb while(lenlast < (4 * TAB_LEN)) { 27097952Sdougb putchar('\t'); 27197952Sdougb lenlast += TAB_LEN; 27297952Sdougb } 27397952Sdougb (void)printf("\t%s\n", str); /* force one tab */ 27497952Sdougb } else { 27597952Sdougb (void)printf("\n%s", str); /* go to next line */ 27697952Sdougb oddfield = !oddfield; /* this'll be undone below */ 27797952Sdougb } 27897952Sdougb } else 27997952Sdougb (void)printf("%s", str); 28097952Sdougb oddfield = !oddfield; /* toggle odd/even marker */ 28197952Sdougb lenlast = lenthis; 28297952Sdougb return(oddfield); 28397952Sdougb} 28497952Sdougb 28597952Sdougbstatic int 28697952Sdougbshow_text(directory, file_name, header) 28797952Sdougb char *directory, *file_name, *header; 28897952Sdougb{ 28997952Sdougb struct stat sb; 29097952Sdougb register FILE *fp; 29197952Sdougb register int ch, cnt, lastc; 29297952Sdougb register char *p; 29397952Sdougb int fd, nr; 29497952Sdougb 29597952Sdougb (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); 29697952Sdougb if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || 29797952Sdougb sb.st_size == 0) 29897952Sdougb return(0); 29997952Sdougb 30097952Sdougb /* If short enough, and no newlines, show it on a single line.*/ 30197952Sdougb if (sb.st_size <= LINE_LEN - strlen(header) - 5) { 30297952Sdougb nr = read(fd, tbuf, sizeof(tbuf)); 30397952Sdougb if (nr <= 0) { 30497952Sdougb (void)close(fd); 30597952Sdougb return(0); 306101773Sdougb } 30797952Sdougb for (p = tbuf, cnt = nr; cnt--; ++p) 30897952Sdougb if (*p == '\n') 30997952Sdougb break; 31097952Sdougb if (cnt <= 1) { 31197952Sdougb (void)printf("%s: ", header); 31297952Sdougb for (p = tbuf, cnt = nr; cnt--; ++p) 31397952Sdougb vputc(lastc = *p); 31497952Sdougb if (lastc != '\n') 315188498Sed (void)putchar('\n'); 316188498Sed (void)close(fd); 317188498Sed return(1); 318188498Sed } 319188498Sed else 320188498Sed (void)lseek(fd, 0L, SEEK_SET); 32197952Sdougb } 322188498Sed if ((fp = fdopen(fd, "r")) == NULL) 323188498Sed return(0); 324216196Sdougb (void)printf("%s:\n", header); 325216196Sdougb while ((ch = getc(fp)) != EOF) 326216196Sdougb vputc(lastc = ch); 327216196Sdougb if (lastc != '\n') 328216196Sdougb (void)putchar('\n'); 329216196Sdougb (void)fclose(fp); 330216196Sdougb return(1); 331216196Sdougb} 332216196Sdougb 333216196Sdougbstatic void 334216196Sdougbvputc(ch) 335188498Sed register int ch; 336188498Sed{ 337188498Sed int meta; 33897952Sdougb 33997952Sdougb if (!isprint(ch) && !isascii(ch)) { 34097952Sdougb (void)putchar('M'); 341101773Sdougb (void)putchar('-'); 342101773Sdougb ch = toascii(ch); 343188498Sed meta = 1; 34497952Sdougb } else 34597952Sdougb meta = 0; 346216206Sdougb if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) 34797952Sdougb (void)putchar(ch); 34897952Sdougb else { 34997952Sdougb (void)putchar('^'); 35097952Sdougb (void)putchar(ch == '\177' ? '?' : ch | 0100); 35197952Sdougb } 35297952Sdougb} 353101773Sdougb