int main()

in common/recipes-core/fw-util/files/fw-util.cpp [182:459]


int main(int argc, char *argv[])
{
  int ret = 0;
  int find_comp = 0;
  int lfd;
  struct sigaction sa;

  System system;
  Component::fru_list_setup();

#ifdef __TEST__
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
#endif
  exec_name = argv[0];
  if (argc < 3) {
    usage();
    return -1;
  }

  string fru(argv[1]);
  string action(argv[2]);
  string component("all");
  string image("");
  string sub_action("");
  string time("");
  string task_id("");
  json json_array(nullptr);
  bool add_task = false;
  Scheduler tasker;

  if (action == "--force") {
    if (argc < 4) {
      usage();
      return -1;
    }
    string action_ext(argv[3]);
    if (action_ext != "--update") {
      usage();
      return -1;
    }
    if (argc >= 5) {
      component.assign(argv[4]);
      if (component.compare(0, 2, "--") == 0) {
        cerr << "WARNING: Passing component as " << component << " is deprecated" << endl;
        component = component.substr(2);
        cerr << "         Use: --version|--update " << component << " instead" << endl;
      }
    }
  } else {
    if (argc >= 4) {
      component.assign(argv[3]);
      if (component.compare(0, 2, "--") == 0) {
        cerr << "WARNING: Passing component as " << component << " is deprecated" << endl;
        component = component.substr(2);
        cerr << "         Use: --version|--update " << component << " instead" << endl;
      }

      if ( argc == 7 ) {
        sub_action.assign(argv[5]);
        time.assign(argv[6]);
        if (time != "now") { // only can set time to "now"
          cerr << "Only can schedule update " << component << " now" << endl;
          usage();
          return -1;
        }
      } else {
        task_id.assign(argv[3]);
      }
    }
  }

  if ((action == "--update") || (action == "--dump")) {
    if (argc != 5 && argc != 7 ) {
      usage();
      return -1;
    }
    image.assign(argv[4]);
    if (action == "--update" && image != "-") {
      ifstream f(image);
      if (!f.good()) {
        cerr << "Cannot access: " << image << endl;
        return -1;
      }
    }
    if (component == "all") {
      cerr << "Upgrading all components not supported" << endl;
      return -1;
    }

    if ( sub_action.empty() == false ) {
      if ( sub_action == "--schedule" ) {
        add_task = true;
      } else {
        cerr << "Invalid action: " << sub_action << endl;
        return -1;
      }
    }
  } else if (action == "--force") {
    if (argc != 6) {
      usage();
      return -1;
    }
    image.assign(argv[5]);
    if (image != "-") {
      ifstream f(image);
      if (!f.good()) {
        cerr << "Cannot access: " << image << endl;
        return -1;
      }
    }
    if (component == "all") {
      cerr << "Upgrading all components not supported" << endl;
      return -1;
    }
  } else if (action == "--version") {
    if(argc > 4) {
      usage();
      return -1;
    }
  } else if (action == "--version-json" ) {
    json_array = json::array();
  } else if ( action == "--show-schedule" ) {
    if (fru != "all") {
      cerr << "Invalid fru: " <<  fru <<" for showing schedule" << endl;
      usage();
      return -1;
    }
    return tasker.show_task();
  } else if ( action == "--delete-schedule" ) {
    if (fru != "all") {
      cerr << "Invalid fru: " <<  fru <<" for deleting schedule" << endl;
      usage();
      return -1;
    }
    return tasker.del_task(task_id);
  } else {
    cerr << "Invalid action: " << action << endl;
    usage();
    return -1;
  }

  sa.sa_handler = fw_util_sig_handler;
  sa.sa_flags = 0;
  sigemptyset(&sa.sa_mask);
  sigaction(SIGHUP, &sa, NULL);
  sigaction(SIGINT, &sa, NULL);
  sigaction(SIGTERM, &sa, NULL);
  sigaction(SIGPIPE, &sa, NULL); // for ssh terminate
  //print the fw version or do the fw update when the fru and the comp are found
  for (auto fkv : *Component::fru_list) {
    if (fru == "all" || fru == fkv.first) {
      for (auto ckv : fkv.second) {
        string comp_name = ckv.first;
        if (component == "all" || component == comp_name) {
          find_comp = 1;
          Component *c = ckv.second;

          // Ignore aliases if their target is going to be
          // considered in one of the loops.
          if (c->is_alias()) {
            if (component == "all" && (fru == "all" || fru == c->alias_fru()))
              continue;
            if (fru == "all" && component == c->alias_component())
              continue;
          }

          // We are going to add a task but print fw version
          // or do fw update.
          if ( add_task == true ) {
            return tasker.add_task(fru, component, image, time);
          }

          if (c->is_sled_cycle_initiated()) {
            cerr << "Upgrade aborted due to fw update preparing" << endl;
            return -1;
          }

          lfd = single_instance_lock_blocked(string("fw-util_"+c->fru()).c_str());
          if (lfd < 0) {
            syslog(LOG_WARNING, "Error getting single_instance_lock");
          }
          if (c->is_update_ongoing()) {
            cerr << "Upgrade aborted due to ongoing upgrade on FRU: " << c->fru() << endl;
            single_instance_unlock(lfd);
            return -1;
          }
          if (action.rfind("--version", 0) == string::npos && fru != "all") {
            // update or dump
            c->set_update_ongoing(60 * 10);
          }
          single_instance_unlock(lfd);

          if (action == "--version") {
            ret = c->print_version();
            if (ret != FW_STATUS_SUCCESS && ret != FW_STATUS_NOT_SUPPORTED) {
              cerr << "Error getting version of " << c->component()
                << " on fru: " << c->fru() << endl;
            }
          } else if ( action == "--version-json" ) {
            json j_object = {{"FRU", c->fru()}, {"COMPONENT", c->component()}};
            c->get_version(j_object);
            json_array.push_back(j_object);
          } else {  // update or dump
            if (fru == "all") {
              usage();
              return -1;
            }

            string str_act("");

            // ensure the shutdown (reboot) will not be execute during update
            if (system.wait_shutdown_non_executable(2)) {
              // the permission of shutdown command not changed
              // add warning message to syslog here, and continue the update process
              syslog(LOG_WARNING, "fw-util: shutdown command can still be executed after 2 seconds waiting");
            }

            if (system.is_reboot_ongoing()) {
              cout << "Aborted action due to reboot ongoing" << endl;
              c->set_update_ongoing(0);
              return -1;
            }

            if (action == "--update") {
              if (image != "-") {
                ret = c->update(image);
              } else {
                ret = c->update(0, false /* force */);
              }
              str_act.assign("Upgrade");
            } else if (action == "--force") {
              if (image != "-") {
                ret = c->fupdate(image);
              } else {
                ret = c->update(0 /* fd */, true /* force */);
              }
              str_act.assign("Force upgrade");
            } else {
              ret = c->dump(image);
              str_act.assign("Dump");
            }
            c->set_update_ongoing(0);
            if (ret == 0) {
              cout << str_act << " of " << c->fru() << " : " << component << " succeeded" << endl;
              c->update_finish();
            } else {
              cerr << str_act << " of " << c->fru() << " : " << component;
              if (ret == FW_STATUS_NOT_SUPPORTED) {
                cerr << " not supported" << endl;
              } else {
                cerr << " failed" << endl;
              }
              return -1;
            }
          }

          if (quit_process.load()) {
            syslog(LOG_DEBUG, "fw-util: Terminate request handled");
            cout << "Aborted action due to signal\n";
            return -1;
          }
        }
      }
    }
  }

  if (!find_comp) {
    usage();
    return -1;
  }

  if ( action == "--version-json" ) {
    cout << json_array.dump(4) << endl;
  }

  return 0;
}