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
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
22*196c7f05SJoshua M. Clulow
23*196c7f05SJoshua M. Clulow /*
24*196c7f05SJoshua M. Clulow * Copyright 2014 Joyent, Inc.
25*196c7f05SJoshua M. Clulow */
26*196c7f05SJoshua M. Clulow
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * Copyright 1995 Sun Microsystems, Inc. All rights reserved.
297c478bd9Sstevel@tonic-gate * Use is subject to license terms.
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
337c478bd9Sstevel@tonic-gate /* All Rights Reserved */
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
387c478bd9Sstevel@tonic-gate * The Regents of the University of California
397c478bd9Sstevel@tonic-gate * All Rights Reserved
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
427c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
437c478bd9Sstevel@tonic-gate * contributors.
447c478bd9Sstevel@tonic-gate */
457c478bd9Sstevel@tonic-gate
46*196c7f05SJoshua M. Clulow #include <err.h>
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate #include "rcv.h"
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate * mailx -- a modified version of a University of California at Berkeley
527c478bd9Sstevel@tonic-gate * mail program
537c478bd9Sstevel@tonic-gate *
547c478bd9Sstevel@tonic-gate * Routines for processing and detecting headlines.
557c478bd9Sstevel@tonic-gate */
567c478bd9Sstevel@tonic-gate
57*196c7f05SJoshua M. Clulow static int nextword(const char *, custr_t *, const char **);
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate * See if the passed line buffer is a mail header.
617c478bd9Sstevel@tonic-gate * Return true if yes.
627c478bd9Sstevel@tonic-gate */
63*196c7f05SJoshua M. Clulow boolean_t
is_headline(const char * linebuf)64*196c7f05SJoshua M. Clulow is_headline(const char *linebuf)
657c478bd9Sstevel@tonic-gate {
66*196c7f05SJoshua M. Clulow headline_t *hl;
67*196c7f05SJoshua M. Clulow boolean_t ret;
687c478bd9Sstevel@tonic-gate
69*196c7f05SJoshua M. Clulow if (strncmp("From ", linebuf, 5) != 0) {
70*196c7f05SJoshua M. Clulow return (B_FALSE);
717c478bd9Sstevel@tonic-gate }
72*196c7f05SJoshua M. Clulow
73*196c7f05SJoshua M. Clulow if (headline_alloc(&hl) != 0 || parse_headline(linebuf, hl) != 0) {
74*196c7f05SJoshua M. Clulow err(1, "could not parse headline");
75*196c7f05SJoshua M. Clulow }
76*196c7f05SJoshua M. Clulow
77*196c7f05SJoshua M. Clulow ret = custr_len(hl->hl_from) > 0 ? B_TRUE : B_FALSE;
78*196c7f05SJoshua M. Clulow
79*196c7f05SJoshua M. Clulow headline_free(hl);
80*196c7f05SJoshua M. Clulow return (ret);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /*
84*196c7f05SJoshua M. Clulow * Manage headline_t objects:
857c478bd9Sstevel@tonic-gate */
867c478bd9Sstevel@tonic-gate void
headline_free(headline_t * hl)87*196c7f05SJoshua M. Clulow headline_free(headline_t *hl)
887c478bd9Sstevel@tonic-gate {
89*196c7f05SJoshua M. Clulow custr_free(hl->hl_from);
90*196c7f05SJoshua M. Clulow custr_free(hl->hl_tty);
91*196c7f05SJoshua M. Clulow custr_free(hl->hl_date);
92*196c7f05SJoshua M. Clulow free(hl);
93*196c7f05SJoshua M. Clulow }
947c478bd9Sstevel@tonic-gate
95*196c7f05SJoshua M. Clulow int
headline_alloc(headline_t ** hl)96*196c7f05SJoshua M. Clulow headline_alloc(headline_t **hl)
97*196c7f05SJoshua M. Clulow {
98*196c7f05SJoshua M. Clulow int en;
99*196c7f05SJoshua M. Clulow headline_t *t;
1007c478bd9Sstevel@tonic-gate
101*196c7f05SJoshua M. Clulow if ((t = calloc(1, sizeof (*t))) == NULL) {
102*196c7f05SJoshua M. Clulow return (-1);
103*196c7f05SJoshua M. Clulow }
1047c478bd9Sstevel@tonic-gate
105*196c7f05SJoshua M. Clulow if (custr_alloc(&t->hl_from) != 0 || custr_alloc(&t->hl_tty) != 0 ||
106*196c7f05SJoshua M. Clulow custr_alloc(&t->hl_date) != 0) {
107*196c7f05SJoshua M. Clulow en = errno;
108*196c7f05SJoshua M. Clulow
109*196c7f05SJoshua M. Clulow headline_free(t);
110*196c7f05SJoshua M. Clulow
111*196c7f05SJoshua M. Clulow errno = en;
112*196c7f05SJoshua M. Clulow return (-1);
113*196c7f05SJoshua M. Clulow }
114*196c7f05SJoshua M. Clulow
115*196c7f05SJoshua M. Clulow *hl = t;
116*196c7f05SJoshua M. Clulow return (0);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /*
120*196c7f05SJoshua M. Clulow * Clear all of the strings in a headline_t:
1217c478bd9Sstevel@tonic-gate */
122*196c7f05SJoshua M. Clulow void
headline_reset(headline_t * hl)123*196c7f05SJoshua M. Clulow headline_reset(headline_t *hl)
1247c478bd9Sstevel@tonic-gate {
125*196c7f05SJoshua M. Clulow custr_reset(hl->hl_from);
126*196c7f05SJoshua M. Clulow custr_reset(hl->hl_tty);
127*196c7f05SJoshua M. Clulow custr_reset(hl->hl_date);
128*196c7f05SJoshua M. Clulow }
1297c478bd9Sstevel@tonic-gate
130*196c7f05SJoshua M. Clulow int
parse_headline(const char * line,headline_t * hl)131*196c7f05SJoshua M. Clulow parse_headline(const char *line, headline_t *hl)
132*196c7f05SJoshua M. Clulow {
133*196c7f05SJoshua M. Clulow const char *c = line;
134*196c7f05SJoshua M. Clulow
135*196c7f05SJoshua M. Clulow headline_reset(hl);
136*196c7f05SJoshua M. Clulow
137*196c7f05SJoshua M. Clulow /*
138*196c7f05SJoshua M. Clulow * Load the first word from the line and ensure that it is "From".
139*196c7f05SJoshua M. Clulow */
140*196c7f05SJoshua M. Clulow if (nextword(c, hl->hl_from, &c) != 0) {
141*196c7f05SJoshua M. Clulow return (-1);
142*196c7f05SJoshua M. Clulow }
143*196c7f05SJoshua M. Clulow if (strcmp(custr_cstr(hl->hl_from), "From") != 0) {
144*196c7f05SJoshua M. Clulow errno = EINVAL;
145*196c7f05SJoshua M. Clulow return (-1);
146*196c7f05SJoshua M. Clulow }
147*196c7f05SJoshua M. Clulow custr_reset(hl->hl_from);
148*196c7f05SJoshua M. Clulow
149*196c7f05SJoshua M. Clulow /*
150*196c7f05SJoshua M. Clulow * The next word will be the From address.
151*196c7f05SJoshua M. Clulow */
152*196c7f05SJoshua M. Clulow if (nextword(c, hl->hl_from, &c) != 0) {
153*196c7f05SJoshua M. Clulow return (-1);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate /*
157*196c7f05SJoshua M. Clulow * If there is a next word, the rest of the string is the Date.
1587c478bd9Sstevel@tonic-gate */
159*196c7f05SJoshua M. Clulow if (c != NULL) {
160*196c7f05SJoshua M. Clulow if (custr_append(hl->hl_date, c) != 0) {
161*196c7f05SJoshua M. Clulow return (-1);
1627c478bd9Sstevel@tonic-gate }
163*196c7f05SJoshua M. Clulow }
164*196c7f05SJoshua M. Clulow
165*196c7f05SJoshua M. Clulow errno = 0;
166*196c7f05SJoshua M. Clulow return (0);
167*196c7f05SJoshua M. Clulow }
168*196c7f05SJoshua M. Clulow
169*196c7f05SJoshua M. Clulow /*
170*196c7f05SJoshua M. Clulow * Collect a space- or tab-delimited word into the word buffer, if one is
171*196c7f05SJoshua M. Clulow * passed. The double quote character (") can be used to include whitespace
172*196c7f05SJoshua M. Clulow * within a word. Set "nextword" to the location of the first character of the
173*196c7f05SJoshua M. Clulow * _next_ word, or NULL if there were no more words. Returns 0 on success or
174*196c7f05SJoshua M. Clulow * -1 otherwise.
175*196c7f05SJoshua M. Clulow */
176*196c7f05SJoshua M. Clulow static int
nextword(const char * input,custr_t * word,const char ** nextword)177*196c7f05SJoshua M. Clulow nextword(const char *input, custr_t *word, const char **nextword)
178*196c7f05SJoshua M. Clulow {
179*196c7f05SJoshua M. Clulow boolean_t in_quotes = B_FALSE;
180*196c7f05SJoshua M. Clulow const char *c = input != NULL ? input : "";
181*196c7f05SJoshua M. Clulow
182*196c7f05SJoshua M. Clulow /*
183*196c7f05SJoshua M. Clulow * Collect the first word into the word buffer, if one is provided.
184*196c7f05SJoshua M. Clulow */
185*196c7f05SJoshua M. Clulow for (;;) {
186*196c7f05SJoshua M. Clulow if (*c == '\0') {
187*196c7f05SJoshua M. Clulow /*
188*196c7f05SJoshua M. Clulow * We have reached the end of the string.
189*196c7f05SJoshua M. Clulow */
190*196c7f05SJoshua M. Clulow *nextword = NULL;
191*196c7f05SJoshua M. Clulow return (0);
192*196c7f05SJoshua M. Clulow }
193*196c7f05SJoshua M. Clulow
194*196c7f05SJoshua M. Clulow if (*c == '"') {
195*196c7f05SJoshua M. Clulow /*
196*196c7f05SJoshua M. Clulow * Either beginning or ending a quoted string.
197*196c7f05SJoshua M. Clulow */
198*196c7f05SJoshua M. Clulow in_quotes = in_quotes ? B_FALSE : B_TRUE;
199*196c7f05SJoshua M. Clulow }
200*196c7f05SJoshua M. Clulow
201*196c7f05SJoshua M. Clulow if (!in_quotes && (*c == ' ' || *c == '\t')) {
202*196c7f05SJoshua M. Clulow /*
203*196c7f05SJoshua M. Clulow * We have reached a whitespace region.
204*196c7f05SJoshua M. Clulow */
205*196c7f05SJoshua M. Clulow break;
206*196c7f05SJoshua M. Clulow }
207*196c7f05SJoshua M. Clulow
208*196c7f05SJoshua M. Clulow /*
209*196c7f05SJoshua M. Clulow * Copy this character into the word buffer.
210*196c7f05SJoshua M. Clulow */
211*196c7f05SJoshua M. Clulow if (word != NULL) {
212*196c7f05SJoshua M. Clulow if (custr_appendc(word, *c) != 0) {
213*196c7f05SJoshua M. Clulow return (-1);
214*196c7f05SJoshua M. Clulow }
215*196c7f05SJoshua M. Clulow }
216*196c7f05SJoshua M. Clulow c++;
217*196c7f05SJoshua M. Clulow }
218*196c7f05SJoshua M. Clulow
219*196c7f05SJoshua M. Clulow /*
220*196c7f05SJoshua M. Clulow * Find the beginning of the next word, if there is one.
221*196c7f05SJoshua M. Clulow */
222*196c7f05SJoshua M. Clulow for (;;) {
223*196c7f05SJoshua M. Clulow if (*c == '\0') {
224*196c7f05SJoshua M. Clulow /*
225*196c7f05SJoshua M. Clulow * We have reached the end of the string.
226*196c7f05SJoshua M. Clulow */
227*196c7f05SJoshua M. Clulow *nextword = NULL;
228*196c7f05SJoshua M. Clulow return (0);
229*196c7f05SJoshua M. Clulow
230*196c7f05SJoshua M. Clulow } else if (*c != ' ' && *c != '\t') {
231*196c7f05SJoshua M. Clulow /*
232*196c7f05SJoshua M. Clulow * We have located the next word.
233*196c7f05SJoshua M. Clulow */
234*196c7f05SJoshua M. Clulow *nextword = c;
235*196c7f05SJoshua M. Clulow return (0);
236*196c7f05SJoshua M. Clulow }
237*196c7f05SJoshua M. Clulow c++;
238*196c7f05SJoshua M. Clulow }
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate /*
2427c478bd9Sstevel@tonic-gate * Copy str1 to str2, return pointer to null in str2.
2437c478bd9Sstevel@tonic-gate */
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate char *
copy(char * str1,char * str2)2467c478bd9Sstevel@tonic-gate copy(char *str1, char *str2)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate register char *s1, *s2;
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate s1 = str1;
2517c478bd9Sstevel@tonic-gate s2 = str2;
2527c478bd9Sstevel@tonic-gate while (*s1)
2537c478bd9Sstevel@tonic-gate *s2++ = *s1++;
2547c478bd9Sstevel@tonic-gate *s2 = 0;
2557c478bd9Sstevel@tonic-gate return(s2);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate * Is ch any of the characters in str?
2607c478bd9Sstevel@tonic-gate */
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate int
any(int ch,char * str)2637c478bd9Sstevel@tonic-gate any(int ch, char *str)
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate register char *f;
2666c83d09fSrobbin int c;
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate f = str;
2697c478bd9Sstevel@tonic-gate c = ch;
2707c478bd9Sstevel@tonic-gate while (*f)
2717c478bd9Sstevel@tonic-gate if (c == *f++)
2727c478bd9Sstevel@tonic-gate return(1);
2737c478bd9Sstevel@tonic-gate return(0);
2747c478bd9Sstevel@tonic-gate }
275