1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)cmd1.c 5.16 (Berkeley) 07/08/88"; 20 #endif /* not lint */ 21 22 #include "rcv.h" 23 24 /* 25 * Mail -- a mail program 26 * 27 * User commands. 28 */ 29 30 /* 31 * Print the current active headings. 32 * Don't change dot if invoker didn't give an argument. 33 */ 34 35 static int screen; 36 37 headers(msgvec) 38 int *msgvec; 39 { 40 register int n, mesg, flag; 41 register struct message *mp; 42 int size; 43 44 size = screensize(); 45 n = msgvec[0]; 46 if (n != 0) 47 screen = (n-1)/size; 48 if (screen < 0) 49 screen = 0; 50 mp = &message[screen * size]; 51 if (mp >= &message[msgCount]) 52 mp = &message[msgCount - size]; 53 if (mp < &message[0]) 54 mp = &message[0]; 55 flag = 0; 56 mesg = mp - &message[0]; 57 if (dot != &message[n-1]) 58 dot = mp; 59 for (; mp < &message[msgCount]; mp++) { 60 mesg++; 61 if (mp->m_flag & MDELETED) 62 continue; 63 if (flag++ >= size) 64 break; 65 printhead(mesg); 66 } 67 if (flag == 0) { 68 printf("No more mail.\n"); 69 return(1); 70 } 71 return(0); 72 } 73 74 /* 75 * Scroll to the next/previous screen 76 */ 77 scroll(arg) 78 char arg[]; 79 { 80 register int s, size; 81 int cur[1]; 82 83 cur[0] = 0; 84 size = screensize(); 85 s = screen; 86 switch (*arg) { 87 case 0: 88 case '+': 89 s++; 90 if (s * size > msgCount) { 91 printf("On last screenful of messages\n"); 92 return(0); 93 } 94 screen = s; 95 break; 96 97 case '-': 98 if (--s < 0) { 99 printf("On first screenful of messages\n"); 100 return(0); 101 } 102 screen = s; 103 break; 104 105 default: 106 printf("Unrecognized scrolling command \"%s\"\n", arg); 107 return(1); 108 } 109 return(headers(cur)); 110 } 111 112 /* 113 * Compute screen size. 114 */ 115 screensize() 116 { 117 int s; 118 char *cp; 119 120 if ((cp = value("screen")) != NOSTR && (s = atoi(cp)) > 0) 121 return s; 122 return screenheight - 4; 123 } 124 125 /* 126 * Print out the headlines for each message 127 * in the passed message list. 128 */ 129 130 from(msgvec) 131 int *msgvec; 132 { 133 register int *ip; 134 135 for (ip = msgvec; *ip != NULL; ip++) 136 printhead(*ip); 137 if (--ip >= msgvec) 138 dot = &message[*ip - 1]; 139 return(0); 140 } 141 142 /* 143 * Print out the header of a specific message. 144 * This is a slight improvement to the standard one. 145 */ 146 147 printhead(mesg) 148 { 149 struct message *mp; 150 char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind; 151 char pbuf[BUFSIZ]; 152 struct headline hl; 153 int subjlen; 154 155 mp = &message[mesg-1]; 156 readline(setinput(mp), headline); 157 if ((subjline = hfield("subject", mp)) == NOSTR) 158 subjline = hfield("subj", mp); 159 /* 160 * Bletch! 161 */ 162 curind = dot == mp ? '>' : ' '; 163 dispc = ' '; 164 if (mp->m_flag & MSAVED) 165 dispc = '*'; 166 if (mp->m_flag & MPRESERVE) 167 dispc = 'P'; 168 if ((mp->m_flag & (MREAD|MNEW)) == MNEW) 169 dispc = 'N'; 170 if ((mp->m_flag & (MREAD|MNEW)) == 0) 171 dispc = 'U'; 172 if (mp->m_flag & MBOX) 173 dispc = 'M'; 174 parse(headline, &hl, pbuf); 175 sprintf(wcount, "%3d/%-4ld", mp->m_lines, mp->m_size); 176 subjlen = screenwidth - 50 - strlen(wcount); 177 if (subjline == NOSTR || subjlen < 0) /* pretty pathetic */ 178 printf("%c%c%3d %-20.20s %16.16s %s\n", 179 curind, dispc, mesg, nameof(mp, 0), hl.l_date, wcount); 180 else 181 printf("%c%c%3d %-20.20s %16.16s %s \"%.*s\"\n", 182 curind, dispc, mesg, nameof(mp, 0), hl.l_date, wcount, 183 subjlen, subjline); 184 } 185 186 /* 187 * Print out the value of dot. 188 */ 189 190 pdot() 191 { 192 printf("%d\n", dot - &message[0] + 1); 193 return(0); 194 } 195 196 /* 197 * Print out all the possible commands. 198 */ 199 200 pcmdlist() 201 { 202 register struct cmd *cp; 203 register int cc; 204 extern struct cmd cmdtab[]; 205 206 printf("Commands are:\n"); 207 for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) { 208 cc += strlen(cp->c_name) + 2; 209 if (cc > 72) { 210 printf("\n"); 211 cc = strlen(cp->c_name) + 2; 212 } 213 if ((cp+1)->c_name != NOSTR) 214 printf("%s, ", cp->c_name); 215 else 216 printf("%s\n", cp->c_name); 217 } 218 return(0); 219 } 220 221 /* 222 * Paginate messages, honor ignored fields. 223 */ 224 more(msgvec) 225 int *msgvec; 226 { 227 return (type1(msgvec, 1, 1)); 228 } 229 230 /* 231 * Paginate messages, even printing ignored fields. 232 */ 233 More(msgvec) 234 int *msgvec; 235 { 236 237 return (type1(msgvec, 0, 1)); 238 } 239 240 /* 241 * Type out messages, honor ignored fields. 242 */ 243 type(msgvec) 244 int *msgvec; 245 { 246 247 return(type1(msgvec, 1, 0)); 248 } 249 250 /* 251 * Type out messages, even printing ignored fields. 252 */ 253 Type(msgvec) 254 int *msgvec; 255 { 256 257 return(type1(msgvec, 0, 0)); 258 } 259 260 /* 261 * Type out the messages requested. 262 */ 263 jmp_buf pipestop; 264 265 type1(msgvec, doign, page) 266 int *msgvec; 267 { 268 register *ip; 269 register struct message *mp; 270 register char *cp; 271 int nlines; 272 int brokpipe(); 273 FILE *obuf; 274 275 obuf = stdout; 276 if (setjmp(pipestop)) { 277 if (obuf != stdout) { 278 pipef = NULL; 279 Pclose(obuf); 280 } 281 signal(SIGPIPE, SIG_DFL); 282 return(0); 283 } 284 if (value("interactive") != NOSTR && 285 (page || (cp = value("crt")) != NOSTR)) { 286 nlines = 0; 287 if (!page) { 288 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) 289 nlines += message[*ip - 1].m_lines; 290 } 291 if (page || nlines > (*cp ? atoi(cp) : realscreenheight)) { 292 cp = value("PAGER"); 293 if (cp == NULL || *cp == '\0') 294 cp = MORE; 295 obuf = Popen(cp, "w"); 296 if (obuf == NULL) { 297 perror(cp); 298 obuf = stdout; 299 } else { 300 pipef = obuf; 301 signal(SIGPIPE, brokpipe); 302 } 303 } 304 } 305 for (ip = msgvec; *ip && ip - msgvec < msgCount; ip++) { 306 mp = &message[*ip - 1]; 307 touch(mp); 308 dot = mp; 309 if (value("quiet") == NOSTR) 310 fprintf(obuf, "Message %d:\n", *ip); 311 (void) send(mp, obuf, doign ? ignore : 0, NOSTR); 312 } 313 if (obuf != stdout) { 314 pipef = NULL; 315 Pclose(obuf); 316 } 317 signal(SIGPIPE, SIG_DFL); 318 return(0); 319 } 320 321 /* 322 * Respond to a broken pipe signal -- 323 * probably caused by using quitting more. 324 */ 325 326 brokpipe() 327 { 328 longjmp(pipestop, 1); 329 } 330 331 /* 332 * Print the top so many lines of each desired message. 333 * The number of lines is taken from the variable "toplines" 334 * and defaults to 5. 335 */ 336 337 top(msgvec) 338 int *msgvec; 339 { 340 register int *ip; 341 register struct message *mp; 342 int c, topl, lines, lineb; 343 char *valtop, linebuf[LINESIZE]; 344 FILE *ibuf; 345 346 topl = 5; 347 valtop = value("toplines"); 348 if (valtop != NOSTR) { 349 topl = atoi(valtop); 350 if (topl < 0 || topl > 10000) 351 topl = 5; 352 } 353 lineb = 1; 354 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 355 mp = &message[*ip - 1]; 356 touch(mp); 357 dot = mp; 358 if (value("quiet") == NOSTR) 359 printf("Message %d:\n", *ip); 360 ibuf = setinput(mp); 361 c = mp->m_lines; 362 if (!lineb) 363 printf("\n"); 364 for (lines = 0; lines < c && lines <= topl; lines++) { 365 if (readline(ibuf, linebuf) < 0) 366 break; 367 puts(linebuf); 368 lineb = blankline(linebuf); 369 } 370 } 371 return(0); 372 } 373 374 /* 375 * Touch all the given messages so that they will 376 * get mboxed. 377 */ 378 stouch(msgvec) 379 int msgvec[]; 380 { 381 register int *ip; 382 383 for (ip = msgvec; *ip != 0; ip++) { 384 dot = &message[*ip-1]; 385 dot->m_flag |= MTOUCH; 386 dot->m_flag &= ~MPRESERVE; 387 } 388 return(0); 389 } 390 391 /* 392 * Make sure all passed messages get mboxed. 393 */ 394 395 mboxit(msgvec) 396 int msgvec[]; 397 { 398 register int *ip; 399 400 for (ip = msgvec; *ip != 0; ip++) { 401 dot = &message[*ip-1]; 402 dot->m_flag |= MTOUCH|MBOX; 403 dot->m_flag &= ~MPRESERVE; 404 } 405 return(0); 406 } 407 408 /* 409 * List the folders the user currently has. 410 */ 411 folders() 412 { 413 char dirname[BUFSIZ]; 414 char *cmd; 415 416 if (getfold(dirname) < 0) { 417 printf("No value set for \"folder\"\n"); 418 return -1; 419 } 420 if ((cmd = value("LISTER")) == NOSTR) 421 cmd = "ls"; 422 (void) run_command(cmd, 0, -1, -1, dirname, NOSTR); 423 return 0; 424 } 425