summaryrefslogtreecommitdiff
path: root/bin/bbackupctl/bbackupctl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bin/bbackupctl/bbackupctl.cpp')
-rw-r--r--bin/bbackupctl/bbackupctl.cpp302
1 files changed, 302 insertions, 0 deletions
diff --git a/bin/bbackupctl/bbackupctl.cpp b/bin/bbackupctl/bbackupctl.cpp
new file mode 100644
index 00000000..5b09b4b5
--- /dev/null
+++ b/bin/bbackupctl/bbackupctl.cpp
@@ -0,0 +1,302 @@
+// distribution boxbackup-0.10 (svn version: 494)
+//
+// Copyright (c) 2003 - 2006
+// Ben Summers and contributors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. All use of this software and associated advertising materials must
+// display the following acknowledgment:
+// This product includes software developed by Ben Summers.
+// 4. The names of the Authors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// [Where legally impermissible the Authors do not disclaim liability for
+// direct physical injury or death caused solely by defects in the software
+// unless it is modified by a third party.]
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//
+//
+// --------------------------------------------------------------------------
+//
+// File
+// Name: bbackupctl.cpp
+// Purpose: bbackupd daemon control program
+// Created: 18/2/04
+//
+// --------------------------------------------------------------------------
+
+#include "Box.h"
+
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+#endif
+
+#include "MainHelper.h"
+#include "BoxPortsAndFiles.h"
+#include "BackupDaemonConfigVerify.h"
+#include "Socket.h"
+#include "SocketStream.h"
+#include "IOStreamGetLine.h"
+
+#ifdef WIN32
+ #include "WinNamedPipeStream.h"
+#endif
+
+#include "MemLeakFindOn.h"
+
+void PrintUsageAndExit()
+{
+ printf("Usage: bbackupctl [-q] [-c config_file] <command>\n"
+ "Commands are:\n"
+ " sync -- start a syncronisation run now\n"
+ " force-sync -- force the start of a syncronisation run, "
+ "even if SyncAllowScript says no\n"
+ " reload -- reload daemon configuration\n"
+ " terminate -- terminate daemon now\n"
+ " wait-for-sync -- wait until the next sync starts, then exit\n"
+ );
+ exit(1);
+}
+
+int main(int argc, const char *argv[])
+{
+ int returnCode = 0;
+
+#if defined WIN32 && ! defined NDEBUG
+ ::openlog("Box Backup (bbackupctl)", 0, 0);
+#endif
+
+ MAINHELPER_SETUP_MEMORY_LEAK_EXIT_REPORT("bbackupctl.memleaks",
+ "bbackupctl")
+
+ MAINHELPER_START
+
+ // Filename for configuraiton file?
+ const char *configFilename = BOX_FILE_BBACKUPD_DEFAULT_CONFIG;
+
+ // Quiet?
+ bool quiet = false;
+
+ // See if there's another entry on the command line
+ int c;
+ while((c = getopt(argc, (char * const *)argv, "qc:l:")) != -1)
+ {
+ switch(c)
+ {
+ case 'q':
+ // Quiet mode
+ quiet = true;
+ break;
+
+ case 'c':
+ // store argument
+ configFilename = optarg;
+ break;
+
+ case '?':
+ default:
+ PrintUsageAndExit();
+ }
+ }
+ // Adjust arguments
+ argc -= optind;
+ argv += optind;
+
+ // Check there's a command
+ if(argc != 1)
+ {
+ PrintUsageAndExit();
+ }
+
+ // Read in the configuration file
+ if(!quiet) printf("Using configuration file %s\n", configFilename);
+ std::string errs;
+ std::auto_ptr<Configuration> config(Configuration::LoadAndVerify(configFilename, &BackupDaemonConfigVerify, errs));
+ if(config.get() == 0 || !errs.empty())
+ {
+ printf("Invalid configuration file:\n%s", errs.c_str());
+ return 1;
+ }
+ // Easier coding
+ const Configuration &conf(*config);
+
+ // Check there's a socket defined in the config file
+ if(!conf.KeyExists("CommandSocket"))
+ {
+ printf("Daemon isn't using a control socket, could not execute command.\nAdd a CommandSocket declaration to the bbackupd.conf file.\n");
+ return 1;
+ }
+
+ // Connect to socket
+
+#ifndef WIN32
+ SocketStream connection;
+#else /* WIN32 */
+ WinNamedPipeStream connection;
+#endif /* ! WIN32 */
+
+ try
+ {
+#ifdef WIN32
+ connection.Connect(BOX_NAMED_PIPE_NAME);
+#else
+ connection.Open(Socket::TypeUNIX, conf.GetKeyValue("CommandSocket").c_str());
+#endif
+ }
+ catch(...)
+ {
+ printf("Failed to connect to daemon control socket.\n"
+ "Possible causes:\n"
+ " * Daemon not running\n"
+ " * Daemon busy syncing with store server\n"
+ " * Another bbackupctl process is communicating with the daemon\n"
+ " * Daemon is waiting to recover from an error\n"
+ );
+
+#if defined WIN32 && ! defined NDEBUG
+ syslog(LOG_ERR,"Failed to connect to the command socket");
+#endif
+
+ return 1;
+ }
+
+ // For receiving data
+ IOStreamGetLine getLine(connection);
+
+ // Wait for the configuration summary
+ std::string configSummary;
+ if(!getLine.GetLine(configSummary))
+ {
+#if defined WIN32 && ! defined NDEBUG
+ syslog(LOG_ERR, "Failed to receive configuration summary "
+ "from daemon");
+#else
+ printf("Failed to receive configuration summary from daemon\n");
+#endif
+
+ return 1;
+ }
+
+ // Was the connection rejected by the server?
+ if(getLine.IsEOF())
+ {
+#if defined WIN32 && ! defined NDEBUG
+ syslog(LOG_ERR, "Server rejected the connection. "
+ "Are you running bbackupctl as the same user "
+ "as the daemon?");
+#else
+ printf("Server rejected the connection. "
+ "Are you running bbackupctl as the same user "
+ "as the daemon?\n");
+#endif
+
+ return 1;
+ }
+
+ // Decode it
+ int autoBackup, updateStoreInterval, minimumFileAge, maxUploadWait;
+ if(::sscanf(configSummary.c_str(), "bbackupd: %d %d %d %d", &autoBackup,
+ &updateStoreInterval, &minimumFileAge, &maxUploadWait) != 4)
+ {
+ printf("Config summary didn't decode\n");
+ return 1;
+ }
+ // Print summary?
+ if(!quiet)
+ {
+ printf("Daemon configuration summary:\n" \
+ " AutomaticBackup = %s\n" \
+ " UpdateStoreInterval = %d seconds\n" \
+ " MinimumFileAge = %d seconds\n" \
+ " MaxUploadWait = %d seconds\n",
+ autoBackup?"true":"false", updateStoreInterval, minimumFileAge, maxUploadWait);
+ }
+
+ // Is the command the "wait for sync to start" command?
+ bool areWaitingForSync = false;
+ if(::strcmp(argv[0], "wait-for-sync") == 0)
+ {
+ // Check that it's not in non-automatic mode, because then it'll never start
+ if(!autoBackup)
+ {
+ printf("ERROR: Daemon is not in automatic mode -- sync will never start!\n");
+ return 1;
+ }
+
+ // Yes... set the flag so we know what we're waiting for a sync to start
+ areWaitingForSync = true;
+ }
+ else
+ {
+ // No? Just send the command given plus a quit command.
+ std::string cmd(argv[0]);
+ cmd += "\nquit\n";
+ connection.Write(cmd.c_str(), cmd.size());
+ }
+
+ // Read the response
+ std::string line;
+ while(!getLine.IsEOF() && getLine.GetLine(line))
+ {
+ if(areWaitingForSync)
+ {
+ // Need to wait for the state change...
+ if(line == "start-sync")
+ {
+ // Send a quit command to finish nicely
+ connection.Write("quit\n", 5);
+
+ // And we're done
+ break;
+ }
+ }
+ else
+ {
+ // Is this an OK or error line?
+ if(line == "ok")
+ {
+ if(!quiet)
+ {
+ printf("Succeeded.\n");
+ }
+ break;
+ }
+ else if(line == "error")
+ {
+ printf("ERROR. (Check command spelling)\n");
+ returnCode = 1;
+ break;
+ }
+ }
+ }
+
+ MAINHELPER_END
+
+#if defined WIN32 && ! defined NDEBUG
+ closelog();
+#endif
+
+ return returnCode;
+}