Init: Start Update Engine at startup

Also related AU Fixes:

- daemonize() for upstart

- remember success in updating across runs of the process.

- bug fixes: don't try to update if an update is in progress, clear
  actions out in Update Attempter when updating is complete.

BUG=None
TEST=on device testing

Review URL: http://codereview.chromium.org/2055008
diff --git a/main.cc b/main.cc
index b2f14c4..ed2fcf5 100644
--- a/main.cc
+++ b/main.cc
@@ -19,6 +19,8 @@
 
 DEFINE_bool(logtostderr, false,
             "Write logs to stderr instead of to a file in log_dir.");
+DEFINE_bool(foreground, false,
+            "Don't daemon()ize; run in foreground.");
 
 using std::string;
 using std::tr1::shared_ptr;
@@ -92,6 +94,9 @@
                         logging::LOG_ONLY_TO_FILE),
                        logging::DONT_LOCK_LOG_FILE,
                        logging::APPEND_TO_OLD_LOG_FILE);
+  if (!FLAGS_foreground)
+    PLOG_IF(FATAL, daemon(0, 0) == 1) << "daemon() failed";
+
   LOG(INFO) << "Chrome OS Update Engine starting";
   
   // Create the single GMainLoop
diff --git a/update_attempter.cc b/update_attempter.cc
index ebfcd1d..ec0e1f5 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -30,6 +30,8 @@
 
 namespace chromeos_update_engine {
 
+const char* kUpdateCompletedMarker = "/tmp/update_engine_autoupdate_completed";
+
 namespace {
 // Returns true on success.
 bool GetCPUClockTime(struct timespec* out) {
@@ -84,6 +86,15 @@
 }
 
 void UpdateAttempter::Update(bool force_full_update) {
+  if (status_ == UPDATE_STATUS_UPDATED_NEED_REBOOT) {
+    LOG(INFO) << "Not updating b/c we already updated and we're waiting for "
+              << "reboot";
+    return;
+  }
+  if (status_ != UPDATE_STATUS_IDLE) {
+    // Update in progress. Do nothing
+    return;
+  }
   full_update_ = force_full_update;
   CHECK(!processor_.IsRunning());
   processor_.set_delegate(this);
@@ -167,8 +178,10 @@
                                      bool success) {
   CHECK(response_handler_action_);
   LOG(INFO) << "Processing Done.";
+  actions_.clear();
   if (success) {
     SetStatusAndNotify(UPDATE_STATUS_UPDATED_NEED_REBOOT);
+    utils::WriteFile(kUpdateCompletedMarker, "", 0);
   } else {
     LOG(INFO) << "Update failed.";
     SetStatusAndNotify(UPDATE_STATUS_IDLE);
@@ -178,6 +191,7 @@
 void UpdateAttempter::ProcessingStopped(const ActionProcessor* processor) {
   download_progress_ = 0.0;
   SetStatusAndNotify(UPDATE_STATUS_IDLE);
+  actions_.clear();
 }
 
 // Called whenever an action has finished processing, either successfully
diff --git a/update_attempter.h b/update_attempter.h
index 76fe3fb..9d69403 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -18,6 +18,8 @@
 
 namespace chromeos_update_engine {
 
+extern const char* kUpdateCompletedMarker;
+
 enum UpdateStatus {
   UPDATE_STATUS_IDLE = 0,
   UPDATE_STATUS_CHECKING_FOR_UPDATE,
@@ -42,6 +44,8 @@
                       new_size_(0) {
     last_notify_time_.tv_sec = 0;
     last_notify_time_.tv_nsec = 0;
+    if (utils::FileExists(kUpdateCompletedMarker))
+      status_ = UPDATE_STATUS_UPDATED_NEED_REBOOT;
   }
   void Update(bool force_full_update);