int main (int argc, char *argv[]) { int ret=1; int option=0; int daemon=1; int forking=1; int strip=0; struct lock *lock=NULL; struct conf *conf=NULL; int forceoverwrite=0; enum action act=ACTION_LIST; const char *backup=NULL; const char *restoreprefix=NULL; const char *regex=NULL; const char *browsefile=NULL; const char *browsedir=NULL; const char *conffile=get_conf_path(); const char *orig_client=NULL; // The orig_client is the original client that the normal client // would like to restore from. #ifndef HAVE_WIN32 const char *sclient=NULL; // Status monitor client to view. int generate_ca_only=0; #endif int vss_restore=1; int json=0; init_log(argv[0]); while((option=getopt(argc, argv, "a:b:c:C:d:ghfFil:nr:s:vxjz:?"))!=-1) { switch(option) { case 'a': if(parse_action(&act, optarg)) goto end; break; case 'b': backup=optarg; break; case 'c': conffile=optarg; break; case 'C': orig_client=optarg; #ifndef HAVE_WIN32 sclient=optarg; #endif break; case 'd': restoreprefix=optarg; // for restores browsedir=optarg; // for lists break; case 'f': forceoverwrite=1; break; case 'F': daemon=0; break; case 'g': #ifndef HAVE_WIN32 generate_ca_only=1; #endif break; case 'i': cmd_print_all(); ret=0; goto end; case 'l': logp("-l <logfile> option obsoleted\n"); break; case 'n': forking=0; break; case 'r': regex=optarg; break; case 's': strip=atoi(optarg); break; case 'v': printf("%s-%s\n", progname(), VERSION); ret=0; goto end; case 'x': vss_restore=0; break; case 'j': json=1; break; case 'z': browsefile=optarg; break; case 'h': case '?': default: usage(); goto end; } } if(optind<argc) { usage(); goto end; } if(!(conf=conf_alloc())) goto end; if(reload(conf, conffile, 1 /* first time */, 0 /* no oldmax_children setting */, 0 /* no oldmax_status_children setting */, json)) goto end; if((act==ACTION_RESTORE || act==ACTION_VERIFY) && !backup) { logp("No backup specified. Using the most recent.\n"); backup="0"; } if(act==ACTION_DELETE && !backup) { logp("No backup specified for deletion.\n"); goto end; } if(conf->mode==MODE_CLIENT) { if(orig_client && *orig_client) { if(!(conf->orig_client=strdup(orig_client))) { log_out_of_memory(__func__); goto end; } } } if(conf->mode==MODE_SERVER && (act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT || act==ACTION_CHAMP_CHOOSER)) { // These server modes need to run without getting the lock. } else { if(!(lock=lock_alloc_and_init(conf->lockfile))) goto end; lock_get(lock); switch(lock->status) { case GET_LOCK_GOT: break; case GET_LOCK_NOT_GOT: logp("Could not get lockfile.\n"); logp("Another process is probably running,\n"); goto end; case GET_LOCK_ERROR: default: logp("Could not get lockfile.\n"); logp("Maybe you do not have permissions to write to %s.\n", conf->lockfile); goto end; } } conf->overwrite=forceoverwrite; conf->strip=strip; conf->forking=forking; conf->daemon=daemon; if(replace_conf_str(backup, &conf->backup) || replace_conf_str(restoreprefix, &conf->restoreprefix) || replace_conf_str(regex, &conf->regex) || replace_conf_str(browsefile, &conf->browsefile) || replace_conf_str(browsedir, &conf->browsedir)) goto end; if(conf->mode==MODE_SERVER) { #ifdef HAVE_WIN32 logp("Sorry, server mode is not implemented for Windows.\n"); #else if(act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT) { // We are running on the server machine, being a client // of the burp server, getting status information. ret=status_client_ncurses(conf, act, sclient); } else if(act==ACTION_CHAMP_CHOOSER) { // We are running on the server machine, wanting to // be a standalone champion chooser process. if(!sclient || !*sclient) { logp("No client name specified for standalone champion chooser process.\n"); logp("Try using the '-C' option.\n"); ret=1; } else ret=champ_chooser_server_standalone(conf, sclient); } else ret=server(conf, conffile, lock, generate_ca_only); #endif } else { logp("before client\n"); ret=client(conf, act, vss_restore, json); logp("after client\n"); } end: lock_release(lock); lock_free(&lock); conf_free(conf); return ret; }
int main (int argc, char *argv[]) { int ret=0; int option=0; int daemon=1; int forking=1; int gotlock=0; int strip=0; struct config conf; int forceoverwrite=0; enum action act=ACTION_LIST; const char *backup=NULL; const char *restoreprefix=NULL; const char *regex=NULL; const char *browsefile=NULL; const char *browsedir=NULL; FILE *fp=NULL; const char *configfile=get_config_path(); const char *orig_client=NULL; // The orig_client is the original client that the normal client // would like to restore from. #ifndef HAVE_WIN32 const char *sclient=NULL; // Status monitor client to view. int generate_ca_only=0; #endif init_log(argv[0]); while((option=getopt(argc, argv, "a:b:c:C:d:ghfFil:nr:s:vz:?"))!=-1) { switch(option) { case 'a': if(!strncmp(optarg, "backup", 1)) act=ACTION_BACKUP; else if(!strncmp(optarg, "timedbackup", 1)) act=ACTION_BACKUP_TIMED; else if(!strncmp(optarg, "restore", 1)) act=ACTION_RESTORE; else if(!strncmp(optarg, "verify", 1)) act=ACTION_VERIFY; else if(!strncmp(optarg, "list", 1)) act=ACTION_LIST; else if(!strncmp(optarg, "List", 1)) act=ACTION_LONG_LIST; else if(!strncmp(optarg, "status", 1)) act=ACTION_STATUS; else if(!strncmp(optarg, "Status", 1)) act=ACTION_STATUS_SNAPSHOT; else if(!strncmp(optarg, "estimate", 1)) act=ACTION_ESTIMATE; else { usage(); return 1; } break; case 'b': backup=optarg; break; case 'c': configfile=optarg; break; case 'C': orig_client=optarg; #ifndef HAVE_WIN32 sclient=optarg; #endif break; case 'd': restoreprefix=optarg; // for restores browsedir=optarg; // for lists break; case 'f': forceoverwrite=1; break; case 'F': daemon=0; break; case 'g': #ifndef HAVE_WIN32 generate_ca_only=1; #endif break; case 'i': print_all_cmds(); return 0; case 'l': logp("-l <logfile> option obsoleted\n"); break; case 'n': forking=0; break; case 'r': regex=optarg; break; case 's': strip=atoi(optarg); break; case 'v': printf("%s-%s\n", progname(), VERSION); return 0; case 'z': browsefile=optarg; break; case 'h': case '?': default: usage(); return 1; break; } } if(optind<argc) { usage(); return 1; } if(reload(&conf, configfile, 1 /* first time */, 0 /* no oldmax_children setting */, 0 /* no oldmax_status_children setting */)) return 1; if((act==ACTION_RESTORE || act==ACTION_VERIFY) && !backup) { logp("No backup specified. Using the most recent.\n"); backup="0"; } if(conf.mode==MODE_CLIENT) { if(orig_client && *orig_client) { if(!(conf.orig_client=strdup(orig_client))) { logp("out of memory\n"); return 1; } } } if(conf.mode==MODE_SERVER && (act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT)) { // Server status mode needs to run without getting the lock. } else { if(get_lock(conf.lockfile)) { logp("Could not get lockfile.\n"); logp("Another process is probably running,\n"); logp("or you do not have permissions to write to %s.\n", conf.lockfile); return 1; } gotlock++; } conf.overwrite=forceoverwrite; conf.strip=strip; conf.forking=forking; conf.daemon=daemon; if(replace_conf_str(backup, &(conf.backup)) || replace_conf_str(restoreprefix, &(conf.restoreprefix)) || replace_conf_str(regex, &(conf.regex)) || replace_conf_str(browsefile, &(conf.browsefile)) || replace_conf_str(browsedir, &(conf.browsedir))) return -1; if(conf.mode==MODE_SERVER) { #ifdef HAVE_WIN32 logp("Sorry, server mode is not implemented for Windows.\n"); #else if(act==ACTION_STATUS || act==ACTION_STATUS_SNAPSHOT) { // We are running on the server machine, being a client // of the burp server, getting status information. ret=status_client_ncurses(&conf, act, sclient); } else ret=server(&conf, configfile, generate_ca_only); #endif } else { logp("before client\n"); ret=client(&conf, act); logp("after client\n"); } if(gotlock) unlink(conf.lockfile); free_config(&conf); // If there was no forking, logfp ends up getting closed before this // and will segfault if we try to do it again. if(fp && conf.forking) fclose(fp); return ret; }
static enum cliret do_client(struct conf **confs, enum action action, int vss_restore) { enum cliret ret=CLIENT_OK; int rfd=-1; SSL *ssl=NULL; SSL_CTX *ctx=NULL; struct cntr *cntr=NULL; char *incexc=NULL; enum action act=action; struct async *as=NULL; struct asfd *asfd=NULL; // as->settimers(0, 100); // logp("begin client\n"); // logp("action %d\n", action); // Status monitor forks a child process instead of connecting to // the server directly. if(action==ACTION_STATUS || action==ACTION_STATUS_SNAPSHOT) { #ifdef HAVE_WIN32 logp("Status mode not implemented on Windows.\n"); goto error; #endif if(status_client_ncurses_init(act) || status_client_ncurses(confs)) ret=CLIENT_ERROR; goto end; } if(!(cntr=cntr_alloc()) || cntr_init(cntr, get_string(confs[OPT_CNAME]))) goto error; set_cntr(confs[OPT_CNTR], cntr); if(act!=ACTION_ESTIMATE && ssl_setup(&rfd, &ssl, &ctx, action, confs)) goto could_not_connect; if(!(as=async_alloc()) || !(asfd=asfd_alloc()) || as->init(as, act==ACTION_ESTIMATE) || asfd->init(asfd, "main socket", as, rfd, ssl, ASFD_STREAM_STANDARD, confs)) goto end; as->asfd_add(as, asfd); // Set quality of service bits on backup packets. if(act==ACTION_BACKUP || act==ACTION_BACKUP_TIMED || act==ACTION_TIMER_CHECK) as->asfd->set_bulk_packets(as->asfd); if(act!=ACTION_ESTIMATE) { if((ret=initial_comms(as, &act, &incexc, confs))) goto end; } rfd=-1; switch(act) { case ACTION_BACKUP: ret=backup_wrapper(asfd, act, "backupphase1", incexc, confs); break; case ACTION_BACKUP_TIMED: ret=backup_wrapper(asfd, act, "backupphase1timed", incexc, confs); break; case ACTION_TIMER_CHECK: ret=backup_wrapper(asfd, act, "backupphase1timedcheck", incexc, confs); break; case ACTION_RESTORE: case ACTION_VERIFY: ret=restore_wrapper(asfd, act, vss_restore, confs); break; case ACTION_ESTIMATE: if(do_backup_client(asfd, confs, act, 0)) goto error; break; case ACTION_DELETE: if(do_delete_client(asfd, confs)) goto error; break; case ACTION_MONITOR: if(do_monitor_client(asfd, confs)) goto error; break; case ACTION_DIFF: case ACTION_DIFF_LONG: /* if(!strcmp(get_string(confs[OPT_BACKUP2]), "n")) // Do a phase1 scan and diff that. ret=backup_wrapper(asfd, act, "backupphase1diff", incexc, confs); else */ // Diff two backups that already exist. // Fall through, the list code is all we need // for simple diffs on the client side. case ACTION_LIST: case ACTION_LIST_LONG: default: if(do_list_client(asfd, act, confs)) goto error; break; } if(asfd_flush_asio(asfd)) ret=CLIENT_ERROR; goto end; error: ret=CLIENT_ERROR; goto end; could_not_connect: ret=CLIENT_COULD_NOT_CONNECT; end: close_fd(&rfd); async_free(&as); asfd_free(&asfd); if(ctx) ssl_destroy_ctx(ctx); free_w(&incexc); set_cntr(confs[OPT_CNTR], NULL); cntr_free(&cntr); //logp("end client\n"); return ret; }