Changeset 352 in MondoRescue
- Timestamp:
- Jan 28, 2006, 6:41:40 PM (19 years ago)
- Location:
- branches/stable/monitas
- Files:
-
- 6 added
- 2 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 } -
branches/stable/monitas/server.c
r351 r352 3 3 4 4 5 SERVER 6 7 8 FIXME 9 - when sysadm requests it:- 10 - connect to relevant port of client 11 - send trigger_backup msg 12 - receive file(s) 13 - close client's port 14 15 05/20 16 - changed 'clientname' to 'clientIP' 5 06/19 6 - fixed bugs in mondoarchive compare code 7 8 06/16 9 - every 15 seconds, update /var/spool/monitas/server-status.txt file 10 - added handle_progress_rpt() 11 - modify restore_path() to allow user to restore to another path 12 13 06/14 14 - added "2> /dev/null" to call to find /var/spool/monitas 15 - improved backup_client(), compare_client(), restore_client() 16 - pipe logs to logfile, not stdout 17 18 06/11 19 - moved register_pid(), set_signals(), termination_in_progress() to common.c 20 - commented code a bit 21 - improved backup_client(), compare_client(), restore_client() 22 23 06/10 24 - improved backup_client() 25 - discover whether mondoarchive returned error (ask client) 26 and act accordingly (i.e. drop archive) 27 28 06/09 29 - added /var/spool/monitas/input.dev FIFO to 30 let external programs instruct me to backup 31 or restore a given computer 32 - added signal trapping 33 34 06/07 35 - rename transmit_file... and move 36 to common.c, as transmit_file_to_socket() 37 - rename receive_file... and move to 38 common.c, as receive_file_from_socket() 39 40 05/27 41 - save bkps to /var/spool/monitas/123.456.789.012/[time] 42 43 05/23 44 - added elementary saving/storing of incoming data 45 from client backing itself up 46 47 05/21 48 - added backup_client, compare_client, restore_client 49 templates for triggers 17 50 18 51 05/11 … … 37 70 38 71 72 /*-----------------------------------------------------------*/ 73 74 75 39 76 #include "structs.h" 40 41 #define LOG_THESE_AND_HIGHER debug /* debug, info, warn, error, fatal */ 77 //#define LOG_THESE_AND_HIGHER debug 78 79 80 42 81 #define NOOF_THREADS 10 43 82 #define LOGFILE "/var/log/monitas-server.log" 83 #define log_it(x,y) { log_it_SUB(g_logfile,x,y); } 84 85 86 /* externs */ 87 88 extern bool does_file_exist(char*); 89 extern char *call_program_and_get_last_line_of_output(char*); 90 extern int call_program_and_log_output(char*); 91 extern int create_and_watch_fifo_for_commands(char*); 92 extern bool does_file_exist(char*); 93 extern void log_it_SUB(char*, t_loglevel, char *); 94 extern int make_hole_for_file (char *); 95 extern int read_block_from_fd(int socket_fd, char*buf, int len_to_read); 96 extern int receive_file_from_socket(FILE*, int); 97 extern void register_pid(pid_t, char*); 98 extern void set_signals(bool); 99 extern void termination_in_progress(int); 100 extern char *tmsg_to_string(t_msg); 101 extern int transmit_file_to_socket(FILE*,int); 44 102 45 103 … … 48 106 49 107 struct s_clientlist g_clientlist; /* FIXME - lock during login/logout, using mutexes */ 50 108 char g_command_fifo[MAX_STR_LEN+1]; // Device which server will monitor for incoming commands 109 pthread_t g_threadinfo[NOOF_THREADS]; // One thread per port, to watch for requests from clients 110 char g_logfile[MAX_STR_LEN+1] = "/var/log/monitas-server.log"; 111 char g_server_status_file[MAX_STR_LEN+1]; 51 112 52 113 … … 54 115 /* prototypes */ 55 116 56 int backup_client(int,char*); 117 int backup_client(char*, int, char*); 118 int compare_client(char*, int, char*); 57 119 int find_client_in_clientlist(char *); 120 int forcibly_logout_all_clients(void); 121 int forcibly_logout_client(int); 122 void* generate_server_status_file_regularly(void*); 58 123 int handle_incoming_message(int, struct sockaddr_in *, struct s_client2server_msg_record *); 59 124 int handle_login_request(int, struct s_client2server_msg_record *, char *); 60 125 int handle_logout_request(int, struct s_client2server_msg_record *, char *); 61 126 int handle_ping_request(int, struct s_client2server_msg_record *, char *); 62 void log_it(t_loglevel, char *); 63 int restore_client(int,char*); 64 int send_msg_to_client(struct s_server2client_msg_record *, char *, int); 127 int handle_progress_rpt(int, struct s_client2server_msg_record *, char *); 128 int handle_user_request(int, struct s_client2server_msg_record *, char *); 129 int process_incoming_command(char*); 130 int read_block_from_fd(int, char*, int); 131 int restore_client(char*, int, char*, char*); 132 int send_msg_to_client(struct s_server2client_msg_record *, char *, int, int*); 65 133 void start_threads_to_watch_ports_for_requests(void); 66 void interact_with_sysadm(void);134 void terminate_daemon(int); 67 135 char *tmsg_to_string(t_msg); 68 136 void* watch_port_for_requests_from_clients(void*); … … 70 138 71 139 72 /* subroutines */ 73 74 int backup_client(int clientno, char*path) 140 /*-----------------------------------------------------------*/ 141 142 143 144 int backup_client(char*ipaddr, int port, char*clientpath) 75 145 /* 76 146 Purpose:Backup the path of a specific client. Receive 77 147 the archives. Store them locally (on me, the server). 78 148 Params: clientno - client# in g_clientlist[] 79 149 clientpath - client's path to be backed up 80 150 Return: result (0=success, nonzero=failure) 81 151 */ 82 152 { 83 153 struct s_server2client_msg_record rec_to_client; 84 int i, res=0; 85 char tmp[MAX_STR_LEN]; 86 87 sprintf(tmp, "Client# = %d", clientno); 154 int res=0, socket_fd, noof_archives, i, len; 155 char tmp[MAX_STR_LEN+1], outfile[MAX_STR_LEN+1]; 156 FILE*fout; 157 158 sprintf(tmp, "%s - backup of %s commencing", ipaddr, clientpath); 159 log_it(info, tmp); 160 sprintf(outfile, "/var/spool/monitas/%s/%s.dat", ipaddr, call_program_and_get_last_line_of_output("date +%s")); 161 if (does_file_exist(outfile)) { log_it(error, "Backup storage location exists already. That should be impossible."); return(1); } 162 if (make_hole_for_file(outfile)) 163 { res++; log_it(error, "Cannot write archive to spool dir"); } 164 else if (!(fout=fopen(outfile, "w"))) 165 { res++; log_it(fatal, "Failed to openout temp data file"); } 166 else 167 { 168 sprintf(tmp, "Backing up %s - archive=%s", ipaddr, outfile); 169 log_it(debug, tmp); 170 rec_to_client.msg_type = trigger_backup; 171 strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); 172 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 173 { log_it(error, "backup_client - failed to send msg to client"); return(1); } 174 res += receive_file_from_socket(fout, socket_fd); 175 len=read(socket_fd, (char*)&i, sizeof(i)); 176 if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondoarchive"); } 177 else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondoarchive"); } 178 else if (i) { res++; log_it(error, "Client said, mondoarchive returned an error."); } 179 else { log_it(debug, "Client said, mondoarchive returned OK"); } 180 fclose(fout); 181 close(socket_fd); 182 } 183 /* Shuffle older backups off the mortal coil. Leave maximum of 4 backup files in /var/spool/monitas/[ipaddr] */ 184 sprintf(tmp, "find /var/spool/monitas/%s -type f 2> /dev/null | grep -n \"\" | tail -n1 | cut -d':' -f1", ipaddr); 185 noof_archives = atoi(call_program_and_get_last_line_of_output(tmp)); 186 i = noof_archives - 3; 187 if (i>0) 188 { 189 sprintf(tmp, "rm -f `find /var/spool/monitas/%s -type f | sort | head -n%d`", ipaddr, i); 190 call_program_and_log_output(tmp); 191 } 192 /* Return success/failure value */ 193 if (res>0) 194 { 195 sprintf(tmp, "%s - error(s) occurred while backing up %s", ipaddr, clientpath); 196 log_it(error, tmp); 197 rec_to_client.msg_type = backup_fail; 198 sprintf(rec_to_client.body, "Failed to backup %s", clientpath); 199 log_it(debug, rec_to_client.body); 200 unlink(outfile); 201 } 202 else 203 { 204 sprintf(tmp, "%s - backed up %s ok", ipaddr, clientpath); 205 log_it(info, tmp); 206 rec_to_client.msg_type = backup_ok; 207 sprintf(rec_to_client.body, "%s - backed up ok", clientpath); 208 log_it(debug, rec_to_client.body); 209 } 210 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 211 { 212 res++; 213 sprintf(tmp, "Unable to notify %s of backup success/failure", ipaddr); 214 log_it(error, tmp); 215 i = find_client_in_clientlist(ipaddr); 216 if (i>=0) { forcibly_logout_client(i); } 217 log_it(info, "I'm assuming the backup was bad because the client cannot be reached."); 218 unlink(outfile); 219 } 220 return(res); 221 } 222 223 224 225 /*-----------------------------------------------------------*/ 226 227 228 229 int compare_client(char*ipaddr, int port, char*clientpath) 230 /* 231 Purpose:Compare the path of a specific client. Transmit 232 the archives from my (the server's) local storage loc. 233 Params: clientno - client# in g_clientlist[] 234 clientpath - client's path to be compared 235 Return: result (0=success, nonzero=failure) 236 */ 237 { 238 struct s_server2client_msg_record rec_to_client; 239 int res=0, socket_fd, len, i; 240 char tmp[MAX_STR_LEN+1], infile[MAX_STR_LEN+1]; 241 FILE*fin; 242 243 sprintf(tmp, "%s - comparison of %s commencing", ipaddr, clientpath); 244 log_it(info, tmp); 245 // FIXME - don't assume the latest backup contains the files we want ;) 246 sprintf(tmp, "find /var/spool/monitas/%s -type f | sort | tail -n1", ipaddr); 247 strcpy(infile, call_program_and_get_last_line_of_output(tmp)); 248 sprintf(tmp, "Comparing to data file '%s'", infile); 88 249 log_it(debug, tmp); 89 if (clientno >= g_clientlist.items) 90 { log_it(fatal, "backup_client: clientno>=g_clientlist.items"); } 91 sprintf(tmp, "Backing up %s - path=%s", g_clientlist.el[clientno].ipaddr, path); 92 log_it(info, tmp); 93 rec_to_client.msg_type = trigger_backup; 94 strncpy(rec_to_client.body, path, sizeof(rec_to_client.body)); 95 if (send_msg_to_client(&rec_to_client, g_clientlist.el[clientno].ipaddr, g_clientlist.el[clientno].port)) 96 { log_it(error, "backup_client - failed to send msg to client"); return(1); } 97 98 if (res) 99 { 100 sprintf(tmp, "Error(s) occurred while backing up %s", g_clientlist.el[clientno].ipaddr); 101 log_it(error, tmp); 102 return(1); 250 if (!does_file_exist(infile)) { log_it(error, "Backup not found. That should be impossible."); return(1); } 251 sprintf(tmp, "Comparing %s - archive=%s", ipaddr, infile); 252 log_it(debug, tmp); 253 rec_to_client.msg_type = trigger_compare; 254 strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); 255 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 256 { log_it(error, "compare_client - failed to send msg to client"); return(1); } 257 if (!(fin=fopen(infile, "r"))) 258 { log_it(fatal, "Failed to openin temp data file"); } 259 res += transmit_file_to_socket(fin, socket_fd); 260 len=read(socket_fd, (char*)&i, sizeof(i)); 261 if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondoarchive"); } 262 else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondoarchive"); } 263 else if (i) { res++; log_it(error, "Client said, mondoarchive returned an error."); } 264 else { log_it(debug, "Client said, mondoarchive returned OK"); } 265 fclose(fin); 266 close(socket_fd); 267 if (res>0) 268 { 269 sprintf(tmp, "%s - error(s) occurred while comparing %s", ipaddr, clientpath); 270 log_it(error, tmp); 271 rec_to_client.msg_type = compare_fail; 272 sprintf(rec_to_client.body, "Failed to compare %s", clientpath); 273 log_it(debug, rec_to_client.body); 103 274 } 104 275 else 105 276 { 106 sprintf(tmp, "Backed up %s OK", g_clientlist.el[clientno].ipaddr); 107 log_it(error, tmp); 108 return(0); 109 } 110 } 277 sprintf(tmp, "%s - compared %s ok", ipaddr, clientpath); 278 log_it(info, tmp); 279 rec_to_client.msg_type = compare_ok; 280 sprintf(rec_to_client.body, "%s - compared ok", clientpath); 281 log_it(debug, rec_to_client.body); 282 } 283 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 284 { 285 sprintf(tmp, "Unable to notify %s of compare success/failure", ipaddr); 286 log_it(error, tmp); 287 i = find_client_in_clientlist(ipaddr); 288 if (i>=0) { forcibly_logout_client(i); } 289 } 290 return(res); 291 } 292 293 294 295 /*-----------------------------------------------------------*/ 296 111 297 112 298 … … 121 307 { 122 308 int i; 123 char tmp[MAX_STR_LEN ];309 char tmp[MAX_STR_LEN+1]; 124 310 125 311 for(i = 0; i < g_clientlist.items; i++) … … 132 318 return(-1); 133 319 } 320 321 322 323 /*-----------------------------------------------------------*/ 324 325 326 327 int forcibly_logout_all_clients() 328 /* 329 Purpose: Tell all clients to disconnect, right now. 330 Params: None 331 Returns: 0=success 332 */ 333 { 334 // FIXME - lock g_clientlist for duration of this function 335 while(g_clientlist.items>0) 336 { 337 forcibly_logout_client(0); 338 } 339 return(0); 340 } 341 342 343 344 /*-----------------------------------------------------------*/ 345 346 347 348 int forcibly_logout_client(int clientno) 349 /* 350 Purpose: Logout specific client(#) by force. 351 Params: Client# in g_clientlist[] array. 352 Returns: 0=success, nonzero=failure to get other end to hear me;) 353 NB: The client was definitely removed from our login table. 354 If the client got the message, return 0; else, nonzero. 355 */ 356 { 357 struct s_server2client_msg_record rec_to_client; 358 char tmp[MAX_STR_LEN+1]; 359 int res=0; 360 361 sprintf(tmp, "Forcibly logging %s out", g_clientlist.el[clientno].ipaddr); 362 log_it(info, tmp); 363 rec_to_client.msg_type = logout_ok; /* to confirm logout */ 364 strcpy(rec_to_client.body, "Server is shutting down. You are forced to logout"); 365 res=send_msg_to_client(&rec_to_client, g_clientlist.el[clientno].ipaddr, g_clientlist.el[clientno].port, NULL); 366 if (--g_clientlist.items > 0) 367 { 368 sprintf(tmp, "Moving clientlist[%d] to clientlist[%d]", clientno, g_clientlist.items); 369 log_it(debug, tmp); 370 sprintf(tmp, "Was ipaddr=%s; now is ipaddr=", g_clientlist.el[clientno].ipaddr); 371 memcpy((void*)&g_clientlist.el[clientno], (void*)&g_clientlist.el[g_clientlist.items], sizeof(struct s_registered_client_record)); 372 strcat(tmp, g_clientlist.el[clientno].ipaddr); 373 log_it(debug, tmp); 374 } 375 return(res); 376 } 377 378 379 380 /*-----------------------------------------------------------*/ 381 382 383 void* generate_server_status_file_regularly(void*inp) 384 { 385 int i; 386 FILE*fout; 387 388 strncpy(g_server_status_file, (char*)inp, MAX_STR_LEN); 389 for(;;) 390 { 391 if ((fout = fopen(g_server_status_file, "w"))) 392 { 393 // FIXME - lock g_clientlist 394 for(i=0; i<g_clientlist.items; i++) 395 { 396 fprintf(fout, "%s [%s] : %s\n", g_clientlist.el[i].ipaddr, g_clientlist.el[i].hostname_pretty, g_clientlist.el[i].last_progress_rpt); 397 } 398 fclose(fout); 399 } 400 sleep(1); 401 } 402 exit(0); 403 } 404 405 406 407 /*-----------------------------------------------------------*/ 134 408 135 409 … … 145 419 */ 146 420 { 147 char clientIP[MAX_STR_LEN], *ptr, tmp[MAX_STR_LEN]; 421 char clientIP[MAX_STR_LEN+1], tmp[MAX_STR_LEN+1]; 422 unsigned char *ptr; 148 423 int res=0; 149 424 … … 152 427 sprintf(clientIP, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]); 153 428 sprintf(tmp, "clientIP = %s", clientIP); 429 log_it(debug, tmp); 430 sprintf(tmp, "%s message from %s [%s] (port %d)", tmsg_to_string(rec->msg_type), clientIP, rec->body, rec->port); 154 431 log_it(debug, tmp); 155 432 switch(rec->msg_type) … … 161 438 res=handle_ping_request(skt, rec, clientIP); 162 439 break; 440 case progress_rpt: 441 res=handle_progress_rpt(skt, rec, clientIP); 442 break; 163 443 case logout: 164 444 res=handle_logout_request(skt, rec, clientIP); 165 445 break; 446 case user_req: 447 res=handle_user_request(skt, rec, clientIP); 448 break; 166 449 default: 167 sprintf(tmp, "%s request from %s [%s] (port %d) - how do I handle it?", tmsg_to_string(rec->msg_type), clientIP, rec->body, rec->port); 168 log_it(error, tmp); 450 log_it(error, "...How do I handle it?"); 169 451 } 170 452 return(res); 171 453 } 454 455 456 457 /*-----------------------------------------------------------*/ 172 458 173 459 … … 185 471 struct s_server2client_msg_record rec_to_client; 186 472 int clientno; 187 char tmp[MAX_STR_LEN]; 188 189 sprintf(tmp, "Login request from %s [%s] (port %d)", clientIP, rec_from_client->body, rec_from_client->port); 190 log_it(info, tmp); 473 char tmp[MAX_STR_LEN+1]; 474 475 //FIXME - lock g_clientlist[] 191 476 clientno = find_client_in_clientlist(clientIP); 192 477 if (clientno>=0) 193 478 { 194 rec_to_client.msg_type = fail;479 rec_to_client.msg_type = login_fail; 195 480 sprintf(rec_to_client.body, "Sorry, you're already logged in!"); 196 481 sprintf(tmp, "Ignoring login rq from %s: he's already logged in.", clientIP); … … 210 495 strncpy(g_clientlist.el[clientno].ipaddr, clientIP, sizeof(g_clientlist.el[clientno].ipaddr)); 211 496 g_clientlist.el[clientno].port = rec_from_client->port; 497 g_clientlist.el[clientno].busy = false; 212 498 g_clientlist.items ++; 213 499 sprintf(tmp, "Login request from %s ACCEPTED", clientIP); 214 500 log_it(info, tmp); 215 } 216 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port); 501 strcpy(g_clientlist.el[clientno].last_progress_rpt, "Logged in"); 502 } 503 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); 217 504 return(0); 218 505 } 506 507 508 509 /*-----------------------------------------------------------*/ 219 510 220 511 … … 225 516 from client. 226 517 Params: skt - client's port to talk to 227 rec_from_client - log inrq record received from client518 rec_from_client - logout rq record received from client 228 519 clientIP - client's IP address, in string 229 520 Return: result (0=success, nonzero=failure) … … 232 523 struct s_server2client_msg_record rec_to_client; 233 524 int i, res=0; 234 char tmp[MAX_STR_LEN]; 235 236 sprintf(tmp, "Logout request from %s [%s] (port %d)", clientIP, rec_from_client->body, rec_from_client->port); 237 log_it(info, tmp); 525 char tmp[MAX_STR_LEN+1]; 526 238 527 i = find_client_in_clientlist(clientIP); 239 528 if (i<0) … … 241 530 sprintf(rec_to_client.body, "Client is not logged in yet. How can I log him out?"); 242 531 log_it(error, rec_to_client.body); 243 rec_to_client.msg_type = fail; 532 rec_to_client.msg_type = logout_fail; 533 res=1; 534 } 535 else if (g_clientlist.el[i].busy) 536 { 537 sprintf(rec_to_client.body, "Client is working. I shouldn't log him out."); 538 log_it(error, rec_to_client.body); 539 rec_to_client.msg_type = logout_fail; 244 540 res=1; 245 541 } … … 257 553 log_it(info, tmp); 258 554 } 259 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port );555 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); 260 556 return(res); 261 557 } 558 559 560 561 /*-----------------------------------------------------------*/ 262 562 263 563 … … 268 568 from client. 269 569 Params: skt - client's port to talk to 270 rec_from_client - login rqrecord received from client570 rec_from_client - ping record received from client 271 571 clientIP - client's IP address, in string 272 572 Return: result (0=success, nonzero=failure) … … 275 575 struct s_server2client_msg_record rec_to_client; 276 576 int i; 277 char tmp[MAX_STR_LEN]; 278 279 sprintf(tmp, "ping request from port %d --- %s", rec_from_client->port, rec_from_client->body); 280 log_it(info, tmp); 577 char tmp[MAX_STR_LEN+1]; 578 281 579 i = find_client_in_clientlist(clientIP); 282 580 if (i < 0) … … 289 587 rec_to_client.msg_type = pong; /* reply to ping */ 290 588 sprintf(rec_to_client.body, "Hey, I'm replying to client#%d's ping. Pong! (re: %s", i, rec_from_client->body); 291 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port );589 send_msg_to_client(&rec_to_client, clientIP, rec_from_client->port, NULL); 292 590 log_it(debug, rec_to_client.body); 293 591 } … … 297 595 298 596 299 void interact_with_sysadm() 300 /* 301 Purpose:Tell sysadm about users logged in, etc. in 302 response to keypresses (1=users, ENTER=exit) 303 Params: none 304 Return: none 305 NB: Called by main() 306 */ 307 { 308 char tmp[MAX_STR_LEN]; 309 int i; 310 bool done; 311 312 for(done=false; !done; ) 313 { 314 printf("Type 1 to list clients\n"); 315 printf("Type 2 to backup a client\n"); 316 printf("Type 3 to restore a client\n"); 317 printf("Type ENTER to quit.\n"); 318 fgets(tmp, sizeof(tmp), stdin); 319 if (!strcmp(tmp, "1\n")) 320 { 321 printf("g_clientlist.items is %d\n", g_clientlist.items); 322 printf("List of %d clients:-\n", g_clientlist.items); 323 printf("\tClient# Port# IP address Client name\n"); 324 for(i=0; i<g_clientlist.items; i++) 325 { 326 printf("\t%d\t%4d %-16s %-20s \n", i, g_clientlist.el[i].port, g_clientlist.el[i].ipaddr, g_clientlist.el[i].hostname_pretty); 327 } 328 printf("<End of list>\n\n"); 329 } 330 else if (!strcmp(tmp, "2\n")) 331 { 332 if (g_clientlist.items!=1) { printf("Forget it\n"); } 333 else 334 { 335 backup_client(0, "/usr/local"); 336 } 337 } 338 else if (!strcmp(tmp, "3\n")) 339 { 340 if (g_clientlist.items!=1) { printf("Forget it\n"); } 341 else 342 { 343 restore_client(0, "/usr/local"); 344 } 345 } 346 else if (!strcmp(tmp, "\n")) 347 { 348 if (g_clientlist.items > 0) 597 /*-----------------------------------------------------------*/ 598 599 600 601 int handle_progress_rpt(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP) 602 /* 603 Purpose:Handle a progress_rpt which has just been received 604 from client. 605 Params: skt - client's port to talk to 606 rec_from_client - user record received from client 607 clientIP - client's IP address, in string 608 Return: result (0=success, nonzero=failure) 609 */ 610 { 611 // struct s_server2client_msg_record rec_to_client; 612 int i, res=0; 613 char tmp[MAX_STR_LEN+1]; 614 615 i = find_client_in_clientlist(clientIP); 616 if (i < 0) 617 { 618 sprintf(tmp, "Hey, %s isn't logged in. I'm not going to deal with his progress_rpt.", clientIP); 619 log_it(error, tmp); 620 res++; 621 } 622 else 623 { 624 strcpy(g_clientlist.el[i].last_progress_rpt, rec_from_client->body); 625 } 626 return(res); 627 } 628 629 630 631 /*-----------------------------------------------------------*/ 632 633 634 635 int handle_user_request(int skt, struct s_client2server_msg_record *rec_from_client, char *clientIP) 636 /* 637 Purpose:Handle a user request which has just been received 638 from client. 639 Params: skt - client's port to talk to 640 rec_from_client - user record received from client 641 clientIP - client's IP address, in string 642 Return: result (0=success, nonzero=failure) 643 */ 644 { 645 // struct s_server2client_msg_record rec_to_client; 646 int i, res=0; 647 char tmp[MAX_STR_LEN+1], command[MAX_STR_LEN+1], first_half[MAX_STR_LEN+1], second_half[MAX_STR_LEN+1], *p; 648 649 i = find_client_in_clientlist(clientIP); 650 if (i < 0) 651 { 652 sprintf(tmp, "Hey, %s isn't logged in. I'm not going to deal with his request.", clientIP); 653 log_it(error, tmp); 654 res++; 655 } 656 else 657 { 658 strcpy(first_half, rec_from_client->body); 659 p = strchr(first_half, ' '); 660 if (!p) { second_half[0]='\0'; } else { strcpy(second_half, p); *p='\0'; } 661 sprintf(command, "echo \"%s %s%s\" > %s", first_half, clientIP, second_half, SERVER_COMDEV); 662 log_it(debug, command); 663 i = system(command); 664 if (i) { res++; log_it(error, "Failed to echo command to FIFO"); } 665 } 666 return(res); 667 } 668 669 670 671 /*-----------------------------------------------------------*/ 672 673 674 675 int process_incoming_command(char*incoming) 676 /* 677 Purpose:Process incoming command, presumably 678 read from FIFO and sent there by sysadm/user. 679 Params: incoming - raw command string itself 680 Return: result (0=success; nonzero=failure) 681 */ 682 { 683 int res=0, port; 684 int clientno; 685 char tmp[MAX_STR_LEN+1]; 686 int pos; 687 char command[MAX_STR_LEN+1], ipaddr[MAX_STR_LEN+1], 688 path[MAX_STR_LEN+1], aux[MAX_STR_LEN+1]; 689 690 // sprintf(tmp, "incoming = '%s'", incoming); 691 // log_it(debug, tmp); 692 pos=0; 693 sscanf(incoming, "%s %s %s", command, ipaddr, path); 694 if (!strcmp(command, "restore")) 695 { sscanf(incoming, "%s %s %s %s", command, ipaddr, path, aux); } 696 else 697 { aux[0] = '\0'; } 698 699 // for(i=0; i<strlen(command); i++) { command[i]=command[i]|0x60; } 700 sprintf(tmp, "cmd=%s ipaddr=%s path=%s", command, ipaddr, path); 701 log_it(debug, tmp); 702 sprintf(tmp, "%s of %s on %s <-- command received", command, path, ipaddr); 703 log_it(info, tmp); 704 if ((clientno = find_client_in_clientlist(ipaddr)) < 0) 349 705 { 350 printf("There are %d users logged in. Are you sure you want to quit? ", g_clientlist.items); 351 fgets(tmp, sizeof(tmp), stdin); 352 if (tmp[0]=='Y' || tmp[0]=='y') 353 { done=true; } 706 sprintf(tmp, "%s not found in clientlist; so, %s failed.", ipaddr, command); 707 log_it(error, tmp); 708 } 709 else if (g_clientlist.el[clientno].busy == true) 710 { 711 sprintf(tmp, "%s is busy; so, %s failed.", ipaddr, command); 712 log_it(error, tmp); 354 713 } 355 714 else 356 { done=true; } 357 if (done) 358 { log_it(info, "OK, you've chosen to shutdown server."); } 359 else 360 { log_it(info, "Shutdown canceled."); } 361 } 362 } 363 } 364 365 366 367 void log_it(t_loglevel level, char *sz_message) 368 { 369 char sz_outstr[MAX_STR_LEN], sz_level[MAX_STR_LEN], sz_time[MAX_STR_LEN]; 370 time_t time_rec; 371 372 time(&time_rec); 373 switch(level) 374 { 375 case debug: strcpy(sz_level, "DEBUG"); break; 376 case info: strcpy(sz_level, "INFO "); break; 377 case warn: strcpy(sz_level, "WARN "); break; 378 case error: strcpy(sz_level, "ERROR"); break; 379 case fatal: strcpy(sz_level, "FATAL"); break; 380 default: strcpy(sz_level, "UNKWN"); break; 381 } 382 sprintf(sz_time, ctime(&time_rec)); 383 sz_time[strlen(sz_time)-6] = '\0'; 384 sprintf(sz_outstr, "%s %s: %s", sz_time+11, sz_level, sz_message); 385 if ((int)level >= LOG_THESE_AND_HIGHER) 386 { 387 fprintf(stderr, "%s\n",sz_outstr); 388 } 389 if (level==fatal) { fprintf(stderr,"Aborting now."); exit(1); } 390 } 391 392 393 394 395 int restore_client(int clientno, char*path) 396 { 397 } 398 399 400 int send_msg_to_client(struct s_server2client_msg_record *rec, char *clientIP, int port) 715 { 716 g_clientlist.el[clientno].busy = true; 717 port = g_clientlist.el[clientno].port; 718 if (!strcmp(command, "backup")) 719 { res = backup_client(ipaddr, port, path); } 720 else if (!strcmp(command, "compare")) 721 { res = compare_client(ipaddr, port, path); } 722 else if (!strcmp(command, "restore")) 723 { res = restore_client(ipaddr, port, path, aux); } 724 else 725 { 726 sprintf(tmp, "%s - cannot '%s'. Command unknown.", ipaddr, command); 727 log_it(error, tmp); 728 res=1; 729 } 730 g_clientlist.el[clientno].busy = false; 731 } 732 return(res); 733 } 734 735 736 737 /*-----------------------------------------------------------*/ 738 739 740 741 int restore_client(char*ipaddr, int port, char*clientpath, char*auxpath) 742 /* 743 Purpose:Restore the path of a specific client. Transmit 744 the archives from my (the server's) local storage loc. 745 Params: clientno - client# in g_clientlist[] 746 clientpath - client's path to be restored 747 Return: result (0=success, nonzero=failure) 748 */ 749 { 750 struct s_server2client_msg_record rec_to_client; 751 int res=0, socket_fd, len, i; 752 char tmp[MAX_STR_LEN+1], infile[MAX_STR_LEN+1]; 753 FILE*fin; 754 755 sprintf(tmp, "%s - restoration of %s commencing", ipaddr, clientpath); 756 log_it(info, tmp); 757 // FIXME - don't assume the latest backup contains the files we want ;) 758 sprintf(tmp, "find /var/spool/monitas/%s -type f | sort | tail -n1", ipaddr); 759 strcpy(infile, call_program_and_get_last_line_of_output(tmp)); 760 sprintf(tmp, "Restoring from data file '%s'", infile); 761 log_it(debug, tmp); 762 if (!does_file_exist(infile)) { log_it(error, "Backup not found. That should be impossible."); return(1); } 763 sprintf(tmp, "Restoring %s - archive=%s", ipaddr, infile); 764 log_it(debug, tmp); 765 rec_to_client.msg_type = trigger_restore; 766 strncpy(rec_to_client.body, clientpath, sizeof(rec_to_client.body)); 767 strncpy(rec_to_client.bodyAux, auxpath, sizeof(rec_to_client.bodyAux)); 768 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 769 { log_it(error, "restore_client - failed to send msg to client"); return(1); } 770 if (!(fin=fopen(infile, "r"))) 771 { log_it(fatal, "Failed to openin temp data file"); } 772 res += transmit_file_to_socket(fin, socket_fd); 773 774 len=read(socket_fd, (char*)&i, sizeof(i)); 775 if (!len) { res++; log_it(error, "Client hasn't told me the result of its call to mondorestore"); } 776 else if (len!=sizeof(i)) { res++; log_it(error, "Client didn't sent _entire_ result of its call to mondorestore"); } 777 else if (i) { res++; log_it(error, "Client said, mondorestore returned an error."); } 778 else { log_it(debug, "Client said, mondorestore returned OK"); } 779 780 fclose(fin); 781 close(socket_fd); 782 if (res>0) 783 { 784 sprintf(tmp, "%s - error(s) occurred while restoring %s", ipaddr, clientpath); 785 log_it(error, tmp); 786 rec_to_client.msg_type = restore_fail; 787 sprintf(rec_to_client.body, "Failed to restore %s", clientpath); 788 log_it(debug, rec_to_client.body); 789 } 790 else 791 { 792 sprintf(tmp, "%s - restored %s ok", ipaddr, clientpath); 793 log_it(info, tmp); 794 rec_to_client.msg_type = restore_ok; 795 sprintf(rec_to_client.body, "%s - restored ok", clientpath); 796 log_it(debug, rec_to_client.body); 797 } 798 if (send_msg_to_client(&rec_to_client, ipaddr, port, &socket_fd)) 799 { 800 sprintf(tmp, "Unable to notify %s of restore success/failure", ipaddr); 801 log_it(error, tmp); 802 i = find_client_in_clientlist(ipaddr); 803 if (i>=0) { forcibly_logout_client(i); } 804 } 805 return(res); 806 } 807 808 809 /*-----------------------------------------------------------*/ 810 811 812 813 int send_msg_to_client(struct s_server2client_msg_record *rec, char *clientIP, int port, int *psocket) 401 814 /* 402 815 Purpose:Send a message from server to client. 403 404 405 406 816 A 'message' could be a response to a login/logout/ping 817 request or perhaps a 'trigger'. (A trigger is a message 818 from server to client intended to initiate a backup 819 or similar activity.) 407 820 Params: rec - record containing the data to be sent to client 408 clientIP - the xxx.yyy.zzz.aaa IP address of client 409 port - the client's port to send data to 410 Return: result (0=success, nonzero=failure) 411 */ 412 { 413 struct hostent *hp; 414 struct sockaddr_in sin; 415 int s; 416 char tmp[MAX_STR_LEN]; 417 418 if ((hp = gethostbyname(clientIP)) == NULL) 419 { 420 sprintf(tmp, "send_msg_to_client: %s: unknown host\n", clientIP); 421 log_it(error, tmp); 422 return(1); 423 } 424 memset((void*)&sin, 0, sizeof(sin)); 425 memcpy((void*)&sin.sin_addr, hp->h_addr, hp->h_length); 426 sin.sin_family = AF_INET; 427 sin.sin_addr.s_addr = INADDR_ANY; 428 sin.sin_port = htons(port); 429 if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 430 { perror("socket"); log_it(error, "send_msg_to_client: SOCKET error"); return(1); } 431 if (connect(s, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) < 0) 432 { sprintf(tmp, "Failed to connect to client %s on port %d", clientIP, port); log_it(error, tmp); return(1); } 433 send(s, (char*)rec, sizeof(struct s_server2client_msg_record), 0); 434 close(s); 435 sprintf(tmp, "Sent %s msg to %s (port %d)", tmsg_to_string(rec->msg_type), clientIP, port); 436 log_it(debug, tmp); 437 return(0); 438 } 821 clientIP - the xxx.yyy.zzz.aaa IP address of client 822 port - the client's port to send data to 823 psocket - returns the socket's file descriptor, left 824 open by me; or, if psocket==NULL, then socket is closed 825 by me before I return. 826 Return: result (0=success, nonzero=failure) 827 */ 828 { 829 struct hostent *hp; 830 struct sockaddr_in sin; 831 int s; 832 char tmp[MAX_STR_LEN+1]; 833 if ((hp = gethostbyname(clientIP)) == NULL) 834 { 835 sprintf(tmp, "send_msg_to_client: %s: unknown host", clientIP); 836 log_it(error, tmp); 837 return(1); 838 } 839 memset((void*)&sin, 0, sizeof(sin)); 840 memcpy((void*)&sin.sin_addr, hp->h_addr, hp->h_length); 841 sin.sin_family = AF_INET; 842 sin.sin_addr.s_addr = INADDR_ANY; 843 sin.sin_port = htons(port); 844 if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 845 { perror("socket"); log_it(error, "send_msg_to_client: SOCKET error"); return(1); } 846 if (connect(s, (struct sockaddr*)&sin, sizeof(struct sockaddr_in)) < 0) 847 { sprintf(tmp, "Failed to connect to client %s on port %d", clientIP, port); log_it(error, tmp); return(1); } 848 send(s, (char*)rec, sizeof(struct s_server2client_msg_record), 0); 849 if (psocket) { *psocket=s; } else { close(s); } 850 sprintf(tmp, "Sent %s msg [%s] to %s (port %d)", tmsg_to_string(rec->msg_type), rec->body, clientIP, port); 851 log_it(debug, tmp); 852 return(0); 853 } 854 855 856 857 /*-----------------------------------------------------------*/ 439 858 440 859 … … 450 869 { 451 870 int i, port, res; 452 pthread_t threadinfo[NOOF_THREADS]; 453 char tmp[MAX_STR_LEN]; 871 char tmp[MAX_STR_LEN+1]; 454 872 455 873 g_clientlist.items = 0; … … 458 876 port = 8700+i; 459 877 sprintf(tmp,"%d", port); 460 res = pthread_create(&( threadinfo[i]), NULL, watch_port_for_requests_from_clients, (void*)tmp);878 res = pthread_create(&(g_threadinfo[i]), NULL, watch_port_for_requests_from_clients, (void*)tmp); 461 879 if (res != 0) 462 880 { 463 881 perror("Thread creation failed"); 464 882 } 465 usleep( 80000);466 } 467 sprintf(tmp, " Threads are now running.");883 usleep(50000); 884 } 885 sprintf(tmp, "Now monitoring ports %d thru %d for requests from clients.", 8700, 8700+NOOF_THREADS-1); 468 886 log_it(info, tmp); 469 887 } … … 471 889 472 890 473 char *tmsg_to_string(t_msg msg_type) 474 /* 475 Purpose:Return a string/name of the msg of type msg_type 476 Params: msg_type - type of message (enum typedef) 477 Return: pointer to static string {name of msg) 478 */ 479 { 480 static char sz_msg[MAX_STR_LEN]; 481 switch(msg_type) 482 { 483 case unused : strcpy(sz_msg, "unused"); break; 484 case login : strcpy(sz_msg, "login"); break; 485 case logout : strcpy(sz_msg, "logout"); break; 486 case login_ok:strcpy(sz_msg, "login_ok"); break; 487 case logout_ok:strcpy(sz_msg, "logout_ok"); break; 488 case ping : strcpy(sz_msg, "ping"); break; 489 case pong : strcpy(sz_msg, "pong"); break; 490 case fail : strcpy(sz_msg, "fail"); break; 491 case trigger_backup: strcpy(sz_msg, "trigger_backup"); break; 492 case trigger_restore: strcpy(sz_msg, "trigger_restore"); break; 493 case begin_stream: strcpy(sz_msg, "begin_stream"); break; 494 case end_stream: strcpy(sz_msg, "end_stream"); break; 495 default: strcpy(sz_msg, "(Fix tmsg_to_string please)"); break; 496 } 497 return(sz_msg); 498 } 891 /*-----------------------------------------------------------*/ 892 893 894 895 void terminate_daemon(int sig) 896 /* 897 Purpose: Shut down the server in response to interrupt. 898 Params: Signal received. 899 Returns: None 900 */ 901 { 902 char command[MAX_STR_LEN+1]; 903 static bool logged_out_everyone=false; 904 905 set_signals(false); // termination in progress 906 log_it(info, "Abort signal caught by interrupt handler"); 907 if (!logged_out_everyone) 908 { 909 // FIXME - lock the var w/mutex 910 logged_out_everyone=true; 911 forcibly_logout_all_clients(); 912 } 913 /* 914 for(i=0; i<NOOF_THREADS; i--) 915 { 916 sprintf(tmp, "Terminating thread #%d", i); 917 log_it(debug, tmp); 918 pthread_join(g_threadinfo[i], NULL); 919 } 920 */ 921 forcibly_logout_all_clients(); 922 sprintf(command, "rm -f %s", g_command_fifo); 923 call_program_and_log_output(command); 924 // chmod(g_command_fifo, 0); 925 unlink(g_command_fifo); 926 unlink(g_server_status_file); 927 register_pid(0, "server"); 928 log_it(info, "---------- Monitas (server) has terminated ----------"); 929 exit(0); 930 } 931 932 933 934 /*-----------------------------------------------------------*/ 499 935 500 936 … … 514 950 int watch_port; 515 951 struct sockaddr_in sin; 516 char buf[MAX_STR_LEN+1], tmp[MAX_STR_LEN ];952 char buf[MAX_STR_LEN+1], tmp[MAX_STR_LEN+1]; 517 953 int len, s, new_s; 518 954 struct s_client2server_msg_record rec; 519 955 520 956 watch_port = atoi((char*)sz_watchport); 521 sprintf(tmp, "watch_port_for_requests_from_clients(%d) - starting", watch_port); 522 log_it(debug, tmp); 957 // sprintf(tmp, "watch_port_for_requests_from_clients(%d) - starting", watch_port); log_it(debug, tmp); 523 958 memset((void*)&sin, 0, sizeof(sin)); 524 959 sin.sin_family = AF_INET; … … 544 979 } 545 980 /* service incoming connections */ 546 sprintf(tmp, " Opened socket onport #%d OK", watch_port);547 log_it( info, tmp);981 sprintf(tmp, "Bound port #%d OK", watch_port); 982 log_it(debug, tmp); 548 983 while(true) 549 984 { … … 568 1003 569 1004 1005 /*-----------------------------------------------------------*/ 1006 1007 1008 570 1009 int main(int argc, char*argv[]) 571 1010 /* … … 575 1014 */ 576 1015 { 577 char tmp[MAX_STR_LEN]; 578 579 /* FIXME - add Ctrl-C / sigterm trapping */ 580 1016 pthread_t server_status_thread; 1017 1018 log_it(info, "---------- Monitas (server) by Hugo Rabson ----------"); 1019 register_pid(getpid(), "server"); 1020 set_signals(true); 581 1021 start_threads_to_watch_ports_for_requests(); 582 interact_with_sysadm(); /* report on users logged in, etc.; return after a while... */ 583 if (g_clientlist.items != 0) 584 { fprintf(stderr, "Ruh-roh! Some users are still logged in. Oh well...\n"); } 585 /* FIXME - force clients to log off */ 586 /* FIXME - send signal to threads, telling them to terminate */ 587 sprintf(tmp, "Done. Server is exiting now."); 588 log_it(info, tmp); 589 return(0); 1022 pthread_create(&server_status_thread, NULL, generate_server_status_file_regularly, (void*)SERVER_STATUS_FILE); 1023 create_and_watch_fifo_for_commands(SERVER_COMDEV); 1024 log_it(warn, "Execution should never reach this point"); 1025 exit(0); 590 1026 } 591 1027 /* end main() */
Note:
See TracChangeset
for help on using the changeset viewer.