diff -u -r nano/src/files.c nano-hist/src/files.c --- nano/src/files.c 2004-08-07 17:27:37.000000000 -0400 +++ nano-hist/src/files.c 2004-08-09 17:55:26.000000000 -0400 @@ -1024,11 +1024,7 @@ /* first, get the current directory, and tack a slash onto the end of it, unless it turns out to be "/", in which case leave it alone */ -#ifdef PATH_MAX d_here = getcwd(NULL, PATH_MAX + 1); -#else - d_here = getcwd(NULL, 0); -#endif if (d_here != NULL) { @@ -1094,11 +1090,7 @@ free(d_there); -#ifdef PATH_MAX d_there = getcwd(NULL, PATH_MAX + 1); -#else - d_there = getcwd(NULL, 0); -#endif align(&d_there); if (d_there != NULL) { @@ -1845,8 +1837,7 @@ /* If we're using restricted mode, the filename isn't blank, * and we're at the "Write File" prompt, disable tab * completion. */ - i = statusq(!ISSET(RESTRICTED) || filename[0] == '\0' ? TRUE : - FALSE, writefile_list, + i = statusq(!ISSET(RESTRICTED) || filename[0] == '\0', writefile_list, #ifndef NANO_SMALL ans, NULL, "%s%s%s", _(msg), formatstr, backupstr #else @@ -2113,12 +2104,7 @@ } else { -#ifdef PATH_MAX if ((dirname = getcwd(NULL, PATH_MAX + 1)) == NULL) -#else - /* The better, but apparently segfault-causing way */ - if ((dirname = getcwd(NULL, 0)) == NULL) -#endif /* PATH_MAX */ return matches; else tmp = buf; @@ -2924,116 +2910,113 @@ } #endif /* !DISABLE_BROWSER */ -#ifndef NANO_SMALL -#ifdef ENABLE_NANORC -void load_history(void) +#if !defined(NANO_SMALL) && defined(ENABLE_NANORC) +/* Return $HOME/.nano_history, or NULL if we can't find the homedir. The + * string is dynamically allocated, and should be freed. */ +char *histfilename(void) { - FILE *hist; - const struct passwd *userage = NULL; - static char *nanohist; - char *buf, *ptr; - char *homenv = getenv("HOME"); - historyheadtype *history = &search_history; + static char *nanohist = NULL; + if (nanohist == NULL) { + const char *homenv = homedir(); - if (homenv != NULL) { - nanohist = charealloc(nanohist, strlen(homenv) + 15); - sprintf(nanohist, "%s/.nano_history", homenv); - } else { - userage = getpwuid(geteuid()); - endpwent(); - nanohist = charealloc(nanohist, strlen(userage->pw_dir) + 15); - sprintf(nanohist, "%s/.nano_history", userage->pw_dir); + if (homenv != NULL) { + size_t homelen = strlen(homenv); + + nanohist = charalloc(homelen + 15); + strcpy(nanohist, homenv); + strcpy(nanohist + homelen, "/.nano_history"); + } } + return nanohist; +} + +void load_history(void) +{ + char *nanohist = histfilename(); /* assume do_rcfile has reported missing home dir */ + if (nanohist != NULL) { + FILE *hist = fopen(nanohist, "r"); - if (homenv != NULL || userage != NULL) { - hist = fopen(nanohist, "r"); if (hist == NULL) { - if (errno != ENOENT) { + if (errno != ENOENT) { /* Don't save history when we quit. */ UNSET(HISTORYLOG); rcfile_error(N_("Unable to open ~/.nano_history file: %s\n"), strerror(errno)); } - free(nanohist); } else { - buf = charalloc(1024); - while (fgets(buf, 1023, hist) != 0) { - ptr = buf; - while (*ptr != '\n' && *ptr != '\0' && ptr < buf + 1023) - ptr++; - *ptr = '\0'; - if (strlen(buf)) - update_history(history, buf); - else + historyheadtype *history = &search_history; + char *line = NULL; + size_t buflen = 0; + ssize_t read; + + while ((read = getline(&line, &buflen, hist)) >= 0) { + if (read > 0 && line[read - 1] == '\n') { + read--; + line[read] = '\0'; + } + if (read > 0) { + unsunder(line, read); + update_history(history, line); + } else history = &replace_history; } + fclose(hist); - free(buf); - free(nanohist); + free(line); UNSET(HISTORY_CHANGED); } + free(nanohist); } } +bool writehist(FILE *hist, historyheadtype *histhead) +{ + historytype *h; + + /* write oldest first */ + for (h = histhead->tail; h->prev != NULL; h = h->prev) { + size_t len = strlen(h->data); + + sunder(h->data); + if (fwrite(h->data, sizeof(char), len, hist) < len || + putc('\n', hist) == EOF) { + rcfile_error(N_("Unable to write ~/.nano_history file: %s\n"), strerror(errno)); + return FALSE; + } + } + return TRUE; +} + /* save histories to ~/.nano_history */ void save_history(void) { - FILE *hist; - const struct passwd *userage = NULL; - char *nanohist = NULL; - char *homenv = getenv("HOME"); - historytype *h; + char *nanohist; /* don't save unchanged or empty histories */ if ((search_history.count == 0 && replace_history.count == 0) || !ISSET(HISTORY_CHANGED) || ISSET(VIEW_MODE)) return; - if (homenv != NULL) { - nanohist = charealloc(nanohist, strlen(homenv) + 15); - sprintf(nanohist, "%s/.nano_history", homenv); - } else { - userage = getpwuid(geteuid()); - endpwent(); - nanohist = charealloc(nanohist, strlen(userage->pw_dir) + 15); - sprintf(nanohist, "%s/.nano_history", userage->pw_dir); - } + nanohist = histfilename(); + + if (nanohist != NULL) { + FILE *hist = fopen(nanohist, "wb"); - if (homenv != NULL || userage != NULL) { - hist = fopen(nanohist, "wb"); if (hist == NULL) rcfile_error(N_("Unable to write ~/.nano_history file: %s\n"), strerror(errno)); else { /* set rw only by owner for security ?? */ chmod(nanohist, S_IRUSR | S_IWUSR); - /* write oldest first */ - for (h = search_history.tail; h->prev; h = h->prev) { - h->data = charealloc(h->data, strlen(h->data) + 2); - strcat(h->data, "\n"); - if (fputs(h->data, hist) == EOF) { - rcfile_error(N_("Unable to write ~/.nano_history file: %s\n"), strerror(errno)); - goto come_from; - } - } - if (fputs("\n", hist) == EOF) { - rcfile_error(N_("Unable to write ~/.nano_history file: %s\n"), strerror(errno)); - goto come_from; - } - for (h = replace_history.tail; h->prev; h = h->prev) { - h->data = charealloc(h->data, strlen(h->data) + 2); - strcat(h->data, "\n"); - if (fputs(h->data, hist) == EOF) { - rcfile_error(N_("Unable to write ~/.nano_history file: %s\n"), strerror(errno)); - goto come_from; - } - } - come_from: + + if (!writehist(hist, &search_history) || + putc('\n', hist) == EOF || + !writehist(hist, &replace_history)) + rcfile_error(N_("Unable to write ~/.nano_history file: %s\n"), strerror(errno)); fclose(hist); } free(nanohist); } } -#endif /* ENABLE_NANORC */ -#endif /* !NANO_SMALL */ +#endif /* !NANO_SMALL && ENABLE_NANORC */ diff -u -r nano/src/proto.h nano-hist/src/proto.h --- nano/src/proto.h 2004-08-07 17:27:37.000000000 -0400 +++ nano-hist/src/proto.h 2004-08-09 17:53:17.000000000 -0400 @@ -223,6 +223,13 @@ char *do_browser(const char *inpath); char *do_browse_from(const char *inpath); #endif +#if !defined(NANO_SMALL) && defined(ENABLE_NANORC) +char *histfilename(void); +void load_history(void); +bool writehist(FILE *hist, historyheadtype *histhead); +void save_history(void); +#endif + /* Public functions in global.c */ size_t length_of_list(const shortcut *s); @@ -409,21 +416,22 @@ void do_find_bracket(void); #ifndef NANO_SMALL void history_init(void); -historytype *find_node(historytype *h, char *s); +historytype *find_node(historytype *h, const char *s); void remove_node(historytype *r); void insert_node(historytype *h, const char *s); -void update_history(historyheadtype *h, char *s); +void update_history(historyheadtype *h, const char *s); char *get_history_older(historyheadtype *h); char *get_history_newer(historyheadtype *h); char *get_history_completion(historyheadtype *h, char *s); +#ifdef DEBUG void free_history(historyheadtype *h); -#ifdef ENABLE_NANORC -void load_history(void); -void save_history(void); #endif #endif /* Public functions in utils.c */ +#ifdef ENABLE_NANORC +const char *homedir(void); +#endif #ifdef HAVE_REGEX_H #ifdef BROKEN_REGEXEC int regexec_safe(const regex_t *preg, const char *string, size_t nmatch, diff -u -r nano/src/rcfile.c nano-hist/src/rcfile.c --- nano/src/rcfile.c 2004-08-04 14:24:53.000000000 -0400 +++ nano-hist/src/rcfile.c 2004-08-09 17:53:43.000000000 -0400 @@ -646,16 +646,14 @@ void do_rcfile(void) { FILE *rcstream; - const struct passwd *userage; - uid_t euid = geteuid(); - char *homenv = getenv("HOME"); + const char *homenv; #ifdef SYSCONFDIR assert(sizeof(SYSCONFDIR) == strlen(SYSCONFDIR) + 1); - nanorc = charalloc(sizeof(SYSCONFDIR) + 7); - sprintf(nanorc, "%s/nanorc", SYSCONFDIR); + nanorc = SYSCONFDIR "/nanorc"; /* Try to open system nanorc */ - if ((rcstream = fopen(nanorc, "r")) != NULL) { + rcstream = fopen(nanorc, "r"); + if (rcstream != NULL) { /* Parse it! */ parse_rcfile(rcstream); fclose(rcstream); @@ -664,33 +662,25 @@ lineno = 0; - /* Rely on $HOME, fall back on getpwuid() */ - if (homenv != NULL) { - nanorc = charealloc(nanorc, strlen(homenv) + 10); - sprintf(nanorc, "%s/.nanorc", homenv); + homenv = homedir(); + if (homenv == NULL) { + rcfile_error(N_("I can't find my home directory! Wah!\n")); + SET(NO_RCFILE); } else { - userage = getpwuid(euid); - endpwent(); + size_t homelen = strlen(homenv); - if (userage == NULL) { - rcfile_error(N_("I can't find my home directory! Wah!\n")); - SET(NO_RCFILE); - } else { - nanorc = charealloc(nanorc, strlen(userage->pw_dir) + 9); - sprintf(nanorc, "%s/.nanorc", userage->pw_dir); - - } - } - - if (!ISSET(NO_RCFILE)) { + nanorc = charalloc(homelen + 9); + strcpy(nanorc, homenv); + strcpy(nanorc + homelen, "/.nanorc"); #if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING) /* If we've already read SYSCONFDIR/nanorc (if it's there), we're root, and --disable-wrapping-as-root is used, turn wrapping off */ - if (euid == NANO_ROOT_UID) + if (geteuid() == NANO_ROOT_UID) SET(NO_WRAP); #endif - if ((rcstream = fopen(nanorc, "r")) == NULL) { + rcstream = fopen(nanorc, "r"); + if (rcstream == NULL) { /* Don't complain about the file not existing */ if (errno != ENOENT) { rcfile_error(N_("Unable to open ~/.nanorc file: %s\n"), strerror(errno)); @@ -700,10 +690,9 @@ parse_rcfile(rcstream); fclose(rcstream); } + free(nanorc); } - lineno = 0; - free(nanorc); #ifdef ENABLE_COLOR set_colorpairs(); #endif diff -u -r nano/src/search.c nano-hist/src/search.c --- nano/src/search.c 2004-08-04 14:24:53.000000000 -0400 +++ nano-hist/src/search.c 2004-08-09 17:53:17.000000000 -0400 @@ -1006,7 +1006,7 @@ } /* find first node containing string *s in history list *h */ -historytype *find_node(historytype *h, char *s) +historytype *find_node(historytype *h, const char *s) { for (; h->next != NULL; h = h->next) if (strcmp(s, h->data) == 0) @@ -1030,14 +1030,14 @@ a = (historytype *)nmalloc(sizeof(historytype)); a->next = h->next; - a->prev = h->next->prev; + a->prev = h; h->next->prev = a; h->next = a; a->data = mallocstrcpy(NULL, s); } /* update history list */ -void update_history(historyheadtype *h, char *s) +void update_history(historyheadtype *h, const char *s) { historytype *p; @@ -1095,14 +1095,16 @@ return s; } +#ifdef DEBUG /* free a history list */ void free_history(historyheadtype *h) { - historytype *p, *n; + historytype *p; - for (p = h->next; (n = p->next); p = n) + for (p = h->next; p->next != NULL; p = p->next) remove_node(p); } +#endif /* end of history support functions */ #endif /* !NANO_SMALL */ diff -u -r nano/src/utils.c nano-hist/src/utils.c --- nano/src/utils.c 2004-08-04 14:24:53.000000000 -0400 +++ nano-hist/src/utils.c 2004-08-09 17:53:17.000000000 -0400 @@ -28,9 +28,30 @@ #include #include #include +#include #include "proto.h" #include "nano.h" + +#ifdef ENABLE_NANORC +/* Return the home directory, $HOME or from /etc/passwd. + * Don't free this string! This string might not be valid after another + * call to getpwent, getpwnam, or getpwuid! */ +const char *homedir(void) +{ + const char *homenv = getenv("HOME"); + + /* Rely on $HOME, fall back on getpwuid() */ + if (homenv == NULL) { + const struct passwd *userage = getpwuid(geteuid()); + + if (userage != NULL) + homenv = userage->pw_dir; + } + return homenv; +} +#endif + #ifdef HAVE_REGEX_H #ifdef BROKEN_REGEXEC #undef regexec @@ -167,10 +188,8 @@ if (n > 0) return (tolower(*s1) - tolower(*s2)); - else if (n == 0) - return 0; else - return -1; + return 0; } #endif