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