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*61d1e6c5SJoshua M. Clulow
23*61d1e6c5SJoshua M. Clulow /*
24*61d1e6c5SJoshua M. Clulow * Copyright 2014 Joyent, Inc.
25*61d1e6c5SJoshua M. Clulow */
26*61d1e6c5SJoshua 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*61d1e6c5SJoshua 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*61d1e6c5SJoshua 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*61d1e6c5SJoshua M. Clulow boolean_t
is_headline(const char * linebuf)64*61d1e6c5SJoshua M. Clulow is_headline(const char *linebuf)
657c478bd9Sstevel@tonic-gate {
66*61d1e6c5SJoshua M. Clulow headline_t *hl;
67*61d1e6c5SJoshua M. Clulow boolean_t ret;
687c478bd9Sstevel@tonic-gate
69*61d1e6c5SJoshua M. Clulow if (strncmp("From ", linebuf, 5) != 0) {
70*61d1e6c5SJoshua M. Clulow return (B_FALSE);
717c478bd9Sstevel@tonic-gate }
72*61d1e6c5SJoshua M. Clulow
73*61d1e6c5SJoshua M. Clulow if (headline_alloc(&hl) != 0 || parse_headline(linebuf, hl) != 0) {
74*61d1e6c5SJoshua M. Clulow err(1, "could not parse headline");
75*61d1e6c5SJoshua M. Clulow }
76*61d1e6c5SJoshua M. Clulow
77*61d1e6c5SJoshua M. Clulow ret = custr_len(hl->hl_from) > 0 ? B_TRUE : B_FALSE;
78*61d1e6c5SJoshua M. Clulow
79*61d1e6c5SJoshua M. Clulow headline_free(hl);
80*61d1e6c5SJoshua M. Clulow return (ret);
817c478bd9Sstevel@tonic-gate }
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /*
84*61d1e6c5SJoshua M. Clulow * Manage headline_t objects:
857c478bd9Sstevel@tonic-gate */
867c478bd9Sstevel@tonic-gate void
headline_free(headline_t * hl)87*61d1e6c5SJoshua M. Clulow headline_free(headline_t *hl)
887c478bd9Sstevel@tonic-gate {
89*61d1e6c5SJoshua M. Clulow custr_free(hl->hl_from);
90*61d1e6c5SJoshua M. Clulow custr_free(hl->hl_tty);
91*61d1e6c5SJoshua M. Clulow custr_free(hl->hl_date);
92*61d1e6c5SJoshua M. Clulow free(hl);
93*61d1e6c5SJoshua M. Clulow }
947c478bd9Sstevel@tonic-gate
95*61d1e6c5SJoshua M. Clulow int
headline_alloc(headline_t ** hl)96*61d1e6c5SJoshua M. Clulow headline_alloc(headline_t **hl)
97*61d1e6c5SJoshua M. Clulow {
98*61d1e6c5SJoshua M. Clulow int en;
99*61d1e6c5SJoshua M. Clulow headline_t *t;
1007c478bd9Sstevel@tonic-gate
101*61d1e6c5SJoshua M. Clulow if ((t = calloc(1, sizeof (*t))) == NULL) {
102*61d1e6c5SJoshua M. Clulow return (-1);
103*61d1e6c5SJoshua M. Clulow }
1047c478bd9Sstevel@tonic-gate
105*61d1e6c5SJoshua M. Clulow if (custr_alloc(&t->hl_from) != 0 || custr_alloc(&t->hl_tty) != 0 ||
106*61d1e6c5SJoshua M. Clulow custr_alloc(&t->hl_date) != 0) {
107*61d1e6c5SJoshua M. Clulow en = errno;
108*61d1e6c5SJoshua M. Clulow
109*61d1e6c5SJoshua M. Clulow headline_free(t);
110*61d1e6c5SJoshua M. Clulow
111*61d1e6c5SJoshua M. Clulow errno = en;
112*61d1e6c5SJoshua M. Clulow return (-1);
113*61d1e6c5SJoshua M. Clulow }
114*61d1e6c5SJoshua M. Clulow
115*61d1e6c5SJoshua M. Clulow *hl = t;
116*61d1e6c5SJoshua M. Clulow return (0);
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /*
120*61d1e6c5SJoshua M. Clulow * Clear all of the strings in a headline_t:
1217c478bd9Sstevel@tonic-gate */
122*61d1e6c5SJoshua M. Clulow void
headline_reset(headline_t * hl)123*61d1e6c5SJoshua M. Clulow headline_reset(headline_t *hl)
1247c478bd9Sstevel@tonic-gate {
125*61d1e6c5SJoshua M. Clulow custr_reset(hl->hl_from);
126*61d1e6c5SJoshua M. Clulow custr_reset(hl->hl_tty);
127*61d1e6c5SJoshua M. Clulow custr_reset(hl->hl_date);
128*61d1e6c5SJoshua M. Clulow }
1297c478bd9Sstevel@tonic-gate
130*61d1e6c5SJoshua M. Clulow int
parse_headline(const char * line,headline_t * hl)131*61d1e6c5SJoshua M. Clulow parse_headline(const char *line, headline_t *hl)
132*61d1e6c5SJoshua M. Clulow {
133*61d1e6c5SJoshua M. Clulow const char *c = line;
134*61d1e6c5SJoshua M. Clulow
135*61d1e6c5SJoshua M. Clulow headline_reset(hl);
136*61d1e6c5SJoshua M. Clulow
137*61d1e6c5SJoshua M. Clulow /*
138*61d1e6c5SJoshua M. Clulow * Load the first word from the line and ensure that it is "From".
139*61d1e6c5SJoshua M. Clulow */
140*61d1e6c5SJoshua M. Clulow if (nextword(c, hl->hl_from, &c) != 0) {
141*61d1e6c5SJoshua M. Clulow return (-1);
142*61d1e6c5SJoshua M. Clulow }
143*61d1e6c5SJoshua M. Clulow if (strcmp(custr_cstr(hl->hl_from), "From") != 0) {
144*61d1e6c5SJoshua M. Clulow errno = EINVAL;
145*61d1e6c5SJoshua M. Clulow return (-1);
146*61d1e6c5SJoshua M. Clulow }
147*61d1e6c5SJoshua M. Clulow custr_reset(hl->hl_from);
148*61d1e6c5SJoshua M. Clulow
149*61d1e6c5SJoshua M. Clulow /*
150*61d1e6c5SJoshua M. Clulow * The next word will be the From address.
151*61d1e6c5SJoshua M. Clulow */
152*61d1e6c5SJoshua M. Clulow if (nextword(c, hl->hl_from, &c) != 0) {
153*61d1e6c5SJoshua M. Clulow return (-1);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate /*
157*61d1e6c5SJoshua M. Clulow * If there is a next word, the rest of the string is the Date.
1587c478bd9Sstevel@tonic-gate */
159*61d1e6c5SJoshua M. Clulow if (c != NULL) {
160*61d1e6c5SJoshua M. Clulow if (custr_append(hl->hl_date, c) != 0) {
161*61d1e6c5SJoshua M. Clulow return (-1);
1627c478bd9Sstevel@tonic-gate }
163*61d1e6c5SJoshua M. Clulow }
164*61d1e6c5SJoshua M. Clulow
165*61d1e6c5SJoshua M. Clulow errno = 0;
166*61d1e6c5SJoshua M. Clulow return (0);
167*61d1e6c5SJoshua M. Clulow }
168*61d1e6c5SJoshua M. Clulow
169*61d1e6c5SJoshua M. Clulow /*
170*61d1e6c5SJoshua M. Clulow * Collect a space- or tab-delimited word into the word buffer, if one is
171*61d1e6c5SJoshua M. Clulow * passed. The double quote character (") can be used to include whitespace
172*61d1e6c5SJoshua M. Clulow * within a word. Set "nextword" to the location of the first character of the
173*61d1e6c5SJoshua M. Clulow * _next_ word, or NULL if there were no more words. Returns 0 on success or
174*61d1e6c5SJoshua M. Clulow * -1 otherwise.
175*61d1e6c5SJoshua M. Clulow */
176*61d1e6c5SJoshua M. Clulow static int
nextword(const char * input,custr_t * word,const char ** nextword)177*61d1e6c5SJoshua M. Clulow nextword(const char *input, custr_t *word, const char **nextword)
178*61d1e6c5SJoshua M. Clulow {
179*61d1e6c5SJoshua M. Clulow boolean_t in_quotes = B_FALSE;
180*61d1e6c5SJoshua M. Clulow const char *c = input != NULL ? input : "";
181*61d1e6c5SJoshua M. Clulow
182*61d1e6c5SJoshua M. Clulow /*
183*61d1e6c5SJoshua M. Clulow * Collect the first word into the word buffer, if one is provided.
184*61d1e6c5SJoshua M. Clulow */
185*61d1e6c5SJoshua M. Clulow for (;;) {
186*61d1e6c5SJoshua M. Clulow if (*c == '\0') {
187*61d1e6c5SJoshua M. Clulow /*
188*61d1e6c5SJoshua M. Clulow * We have reached the end of the string.
189*61d1e6c5SJoshua M. Clulow */
190*61d1e6c5SJoshua M. Clulow *nextword = NULL;
191*61d1e6c5SJoshua M. Clulow return (0);
192*61d1e6c5SJoshua M. Clulow }
193*61d1e6c5SJoshua M. Clulow
194*61d1e6c5SJoshua M. Clulow if (*c == '"') {
195*61d1e6c5SJoshua M. Clulow /*
196*61d1e6c5SJoshua M. Clulow * Either beginning or ending a quoted string.
197*61d1e6c5SJoshua M. Clulow */
198*61d1e6c5SJoshua M. Clulow in_quotes = in_quotes ? B_FALSE : B_TRUE;
199*61d1e6c5SJoshua M. Clulow }
200*61d1e6c5SJoshua M. Clulow
201*61d1e6c5SJoshua M. Clulow if (!in_quotes && (*c == ' ' || *c == '\t')) {
202*61d1e6c5SJoshua M. Clulow /*
203*61d1e6c5SJoshua M. Clulow * We have reached a whitespace region.
204*61d1e6c5SJoshua M. Clulow */
205*61d1e6c5SJoshua M. Clulow break;
206*61d1e6c5SJoshua M. Clulow }
207*61d1e6c5SJoshua M. Clulow
208*61d1e6c5SJoshua M. Clulow /*
209*61d1e6c5SJoshua M. Clulow * Copy this character into the word buffer.
210*61d1e6c5SJoshua M. Clulow */
211*61d1e6c5SJoshua M. Clulow if (word != NULL) {
212*61d1e6c5SJoshua M. Clulow if (custr_appendc(word, *c) != 0) {
213*61d1e6c5SJoshua M. Clulow return (-1);
214*61d1e6c5SJoshua M. Clulow }
215*61d1e6c5SJoshua M. Clulow }
216*61d1e6c5SJoshua M. Clulow c++;
217*61d1e6c5SJoshua M. Clulow }
218*61d1e6c5SJoshua M. Clulow
219*61d1e6c5SJoshua M. Clulow /*
220*61d1e6c5SJoshua M. Clulow * Find the beginning of the next word, if there is one.
221*61d1e6c5SJoshua M. Clulow */
222*61d1e6c5SJoshua M. Clulow for (;;) {
223*61d1e6c5SJoshua M. Clulow if (*c == '\0') {
224*61d1e6c5SJoshua M. Clulow /*
225*61d1e6c5SJoshua M. Clulow * We have reached the end of the string.
226*61d1e6c5SJoshua M. Clulow */
227*61d1e6c5SJoshua M. Clulow *nextword = NULL;
228*61d1e6c5SJoshua M. Clulow return (0);
229*61d1e6c5SJoshua M. Clulow
230*61d1e6c5SJoshua M. Clulow } else if (*c != ' ' && *c != '\t') {
231*61d1e6c5SJoshua M. Clulow /*
232*61d1e6c5SJoshua M. Clulow * We have located the next word.
233*61d1e6c5SJoshua M. Clulow */
234*61d1e6c5SJoshua M. Clulow *nextword = c;
235*61d1e6c5SJoshua M. Clulow return (0);
236*61d1e6c5SJoshua M. Clulow }
237*61d1e6c5SJoshua M. Clulow c++;
238*61d1e6c5SJoshua 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