1 /*
2 ** id_parse.c Receive and parse a reply from an IDENT server
3 **
4 ** Author: Peter Eriksson <pen@lysator.liu.se>
5 ** Fiddling: P�r Emanuelsson <pell@lysator.liu.se>
6 */
7
8 #if HAVE_CONFIG_H
9 # include "config.h"
10 #endif
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <ctype.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #if HAVE_SYS_TYPES_H
19 # include <sys/types.h>
20 #endif
21 #if HAVE_UNISTD_H
22 # include <unistd.h>
23 #endif
24 #if HAVE_SYS_SELECT_H
25 # include <sys/select.h>
26 #else
27 # if HAVE_SYS_TIME_H
28 # include <sys/time.h>
29 # endif
30 #endif
31
32 #define IN_LIBIDENT_SRC
33 #include "ident.h"
34
35
id_parse(ident_t * id,struct timeval * timeout,int * lport,int * fport,char ** identifier,char ** opsys,char ** charset)36 int id_parse (ident_t *id, struct timeval *timeout, int *lport, int *fport,
37 char **identifier, char **opsys, char **charset)
38 {
39 char c, *cp, *tmp_charset;
40 fd_set rs;
41 int pos, res=0, lp, fp;
42
43 errno = 0;
44
45 tmp_charset = 0;
46
47 if (!id)
48 return -1;
49 if (lport)
50 *lport = 0;
51 if (fport)
52 *fport = 0;
53 if (identifier)
54 *identifier = 0;
55 if (opsys)
56 *opsys = 0;
57 if (charset)
58 *charset = 0;
59
60 pos = strlen(id->buf);
61
62 if (timeout)
63 {
64 FD_ZERO(&rs);
65 FD_SET(id->fd, &rs);
66
67 res = select(FD_SETSIZE, &rs, NULL, NULL, timeout);
68 if (res < 0)
69 return -1;
70
71 if (res == 0)
72 {
73 errno = ETIMEDOUT;
74 return -1;
75 }
76 }
77
78 /* Every octal value is allowed except 0, \n and \r */
79 while (pos < sizeof(id->buf) &&
80 (res = read(id->fd, id->buf + pos, 1)) == 1 &&
81 id->buf[pos] != '\n' && id->buf[pos] != '\r')
82 pos++;
83
84 if (res < 0)
85 return -1;
86
87 if (res == 0)
88 {
89 errno = ENOTCONN;
90 return -1;
91 }
92
93 if (id->buf[pos] != '\n' && id->buf[pos] != '\r')
94 return 0; /* Not properly terminated string */
95
96 id->buf[pos++] = '\0';
97
98 /*
99 ** Get first field (<lport> , <fport>)
100 */
101 cp = id_strtok(id->buf, ":", &c);
102 if (!cp)
103 return -2;
104
105 if (sscanf(cp, " %d , %d", &lp, &fp) != 2)
106 {
107 if (identifier)
108 {
109 *identifier = id_strdup(cp);
110 if (*identifier == NULL)
111 return -4;
112 }
113 return -2;
114 }
115
116 if (lport)
117 *lport = lp;
118 if (fport)
119 *fport = fp;
120
121 /*
122 ** Get second field (USERID or ERROR)
123 */
124 cp = id_strtok((char *)0, ":", &c);
125 if (!cp)
126 return -2;
127
128 if (strcmp(cp, "ERROR") == 0)
129 {
130 cp = id_strtok((char *)0, "\n\r", &c);
131 if (!cp)
132 return -2;
133
134 if (identifier)
135 {
136 *identifier = id_strdup(cp);
137 if (*identifier == NULL)
138 return -4;
139 }
140
141 return 2;
142 }
143 else if (strcmp(cp, "USERID") == 0)
144 {
145 /*
146 ** Get first subfield of third field <opsys>
147 */
148 cp = id_strtok((char *) 0, ",:", &c);
149 if (!cp)
150 return -2;
151
152 if (opsys)
153 {
154 *opsys = id_strdup(cp);
155 if (*opsys == NULL)
156 return -4;
157 }
158
159 /*
160 ** We have a second subfield (<charset>)
161 */
162 if (c == ',')
163 {
164 cp = id_strtok((char *)0, ":", &c);
165 if (!cp)
166 return -2;
167
168 tmp_charset = cp;
169 if (charset)
170 {
171 *charset = id_strdup(cp);
172 if (*charset == NULL)
173 return -4;
174 }
175
176 /*
177 ** We have even more subfields - ignore them
178 */
179 if (c == ',')
180 id_strtok((char *)0, ":", &c);
181 }
182
183 if (tmp_charset && strcmp(tmp_charset, "OCTET") == 0)
184 cp = id_strtok((char *)0, (char *)0, &c);
185 else
186 cp = id_strtok((char *)0, "\n\r", &c);
187
188 if (identifier && cp)
189 {
190 *identifier = id_strdup(cp);
191 if (*identifier == NULL)
192 return -4;
193 }
194 return 1;
195 }
196 else
197 {
198 if (identifier)
199 {
200 *identifier = id_strdup(cp);
201 if (*identifier == NULL)
202 return -4;
203 }
204 return -3;
205 }
206 }
207