Example #1
0
// quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
const char* parse_quoted_string(unsigned char **p)
{
	unsigned char *ptmp = *p;
	int arr[4][4] =
	    { {1, -1, -1, -1},
	      {-1, 2, 99, 99},
	      {-1, -1, 3, 3},
	      {-1, -1, -1,-1} };

	int line = 0, state = 0;
	do {
		if (state == 0 && !parse_lws(p))
			line = 0;
		else if (!parse_dquote(p))
			line = 1;
		else if (!parse_qdtext(p) || parse_quoted_pair(p))
			line = 2;
		else
			line = 3;

		state = arr[line][state];
		if (-1 == state) {
			*p = ptmp;
			return ERR;
		}
	}
	while (state != 99);

	return NULL;
}
int wordexp(const char *words, wordexp_t * we, int flags)
{
	size_t words_offset;
	size_t word_length;
	size_t max_length;
	char *word = w_newword(&word_length, &max_length);
	int error;
	char *ifs;
	char ifs_white[4];
	wordexp_t old_word = *we;

	if (flags & WRDE_REUSE) {
		/* Minimal implementation of WRDE_REUSE for now */
		wordfree(we);
		old_word.we_wordv = NULL;
	}

	if ((flags & WRDE_APPEND) == 0) {
		we->we_wordc = 0;

		if (flags & WRDE_DOOFFS) {
			we->we_wordv = calloc(1 + we->we_offs, sizeof(char *));
			if (we->we_wordv == NULL) {
				error = WRDE_NOSPACE;
				goto do_error;
			}
		} else {
			we->we_wordv = calloc(1, sizeof(char *));
			if (we->we_wordv == NULL) {
				error = WRDE_NOSPACE;
				goto do_error;
			}

			we->we_offs = 0;
		}
	}

	/* Find out what the field separators are.
	 * There are two types: whitespace and non-whitespace.
	 */
	ifs = getenv("IFS");

	if (!ifs)
		/* IFS unset - use <space><tab><newline>. */
		ifs = strcpy(ifs_white, " \t\n");
	else {
		char *ifsch = ifs;
		char *whch = ifs_white;

		/* Start off with no whitespace IFS characters */
		ifs_white[0] = '\0';

		while (*ifsch != '\0') {
			if ((*ifsch == ' ') || (*ifsch == '\t') || (*ifsch == '\n')) {
				/* Whitespace IFS.  See first whether it is already in our
				   collection.  */
				char *runp = ifs_white;

				while (runp < whch && *runp != '\0' && *runp != *ifsch)
					++runp;

				if (runp == whch)
					*whch++ = *ifsch;
			}

			++ifsch;
		}
		*whch = '\0';
	}

	for (words_offset = 0; words[words_offset]; ++words_offset)
		switch (words[words_offset]) {
		case '\\':
			error = parse_backslash(&word, &word_length, &max_length, words,
								&words_offset);

			if (error)
				goto do_error;

			break;

		case '$':
			error = parse_dollars(&word, &word_length, &max_length, words,
								  &words_offset, flags, we, ifs, ifs_white,
								  0);

			if (error)
				goto do_error;

			break;

		case '`':
			if (flags & WRDE_NOCMD) {
				error = WRDE_CMDSUB;
				goto do_error;
			}

			++words_offset;
			error = parse_backtick(&word, &word_length, &max_length, words,
								   &words_offset, flags, we, ifs,
								   ifs_white);

			if (error)
				goto do_error;

			break;

		case '"':
			++words_offset;
			error = parse_dquote(&word, &word_length, &max_length, words,
								 &words_offset, flags, we, ifs, ifs_white);

			if (error)
				goto do_error;

			if (!word_length) {
				error = w_addword(we, NULL);

				if (error)
					return error;
			}

			break;

		case '\'':
			++words_offset;
			error = parse_squote(&word, &word_length, &max_length, words,
								 &words_offset);

			if (error)
				goto do_error;

			if (!word_length) {
				error = w_addword(we, NULL);

				if (error)
					return error;
			}

			break;

		case '~':
			error = parse_tilde(&word, &word_length, &max_length, words,
								&words_offset, we->we_wordc);

			if (error)
				goto do_error;

			break;

		case '*':
		case '[':
		case '?':
			error = parse_glob(&word, &word_length, &max_length, words,
							   &words_offset, flags, we, ifs, ifs_white);

			if (error)
				goto do_error;

			break;

		default:
			/* Is it a word separator? */
			if (strchr(" \t", words[words_offset]) == NULL) {
				char ch = words[words_offset];

				/* Not a word separator -- but is it a valid word char? */
				if (strchr("\n|&;<>(){}", ch)) {
					/* Fail */
					error = WRDE_BADCHAR;
					goto do_error;
				}

				/* "Ordinary" character -- add it to word */
				word = w_addchar(word, &word_length, &max_length, ch);
				if (word == NULL) {
					error = WRDE_NOSPACE;
					goto do_error;
				}

				break;
			}

			/* If a word has been delimited, add it to the list. */
			if (word != NULL) {
				error = w_addword(we, word);
				if (error)
					goto do_error;
			}

			word = w_newword(&word_length, &max_length);
		}

	/* End of string */

	/* There was a word separator at the end */
	if (word == NULL)			/* i.e. w_newword */
		return 0;

	/* There was no field separator at the end */
	return w_addword(we, word);

  do_error:
	/* Error:
	 *  free memory used (unless error is WRDE_NOSPACE), and
	 *  set we members back to what they were.
	 */

	free(word);

	if (error == WRDE_NOSPACE)
		return WRDE_NOSPACE;

	if ((flags & WRDE_APPEND) == 0)
		wordfree(we);

	*we = old_word;
	return error;
}