int mkdir_p(const char *dir) { char *p = NULL, *path = NULL; path = p = strdup(dir); do { p = strchr(p + 1, '/'); if (p) *p = '\0'; if (can_stat(path) && !is_dir(path)) unlink(path); if (!can_stat(path)) { if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR)) { unlink(path); mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR); } } if (p) *p = '/'; } while(p); int couldStat = can_stat(path); free(path); return couldStat; }
static bool check_tempdir(bool do_mod) { mkdir_p(tempdir); if (!can_stat(tempdir)) return 0; if (do_mod && fixmod(tempdir)) return 0; /* test tempdir: it's vital */ Tempfile *testdir = new Tempfile("test"); /* There was an error creating a file in this directory, return to move on in list of dirs */ if (!testdir || testdir->error) { if (testdir) delete testdir; return 0; } fprintf(testdir->f, "\n"); int result = fflush(testdir->f); delete testdir; if (result) { sdprintf("%s: %s", tempdir, strerror(errno)); return 0; } return 1; }
char *move_bin(const char *ipath, const char *file, bool run) { char *path = strdup(ipath); expand_tilde(&path); /* move the binary to the correct place */ static char newbin[DIRMAX] = ""; char real[DIRMAX] = ""; simple_snprintf(newbin, sizeof newbin, "%s%s%s", path, path[strlen(path) - 1] == '/' ? "" : "/", file); ContextNote(STR("realpath()")); realpath(binname, real); /* get the realpath of binname */ ContextNote(STR("realpath(): Success")); /* running from wrong dir, or wrong bin name.. lets try to fix that :) */ sdprintf(STR("binname: %s"), binname); sdprintf(STR("newbin: %s"), newbin); sdprintf(STR("real: %s"), real); if (strcmp(binname, newbin) && strcmp(newbin, real)) { /* if wrong path and new path != current */ bool ok = 1; sdprintf(STR("wrong dir, is: %s :: %s"), binname, newbin); unlink(newbin); if (copyfile(binname, newbin)) ok = 0; if (ok && !can_stat(newbin)) { unlink(newbin); ok = 0; } if (ok && fixmod(newbin)) { unlink(newbin); ok = 0; } if (ok) { sdprintf(STR("Binary successfully moved to: %s"), newbin); unlink(binname); if (run) { simple_snprintf(newbin, sizeof newbin, "%s%s%s", path, path[strlen(path) - 1] == '/' ? "" : "/", shell_escape(file)); system(newbin); sdprintf(STR("exiting to let new binary run...")); exit(0); } } else { if (run) werr(ERR_WRONGBINDIR); sdprintf(STR("Binary move failed to: %s"), newbin); return binname; } } return newbin; }
void check_mypid() { pid_t pid = 0; if (can_stat(conf.bot->pid_file)) pid = checkpid(conf.bot->nick, NULL); if (pid && (pid != getpid())) fatal(STR("getpid() does not match pid in file. Possible cloned process, exiting.."), 0); }
int fixmod(const char *s) { if (!can_stat(s)) return 1; return chmod(s, S_IRUSR | S_IWUSR | S_IXUSR); }
int updatebin(int idx, char *par, int secs) { if (!par || !par[0]) { logidx(idx, "Not enough parameters."); return 1; } size_t path_siz = strlen(binname) + strlen(par) + 2; char *path = (char *) my_calloc(1, path_siz); char *newbin = NULL, buf[DIRMAX] = ""; const char* argv[5]; int i; strlcpy(path, binname, path_siz); newbin = strrchr(path, '/'); if (!newbin) { free(path); logidx(idx, STR("Don't know current binary name")); return 1; } newbin++; if (strchr(par, '/')) { *newbin = 0; logidx(idx, STR("New binary must be in %s and name must be specified without path information"), path); free(path); return 1; } strcpy(newbin, par); if (!strcmp(path, binname)) { free(path); logidx(idx, STR("Can't update with the current binary")); return 1; } if (!can_stat(path)) { logidx(idx, STR("%s can't be accessed"), path); free(path); return 1; } if (fixmod(path)) { logidx(idx, STR("Can't set mode 0600 on %s"), path); free(path); return 1; } /* Check if the new binary is compatible */ int initialized_code = check_bin_initialized(path); if (initialized_code == 2) { logidx(idx, STR("New binary is corrupted or the wrong architecture/operating system.")); free(path); return 1; } else if (initialized_code == 1 && !check_bin_compat(path)) { logidx(idx, STR("New binary must be initialized as pack structure has been changed in new version.")); free(path); return 1; } /* make a backup just in case. */ simple_snprintf(buf, sizeof(buf), STR("%s/.bin.old"), conf.datadir); copyfile(binname, buf); write_settings(path, -1, 0, initialized_code ? 0 : 1); /* re-write the binary with our packdata */ Tempfile *conffile = new Tempfile("conf"); if (writeconf(NULL, conffile->fd, CONF_ENC)) { logidx(idx, STR("Failed to write temporary config file for update.")); delete conffile; return 1; } /* The binary should return '2' when ran with -2, if not it's probably corrupt. */ putlog(LOG_DEBUG, "*", STR("Running for update binary test: %s -2"), path); argv[0] = path; argv[1] = "-2"; argv[2] = 0; i = simple_exec(argv); if (i == -1 || WEXITSTATUS(i) != 2) { logidx(idx, STR("Couldn't restart new binary (error %d)"), i); delete conffile; return i; } /* now to send our config to the new binary */ putlog(LOG_DEBUG, "*", STR("Running for update conf: %s -4 %s"), path, conffile->file); argv[0] = path; argv[1] = "-4"; argv[2] = conffile->file; argv[3] = 0; i = simple_exec(argv); delete conffile; if (i == -1 || WEXITSTATUS(i) != 6) { /* 6 for successfull config read/write */ logidx(idx, STR("Couldn't pass config to new binary (error %d)"), i); return i; } if (movefile(path, binname)) { logidx(idx, STR("Can't rename %s to %s"), path, binname); free(path); return 1; } if (updating == UPDATE_EXIT) { /* dont restart/kill/spawn bots, just die ! */ printf(STR("* Moved binary to: %s\n"), binname); fatal(STR("Binary updated."), 0); } if (updating == UPDATE_AUTO) { /* Make all other bots do a soft restart */ conf_checkpids(conf.bots); conf_killbot(conf.bots, NULL, NULL, SIGHUP); if (conf.bot->pid) kill(conf.bot->pid, SIGHUP); exit(0); } if (!conf.bot->hub && secs > 0) { /* Make all other bots do a soft restart */ conf_checkpids(conf.bots); conf_killbot(conf.bots, NULL, NULL, SIGHUP); /* invoked with -u */ if (updating == UPDATE_AUTO) { if (conf.bot->pid) kill(conf.bot->pid, SIGHUP); exit(0); } /* this odd statement makes it so specifying 1 sec will restart other bots running * and then just restart with no delay */ updating = UPDATE_AUTO; if (secs > 1) { egg_timeval_t howlong; howlong.sec = secs; howlong.usec = 0; timer_create_complex(&howlong, STR("restarting for update"), (Function) restart, (void *) (long) idx, 0); } else restart(idx); return 0; } else restart(idx); /* no timer */ /* this should never be reached */ return 2; }