]> andersk Git - moira.git/blob - server/mr_scall.c
reset ingres_errno before each operation
[moira.git] / server / mr_scall.c
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987 by the Massachusetts Institute of Technology
7  *      For copying and distribution information, please see the file
8  *      <mit-copyright.h>.
9  *
10  */
11
12 #ifndef lint
13 static char *rcsid_sms_scall_c = "$Header$";
14 #endif lint
15
16 #include <mit-copyright.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/file.h>
20 #include <krb.h>
21 #include <errno.h>
22 #include "query.h"
23 #include "mr_server.h"
24 extern char buf1[];
25 extern int nclients;
26 extern char *whoami;
27 extern char *malloc();
28 extern int errno;
29
30 extern void clist_delete(), do_auth(), do_shutdown();
31 void do_call();
32
33 /*
34  * Welcome to the (finite state) machine (highest level).
35  */
36 void
37 do_client(cp)
38         client *cp;
39 {
40         struct stat stbuf;
41
42         free_rtn_tuples(cp);
43         if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
44                 com_err(whoami, 0, "Closed connection (now %d client%s, %d new queries, %d old)",
45                         nclients-1,
46                         nclients!=2?"s":"",
47                         newqueries,
48                         oldqueries);
49                 clist_delete(cp);
50                 /* if we no longer have any clients, and we're supposed to
51                  * go down, then go down now.
52                  */
53                 if ((dormant == AWAKE) && (nclients == 0) &&
54                     (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) {
55                     com_err(whoami, 0, "motd file exists, slumbertime");
56                     dormant = SLEEPY;
57                 }
58                 return;
59         }
60         switch (cp->action) {
61         case CL_ACCEPT:
62         case CL_SEND:
63                 /* Start recieving next request */
64                 initialize_operation(cp->pending_op, mr_start_recv,
65                                      (char *)&cp->args, (int (*)())NULL);
66                 queue_operation(cp->con, CON_INPUT, cp->pending_op);
67                 cp->action = CL_RECEIVE;
68                 break;
69         case CL_RECEIVE:
70                 /* Data is here. Process it & start it heading back */
71                 do_call(cp); /* This may block for a while. */
72                 mr_destroy_reply(cp->args);
73                 cp->args = NULL;
74                 initialize_operation(cp->pending_op, mr_start_send,
75                                      (char *)&cp->reply, (int (*)())NULL);
76                 queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
77                 cp->action = CL_SEND;
78                 break;
79         }
80 }               
81
82 char *procnames[] = {
83          "noop",
84          "auth",
85          "shutdown",
86          "query",
87          "access",
88          "dcm",
89          "motd",
90 };
91
92
93 void
94 do_call(cl)
95         client *cl;
96 {
97         int pn;
98         extern int ingres_errno;
99         cl->reply.mr_argc = 0;
100         cl->reply.mr_status = 0;
101         cl->reply.mr_version_no = cl->args->mr_version_no;
102         if (((pn = cl->args->mr_procno) < 0) ||
103             (pn > MR_MAX_PROC)) {
104                 com_err(whoami, 0, "procno out of range");
105                 cl->reply.mr_status = MR_UNKNOWN_PROC;
106                 return;
107         }
108         if (log_flags & LOG_ARGS)
109                 log_args(procnames[pn], cl->args->mr_version_no,
110                          cl->args->mr_argc, cl->args->mr_argv);
111         else if (log_flags & LOG_REQUESTS)
112                 com_err(whoami, 0, "%s", procnames[pn]);
113
114         if ((dormant == ASLEEP || dormant == GROGGY) &&
115             pn != MR_NOOP && pn != MR_MOTD) {
116             cl->reply.mr_status = MR_DOWN;
117             if (log_flags & LOG_RES)
118               com_err(whoami, MR_DOWN, "(query refused)");
119             return;
120         }
121
122         /* make sure this gets cleared before every operation */
123         ingres_errno = 0;
124
125         switch(pn) {
126         case MR_NOOP:
127                 cl->reply.mr_status = 0;
128                 return;
129
130         case MR_AUTH:
131                 do_auth(cl);
132                 return;
133
134         case MR_QUERY:
135                 do_retr(cl);
136                 return;
137
138         case MR_ACCESS:
139                 do_access(cl);
140                 return;
141                 
142         case MR_SHUTDOWN:
143                 do_shutdown(cl);
144                 return;
145
146         case MR_DO_UPDATE:
147                 trigger_dcm(0, 0, cl);
148                 return;
149
150         case MR_MOTD:
151                 get_motd(cl);
152                 return;
153         }
154 }
155
156 free_rtn_tuples(cp)
157         client *cp;
158 {
159         register returned_tuples *temp;
160         for (temp=cp->first; temp && OP_DONE(temp->op); ) {
161                 register returned_tuples *t1=temp;
162                 temp = t1->next;
163                 if (t1 == cp->last) cp->last = NULL;
164
165                 mr_destroy_reply(t1->retval);
166                 delete_operation(t1->op);
167                 free(t1);
168         }
169         cp->first = temp;
170 }       
171
172 retr_callback(argc, argv, p_cp)
173         register int argc;
174         register char **argv;
175         char *p_cp;
176 {
177         register client *cp = (client *)p_cp;
178         /*
179          * This takes too much advantage of the fact that
180          * serialization of the data happens during the queue operation.
181          */
182         mr_params *arg_tmp = (mr_params *)db_alloc(sizeof(mr_params));
183         returned_tuples *tp = (returned_tuples *)
184                 db_alloc(sizeof(returned_tuples));
185         register char **nargv = (char **)malloc(argc * sizeof(char *));
186         register int i;
187         
188         OPERATION op_tmp = create_operation();
189
190         if (mr_trim_args(argc, argv) == MR_NO_MEM) {
191             com_err(whoami, MR_NO_MEM, "while trimming args");
192         }
193         if (log_flags & LOG_RESP)
194                 log_args("return: ", cp->args->mr_version_no, argc, argv);
195
196         tp->op = op_tmp;
197         tp->retval = arg_tmp;
198         tp->next = NULL;
199         
200         arg_tmp->mr_status = MR_MORE_DATA;
201         arg_tmp->mr_version_no = cp->args->mr_version_no;
202         arg_tmp->mr_argc = argc;
203         arg_tmp->mr_argv = nargv;
204         for (i = 0; i < argc; i++) {
205                 register int len = strlen(argv[i]) + 1;
206                 nargv[i] = malloc(len);
207                 bcopy(argv[i], nargv[i], len);
208         }
209         arg_tmp->mr_flattened = (char *)NULL;
210         arg_tmp->mr_argl = (int *)NULL;
211
212         if (cp->last) {
213                 cp->last->next = tp;
214                 cp->last = tp;
215         } else {
216                 cp->last = cp->first = tp;
217         }
218         
219         reset_operation(op_tmp);
220         initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp,
221                              (int (*)())NULL);
222         queue_operation(cp->con, CON_OUTPUT, op_tmp);
223 }
224
225 list_users(callbk, callarg)
226         int (*callbk)();
227         char *callarg;
228 {
229         char *argv[6];
230         char buf[30];
231         char buf1[30];
232         int i;
233         extern client **clients;
234         extern char *inet_ntoa();
235         char *cp;
236         char *index();
237         char *ctime();
238
239         for (i = 0; i < nclients; i++) {
240                 register client *cl = clients[i];
241                 if (cl->clname) 
242                         argv[0] = cl->clname;
243                 else argv[0] = "unauthenticated";
244                 
245                 argv[1] = inet_ntoa(cl->haddr.sin_addr);
246                 argv[2] = buf;
247                 sprintf(buf, "port %d", ntohs(cl->haddr.sin_port));
248                 argv[3] = ctime(&cl->last_time_used);
249                 cp = index(argv[3], '\n');
250                 if (cp) *cp = '\0';
251                 argv[4] = buf1;
252                 sprintf(buf1, "[#%d]", cl->id);
253                 (*callbk)(5, argv, callarg);
254         }
255         return 0;
256 }
257
258 do_retr(cl)
259         register client *cl;
260 {
261         register char *queryname;
262
263         cl->reply.mr_argc = 0;
264         cl->reply.mr_status = 0;
265
266         queryname = cl->args->mr_argv[0];
267         
268         if (cl->args->mr_version_no == MR_VERSION_2)
269           newqueries++;
270         else
271           oldqueries++;
272
273         if (strcmp(queryname, "_list_users") == 0)
274                 cl->reply.mr_status = list_users(retr_callback, (char *)cl);
275         else {
276                 cl->reply.mr_status = 
277                         mr_process_query(cl,
278                                           cl->args->mr_argv[0],
279                                           cl->args->mr_argc-1,
280                                           cl->args->mr_argv+1,
281                                           retr_callback,
282                                           (char *)cl);
283         }
284         if (log_flags & LOG_RES)
285                 com_err(whoami, 0, "Query complete.");
286 }
287
288 do_access(cl)
289         client *cl;
290 {
291         cl->reply.mr_argc = 0;
292
293         cl->reply.mr_status = 
294           mr_check_access(cl,
295                            cl->args->mr_argv[0],
296                            cl->args->mr_argc-1,
297                            cl->args->mr_argv+1);
298         
299         com_err(whoami, 0, "Access check complete.");
300 }
301
302
303 /* trigger_dcm is also used as a followup routine to the 
304  * set_server_host_override query, hence the two dummy arguments.
305  */
306
307 struct query pseudo_query = {
308         "trigger_dcm",
309         "tdcm",
310 };
311
312 trigger_dcm(dummy0, dummy1, cl)
313         int dummy0, dummy1;
314         client *cl;
315 {
316         register int pid;
317         char prog[128];
318
319         cl->reply.mr_argc = 0;
320
321         if (cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl) )
322                 return(cl->reply.mr_status);
323
324         sprintf(prog, "%s/startdcm", BIN_DIR);
325         pid = vfork();
326         switch (pid) {
327         case 0:
328                 for (dummy0 = getdtablesize() - 1; dummy0 > 2; dummy0--)
329                   close(dummy0);
330                 execl(prog, "startdcm", 0);
331                 exit(1);
332                 
333         case -1:
334                 cl->reply.mr_status = errno;
335                 return(0);
336
337         default:
338                 return(0);
339         }
340 }
341
342
343 get_motd(cl)
344 client *cl;
345 {
346     int motd, len;
347     char buffer[1024];
348     char *arg[1];
349
350     arg[0] = buffer;
351     cl->reply.mr_status = 0;
352     motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
353     if (motd < 0) return;
354     len = read(motd, buffer, sizeof(buffer) - 1);
355     close(motd);
356     buffer[len] = 0;
357     retr_callback(1, arg, cl);
358     cl->reply.mr_status = 0;
359 }
This page took 0.065151 seconds and 5 git commands to generate.