]> andersk Git - moira.git/blame - server/mr_scall.c
Do proper validation of sids to ensure row doesn't already exist.
[moira.git] / server / mr_scall.c
CommitLineData
7ac48069 1/* $Id$
2 *
3 * Do RPC
a3cf6921 4 *
7ac48069 5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
7 * <mit-copyright.h>.
a3cf6921 8 *
a3cf6921 9 */
10
c801de4c 11#include <mit-copyright.h>
7ac48069 12#include "mr_server.h"
13#include "query.h"
14
57c08162 15#include <sys/stat.h>
7ac48069 16#include <sys/types.h>
17
960b073b 18#include <arpa/inet.h>
7ac48069 19#include <netinet/in.h>
20
78849033 21#include <errno.h>
7ac48069 22#include <fcntl.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27RCSID("$Header$");
28
a3cf6921 29extern int nclients;
85330553 30extern client **clients;
a3cf6921 31extern char *whoami;
32
03c05291 33extern int dbms_errno, mr_errcode;
78543660 34
c44ddfa7 35int max_version;
36
7ac48069 37void do_call(client *cl);
38void free_rtn_tuples(client *cp);
85330553 39int retr_callback(int argc, char **argv, void *p_cl);
40int list_users(client *cl);
8691463b 41void do_retr(client *cl);
42void do_access(client *cl);
7ac48069 43void get_motd(client *cl);
c44ddfa7 44void do_version(client *cl);
7ac48069 45
a3cf6921 46char *procnames[] = {
5eaef520 47 "noop",
48 "auth",
49 "shutdown",
50 "query",
51 "access",
52 "dcm",
53 "motd",
ed00e35e 54 "proxy",
c44ddfa7 55 "version",
630e8323 56};
57
85330553 58int newqueries;
a3cf6921 59
85330553 60void client_read(client *cl)
a3cf6921 61{
85330553 62 int status, pn;
63
8691463b 64 status = mr_cont_receive(cl->con, &cl->req);
65 if (status == -1)
66 return;
67 else if (status != MR_SUCCESS)
5eaef520 68 {
8691463b 69 cl->state = CL_CLOSING;
85330553 70 if (status != MR_NOT_CONNECTED)
71 com_err(whoami, status, "while reading from socket");
5eaef520 72 return;
73 }
85330553 74
8691463b 75 pn = cl->req.u.mr_procno;
85330553 76 if (pn < 0 || pn > MR_MAX_PROC)
5eaef520 77 {
85330553 78 com_err(whoami, 0, "procno out of range");
79 client_reply(cl, MR_UNKNOWN_PROC);
187dc9ed 80 goto out;
5eaef520 81 }
8691463b 82 log_args(procnames[pn], 2, cl->req.mr_argc, cl->req.mr_argv);
5eaef520 83
85330553 84 if (dormant == ASLEEP && pn != MR_NOOP && pn != MR_MOTD)
5eaef520 85 {
85330553 86 client_reply(cl, MR_DOWN);
87 com_err(whoami, MR_DOWN, "(query refused)");
187dc9ed 88 goto out;
5eaef520 89 }
90
91 /* make sure this gets cleared before every operation */
92 dbms_errno = 0;
93
94 switch (pn)
95 {
96 case MR_NOOP:
85330553 97 client_reply(cl, MR_SUCCESS);
e688520a 98 break;
5eaef520 99
100 case MR_AUTH:
8691463b 101 do_auth(cl);
e688520a 102 break;
5eaef520 103
104 case MR_QUERY:
8691463b 105 do_retr(cl);
e688520a 106 break;
5eaef520 107
108 case MR_ACCESS:
8691463b 109 do_access(cl);
e688520a 110 break;
5eaef520 111
112 case MR_SHUTDOWN:
113 do_shutdown(cl);
e688520a 114 break;
5eaef520 115
116 case MR_DO_UPDATE:
85330553 117 client_reply(cl, MR_PERM);
e688520a 118 break;
5eaef520 119
120 case MR_MOTD:
121 get_motd(cl);
e688520a 122 break;
ed00e35e 123
124 case MR_PROXY:
125 do_proxy(cl);
126 break;
c44ddfa7 127
128 case MR_SETVERSION:
129 do_version(cl);
130 break;
5eaef520 131 }
187dc9ed 132
133out:
8691463b 134 mr_destroy_reply(cl->req);
135 memset(&cl->req, 0, sizeof(mr_params));
a3cf6921 136}
137
85330553 138/* Set the final return status for a query. We always keep one more
139 free slot in cl->tuples[] than we're using so that this can't fail */
140void client_reply(client *cl, long status)
ed31e0d1 141{
85330553 142 cl->tuples[cl->ntuples].u.mr_status = status;
143 cl->tuples[cl->ntuples].mr_argc = 0;
144 cl->tuples[cl->ntuples].mr_argl = NULL;
145 cl->tuples[cl->ntuples].mr_argv = NULL;
146 cl->ntuples++;
5eaef520 147}
ed31e0d1 148
85330553 149void client_return_tuple(client *cl, int argc, char **argv)
78849033 150{
8691463b 151 if (cl->state == CL_CLOSING || dbms_errno)
85330553 152 return;
5eaef520 153
85330553 154 if (cl->ntuples == cl->tuplessize - 1)
5eaef520 155 {
85330553 156 int newsize = (cl->tuplessize + 4) * 2;
157 mr_params *newtuples;
158
159 newtuples = realloc(cl->tuples, newsize * sizeof(mr_params));
160 if (!newtuples)
161 {
162 free_rtn_tuples(cl);
163 dbms_errno = mr_errcode = MR_NO_MEM;
164 return;
165 }
166 cl->tuplessize = newsize;
167 cl->tuples = newtuples;
5eaef520 168 }
5eaef520 169
85330553 170 cl->tuples[cl->ntuples].u.mr_status = MR_MORE_DATA;
171 cl->tuples[cl->ntuples].mr_argc = argc;
172 cl->tuples[cl->ntuples].mr_argl = NULL;
173 cl->tuples[cl->ntuples].mr_argv = mr_copy_args(argv, argc);
174 cl->ntuples++;
78849033 175}
176
85330553 177void client_write(client *cl)
de24f12d 178{
85330553 179 int status;
5eaef520 180
85330553 181 status = mr_send(cl->con, &cl->tuples[cl->nexttuple]);
182 if (status)
5eaef520 183 {
85330553 184 com_err(whoami, status, "writing to socket");
8691463b 185 cl->state = CL_CLOSING;
85330553 186 }
187 else
188 {
189 cl->nexttuple++;
190 if (cl->nexttuple == cl->ntuples)
191 free_rtn_tuples(cl);
5eaef520 192 }
de24f12d 193}
78849033 194
85330553 195void free_rtn_tuples(client *cl)
a3cf6921 196{
85330553 197 for (cl->ntuples--; cl->ntuples >= 0; cl->ntuples--)
198 free_argv(cl->tuples[cl->ntuples].mr_argv,
199 cl->tuples[cl->ntuples].mr_argc);
200 free(cl->tuples);
201
202 cl->tuples = xmalloc(sizeof(mr_params));
203 cl->tuplessize = 1;
204 cl->ntuples = cl->nexttuple = 0;
205}
5eaef520 206
8691463b 207void do_retr(client *cl)
85330553 208{
209 char *queryname;
210 int status;
5eaef520 211
8691463b 212 if (cl->req.mr_argc < 1)
5eaef520 213 {
85330553 214 client_reply(cl, MR_ARGS);
5eaef520 215 com_err(whoami, MR_ARGS, "got nameless query");
216 return;
217 }
8691463b 218 queryname = cl->req.mr_argv[0];
85330553 219 newqueries++;
5eaef520 220
221 if (!strcmp(queryname, "_list_users"))
85330553 222 status = list_users(cl);
5eaef520 223 else
8691463b 224 status = mr_process_query(cl, queryname, cl->req.mr_argc - 1,
225 cl->req.mr_argv + 1, retr_callback, cl);
85330553 226
227 client_reply(cl, status);
228
85330553 229 com_err(whoami, 0, "Query complete.");
230}
231
232int retr_callback(int argc, char **argv, void *p_cl)
233{
234 client *cl = p_cl;
235
236 mr_trim_args(argc, argv);
237 client_return_tuple(cl, argc, argv);
a3cf6921 238}
78849033 239
8691463b 240void do_access(client *cl)
3630192b 241{
85330553 242 int status;
243
8691463b 244 if (cl->req.mr_argc < 1)
5eaef520 245 {
85330553 246 client_reply(cl, MR_ARGS);
5eaef520 247 com_err(whoami, MR_ARGS, "got nameless access");
248 return;
249 }
5eaef520 250
8691463b 251 status = mr_check_access(cl, cl->req.mr_argv[0], cl->req.mr_argc - 1,
252 cl->req.mr_argv + 1);
85330553 253 client_reply(cl, status);
5eaef520 254
255 com_err(whoami, 0, "Access check complete.");
3630192b 256}
8165c536 257
c44ddfa7 258void do_version(client *cl)
259{
260 if (cl->req.mr_argc != 1)
261 {
262 client_reply(cl, MR_ARGS);
263 com_err(whoami, MR_ARGS, "incorrect number of arguments");
264 return;
265 }
266
267 cl->version = atoi(cl->req.mr_argv[0]);
268 if (cl->version == -1)
269 cl->version = max_version;
270
271 client_reply(cl, cl->version == max_version ? MR_SUCCESS :
272 cl->version < max_version ? MR_VERSION_LOW : MR_VERSION_HIGH);
273}
274
85330553 275void get_motd(client *cl)
8165c536 276{
85330553 277 int motd;
278 char *buffer;
279 struct stat statb;
5eaef520 280
85330553 281 if (stat(MOIRA_MOTD_FILE, &statb) == -1)
5eaef520 282 {
85330553 283 client_reply(cl, MR_SUCCESS);
284 return;
285 }
286
287 buffer = malloc(statb.st_size + 1);
288 if (!buffer)
289 {
290 client_reply(cl, MR_NO_MEM);
291 return;
292 }
5eaef520 293
85330553 294 motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
295 if (motd)
296 {
297 read(motd, buffer, statb.st_size);
298 close(motd);
299 buffer[statb.st_size] = '\0';
300 client_return_tuple(cl, 1, &buffer);
301 client_reply(cl, MR_SUCCESS);
5eaef520 302 }
85330553 303 else
304 client_reply(cl, errno);
8165c536 305
85330553 306 free(buffer);
307}
57c08162 308
85330553 309int list_users(client *cl)
57c08162 310{
85330553 311 char *argv[5];
312 char buf[30];
313 char buf1[30];
314 int i;
315 char *cp;
5eaef520 316
85330553 317 for (i = 0; i < nclients; i++)
318 {
319 client *c = clients[i];
320 argv[0] = c->clname;
321 argv[1] = inet_ntoa(c->haddr.sin_addr);
322 argv[2] = buf;
323 sprintf(buf, "port %d", ntohs(c->haddr.sin_port));
324 argv[3] = ctime(&c->last_time_used);
325 cp = strchr(argv[3], '\n');
326 if (cp)
327 *cp = '\0';
328 argv[4] = buf1;
329 sprintf(buf1, "[#%d]", c->id);
330 client_return_tuple(cl, 5, argv);
331 }
332 return MR_SUCCESS;
57c08162 333}
85330553 334
This page took 0.162064 seconds and 5 git commands to generate.