17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5eb2b0a61Sas145665 * Common Development and Distribution License (the "License"). 6eb2b0a61Sas145665 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* 23eb2b0a61Sas145665 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24eb2b0a61Sas145665 * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27eb2b0a61Sas145665 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28eb2b0a61Sas145665 /* All Rights Reserved */ 29eb2b0a61Sas145665 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 327c478bd9Sstevel@tonic-gate * The Regents of the University of California 337c478bd9Sstevel@tonic-gate * All Rights Reserved 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 367c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 377c478bd9Sstevel@tonic-gate * contributors. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #include "rcv.h" 427c478bd9Sstevel@tonic-gate #include <locale.h> 43*411fa6a8Sas145665 #include <stdlib.h> 44*411fa6a8Sas145665 #include <string.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate /* 477c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley 487c478bd9Sstevel@tonic-gate * mail program 497c478bd9Sstevel@tonic-gate * 507c478bd9Sstevel@tonic-gate * Message list handling. 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate static int check(int mesg, int f); 547c478bd9Sstevel@tonic-gate static int evalcol(int col); 55*411fa6a8Sas145665 static int isinteger(char *buf); 567c478bd9Sstevel@tonic-gate static void mark(int mesg); 577c478bd9Sstevel@tonic-gate static int markall(char buf[], int f); 587c478bd9Sstevel@tonic-gate static int matchsubj(char *str, int mesg); 597c478bd9Sstevel@tonic-gate static int metamess(int meta, int f); 607c478bd9Sstevel@tonic-gate static void regret(int token); 617c478bd9Sstevel@tonic-gate static int scan(char **sp); 627c478bd9Sstevel@tonic-gate static void scaninit(void); 637c478bd9Sstevel@tonic-gate static int sender(char *str, int mesg); 647c478bd9Sstevel@tonic-gate static void unmark(int mesg); 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate /* 67eb2b0a61Sas145665 * Process message operand list. 68eb2b0a61Sas145665 * Convert the user string of message numbers and 69eb2b0a61Sas145665 * store the numbers into vector. 70eb2b0a61Sas145665 * 71eb2b0a61Sas145665 * Returns the count of messages picked up or -1 on error. 72eb2b0a61Sas145665 */ 73eb2b0a61Sas145665 int 74eb2b0a61Sas145665 getmessage(char *buf, int *vector, int flags) 75eb2b0a61Sas145665 { 76eb2b0a61Sas145665 register int *ip; 77eb2b0a61Sas145665 register struct message *mp; 78*411fa6a8Sas145665 int firstmsg = -1; 79*411fa6a8Sas145665 char delims[] = "\t- "; 80*411fa6a8Sas145665 char *result = NULL; 81eb2b0a61Sas145665 82eb2b0a61Sas145665 if (markall(buf, flags) < 0) 83eb2b0a61Sas145665 return (-1); 84eb2b0a61Sas145665 ip = vector; 85eb2b0a61Sas145665 86eb2b0a61Sas145665 /* 87eb2b0a61Sas145665 * Check for first message number and make sure it is 88eb2b0a61Sas145665 * at the beginning of the vector. 89eb2b0a61Sas145665 */ 90*411fa6a8Sas145665 result = strtok(buf, delims); 91*411fa6a8Sas145665 if (result != NULL && isinteger(result)) { 92*411fa6a8Sas145665 firstmsg = atoi(result); 93eb2b0a61Sas145665 *ip++ = firstmsg; 94eb2b0a61Sas145665 } 95eb2b0a61Sas145665 96eb2b0a61Sas145665 /* 97eb2b0a61Sas145665 * Add marked messages to vector and skip first 98eb2b0a61Sas145665 * message number because it is already at the 99eb2b0a61Sas145665 * beginning of the vector 100eb2b0a61Sas145665 */ 101eb2b0a61Sas145665 for (mp = &message[0]; mp < &message[msgCount]; mp++) { 102eb2b0a61Sas145665 if (firstmsg == mp - &message[0] + 1) 103eb2b0a61Sas145665 continue; 104eb2b0a61Sas145665 if (mp->m_flag & MMARK) 105eb2b0a61Sas145665 *ip++ = mp - &message[0] + 1; 106eb2b0a61Sas145665 } 107eb2b0a61Sas145665 *ip = NULL; 108eb2b0a61Sas145665 return (ip - vector); 109eb2b0a61Sas145665 } 110eb2b0a61Sas145665 111eb2b0a61Sas145665 /* 112*411fa6a8Sas145665 * Check to see if string is an integer 113*411fa6a8Sas145665 * 114*411fa6a8Sas145665 * Returns 1 if is an integer and 0 if it is not 115*411fa6a8Sas145665 */ 116*411fa6a8Sas145665 static int 117*411fa6a8Sas145665 isinteger(char *buf) 118*411fa6a8Sas145665 { 119*411fa6a8Sas145665 int i, result = 1; 120*411fa6a8Sas145665 121*411fa6a8Sas145665 /* check for empty string */ 122*411fa6a8Sas145665 if (strcmp(buf, "") == 0) { 123*411fa6a8Sas145665 result = 0; 124*411fa6a8Sas145665 return (result); 125*411fa6a8Sas145665 } 126*411fa6a8Sas145665 127*411fa6a8Sas145665 i = 0; 128*411fa6a8Sas145665 while (buf[i] != '\0') { 129*411fa6a8Sas145665 if (!isdigit(buf[i])) { 130*411fa6a8Sas145665 result = 0; 131*411fa6a8Sas145665 break; 132*411fa6a8Sas145665 } 133*411fa6a8Sas145665 i++; 134*411fa6a8Sas145665 } 135*411fa6a8Sas145665 return (result); 136*411fa6a8Sas145665 } 137*411fa6a8Sas145665 138*411fa6a8Sas145665 /* 139eb2b0a61Sas145665 * Process msglist operand list. 1407c478bd9Sstevel@tonic-gate * Convert the user string of message numbers and 1417c478bd9Sstevel@tonic-gate * store the numbers into vector. 1427c478bd9Sstevel@tonic-gate * 1437c478bd9Sstevel@tonic-gate * Returns the count of messages picked up or -1 on error. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate int 1477c478bd9Sstevel@tonic-gate getmsglist(char *buf, int *vector, int flags) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate register int *ip; 1507c478bd9Sstevel@tonic-gate register struct message *mp; 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate if (markall(buf, flags) < 0) 1537c478bd9Sstevel@tonic-gate return (-1); 1547c478bd9Sstevel@tonic-gate ip = vector; 1557c478bd9Sstevel@tonic-gate for (mp = &message[0]; mp < &message[msgCount]; mp++) 1567c478bd9Sstevel@tonic-gate if (mp->m_flag & MMARK) 1577c478bd9Sstevel@tonic-gate *ip++ = mp - &message[0] + 1; 1587c478bd9Sstevel@tonic-gate *ip = NULL; 1597c478bd9Sstevel@tonic-gate return (ip - vector); 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 162eb2b0a61Sas145665 1637c478bd9Sstevel@tonic-gate /* 1647c478bd9Sstevel@tonic-gate * Mark all messages that the user wanted from the command 1657c478bd9Sstevel@tonic-gate * line in the message structure. Return 0 on success, -1 1667c478bd9Sstevel@tonic-gate * on error. 1677c478bd9Sstevel@tonic-gate */ 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * Bit values for colon modifiers. 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate #define CMNEW 01 /* New messages */ 1747c478bd9Sstevel@tonic-gate #define CMOLD 02 /* Old messages */ 1757c478bd9Sstevel@tonic-gate #define CMUNREAD 04 /* Unread messages */ 1767c478bd9Sstevel@tonic-gate #define CMDELETED 010 /* Deleted messages */ 1777c478bd9Sstevel@tonic-gate #define CMREAD 020 /* Read messages */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * The following table describes the letters which can follow 1817c478bd9Sstevel@tonic-gate * the colon and gives the corresponding modifier bit. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate static struct coltab { 1857c478bd9Sstevel@tonic-gate char co_char; /* What to find past : */ 1867c478bd9Sstevel@tonic-gate int co_bit; /* Associated modifier bit */ 1877c478bd9Sstevel@tonic-gate int co_mask; /* m_status bits to mask */ 1887c478bd9Sstevel@tonic-gate int co_equal; /* ... must equal this */ 1897c478bd9Sstevel@tonic-gate } coltab[] = { 1907c478bd9Sstevel@tonic-gate 'n', CMNEW, MNEW, MNEW, 1917c478bd9Sstevel@tonic-gate 'o', CMOLD, MNEW, 0, 1927c478bd9Sstevel@tonic-gate 'u', CMUNREAD, MREAD, 0, 1937c478bd9Sstevel@tonic-gate 'd', CMDELETED, MDELETED, MDELETED, 1947c478bd9Sstevel@tonic-gate 'r', CMREAD, MREAD, MREAD, 1957c478bd9Sstevel@tonic-gate 0, 0, 0, 0 1967c478bd9Sstevel@tonic-gate }; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate static int lastcolmod; 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate static int 2017c478bd9Sstevel@tonic-gate markall(char buf[], int f) 2027c478bd9Sstevel@tonic-gate { 2037c478bd9Sstevel@tonic-gate register char **np; 2047c478bd9Sstevel@tonic-gate register int i; 2057c478bd9Sstevel@tonic-gate register struct message *mp; 2067c478bd9Sstevel@tonic-gate char *namelist[NMLSIZE], *bufp; 2077c478bd9Sstevel@tonic-gate int tok, beg, mc, star, other, colmod, colresult; 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate colmod = 0; 2107c478bd9Sstevel@tonic-gate for (i = 1; i <= msgCount; i++) 2117c478bd9Sstevel@tonic-gate unmark(i); 2127c478bd9Sstevel@tonic-gate bufp = buf; 2137c478bd9Sstevel@tonic-gate mc = 0; 2147c478bd9Sstevel@tonic-gate np = &namelist[0]; 2157c478bd9Sstevel@tonic-gate scaninit(); 2167c478bd9Sstevel@tonic-gate tok = scan(&bufp); 2177c478bd9Sstevel@tonic-gate star = 0; 2187c478bd9Sstevel@tonic-gate other = 0; 2197c478bd9Sstevel@tonic-gate beg = 0; 2207c478bd9Sstevel@tonic-gate while (tok != TEOL) { 2217c478bd9Sstevel@tonic-gate switch (tok) { 2227c478bd9Sstevel@tonic-gate case TNUMBER: 2237c478bd9Sstevel@tonic-gate number: 2247c478bd9Sstevel@tonic-gate if (star) { 2257c478bd9Sstevel@tonic-gate printf(gettext("No numbers mixed with *\n")); 2267c478bd9Sstevel@tonic-gate return (-1); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate mc++; 2297c478bd9Sstevel@tonic-gate other++; 2307c478bd9Sstevel@tonic-gate if (beg != 0) { 2317c478bd9Sstevel@tonic-gate if (check(lexnumber, f)) 2327c478bd9Sstevel@tonic-gate return (-1); 2337c478bd9Sstevel@tonic-gate for (i = beg; i <= lexnumber; i++) 2347c478bd9Sstevel@tonic-gate if ((message[i-1].m_flag&MDELETED) == f) 2357c478bd9Sstevel@tonic-gate mark(i); 2367c478bd9Sstevel@tonic-gate beg = 0; 2377c478bd9Sstevel@tonic-gate break; 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate beg = lexnumber; 2407c478bd9Sstevel@tonic-gate if (check(beg, f)) 2417c478bd9Sstevel@tonic-gate return (-1); 2427c478bd9Sstevel@tonic-gate tok = scan(&bufp); 2437c478bd9Sstevel@tonic-gate if (tok != TDASH) { 2447c478bd9Sstevel@tonic-gate regret(tok); 2457c478bd9Sstevel@tonic-gate mark(beg); 2467c478bd9Sstevel@tonic-gate beg = 0; 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate break; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate case TSTRING: 2517c478bd9Sstevel@tonic-gate if (beg != 0) { 2527c478bd9Sstevel@tonic-gate printf(gettext( 2537c478bd9Sstevel@tonic-gate "Non-numeric second argument\n")); 2547c478bd9Sstevel@tonic-gate return (-1); 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate other++; 2577c478bd9Sstevel@tonic-gate if (lexstring[0] == ':') { 2587c478bd9Sstevel@tonic-gate colresult = evalcol(lexstring[1]); 2597c478bd9Sstevel@tonic-gate if (colresult == 0) { 2607c478bd9Sstevel@tonic-gate printf(gettext( 2617c478bd9Sstevel@tonic-gate "Unknown colon modifier \"%s\"\n"), 2627c478bd9Sstevel@tonic-gate lexstring); 2637c478bd9Sstevel@tonic-gate return (-1); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate colmod |= colresult; 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate else 2687c478bd9Sstevel@tonic-gate *np++ = savestr(lexstring); 2697c478bd9Sstevel@tonic-gate break; 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate case TDASH: 2727c478bd9Sstevel@tonic-gate case TPLUS: 2737c478bd9Sstevel@tonic-gate case TDOLLAR: 2747c478bd9Sstevel@tonic-gate case TUP: 2757c478bd9Sstevel@tonic-gate case TDOT: 2767c478bd9Sstevel@tonic-gate lexnumber = metamess(lexstring[0], f); 2777c478bd9Sstevel@tonic-gate if (lexnumber == -1) 2787c478bd9Sstevel@tonic-gate return (-1); 2797c478bd9Sstevel@tonic-gate goto number; 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate case TSTAR: 2827c478bd9Sstevel@tonic-gate if (other) { 2837c478bd9Sstevel@tonic-gate printf(gettext( 2847c478bd9Sstevel@tonic-gate "Can't mix \"*\" with anything\n")); 2857c478bd9Sstevel@tonic-gate return (-1); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate star++; 2887c478bd9Sstevel@tonic-gate break; 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate tok = scan(&bufp); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate lastcolmod = colmod; 2937c478bd9Sstevel@tonic-gate *np = NOSTR; 2947c478bd9Sstevel@tonic-gate mc = 0; 2957c478bd9Sstevel@tonic-gate if (star) { 2967c478bd9Sstevel@tonic-gate for (i = 0; i < msgCount; i++) 2977c478bd9Sstevel@tonic-gate if ((message[i].m_flag & MDELETED) == f) { 2987c478bd9Sstevel@tonic-gate mark(i+1); 2997c478bd9Sstevel@tonic-gate mc++; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate if (mc == 0) { 3027c478bd9Sstevel@tonic-gate printf(gettext("No applicable messages\n")); 3037c478bd9Sstevel@tonic-gate return (-1); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate return (0); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* 3097c478bd9Sstevel@tonic-gate * If no numbers were given, mark all of the messages, 3107c478bd9Sstevel@tonic-gate * so that we can unmark any whose sender was not selected 3117c478bd9Sstevel@tonic-gate * if any user names were given. 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate if ((np > namelist || colmod != 0) && mc == 0) 3157c478bd9Sstevel@tonic-gate for (i = 1; i <= msgCount; i++) 3167c478bd9Sstevel@tonic-gate if ((message[i-1].m_flag & MDELETED) == f) 3177c478bd9Sstevel@tonic-gate mark(i); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * If any names were given, go through and eliminate any 3217c478bd9Sstevel@tonic-gate * messages whose senders were not requested. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate if (np > namelist) { 3257c478bd9Sstevel@tonic-gate for (i = 1; i <= msgCount; i++) { 3267c478bd9Sstevel@tonic-gate for (mc = 0, np = &namelist[0]; *np != NOSTR; np++) 3277c478bd9Sstevel@tonic-gate if (**np == '/') { 3287c478bd9Sstevel@tonic-gate if (matchsubj(*np, i)) { 3297c478bd9Sstevel@tonic-gate mc++; 3307c478bd9Sstevel@tonic-gate break; 3317c478bd9Sstevel@tonic-gate } 332eb2b0a61Sas145665 } else { 3337c478bd9Sstevel@tonic-gate if (sender(*np, i)) { 3347c478bd9Sstevel@tonic-gate mc++; 3357c478bd9Sstevel@tonic-gate break; 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate if (mc == 0) 3397c478bd9Sstevel@tonic-gate unmark(i); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* 3437c478bd9Sstevel@tonic-gate * Make sure we got some decent messages. 3447c478bd9Sstevel@tonic-gate */ 3457c478bd9Sstevel@tonic-gate 3467c478bd9Sstevel@tonic-gate mc = 0; 3477c478bd9Sstevel@tonic-gate for (i = 1; i <= msgCount; i++) 3487c478bd9Sstevel@tonic-gate if (message[i-1].m_flag & MMARK) { 3497c478bd9Sstevel@tonic-gate mc++; 3507c478bd9Sstevel@tonic-gate break; 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate if (mc == 0) { 3537c478bd9Sstevel@tonic-gate printf(gettext("No applicable messages from {%s"), 3547c478bd9Sstevel@tonic-gate namelist[0]); 3557c478bd9Sstevel@tonic-gate for (np = &namelist[1]; *np != NOSTR; np++) 3567c478bd9Sstevel@tonic-gate printf(", %s", *np); 3577c478bd9Sstevel@tonic-gate printf("}\n"); 3587c478bd9Sstevel@tonic-gate return (-1); 3597c478bd9Sstevel@tonic-gate } 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * If any colon modifiers were given, go through and 3647c478bd9Sstevel@tonic-gate * unmark any messages which do not satisfy the modifiers. 3657c478bd9Sstevel@tonic-gate */ 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (colmod != 0) { 3687c478bd9Sstevel@tonic-gate for (i = 1; i <= msgCount; i++) { 3697c478bd9Sstevel@tonic-gate register struct coltab *colp; 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate mp = &message[i - 1]; 3727c478bd9Sstevel@tonic-gate for (colp = &coltab[0]; colp->co_char; colp++) 3737c478bd9Sstevel@tonic-gate if (colp->co_bit & colmod) 3747c478bd9Sstevel@tonic-gate if ((mp->m_flag & colp->co_mask) 3757c478bd9Sstevel@tonic-gate != colp->co_equal) 3767c478bd9Sstevel@tonic-gate unmark(i); 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate for (mp = &message[0]; mp < &message[msgCount]; mp++) 3807c478bd9Sstevel@tonic-gate if (mp->m_flag & MMARK) 3817c478bd9Sstevel@tonic-gate break; 3827c478bd9Sstevel@tonic-gate if (mp >= &message[msgCount]) { 3837c478bd9Sstevel@tonic-gate register struct coltab *colp; 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate printf(gettext("No messages satisfy")); 3867c478bd9Sstevel@tonic-gate for (colp = &coltab[0]; colp->co_char; colp++) 3877c478bd9Sstevel@tonic-gate if (colp->co_bit & colmod) 3887c478bd9Sstevel@tonic-gate printf(" :%c", colp->co_char); 3897c478bd9Sstevel@tonic-gate printf("\n"); 3907c478bd9Sstevel@tonic-gate return (-1); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate return (0); 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate /* 3977c478bd9Sstevel@tonic-gate * Turn the character after a colon modifier into a bit 3987c478bd9Sstevel@tonic-gate * value. 3997c478bd9Sstevel@tonic-gate */ 4007c478bd9Sstevel@tonic-gate static int 4017c478bd9Sstevel@tonic-gate evalcol(int col) 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate register struct coltab *colp; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if (col == 0) 4067c478bd9Sstevel@tonic-gate return (lastcolmod); 4077c478bd9Sstevel@tonic-gate for (colp = &coltab[0]; colp->co_char; colp++) 4087c478bd9Sstevel@tonic-gate if (colp->co_char == col) 4097c478bd9Sstevel@tonic-gate return (colp->co_bit); 4107c478bd9Sstevel@tonic-gate return (0); 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* 4147c478bd9Sstevel@tonic-gate * Check the passed message number for legality and proper flags. 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate static int 4177c478bd9Sstevel@tonic-gate check(int mesg, int f) 4187c478bd9Sstevel@tonic-gate { 4197c478bd9Sstevel@tonic-gate register struct message *mp; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (mesg < 1 || mesg > msgCount) { 4227c478bd9Sstevel@tonic-gate printf(gettext("%d: Invalid message number\n"), mesg); 4237c478bd9Sstevel@tonic-gate return (-1); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate mp = &message[mesg-1]; 4267c478bd9Sstevel@tonic-gate if ((mp->m_flag & MDELETED) != f) { 4277c478bd9Sstevel@tonic-gate printf(gettext("%d: Inappropriate message\n"), mesg); 4287c478bd9Sstevel@tonic-gate return (-1); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate return (0); 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * Scan out the list of string arguments, shell style 4357c478bd9Sstevel@tonic-gate * for a RAWLIST. 4367c478bd9Sstevel@tonic-gate */ 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate int 4397c478bd9Sstevel@tonic-gate getrawlist(char line[], char **argv, int argc) 4407c478bd9Sstevel@tonic-gate { 4417c478bd9Sstevel@tonic-gate register char **ap, *cp, *cp2; 4427c478bd9Sstevel@tonic-gate char linebuf[LINESIZE], quotec; 4437c478bd9Sstevel@tonic-gate register char **last; 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate ap = argv; 4467c478bd9Sstevel@tonic-gate cp = line; 4477c478bd9Sstevel@tonic-gate last = argv + argc - 1; 4487c478bd9Sstevel@tonic-gate while (*cp != '\0') { 4497c478bd9Sstevel@tonic-gate while (any(*cp, " \t")) 4507c478bd9Sstevel@tonic-gate cp++; 4517c478bd9Sstevel@tonic-gate cp2 = linebuf; 4527c478bd9Sstevel@tonic-gate quotec = 0; 4537c478bd9Sstevel@tonic-gate while (*cp != '\0') { 4547c478bd9Sstevel@tonic-gate if (quotec) { 4557c478bd9Sstevel@tonic-gate if (*cp == quotec) { 4567c478bd9Sstevel@tonic-gate quotec = 0; 4577c478bd9Sstevel@tonic-gate cp++; 4587c478bd9Sstevel@tonic-gate } else 4597c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 4607c478bd9Sstevel@tonic-gate } else { 4617c478bd9Sstevel@tonic-gate if (*cp == '\\') { 4627c478bd9Sstevel@tonic-gate if (*(cp+1) != '\0') { 4637c478bd9Sstevel@tonic-gate *cp2++ = *++cp; 4647c478bd9Sstevel@tonic-gate cp++; 4657c478bd9Sstevel@tonic-gate } else { 4667c478bd9Sstevel@tonic-gate printf(gettext( 4677c478bd9Sstevel@tonic-gate "Trailing \\; ignoring\n")); 4687c478bd9Sstevel@tonic-gate break; 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate if (any(*cp, " \t")) 4727c478bd9Sstevel@tonic-gate break; 4737c478bd9Sstevel@tonic-gate if (any(*cp, "'\"")) 4747c478bd9Sstevel@tonic-gate quotec = *cp++; 4757c478bd9Sstevel@tonic-gate else 4767c478bd9Sstevel@tonic-gate *cp2++ = *cp++; 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate *cp2 = '\0'; 4807c478bd9Sstevel@tonic-gate if (cp2 == linebuf) 4817c478bd9Sstevel@tonic-gate break; 4827c478bd9Sstevel@tonic-gate if (ap >= last) { 483eb2b0a61Sas145665 printf(gettext("Too many elements in the list;" 484eb2b0a61Sas145665 " excess discarded\n")); 4857c478bd9Sstevel@tonic-gate break; 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate *ap++ = savestr(linebuf); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate *ap = NOSTR; 4907c478bd9Sstevel@tonic-gate return (ap-argv); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * scan out a single lexical item and return its token number, 4957c478bd9Sstevel@tonic-gate * updating the string pointer passed **p. Also, store the value 4967c478bd9Sstevel@tonic-gate * of the number or string scanned in lexnumber or lexstring as 4977c478bd9Sstevel@tonic-gate * appropriate. In any event, store the scanned `thing' in lexstring. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate 5007c478bd9Sstevel@tonic-gate static struct lex { 5017c478bd9Sstevel@tonic-gate char l_char; 5027c478bd9Sstevel@tonic-gate char l_token; 5037c478bd9Sstevel@tonic-gate } singles[] = { 5047c478bd9Sstevel@tonic-gate '$', TDOLLAR, 5057c478bd9Sstevel@tonic-gate '.', TDOT, 5067c478bd9Sstevel@tonic-gate '^', TUP, 5077c478bd9Sstevel@tonic-gate '*', TSTAR, 5087c478bd9Sstevel@tonic-gate '-', TDASH, 5097c478bd9Sstevel@tonic-gate '+', TPLUS, 5107c478bd9Sstevel@tonic-gate '(', TOPEN, 5117c478bd9Sstevel@tonic-gate ')', TCLOSE, 5127c478bd9Sstevel@tonic-gate 0, 0 5137c478bd9Sstevel@tonic-gate }; 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate static int 5167c478bd9Sstevel@tonic-gate scan(char **sp) 5177c478bd9Sstevel@tonic-gate { 5187c478bd9Sstevel@tonic-gate register char *cp, *cp2; 5197c478bd9Sstevel@tonic-gate register char c; 5207c478bd9Sstevel@tonic-gate register struct lex *lp; 5217c478bd9Sstevel@tonic-gate int quotec; 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (regretp >= 0) { 5247c478bd9Sstevel@tonic-gate copy(stringstack[regretp], lexstring); 5257c478bd9Sstevel@tonic-gate lexnumber = numberstack[regretp]; 5267c478bd9Sstevel@tonic-gate return (regretstack[regretp--]); 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate cp = *sp; 5297c478bd9Sstevel@tonic-gate cp2 = lexstring; 5307c478bd9Sstevel@tonic-gate c = *cp++; 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate /* 5337c478bd9Sstevel@tonic-gate * strip away leading white space. 5347c478bd9Sstevel@tonic-gate */ 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate while (any(c, " \t")) 5377c478bd9Sstevel@tonic-gate c = *cp++; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate /* 5407c478bd9Sstevel@tonic-gate * If no characters remain, we are at end of line, 5417c478bd9Sstevel@tonic-gate * so report that. 5427c478bd9Sstevel@tonic-gate */ 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate if (c == '\0') { 5457c478bd9Sstevel@tonic-gate *sp = --cp; 5467c478bd9Sstevel@tonic-gate return (TEOL); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* 5507c478bd9Sstevel@tonic-gate * If the leading character is a digit, scan 5517c478bd9Sstevel@tonic-gate * the number and convert it on the fly. 5527c478bd9Sstevel@tonic-gate * Return TNUMBER when done. 5537c478bd9Sstevel@tonic-gate */ 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate if (isdigit(c)) { 5567c478bd9Sstevel@tonic-gate lexnumber = 0; 5577c478bd9Sstevel@tonic-gate while (isdigit(c)) { 5587c478bd9Sstevel@tonic-gate lexnumber = lexnumber*10 + c - '0'; 5597c478bd9Sstevel@tonic-gate *cp2++ = c; 5607c478bd9Sstevel@tonic-gate c = *cp++; 5617c478bd9Sstevel@tonic-gate } 5627c478bd9Sstevel@tonic-gate *cp2 = '\0'; 5637c478bd9Sstevel@tonic-gate *sp = --cp; 5647c478bd9Sstevel@tonic-gate return (TNUMBER); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * Check for single character tokens; return such 5697c478bd9Sstevel@tonic-gate * if found. 5707c478bd9Sstevel@tonic-gate */ 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate for (lp = &singles[0]; lp->l_char != 0; lp++) 5737c478bd9Sstevel@tonic-gate if (c == lp->l_char) { 5747c478bd9Sstevel@tonic-gate lexstring[0] = c; 5757c478bd9Sstevel@tonic-gate lexstring[1] = '\0'; 5767c478bd9Sstevel@tonic-gate *sp = cp; 5777c478bd9Sstevel@tonic-gate return (lp->l_token); 5787c478bd9Sstevel@tonic-gate } 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate /* 5817c478bd9Sstevel@tonic-gate * We've got a string! Copy all the characters 5827c478bd9Sstevel@tonic-gate * of the string into lexstring, until we see 5837c478bd9Sstevel@tonic-gate * a null, space, or tab. 5847c478bd9Sstevel@tonic-gate * If the lead character is a " or ', save it 5857c478bd9Sstevel@tonic-gate * and scan until you get another. 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate 5887c478bd9Sstevel@tonic-gate quotec = 0; 5897c478bd9Sstevel@tonic-gate if (any(c, "'\"")) { 5907c478bd9Sstevel@tonic-gate quotec = c; 5917c478bd9Sstevel@tonic-gate c = *cp++; 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate while (c != '\0') { 5947c478bd9Sstevel@tonic-gate if (quotec == 0 && c == '\\') { 5957c478bd9Sstevel@tonic-gate if (*cp != '\0') { 5967c478bd9Sstevel@tonic-gate c = *cp++; 5977c478bd9Sstevel@tonic-gate } else { 5987c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Trailing \\; " 5997c478bd9Sstevel@tonic-gate "ignoring\n")); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate if (c == quotec) { 6037c478bd9Sstevel@tonic-gate cp++; 6047c478bd9Sstevel@tonic-gate break; 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate if (quotec == 0 && any(c, " \t")) 6077c478bd9Sstevel@tonic-gate break; 6087c478bd9Sstevel@tonic-gate if (cp2 - lexstring < STRINGLEN-1) 6097c478bd9Sstevel@tonic-gate *cp2++ = c; 6107c478bd9Sstevel@tonic-gate c = *cp++; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate if (quotec && c == 0) 6137c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Missing %c\n"), quotec); 6147c478bd9Sstevel@tonic-gate *sp = --cp; 6157c478bd9Sstevel@tonic-gate *cp2 = '\0'; 6167c478bd9Sstevel@tonic-gate return (TSTRING); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate /* 6207c478bd9Sstevel@tonic-gate * Unscan the named token by pushing it onto the regret stack. 6217c478bd9Sstevel@tonic-gate */ 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate static void 6247c478bd9Sstevel@tonic-gate regret(int token) 6257c478bd9Sstevel@tonic-gate { 6267c478bd9Sstevel@tonic-gate if (++regretp >= REGDEP) 6277c478bd9Sstevel@tonic-gate panic("Too many regrets"); 6287c478bd9Sstevel@tonic-gate regretstack[regretp] = token; 6297c478bd9Sstevel@tonic-gate lexstring[STRINGLEN-1] = '\0'; 6307c478bd9Sstevel@tonic-gate stringstack[regretp] = savestr(lexstring); 6317c478bd9Sstevel@tonic-gate numberstack[regretp] = lexnumber; 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate /* 6357c478bd9Sstevel@tonic-gate * Reset all the scanner global variables. 6367c478bd9Sstevel@tonic-gate */ 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate static void 6397c478bd9Sstevel@tonic-gate scaninit(void) 6407c478bd9Sstevel@tonic-gate { 6417c478bd9Sstevel@tonic-gate regretp = -1; 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * Find the first message whose flags & m == f and return 6467c478bd9Sstevel@tonic-gate * its message number. 6477c478bd9Sstevel@tonic-gate */ 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate int 6507c478bd9Sstevel@tonic-gate first(int f, int m) 6517c478bd9Sstevel@tonic-gate { 6527c478bd9Sstevel@tonic-gate register int mesg; 6537c478bd9Sstevel@tonic-gate register struct message *mp; 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate mesg = dot - &message[0] + 1; 6567c478bd9Sstevel@tonic-gate f &= MDELETED; 6577c478bd9Sstevel@tonic-gate m &= MDELETED; 6587c478bd9Sstevel@tonic-gate for (mp = dot; mp < &message[msgCount]; mp++) { 6597c478bd9Sstevel@tonic-gate if ((mp->m_flag & m) == f) 6607c478bd9Sstevel@tonic-gate return (mesg); 6617c478bd9Sstevel@tonic-gate mesg++; 6627c478bd9Sstevel@tonic-gate } 6637c478bd9Sstevel@tonic-gate mesg = dot - &message[0]; 6647c478bd9Sstevel@tonic-gate for (mp = dot-1; mp >= &message[0]; mp--) { 6657c478bd9Sstevel@tonic-gate if ((mp->m_flag & m) == f) 6667c478bd9Sstevel@tonic-gate return (mesg); 6677c478bd9Sstevel@tonic-gate mesg--; 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate return (NULL); 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* 6737c478bd9Sstevel@tonic-gate * See if the passed name sent the passed message number. Return true 6747c478bd9Sstevel@tonic-gate * if so. 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate static int 6777c478bd9Sstevel@tonic-gate sender(char *str, int mesg) 6787c478bd9Sstevel@tonic-gate { 6797c478bd9Sstevel@tonic-gate return (samebody(str, skin(nameof(&message[mesg-1])), TRUE)); 6807c478bd9Sstevel@tonic-gate } 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate /* 6837c478bd9Sstevel@tonic-gate * See if the given string matches inside the subject field of the 6847c478bd9Sstevel@tonic-gate * given message. For the purpose of the scan, we ignore case differences. 6857c478bd9Sstevel@tonic-gate * If it does, return true. The string search argument is assumed to 6867c478bd9Sstevel@tonic-gate * have the form "/search-string." If it is of the form "/," we use the 6877c478bd9Sstevel@tonic-gate * previous search string. 6887c478bd9Sstevel@tonic-gate */ 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate static char lastscan[128]; 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate static int 6937c478bd9Sstevel@tonic-gate matchsubj(char *str, int mesg) 6947c478bd9Sstevel@tonic-gate { 6957c478bd9Sstevel@tonic-gate register struct message *mp; 6967c478bd9Sstevel@tonic-gate register char *cp, *cp2, *backup; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate str++; 6997c478bd9Sstevel@tonic-gate if (strlen(str) == 0) 7007c478bd9Sstevel@tonic-gate str = lastscan; 7017c478bd9Sstevel@tonic-gate else 7027c478bd9Sstevel@tonic-gate nstrcpy(lastscan, sizeof (lastscan), str); 7037c478bd9Sstevel@tonic-gate mp = &message[mesg-1]; 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate /* 7067c478bd9Sstevel@tonic-gate * Now look, ignoring case, for the word in the string. 7077c478bd9Sstevel@tonic-gate */ 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate cp = str; 7107c478bd9Sstevel@tonic-gate cp2 = hfield("subject", mp, addone); 7117c478bd9Sstevel@tonic-gate if (cp2 == NOSTR) 7127c478bd9Sstevel@tonic-gate return (0); 7137c478bd9Sstevel@tonic-gate backup = cp2; 7147c478bd9Sstevel@tonic-gate while (*cp2) { 7157c478bd9Sstevel@tonic-gate if (*cp == 0) 7167c478bd9Sstevel@tonic-gate return (1); 7177c478bd9Sstevel@tonic-gate if (toupper(*cp++) != toupper(*cp2++)) { 7187c478bd9Sstevel@tonic-gate cp2 = ++backup; 7197c478bd9Sstevel@tonic-gate cp = str; 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate return (*cp == 0); 7237c478bd9Sstevel@tonic-gate } 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate /* 7267c478bd9Sstevel@tonic-gate * Mark the named message by setting its mark bit. 7277c478bd9Sstevel@tonic-gate */ 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate static void 7307c478bd9Sstevel@tonic-gate mark(int mesg) 7317c478bd9Sstevel@tonic-gate { 7327c478bd9Sstevel@tonic-gate register int i; 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate i = mesg; 7357c478bd9Sstevel@tonic-gate if (i < 1 || i > msgCount) 7367c478bd9Sstevel@tonic-gate panic("Bad message number to mark"); 7377c478bd9Sstevel@tonic-gate message[i-1].m_flag |= MMARK; 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate /* 7417c478bd9Sstevel@tonic-gate * Unmark the named message. 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate static void 7457c478bd9Sstevel@tonic-gate unmark(int mesg) 7467c478bd9Sstevel@tonic-gate { 7477c478bd9Sstevel@tonic-gate register int i; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate i = mesg; 7507c478bd9Sstevel@tonic-gate if (i < 1 || i > msgCount) 7517c478bd9Sstevel@tonic-gate panic("Bad message number to unmark"); 7527c478bd9Sstevel@tonic-gate message[i-1].m_flag &= ~MMARK; 7537c478bd9Sstevel@tonic-gate } 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate /* 7567c478bd9Sstevel@tonic-gate * Return the message number corresponding to the passed meta character. 7577c478bd9Sstevel@tonic-gate */ 7587c478bd9Sstevel@tonic-gate static int 7597c478bd9Sstevel@tonic-gate metamess(int meta, int f) 7607c478bd9Sstevel@tonic-gate { 7617c478bd9Sstevel@tonic-gate register int c, m; 7627c478bd9Sstevel@tonic-gate register struct message *mp; 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate c = meta; 7657c478bd9Sstevel@tonic-gate switch (c) { 7667c478bd9Sstevel@tonic-gate case '^': 7677c478bd9Sstevel@tonic-gate /* 7687c478bd9Sstevel@tonic-gate * First 'good' message left. 7697c478bd9Sstevel@tonic-gate */ 7707c478bd9Sstevel@tonic-gate for (mp = &message[0]; mp < &message[msgCount]; mp++) 7717c478bd9Sstevel@tonic-gate if ((mp->m_flag & MDELETED) == f) 7727c478bd9Sstevel@tonic-gate return (mp - &message[0] + 1); 7737c478bd9Sstevel@tonic-gate printf(gettext("No applicable messages\n")); 7747c478bd9Sstevel@tonic-gate return (-1); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate case '+': 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * Next 'good' message left. 7797c478bd9Sstevel@tonic-gate */ 7807c478bd9Sstevel@tonic-gate for (mp = dot + 1; mp < &message[msgCount]; mp++) 7817c478bd9Sstevel@tonic-gate if ((mp->m_flag & MDELETED) == f) 7827c478bd9Sstevel@tonic-gate return (mp - &message[0] + 1); 7837c478bd9Sstevel@tonic-gate printf(gettext("Referencing beyond last message\n")); 7847c478bd9Sstevel@tonic-gate return (-1); 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate case '-': 7877c478bd9Sstevel@tonic-gate /* 7887c478bd9Sstevel@tonic-gate * Previous 'good' message. 7897c478bd9Sstevel@tonic-gate */ 7907c478bd9Sstevel@tonic-gate for (mp = dot - 1; mp >= &message[0]; mp--) 7917c478bd9Sstevel@tonic-gate if ((mp->m_flag & MDELETED) == f) 7927c478bd9Sstevel@tonic-gate return (mp - &message[0] + 1); 7937c478bd9Sstevel@tonic-gate printf(gettext("Referencing before first message\n")); 7947c478bd9Sstevel@tonic-gate return (-1); 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate case '$': 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * Last 'good message left. 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate for (mp = &message[msgCount-1]; mp >= &message[0]; mp--) 8017c478bd9Sstevel@tonic-gate if ((mp->m_flag & MDELETED) == f) 8027c478bd9Sstevel@tonic-gate return (mp - &message[0] + 1); 8037c478bd9Sstevel@tonic-gate printf(gettext("No applicable messages\n")); 8047c478bd9Sstevel@tonic-gate return (-1); 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate case '.': 8077c478bd9Sstevel@tonic-gate /* 8087c478bd9Sstevel@tonic-gate * Current message. 8097c478bd9Sstevel@tonic-gate */ 8107c478bd9Sstevel@tonic-gate m = dot - &message[0] + 1; 8117c478bd9Sstevel@tonic-gate if ((dot->m_flag & MDELETED) != f) { 8127c478bd9Sstevel@tonic-gate printf(gettext("%d: Inappropriate message\n"), m); 8137c478bd9Sstevel@tonic-gate return (-1); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate return (m); 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate default: 8187c478bd9Sstevel@tonic-gate printf(gettext("Unknown metachar (%c)\n"), c); 8197c478bd9Sstevel@tonic-gate return (-1); 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate } 822