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