Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / nfs-utils / utils / mount / token.c
blob5ef960477698c6625b388cdd754f62b467eaaf6b
1 /*
2 * token.c -- tokenize strings, a la strtok(3)
4 * Copyright (C) 2007 Oracle. All rights reserved.
5 * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public
18 * License along with this program; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 021110-1307, USA.
25 * We've constructed a simple string tokenizer that is better than
26 * strtok(3) in several ways:
28 * 1. It doesn't interfere with ongoing tokenizations using strtok(3).
29 * 2. It's re-entrant so we can nest tokenizations, if needed.
30 * 3. It can handle double-quoted delimiters (needed for 'context="sd,fslj"').
31 * 4. It doesn't alter the string we're tokenizing, so it can work
32 * on write-protected strings as well as writable strings.
36 #include <ctype.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <errno.h>
43 #include "token.h"
46 struct tokenizer_state {
47 char *pos;
48 char delimiter;
49 int error;
52 static void find_next_nondelimiter(struct tokenizer_state *tstate)
54 while (*tstate->pos != '\0' && *tstate->pos == tstate->delimiter)
55 tstate->pos++;
58 static size_t find_next_delimiter(struct tokenizer_state *tstate)
60 size_t len = 0;
61 int quote_seen = 0;
63 while (*tstate->pos != '\0') {
64 if (*tstate->pos == '"')
65 quote_seen ^= 1;
67 if (!quote_seen && *tstate->pos == tstate->delimiter)
68 break;
70 len++;
71 tstate->pos++;
74 /* did the string terminate before the close quote? */
75 if (quote_seen) {
76 tstate->error = EINVAL;
77 return 0;
80 return len;
83 /**
84 * next_token - find the next token in a string and return it
85 * @tstate: pointer to tokenizer context object
87 * Returns the next token found in the current string.
88 * Returns NULL if there are no more tokens in the string,
89 * or if an error occurs.
91 * Side effect: tstate is updated
93 char *next_token(struct tokenizer_state *tstate)
95 char *token;
96 size_t len;
98 if (!tstate || !tstate->pos || tstate->error)
99 return NULL;
101 find_next_nondelimiter(tstate);
102 if (*tstate->pos == '\0')
103 goto fail;
104 token = tstate->pos;
106 len = find_next_delimiter(tstate);
107 if (len) {
108 token = strndup(token, len);
109 if (token)
110 return token;
111 tstate->error = ENOMEM;
114 fail:
115 tstate->pos = NULL;
116 return NULL; /* no tokens found in this string */
120 * init_tokenizer - return an initialized tokenizer context object
121 * @string: pointer to C string
122 * @delimiter: single character that delimits tokens in @string
124 * Returns an initialized tokenizer context object
126 struct tokenizer_state *init_tokenizer(char *string, char delimiter)
128 struct tokenizer_state *tstate;
130 tstate = malloc(sizeof(*tstate));
131 if (tstate) {
132 tstate->pos = string;
133 tstate->delimiter = delimiter;
134 tstate->error = 0;
136 return tstate;
140 * tokenizer_error - digs error value out of tokenizer context
141 * @tstate: pointer to tokenizer context object
144 int tokenizer_error(struct tokenizer_state *tstate)
146 return tstate ? tstate->error : 0;
150 * end_tokenizer - free a tokenizer context object
151 * @tstate: pointer to tokenizer context object
154 void end_tokenizer(struct tokenizer_state *tstate)
156 free(tstate);