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