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