~ubuntu-branches/ubuntu/hardy/nfs-utils/hardy-updates

« back to all changes in this revision

Viewing changes to utils/mount/token.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathias Gug
  • Date: 2007-11-14 04:52:46 UTC
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: james.westby@ubuntu.com-20071114045246-37yxn6na36segpuh
Tags: upstream-1.1.1
ImportĀ upstreamĀ versionĀ 1.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * token.c -- tokenize strings, a la strtok(3)
 
3
 *
 
4
 * Copyright (C) 2007 Oracle.  All rights reserved.
 
5
 * Copyright (C) 2007 Chuck Lever <chuck.lever@oracle.com>
 
6
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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.
 
21
 *
 
22
 */
 
23
 
 
24
/*
 
25
 * We've constructed a simple string tokenizer that is better than
 
26
 * strtok(3) in several ways:
 
27
 *
 
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.
 
33
 */
 
34
 
 
35
 
 
36
#include <ctype.h>
 
37
#include <unistd.h>
 
38
#include <stdio.h>
 
39
#include <string.h>
 
40
#include <stdlib.h>
 
41
#include <errno.h>
 
42
 
 
43
#include "token.h"
 
44
 
 
45
 
 
46
struct tokenizer_state {
 
47
        char *pos;
 
48
        char delimiter;
 
49
        int error;
 
50
};
 
51
 
 
52
static void find_next_nondelimiter(struct tokenizer_state *tstate)
 
53
{
 
54
        while (*tstate->pos != '\0' && *tstate->pos == tstate->delimiter)
 
55
                tstate->pos++;
 
56
}
 
57
 
 
58
static size_t find_next_delimiter(struct tokenizer_state *tstate)
 
59
{
 
60
        size_t len = 0;
 
61
        int quote_seen = 0;
 
62
 
 
63
        while (*tstate->pos != '\0') {
 
64
                if (*tstate->pos == '"')
 
65
                        quote_seen ^= 1;
 
66
 
 
67
                if (!quote_seen && *tstate->pos == tstate->delimiter)
 
68
                        break;
 
69
 
 
70
                len++;
 
71
                tstate->pos++;
 
72
        }
 
73
 
 
74
        /* did the string terminate before the close quote? */
 
75
        if (quote_seen) {
 
76
                tstate->error = EINVAL;
 
77
                return 0;
 
78
        }
 
79
 
 
80
        return len;
 
81
}
 
82
 
 
83
/**
 
84
 * next_token - find the next token in a string and return it
 
85
 * @tstate: pointer to tokenizer context object
 
86
 *
 
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.
 
90
 *
 
91
 * Side effect: tstate is updated
 
92
 */
 
93
char *next_token(struct tokenizer_state *tstate)
 
94
{
 
95
        char *token;
 
96
        size_t len;
 
97
 
 
98
        if (!tstate || !tstate->pos || tstate->error)
 
99
                return NULL;
 
100
 
 
101
        find_next_nondelimiter(tstate);
 
102
        if (*tstate->pos == '\0')
 
103
                goto fail;
 
104
        token = tstate->pos;
 
105
 
 
106
        len = find_next_delimiter(tstate);
 
107
        if (len) {
 
108
                token = strndup(token, len);
 
109
                if (token)
 
110
                        return token;
 
111
                tstate->error = ENOMEM;
 
112
        }
 
113
 
 
114
fail:
 
115
        tstate->pos = NULL;
 
116
        return NULL;                    /* no tokens found in this string */
 
117
}
 
118
 
 
119
/**
 
120
 * init_tokenizer - return an initialized tokenizer context object
 
121
 * @string: pointer to C string
 
122
 * @delimiter: single character that delimits tokens in @string
 
123
 *
 
124
 * Returns an initialized tokenizer context object
 
125
 */
 
126
struct tokenizer_state *init_tokenizer(char *string, char delimiter)
 
127
{
 
128
        struct tokenizer_state *tstate;
 
129
 
 
130
        tstate = malloc(sizeof(*tstate));
 
131
        if (tstate) {
 
132
                tstate->pos = string;
 
133
                tstate->delimiter = delimiter;
 
134
                tstate->error = 0;
 
135
        }
 
136
        return tstate;
 
137
}
 
138
 
 
139
/**
 
140
 * tokenizer_error - digs error value out of tokenizer context
 
141
 * @tstate: pointer to tokenizer context object
 
142
 *
 
143
 */
 
144
int tokenizer_error(struct tokenizer_state *tstate)
 
145
{
 
146
        return tstate ? tstate->error : 0;
 
147
}
 
148
 
 
149
/**
 
150
 * end_tokenizer - free a tokenizer context object
 
151
 * @tstate: pointer to tokenizer context object
 
152
 *
 
153
 */
 
154
void end_tokenizer(struct tokenizer_state *tstate)
 
155
{
 
156
        free(tstate);
 
157
}