7 static char *rcsid_client2_c = "$Header$";
11 * MODULE IDENTIFICATION:
13 * Copyright 1987 MIT Project Athena.
15 * This code handles the actual distribution of data files
16 * to servers in the SMS server-update program.
18 * Ken Raeburn (spook@athena.MIT.EDU),
19 * MIT Project Athena/MIT Information Systems.
26 * Revision 1.1 1987-08-22 17:53:46 wesommer
36 #include <sys/param.h>
39 #include "sms_update_int.h"
43 extern char *malloc(), *error_message();
50 static char buf[BUFSIZ];
53 struct update_desc *info;
61 * Insures that various libraries have a chance to get
68 * Initializes GDB library and SMSU error table.
76 static int initialized = 0;
86 * sms_update_server(info)
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).
96 * Name of service to be updated; used to find
97 * the source data file in the SMS data directory.
100 * Location to install the file.
104 * Sequence of commands to execute on remote
105 * machine to effect the installation.
108 * Set to the current time if the update was
111 * Set to non-zero if the update succeeded, set
114 * Set to -1 if the update succeeds, to (possibly)
115 * some other value otherwise.
118 * Error code, or zero if no error was detected
119 * in the data supplied to this routine.
121 * May write information to logs.
127 sms_update_server(update_info, pathname)
128 struct update_desc *update_info;
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;}
138 char *service_address;
139 char *service_updated;
142 STRING string_data, string2;
147 /* variable initializations */
150 service_updated = (char *)NULL;
151 STRING_DATA(string_data) = (char *)NULL;
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++)
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) {
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");
186 string_alloc(&string2, BUFSIZ);
188 sprintf(buf, "starting update for %s", service_updated);
191 fd = open(pathname, O_RDONLY, 0);
197 if (fstat(fd, &statb)) {
200 strcat(buf, ": can't fstat:");
201 strcat(buf, error_message(code));
205 size = statb.st_size;
207 /* open connection */
208 conn = start_server_connection(service_address, 0);
210 com_err(whoami, 0, "can't connect to update %s", service_address);
212 if (info->override<0 || info->override>INTERVAL_connection_failed)
213 info->override = INTERVAL_connection_failed;
216 else if (connection_status(conn) == CON_STOPPED) {
217 com_err(whoami, connection_errno(conn), ": can't connect to update %s",
223 /* send authenticators */
226 sprintf(buf, "authorization attempt to %s failed: %s\n",
227 service_updated, error_message(code));
232 fd = open(pathname, O_RDONLY, 0);
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);
242 IO_ERROR("%s: sending XFER_002 request");
243 code = receive_object(conn, (char *)&num, INTEGER_T);
245 IO_ERROR("%s: getting reply from XFER_002 request");
247 sprintf(buf, "transfer request to %s (XFER_002) rejected: %s",
248 service_updated, error_message(num));
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
258 if (info->override < INTERVAL_update_failed && info->override != -1)
259 info->override = INTERVAL_update_failed;
262 /* send actual data */
263 code = send_file(pathname, size);
265 goto update_failed_1;
266 string_free(&string_data);
269 /* send instructions for installation */
270 strcpy(buf, "/tmp/sms-update.XXXXXX");
272 fd = open(info->instructions, O_RDONLY, 0);
275 log_priority = log_ERROR;
276 com_err(whoami, code, ": can't open %s", info->instructions);
278 info->override = INTERVAL_local_error;
281 if (fstat(fd, &statb)) {
285 log_priority = log_ERROR;
286 com_err(whoami, code, ": can't fstat %s", info->instructions);
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);
293 IO_ERROR("%s: sending request for transfer of instructions");
294 code = receive_object(conn, (char *)&num, INTEGER_T);
296 IO_ERROR("%s: lost reply from installation script request");
298 com_err(whoami, num, ": transfer request rejected for %s", buf);
299 goto update_failed_1;
301 code = send_file(info->instructions, statb.st_size);
303 goto update_failed_1;
305 /* perform installation */
308 sprintf(buf, "installation of %s failed: %s", service_updated,
309 error_message(code));
313 /* clear override timer and indicate success */
317 /* finished updates */
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);
334 log_priority = log_ERROR;
335 com_err(whoami, code, code ? ": %s" : "%s", msg);
336 return(SMSU_INTERNAL_ERROR);
340 if (info->override== -1 || info->override > INTERVAL_connection_lost)
341 info->override = INTERVAL_connection_lost;
353 KTEXT ticket = &ticket_st;
358 code = get_sms_update_ticket(info->host_name, ticket);
362 STRING_DATA(data) = "AUTH_001";
363 MAX_STRING_SIZE(data) = 9;
364 code = send_object(conn, (char *)&data, STRING_T);
366 return(connection_errno(conn));
368 code = receive_object(conn, (char *)&response, INTEGER_T);
370 return(connection_errno(conn));
375 STRING_DATA(data) = (char *)ticket->dat;
376 MAX_STRING_SIZE(data) = ticket->length;
377 code = send_object(conn, (char *)&data, STRING_T);
379 return(connection_errno(conn));
381 code = receive_object(conn, (char *)&response, INTEGER_T);
383 return(connection_errno(conn));
399 string_alloc(&data, BUFSIZ);
400 sprintf(STRING_DATA(data), "EXEC_002 %s", path);
401 code = send_object(conn, (char *)&data, STRING_T);
403 return(connection_errno(conn));
404 code = receive_object(conn, (char *)&response, INTEGER_T);
406 return(connection_errno(conn));
417 string_alloc(&str, 5);
418 (void) strcpy(STRING_DATA(str), "quit");
419 (void) send_object(conn, (char *)&str, STRING_T);