fprintf(stderr, "Usage: updater <dir-path> <parent-pid> [callback args...]\n");
fprintf(stderr, "Usage: updater <dir-path> <parent-pid> [working-dir callback args...]\n");
int main(int argc, char **argv){  InitProgressUI(&argc, &argv);  // The updater command line consists of the directory path containing the  // updater.mar file to process followed by the PID of the calling process.  // The updater will wait on the parent process to exit if the PID is non-  // zero.  This is leveraged on platforms such as Windows where it is  // necessary for the parent process to exit before its executable image may  // be altered.  if (argc < 3) {    fprintf(stderr, "Usage: updater <dir-path> <parent-pid> [callback args...]\n");    return 1;  }  int pid = atoi(argv[2]);  if (pid) {#ifdef XP_WIN    HANDLE parent = OpenProcess(SYNCHRONIZE, FALSE, (DWORD) pid);    // May return NULL if the parent process has already gone away.    // Otherwise, wait for the parent process to exit before starting the    // update.    if (parent) {      DWORD result = WaitForSingleObject(parent, 5000);      CloseHandle(parent);      if (result != WAIT_OBJECT_0)        return 1;      // The process may be signaled before it releases the executable image.      // This is a terrible hack, but it'll have to do for now :-(      Sleep(50);    }#else    int status;    waitpid(pid, &status, 0);#endif  }  gSourcePath = argv[1];  LogInit();  // Run update process on a background thread.  ShowProgressUI may return  // before QuitProgressUI has been called, so wait for UpdateThreadFunc to  // terminate.  Thread t;  if (t.Run(UpdateThreadFunc, NULL) == 0)    ShowProgressUI();  t.Join();  LogFinish();  // The callback to execute is given as the last N arguments of our command  // line.  if (argc > 3)    LaunchCallbackApp(argc - 3, argv + 3);  return 0;}