xref: /titanic_41/usr/src/cmd/mailx/head.c (revision 61d1e6c58253de1520313067e756b41e17a077cb)
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