From e21adfa181d6413a2f0ca2c6f90b1c45005136e2 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Fri, 13 Sep 2002 18:14:04 +0000 Subject: [PATCH] David Benbennick's minor fixes, plus one of mine git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1275 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- ChangeLog | 30 ++- files.c | 561 ++++++++++++++++++++++++------------------------------ global.c | 12 +- nano.c | 57 +++--- nano.h | 3 +- proto.h | 22 +-- rcfile.c | 9 +- search.c | 2 +- utils.c | 11 +- winio.c | 9 +- 10 files changed, 330 insertions(+), 386 deletions(-) diff --git a/ChangeLog b/ChangeLog index a6484205..234cef54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,15 @@ CVS code - some functions around to put similar functions closer together (for this, rename clear_bottombars() to blank_bottombars()). (DLR; suggested by David Benbennick) + - More changes of char *'s to const char *'s when possible. + (David Benbennick) + - Fix various minor memory leaks in files.c. (David Benbennick) + - Fix minor problems with the operating directory code: set the + operating directory properly if it's specified only in a + nanorc file, and handle an operating directory of "/" + properly. New function init_operating_dir() to handle + setting it both on the command line and in the nanorc file. + (David Benbennick) - configure.ac: - Added pt_BR to ALL_LINGUAS (Jordi). - Changed --enable-color warning to be slightly less severe. @@ -28,10 +37,9 @@ CVS code - - Disallow multibuffer toggling at the "Insert File" prompt if we're in both view and multibuffer mode, so as to keep proper integration between the two, and make sure the toggle - actually works all the time otherwise. Also, use - NANO_LOAD_KEY as an alias for TOGGLE_LOAD_KEY, so - --enable-tiny and --enable-multibuffer can be used together - again. (DLR) + actually works all the time otherwise. Also, make sure + TOGGLE_LOAD_KEY isn't referenced when NANO_SMALL and + ENABLE_MULTIBUFFER are both defined. (DLR) open_prevfile_void(), open_nextfile_void() - Return the return values of open_prevfile() and open_nextfile(), respectively, instead of (incorrectly) @@ -45,9 +53,9 @@ CVS code - username and the string already contains data. (DLR) - global.c: shortcut_init() - - Use NANO_LOAD_KEY as an alias for TOGGLE_LOAD_KEY, so - --enable-tiny and --enable-multibuffer can be used together - again. (DLR) + - Disable the new multibuffer toggle at the file insertion + prompt when NANO_SMALL and ENABLE_MULTIBUFFER are both + defined. (DLR) thanks_for_all_the_fish() - Make sure the reference to help_text is #ifdefed out when --disable-help is used. (DLR) @@ -92,7 +100,9 @@ CVS code - Benbennick) do_justify() - Fix cosmetic problems caused when justifying on the - magicline. (David Benbennick) + magicline, and a minor problem where the cursor would + sometimes be moved to the wrong line after justification. + (David Benbennick) main() - When searching through the main shortcut list looking for a shortcut key, stop searching after finding one; this avoids a @@ -104,6 +114,10 @@ CVS code - - nanorc.sample: - Fix the c-file regex for all caps words to be extended regex format ({} instead of \{\}) (found by DLR). +- utils.c: + charalloc() + - Switch from using calloc() to using malloc(). (David + Benbennick) - faq.html: - Typo fix. (DLR) - TODO: diff --git a/files.c b/files.c index 7dff3ba9..a615a713 100644 --- a/files.c +++ b/files.c @@ -489,16 +489,16 @@ int do_insertfile(int loading_file) } #endif +#ifndef NANO_SMALL #ifdef ENABLE_MULTIBUFFER - if (i == NANO_LOAD_KEY) { + if (i == TOGGLE_LOAD_KEY) { /* don't allow toggling if we're in both view mode and multibuffer mode now */ if (!ISSET(VIEW_MODE) || !ISSET(MULTIBUFFER)) TOGGLE(MULTIBUFFER); return do_insertfile(ISSET(MULTIBUFFER)); } -#endif -#ifndef NANO_SMALL +#endif /* ENABLE_MULTIBUFFER */ if (i == NANO_EXTCMD_KEY) { int ts; ts = statusq(1, extcmd_list, "", _("Command to execute ")); @@ -509,7 +509,7 @@ int do_insertfile(int loading_file) return 0; } } -#endif +#endif /* !NANO_SMALL */ #ifdef ENABLE_MULTIBUFFER if (loading_file) { @@ -1000,7 +1000,7 @@ int close_open_file(void) * yet on disk); it is not done if the relative path doesn't exist (since * the first call to chdir() will fail then). */ -char *get_full_path(char *origpath) +char *get_full_path(const char *origpath) { char *newpath = NULL, *last_slash, *d_here, *d_there, *d_there_file, tmp; int path_only, last_slash_index; @@ -1136,7 +1136,7 @@ char *get_full_path(char *origpath) * get_full_path()). On error, if the path doesn't reference a * directory, or if the directory isn't writable, it returns NULL. */ -char *check_writable_directory(char *path) +char *check_writable_directory(const char *path) { char *full_path = get_full_path(path); int writable; @@ -1177,49 +1177,27 @@ char *check_writable_directory(char *path) */ char *safe_tempnam(const char *dirname, const char *filename_prefix) { - char *buf, *tempdir = NULL, *full_tempdir = NULL; + char *full_tempdir = NULL; + const char *TMPDIR_env; int filedesc; - /* if $TMPDIR is set and non-empty, set tempdir to it, run it through - get_full_path(), and save the result in full_tempdir; otherwise, - leave full_tempdir set to to NULL */ - if (getenv("TMPDIR") && strcmp(getenv("TMPDIR"),"")) { + /* if $TMPDIR is set and non-empty, set tempdir to it, run it through + get_full_path(), and save the result in full_tempdir; otherwise, + leave full_tempdir set to to NULL */ + TMPDIR_env = getenv("TMPDIR"); + if (TMPDIR_env && TMPDIR_env[0] != '\0') + full_tempdir = check_writable_directory(TMPDIR_env); - /* store the value of $TMPDIR in tempdir, run its value through - get_full_path(), and save the result in full_tempdir */ - tempdir = charalloc(strlen(getenv("TMPDIR")) + 1); - sprintf(tempdir, "%s", getenv("TMPDIR")); - full_tempdir = check_writable_directory(tempdir); - - /* we don't need the value of tempdir anymore */ - free(tempdir); - } - - if (!full_tempdir) { - - /* if $TMPDIR is blank or isn't set, or isn't a writable - directory, and dirname isn't NULL, try it; otherwise, leave - full_tempdir set to NULL */ - if (dirname) { - tempdir = charalloc(strlen(dirname) + 1); - strcpy(tempdir, dirname); - full_tempdir = check_writable_directory(tempdir); - - /* we don't need the value of tempdir anymore */ - free(tempdir); - } - } + /* if $TMPDIR is blank or isn't set, or isn't a writable + directory, and dirname isn't NULL, try it; otherwise, leave + full_tempdir set to NULL */ + if (!full_tempdir && dirname) + full_tempdir = check_writable_directory(dirname); /* if $TMPDIR is blank or isn't set, or if it isn't a writable directory, and dirname is NULL, try P_tmpdir instead */ - if (!full_tempdir) { - tempdir = charalloc(strlen(P_tmpdir) + 1); - strcpy(tempdir, P_tmpdir); - full_tempdir = check_writable_directory(tempdir); - - /* we don't need the value of tempdir anymore */ - free(tempdir); - } + if (!full_tempdir) + full_tempdir = check_writable_directory(P_tmpdir); /* if P_tmpdir didn't work, use /tmp instead */ if (!full_tempdir) { @@ -1227,84 +1205,68 @@ char *safe_tempnam(const char *dirname, const char *filename_prefix) strcpy(full_tempdir, "/tmp/"); } - buf = charalloc(strlen(full_tempdir) + 12); - sprintf(buf, "%s", full_tempdir); + full_tempdir = nrealloc(full_tempdir, strlen(full_tempdir) + 12); /* like tempnam(), use only the first 5 characters of the prefix */ - strncat(buf, filename_prefix, 5); + strncat(full_tempdir, filename_prefix, 5); + strcat(full_tempdir, "XXXXXX"); + filedesc = mkstemp(full_tempdir); - strcat(buf, "XXXXXX"); - filedesc = mkstemp(buf); - - /* if mkstemp() failed, get out */ - if (filedesc == -1) - return NULL; - - /* otherwise, close the resulting file; afterwards, it'll be 0 bytes - long, so delete it; finally, return the filename (all that's left - of it) */ - else { + /* if mkstemp succeeded, close the resulting file; afterwards, it'll be + 0 bytes long, so delete it; finally, return the filename (all that's + left of it) */ + if (filedesc != -1) { close(filedesc); - unlink(buf); - return buf; + unlink(full_tempdir); + return full_tempdir; } + + free(full_tempdir); + return NULL; } #endif /* !DISABLE_SPELLER */ #ifndef DISABLE_OPERATINGDIR +/* Initialize full_operating_dir based on operating_dir. */ +void init_operating_dir(void) +{ + assert(full_operating_dir == NULL); + + if (!operating_dir) + return; + full_operating_dir = get_full_path(operating_dir); + + /* If get_full_path() failed or the operating directory is + inaccessible, unset operating_dir. */ + if (!full_operating_dir || chdir(full_operating_dir) == -1) { + free(full_operating_dir); + full_operating_dir = NULL; + free(operating_dir); + operating_dir = NULL; + } +} + /* * Check to see if we're inside the operating directory. Return 0 if we * are, or 1 otherwise. If allow_tabcomp is nonzero, allow incomplete * names that would be matches for the operating directory, so that tab * completion will work. */ -int check_operating_dir(char *currpath, int allow_tabcomp) +int check_operating_dir(const char *currpath, int allow_tabcomp) { /* The char *full_operating_dir is global for mem cleanup, and therefore we only need to get it the first time this function is called; also, a relative operating directory path will only be handled properly if this is done */ - char *fullpath, *whereami1, *whereami2 = NULL; + char *fullpath; + int retval = 0; + const char *whereami1, *whereami2 = NULL; /* if no operating directory is set, don't bother doing anything */ if (!operating_dir) return 0; - /* if the operating directory is "/", that's the same as having no - operating directory, so discard it and get out */ - if (!strcmp(operating_dir, "/")) { - free(operating_dir); - operating_dir = NULL; - return 0; - } - - /* get the full operating (if we don't have it already) and current - directories, and then search the current for the operating (for - normal usage) and the operating for the current (for tab - completion, if we're allowing it); if the current directory's path - doesn't exist, assume we're outside the operating directory */ - if (!full_operating_dir) { - full_operating_dir = get_full_path(operating_dir); - - /* if get_full_path() failed, discard the operating directory */ - if (!full_operating_dir) { - free(operating_dir); - operating_dir = NULL; - return 0; - } - - /* if the full operating directory is "/", that's the same as - having no operating directory, so discard it and get out */ - if (!strcmp(full_operating_dir, "/")) { - free(full_operating_dir); - full_operating_dir = NULL; - free(operating_dir); - operating_dir = NULL; - return 0; - } - } - fullpath = get_full_path(currpath); if (!fullpath) return 1; @@ -1314,18 +1276,16 @@ int check_operating_dir(char *currpath, int allow_tabcomp) whereami2 = strstr(full_operating_dir, fullpath); /* if both searches failed, we're outside the operating directory */ - if (!whereami1 && !whereami2) - return 1; - + /* otherwise */ /* check the search results; if the full operating directory path is not at the beginning of the full current path (for normal usage) and vice versa (for tab completion, if we're allowing it), we're outside the operating directory */ if (whereami1 != fullpath && whereami2 != full_operating_dir) - return 1; - + retval = 1; + free(fullpath); /* otherwise, we're still inside it */ - return 0; + return retval; } #endif @@ -1343,11 +1303,14 @@ int check_operating_dir(char *currpath, int allow_tabcomp) * nonamechange means don't change the current filename, it is ignored * if tmp == 1 or if we're appending/prepending. */ -int write_file(char *name, int tmp, int append, int nonamechange) +int write_file(const char *name, int tmp, int append, int nonamechange) { + int retval = -1; + /* Instead of returning in this function, you should always + * merely set retval then goto cleanup_and_exit. */ long size, lineswritten = 0; char *buf = NULL; - filestruct *fileptr; + const filestruct *fileptr; FILE *f; int fd; int mask = 0, realexists, anyexists; @@ -1361,12 +1324,6 @@ int write_file(char *name, int tmp, int append, int nonamechange) titlebar(NULL); fileptr = fileage; - if (realname != NULL) - free(realname); - - if (buf != NULL) - free(buf); - #ifndef DISABLE_TABCOMP realname = real_dir_from_tilde(name); #else @@ -1374,19 +1331,16 @@ int write_file(char *name, int tmp, int append, int nonamechange) #endif #ifndef DISABLE_OPERATINGDIR - if (!tmp && operating_dir) { - /* if we're writing a temporary file, we're probably going - outside the operating directory, so skip the operating - directory test */ - if (check_operating_dir(realname, 0)) { - statusbar(_("Can't write outside of %s"), operating_dir); - - return -1; - } + /* If we're writing a temporary file, we're probably going outside + the operating directory, so skip the operating directory test. */ + if (!tmp && operating_dir && check_operating_dir(realname, 0)) { + statusbar(_("Can't write outside of %s"), operating_dir); + goto cleanup_and_exit; } #endif - /* Save the state of file at the end of the symlink (if there is one) */ + /* Save the state of file at the end of the symlink (if there is + one). */ realexists = stat(realname, &st); #ifndef NANO_SMALL @@ -1463,7 +1417,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) /* New case: if the file exists, just give up */ if (tmp && anyexists != -1) - return -1; + goto cleanup_and_exit; /* NOTE: If you change this statement, you MUST CHANGE the if statement below (that says: if (realexists == -1 || tmp || (!ISSET(FOLLOW_SYMLINKS) && @@ -1484,11 +1438,11 @@ int write_file(char *name, int tmp, int append, int nonamechange) if (fd == -1) { if (!tmp && ISSET(TEMP_OPT)) { UNSET(TEMP_OPT); - return do_writeout(filename, 1, 0); - } - statusbar(_("Could not open file for writing: %s"), - strerror(errno)); - return -1; + retval = do_writeout(filename, 1, 0); + } else + statusbar(_("Could not open file for writing: %s"), + strerror(errno)); + goto cleanup_and_exit; } } @@ -1500,11 +1454,11 @@ int write_file(char *name, int tmp, int append, int nonamechange) if ((fd = mkstemp(buf)) == -1) { if (ISSET(TEMP_OPT)) { UNSET(TEMP_OPT); - return do_writeout(filename, 1, 0); - } - statusbar(_("Could not open file for writing: %s"), - strerror(errno)); - return -1; + retval = do_writeout(filename, 1, 0); + } else + statusbar(_("Could not open file for writing: %s"), + strerror(errno)); + goto cleanup_and_exit; } } @@ -1514,13 +1468,13 @@ int write_file(char *name, int tmp, int append, int nonamechange) f = fdopen(fd, append == 1 ? "ab" : "wb"); if (!f) { - statusbar(_("Could not open file for writing: %s"), - strerror(errno)); - return -1; + statusbar(_("Could not open file for writing: %s"), strerror(errno)); + goto cleanup_and_exit; } while (fileptr != NULL && fileptr->next != NULL) { int data_len; + /* Next line is so we discount the "magic line" */ if (filebot == fileptr && fileptr->data[0] == '\0') break; @@ -1539,7 +1493,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) statusbar(_("Could not open file for writing: %s"), strerror(errno)); fclose(f); - return -1; + goto cleanup_and_exit; } #ifdef DEBUG else @@ -1558,9 +1512,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) } if (fileptr != NULL) { - int data_len; - - data_len = strlen(fileptr->data); + int data_len = strlen(fileptr->data); /* newlines to nulls, just before we write to disk */ sunder(fileptr->data); @@ -1573,7 +1525,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) if (size < data_len) { statusbar(_("Could not open file for writing: %s"), strerror(errno)); - return -1; + goto cleanup_and_exit; } else if (data_len > 0) { #ifndef NANO_SMALL if (ISSET(DOS_FILE) || ISSET(MAC_FILE)) { @@ -1581,7 +1533,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) statusbar(_("Could not open file for writing: %s"), strerror(errno)); fclose(f); - return -1; + goto cleanup_and_exit; } lineswritten++; } @@ -1593,7 +1545,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) statusbar(_("Could not open file for writing: %s"), strerror(errno)); fclose(f); - return -1; + goto cleanup_and_exit; } lineswritten++; } @@ -1603,7 +1555,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) if (fclose(f)) { statusbar(_("Could not close %s: %s"), realname, strerror(errno)); unlink(buf); - return -1; + goto cleanup_and_exit; } /* if we're prepending, open the real file, and append it here */ @@ -1614,25 +1566,25 @@ int write_file(char *name, int tmp, int append, int nonamechange) if ((fd_dest = open(buf, O_WRONLY | O_APPEND, (S_IRUSR|S_IWUSR))) == -1) { statusbar(_("Could not reopen %s: %s"), buf, strerror(errno)); - return -1; + goto cleanup_and_exit; } f_dest = fdopen(fd_dest, "wb"); if (!f_dest) { statusbar(_("Could not reopen %s: %s"), buf, strerror(errno)); close(fd_dest); - return -1; + goto cleanup_and_exit; } if ((fd_source = open(realname, O_RDONLY | O_CREAT)) == -1) { statusbar(_("Could not open %s for prepend: %s"), realname, strerror(errno)); fclose(f_dest); - return -1; + goto cleanup_and_exit; } f_source = fdopen(fd_source, "rb"); if (!f_source) { statusbar(_("Could not open %s for prepend: %s"), realname, strerror(errno)); fclose(f_dest); close(fd_source); - return -1; + goto cleanup_and_exit; } /* Doing this in blocks is an exercise left to some other reader. */ @@ -1641,7 +1593,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) statusbar(_("Could not open %s for prepend: %s"), realname, strerror(errno)); fclose(f_source); fclose(f_dest); - return -1; + goto cleanup_and_exit; } } @@ -1649,7 +1601,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) statusbar(_("Could not reopen %s: %s"), buf, strerror(errno)); fclose(f_source); fclose(f_dest); - return -1; + goto cleanup_and_exit; } fclose(f_source); @@ -1678,7 +1630,7 @@ int write_file(char *name, int tmp, int append, int nonamechange) statusbar(_("Could not open %s for writing: %s"), realname, strerror(errno)); unlink(buf); - return -1; + goto cleanup_and_exit; } } if (link(buf, realname) != -1) @@ -1687,12 +1639,12 @@ int write_file(char *name, int tmp, int append, int nonamechange) statusbar(_("Could not open %s for writing: %s"), name, strerror(errno)); unlink(buf); - return -1; + goto cleanup_and_exit; } else if (rename(buf, realname) == -1) { /* Try a rename?? */ statusbar(_("Could not open %s for writing: %s"), realname, strerror(errno)); unlink(buf); - return -1; + goto cleanup_and_exit; } } if (chmod(realname, mask) == -1) @@ -1711,15 +1663,18 @@ int write_file(char *name, int tmp, int append, int nonamechange) UNSET(MODIFIED); titlebar(NULL); } - return 1; + + retval = 1; + + cleanup_and_exit: + free(realname); + free(buf); + return retval; } -int do_writeout(char *path, int exiting, int append) +int do_writeout(const char *path, int exiting, int append) { int i = 0; -#ifndef NANO_SMALL - const char *formatstr, *backupstr; -#endif #ifdef NANO_EXTRA static int did_cred = 0; #endif @@ -1730,7 +1685,7 @@ int do_writeout(char *path, int exiting, int append) answer = mallocstrcpy(answer, path); - if ((exiting) && (ISSET(TEMP_OPT))) { + if (exiting && ISSET(TEMP_OPT)) { if (filename[0]) { i = write_file(answer, 0, 0, 0); display_main_list(); @@ -1745,8 +1700,9 @@ int do_writeout(char *path, int exiting, int append) } while (1) { - #ifndef NANO_SMALL + const char *formatstr, *backupstr; + if (ISSET(MAC_FILE)) formatstr = _(" [Mac Format]"); else if (ISSET(DOS_FILE)) @@ -1793,64 +1749,67 @@ int do_writeout(char *path, int exiting, int append) "%s", _("File Name to Write")); #endif /* !NANO_SMALL */ - if (i != -1) { + if (i == -1) { + statusbar(_("Cancelled")); + display_main_list(); + return 0; + } #ifndef DISABLE_BROWSER if (i == NANO_TOFILES_KEY) { - char *tmp = do_browse_from(answer); -#if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) currshortcut = writefile_list; -#endif - - if (tmp != NULL) { - answer = mallocstrcpy(answer, tmp); - } else - return do_writeout(answer, exiting, append); + if (tmp == NULL) + continue; + free(answer); + answer = tmp; } else -#endif +#endif /* !DISABLE_BROWSER */ #ifndef NANO_SMALL if (i == TOGGLE_DOS_KEY) { UNSET(MAC_FILE); TOGGLE(DOS_FILE); - return(do_writeout(answer, exiting, append)); + continue; } else if (i == TOGGLE_MAC_KEY) { UNSET(DOS_FILE); TOGGLE(MAC_FILE); - return(do_writeout(answer, exiting, append)); + continue; } else if (i == TOGGLE_BACKUP_KEY) { TOGGLE(BACKUP_FILE); - return(do_writeout(answer, exiting, append)); -#else - if (0) { -#endif - } else if (i == NANO_PREPEND_KEY) - return(do_writeout(answer, exiting, append == 2 ? 0 : 2)); - else if (i == NANO_APPEND_KEY) - return(do_writeout(answer, exiting, append == 1 ? 0 : 1)); + continue; + } else +#endif /* ! NANO_SMALL */ + if (i == NANO_PREPEND_KEY) { + append = append == 2 ? 0 : 2; + continue; + } else if (i == NANO_APPEND_KEY) { + append = append == 1 ? 0 : 1; + continue; + } #ifdef DEBUG - fprintf(stderr, _("filename is %s\n"), answer); + fprintf(stderr, _("filename is %s\n"), answer); #endif #ifdef NANO_EXTRA - if (exiting && !ISSET(TEMP_OPT) && !strcasecmp(answer, "zzy") + if (exiting && !ISSET(TEMP_OPT) && !strcasecmp(answer, "zzy") && !did_cred) { - do_credits(); - did_cred = 1; - return -1; - } + do_credits(); + did_cred = 1; + return -1; + } #endif - if (!append && strcmp(answer, filename)) { - struct stat st; - if (!stat(answer, &st)) { - i = do_yesno(0, 0, _("File exists, OVERWRITE ?")); + if (!append && strcmp(answer, filename)) { + struct stat st; - if (!i || (i == -1)) - continue; - } + if (!stat(answer, &st)) { + i = do_yesno(0, 0, _("File exists, OVERWRITE ?")); + + if (i == 0 || i == -1) + continue; } + } #ifndef NANO_SMALL /* Here's where we allow the selected text to be written to @@ -1859,56 +1818,40 @@ int do_writeout(char *path, int exiting, int append) filestruct *fileagebak = fileage; filestruct *filebotbak = filebot; filestruct *cutback = cutbuffer; - long totsizebak = totsize; - int oldmod = 0; + int oldmod = ISSET(MODIFIED); + /* write_file() unsets the MODIFIED flag. */ + cutbuffer = NULL; - /* Okay, since write_file changes the filename, back it up */ - if (ISSET(MODIFIED)) - oldmod = 1; - - /* Now, non-destructively add the marked text to the - cutbuffer, and write the file out using the cutbuffer ;) */ - if (current->lineno <= mark_beginbuf->lineno) - cut_marked_segment(current, current_x, mark_beginbuf, + /* Put the marked text in the cutbuffer without changing + the open file. */ + cut_marked_segment(current, current_x, mark_beginbuf, mark_beginx, 0); - else - cut_marked_segment(mark_beginbuf, mark_beginx, current, - current_x, 0); fileage = cutbuffer; - for (filebot = cutbuffer; filebot->next != NULL; - filebot = filebot->next) - ; + filebot = get_cutbottom(); i = write_file(answer, 0, append, 1); /* Now restore everything */ + free_filestruct(cutbuffer); fileage = fileagebak; filebot = filebotbak; cutbuffer = cutback; - totsize = totsizebak; if (oldmod) set_modified(); } else #endif /* !NANO_SMALL */ - i = write_file(answer, 0, append, 0); #ifdef ENABLE_MULTIBUFFER - /* if we're not about to exit, update the current entry in - the open_files structure */ - if (!exiting) - add_open_file(1); + /* If we're not about to exit, update the current entry in + the open_files structure. */ + if (!exiting) + add_open_file(1); #endif - - display_main_list(); - return i; - } else { - statusbar(_("Cancelled")); - display_main_list(); - return 0; - } - } + display_main_list(); + return i; + } /* while (1) */ } int do_writeout_void(void) @@ -1919,76 +1862,67 @@ int do_writeout_void(void) #ifndef DISABLE_TABCOMP /* Return a malloc()ed string containing the actual directory, used - * to convert ~user and ~/ notation... - */ -char *real_dir_from_tilde(char *buf) + * to convert ~user and ~/ notation... */ +char *real_dir_from_tilde(const char *buf) { char *dirtmp = NULL; - int i = 1; - struct passwd *userdata; - - /* set a default value for dirtmp, in the case user home dir not found */ - dirtmp = mallocstrcpy(dirtmp, buf); if (buf[0] == '~') { - if (buf[1] == 0 || buf[1] == '/') { + size_t i; + const struct passwd *userdata; + + /* Figure how how much of the str we need to compare */ + for (i = 1; buf[i] != '/' && buf[i] != '\0'; i++) + ; + + if (i == 1) { /* Determine home directory using getpwent(), don't rely on $HOME */ uid_t euid = geteuid(); + do { userdata = getpwent(); } while (userdata != NULL && userdata->pw_uid != euid); - } - else { - char *find_user = NULL; - - /* Figure how how much of the str we need to compare */ - for (i = 1; buf[i] != '/' && buf[i] != 0; i++) - ; - - find_user = mallocstrcpy(find_user, &buf[1]); - find_user[i - 1] = '\0'; - - for (userdata = getpwent(); userdata != NULL && - strcmp(userdata->pw_name, find_user); - userdata = getpwent()); - - free(find_user); + } else { + do { + userdata = getpwent(); + } while (userdata != NULL && + strncmp(userdata->pw_name, buf + 1, i - 1)); } endpwent(); if (userdata != NULL) { /* User found */ - free(dirtmp); - dirtmp = charalloc(strlen(buf) + 2 + strlen(userdata->pw_dir)); + dirtmp = charalloc(strlen(userdata->pw_dir) + strlen(buf + i) + 1); sprintf(dirtmp, "%s%s", userdata->pw_dir, &buf[i]); } } + if (dirtmp == NULL) + dirtmp = mallocstrcpy(dirtmp, buf); + return dirtmp; } -/* Tack a slash onto the string we're completing if it's a directory */ +/* Tack a slash onto the string we're completing if it's a directory. We + * assume there is room for one more character on the end of buf. The + * return value says whether buf is a directory. */ int append_slash_if_dir(char *buf, int *lastwastab, int *place) { - char *dirptr; + char *dirptr = real_dir_from_tilde(buf); struct stat fileinfo; int ret = 0; - dirptr = real_dir_from_tilde(buf); + assert(dirptr != buf); - if (stat(dirptr, &fileinfo) == -1) - ret = 0; - else if (S_ISDIR(fileinfo.st_mode)) { + if (stat(dirptr, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode)) { strncat(buf, "/", 1); - *place += 1; + (*place)++; /* now we start over again with # of tabs so far */ *lastwastab = 0; ret = 1; } - if (dirptr != buf) - free(dirptr); - + free(dirptr); return ret; } @@ -2383,7 +2317,7 @@ char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list) curs_set(1); return buf; } -#endif +#endif /* !DISABLE_TABCOMP */ #ifndef DISABLE_BROWSER @@ -2397,57 +2331,53 @@ struct stat filestat(const char *path) } /* Our sort routine for file listings - sort directories before - * files, and then alphabetically - */ + * files, and then alphabetically. */ int diralphasort(const void *va, const void *vb) { - struct stat file1info, file2info; - char *a = *(char **)va, *b = *(char **)vb; - int aisdir, bisdir; + struct stat fileinfo; + const char *a = *(char *const *)va, *b = *(char *const *)vb; + int aisdir = stat(a, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode); + int bisdir = stat(b, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode); - aisdir = (stat(a, &file1info) != -1) && S_ISDIR(file1info.st_mode); - bisdir = (stat(b, &file2info) != -1) && S_ISDIR(file2info.st_mode); - - if (aisdir && !bisdir) return -1; - if (!aisdir && bisdir) return 1; + if (aisdir && !bisdir) + return -1; + if (!aisdir && bisdir) + return 1; #ifdef HAVE_STRCASECMP - return(strcasecmp(a,b)); + return strcasecmp(a, b); #else - return(strcmp(a,b)); + return strcmp(a, b); #endif - } /* Free our malloc()ed memory */ void free_charptrarray(char **array, int len) { - int i; - - for (i = 0; i < len; i++) - free(array[i]); + for (; len > 0; len--) + free(array[len - 1]); free(array); } -/* only print the last part of a path; isn't there a shell - command for this? */ -char *tail(char *foo) +/* Only print the last part of a path; isn't there a shell + * command for this? */ +const char *tail(const char *foo) { - char *tmp = NULL; + const char *tmp = foo + strlen(foo); - tmp = foo + strlen(foo); while (*tmp != '/' && tmp != foo) tmp--; - tmp++; + if (*tmp == '/') + tmp++; return tmp; } -/* Strip one dir from the end of a string */ +/* Strip one dir from the end of a string. */ void striponedir(char *foo) { - char *tmp = NULL; + char *tmp; /* Don't strip the root dir */ if (!strcmp(foo, "/")) @@ -2461,23 +2391,22 @@ void striponedir(char *foo) tmp--; if (tmp != foo) - *tmp = 0; - else - { /* SPK may need to make a 'default' path here */ - if (*tmp != '/') *(tmp) = '.'; - *(tmp+1) = 0; + *tmp = '\0'; + else { /* SPK may need to make a 'default' path here */ + if (*tmp != '/') + *tmp = '.'; + *(tmp + 1) = '\0'; } - - return; } /* Initialize the browser code, including the list of files in *path */ -char **browser_init(char *path, int *longest, int *numents) +char **browser_init(const char *path, int *longest, int *numents) { DIR *dir; struct dirent *next; - char **filelist = (char **) NULL; + char **filelist; int i = 0; + size_t path_len; dir = opendir(path); if (!dir) @@ -2496,17 +2425,16 @@ char **browser_init(char *path, int *longest, int *numents) filelist = nmalloc(*numents * sizeof (char *)); + if (!strcmp(path, "/")) + path = ""; + path_len = strlen(path); + while ((next = readdir(dir)) != NULL) { if (!strcmp(next->d_name, ".")) continue; - filelist[i] = charalloc(strlen(next->d_name) + strlen(path) + 2); - if (!strcmp(path, "/")) - snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 1, - "%s%s", path, next->d_name); - else - snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 2, - "%s/%s", path, next->d_name); + filelist[i] = charalloc(strlen(next->d_name) + path_len + 2); + sprintf(filelist[i], "%s/%s", path, next->d_name); i++; } @@ -2517,7 +2445,7 @@ char **browser_init(char *path, int *longest, int *numents) } /* Our browser function. inpath is the path to start browsing from */ -char *do_browser(char *inpath) +char *do_browser(const char *inpath) { struct stat st; char *foo, *retval = NULL; @@ -2532,6 +2460,8 @@ char *do_browser(char *inpath) #endif #endif + assert(inpath != NULL); + /* If path isn't the same as inpath, we are being passed a new dir as an arg. We free it here so it will be copied from inpath below */ @@ -2542,7 +2472,7 @@ char *do_browser(char *inpath) /* if path doesn't exist, make it so */ if (path == NULL) - path = mallocstrcpy(path, inpath); + path = mallocstrcpy(NULL, inpath); filelist = browser_init(path, &longest, &numents); foo = charalloc(longest + 8); @@ -2868,34 +2798,37 @@ char *do_browser(char *inpath) /* Browser front end, checks to see if inpath has a dir in it and, if so, starts do_browser from there, else from the current dir */ -char *do_browse_from(char *inpath) +char *do_browse_from(const char *inpath) { struct stat st; - char *tmp = NULL; - - tmp = mallocstrcpy(tmp, inpath); - + char *tmp; + char *bob; /* If there's no / in the string, we may as well start from . */ - if (tmp == NULL || *tmp == '\0' || !strstr(tmp, "/")) { + if (inpath == NULL || strchr(inpath, '/') == NULL) { #ifdef PATH_MAX char *from = getcwd(NULL, PATH_MAX + 1); #else char *from = getcwd(NULL, 0); -#endif /* PATH_MAX */ - return do_browser(from ? from : "./"); +#endif + + bob = do_browser(from ? from : "./"); + free(from); + return bob; } /* If the string is a directory, pass do_browser that */ - st = filestat(tmp); + st = filestat(inpath); if (S_ISDIR(st.st_mode)) - return do_browser(tmp); + return do_browser(inpath); + tmp = mallocstrcpy(NULL, inpath); /* Okay, there's a dir in there, but not at the end of the string... try stripping it off */ striponedir(tmp); align(&tmp); - return do_browser(tmp); - + bob = do_browser(tmp); + free(tmp); + return bob; } #endif /* !DISABLE_BROWSER */ diff --git a/global.c b/global.c index 7a9cf725..74a171f7 100644 --- a/global.c +++ b/global.c @@ -153,10 +153,10 @@ regex_t syntaxfile_regexp; /* Global to store compiled search regexp */ regmatch_t synfilematches[1]; /* Match positions for parenthetical */ #endif /* ENABLE_COLOR */ - int length_of_list(const shortcut *s) { int i = 0; + for (; s != NULL; s = s->next) i++; return i; @@ -304,7 +304,7 @@ void free_shortcutage(shortcut **shortcutage) void shortcut_init(int unjustify) { #ifndef DISABLE_HELP - char *nano_help_msg = "", *nano_writeout_msg = "", *nano_exit_msg = + const char *nano_help_msg = "", *nano_writeout_msg = "", *nano_exit_msg = "", *nano_goto_msg = "", *nano_justify_msg = "", *nano_replace_msg = "", *nano_insert_msg = "", *nano_whereis_msg = "", *nano_prevpage_msg = @@ -325,11 +325,11 @@ void shortcut_init(int unjustify) "", *nano_backup_msg = ""; #ifdef ENABLE_MULTIBUFFER - char *nano_openprev_msg = "", *nano_opennext_msg = + const char *nano_openprev_msg = "", *nano_opennext_msg = "", *nano_multibuffer_msg = ""; #endif #ifdef HAVE_REGEX_H - char *nano_regexp_msg = "", *nano_bracket_msg = ""; + const char *nano_regexp_msg = "", *nano_bracket_msg = ""; #endif nano_help_msg = _("Invoke the help menu"); @@ -725,10 +725,10 @@ void shortcut_init(int unjustify) #ifndef NANO_SMALL sc_init_one(&insertfile_list, NANO_EXTCMD_KEY, _("Execute Command"), IFHELP(nano_execute_msg, 0), 0, 0, NOVIEW, 0); -#endif #ifdef ENABLE_MULTIBUFFER - sc_init_one(&insertfile_list, NANO_LOAD_KEY, _("New Buffer"), + sc_init_one(&insertfile_list, TOGGLE_LOAD_KEY, _("New Buffer"), IFHELP(nano_multibuffer_msg, 0), 0, 0, NOVIEW, 0); +#endif #endif free_shortcutage(&spell_list); diff --git a/nano.c b/nano.c index 52185080..76863245 100644 --- a/nano.c +++ b/nano.c @@ -2177,7 +2177,7 @@ int do_justify(void) * 2) the line above it is not part of a paragraph, or * 3) the line above it does not have precisely the same quote * part, or - * 4) the indentation of this line is not a subset of the + * 4) the indentation of this line is not an initial substring of the * indentation of the previous line, or * 5) this line has no quote part and some indentation, and * AUTOINDENT is not set. @@ -2250,29 +2250,28 @@ int do_justify(void) current_x = 0; if (current->data[quote_len + indent_len] != '\0') { /* This line is part of a paragraph. So we must search back to - * the first line of this paragraph. */ - if (quote_len > 0 || indent_len == 0 -#ifndef NANO_SMALL - || ISSET(AUTOINDENT) -#endif - ) { - /* We don't justify indented paragraphs unless AUTOINDENT is - * turned on. See 5) above. */ - while (current->prev && quotes_match(current->data, + * the first line of this paragraph. First we check items 1) and + * 3) above. */ + while (current->prev && quotes_match(current->data, quote_len, IFREG(current->prev->data, &qreg))) { - /* indentation length of the previous line */ - size_t temp_id_len = + size_t temp_id_len = indent_length(current->prev->data + quote_len); + /* The indentation length of the previous line. */ - if (!indents_match(current->prev->data + quote_len, - temp_id_len, current->data + quote_len, - indent_len) || - current->prev->data[quote_len + temp_id_len] == '\0') - break; - indent_len = temp_id_len; - current = current->prev; - current_y--; - } + /* Is this line the beginning of a paragraph, according to + items 2), 5), or 4) above? If so, stop. */ + if (current->prev->data[quote_len + temp_id_len] == '\0' || + (quote_len == 0 && indent_len > 0 +#ifndef NANO_SMALL + && !ISSET(AUTOINDENT) +#endif + ) || + !indents_match(current->prev->data + quote_len, + temp_id_len, current->data + quote_len, indent_len)) + break; + indent_len = temp_id_len; + current = current->prev; + current_y--; } } else { /* This line is not part of a paragraph. Move down until we get @@ -2646,15 +2645,13 @@ void signal_init(void) #endif /* _POSIX_VDISABLE */ if (!ISSET(SUSPEND)) { - -/* Insane! */ + /* Insane! */ #ifdef _POSIX_VDISABLE term.c_cc[VSUSP] = _POSIX_VDISABLE; #else act.sa_handler = SIG_IGN; sigaction(SIGTSTP, &act, NULL); #endif - } else { /* If we don't do this, it seems other stuff interrupts the suspend handler! Try using nano with mutt without this @@ -3091,12 +3088,6 @@ int main(int argc, char *argv[]) #ifndef DISABLE_OPERATINGDIR case 'o': operating_dir = mallocstrcpy(operating_dir, optarg); - - /* make sure we're inside the operating directory */ - if (check_operating_dir(".", 0) && chdir(operating_dir) == -1) { - free(operating_dir); - operating_dir = NULL; - } break; #endif case 'p': @@ -3150,6 +3141,12 @@ int main(int argc, char *argv[]) } } +#ifndef DISABLE_OPERATINGDIR + /* Set up the operating directory. This entails chdir()ing there, so + that file reads and writes will be based there. */ + init_operating_dir(); +#endif + /* Clear the filename we'll be using */ filename = charalloc(1); filename[0] = '\0'; diff --git a/nano.h b/nano.h index 74179e6f..8fcb846d 100644 --- a/nano.h +++ b/nano.h @@ -137,7 +137,7 @@ typedef struct toggle { #ifdef ENABLE_NANORC typedef struct rcoption { - char *name; + const char *name; int flag; } rcoption; #endif /* ENABLE_NANORC */ @@ -326,7 +326,6 @@ know what you're doing */ #define NANO_TOFILES_KEY NANO_CONTROL_T #define NANO_APPEND_KEY NANO_ALT_A #define NANO_PREPEND_KEY NANO_ALT_P -#define NANO_LOAD_KEY NANO_ALT_F #define NANO_OPENPREV_KEY NANO_ALT_LCARAT #define NANO_OPENNEXT_KEY NANO_ALT_RCARAT #define NANO_OPENPREV_ALTKEY NANO_ALT_COMMA diff --git a/proto.h b/proto.h index 63ba5800..50fb5549 100644 --- a/proto.h +++ b/proto.h @@ -126,7 +126,6 @@ int do_uncut_text(void); void load_file(int update); void new_file(void); filestruct *read_line(char *buf, filestruct *prev, int *line1ins, int len); -int write_file(char *name, int tmpfile, int append, int nonamechange); int read_file(FILE *f, const char *filename, int quiet); int open_file(const char *filename, int insert, int quiet); char *get_next_filename(const char *name); @@ -147,20 +146,21 @@ int open_nextfile_void(void); int close_open_file(void); #endif #if !defined(DISABLE_SPELLER) || !defined(DISABLE_OPERATINGDIR) -char *get_full_path(char *origpath); +char *get_full_path(const char *origpath); #endif #ifndef DISABLE_SPELLER -char *check_writable_directory(char *path); +char *check_writable_directory(const char *path); char *safe_tempnam(const char *dirname, const char *filename_prefix); #endif #ifndef DISABLE_OPERATINGDIR -int check_operating_dir(char *currpath, int allow_tabcomp); +void init_operating_dir(void); +int check_operating_dir(const char *currpath, int allow_tabcomp); #endif -int write_file(char *name, int tmp, int append, int nonamechange); -int do_writeout(char *path, int exiting, int append); +int write_file(const char *name, int tmp, int append, int nonamechange); +int do_writeout(const char *path, int exiting, int append); int do_writeout_void(void); #ifndef DISABLE_TABCOMP -char *real_dir_from_tilde(char *buf); +char *real_dir_from_tilde(const char *buf); #endif int append_slash_if_dir(char *buf, int *lastwastab, int *place); char **username_tab_completion(char *buf, int *num_matches); @@ -170,11 +170,11 @@ char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list) struct stat filestat(const char *path); int diralphasort(const void *va, const void *vb); void free_charptrarray(char **array, int len); -char *tail(char *foo); +const char *tail(const char *foo); void striponedir(char *foo); -char **browser_init(char *path, int *longest, int *numents); -char *do_browser(char *inpath); -char *do_browse_from(char *inpath); +char **browser_init(const char *path, int *longest, int *numents); +char *do_browser(const char *inpath); +char *do_browse_from(const char *inpath); #endif /* Public functions in global.c */ diff --git a/rcfile.c b/rcfile.c index 26c5e359..8545526b 100644 --- a/rcfile.c +++ b/rcfile.c @@ -19,6 +19,8 @@ * * **************************************************************************/ +#include "config.h" + #include #include #include @@ -30,7 +32,6 @@ #include #include #include -#include "config.h" #include "proto.h" #include "nano.h" @@ -43,7 +44,7 @@ #define _(string) (string) #endif -static rcoption rcopts[] = { +const static rcoption rcopts[] = { #ifndef NANO_SMALL {"autoindent", AUTOINDENT}, {"backup", BACKUP_FILE}, @@ -90,7 +91,7 @@ static rcoption rcopts[] = { {"tabsize", 0}, {"tempfile", TEMP_OPT}, {"view", VIEW_MODE}, - {"", 0} + {NULL, 0} }; static int errors = 0; @@ -483,7 +484,7 @@ void parse_rcfile(FILE *rcstream) /* We don't care if ptr == NULL, as it should if using proper syntax */ if (set != 0) { - for (i = 0; rcopts[i].name != ""; i++) { + for (i = 0; rcopts[i].name != NULL; i++) { if (!strcasecmp(option, rcopts[i].name)) { #ifdef DEBUG fprintf(stderr, _("parse_rcfile: Parsing option %s\n"), diff --git a/search.c b/search.c index 319cfa18..f7929cf7 100644 --- a/search.c +++ b/search.c @@ -820,7 +820,7 @@ void do_gotopos(int line, int pos_x, int pos_y, int pos_placewewant) int do_find_bracket(void) { char ch_under_cursor, wanted_ch; - char *pos, *brackets = "([{<>}])"; + const char *pos, *brackets = "([{<>}])"; char regexp_pat[] = "[ ]"; int offset, have_past_editbuff = 0, flagsave, current_x_save, count = 1; filestruct *current_save; diff --git a/utils.c b/utils.c index acd67a11..431824e1 100644 --- a/utils.c +++ b/utils.c @@ -19,13 +19,14 @@ * * **************************************************************************/ +#include "config.h" + #include #include #include #include #include #include -#include "config.h" #include "proto.h" #include "nano.h" @@ -221,12 +222,10 @@ void *nmalloc(size_t howmuch) the transition cost of moving to the appropriate function. */ char *charalloc(size_t howmuch) { - char *r; + char *r = (char *)malloc(howmuch * sizeof(char)); - /* Panic save? */ - - if (!(r = (char *)calloc(howmuch, sizeof (char)))) - die(_("nano: calloc: out of memory!")); + if (r == NULL) + die(_("nano: malloc: out of memory!")); return r; } diff --git a/winio.c b/winio.c index 57609c31..9f27d647 100644 --- a/winio.c +++ b/winio.c @@ -19,13 +19,14 @@ * * **************************************************************************/ +#include "config.h" + #include #include #include #include #include #include -#include "config.h" #include "proto.h" #include "nano.h" @@ -1804,10 +1805,10 @@ void do_credits(void) { int i, j = 0, k, place = 0, start_x; - char *what; - char *xlcredits[XLCREDIT_LEN]; + const char *what; + const char *xlcredits[XLCREDIT_LEN]; - char *credits[CREDIT_LEN] = { + const char *credits[CREDIT_LEN] = { "0", /* "The nano text editor" */ "1", /* "version" */ VERSION,