X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fuxstore.c;h=15801785cbd93106d611a64aaf2a38aea77ba9d4;hb=510f49e405e71ba5c97875e7a019364e1ef5fac9;hp=e7b9c15897c4ea45bead1e498a32393b4516acc4;hpb=99fffd6ed357d25a228637be173e8187746b6b77;p=PuTTY.git diff --git a/unix/uxstore.c b/unix/uxstore.c index e7b9c158..15801785 100644 --- a/unix/uxstore.c +++ b/unix/uxstore.c @@ -98,17 +98,78 @@ static char *make_filename(int index, const char *subname) */ if (index == INDEX_DIR) { struct passwd *pwd; + char *xdg_dir, *old_dir, *old_dir2, *old_dir3, *home, *pwd_home; env = getenv("PUTTYDIR"); if (env) return dupstr(env); - env = getenv("HOME"); - if (env) - return dupprintf("%s/.putty", env); + + home = getenv("HOME"); pwd = getpwuid(getuid()); - if (pwd && pwd->pw_dir) - return dupprintf("%s/.putty", pwd->pw_dir); - return dupstr("/.putty"); + if (pwd && pwd->pw_dir) { + pwd_home = pwd->pw_dir; + } else { + pwd_home = NULL; + } + + xdg_dir = NULL; + env = getenv("XDG_CONFIG_HOME"); + if (env && *env) { + xdg_dir = dupprintf("%s/putty", env); + } + if (!xdg_dir) { + if (home) { + tmp = home; + } else if (pwd_home) { + tmp = pwd_home; + } else { + tmp = ""; + } + xdg_dir = dupprintf("%s/.config/putty", tmp); + } + if (xdg_dir && access(xdg_dir, F_OK) == 0) { + return xdg_dir; + } + + old_dir = old_dir2 = old_dir3 = NULL; + if (home) { + old_dir = dupprintf("%s/.putty", home); + } + if (pwd_home) { + old_dir2 = dupprintf("%s/.putty", pwd_home); + } + old_dir3 = dupstr("/.putty"); + + if (old_dir && access(old_dir, F_OK) == 0) { + ret = old_dir; + goto out; + } + if (old_dir2 && access(old_dir2, F_OK) == 0) { + ret = old_dir2; + goto out; + } + if (access(old_dir3, F_OK) == 0) { + ret = old_dir3; + goto out; + } +#ifdef XDG_DEFAULT + if (xdg_dir) { + ret = xdg_dir; + goto out; + } +#endif + ret = old_dir ? old_dir : (old_dir2 ? old_dir2 : old_dir3); + + out: + if (ret != old_dir) + sfree(old_dir); + if (ret != old_dir2) + sfree(old_dir2); + if (ret != old_dir3) + sfree(old_dir3); + if (ret != xdg_dir) + sfree(xdg_dir); + return ret; } if (index == INDEX_SESSIONDIR) { env = getenv("PUTTYSESSIONS"); @@ -159,32 +220,38 @@ static char *make_filename(int index, const char *subname) void *open_settings_w(const char *sessionname, char **errmsg) { - char *filename; + char *filename, *err; FILE *fp; *errmsg = NULL; /* * Start by making sure the .putty directory and its sessions - * subdir actually exist. Ignore error returns from mkdir since - * they're perfectly likely to be `already exists', and any - * other error will trip us up later on so there's no real need - * to catch it now. + * subdir actually exist. */ + filename = make_filename(INDEX_DIR, NULL); + if ((err = make_dir_path(filename, 0700)) != NULL) { + *errmsg = dupprintf("Unable to save session: %s", err); + sfree(err); + sfree(filename); + return NULL; + } + sfree(filename); + filename = make_filename(INDEX_SESSIONDIR, NULL); - if (mkdir(filename, 0700) != 0) { - char *filename2 = make_filename(INDEX_DIR, NULL); - mkdir(filename2, 0700); - sfree(filename2); - mkdir(filename, 0700); + if ((err = make_dir_path(filename, 0700)) != NULL) { + *errmsg = dupprintf("Unable to save session: %s", err); + sfree(err); + sfree(filename); + return NULL; } sfree(filename); filename = make_filename(INDEX_SESSION, sessionname); fp = fopen(filename, "w"); if (!fp) { - *errmsg = dupprintf("Unable to create %s: %s", - filename, strerror(errno)); + *errmsg = dupprintf("Unable to save session: open(\"%s\") " + "returned '%s'", filename, strerror(errno)); sfree(filename); return NULL; /* can't open */ } @@ -299,8 +366,10 @@ void *open_settings_r(const char *sessionname) char *value = strchr(line, '='); struct skeyval *kv; - if (!value) + if (!value) { + sfree(line); continue; + } *value++ = '\0'; value[strcspn(value, "\r\n")] = '\0'; /* trim trailing NL */ @@ -317,7 +386,7 @@ void *open_settings_r(const char *sessionname) return ret; } -char *read_setting_s(void *handle, const char *key, char *buffer, int buflen) +char *read_setting_s(void *handle, const char *key) { tree234 *tree = (tree234 *)handle; const char *val; @@ -333,11 +402,8 @@ char *read_setting_s(void *handle, const char *key, char *buffer, int buflen) if (!val) return NULL; - else { - strncpy(buffer, val, buflen); - buffer[buflen-1] = '\0'; - return buffer; - } + else + return dupstr(val); } int read_setting_i(void *handle, const char *key, int defvalue) @@ -360,7 +426,7 @@ int read_setting_i(void *handle, const char *key, int defvalue) return atoi(val); } -int read_setting_fontspec(void *handle, const char *name, FontSpec *result) +FontSpec *read_setting_fontspec(void *handle, const char *name) { /* * In GTK1-only PuTTY, we used to store font names simply as a @@ -375,29 +441,41 @@ int read_setting_fontspec(void *handle, const char *name, FontSpec *result) * ("FontName"). */ char *suffname = dupcat(name, "Name", NULL); - if (read_setting_s(handle, suffname, result->name, sizeof(result->name))) { + char *tmp; + + if ((tmp = read_setting_s(handle, suffname)) != NULL) { + FontSpec *fs = fontspec_new(tmp); sfree(suffname); - return TRUE; /* got new-style name */ + sfree(tmp); + return fs; /* got new-style name */ } sfree(suffname); /* Fall back to old-style name. */ - memcpy(result->name, "server:", 7); - if (!read_setting_s(handle, name, - result->name + 7, sizeof(result->name) - 7) || - !result->name[7]) { - result->name[0] = '\0'; - return FALSE; + tmp = read_setting_s(handle, name); + if (tmp && *tmp) { + char *tmp2 = dupcat("server:", tmp, NULL); + FontSpec *fs = fontspec_new(tmp2); + sfree(tmp2); + sfree(tmp); + return fs; } else { - return TRUE; + sfree(tmp); + return NULL; } } -int read_setting_filename(void *handle, const char *name, Filename *result) +Filename *read_setting_filename(void *handle, const char *name) { - return !!read_setting_s(handle, name, result->path, sizeof(result->path)); + char *tmp = read_setting_s(handle, name); + if (tmp) { + Filename *ret = filename_from_str(tmp); + sfree(tmp); + return ret; + } else + return NULL; } -void write_setting_fontspec(void *handle, const char *name, FontSpec result) +void write_setting_fontspec(void *handle, const char *name, FontSpec *fs) { /* * read_setting_fontspec had to handle two cases, but when @@ -405,12 +483,12 @@ void write_setting_fontspec(void *handle, const char *name, FontSpec result) * new-style name. */ char *suffname = dupcat(name, "Name", NULL); - write_setting_s(handle, suffname, result.name); + write_setting_s(handle, suffname, fs->name); sfree(suffname); } -void write_setting_filename(void *handle, const char *name, Filename result) +void write_setting_filename(void *handle, const char *name, Filename *result) { - write_setting_s(handle, name, result.path); + write_setting_s(handle, name, result->path); } void close_settings_r(void *handle) @@ -572,6 +650,16 @@ int verify_host_key(const char *hostname, int port, return ret; } +int have_ssh_host_key(const char *hostname, int port, + const char *keytype) +{ + /* + * If we have a host key, verify_host_key will return 0 or 2. + * If we don't have one, it'll return 1. + */ + return verify_host_key(hostname, port, keytype, "") != 1; +} + void store_host_key(const char *hostname, int port, const char *keytype, const char *key) { @@ -580,30 +668,38 @@ void store_host_key(const char *hostname, int port, int headerlen; char *filename, *tmpfilename; - newtext = dupprintf("%s@%d:%s %s\n", keytype, port, hostname, key); - headerlen = 1 + strcspn(newtext, " "); /* count the space too */ - /* * Open both the old file and a new file. */ tmpfilename = make_filename(INDEX_HOSTKEYS_TMP, NULL); wfp = fopen(tmpfilename, "w"); - if (!wfp) { - char *dir; + if (!wfp && errno == ENOENT) { + char *dir, *errmsg; dir = make_filename(INDEX_DIR, NULL); - mkdir(dir, 0700); + if ((errmsg = make_dir_path(dir, 0700)) != NULL) { + nonfatal("Unable to store host key: %s", errmsg); + sfree(errmsg); + sfree(dir); + sfree(tmpfilename); + return; + } sfree(dir); wfp = fopen(tmpfilename, "w"); } if (!wfp) { - sfree(tmpfilename); - return; + nonfatal("Unable to store host key: open(\"%s\") " + "returned '%s'", tmpfilename, strerror(errno)); + sfree(tmpfilename); + return; } filename = make_filename(INDEX_HOSTKEYS, NULL); rfp = fopen(filename, "r"); + newtext = dupprintf("%s@%d:%s %s\n", keytype, port, hostname, key); + headerlen = 1 + strcspn(newtext, " "); /* count the space too */ + /* * Copy all lines from the old file to the new one that _don't_ * involve the same host key identifier as the one we're adding. @@ -612,6 +708,7 @@ void store_host_key(const char *hostname, int port, while ( (line = fgetline(rfp)) ) { if (strncmp(line, newtext, headerlen)) fputs(line, wfp); + sfree(line); } fclose(rfp); } @@ -623,7 +720,11 @@ void store_host_key(const char *hostname, int port, fclose(wfp); - rename(tmpfilename, filename); + if (rename(tmpfilename, filename) < 0) { + nonfatal("Unable to store host key: rename(\"%s\",\"%s\")" + " returned '%s'", tmpfilename, filename, + strerror(errno)); + } sfree(tmpfilename); sfree(filename); @@ -660,18 +761,40 @@ void write_random_seed(void *data, int len) */ fd = open(fname, O_CREAT | O_WRONLY, 0600); if (fd < 0) { - char *dir; + if (errno != ENOENT) { + nonfatal("Unable to write random seed: open(\"%s\") " + "returned '%s'", fname, strerror(errno)); + sfree(fname); + return; + } + char *dir, *errmsg; dir = make_filename(INDEX_DIR, NULL); - mkdir(dir, 0700); + if ((errmsg = make_dir_path(dir, 0700)) != NULL) { + nonfatal("Unable to write random seed: %s", errmsg); + sfree(errmsg); + sfree(fname); + sfree(dir); + return; + } sfree(dir); fd = open(fname, O_CREAT | O_WRONLY, 0600); + if (fd < 0) { + nonfatal("Unable to write random seed: open(\"%s\") " + "returned '%s'", fname, strerror(errno)); + sfree(fname); + return; + } } while (len > 0) { int ret = write(fd, data, len); - if (ret <= 0) break; + if (ret < 0) { + nonfatal("Unable to write random seed: write " + "returned '%s'", strerror(errno)); + break; + } len -= ret; data = (char *)data + len; }