Changeset 352 in MondoRescue for branches/stable/monitas/client.c
- Timestamp:
- Jan 28, 2006, 6:41:40 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/monitas/client.c
r351 r352 4 4 5 5 6 6 7 FIXME 7 - fork child process ('daemon', almost) to interact with server 8 - parent process will interact with keyboard ('logout'=quit) 9 - if trigger_backup msg arrives then act accordingly 10 - remember, the client is a 'server' from the minute it logs in 11 until the minute it logs out of the server: the client listens 12 on a port between 8800 and 8899, waiting for incoming msgs 13 from server; all the forked process has to do is take over the 14 task of watching that port and act on the incoming data 15 - when trigger_backup is received then send file along connection 16 17 05/19 8 - perror() --- replace with log_it() 9 10 11 12 06/19 13 - fixed bugs in mondoarchive compare code 14 - added track_restore_task_progress() 15 16 06/16 17 - when calling mondoarchive in bkgd, see if it starts OK; if it 18 doesn't then say so & return error 19 20 06/14 21 - added a FIFO to let user request backup/compare/restore 22 - send progress info to server - % done, etc. - when backing up 23 - pipe logs to logfile, not stdout 24 25 06/11 26 - added call to register_pid() 27 - commented code a bit 28 - implemented compare_archives and restore_archives() 29 30 06/10 31 - create function to call external executable in background 32 - create function to wait for it to terminate & to grab its result 33 - put them in common.c 34 35 05/27 36 - fixed watch_port_for_triggers() 37 - turned st_'s into a global and some locals 38 - fork in login thingy becomes a thread 39 - added bind_client_port() 40 - added accept_and_recv_thru_client_port() 41 - changed flag (recv) from DONTWAIT to 0 [no flag] 42 43 05/21 44 - added back_my_smitch_up(), compare_archives(), restore_archives() 45 - added log_it(); fixed fprintf(stderr,"") and printf() reporting 46 - parallelize/fork the 'watch for triggers from server' process 18 47 - added tmsg_to_string() 19 48 - forked port-watcher to receive triggers from server in bkgd … … 32 61 33 62 #include "structs.h" 63 //#define LOG_THESE_AND_HIGHER debug 64 #define LOGFILE "/var/log/monitas-client.log" 34 65 35 66 … … 37 68 /* global vars */ 38 69 39 70 bool g_logged_in_currently=false, g_logging_out=false; 71 int g_sClient=-1, g_client_port=0; /* client port; set by login */ 72 struct sockaddr_in g_sinClient; /* client port */ 73 char g_server_name[MAX_STR_LEN+1]; 74 pthread_t g_mondo_thread=0; 75 char g_command_fifo[MAX_STR_LEN+1]; 76 char g_logfile[MAX_STR_LEN+1] = "/var/log/monitas-client.log"; 77 78 /* externs */ 79 80 extern char *call_program_and_get_last_line_of_output(char*); 81 extern int call_program_and_log_output(char*); 82 extern void call_program_in_background(pthread_t*, char*); 83 extern int create_and_watch_fifo_for_commands(char*); 84 extern bool does_file_exist(char*); 85 extern int get_bkgd_prog_result(pthread_t*); 86 extern void log_it_SUB(char*, t_loglevel level, char *sz_message); 87 extern bool program_still_running(char*); 88 extern int receive_file_from_socket(FILE*, int); 89 extern void register_pid(pid_t, char*); 90 extern char *tmsg_to_string(t_msg msg_type); 91 extern int transmit_file_to_socket(FILE*, int); 92 extern void register_pid(pid_t, char*); 93 extern void set_signals(bool); 40 94 41 95 /* prototypes */ 42 96 97 int accept_and_recv_thru_client_port(int, int*, struct sockaddr_in*, char*, int); 98 int back_my_smitch_up(char*, int); 99 int bind_client_port(struct sockaddr_in*, int); 100 int compare_archives(char*, int); 43 101 int find_and_bind_free_server_port(struct sockaddr_in*, int*); 44 102 long increment_magic_number(void); 45 103 int login_to_server(char*,char*); 104 void logout_and_exit(char*); 46 105 int logout_of_server(char*); 106 int process_incoming_command(char*); 107 int restore_archives(char*, char*, int); 108 void restore_archives_SIGPIPE(int); 109 int send_final_progress_report(char*); 47 110 int send_msg_to_server(struct s_client2server_msg_record*, char*); 48 111 int send_ping_to_server(char*,char*); 49 char *tmsg_to_string(t_msg); 50 void watch_port_for_triggers_from_server(struct sockaddr_in *, int, int); 51 52 /* subroutines */ 112 int send_progress_rpt_to_server(char*, char*); 113 void terminate_daemon(int); 114 void *track_backup_task_progress(void*); 115 void *track_compare_task_progress(void*); 116 void *track_restore_task_progress(void*); 117 void *watch_port_for_triggers_from_server(void*); 118 119 120 121 122 /*-----------------------------------------------------------*/ 123 124 125 126 int accept_and_recv_thru_client_port(int sClient, int *new_sClient, struct sockaddr_in*sinClient, char*incoming, int expected_length) 127 /* 128 Purpose:Run accept() and recv() to open port and receive 129 message from server. 130 Params: sClient - file descriptor of port 131 new_sClient - [returned] file descriptor of the 132 new connection to port which we open in this func 133 sinClient - record about port 134 expected_length - expected length of incoming block 135 Return: length of block received, or <0 if error 136 */ 137 { 138 int len; 139 140 len = sizeof(struct sockaddr_in); 141 if ((*new_sClient = accept(sClient, (struct sockaddr*)sinClient, (unsigned int*)&len)) < 0) { log_it(error, "[child] Cannot accept"); return(-6); } 142 if ((len = recv(*new_sClient, incoming, expected_length, /*MSG_DONTWAIT*/0)) <= 0) { log_it(error, "[child] Cannot recv"); return(-7); } 143 return(len); 144 } 145 146 147 148 /*-----------------------------------------------------------*/ 149 150 151 152 char *get_param_from_rcfile(char*fname, char*field) 153 { 154 char command[MAX_STR_LEN+1], tmp[MAX_STR_LEN+1]; 155 static char sz_res[MAX_STR_LEN+1]; 156 157 sz_res[0]='\0'; 158 if (does_file_exist(fname)) 159 { 160 sprintf(command, "cat %s | grep %s= | cut -d'=' -f2,3,4,5,6,7,8,9", fname, field); 161 strcpy(tmp, call_program_and_get_last_line_of_output(command)); 162 strcpy(sz_res, tmp); 163 } 164 return(sz_res); 165 } 166 167 168 169 int back_my_smitch_up(char*msgbody, int socket_fd) 170 /* 171 Purpose:Backup archives to server. 172 Params: msgbody - char[MSG_BODY_SIZE] containing info 173 about the archives to be created 174 socket_fd - file descriptor to which to 175 write the archives to server. 176 Return: result (0=success; nonzero=failure) 177 */ 178 { 179 char tmp[MAX_STR_LEN+1], command[MAX_STR_LEN+1], tempdev[MAX_STR_LEN+1]; 180 char temporary_logfile[MAX_STR_LEN+1]; // where mondoarchive writes its stdout,stderr 181 char mondoparams_str[MAX_STR_LEN+1]; 182 struct s_server2client_msg_record incoming_rec; 183 int retval=0, len, new_sClient, res=0; 184 FILE*fin; 185 pthread_t progress_thread; 186 187 sprintf(tmp, "Backup of %s commenced", msgbody); 188 log_it(info, tmp); 189 if (send_progress_rpt_to_server(g_server_name, tmp)) { log_it(error, "Unable to send 'yep, got this msg' progress_rpt to server"); } 190 sprintf(temporary_logfile, "/tmp/monitas-client.templog.%d", (int)random()%32767); 191 sprintf(tempdev, "/tmp/monitas-client.device.%d", (int)random()%32767); 192 unlink(tempdev); 193 if (mkfifo(tempdev, 700)) 194 { 195 log_it(error, "Unable to create temporary data output fifo in preparation for the call to mondoarchive"); 196 return(1); 197 } 198 unlink(temporary_logfile); 199 if (mkfifo(temporary_logfile, 700)) 200 { 201 log_it(error, "Unable to create temporary logfile fifo in preparation for the call to mondoarchive"); 202 return(1); 203 } 204 strcpy(mondoparams_str, get_param_from_rcfile(CLIENT_RCFILE, "mondoarchive_params")); 205 sprintf(tmp, "mondoarchive_params --> '%s'", mondoparams_str); 206 log_it(debug, tmp); 207 sprintf(command, "mondoarchive -Ou %s -d %s -I %s -F &> %s; rm -f %s %s", mondoparams_str, tempdev, msgbody, temporary_logfile, tempdev, temporary_logfile); 208 call_program_in_background(&g_mondo_thread, command); 209 sleep(10); 210 if (!program_still_running(command)) 211 { res=1; log_it(error, "Unable to start mondoarchive. Please check /var/log/mondo-archive.log"); } 212 else 213 { 214 if (pthread_create(&progress_thread, NULL, track_backup_task_progress, (void*)temporary_logfile)) 215 { log_it(error, "Cannot create pthread to track mondo task progress"); return(1); } 216 log_it(debug, "Opening fopen() to tempdev"); 217 if (!(fin = fopen(tempdev, "r"))) { log_it(error, "Cannot open FIFO"); return(1); } 218 log_it(debug, "fopen() OK"); 219 retval = transmit_file_to_socket(fin, socket_fd); 220 fclose(fin); 221 res = get_bkgd_prog_result(&g_mondo_thread); 222 pthread_join(progress_thread, NULL); 223 } 224 if (res) 225 { retval++; log_it(error, "Mondoarchive returned an error. Notifying server..."); } 226 if (res) 227 { retval++; log_it(error, "Mondoarchive returned an error."); } 228 if (retval) { log_it(debug, "Errors have occurred. Notifing server..."); } 229 else { log_it(debug, "Everything is OK so far. Notifying server..."); } 230 if (write(socket_fd, (char*)&retval, sizeof(retval))!=sizeof(retval)) {retval++;} 231 /* receive msg from server; did backup go OK at its end or not? */ 232 unlink(tempdev); 233 unlink(temporary_logfile); 234 log_it(debug, "Waiting for progress thread to join us"); 235 log_it(debug, "Groovy. Continuing.."); 236 len = accept_and_recv_thru_client_port(g_sClient, &new_sClient, &g_sinClient, (char*)&incoming_rec, sizeof(incoming_rec)); 237 if (len<0) { log_it(error, "After backup, unable to accept/recv thru client port"); return(-10); } 238 sprintf(tmp, "After backup, I received %s - %s", tmsg_to_string(incoming_rec.msg_type), incoming_rec.body); 239 log_it(debug, tmp); 240 if (incoming_rec.msg_type == backup_fail) 241 { retval++; log_it(error, "Server reported error(s) during backup, although client didn't."); } 242 if (retval) 243 { 244 sprintf(tmp, "Backup of %s failed", msgbody); 245 log_it(error, tmp); 246 call_program_and_log_output("tail -n6 /var/log/mondo-archive.log"); 247 } 248 else 249 { 250 sprintf(tmp, "Server agrees, backup of %s succeeded :-)", msgbody); 251 log_it(info, tmp); 252 } 253 if (send_final_progress_report(tmp) < 0) { retval++; log_it(error, "Unable to send final progress_rpt to server"); } 254 return(retval); 255 } 256 257 258 259 /*-----------------------------------------------------------*/ 260 261 262 263 int bind_client_port(struct sockaddr_in *sinClient, int client_port) 264 /* 265 Purpose:Bind one of my ports so that I may open it later and 266 write/read data to/from server with it. 267 Params: sinClient - record/structure relating to the socket 268 client_port - port# to be bound 269 Return: socket handle, to be used by other subroutines, if success 270 or <0 if failure 271 */ 272 { 273 int sClient=-1; 274 char tmp[MAX_STR_LEN+1]; 275 276 memset((void*)sinClient, 0, sizeof(struct sockaddr_in)); 277 sinClient->sin_family = AF_INET; 278 sinClient->sin_addr.s_addr = INADDR_ANY; 279 sinClient->sin_port = htons(client_port); 280 if ((sClient = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 281 { 282 sprintf(tmp, "Unable to open socket on port #%d", g_client_port); 283 log_it(error, tmp); 284 return(-1); 285 } 286 if (bind(sClient, (struct sockaddr*)sinClient, sizeof(struct sockaddr_in)) < 0) 287 { 288 sprintf(tmp, "Cannot bind %d - %s", g_client_port, strerror(errno)); 289 log_it(error, tmp); 290 return(-2); 291 } 292 if (listen(sClient, MAX_PENDING) < 0) 293 { 294 sprintf(tmp, "Cannot setup listen (%d) - %sn", g_client_port, strerror(errno)); 295 log_it(error, tmp); 296 return(-3); 297 } 298 log_it(debug, "Successfully bound client port."); 299 return(sClient); 300 } 301 302 303 304 /*-----------------------------------------------------------*/ 305 306 307 308 int compare_archives(char*msgbody, int socket_fd) 309 /* 310 Purpose:Compare archives, sent by server. 311 Params: msgbody - char[MSG_BODY_SIZE] containing info 312 about the archives to be compared 313 socket_fd - file descriptor from which to 314 read the archives sent by server to be compared. 315 Return: result (0=success; nonzero=failure) 316 */ 317 { 318 char tmp[MAX_STR_LEN+1], command[MAX_STR_LEN+1], tempdev[MAX_STR_LEN+1], *p; 319 char temporary_logfile[MAX_STR_LEN+1]; // where mondoarchive writes its stdout,stderr 320 char mondoparams_str[MAX_STR_LEN+1]; 321 struct s_server2client_msg_record incoming_rec; 322 int retval=0, len, new_sClient, res=0; 323 FILE*fout, *fin; 324 long diffs=0; 325 pthread_t progress_thread; 326 327 sprintf(tmp, "Comparison of %s commenced", msgbody); 328 log_it(info, tmp); 329 if (send_progress_rpt_to_server(g_server_name, tmp)) { log_it(error, "Unable to send 'yep, got this msg' progress_rpt to server"); } 330 sprintf(temporary_logfile, "/tmp/monitas-client.templog.%d", (int)random()%32767); 331 sprintf(tempdev, "/tmp/monitas-client.device.%d", (int)random()%32767); 332 unlink(tempdev); 333 if (mkfifo(tempdev, 700)) 334 { 335 log_it(error, "Unable to create temporary fifo in preparation for the call to mondoarchive"); 336 return(1); 337 } 338 unlink(temporary_logfile); 339 if (mkfifo(temporary_logfile, 700)) 340 { 341 log_it(error, "Unable to create temporary logfile fifo in preparation for the call to mondoarchive"); 342 return(1); 343 } 344 strcpy(mondoparams_str, get_param_from_rcfile(CLIENT_RCFILE, "mondoarchive_params")); 345 sprintf(tmp, "mondoarchive_params --> '%s'", mondoparams_str); 346 log_it(debug, tmp); 347 sprintf(command, "mondoarchive -Vu -F %s -d %s -I %s > %s"/*; rm -f %s %s"*/, mondoparams_str, tempdev, msgbody, temporary_logfile/*, tempdev, temporary_logfile*/); 348 call_program_in_background(&g_mondo_thread, command); 349 sleep(5); 350 if (!program_still_running(command)) 351 { res=1; log_it(error, "Unable to start mondoarchive. Please check /var/log/mondo-archive.log"); } 352 else 353 { 354 if (pthread_create(&progress_thread, NULL, track_compare_task_progress, (void*)temporary_logfile)) 355 { log_it(error, "Cannot create pthread to track mondo task progress"); return(1); } 356 fout = fopen(tempdev, "w"); 357 log_it(debug, "Opened fopen() to tempdev"); 358 retval = receive_file_from_socket(fout, socket_fd); 359 log_it(debug, "Calling get_bkgd_prog_result"); 360 fclose(fout); 361 res = get_bkgd_prog_result(&g_mondo_thread); 362 res = 0; // *shrug* Seems to help :) 363 pthread_join(progress_thread, NULL); 364 } 365 if (res) 366 { retval++; log_it(error, "Mondoarchive returned an error."); } 367 if (retval) { log_it(debug, "Errors have occurred. Notifing server..."); } 368 else { log_it(debug, "Everything is OK so far. Notifying server..."); } 369 if (write(socket_fd, (char*)&retval, sizeof(retval))!=sizeof(retval)) {retval++;} 370 /* receive msg from server; did comparison go OK at its end or not? */ 371 unlink(tempdev); 372 unlink(temporary_logfile); 373 len = accept_and_recv_thru_client_port(g_sClient, &new_sClient, &g_sinClient, (char*)&incoming_rec, sizeof(incoming_rec)); 374 if (len<0) { log_it(error, "After comparison, unable to accept/recv thru client port"); return(-10); } 375 sprintf(tmp, "After comparison, I received %s - %s", tmsg_to_string(incoming_rec.msg_type), incoming_rec.body); 376 log_it(debug, tmp); 377 if (incoming_rec.msg_type == compare_fail) 378 { retval++; log_it(error, "Server reported error(s) during comparison, although client didn't."); } 379 if (retval) 380 { 381 sprintf(tmp, "Errors occurred during comparison of %s", msgbody); 382 strcpy(command, call_program_and_get_last_line_of_output("tail -n20 /var/log/mondo-archive.log | grep /tmp/changed | head -n1")); 383 p = strstr(command, "/tmp/changed"); 384 if (p) 385 { 386 strcat(command, " "); 387 sprintf(tmp, "command = '%s'", command); 388 log_it(debug, tmp); 389 *(strchr(p, ' '))='\0'; 390 sprintf(tmp, "Opening list of changed files ('%s')", p); 391 log_it(debug, tmp); 392 log_it(info, "---Changed files---"); 393 if ((fin=fopen(p, "r"))) 394 { for(diffs=0; !feof(fin); diffs++) { fgets(tmp, MAX_STR_LEN, fin); if (strlen(tmp)>0) {tmp[strlen(tmp)-1]='\0';} log_it(info, tmp); } fclose(fin); } 395 log_it(info, "----End of list----"); 396 sprintf(tmp, "%ld differences were found during comparison of %s", diffs, msgbody); 397 log_it(warn, tmp); 398 unlink(p); 399 } 400 else 401 { 402 sprintf(tmp, "Errors occurred during comparison of %s", msgbody); 403 log_it(error, tmp); 404 call_program_and_log_output("tail -n6 /var/log/mondo-archive.log"); 405 log_it(info, "Please check /var/log/mondo-archive.log for more information"); 406 } 407 } 408 else 409 { 410 sprintf(tmp, "Server agrees, comparison of %s succeeded :-)", msgbody); 411 log_it(info, tmp); 412 } 413 if (send_final_progress_report(tmp)) { retval++; log_it(error, "Unable to send final progress_rpt to server"); } 414 return(retval); 415 } 416 417 418 419 /*-----------------------------------------------------------*/ 420 421 53 422 54 423 int find_and_bind_free_server_port(struct sockaddr_in *sin, int *p_s) … … 59 428 Params: sin - server's IP address in a structure 60 429 p_s - [return] file descriptor of port binding 61 Return: result ( 0=success, nonzero=failure)430 Return: result (>0=success, -1=failure) 62 431 */ 63 432 { 64 433 int server_port; 434 char tmp[MAX_STR_LEN+1]; 65 435 66 436 for(server_port = 8700; server_port < 8710; server_port++) … … 70 440 { 71 441 perror("socket"); 72 return( 1);442 return(-1); 73 443 } 74 444 if (connect(*p_s, (struct sockaddr*)sin, sizeof(struct sockaddr_in)) < 0) 75 445 { 76 printf("Not connecting at %d\r", server_port); 446 sprintf(tmp, "Not connecting at %d", server_port); 447 log_it(debug, tmp); 77 448 continue; 78 449 } 79 450 return(server_port); 80 451 } 81 fprintf(stderr, "Cannot find free server port\nIs server actually running?\n"); 82 return(1); 83 } 452 return(-1); 453 } 454 455 456 457 /*-----------------------------------------------------------*/ 84 458 85 459 … … 98 472 return(magic); 99 473 } 474 475 476 477 /*-----------------------------------------------------------*/ 100 478 101 479 … … 113 491 { 114 492 struct s_client2server_msg_record orig_rec; 115 int i;116 493 117 494 orig_rec.msg_type = login; 118 495 strncpy(orig_rec.body, hostname, sizeof(orig_rec.body)); 119 for(i=0; i<3; i++) 120 { 121 if (send_msg_to_server(&orig_rec, servername) > 0) 122 { return(orig_rec.port); } 123 printf("Attempt #%d to login failed. Retrying...\n", i+1); 124 } 125 printf("Failed to login\n"); 126 return(-1); 127 } 496 if (send_msg_to_server(&orig_rec, servername) < 0) 497 { return(-1); } 498 else 499 { return(orig_rec.port); } 500 } 501 502 503 504 /*-----------------------------------------------------------*/ 505 506 507 508 509 void logout_and_exit(char*servername) 510 /* 511 Purpose:Logout of server. Terminate. 512 Params: servername - ip address of server 513 Return: none 514 */ 515 { 516 if (g_logged_in_currently) 517 { 518 if (logout_of_server(servername)) 519 { log_it(warn, "Failed to logout of server."); } 520 } 521 call_program_and_log_output("rm -Rf /tmp/monitas-client.*"); 522 register_pid(0, "client"); 523 // chmod(g_command_fifo, 0); 524 unlink(g_command_fifo); 525 log_it(info, "---------- Monitas (client) has terminated ----------"); 526 exit(0); 527 } 528 529 530 531 /*-----------------------------------------------------------*/ 128 532 129 533 … … 138 542 struct s_client2server_msg_record orig_rec; 139 543 544 g_logging_out = true; 545 log_it(debug, "Logging out of server"); 140 546 orig_rec.msg_type = logout; 141 547 strncpy(orig_rec.body, "Bye bye!", sizeof(orig_rec.body)); 142 if (send_msg_to_server(&orig_rec, servername) < =0)548 if (send_msg_to_server(&orig_rec, servername) < 0) 143 549 { return(1); } 144 550 else … … 148 554 149 555 150 // FIXME - 151 // Are the threads trampling on one another's st_sClient, st_new_sClient's? 152 // I don't see how. After all, there's only one thread... :-) 556 /*-----------------------------------------------------------*/ 557 558 559 560 int process_incoming_command(char*incoming) 561 /* 562 Purpose:Process incoming command, presumably 563 read from FIFO and sent there by sysadm/user. 564 Params: incoming - raw command string itself 565 Return: result (0=success; nonzero=failure) 566 */ 567 { 568 int res=0; 569 char tmp[MAX_STR_LEN+1]; 570 int pos, i; 571 char command[MAX_STR_LEN+1], path[MAX_STR_LEN+1], aux[MAX_STR_LEN+1]; 572 struct s_client2server_msg_record orig_rec; 573 574 pos=0; 575 sscanf(incoming, "%s %s", command, path); 576 for(i=0; i<strlen(command); i++) { command[i]=command[i]|0x60; } 577 if (!strcmp(command, "restore")) 578 { sscanf(incoming, "%s %s %s", command, path, aux); } 579 else 580 { aux[0] = '\0'; } 581 sprintf(tmp, "cmd=%s path=%s aux=%s", command, path, aux); 582 log_it(debug, tmp); 583 sprintf(tmp, "%s of %s [aux='%s'] <-- command received", command, path, aux); 584 log_it(info, tmp); 585 if (strcmp(command, "restore") && aux[0]!='\0') 586 { log_it(warn, "Ignoring auxiliary parameter: it is superfluous."); } 587 if (strcmp(command, "backup") && strcmp(command, "compare") && strcmp(command, "restore")) 588 { 589 sprintf(tmp, "%s - command unknown.", command); 590 log_it(error, tmp); 591 res=1; 592 } 593 else 594 { 595 sprintf(tmp, "'%s' sent to server as a formal request", incoming); 596 orig_rec.msg_type = user_req; 597 strncpy(orig_rec.body, incoming, sizeof(orig_rec.body)); 598 if (send_msg_to_server(&orig_rec, g_server_name) < 0) 599 { res++; log_it(error, "Unable to send user req to server"); } 600 else 601 { log_it(debug, tmp); } 602 } 603 return(res); 604 } 605 606 607 608 /*-----------------------------------------------------------*/ 609 610 611 612 int restore_archives(char*msgbody, char*msgbodyAux, int socket_fd) 613 /* 614 Purpose:Restore archives, sent by server. 615 Params: msgbody - char[MSG_BODY_SIZE] containing info 616 about the archives to be restored 617 socket_fd - file descriptor from which to 618 read the archives sent by server. 619 Return: result (0=success; nonzero=failure) 620 */ 621 { 622 char tmp[MAX_STR_LEN+1], command[MAX_STR_LEN+1], tempdev[MAX_STR_LEN+1], *p; 623 char temporary_logfile[MAX_STR_LEN+1]; // where mondorestore writes its stdout,stderr 624 struct s_server2client_msg_record incoming_rec; 625 int retval=0, len, new_sClient, res=0; 626 FILE*fout, *fin; 627 long diffs=0; 628 pthread_t progress_thread; 629 630 sprintf(tmp, "Restoration of %s commenced", msgbody); 631 log_it(info, tmp); 632 if (send_progress_rpt_to_server(g_server_name, tmp)) { log_it(error, "Unable to send 'yep, got this msg' progress_rpt to server"); } 633 sprintf(temporary_logfile, "/tmp/monitas-client.templog.%d", (int)random()%32767); 634 sprintf(tempdev, "/tmp/monitas-client.device.%d", (int)random()%32767); 635 unlink(tempdev); 636 if (mkfifo(tempdev, 700)) 637 { 638 log_it(error, "Unable to create temporary fifo in preparation for the call to mondorestore"); 639 return(1); 640 } 641 unlink(temporary_logfile); 642 if (mkfifo(temporary_logfile, 700)) 643 { 644 log_it(error, "Unable to create temporary logfile in preparation for the call to mondorestore"); 645 return(1); 646 } 647 sprintf(command, "mondorestore --monitas-live %s %s %s &> %s", tempdev, msgbody, msgbodyAux, temporary_logfile); 648 // sprintf(command, "cat %s > %s", tempdev, "/tmp/out.dat"); 649 call_program_in_background(&g_mondo_thread, command); 650 sleep(5); 651 if (!program_still_running(command)) 652 { 653 res=1; log_it(error, "mondorestore could not be started. Please check /tmp/mondo-restore.log"); 654 } 655 else 656 { 657 if (pthread_create(&progress_thread, NULL, track_restore_task_progress, (void*)temporary_logfile)) 658 { log_it(error, "Cannot create pthread to track mondo task progress"); return(1); } 659 fout = fopen(tempdev, "w"); 660 log_it(debug, "Opened fopen() to tempdev"); 661 retval = receive_file_from_socket(fout, socket_fd); 662 if (retval && !system("cat /tmp/mondo-restore.log | grep -i \"End of restore_live_from_monitas_server\" &> /dev/null")) 663 { 664 retval=0; 665 log_it(debug, "SIGPIPE caught but that's OK, it was anticipated."); 666 res=0; 667 } 668 log_it(debug, "Calling get_bkgd_prog_result"); 669 fclose(fout); 670 res = get_bkgd_prog_result(&g_mondo_thread); 671 pthread_join(progress_thread, NULL); 672 } 673 unlink(tempdev); 674 unlink(temporary_logfile); 675 if (res) 676 { retval++; log_it(error, "mondorestore returned an error."); } 677 if (retval) { log_it(debug, "Errors have occurred. Notifing server..."); } 678 else { log_it(debug, "Everything is OK so far. Notifying server..."); } 679 sleep(1); // probably unnecessary 680 /* I do this thrice because mondorestore often causes a SIGPIPE, which means... I have to do this thrice :-) */ 681 if (write(socket_fd, (char*)&retval, sizeof(retval))!=sizeof(retval)) {log_it(debug, "Failed to write wtf-info"); retval++;} 682 if (write(socket_fd, (char*)&retval, sizeof(retval))!=sizeof(retval)) {log_it(debug, "Failed to write wtf-info"); retval++;} 683 if (write(socket_fd, (char*)&retval, sizeof(retval))!=sizeof(retval)) {log_it(debug, "Failed to write wtf-info"); retval++;} 684 /* receive msg from server; did restoration go OK at its end or not? */ 685 unlink(tempdev); 686 unlink(temporary_logfile); 687 len = accept_and_recv_thru_client_port(g_sClient, &new_sClient, &g_sinClient, (char*)&incoming_rec, sizeof(incoming_rec)); 688 if (len<0) { log_it(error, "After restoration, unable to accept/recv thru client port"); return(-10); } 689 sprintf(tmp, "After restoration, I received %s - %s", tmsg_to_string(incoming_rec.msg_type), incoming_rec.body); 690 log_it(debug, tmp); 691 if (incoming_rec.msg_type == restore_fail) 692 { retval++; log_it(error, "Server reported error(s) during restoration, although client didn't."); } 693 if (retval) 694 { 695 sprintf(tmp, "Errors occurred during restoration of %s", msgbody); 696 strcpy(command, call_program_and_get_last_line_of_output("tail -n20 /var/log/mondo-archive.log | grep /tmp/changed | head -n1")); 697 p = strstr(command, "/tmp/changed"); 698 if (p) 699 { 700 strcat(command, " "); 701 sprintf(tmp, "command = '%s'", command); 702 log_it(debug, tmp); 703 *(strchr(p, ' '))='\0'; 704 sprintf(tmp, "Opening list of changed files ('%s')", p); 705 log_it(debug, tmp); 706 log_it(info, "---Changed files---"); 707 if ((fin=fopen(p, "r"))) 708 { for(diffs=0; !feof(fin); diffs++) { fgets(tmp, MAX_STR_LEN, fin); if (strlen(tmp)>0) {tmp[strlen(tmp)-1]='\0';} log_it(info, tmp); } fclose(fin); } 709 log_it(info, "----End of list----"); 710 sprintf(tmp, "%ld differences were found during restoration of %s", diffs, msgbody); 711 log_it(warn, tmp); 712 } 713 else 714 { 715 sprintf(tmp, "Errors occurred during restoration of %s", msgbody); 716 log_it(error, tmp); 717 call_program_and_log_output("tail -n6 /var/log/mondo-archive.log"); 718 log_it(info, "Please check /var/log/mondo-archive.log for more information"); 719 } 720 } 721 else 722 { 723 sprintf(tmp, "Server agrees, restoration of %s succeeded :-)", msgbody); 724 log_it(info, tmp); 725 } 726 if (send_final_progress_report(tmp)) { retval++; log_it(error, "Unable to send final progress_rpt to server"); } 727 return(retval); 728 } 729 730 731 732 /*-----------------------------------------------------------*/ 733 734 735 736 void *send_final_progress_report_SUB(void*inp) 737 { 738 char message[MAX_STR_LEN+1]; 739 740 strncpy(message, (char*)inp, MAX_STR_LEN); 741 sleep(10); 742 send_progress_rpt_to_server(g_server_name, message); 743 pthread_exit(NULL); 744 } 745 746 747 748 int send_final_progress_report(char*final_string) 749 { 750 pthread_t thread; 751 752 if (send_progress_rpt_to_server(g_server_name, final_string)) { return(1); } 753 if (pthread_create(&thread, NULL, send_final_progress_report_SUB, (void*)"Idle")) { log_it(error, "Unable to create pthread"); return(1); } 754 return(0); 755 } 756 757 758 759 /*-----------------------------------------------------------*/ 760 761 762 153 763 int send_msg_to_server(struct s_client2server_msg_record *rec, char *servername) 154 764 /* 155 765 Purpose:Send message to server - a login/logout/ping request 156 766 or perhaps a request for data to be restored. 157 767 Params: rec - the message to be sent to server 158 159 Return: result ( -1=failure, >0=success)768 servername - the hostname of server 769 Return: result (<0=failure, 0+=success) 160 770 */ 161 771 { 162 772 struct hostent *hp; 163 773 struct sockaddr_in sin; 164 static struct sockaddr_in st_sinClient; /* client port; connected by login; closed by logout */ 165 static int st_sClient; /* client connection */ 166 static int st_new_sClient; 167 int server_port, s, len; 168 static int st_client_port=0; /* client port; set by login */ 774 int server_port, new_sClient, s, len, res; 169 775 struct s_server2client_msg_record incoming_rec; 170 776 struct pollfd ufds; 171 static t_pid st_pid=-1; 777 char tmp[MAX_STR_LEN+1]; 778 void *thread_result; 779 pthread_t a_thread; 172 780 173 781 /* If logging out then kill the trigger-watcher before trying; 174 otherwise, the trigger-watcher will probably catch the 175 'logout_ok' packet and go nutty on us :-) 176 */ 177 if (rec->msg_type == logout) 178 { 179 sprintf(tmp, "kill %d &> /dev/null", st_pid); 180 system(tmp); 181 // kill(st_pid); 182 st_pid = -1; 183 } 184 185 /* st_sinClient, st_new_sClient and st_sClient contain info 186 relating to the permanent socket which this subroutine 187 opens at login-time so that it can listen for messages 188 from the server. This subroutine doesn't watch the 189 socket all the time (yet) but it leaves it open until 190 logout-time, for neatness' sake. 191 */ 192 if ((hp = gethostbyname(servername)) == NULL) { fprintf(stderr, "%s: unknown host\n", servername); return(1); } 193 if (st_client_port > 0 && rec->msg_type == login) { fprintf(stderr, "Already logged in. Why try again?\n"); return(1); } 194 if (st_client_port <= 0 && rec->msg_type != login) { fprintf(stderr, "Don't try to send msgs before logging in.\n"); return(1); } 782 otherwise, the trigger-watcher will probably catch the 783 'logout_ok' packet and go nutty on us :-) 784 */ 785 if ((hp = gethostbyname(servername)) == NULL) 786 { 787 sprintf(tmp, "%s: unknown host", servername); 788 log_it(error, tmp); 789 return(-1); 790 } 791 if (g_logged_in_currently && rec->msg_type == login) { log_it(error, "Already logged in. Why try again?"); return(-1); } 792 if (!g_logged_in_currently && rec->msg_type != login) 793 { 794 log_it(fatal, "Server has forcibly logged you out."); 795 } /* or you never logged in to begin which, which suggests the programmer screwed up */ 195 796 /* open client port if login */ 196 197 797 if (rec->msg_type == login) 198 798 { 199 printf("Logging in\n"); 200 st_client_port = 8800 + rand()%100; // FIXME: retry if I can't use this port 201 memset((void*)&st_sinClient, 0, sizeof(st_sinClient)); 202 st_sinClient.sin_family = AF_INET; 203 st_sinClient.sin_addr.s_addr = INADDR_ANY; 204 st_sinClient.sin_port = htons(st_client_port); 205 if ((st_sClient = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { fprintf(stderr, "Unable to open socket on port #%d\n", st_client_port); return(1); } 206 if (bind(st_sClient, (struct sockaddr*)&st_sinClient, sizeof(st_sinClient)) < 0) { fprintf(stderr, "Cannot bind %d - %s\n", st_client_port, strerror(errno)); return(2); } 207 if (listen(st_sClient, MAX_PENDING) < 0) { fprintf(stderr, "Cannot setup listen (%d) - %s\n", st_client_port, strerror(errno)); return(3); } 208 } 209 799 log_it(info, "Trying to login"); 800 g_client_port = 8800 + rand()%100; // FIXME: retry if I can't use this port 801 g_sClient = bind_client_port(&g_sinClient, g_client_port); 802 if (g_sClient<0) { log_it(error, "Cannot bind client port"); return(-1); } 803 } 210 804 /* send msg to server */ 211 rec->port = st_client_port;805 rec->port = g_client_port; 212 806 memset((void*)&sin, 0, sizeof(sin)); 213 807 sin.sin_family = AF_INET; 214 808 memcpy((void*)&sin.sin_addr, hp->h_addr, hp->h_length); 215 809 server_port = find_and_bind_free_server_port(&sin, &s); 216 if (server_port<=0) { fprintf(stderr, "Cannot find free server port\nIs server running?\n"); return(1); } 810 if (server_port<=0) 811 { 812 sprintf(tmp, "Cannot find+bind free server port. Is server running?"); 813 log_it(error, tmp); 814 return(-3); 815 } 217 816 rec->magic = increment_magic_number(); 218 817 send (s, (char*)rec, sizeof(struct s_client2server_msg_record), 0); 219 818 close(s); 220 221 /* wait for ack/pong/feedback */ 222 ufds.fd = st_sClient; 223 ufds.events = POLLIN|POLLPRI; 224 poll(&ufds, 1, 1000); 225 if (!ufds.revents) { fprintf(stderr,"Failed to poll\n"); return(-1); } 226 len = sizeof(st_sinClient); 227 if ((st_new_sClient = accept(st_sClient, (struct sockaddr*)&st_sinClient, &len)) < 0) { fprintf(stderr,"[child] Cannot accept\n"); return(1); } 228 if ((len = recv(st_new_sClient, (char*)&incoming_rec, sizeof(incoming_rec), MSG_DONTWAIT)) <= 0) { fprintf(stderr, "[child] Cannot recv\n"); return(2); } 229 230 printf("Received %s - %s\n", tmsg_to_string(incoming_rec.msg_Type, incoming_rec.body); 231 if (rec->msg_type != login && incoming_rec.msg_type == login_ok) { fprintf(stderr, "WTF? login_ok but I wasn't logging in\n"); } 232 if (rec->msg_type != logout&& incoming_rec.msg_type == logout_ok){ fprintf(stderr, "WTF? logout_ok but I wasn't logging out\n"); } 233 // FIXME - should I close() after accepting and recving? Or should I wait until logging out? 234 235 /* close client port if logout */ 819 /* wait for ack/pong/feedback (if logging in/out) */ 820 if (rec->msg_type == login /* || rec->msg_type == logout */) 821 { 822 ufds.fd = g_sClient; 823 ufds.events = POLLIN|POLLPRI; 824 poll(&ufds, 1, 1000); 825 if (!ufds.revents) { log_it(error, "Failed to poll"); return(-5); } 826 len = accept_and_recv_thru_client_port(g_sClient, &new_sClient, &g_sinClient, (char*)&incoming_rec, sizeof(incoming_rec)); 827 if (len<0) { log_it(error, "Unable to accept/recv thru client port"); return(-10); } 828 sprintf(tmp, "Received %s - %s", tmsg_to_string(incoming_rec.msg_type), incoming_rec.body); 829 log_it(info, tmp); 830 if (rec->msg_type != login && incoming_rec.msg_type == login_ok) { log_it(error, "WTF? login_ok but I wasn't logging in"); } 831 if (rec->msg_type != logout&& incoming_rec.msg_type == logout_ok){ log_it(error, "WTF? logout_ok but I wasn't logging out"); } 832 close(new_sClient); 833 new_sClient=-1; 834 } 835 if (incoming_rec.msg_type == backup_fail) { log_it(error, "Failed, says server"); return(-8); } 836 /* fork the process which watches in the background for pings/requests/etc. */ 837 if (rec->msg_type == login) 838 { 839 g_logged_in_currently = true; 840 strcpy(tmp, "Hello world!"); 841 res = pthread_create(&a_thread, NULL, watch_port_for_triggers_from_server, (void*)tmp); 842 log_it(debug, "Returning from login + call to pthread_create"); 843 return(server_port); 844 } 236 845 if (rec->msg_type == logout) 237 846 { 238 close(st_new_sClient); 239 st_new_sClient = st_sClient = st_client_port = 0; 240 } 241 242 if (incoming_rec.msg_type == fail) { return(-1); } 243 244 /* fork the process which watches in the background for pings/requests/etc. */ 245 if (rec->msg_type == login) 246 { 247 st_pid = fork(); 248 switch(st_pid) 249 { 250 case -1: 251 fprintf(stderr, "Failed to fork\n"); exit(1); 252 case 0: /* child */ 253 watch_port_for_triggers_from_server(&st_sinClient, st_new_sClient, st_sClient); 254 exit(0); 255 default:/* parent */ 256 return(server_port); 257 } 258 } 259 } 260 261 262 263 int send_ping_to_server(char*msg, char*servername) 264 /* 265 Purpose:Send a 'ping' to server. Wait for 'pong!'. 847 log_it(debug, "Calling pthread_join to reunite trigger-watcher and main loop"); 848 res = pthread_join(a_thread, &thread_result); 849 if (res) { /*perror("Thread join failed");*/ log_it(debug, "Thread join failed in send_msg_to_server()"); } 850 else { sprintf(tmp, "Thread join succeeded. Result: %s", (char*)thread_result); log_it(debug, tmp); } 851 } 852 return(0); 853 } 854 855 856 857 /*-----------------------------------------------------------*/ 858 859 860 861 int send_ping_to_server(char*servername, char*msg) 862 /* 863 Purpose:Send a 'ping' to server. 266 864 Params: msg - string to send ("Hello world"?) 267 865 servername - server's hostname … … 272 870 orig_rec.msg_type = ping; 273 871 strncpy(orig_rec.body, msg, sizeof(orig_rec.body)); 274 if (send_msg_to_server(&orig_rec, servername) < =0)872 if (send_msg_to_server(&orig_rec, servername) < 0) 275 873 { return(1); } 276 874 else … … 280 878 281 879 282 char *tmsg_to_string(t_msg msg_type) 283 /* 284 Purpose:Return a string/name of the msg of type msg_type 285 Params: msg_type - type of message (enum typedef) 286 Return: pointer to static string {name of msg) 287 */ 288 { 289 static char sz_msg[MAX_STR_LEN]; 290 switch(msg_type) 291 { 292 case unused : strcpy(sz_msg, "unused"); break; 293 case login : strcpy(sz_msg, "login"); break; 294 case logout : strcpy(sz_msg, "logout"); break; 295 case login_ok:strcpy(sz_msg, "login_ok"); break; 296 case logout_ok:strcpy(sz_msg, "logout_ok"); break; 297 case ping : strcpy(sz_msg, "ping"); break; 298 case pong : strcpy(sz_msg, "pong"); break; 299 case fail : strcpy(sz_msg, "fail"); break; 300 case trigger_backup: strcpy(sz_msg, "trigger_backup"); break; 301 case trigger_restore: strcpy(sz_msg, "trigger_restore"); break; 302 case begin_stream: strcpy(sz_msg, "begin_stream"); break; 303 case end_stream: strcpy(sz_msg, "end_stream"); break; 304 default: strcpy(sz_msg, "(Fix tmsg_to_string please)"); break; 305 } 306 return(sz_msg); 307 } 308 309 310 void watch_port_for_triggers_from_server(struct sockaddr_in *sin, int new_s, int s) 880 /*-----------------------------------------------------------*/ 881 882 883 884 int send_progress_rpt_to_server(char*servername, char*msg) 885 /* 886 Purpose:Send a 'progress_rpt' string to server. 887 Params: msg - string to send ("Hello world"?) 888 servername - server's hostname 889 Return: result (0=success, nonzero=failure) 890 */ 891 { 892 struct s_client2server_msg_record orig_rec; 893 orig_rec.msg_type = progress_rpt; 894 strncpy(orig_rec.body, msg, sizeof(orig_rec.body)); 895 if (send_msg_to_server(&orig_rec, servername) < 0) 896 { return(1); } 897 else 898 { return(0); } 899 } 900 901 902 903 /*-----------------------------------------------------------*/ 904 905 906 907 void terminate_daemon(int sig) 908 /* 909 Purpose: Shut down the server in response to interrupt. 910 Params: Signal received. 911 Returns: None 912 */ 913 { 914 int res; 915 916 // FIXME - takes server 1-2 mins to realize I've aborted. I want that to be 5-10 seconds :) 917 set_signals(false); // termination in progress 918 log_it(info, "Abort signal caught by interrupt handler"); 919 call_program_and_log_output("kill `ps ax | grep mondo | grep -v \"ps ax\" | grep -v \"grep mondo\" | grep monitas | cut -d' ' -f1`"); 920 if (send_ping_to_server(g_server_name, "I'm pinging you before I logout")) 921 { log_it(error, "Server has shut down without warning."); } 922 if (g_mondo_thread) 923 { 924 res = get_bkgd_prog_result(&g_mondo_thread); 925 } 926 logout_and_exit(g_server_name); 927 } 928 929 930 931 /*-----------------------------------------------------------*/ 932 933 934 935 void *track_backup_task_progress(void*inp) 936 { 937 char fname[MAX_STR_LEN+1], 938 tmp[MAX_STR_LEN+1], 939 progress_str[MAX_STR_LEN+1], 940 old_progstr[MAX_STR_LEN+1], 941 *p; 942 struct s_client2server_msg_record rec; 943 FILE*fin; 944 bool biggies=false, regulars=false; 945 int prev_percentage=0, i; 946 947 rec.msg_type = progress_rpt; 948 strcpy(fname, (char*)inp); 949 log_it(debug, "track_backup_task_progres() --- entering"); 950 fin = fopen(fname, "r"); 951 old_progstr[0]='\0'; 952 sprintf(tmp, "fname = %s", fname); 953 log_it(debug, tmp); 954 sleep(2); 955 if (!does_file_exist(fname)) { log_it(fatal, "track_backup_task_progress() -- fname not found"); } 956 strcpy(rec.body, "Working"); 957 if (send_msg_to_server(&rec, g_server_name) < 0) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 958 log_it(debug, rec.body); 959 /* skip initial stuff */ 960 while(!feof(fin)) 961 { 962 fgets(progress_str, MAX_STR_LEN, fin); 963 progress_str[MAX_STR_LEN]='\0'; 964 if (strlen(progress_str)<2) { continue; } 965 if (strstr(progress_str, "TASK")) { break; } 966 } 967 /* skip more stuff */ 968 while(!feof(fin)) 969 { 970 fgets(progress_str, MAX_STR_LEN, fin); 971 progress_str[MAX_STR_LEN]='\0'; 972 if (strlen(progress_str)<2) { continue; } 973 if (!strstr(progress_str, "TASK")) { break; } 974 } 975 /* report on regular+biggie files */ 976 while(!feof(fin)) 977 { 978 fgets(progress_str, MAX_STR_LEN, fin); 979 progress_str[MAX_STR_LEN]='\0'; 980 if (strstr(progress_str, "rchiving set 0")) 981 { prev_percentage = 0; regulars = true; } 982 if (strstr(progress_str, "acking up all large files")) 983 { prev_percentage = 0; regulars = false; biggies = true; } 984 if (strlen(progress_str)<2) { continue; } 985 if (!strstr(progress_str, "TASK")) { continue; } 986 progress_str[strlen(progress_str)-1] = '\0'; 987 log_it(debug, progress_str); 988 if (!biggies && !regulars) 989 { strcpy(progress_str, "Still working..."); } 990 if (strcmp(progress_str, old_progstr)) 991 { 992 strcpy(old_progstr, progress_str); 993 if (biggies) 994 { sprintf(rec.body, "Large files: %s", progress_str+6); } 995 else if (regulars) 996 { sprintf(rec.body, "Regular files: %s", progress_str+6); } 997 if (!(p=strstr(progress_str, "% done"))) { continue; } 998 999 log_it(info, rec.body); 1000 if (send_progress_rpt_to_server(g_server_name, rec.body)) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1001 continue; 1002 1003 while(!isdigit(*(p-1))) { p--; } 1004 strcpy(tmp, p); 1005 *(strchr(tmp, '%')) = '\0'; 1006 i = atoi(tmp); 1007 if (i > prev_percentage) 1008 { 1009 prev_percentage = i; 1010 log_it(info, rec.body); 1011 // FIXME - could simply call send_progress_rpt_to_server() 1012 if (send_msg_to_server(&rec, g_server_name) < 0) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1013 } 1014 } 1015 } 1016 log_it(debug, "track_backup_task_progress() --- leaving"); 1017 pthread_exit(NULL); 1018 } 1019 1020 1021 1022 /*-----------------------------------------------------------*/ 1023 1024 1025 1026 void *track_compare_task_progress(void*inp) 1027 { 1028 char fname[MAX_STR_LEN+1], 1029 tmp[MAX_STR_LEN+1], 1030 progress_str[MAX_STR_LEN+1], 1031 old_progstr[MAX_STR_LEN+1], 1032 *p; 1033 // struct s_client2server_msg_record rec; 1034 FILE*fin; 1035 bool biggies=false, regulars=false; 1036 int prev_percentage=0, i; 1037 1038 strcpy(fname, (char*)inp); 1039 log_it(debug, "track_compare_task_progress() --- entering"); 1040 if (!(fin = fopen(fname, "r"))) { log_it(fatal, "Unable to openin tempdev while comparing"); } 1041 old_progstr[0]='\0'; 1042 sprintf(tmp, "fname = %s", fname); 1043 log_it(debug, tmp); 1044 sleep(2); 1045 if (!does_file_exist(fname)) { log_it(fatal, "track_compare_task_progress() -- fname not found"); } 1046 log_it(debug, "Working"); 1047 if (send_progress_rpt_to_server(g_server_name, "Working")) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1048 1049 /* report on regular+biggie files */ 1050 while(!feof(fin)) 1051 { 1052 fgets(progress_str, MAX_STR_LEN, fin); 1053 progress_str[MAX_STR_LEN]='\0'; 1054 log_it(debug, progress_str); 1055 if (strstr(progress_str, "erifying fileset #0")) 1056 { prev_percentage = 0; regulars = true; } 1057 if (strstr(progress_str, "erifying all bigfiles")) 1058 { prev_percentage = 0; regulars = false; biggies = true; } 1059 if (strlen(progress_str)<2) { continue; } 1060 if (!strstr(progress_str, "TASK")) { continue; } 1061 progress_str[strlen(progress_str)-1] = '\0'; 1062 if (!biggies && !regulars) 1063 { strcpy(progress_str, "Still working..."); } 1064 if (strcmp(progress_str, old_progstr)) 1065 { 1066 strcpy(old_progstr, progress_str); 1067 if (biggies) 1068 { sprintf(tmp, "Large files: %s", progress_str+6); } 1069 else if (regulars) 1070 { sprintf(tmp, "Regular files: %s", progress_str+6); } 1071 if (!(p=strstr(progress_str, "% done"))) { continue; } 1072 1073 log_it(info, tmp); 1074 if (send_progress_rpt_to_server(g_server_name, tmp)) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1075 continue; 1076 1077 while(!isdigit(*(p-1))) { p--; } 1078 strcpy(tmp, p); 1079 *(strchr(tmp, '%')) = '\0'; 1080 i = atoi(tmp); 1081 if (i > prev_percentage) 1082 { 1083 prev_percentage = i; 1084 log_it(info, tmp); 1085 // FIXME - could simply call send_progress_rpt_to_server() 1086 if (send_progress_rpt_to_server(g_server_name, tmp)) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1087 } 1088 } 1089 } 1090 log_it(debug, "track_compare_task_progress() --- leaving"); 1091 pthread_exit(NULL); 1092 } 1093 1094 1095 1096 /*-----------------------------------------------------------*/ 1097 1098 1099 1100 void *track_restore_task_progress(void*inp) 1101 { 1102 char fname[MAX_STR_LEN+1], 1103 tmp[MAX_STR_LEN+1], 1104 progress_str[MAX_STR_LEN+1], 1105 old_progstr[MAX_STR_LEN+1], 1106 *p; 1107 // struct s_client2server_msg_record rec; 1108 FILE*fin; 1109 bool biggies=false, regulars=false; 1110 int prev_percentage=0, i; 1111 1112 strcpy(fname, (char*)inp); 1113 log_it(debug, "track_restore_task_progress() --- entering"); 1114 if (!(fin = fopen(fname, "r"))) { log_it(fatal, "Unable to openin tempdev while restoring"); } 1115 old_progstr[0]='\0'; 1116 sprintf(tmp, "fname = %s", fname); 1117 log_it(debug, tmp); 1118 sleep(2); 1119 if (!does_file_exist(fname)) { log_it(fatal, "track_restore_task_progress() -- fname not found"); } 1120 log_it(debug, "Working"); 1121 if (send_progress_rpt_to_server(g_server_name, "Working")) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1122 1123 // FIXME --- mondorestore does not yet spit out its progress in 1124 // a user-friendly format; so, most of the following code won't 1125 // work. The server will know we're working but it won't know 1126 // how far along we've gotten. 1127 1128 /* report on regular+biggie files */ 1129 while(!feof(fin)) 1130 { 1131 fgets(progress_str, MAX_STR_LEN, fin); 1132 progress_str[MAX_STR_LEN]='\0'; 1133 continue; 1134 1135 log_it(debug, progress_str); 1136 if (strstr(progress_str, "estoring fileset #0")) 1137 { prev_percentage = 0; regulars = true; } 1138 if (strstr(progress_str, "erifying all bigfiles")) 1139 { prev_percentage = 0; regulars = false; biggies = true; } 1140 if (strlen(progress_str)<2) { continue; } 1141 if (!strstr(progress_str, "TASK")) { continue; } 1142 progress_str[strlen(progress_str)-1] = '\0'; 1143 if (!biggies && !regulars) 1144 { strcpy(progress_str, "Still working..."); } 1145 if (strcmp(progress_str, old_progstr)) 1146 { 1147 strcpy(old_progstr, progress_str); 1148 if (biggies) 1149 { sprintf(tmp, "Large files: %s", progress_str+6); } 1150 else if (regulars) 1151 { sprintf(tmp, "Regular files: %s", progress_str+6); } 1152 if (!(p=strstr(progress_str, "% done"))) { continue; } 1153 1154 log_it(info, tmp); 1155 if (send_progress_rpt_to_server(g_server_name, tmp)) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1156 continue; 1157 1158 while(!isdigit(*(p-1))) { p--; } 1159 strcpy(tmp, p); 1160 *(strchr(tmp, '%')) = '\0'; 1161 i = atoi(tmp); 1162 if (i > prev_percentage) 1163 { 1164 prev_percentage = i; 1165 log_it(info, tmp); 1166 // FIXME - could simply call send_progress_rpt_to_server() 1167 if (send_progress_rpt_to_server(g_server_name, tmp)) { log_it(error, "Failed to send progress_rpt msg to server."); pthread_exit(NULL); } 1168 } 1169 } 1170 } 1171 log_it(debug, "track_restore_task_progress() --- leaving"); 1172 pthread_exit(NULL); 1173 } 1174 1175 1176 1177 /*-----------------------------------------------------------*/ 1178 1179 1180 1181 void *watch_port_for_triggers_from_server(void*arg) 311 1182 /* 312 1183 Purpose:Watch client port for incoming trigger 313 Params: sin - record containing info on the port/socket 314 new_s - file descriptor of _open_ client socket 315 s - file descriptor of client socket (not the 'open' side of it) 316 NB: I don't really know why new_s and s are what they are or how or why. 1184 Params: none; uses global vars instead 317 1185 Return: none 1186 */ 318 1187 { 319 1188 struct pollfd ufds; 320 int len; 321 1189 struct s_server2client_msg_record incoming_rec; 1190 int len, res, new_s; 1191 char tmp[MAX_STR_LEN+1]; 1192 1193 strcpy(tmp,(char*)arg); 1194 log_it(info, "Awaiting triggers from server"); 322 1195 for(;;) 323 1196 { 324 /* wait for ack/pong/feedback*/325 ufds.fd = s;1197 /* wait for ack/pong/feedback/trigger */ 1198 ufds.fd = g_sClient; 326 1199 ufds.events = POLLIN|POLLPRI; 327 1200 poll(&ufds, 1, 1000); 328 1201 if (!ufds.revents) { continue; } /* wait again */ 329 len = sizeof(struct sockaddr_in); 330 if ((new_s = accept(s, (struct sockaddr*)sin, &len)) < 0) { fprintf(stderr,"[child] Cannot accept\n"); return(1); } 331 if ((len = recv(new_s, (char*)&incoming_rec, sizeof(incoming_rec), MSG_DONTWAIT)) <= 0) { fprintf(stderr, "[child] Cannot recv\n"); return(2); } 332 printf("Received %s - %s\n", tmsg_to_string(incoming_rec.msg_Type, incoming_rec.body); 333 // FIXME - should I close() after accepting and recving? 334 } 335 } 336 337 338 339 /* main */ 1202 len = accept_and_recv_thru_client_port(g_sClient, &new_s, &g_sinClient, (char*)&incoming_rec, sizeof(incoming_rec)); 1203 if (len<0) { log_it(error, "Unable to receive incoming trigger from server"); continue; } 1204 switch(incoming_rec.msg_type) 1205 { 1206 case trigger_backup: 1207 res = back_my_smitch_up(incoming_rec.body, new_s); /* no need to multitask: it's the client! :) */ 1208 break; 1209 case trigger_compare: 1210 res = compare_archives(incoming_rec.body, new_s); 1211 break; 1212 case trigger_restore: 1213 res = restore_archives(incoming_rec.body, incoming_rec.bodyAux, new_s); 1214 break; 1215 case logout_ok: 1216 if (!g_logging_out) 1217 { log_it(fatal, "Server has forcibly logged you out. Has server shut down?"); } 1218 g_logged_in_currently = false; 1219 g_logging_out = false; 1220 // exit(0); 1221 pthread_exit("Thou hast been logged out."); 1222 case login_fail: 1223 log_it(fatal, "Failed to login. Server thinks we're logged in already."); 1224 default: 1225 sprintf(tmp, "Received %s - '%s'", tmsg_to_string(incoming_rec.msg_type), incoming_rec.body); 1226 log_it(info, tmp); 1227 } 1228 close(new_s); 1229 } 1230 } 1231 1232 1233 1234 /*-----------------------------------------------------------*/ 1235 1236 340 1237 341 1238 int main(int argc, char*argv[]) … … 347 1244 { 348 1245 int client_port; 349 char hostname[MAX_STR_LEN+1], msg[MAX_STR_LEN+1], servername[MAX_STR_LEN+1]; 350 bool done; 351 1246 char hostname[MAX_STR_LEN+1], tmp[MAX_STR_LEN+1]; 1247 // char msg[MAX_STR_LEN+1]; 1248 // bool done; 1249 // pthread_t thread; 1250 1251 log_it(info, "---------- Monitas (client) by Hugo Rabson ----------"); 1252 register_pid(getpid(), "client"); 1253 set_signals(true); 352 1254 srandom(time(NULL)); 353 1255 /* FIXME - add Ctrl-C / sigterm trapping */ 354 /* FIXME - run login/logout code as a fork and share the logged in/logged out status flag */ 355 1256 1257 /* 1258 call_program_in_background(&thread, "ls aaa"); 1259 if (program_still_running("ls aaa")) 1260 { printf("Program is still running\n"); } 1261 else 1262 { printf("Program is no longer running\n"); } 1263 exit(0); 1264 */ 356 1265 if (argc == 2) 357 1266 { 358 strncpy( servername, argv[1], MAX_STR_LEN);359 servername[MAX_STR_LEN]='\0';1267 strncpy(g_server_name, argv[1], MAX_STR_LEN); 1268 g_server_name[MAX_STR_LEN]='\0'; 360 1269 } 361 1270 else … … 365 1274 } 366 1275 gethostname(hostname, sizeof(hostname)); 367 printf("Logging onto server as client '%s'\n", hostname); 368 client_port = login_to_server(hostname, servername); 369 if (client_port <= 0) { fprintf(stderr, "Unable to login to server. Aborting\n"); exit(1); } 370 for(done=false; !done; ) 371 { 372 printf("MsgToSend: "); 373 fgets(msg, sizeof(msg), stdin); 374 if (!strncmp(msg, "logout", 6)) { done=true; } 375 else 376 { 377 if (send_ping_to_server(msg, servername)) 378 { fprintf(stderr, "Error while waiting for response to ping\n"); exit(1); } 379 } 380 } 381 printf("Logging out of server\n"); 382 if (logout_of_server(servername)) 383 { fprintf(stderr, "Warning - failed to logout of server.\n"); } 1276 sprintf(tmp, "Logging onto server as client '%s'", hostname); 1277 log_it(info, tmp); 1278 client_port = login_to_server(hostname, g_server_name); 1279 if (client_port <= 0) 1280 { 1281 fprintf(stderr, "Unable to login to server.\n"); 1282 log_it(error, "Unable to login to server."); 1283 exit(1); 1284 } 1285 1286 // set_param_in_rcfile(CLIENT_RCFILE, "mondoarchive_params", "-1 -L"); 1287 log_it(debug, "Awaiting commands from FIFO"); 1288 create_and_watch_fifo_for_commands(CLIENT_COMDEV); 1289 logout_and_exit(g_server_name); 384 1290 exit(0); 385 1291 }
Note:
See TracChangeset
for help on using the changeset viewer.