20b3c40dc14a4da3a7462b6e99bbcc8f479f5596
[dragonfly.git] / lib / libcaps / caps_msgbuf.c
1 /*
2  * Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $DragonFly: src/lib/libcaps/caps_msgbuf.c,v 1.1 2004/03/07 23:36:44 dillon Exp $
27  */
28
29 #include "defs.h"
30
31 void
32 caps_init_msgbuf(caps_msgbuf_t msg, void *data, int size)
33 {
34     msg->base = data;
35     msg->index = 0;
36     msg->bufsize = size;
37     msg->error = 0;
38 }
39
40 void
41 caps_msgbuf_error(caps_msgbuf_t msg, int eno, int undo)
42 {
43     if (eno)
44         msg->error = eno;
45     if (msg->index < undo)
46         msg->index = 0;
47     else
48         msg->index -= undo;
49 }
50
51 /*
52  * Extract the next class specification.  A class specification is an upper
53  * case letter followed by quoted data or non-quoted data.  Non-quoted data
54  * may only contain the characters 0-9 and LOWER CASE a-z, '.', or '_'.
55  * The returned (ptr,len) tuple includes the quotes in quoted data.
56  */
57 u_int8_t
58 caps_msgbuf_getclass(caps_msgbuf_t msg, u_int8_t **pptr, int *plen)
59 {
60     u_int8_t c;
61     u_int8_t cc;
62     int i;
63
64     while (msg->index < msg->bufsize) {
65         c = msg->base[msg->index++];
66         if (c >= 'A' && c <= 'Z') {
67             i = msg->index;
68             *pptr = msg->base + i;
69             if (i < msg->bufsize && msg->base[i] == '\"') {
70                 for (++i; i < msg->bufsize; ++i) {
71                     cc = msg->base[i];
72                     if ((cc >= 'a' && cc <= 'z') ||
73                         (cc >= 'A' && cc <= 'Z') ||
74                         (cc >= '0' && cc <= '9') ||
75                         cc == '_' || cc == '.' || cc == '/' || cc == '+' || 
76                         cc == '-' || cc == '%'
77                     ) {
78                         continue;
79                     }
80                     if (cc == '"')      /* quote end string, else error */
81                         ++i;
82                     else
83                         msg->error = EINVAL;
84                     break;
85                 }
86             } else {
87                 for (; i < msg->bufsize; ++i) {
88                     cc = msg->base[i];
89                     if (cc >= 'a' && cc <= 'z')
90                         continue;
91                     if (cc >= '0' && cc <= '9')
92                         continue;
93                     if (cc == '.' || cc == '_')
94                         continue;
95                     break;
96                 }
97             }
98             *plen = i - msg->index;
99             msg->index = i;
100             return(c);
101         }
102         if (c == ',' || c == '{' || c == '}')
103             return(c);
104         if (c != '\t' && c != ' ' && c != '\r' && c != '\n') {
105             msg->error = EINVAL;
106             break;
107         }
108         /* loop on whitespce */
109     }
110     return(0);
111 }
112
113 /*
114  * Support routines for encoding/decoding
115  */
116 void
117 caps_msgbuf_printf(caps_msgbuf_t msg, const char *ctl, ...)
118 {
119     va_list va;
120     int i;
121
122     va_start(va, ctl);
123     i = msg->index;
124     if (i <= msg->bufsize)
125         i += vsnprintf(msg->base + i, msg->bufsize - i, ctl, va);
126     else
127         i += vsnprintf(NULL, 0, ctl, va);
128     msg->index = i;
129     va_end(va);
130 }
131