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