]> andersk Git - moira.git/blob - update/client.c
Changed to use rcmd instead of sms on target end of xfer.
[moira.git] / update / client.c
1 /*
2  *      $Source$
3  *      $Header$
4  */
5
6 #ifndef lint
7 static char *rcsid_client2_c = "$Header$";
8 #endif  lint
9
10 /*
11  * MODULE IDENTIFICATION:
12  *      $Header$
13  *      Copyright 1987 MIT Project Athena.
14  * DESCRIPTION:
15  *      This code handles the actual distribution of data files
16  *      to servers in the SMS server-update program.
17  * AUTHOR:
18  *      Ken Raeburn (spook@athena.MIT.EDU),
19  *              MIT Project Athena/MIT Information Systems.
20  * DEFINED VALUES:
21  *      conn
22  *      update_info
23  *      sms_update_server
24  * VERSION HISTORY:
25  *      $Log$
26  *      Revision 1.1  1987-08-22 17:53:46  wesommer
27  *      Initial revision
28  *
29  */
30
31 #include <stdio.h>
32 #include <strings.h>
33 #include "gdb.h"
34 #include <sys/stat.h>
35 #include <sys/file.h>
36 #include <sys/param.h>
37 #include "update.h"
38 #include <errno.h>
39 #include "sms_update_int.h"
40 #include "smsu_int.h"
41 #include <krb.h>
42
43 extern char *malloc(), *error_message();
44 extern int errno;
45
46 /* XXX */
47 #include "kludge.h"
48 /* XXX */
49
50 static char buf[BUFSIZ];
51
52 CONNECTION conn;
53 struct update_desc *info;
54
55 static int code;
56
57 /*
58  * FUNCTION:
59  *      initialize()
60  * DESCRIPTION:
61  *      Insures that various libraries have a chance to get
62  *      initialized.
63  * INPUT:
64  * OUTPUT:
65  * RETURN VALUE:
66  *      void
67  * SIDE EFFECTS:
68  *      Initializes GDB library and SMSU error table.
69  * PROBLEMS:
70  *
71  */
72 static
73 void
74 initialize()
75 {
76     static int initialized = 0;
77     if (!initialized) {
78         gdb_init();
79         init_smsU_err_tbl();
80         initialized++;
81     }
82 }
83
84 /*
85  * FUNCTION:
86  *      sms_update_server(info)
87  * DESCRIPTION:
88  *      Attempts to perform an update based on the information
89  *      contained in the data structure pointed to by "info".
90  *      Errors in performing the update are logged with the
91  *      sms_log* routines; the 'override' field may be updated
92  *      to cause updates to occur other than on the regular
93  *      schedule (generally to force an earlier retry).
94  * INPUT:
95  *      info->service_name
96  *              Name of service to be updated; used to find
97  *              the source data file in the SMS data directory.
98  *      info->host_name
99  *      info->target_path
100  *              Location to install the file.
101  *      info->enable
102  *              Must be non-zero.
103  *      info->instructions
104  *              Sequence of commands to execute on remote
105  *              machine to effect the installation.
106  * OUTPUT:
107  *      info->last_time
108  *              Set to the current time if the update was
109  *              attempted.
110  *      info->success
111  *              Set to non-zero if the update succeeded, set
112  *              to zero otherwise.
113  *      info->override
114  *              Set to -1 if the update succeeds, to (possibly)
115  *              some other value otherwise.
116  * RETURN VALUE:
117  *      int:
118  *              Error code, or zero if no error was detected
119  *              in the data supplied to this routine.
120  * SIDE EFFECTS:
121  *      May write information to logs.
122  * PROBLEMS:
123  *
124  */
125
126 int
127 sms_update_server(update_info, pathname)
128     struct update_desc *update_info;
129     char *pathname;
130 {
131 #define ASSERT(condition,amsg) \
132     if (!(condition)) { msg = amsg; code = 0; goto local_error; }
133 #define NONNULL(str) \
134     (((str) != (char *)NULL) && ((size = strlen(str)) != 0))
135 #define IO_ERROR(msg) \
136     {log_priority=log_ERROR;com_err(whoami,connection_errno(conn),msg);goto io_error;}
137
138     char *service_address;
139     char *service_updated;
140     char *msg;
141     register char *cp;
142     STRING string_data, string2;
143     int size, num;
144     int fd = -1;
145     struct stat statb;
146     
147     /* variable initializations */
148     code = 0;
149     info = update_info;
150     service_updated = (char *)NULL;
151     STRING_DATA(string_data) = (char *)NULL;
152
153     /* pessimism */
154     info->success = 0;
155
156     /* some sanity checking of arguments while we build data */
157     strcpy(buf, "???:???");
158     ASSERT(NONNULL(info->host_name), "null host name");
159     /* XXX -- check length here */
160     strcpy(buf, info->host_name);
161     for (cp = buf; *cp; cp++)
162         ;
163     strcpy(cp, ":???");
164     ASSERT(NONNULL(info->service_name), "null service name");
165     /* XXX -- check length here */
166     strcpy(++cp, info->service_name);
167     service_updated = malloc(strlen(buf)+1);
168     /* XXX -- check allocation succeeded */
169     strcpy(service_updated, buf);
170     service_address = malloc(strlen(SERVICE_NAME)+strlen(info->host_name)+1);
171     if (!service_address) {
172         code = errno;
173         info->override = -1;
174         return(code);
175     }
176     strcpy(service_address, info->host_name);
177     strcat(service_address, ":");
178     strcat(service_address, SERVICE_NAME);
179     ASSERT(info->enable, "server is disabled");
180     ASSERT(NONNULL(info->target_path), "null target pathname");
181     ASSERT(size < MAXPATHLEN, "target pathname too long");
182     ASSERT(info->target_path[0] == '/', "non-absolute pathname supplied");
183     
184     initialize();
185     
186     string_alloc(&string2, BUFSIZ);
187     
188     sprintf(buf, "starting update for %s", service_updated);
189     sms_log_info(buf);
190     
191     fd = open(pathname, O_RDONLY, 0);
192     if (fd < 0) {
193         code = errno;
194         msg = pathname;
195         goto local_error;
196     }
197     if (fstat(fd, &statb)) {
198         code = errno;
199         close(fd); fd = -1;
200         strcat(buf, ": can't fstat:");
201         strcat(buf, error_message(code));
202         sms_log_error(buf);
203         goto error_exit;
204     }
205     size = statb.st_size;
206     
207     /* open connection */
208     conn = start_server_connection(service_address, 0);
209     if (!conn) {
210         com_err(whoami, 0, "can't connect to update %s", service_address);
211     connect_failed:
212         if (info->override<0 || info->override>INTERVAL_connection_failed)
213             info->override = INTERVAL_connection_failed;
214         return(0);
215     }
216     else if (connection_status(conn) == CON_STOPPED) {
217         com_err(whoami, connection_errno(conn), ": can't connect to update %s",
218                 service_address);
219         goto connect_failed;
220     }
221     
222     
223     /* send authenticators */
224     code = send_auth();
225     if (code) {
226         sprintf(buf, "authorization attempt to %s failed: %s\n",
227                 service_updated, error_message(code));
228         goto update_failed;
229     }
230     
231     /* send file over */
232     fd = open(pathname, O_RDONLY, 0);
233     if (fd < 0) {
234         code = errno;
235         msg = pathname;
236         goto local_error;
237     }
238     sprintf(STRING_DATA(string2), "XFER_002 %d %d %s",
239             size, checksum_fd(fd), info->target_path);
240     code = send_object(conn, (char *)&string2, STRING_T);
241     if (code)
242         IO_ERROR("%s: sending XFER_002 request");
243     code = receive_object(conn, (char *)&num, INTEGER_T);
244     if (code)
245         IO_ERROR("%s: getting reply from XFER_002 request");
246     if (num) {
247         sprintf(buf, "transfer request to %s (XFER_002) rejected: %s",
248                 service_updated, error_message(num));
249     update_failed:
250         sms_log_error(buf);
251         /*
252          *         * if the update fails, something is probably wrong on
253          *         * the remote side; we'll have to let a maintainer
254          *         * take care of it.  don't bother trying again any sooner
255          *         * than INTERVAL_update_failed minutes
256          *         */
257     update_failed_1:
258         if (info->override < INTERVAL_update_failed && info->override != -1)
259             info->override = INTERVAL_update_failed;
260         goto do_quit;
261     }
262     /* send actual data */
263     code = send_file(pathname, size);
264     if (code)
265         goto update_failed_1;
266     string_free(&string_data);
267     close(fd);
268     
269     /* send instructions for installation */
270     strcpy(buf, "/tmp/sms-update.XXXXXX");
271     mktemp(buf);
272     fd = open(info->instructions, O_RDONLY, 0);
273     if (fd < 0) {
274         code = errno;
275         log_priority = log_ERROR;
276         com_err(whoami, code, ": can't open %s", info->instructions);
277         send_quit();
278         info->override = INTERVAL_local_error;
279         goto error_exit;
280     }
281     if (fstat(fd, &statb)) {
282         code = errno;
283         close(fd);
284         fd = -1;
285         log_priority = log_ERROR;
286         com_err(whoami, code, ": can't fstat %s", info->instructions);
287         goto error_exit;
288     }
289     sprintf(STRING_DATA(string2), "XFER_002 %d %d %s",
290             statb.st_size, checksum_fd(fd), buf);
291     code = send_object(conn, (char *)&string2, STRING_T);
292     if (code)
293         IO_ERROR("%s: sending request for transfer of instructions");
294     code = receive_object(conn, (char *)&num, INTEGER_T);
295     if (code)
296         IO_ERROR("%s: lost reply from installation script request");
297     if (num) {
298         com_err(whoami, num, ": transfer request rejected for %s", buf);
299         goto update_failed_1;
300     }
301     code = send_file(info->instructions, statb.st_size);
302     if (code)
303         goto update_failed_1;
304     
305     /* perform installation */
306     code = execute(buf);
307     if (code) {
308         sprintf(buf, "installation of %s failed: %s", service_updated,
309                 error_message(code));
310         sms_log_error(buf);
311     }
312     
313     /* clear override timer and indicate success */
314     info->override = -1;
315     info->success = 1;
316
317     /* finished updates */
318 do_quit:
319     send_quit();
320     
321     /* fall through */
322 EGRESS:
323     code = 0;
324 error_exit:
325     info->last_time = time((long *)0);
326     if (STRING_DATA(string2))
327         string_free(&string2);
328     if (STRING_DATA(string_data))
329         string_free(&string_data);
330     conn = sever_connection(conn);
331     return(code);
332     
333 local_error:
334     log_priority = log_ERROR;
335     com_err(whoami, code, code ? ": %s" : "%s", msg);
336     return(SMSU_INTERNAL_ERROR);
337     
338 io_error:
339     sms_log_error(buf);
340     if (info->override== -1 || info->override > INTERVAL_connection_lost)
341         info->override = INTERVAL_connection_lost;
342     goto EGRESS;
343     
344 #undef IO_ERROR
345 #undef NONNULL
346 #undef ASSERT
347 }
348
349 static
350 send_auth()
351 {
352     KTEXT_ST ticket_st;
353     KTEXT ticket = &ticket_st;
354     STRING data;
355     register int code;
356     int response;
357     
358     code = get_sms_update_ticket(info->host_name, ticket);
359     if (code) {
360         return(code);
361     }
362     STRING_DATA(data) = "AUTH_001";
363     MAX_STRING_SIZE(data) = 9;
364     code = send_object(conn, (char *)&data, STRING_T);
365     if (code) {
366         return(connection_errno(conn));
367     }
368     code = receive_object(conn, (char *)&response, INTEGER_T);
369     if (code) {
370         return(connection_errno(conn));
371     }
372     if (response) {
373         return(response);
374     }
375     STRING_DATA(data) = (char *)ticket->dat;
376     MAX_STRING_SIZE(data) = ticket->length;
377     code = send_object(conn, (char *)&data, STRING_T);
378     if (code) {
379         return(connection_errno(conn));
380     }
381     code = receive_object(conn, (char *)&response, INTEGER_T);
382     if (code) {
383         return(connection_errno(conn));
384     }
385     if (response) {
386         return(response);
387     }
388     return(0);
389 }
390
391 static
392 execute(path)
393     char *path;
394 {
395     int response;
396     STRING data;
397     register int code;
398     
399     string_alloc(&data, BUFSIZ);
400     sprintf(STRING_DATA(data), "EXEC_002 %s", path);
401     code = send_object(conn, (char *)&data, STRING_T);
402     if (code)
403         return(connection_errno(conn));
404     code = receive_object(conn, (char *)&response, INTEGER_T);
405     if (code)
406         return(connection_errno(conn));
407     if (response)
408         return(response);
409     return(0);
410 }
411
412 send_quit()
413 {
414     STRING str;
415     if (!conn)
416         return;
417     string_alloc(&str, 5);
418     (void) strcpy(STRING_DATA(str), "quit");
419     (void) send_object(conn, (char *)&str, STRING_T);
420     string_free(&str);
421 }
This page took 0.154651 seconds and 5 git commands to generate.