]> andersk Git - moira.git/blame - server/mr_scall.c
punt mrgdb
[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
7ac48069 35void do_call(client *cl);
36void free_rtn_tuples(client *cp);
85330553 37int retr_callback(int argc, char **argv, void *p_cl);
38int list_users(client *cl);
39void do_retr(client *cl, mr_params req);
40void do_access(client *cl, mr_params req);
7ac48069 41void get_motd(client *cl);
42
78543660 43/* Put this in a variable so that we can patch it if necessary */
50e114e1 44int max_row_count = 4096;
a3cf6921 45
a3cf6921 46char *procnames[] = {
5eaef520 47 "noop",
48 "auth",
49 "shutdown",
50 "query",
51 "access",
52 "dcm",
53 "motd",
630e8323 54};
55
85330553 56int newqueries;
a3cf6921 57
85330553 58void client_read(client *cl)
a3cf6921 59{
85330553 60 mr_params req;
61 int status, pn;
62
63 status = mr_receive(cl->con, &req);
64 if (status != MR_SUCCESS)
5eaef520 65 {
85330553 66 cl->done = 1;
67 if (status != MR_NOT_CONNECTED)
68 com_err(whoami, status, "while reading from socket");
5eaef520 69 return;
70 }
85330553 71
72 pn = req.u.mr_procno;
73 if (pn < 0 || pn > MR_MAX_PROC)
5eaef520 74 {
85330553 75 com_err(whoami, 0, "procno out of range");
76 client_reply(cl, MR_UNKNOWN_PROC);
77 return;
5eaef520 78 }
85330553 79 log_args(procnames[pn], 2, req.mr_argc, req.mr_argv);
5eaef520 80
85330553 81 if (dormant == ASLEEP && pn != MR_NOOP && pn != MR_MOTD)
5eaef520 82 {
85330553 83 client_reply(cl, MR_DOWN);
84 com_err(whoami, MR_DOWN, "(query refused)");
5eaef520 85 return;
86 }
87
88 /* make sure this gets cleared before every operation */
89 dbms_errno = 0;
90
91 switch (pn)
92 {
93 case MR_NOOP:
85330553 94 client_reply(cl, MR_SUCCESS);
5eaef520 95 return;
96
97 case MR_AUTH:
85330553 98 do_auth(cl, req);
5eaef520 99 return;
100
101 case MR_QUERY:
85330553 102 do_retr(cl, req);
5eaef520 103 return;
104
105 case MR_ACCESS:
85330553 106 do_access(cl, req);
5eaef520 107 return;
108
109 case MR_SHUTDOWN:
110 do_shutdown(cl);
111 return;
112
113 case MR_DO_UPDATE:
85330553 114 client_reply(cl, MR_PERM);
5eaef520 115 return;
116
117 case MR_MOTD:
118 get_motd(cl);
119 return;
120 }
a3cf6921 121}
122
85330553 123/* Set the final return status for a query. We always keep one more
124 free slot in cl->tuples[] than we're using so that this can't fail */
125void client_reply(client *cl, long status)
ed31e0d1 126{
85330553 127 cl->tuples[cl->ntuples].u.mr_status = status;
128 cl->tuples[cl->ntuples].mr_argc = 0;
129 cl->tuples[cl->ntuples].mr_argl = NULL;
130 cl->tuples[cl->ntuples].mr_argv = NULL;
131 cl->ntuples++;
5eaef520 132}
ed31e0d1 133
85330553 134void client_return_tuple(client *cl, int argc, char **argv)
78849033 135{
85330553 136 if (cl->done || dbms_errno)
137 return;
5eaef520 138
85330553 139 if (cl->ntuples == max_row_count)
5eaef520 140 {
141 dbms_errno = mr_errcode = MR_NO_MEM;
85330553 142 return;
5eaef520 143 }
144
85330553 145 if (cl->ntuples == cl->tuplessize - 1)
5eaef520 146 {
85330553 147 int newsize = (cl->tuplessize + 4) * 2;
148 mr_params *newtuples;
149
150 newtuples = realloc(cl->tuples, newsize * sizeof(mr_params));
151 if (!newtuples)
152 {
153 free_rtn_tuples(cl);
154 dbms_errno = mr_errcode = MR_NO_MEM;
155 return;
156 }
157 cl->tuplessize = newsize;
158 cl->tuples = newtuples;
5eaef520 159 }
5eaef520 160
85330553 161 cl->tuples[cl->ntuples].u.mr_status = MR_MORE_DATA;
162 cl->tuples[cl->ntuples].mr_argc = argc;
163 cl->tuples[cl->ntuples].mr_argl = NULL;
164 cl->tuples[cl->ntuples].mr_argv = mr_copy_args(argv, argc);
165 cl->ntuples++;
78849033 166}
167
85330553 168void client_write(client *cl)
de24f12d 169{
85330553 170 int status;
5eaef520 171
85330553 172 status = mr_send(cl->con, &cl->tuples[cl->nexttuple]);
173 if (status)
5eaef520 174 {
85330553 175 com_err(whoami, status, "writing to socket");
176 cl->done = 1;
177 }
178 else
179 {
180 cl->nexttuple++;
181 if (cl->nexttuple == cl->ntuples)
182 free_rtn_tuples(cl);
5eaef520 183 }
de24f12d 184}
78849033 185
85330553 186void free_rtn_tuples(client *cl)
a3cf6921 187{
85330553 188 for (cl->ntuples--; cl->ntuples >= 0; cl->ntuples--)
189 free_argv(cl->tuples[cl->ntuples].mr_argv,
190 cl->tuples[cl->ntuples].mr_argc);
191 free(cl->tuples);
192
193 cl->tuples = xmalloc(sizeof(mr_params));
194 cl->tuplessize = 1;
195 cl->ntuples = cl->nexttuple = 0;
196}
5eaef520 197
85330553 198void do_retr(client *cl, mr_params req)
199{
200 char *queryname;
201 int status;
5eaef520 202
85330553 203 if (req.mr_argc < 1)
5eaef520 204 {
85330553 205 client_reply(cl, MR_ARGS);
5eaef520 206 com_err(whoami, MR_ARGS, "got nameless query");
207 return;
208 }
85330553 209 queryname = req.mr_argv[0];
210 newqueries++;
5eaef520 211
212 if (!strcmp(queryname, "_list_users"))
85330553 213 status = list_users(cl);
5eaef520 214 else
85330553 215 status = mr_process_query(cl, queryname, req.mr_argc - 1, req.mr_argv + 1,
216 retr_callback, cl);
217
218 client_reply(cl, status);
219
220 if (cl->ntuples >= max_row_count)
5eaef520 221 {
85330553 222 critical_alert("moirad", "attempted query %s with too many rows\n",
223 queryname);
5eaef520 224 }
225
85330553 226 com_err(whoami, 0, "Query complete.");
227}
228
229int retr_callback(int argc, char **argv, void *p_cl)
230{
231 client *cl = p_cl;
232
233 mr_trim_args(argc, argv);
234 client_return_tuple(cl, argc, argv);
a3cf6921 235}
78849033 236
85330553 237void do_access(client *cl, mr_params req)
3630192b 238{
85330553 239 int status;
240
241 if (req.mr_argc < 1)
5eaef520 242 {
85330553 243 client_reply(cl, MR_ARGS);
5eaef520 244 com_err(whoami, MR_ARGS, "got nameless access");
245 return;
246 }
5eaef520 247
85330553 248 status = mr_check_access(cl, req.mr_argv[0], req. mr_argc - 1,
249 req.mr_argv + 1);
250 client_reply(cl, status);
5eaef520 251
252 com_err(whoami, 0, "Access check complete.");
3630192b 253}
8165c536 254
85330553 255void get_motd(client *cl)
8165c536 256{
85330553 257 int motd;
258 char *buffer;
259 struct stat statb;
5eaef520 260
85330553 261 if (stat(MOIRA_MOTD_FILE, &statb) == -1)
5eaef520 262 {
85330553 263 client_reply(cl, MR_SUCCESS);
264 return;
265 }
266
267 buffer = malloc(statb.st_size + 1);
268 if (!buffer)
269 {
270 client_reply(cl, MR_NO_MEM);
271 return;
272 }
5eaef520 273
85330553 274 motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
275 if (motd)
276 {
277 read(motd, buffer, statb.st_size);
278 close(motd);
279 buffer[statb.st_size] = '\0';
280 client_return_tuple(cl, 1, &buffer);
281 client_reply(cl, MR_SUCCESS);
5eaef520 282 }
85330553 283 else
284 client_reply(cl, errno);
8165c536 285
85330553 286 free(buffer);
287}
57c08162 288
85330553 289int list_users(client *cl)
57c08162 290{
85330553 291 char *argv[5];
292 char buf[30];
293 char buf1[30];
294 int i;
295 char *cp;
5eaef520 296
85330553 297 for (i = 0; i < nclients; i++)
298 {
299 client *c = clients[i];
300 argv[0] = c->clname;
301 argv[1] = inet_ntoa(c->haddr.sin_addr);
302 argv[2] = buf;
303 sprintf(buf, "port %d", ntohs(c->haddr.sin_port));
304 argv[3] = ctime(&c->last_time_used);
305 cp = strchr(argv[3], '\n');
306 if (cp)
307 *cp = '\0';
308 argv[4] = buf1;
309 sprintf(buf1, "[#%d]", c->id);
310 client_return_tuple(cl, 5, argv);
311 }
312 return MR_SUCCESS;
57c08162 313}
85330553 314
This page took 0.150653 seconds and 5 git commands to generate.