xref: /csrg-svn/usr.bin/finger/lprint.c (revision 37660)
1*37660Sbostic /*
2*37660Sbostic  * Copyright (c) 1989 The Regents of the University of California.
3*37660Sbostic  * All rights reserved.
4*37660Sbostic  *
5*37660Sbostic  * This code is derived from software contributed to Berkeley by
6*37660Sbostic  * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
7*37660Sbostic  *
8*37660Sbostic  * Redistribution and use in source and binary forms are permitted
9*37660Sbostic  * provided that the above copyright notice and this paragraph are
10*37660Sbostic  * duplicated in all such forms and that any documentation,
11*37660Sbostic  * advertising materials, and other materials related to such
12*37660Sbostic  * distribution and use acknowledge that the software was developed
13*37660Sbostic  * by the University of California, Berkeley.  The name of the
14*37660Sbostic  * University may not be used to endorse or promote products derived
15*37660Sbostic  * from this software without specific prior written permission.
16*37660Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17*37660Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18*37660Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19*37660Sbostic  */
20*37660Sbostic 
21*37660Sbostic #ifndef lint
22*37660Sbostic static char sccsid[] = "@(#)lprint.c	5.1 (Berkeley) 05/06/89";
23*37660Sbostic #endif /* not lint */
24*37660Sbostic 
25*37660Sbostic #include <sys/types.h>
26*37660Sbostic #include <sys/file.h>
27*37660Sbostic #include <sys/stat.h>
28*37660Sbostic #include <sys/time.h>
29*37660Sbostic #include <tzfile.h>
30*37660Sbostic #include <stdio.h>
31*37660Sbostic #include "finger.h"
32*37660Sbostic #include "pathnames.h"
33*37660Sbostic 
34*37660Sbostic #define	LINE_LEN	80
35*37660Sbostic #define	TAB_LEN		8		/* 8 spaces between tabs */
36*37660Sbostic #define	_PATH_PLAN	".plan"
37*37660Sbostic #define	_PATH_PROJECT	".project"
38*37660Sbostic 
39*37660Sbostic lflag_print()
40*37660Sbostic {
41*37660Sbostic 	extern PERSON *head;
42*37660Sbostic 	extern int pplan;
43*37660Sbostic 	register PERSON *pn;
44*37660Sbostic 
45*37660Sbostic 	for (pn = head;;) {
46*37660Sbostic 		if (pn->info == PRINTED) {
47*37660Sbostic 			if (!(pn = pn->next))
48*37660Sbostic 				break;
49*37660Sbostic 			continue;
50*37660Sbostic 		}
51*37660Sbostic 		lprint(pn);
52*37660Sbostic 		if (!pplan) {
53*37660Sbostic 			(void)show_text(pn->dir, _PATH_PROJECT,
54*37660Sbostic 			    "Project:");
55*37660Sbostic 			if (!show_text(pn->dir, _PATH_PLAN, "Plan:"))
56*37660Sbostic 				(void)printf("No Plan.\n");
57*37660Sbostic 		}
58*37660Sbostic 		if (!(pn = pn->next))
59*37660Sbostic 			break;
60*37660Sbostic 		putchar('\n');
61*37660Sbostic 	}
62*37660Sbostic }
63*37660Sbostic 
64*37660Sbostic lprint(pn)
65*37660Sbostic 	register PERSON *pn;
66*37660Sbostic {
67*37660Sbostic 	extern time_t now;
68*37660Sbostic 	register struct tm *delta;
69*37660Sbostic 	register PERSON *p;
70*37660Sbostic 	register int cpr, len, maxlen;
71*37660Sbostic 	int oddfield;
72*37660Sbostic 	time_t time();
73*37660Sbostic 	char *t, *ctime();
74*37660Sbostic 
75*37660Sbostic 	/*
76*37660Sbostic 	 * long format --
77*37660Sbostic 	 *	login name
78*37660Sbostic 	 *	real name
79*37660Sbostic 	 *	home directory
80*37660Sbostic 	 *	shell
81*37660Sbostic 	 *	office, office phone, home phone if available
82*37660Sbostic 	 */
83*37660Sbostic 	(void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s",
84*37660Sbostic 	    pn->name, pn->realname, pn->dir);
85*37660Sbostic 	(void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL);
86*37660Sbostic 
87*37660Sbostic 	/*
88*37660Sbostic 	 * try and print office, office phone, and home phone on one line;
89*37660Sbostic 	 * if that fails, do line filling so it looks nice.
90*37660Sbostic 	 */
91*37660Sbostic #define	OFFICE_TAG		"Office"
92*37660Sbostic #define	OFFICE_PHONE_TAG	"Office Phone"
93*37660Sbostic 	oddfield = 0;
94*37660Sbostic 	if (pn->office && pn->officephone &&
95*37660Sbostic 	    strlen(pn->office) + strlen(pn->officephone) +
96*37660Sbostic 	    sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) {
97*37660Sbostic 		(void)sprintf(tbuf, "%s: %s, %s", OFFICE_TAG, pn->office,
98*37660Sbostic 		    pn->officephone);
99*37660Sbostic 		oddfield = demi_print(tbuf, oddfield);
100*37660Sbostic 	} else {
101*37660Sbostic 		if (pn->office) {
102*37660Sbostic 			(void)sprintf(tbuf, "%s: %s", OFFICE_TAG, pn->office);
103*37660Sbostic 			oddfield = demi_print(tbuf, oddfield);
104*37660Sbostic 		}
105*37660Sbostic 		if (pn->officephone) {
106*37660Sbostic 			(void)sprintf(tbuf, "%s: %s", OFFICE_PHONE_TAG,
107*37660Sbostic 			    pn->officephone);
108*37660Sbostic 			oddfield = demi_print(tbuf, oddfield);
109*37660Sbostic 		}
110*37660Sbostic 	}
111*37660Sbostic 	if (pn->homephone) {
112*37660Sbostic 		(void)sprintf(tbuf, "%s: %s", "Home Phone", pn->homephone);
113*37660Sbostic 		oddfield = demi_print(tbuf, oddfield);
114*37660Sbostic 	}
115*37660Sbostic 	if (oddfield)
116*37660Sbostic 		putchar('\n');
117*37660Sbostic 
118*37660Sbostic 	/*
119*37660Sbostic 	 * long format con't: if logged in
120*37660Sbostic 	 *	terminal
121*37660Sbostic 	 *	idle time
122*37660Sbostic 	 *	if messages allowed
123*37660Sbostic 	 *	where logged in from
124*37660Sbostic 	 */
125*37660Sbostic 	if (pn->info == LOGGEDIN) {
126*37660Sbostic 		/* find out longest device name for this user for formatting */
127*37660Sbostic 		for (maxlen = -1, p = pn; p; p = p->next)
128*37660Sbostic 			if (!strcmp(p->name, pn->name) &&
129*37660Sbostic 			    (len = strlen(p->tty)) > maxlen)
130*37660Sbostic 				maxlen = len;
131*37660Sbostic 		/* find rest of entries for user */
132*37660Sbostic 		for (p = pn; p; p = p->next) {
133*37660Sbostic 			if (strcmp(p->name, pn->name))
134*37660Sbostic 				continue;
135*37660Sbostic 			p->info = PRINTED;
136*37660Sbostic 			cpr = printf("On since %16.16s on %s",
137*37660Sbostic 			    ctime(&p->loginat), p->tty);
138*37660Sbostic 			/*
139*37660Sbostic 			 * idle time is tough; if have one, print a comma,
140*37660Sbostic 			 * then spaces to pad out the device name, then the
141*37660Sbostic 			 * idle time.  Follow with a comma if a remote login.
142*37660Sbostic 			 */
143*37660Sbostic 			delta = gmtime(&p->idletime);
144*37660Sbostic 			if (delta->tm_yday || delta->tm_hour || delta->tm_min) {
145*37660Sbostic 				cpr += printf("%-*s idle ",
146*37660Sbostic 				    maxlen - strlen(p->tty) + 1, ",");
147*37660Sbostic 				if (delta->tm_yday > 0) {
148*37660Sbostic 					cpr += printf("%d day%s ",
149*37660Sbostic 					   delta->tm_yday,
150*37660Sbostic 					   delta->tm_yday == 1 ? "" : "s");
151*37660Sbostic 				}
152*37660Sbostic 				cpr += printf("%d:%02d",
153*37660Sbostic 				    delta->tm_hour, delta->tm_min);
154*37660Sbostic 				if (*p->host) {
155*37660Sbostic 					putchar(',');
156*37660Sbostic 					++cpr;
157*37660Sbostic 				}
158*37660Sbostic 			}
159*37660Sbostic 			if (!p->writable)
160*37660Sbostic 				cpr += printf(" (messages off)");
161*37660Sbostic 			if (*p->host) {
162*37660Sbostic 				if (LINE_LEN < (cpr + 6 +
163*37660Sbostic 				    strlen(p->host))) {
164*37660Sbostic 					(void)printf("\n   ");
165*37660Sbostic 				}
166*37660Sbostic 				(void)printf(" from %s", p->host);
167*37660Sbostic 			}
168*37660Sbostic 			(void)putchar('\n');
169*37660Sbostic 		}
170*37660Sbostic 	}
171*37660Sbostic 	/*
172*37660Sbostic 	 * long format con't: if not logged in
173*37660Sbostic 	 *	when last logged in
174*37660Sbostic 	 */
175*37660Sbostic 	else if (!pn->loginat)
176*37660Sbostic 		(void)printf("Never logged in.\n");
177*37660Sbostic 	else {
178*37660Sbostic 		t = ctime(&pn->loginat);
179*37660Sbostic 		if (now - pn->loginat > SECSPERDAY * DAYSPERNYEAR / 2)
180*37660Sbostic 			cpr = printf("Last login %10.10s, %4.4s on %s",
181*37660Sbostic 			    t, t + 20, pn->tty);
182*37660Sbostic 		else
183*37660Sbostic 			cpr = printf("Last login %16.16s on %s", t, pn->tty);
184*37660Sbostic 		if (*pn->host) {
185*37660Sbostic 			if (LINE_LEN < (cpr + 6 + strlen(pn->host)))
186*37660Sbostic 				(void)printf("\n   ");
187*37660Sbostic 			(void)printf(" from %s", pn->host);
188*37660Sbostic 		}
189*37660Sbostic 		putchar('\n');
190*37660Sbostic 	}
191*37660Sbostic 	/*
192*37660Sbostic 	 * long format con't:
193*37660Sbostic 	 *	mail status
194*37660Sbostic 	 */
195*37660Sbostic 	chkmail(pn);
196*37660Sbostic }
197*37660Sbostic 
198*37660Sbostic demi_print(str, oddfield)
199*37660Sbostic 	char *str;
200*37660Sbostic 	int oddfield;
201*37660Sbostic {
202*37660Sbostic 	static int lenlast;
203*37660Sbostic 	int lenthis, maxlen;
204*37660Sbostic 
205*37660Sbostic 	lenthis = strlen(str);
206*37660Sbostic 	if (oddfield) {
207*37660Sbostic 		/*
208*37660Sbostic 		 * We left off on an odd number of fields.  If we haven't
209*37660Sbostic 		 * crossed the midpoint of the screen, and we have room for
210*37660Sbostic 		 * the next field, print it on the same line; otherwise,
211*37660Sbostic 		 * print it on a new line.
212*37660Sbostic 		 *
213*37660Sbostic 		 * Note: we insist on having the right hand fields start
214*37660Sbostic 		 * no less than 5 tabs out.
215*37660Sbostic 		 */
216*37660Sbostic 		maxlen = 5 * TAB_LEN;
217*37660Sbostic 		if (maxlen < lenlast)
218*37660Sbostic 			maxlen = lenlast;
219*37660Sbostic 		if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) +
220*37660Sbostic 		    lenthis) <= LINE_LEN) {
221*37660Sbostic 			while(lenlast < (4 * TAB_LEN)) {
222*37660Sbostic 				putchar('\t');
223*37660Sbostic 				lenlast += TAB_LEN;
224*37660Sbostic 			}
225*37660Sbostic 			(void)printf("\t%s\n", str);	/* force one tab */
226*37660Sbostic 		} else {
227*37660Sbostic 			(void)printf("\n%s", str);	/* go to next line */
228*37660Sbostic 			oddfield = !oddfield;	/* this'll be undone below */
229*37660Sbostic 		}
230*37660Sbostic 	} else
231*37660Sbostic 		(void)printf("%s", str);
232*37660Sbostic 	oddfield = !oddfield;			/* toggle odd/even marker */
233*37660Sbostic 	lenlast = lenthis;
234*37660Sbostic 	return(oddfield);
235*37660Sbostic }
236*37660Sbostic 
237*37660Sbostic show_text(directory, file_name, header)
238*37660Sbostic 	char *directory, *file_name, *header;
239*37660Sbostic {
240*37660Sbostic 	register int fd, n;
241*37660Sbostic 
242*37660Sbostic 	(void)sprintf(tbuf, "%s/%s", directory, file_name);
243*37660Sbostic 	if ((fd = open(tbuf, O_RDONLY, 0)) < 0)
244*37660Sbostic 		return(0);
245*37660Sbostic 	(void)printf("%s\n", header);
246*37660Sbostic 	(void)fflush(stdout);
247*37660Sbostic 	while ((n = read(fd, tbuf, sizeof(tbuf))) > 0)
248*37660Sbostic 		if (write(1, tbuf, n) != n)
249*37660Sbostic 			break;
250*37660Sbostic 	(void)close(fd);
251*37660Sbostic 	return(1);
252*37660Sbostic }
253*37660Sbostic 
254*37660Sbostic chkmail(pn)
255*37660Sbostic 	PERSON *pn;
256*37660Sbostic {
257*37660Sbostic 	register char *date;
258*37660Sbostic 	struct stat sb;
259*37660Sbostic 
260*37660Sbostic 	/*
261*37660Sbostic 	 * build path of user's mail box and get stats; if missing
262*37660Sbostic 	 * or empty, no mail.
263*37660Sbostic 	 */
264*37660Sbostic 	(void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pn->name);
265*37660Sbostic 	if (stat(tbuf, &sb) < 0 || !sb.st_size) {
266*37660Sbostic 		(void)printf("No unread mail.\n");
267*37660Sbostic 		return;
268*37660Sbostic 	}
269*37660Sbostic 
270*37660Sbostic 	/*
271*37660Sbostic 	 * if access time matches the modification time then we know
272*37660Sbostic 	 * that new mail was received but we haven't a clue as to when
273*37660Sbostic 	 * it was last read.
274*37660Sbostic 	 */
275*37660Sbostic 	date = ctime(&sb.st_ctime);
276*37660Sbostic 	if (sb.st_atime == sb.st_ctime)
277*37660Sbostic 		(void)printf("New mail received %16.16s.\n", date);
278*37660Sbostic 	else if (sb.st_atime > sb.st_ctime) {
279*37660Sbostic 		date = ctime(&sb.st_atime);
280*37660Sbostic 		(void)printf("No new mail, last read %16.16s.\n", date);
281*37660Sbostic 	} else {
282*37660Sbostic 		(void)printf("Mail received %16.16s; ", date);
283*37660Sbostic 		date = ctime(&sb.st_atime);
284*37660Sbostic 		(void)printf("last read %16.16s.\n", date);
285*37660Sbostic 	}
286*37660Sbostic }
287