]> andersk Git - moira.git/blob - server/mr_scall.c
Command line printer manipulation client, and build goo.
[moira.git] / server / mr_scall.c
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
27 RCSID("$Header$");
28
29 extern int nclients;
30 extern client **clients;
31 extern char *whoami;
32
33 extern int dbms_errno, mr_errcode;
34
35 int max_version;
36
37 void do_call(client *cl);
38 void free_rtn_tuples(client *cp);
39 int retr_callback(int argc, char **argv, void *p_cl);
40 int list_users(client *cl);
41 void do_retr(client *cl);
42 void do_access(client *cl);
43 void get_motd(client *cl);
44 void do_version(client *cl);
45
46 char *procnames[] = {
47   "noop",
48   "auth",
49   "shutdown",
50   "query",
51   "access",
52   "dcm",
53   "motd",
54   "proxy",
55   "version",
56   "auth_krb5",
57 };
58
59 int newqueries;
60
61 void 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
139 out:
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 */
146 void 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
155 void 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
183 void 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
201 void 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
213 void 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
238 int 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
246 void 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
264 void 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
281 void 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
315 int 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 1.782082 seconds and 5 git commands to generate.