1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)lprint.c 5.14 (Berkeley) 07/27/91"; 13 #endif /* not lint */ 14 15 #include <sys/types.h> 16 #include <sys/file.h> 17 #include <sys/stat.h> 18 #include <sys/time.h> 19 #include <tzfile.h> 20 #include <stdio.h> 21 #include <ctype.h> 22 #include <paths.h> 23 #include "finger.h" 24 25 #define LINE_LEN 80 26 #define TAB_LEN 8 /* 8 spaces between tabs */ 27 #define _PATH_FORWARD ".forward" 28 #define _PATH_PLAN ".plan" 29 #define _PATH_PROJECT ".project" 30 31 lflag_print() 32 { 33 extern int pplan; 34 register PERSON *pn; 35 36 for (pn = phead;;) { 37 lprint(pn); 38 if (!pplan) { 39 (void)show_text(pn->dir, 40 _PATH_FORWARD, "Mail forwarded to"); 41 (void)show_text(pn->dir, _PATH_PROJECT, "Project"); 42 if (!show_text(pn->dir, _PATH_PLAN, "Plan")) 43 (void)printf("No Plan.\n"); 44 } 45 if (!(pn = pn->next)) 46 break; 47 putchar('\n'); 48 } 49 } 50 51 lprint(pn) 52 register PERSON *pn; 53 { 54 extern time_t now; 55 register struct tm *delta; 56 register WHERE *w; 57 register int cpr, len, maxlen; 58 struct tm *tp; 59 int oddfield; 60 time_t time(); 61 char *t, *tzn, *prphone(); 62 63 /* 64 * long format -- 65 * login name 66 * real name 67 * home directory 68 * shell 69 * office, office phone, home phone if available 70 */ 71 (void)printf("Login: %-15s\t\t\tName: %s\nDirectory: %-25s", 72 pn->name, pn->realname, pn->dir); 73 (void)printf("\tShell: %-s\n", *pn->shell ? pn->shell : _PATH_BSHELL); 74 75 /* 76 * try and print office, office phone, and home phone on one line; 77 * if that fails, do line filling so it looks nice. 78 */ 79 #define OFFICE_TAG "Office" 80 #define OFFICE_PHONE_TAG "Office Phone" 81 oddfield = 0; 82 if (pn->office && pn->officephone && 83 strlen(pn->office) + strlen(pn->officephone) + 84 sizeof(OFFICE_TAG) + 2 <= 5 * TAB_LEN) { 85 (void)snprintf(tbuf, sizeof(tbuf), "%s: %s, %s", 86 OFFICE_TAG, pn->office, prphone(pn->officephone)); 87 oddfield = demi_print(tbuf, oddfield); 88 } else { 89 if (pn->office) { 90 (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 91 OFFICE_TAG, pn->office); 92 oddfield = demi_print(tbuf, oddfield); 93 } 94 if (pn->officephone) { 95 (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", 96 OFFICE_PHONE_TAG, prphone(pn->officephone)); 97 oddfield = demi_print(tbuf, oddfield); 98 } 99 } 100 if (pn->homephone) { 101 (void)snprintf(tbuf, sizeof(tbuf), "%s: %s", "Home Phone", 102 prphone(pn->homephone)); 103 oddfield = demi_print(tbuf, oddfield); 104 } 105 if (oddfield) 106 putchar('\n'); 107 108 /* 109 * long format con't: * if logged in 110 * terminal 111 * idle time 112 * if messages allowed 113 * where logged in from 114 * if not logged in 115 * when last logged in 116 */ 117 /* find out longest device name for this user for formatting */ 118 for (w = pn->whead, maxlen = -1; w != NULL; w = w->next) 119 if ((len = strlen(w->tty)) > maxlen) 120 maxlen = len; 121 /* find rest of entries for user */ 122 for (w = pn->whead; w != NULL; w = w->next) { 123 switch (w->info) { 124 case LOGGEDIN: 125 tp = localtime(&w->loginat); 126 t = asctime(tp); 127 tzn = tp->tm_zone; 128 cpr = printf("On since %.16s (%s) on %s", 129 t, tzn, w->tty); 130 /* 131 * idle time is tough; if have one, print a comma, 132 * then spaces to pad out the device name, then the 133 * idle time. Follow with a comma if a remote login. 134 */ 135 delta = gmtime(&w->idletime); 136 if (delta->tm_yday || delta->tm_hour || delta->tm_min) { 137 cpr += printf("%-*s idle ", 138 maxlen - strlen(w->tty) + 1, ","); 139 if (delta->tm_yday > 0) { 140 cpr += printf("%d day%s ", 141 delta->tm_yday, 142 delta->tm_yday == 1 ? "" : "s"); 143 } 144 cpr += printf("%d:%02d", 145 delta->tm_hour, delta->tm_min); 146 if (*w->host) { 147 putchar(','); 148 ++cpr; 149 } 150 } 151 if (!w->writable) 152 cpr += printf(" (messages off)"); 153 break; 154 case LASTLOG: 155 if (w->loginat == 0) { 156 (void)printf("Never logged in."); 157 break; 158 } 159 tp = localtime(&w->loginat); 160 t = asctime(tp); 161 tzn = tp->tm_zone; 162 if (now - w->loginat > SECSPERDAY * DAYSPERNYEAR / 2) 163 cpr = 164 printf("Last login %.16s %.4s (%s) on %s", 165 t, t + 20, tzn, w->tty); 166 else 167 cpr = printf("Last login %.16s (%s) on %s", 168 t, tzn, w->tty); 169 break; 170 } 171 if (*w->host) { 172 if (LINE_LEN < (cpr + 6 + strlen(w->host))) 173 (void)printf("\n "); 174 (void)printf(" from %s", w->host); 175 } 176 putchar('\n'); 177 } 178 } 179 180 demi_print(str, oddfield) 181 char *str; 182 int oddfield; 183 { 184 static int lenlast; 185 int lenthis, maxlen; 186 187 lenthis = strlen(str); 188 if (oddfield) { 189 /* 190 * We left off on an odd number of fields. If we haven't 191 * crossed the midpoint of the screen, and we have room for 192 * the next field, print it on the same line; otherwise, 193 * print it on a new line. 194 * 195 * Note: we insist on having the right hand fields start 196 * no less than 5 tabs out. 197 */ 198 maxlen = 5 * TAB_LEN; 199 if (maxlen < lenlast) 200 maxlen = lenlast; 201 if (((((maxlen / TAB_LEN) + 1) * TAB_LEN) + 202 lenthis) <= LINE_LEN) { 203 while(lenlast < (4 * TAB_LEN)) { 204 putchar('\t'); 205 lenlast += TAB_LEN; 206 } 207 (void)printf("\t%s\n", str); /* force one tab */ 208 } else { 209 (void)printf("\n%s", str); /* go to next line */ 210 oddfield = !oddfield; /* this'll be undone below */ 211 } 212 } else 213 (void)printf("%s", str); 214 oddfield = !oddfield; /* toggle odd/even marker */ 215 lenlast = lenthis; 216 return(oddfield); 217 } 218 219 show_text(directory, file_name, header) 220 char *directory, *file_name, *header; 221 { 222 struct stat sb; 223 register FILE *fp; 224 register int ch, cnt, lastc; 225 register char *p; 226 int fd, nr; 227 228 (void)snprintf(tbuf, sizeof(tbuf), "%s/%s", directory, file_name); 229 if ((fd = open(tbuf, O_RDONLY)) < 0 || fstat(fd, &sb) || 230 sb.st_size == 0) 231 return(0); 232 233 /* If short enough, and no newlines, show it on a single line.*/ 234 if (sb.st_size <= LINE_LEN - strlen(header) - 5) { 235 nr = read(fd, tbuf, sizeof(tbuf)); 236 if (nr <= 0) { 237 (void)close(fd); 238 return(0); 239 } 240 for (p = tbuf, cnt = nr; cnt--; ++p) 241 if (*p == '\n') 242 break; 243 if (cnt <= 1) { 244 (void)printf("%s: ", header); 245 for (p = tbuf, cnt = nr; cnt--; ++p) 246 vputc(lastc = *p); 247 if (lastc != '\n') 248 (void)putchar('\n'); 249 (void)close(fd); 250 return(1); 251 } 252 else 253 (void)lseek(fd, 0L, SEEK_SET); 254 } 255 if ((fp = fdopen(fd, "r")) == NULL) 256 return(0); 257 (void)printf("%s:\n", header); 258 while ((ch = getc(fp)) != EOF) 259 vputc(lastc = ch); 260 if (lastc != '\n') 261 (void)putchar('\n'); 262 (void)fclose(fp); 263 return(1); 264 } 265 266 vputc(ch) 267 register int ch; 268 { 269 int meta; 270 271 if (!isascii(ch)) { 272 (void)putchar('M'); 273 (void)putchar('-'); 274 ch = toascii(ch); 275 meta = 1; 276 } else 277 meta = 0; 278 if (isprint(ch) || !meta && (ch == ' ' || ch == '\t' || ch == '\n')) 279 (void)putchar(ch); 280 else { 281 (void)putchar('^'); 282 (void)putchar(ch == '\177' ? '?' : ch | 0100); 283 } 284 } 285