Changeset 352 in MondoRescue for branches/stable/monitas/client.c


Ignore:
Timestamp:
Jan 28, 2006, 6:41:40 PM (18 years ago)
Author:
bcornec
Message:

monitas v0.1a

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/monitas/client.c

    r351 r352  
    44
    55
     6
    67FIXME
    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
     1206/19
     13- fixed bugs in mondoarchive compare code
     14- added track_restore_task_progress()
     15
     1606/16
     17- when calling mondoarchive in bkgd, see if it starts OK; if it
     18  doesn't then say so & return error
     19
     2006/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
     2506/11
     26- added call to register_pid()
     27- commented code a bit
     28- implemented compare_archives and restore_archives()
     29
     3006/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
     3505/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
     4305/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
    1847- added tmsg_to_string()
    1948- forked port-watcher to receive triggers from server in bkgd
     
    3261
    3362#include "structs.h"
     63//#define LOG_THESE_AND_HIGHER debug
     64#define LOGFILE "/var/log/monitas-client.log"
    3465
    3566
     
    3768/* global vars */
    3869
    39 
     70bool g_logged_in_currently=false, g_logging_out=false;
     71int g_sClient=-1, g_client_port=0; /* client port; set by login */
     72struct sockaddr_in g_sinClient; /* client port */
     73char g_server_name[MAX_STR_LEN+1];
     74pthread_t g_mondo_thread=0;
     75char g_command_fifo[MAX_STR_LEN+1];
     76char g_logfile[MAX_STR_LEN+1] = "/var/log/monitas-client.log";
     77
     78/* externs */
     79
     80extern char *call_program_and_get_last_line_of_output(char*);
     81extern int call_program_and_log_output(char*);
     82extern void call_program_in_background(pthread_t*, char*);
     83extern int create_and_watch_fifo_for_commands(char*);
     84extern bool does_file_exist(char*);
     85extern int get_bkgd_prog_result(pthread_t*);
     86extern void log_it_SUB(char*, t_loglevel level, char *sz_message);
     87extern bool program_still_running(char*);
     88extern int receive_file_from_socket(FILE*, int);
     89extern void register_pid(pid_t, char*);
     90extern char *tmsg_to_string(t_msg msg_type);
     91extern int transmit_file_to_socket(FILE*, int);
     92extern void register_pid(pid_t, char*);
     93extern void set_signals(bool);
    4094
    4195/* prototypes */
    4296
     97int accept_and_recv_thru_client_port(int, int*, struct sockaddr_in*, char*, int);
     98int back_my_smitch_up(char*, int);
     99int bind_client_port(struct sockaddr_in*, int);
     100int compare_archives(char*, int);
    43101int find_and_bind_free_server_port(struct sockaddr_in*, int*);
    44102long increment_magic_number(void);
    45103int login_to_server(char*,char*);
     104void logout_and_exit(char*);
    46105int logout_of_server(char*);
     106int process_incoming_command(char*);
     107int restore_archives(char*, char*, int);
     108void restore_archives_SIGPIPE(int);
     109int send_final_progress_report(char*);
    47110int send_msg_to_server(struct s_client2server_msg_record*, char*);
    48111int 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 */
     112int send_progress_rpt_to_server(char*, char*);
     113void terminate_daemon(int);
     114void *track_backup_task_progress(void*);
     115void *track_compare_task_progress(void*);
     116void *track_restore_task_progress(void*);
     117void *watch_port_for_triggers_from_server(void*);
     118
     119
     120
     121
     122/*-----------------------------------------------------------*/
     123
     124
     125
     126int accept_and_recv_thru_client_port(int sClient, int *new_sClient, struct sockaddr_in*sinClient, char*incoming, int expected_length)
     127/*
     128Purpose:Run accept() and recv() to open port and receive
     129    message from server.
     130Params: 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
     135Return: 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
     152char *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
     169int back_my_smitch_up(char*msgbody, int socket_fd)
     170/*
     171Purpose:Backup archives to server.
     172Params: 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.
     176Return: 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
     263int bind_client_port(struct sockaddr_in *sinClient, int client_port)
     264/*
     265Purpose:Bind one of my ports so that I may open it later and
     266        write/read data to/from server with it.
     267Params: sinClient - record/structure relating to the socket
     268        client_port - port# to be bound
     269Return: 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
     308int compare_archives(char*msgbody, int socket_fd)
     309/*
     310Purpose:Compare archives, sent by server.
     311Params: msgbody - char[MSG_BODY_SIZE] containing info
     312about the archives to be compared
     313socket_fd - file descriptor from which to
     314read the archives sent by server to be compared.
     315Return: 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
    53422
    54423int find_and_bind_free_server_port(struct sockaddr_in *sin, int *p_s)
     
    59428Params: sin - server's IP address in a structure
    60429    p_s - [return] file descriptor of port binding
    61 Return: result (0=success, nonzero=failure)
     430Return: result (>0=success, -1=failure)
    62431*/
    63432{
    64433  int server_port;
     434  char tmp[MAX_STR_LEN+1];
    65435
    66436  for(server_port = 8700; server_port < 8710; server_port++)
     
    70440    {
    71441      perror("socket");
    72       return(1);
     442      return(-1);
    73443    }
    74444      if (connect(*p_s, (struct sockaddr*)sin, sizeof(struct sockaddr_in)) < 0)
    75445    {
    76       printf("Not connecting at %d\r", server_port);
     446      sprintf(tmp, "Not connecting at %d", server_port);
     447      log_it(debug, tmp);
    77448      continue;
    78449    }
    79450      return(server_port);
    80451    }
    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/*-----------------------------------------------------------*/
    84458
    85459
     
    98472  return(magic);
    99473}
     474
     475
     476
     477/*-----------------------------------------------------------*/
    100478
    101479
     
    113491{
    114492  struct s_client2server_msg_record orig_rec;
    115   int i;
    116493
    117494  orig_rec.msg_type = login;
    118495  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
     509void logout_and_exit(char*servername)
     510/*
     511Purpose:Logout of server. Terminate.
     512Params: servername - ip address of server
     513Return: 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/*-----------------------------------------------------------*/
    128532
    129533
     
    138542  struct s_client2server_msg_record orig_rec;
    139543
     544  g_logging_out = true;
     545  log_it(debug, "Logging out of server");
    140546  orig_rec.msg_type = logout;
    141547  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)
    143549    { return(1); }
    144550  else
     
    148554
    149555
    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
     560int process_incoming_command(char*incoming)
     561/*
     562Purpose:Process incoming command, presumably
     563        read from FIFO and sent there by sysadm/user.
     564Params: incoming - raw command string itself
     565Return: 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
     612int restore_archives(char*msgbody, char*msgbodyAux, int socket_fd)
     613/*
     614Purpose:Restore archives, sent by server.
     615Params: msgbody - char[MSG_BODY_SIZE] containing info
     616about the archives to be restored
     617socket_fd - file descriptor from which to
     618read the archives sent by server.
     619Return: 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
     736void *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
     748int 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
    153763int send_msg_to_server(struct s_client2server_msg_record *rec, char *servername)
    154764/*
    155765Purpose:Send message to server - a login/logout/ping request
    156     or perhaps a request for data to be restored.
     766        or perhaps a request for data to be restored.
    157767Params: rec - the message to be sent to server
    158     servername - the hostname of server
    159 Return: result (-1=failure, >0=success)
     768        servername - the hostname of server
     769Return: result (<0=failure, 0+=success)
    160770*/
    161771{
    162772  struct hostent *hp;
    163773  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;
    169775  struct s_server2client_msg_record incoming_rec;
    170776  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;
    172780
    173781/* 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); }
     782otherwise, 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 */
    195796  /* open client port if login */
    196 
    197797  if (rec->msg_type == login)
    198798    {
    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    }
    210804  /* send msg to server */
    211   rec->port = st_client_port;
     805  rec->port = g_client_port;
    212806  memset((void*)&sin, 0, sizeof(sin));
    213807  sin.sin_family = AF_INET;
    214808  memcpy((void*)&sin.sin_addr, hp->h_addr, hp->h_length);
    215809  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    }
    217816  rec->magic = increment_magic_number();
    218817  send (s, (char*)rec, sizeof(struct s_client2server_msg_record), 0);
    219818  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    }
    236845  if (rec->msg_type == logout)
    237846    {
    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
     861int send_ping_to_server(char*servername, char*msg)
     862/*
     863Purpose:Send a 'ping' to server.
    266864Params: msg - string to send ("Hello world"?)
    267865    servername - server's hostname
     
    272870  orig_rec.msg_type = ping;
    273871  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)
    275873    { return(1); }
    276874  else
     
    280878
    281879
    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
     884int send_progress_rpt_to_server(char*servername, char*msg)
     885/*
     886Purpose:Send a 'progress_rpt' string to server.
     887Params: msg - string to send ("Hello world"?)
     888    servername - server's hostname
     889Return: 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
     907void terminate_daemon(int sig)
     908/*
     909Purpose: Shut down the server in response to interrupt.
     910Params:  Signal received.
     911Returns: 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
     935void *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
     1026void *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
     1100void *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
     1181void *watch_port_for_triggers_from_server(void*arg)
    3111182/*
    3121183Purpose: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.
     1184Params: none; uses global vars instead
    3171185Return: none
     1186*/
    3181187{
    3191188  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");
    3221195  for(;;)
    3231196    {
    324   /* wait for ack/pong/feedback */
    325       ufds.fd = s;
     1197      /* wait for ack/pong/feedback/trigger */
     1198      ufds.fd = g_sClient;
    3261199      ufds.events = POLLIN|POLLPRI;
    3271200      poll(&ufds, 1, 1000);
    3281201      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
    3401237
    3411238int main(int argc, char*argv[])
     
    3471244{
    3481245  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);
    3521254  srandom(time(NULL));
    3531255  /* 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*/
    3561265  if (argc == 2)
    3571266    {
    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';
    3601269    }
    3611270  else
     
    3651274    }
    3661275  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);
    3841290  exit(0);
    3851291}
Note: See TracChangeset for help on using the changeset viewer.