nano

nano with my custom patches
git clone git://bsandro.tech/nano
Log | Files | Refs | README | LICENSE

files.c (79799B)


      1 /**************************************************************************
      2  *   files.c  --  This file is part of GNU nano.                          *
      3  *                                                                        *
      4  *   Copyright (C) 1999-2011, 2013-2025 Free Software Foundation, Inc.    *
      5  *   Copyright (C) 2015-2022 Benno Schulenberg                            *
      6  *                                                                        *
      7  *   GNU nano is free software: you can redistribute it and/or modify     *
      8  *   it under the terms of the GNU General Public License as published    *
      9  *   by the Free Software Foundation, either version 3 of the License,    *
     10  *   or (at your option) any later version.                               *
     11  *                                                                        *
     12  *   GNU nano is distributed in the hope that it will be useful,          *
     13  *   but WITHOUT ANY WARRANTY; without even the implied warranty          *
     14  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.              *
     15  *   See the GNU General Public License for more details.                 *
     16  *                                                                        *
     17  *   You should have received a copy of the GNU General Public License    *
     18  *   along with this program.  If not, see https://gnu.org/licenses/.     *
     19  *                                                                        *
     20  **************************************************************************/
     21 
     22 #include "prototypes.h"
     23 
     24 #include <errno.h>
     25 #include <fcntl.h>
     26 #include <libgen.h>
     27 #ifdef HAVE_PWD_H
     28 #include <pwd.h>
     29 #endif
     30 #include <string.h>
     31 #include <unistd.h>
     32 #include <sys/wait.h>
     33 
     34 #define RW_FOR_ALL  (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
     35 
     36 #ifndef HAVE_FSYNC
     37 # define fsync(...)  0
     38 #endif
     39 
     40 /* Add an item to the circular list of openfile structs. */
     41 void make_new_buffer(void)
     42 {
     43 	openfilestruct *newnode = nmalloc(sizeof(openfilestruct));
     44 
     45 #ifdef ENABLE_MULTIBUFFER
     46 	if (openfile == NULL) {
     47 		/* Make the first buffer the only element in the list. */
     48 		newnode->prev = newnode;
     49 		newnode->next = newnode;
     50 
     51 		startfile = newnode;
     52 	} else {
     53 		/* Add the new buffer after the current one in the list. */
     54 		newnode->prev = openfile;
     55 		newnode->next = openfile->next;
     56 		openfile->next->prev = newnode;
     57 		openfile->next = newnode;
     58 
     59 		/* There is more than one buffer: show "Close" in help lines. */
     60 		exitfunc->tag = close_tag;
     61 		more_than_one = !inhelp || more_than_one;
     62 	}
     63 #endif
     64 	/* Make the new buffer the current one, and start initializing it. */
     65 	openfile = newnode;
     66 
     67 	openfile->filename = copy_of("");
     68 
     69 	openfile->filetop = make_new_node(NULL);
     70 	openfile->filetop->data = copy_of("");
     71 	openfile->filebot = openfile->filetop;
     72 
     73 	openfile->current = openfile->filetop;
     74 	openfile->current_x = 0;
     75 	openfile->placewewant = 0;
     76 	openfile->cursor_row = 0;
     77 
     78 	openfile->edittop = openfile->filetop;
     79 	openfile->firstcolumn = 0;
     80 
     81 	openfile->totsize = 0;
     82 	openfile->modified = FALSE;
     83 #ifdef ENABLE_WRAPPING
     84 	openfile->spillage_line = NULL;
     85 #endif
     86 #ifndef NANO_TINY
     87 	openfile->mark = NULL;
     88 	openfile->softmark = FALSE;
     89 
     90 	openfile->fmt = UNSPECIFIED;
     91 
     92 	openfile->undotop = NULL;
     93 	openfile->current_undo = NULL;
     94 	openfile->last_saved = NULL;
     95 	openfile->last_action = OTHER;
     96 
     97 	openfile->statinfo = NULL;
     98 	openfile->lock_filename = NULL;
     99 #endif
    100 #ifdef ENABLE_MULTIBUFFER
    101 	openfile->errormessage = NULL;
    102 #endif
    103 #ifdef ENABLE_COLOR
    104 	openfile->syntax = NULL;
    105 #endif
    106 }
    107 
    108 /* Return the given file name in a way that fits within the given space. */
    109 char *crop_to_fit(const char *name, int room)
    110 {
    111 	char *clipped;
    112 
    113 	if (breadth(name) <= room)
    114 		return display_string(name, 0, room, FALSE, FALSE);
    115 
    116 	if (room < 4)
    117 		return copy_of("_");
    118 
    119 	clipped = display_string(name, breadth(name) - room + 3, room, FALSE, FALSE);
    120 
    121 	clipped = nrealloc(clipped, strlen(clipped) + 4);
    122 	memmove(clipped + 3, clipped, strlen(clipped) + 1);
    123 	clipped[0] = '.'; clipped[1] = '.'; clipped[2] = '.';
    124 
    125 	return clipped;
    126 }
    127 
    128 #ifndef NANO_TINY
    129 /* Delete the lock file.  Return TRUE on success, and FALSE otherwise. */
    130 bool delete_lockfile(const char *lockfilename)
    131 {
    132 	if (unlink(lockfilename) < 0 && errno != ENOENT) {
    133 		statusline(MILD, _("Error deleting lock file %s: %s"),
    134 							lockfilename, strerror(errno));
    135 		return FALSE;
    136 	} else
    137 		return TRUE;
    138 }
    139 
    140 #define LOCKSIZE  1024
    141 #define SKIPTHISFILE  (char *)-1
    142 
    143 const char *locking_prefix = ".";
    144 const char *locking_suffix = ".swp";
    145 
    146 /* Write a lock file, under the given lockfilename.  This always annihilates an
    147  * existing version of that file.  Return TRUE on success; FALSE otherwise. */
    148 bool write_lockfile(const char *lockfilename, const char *filename, bool modified)
    149 {
    150 #if defined(HAVE_PWD_H) && defined(HAVE_GETEUID)
    151 	pid_t mypid = getpid();
    152 	uid_t myuid = geteuid();
    153 	struct passwd *mypwuid = getpwuid(myuid);
    154 	char myhostname[32];
    155 	int fd;
    156 	FILE *filestream = NULL;
    157 	char *lockdata;
    158 	size_t wroteamt;
    159 
    160 	if (mypwuid == NULL) {
    161 		/* TRANSLATORS: Keep the next seven messages at most 76 characters. */
    162 		statusline(MILD, _("Couldn't determine my identity for lock file"));
    163 		return FALSE;
    164 	}
    165 
    166 	if (gethostname(myhostname, 31) < 0 && errno != ENAMETOOLONG) {
    167 		statusline(MILD, _("Couldn't determine hostname: %s"), strerror(errno));
    168 		return FALSE;
    169 	} else
    170 		myhostname[31] = '\0';
    171 
    172 	/* First make sure to remove an existing lock file. */
    173 	if (!delete_lockfile(lockfilename))
    174 		return FALSE;
    175 
    176 	/* Create the lock file -- do not accept an existing one. */
    177 	fd = open(lockfilename, O_WRONLY|O_CREAT|O_EXCL, RW_FOR_ALL);
    178 
    179 	if (fd > 0)
    180 		filestream = fdopen(fd, "wb");
    181 
    182 	if (filestream == NULL) {
    183 		statusline(MILD, _("Error writing lock file %s: %s"),
    184 							lockfilename, strerror(errno));
    185 		if (fd > 0)
    186 			close(fd);
    187 		return FALSE;
    188 	}
    189 
    190 	lockdata = nmalloc(LOCKSIZE);
    191 	memset(lockdata, 0, LOCKSIZE);
    192 
    193 	/* This is the lock data we will store (other bytes remain 0x00):
    194 	 *
    195 	 *   bytes 0-1     - 0x62 0x30
    196 	 *   bytes 2-11    - name of program that created the lock
    197 	 *   bytes 24-27   - PID (little endian) of creator process
    198 	 *   bytes 28-43   - username of the user who created the lock
    199 	 *   bytes 68-99   - hostname of machine from where the lock was created
    200 	 *   bytes 108-876 - filename that the lock is for
    201 	 *   byte 1007     - 0x55 if file is modified
    202 	 *
    203 	 * Nano does not write the page size (bytes 12-15), nor the modification
    204 	 * time (bytes 16-19), nor the inode of the relevant file (bytes 20-23).
    205 	 * Nano also does not use all available space for user name (40 bytes),
    206 	 * host name (40 bytes), and file name (890 bytes).  Nor does nano write
    207 	 * some byte-order-checking numbers (bytes 1008-1022). */
    208 	lockdata[0] = 0x62;
    209 	lockdata[1] = 0x30;
    210 	/* It's fine to overwrite byte 12 with the \0 as it is 0x00 anyway. */
    211 	snprintf(&lockdata[2], 11, "nano %s", VERSION);
    212 	lockdata[24] = mypid % 256;
    213 	lockdata[25] = (mypid / 256) % 256;
    214 	lockdata[26] = (mypid / (256 * 256)) % 256;
    215 	lockdata[27] = mypid / (256 * 256 * 256);
    216 	strncpy(&lockdata[28], mypwuid->pw_name, 16);
    217 	strncpy(&lockdata[68], myhostname, 32);
    218 	strncpy(&lockdata[108], filename, 768);
    219 	lockdata[1007] = (modified) ? 0x55 : 0x00;
    220 
    221 	wroteamt = fwrite(lockdata, 1, LOCKSIZE, filestream);
    222 
    223 	free(lockdata);
    224 
    225 	if (fclose(filestream) == EOF || wroteamt < LOCKSIZE) {
    226 		statusline(MILD, _("Error writing lock file %s: %s"),
    227 							lockfilename, strerror(errno));
    228 		return FALSE;
    229 	}
    230 #endif
    231 	return TRUE;
    232 }
    233 
    234 /* First check if a lock file already exists.  If so, and ask_the_user is TRUE,
    235  * then ask whether to open the corresponding file anyway.  Return SKIPTHISFILE
    236  * when the user answers "No", return the name of the lock file on success, and
    237  * return NULL on failure. */
    238 char *do_lockfile(const char *filename, bool ask_the_user)
    239 {
    240 	char *namecopy = copy_of(filename);
    241 	char *secondcopy = copy_of(filename);
    242 	size_t locknamesize = strlen(filename) + strlen(locking_prefix) +
    243 							strlen(locking_suffix) + 3;
    244 	char *lockfilename = nmalloc(locknamesize);
    245 	struct stat fileinfo;
    246 
    247 	snprintf(lockfilename, locknamesize, "%s/%s%s%s", dirname(namecopy),
    248 				locking_prefix, basename(secondcopy), locking_suffix);
    249 	free(secondcopy);
    250 	free(namecopy);
    251 
    252 	if (!ask_the_user && stat(lockfilename, &fileinfo) != -1) {
    253 		blank_bottombars();
    254 		statusline(ALERT, _("Someone else is also editing this file"));
    255 		napms(1200);
    256 	} else if (stat(lockfilename, &fileinfo) != -1) {
    257 		char *lockbuf, *question, *pidstring, *postedname, *promptstr;
    258 		static char lockprog[11], lockuser[17];
    259 		int lockfd, lockpid, choice;
    260 		ssize_t readamt;
    261 
    262 		if ((lockfd = open(lockfilename, O_RDONLY)) < 0) {
    263 			statusline(ALERT, _("Error opening lock file %s: %s"),
    264 								lockfilename, strerror(errno));
    265 			free(lockfilename);
    266 			return NULL;
    267 		}
    268 
    269 		lockbuf = nmalloc(LOCKSIZE);
    270 
    271 		readamt = read(lockfd, lockbuf, LOCKSIZE);
    272 
    273 		close(lockfd);
    274 
    275 		/* If not enough data has been read to show the needed things,
    276 		 * or the two magic bytes are not there, skip the lock file. */
    277 		if (readamt < 68 || lockbuf[0] != 0x62 || lockbuf[1] != 0x30) {
    278 			statusline(ALERT, _("Bad lock file is ignored: %s"), lockfilename);
    279 			free(lockfilename);
    280 			free(lockbuf);
    281 			return NULL;
    282 		}
    283 
    284 		strncpy(lockprog, &lockbuf[2], 10);
    285 		lockprog[10] = '\0';
    286 		lockpid = (((unsigned char)lockbuf[27] * 256 + (unsigned char)lockbuf[26]) * 256 +
    287 						(unsigned char)lockbuf[25]) * 256 + (unsigned char)lockbuf[24];
    288 		strncpy(lockuser, &lockbuf[28], 16);
    289 		lockuser[16] = '\0';
    290 		free(lockbuf);
    291 
    292 		pidstring = nmalloc(11);
    293 		sprintf (pidstring, "%u", (unsigned int)lockpid);
    294 
    295 		/* Display newlines in filenames as ^J. */
    296 		as_an_at = FALSE;
    297 
    298 		/* TRANSLATORS: The second %s is the name of the user, the third that of the editor. */
    299 		question = _("File %s is being edited by %s (with %s, PID %s); open anyway?");
    300 		postedname = crop_to_fit(filename, COLS - breadth(question) - breadth(lockuser) -
    301 											breadth(lockprog) - breadth(pidstring) + 7);
    302 
    303 		/* Allow extra space for username (14), program name (8), PID (8),
    304 		 * and terminating \0 (1), minus the %s (2) for the file name. */
    305 		promptstr = nmalloc(strlen(question) + 29 + strlen(postedname));
    306 		sprintf(promptstr, question, postedname, lockuser, lockprog, pidstring);
    307 		free(postedname);
    308 		free(pidstring);
    309 
    310 		choice = ask_user(YESORNO, promptstr);
    311 		free(promptstr);
    312 
    313 		/* When the user cancelled while we're still starting up, quit. */
    314 		if (choice == CANCEL && !we_are_running)
    315 			finish();
    316 
    317 		if (choice != YES) {
    318 			free(lockfilename);
    319 			wipe_statusbar();
    320 			return SKIPTHISFILE;
    321 		}
    322 	}
    323 
    324 	if (write_lockfile(lockfilename, filename, FALSE))
    325 		return lockfilename;
    326 
    327 	free(lockfilename);
    328 	return NULL;
    329 }
    330 
    331 /* Perform a stat call on the given filename, allocating a stat struct
    332  * if necessary.  On success, *pstat points to the stat's result.  On
    333  * failure, *pstat is freed and made NULL. */
    334 void stat_with_alloc(const char *filename, struct stat **pstat)
    335 {
    336 	if (*pstat == NULL)
    337 		*pstat = nmalloc(sizeof(struct stat));
    338 
    339 	if (stat(filename, *pstat) != 0) {
    340 		free(*pstat);
    341 		*pstat = NULL;
    342 	}
    343 }
    344 #endif /* !NANO_TINY */
    345 
    346 /* Verify that the containing directory of the given filename exists. */
    347 bool has_valid_path(const char *filename)
    348 {
    349 	char *namecopy = copy_of(filename);
    350 	char *parentdir = dirname(namecopy);
    351 	struct stat parentinfo;
    352 	bool validity = FALSE;
    353 	bool gone = FALSE;
    354 
    355 	if (strcmp(parentdir, ".") == 0) {
    356 		char *currentdir = realpath(".", NULL);
    357 
    358 		gone = (currentdir == NULL && errno == ENOENT);
    359 		free(currentdir);
    360 	}
    361 
    362 	if (gone)
    363 		statusline(ALERT, _("The working directory has disappeared"));
    364 	else if (stat(parentdir, &parentinfo) == -1) {
    365 		if (errno == ENOENT)
    366 			/* TRANSLATORS: Keep the next ten messages at most 76 characters. */
    367 			statusline(ALERT, _("Directory '%s' does not exist"), parentdir);
    368 		else
    369 			statusline(ALERT, _("Path '%s': %s"), parentdir, strerror(errno));
    370 	} else if (!S_ISDIR(parentinfo.st_mode))
    371 		statusline(ALERT, _("Path '%s' is not a directory"), parentdir);
    372 	else if (access(parentdir, X_OK) == -1)
    373 		statusline(ALERT, _("Path '%s' is not accessible"), parentdir);
    374 #ifndef NANO_TINY
    375 	else if (ISSET(LOCKING) && !ISSET(VIEW_MODE) && access(parentdir, W_OK) < 0)
    376 		statusline(MILD, _("Directory '%s' is not writable"), parentdir);
    377 #endif
    378 	else
    379 		validity = TRUE;
    380 
    381 	free(namecopy);
    382 
    383 	return validity;
    384 }
    385 
    386 /* This does one of three things.  If the filename is "", it just creates
    387  * a new empty buffer.  When the filename is not empty, it reads that file
    388  * into a new buffer when requested, otherwise into the existing buffer. */
    389 bool open_buffer(const char *filename, bool new_one)
    390 {
    391 	char *realname;
    392 		/* The filename after tilde expansion. */
    393 	struct stat fileinfo;
    394 	int descriptor = 0;
    395 		/* Code 0 means new file, -1 means failure, and else it's the fd. */
    396 	FILE *f;
    397 
    398 	/* Display newlines in filenames as ^J. */
    399 	as_an_at = FALSE;
    400 
    401 #ifdef ENABLE_OPERATINGDIR
    402 	if (outside_of_confinement(filename, FALSE)) {
    403 		statusline(ALERT, _("Can't read file from outside of %s"), operating_dir);
    404 		return FALSE;
    405 	}
    406 #endif
    407 
    408 	realname = real_dir_from_tilde(filename);
    409 
    410 	/* Don't try to open directories, character files, or block files. */
    411 	if (*filename != '\0' && stat(realname, &fileinfo) == 0) {
    412 		if (S_ISDIR(fileinfo.st_mode)) {
    413 			statusline(ALERT, _("\"%s\" is a directory"), realname);
    414 			free(realname);
    415 			return FALSE;
    416 		}
    417 		if (S_ISCHR(fileinfo.st_mode) || S_ISBLK(fileinfo.st_mode)) {
    418 			statusline(ALERT, _("\"%s\" is a device file"), realname);
    419 			free(realname);
    420 			return FALSE;
    421 		}
    422 #ifdef NANO_TINY
    423 		if (S_ISFIFO(fileinfo.st_mode)) {
    424 			statusline(ALERT, _("\"%s\" is a FIFO"), realname);
    425 			free(realname);
    426 			return FALSE;
    427 		}
    428 #elif defined(HAVE_GETEUID)
    429 		if (new_one && !(fileinfo.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) &&
    430 						geteuid() == ROOT_UID)
    431 			statusline(ALERT, _("%s is meant to be read-only"), realname);
    432 #endif
    433 	}
    434 
    435 	/* When loading into a new buffer, first check the file's path is valid,
    436 	 * and then (if requested and possible) create a lock file for it. */
    437 	if (new_one) {
    438 		make_new_buffer();
    439 
    440 		if (has_valid_path(realname)) {
    441 #ifndef NANO_TINY
    442 			if (ISSET(LOCKING) && !ISSET(VIEW_MODE) && filename[0] != '\0') {
    443 				char *thelocksname = do_lockfile(realname, TRUE);
    444 
    445 				/* When not overriding an existing lock, discard the buffer. */
    446 				if (thelocksname == SKIPTHISFILE) {
    447 #ifdef ENABLE_MULTIBUFFER
    448 					close_buffer();
    449 #endif
    450 					free(realname);
    451 					return FALSE;
    452 				} else
    453 					openfile->lock_filename = thelocksname;
    454 			}
    455 #endif /* NANO_TINY */
    456 		}
    457 	}
    458 
    459 	/* If we have a filename and are not in NOREAD mode, open the file. */
    460 	if (filename[0] != '\0' && !ISSET(NOREAD_MODE))
    461 		descriptor = open_file(realname, new_one, &f);
    462 
    463 	/* If we've successfully opened an existing file, read it in. */
    464 	if (descriptor > 0) {
    465 		install_handler_for_Ctrl_C();
    466 
    467 		read_file(f, descriptor, realname, !new_one);
    468 
    469 		restore_handler_for_Ctrl_C();
    470 
    471 #ifndef NANO_TINY
    472 		if (openfile->statinfo == NULL)
    473 			stat_with_alloc(realname, &openfile->statinfo);
    474 #endif
    475 	}
    476 
    477 	/* For a new buffer, store filename and put cursor at start of buffer. */
    478 	if (descriptor >= 0 && new_one) {
    479 		openfile->filename = mallocstrcpy(openfile->filename, realname);
    480 		openfile->current = openfile->filetop;
    481 		openfile->current_x = 0;
    482 		openfile->placewewant = 0;
    483 	}
    484 
    485 #ifdef ENABLE_COLOR
    486 	/* If a new buffer was opened, check whether a syntax can be applied. */
    487 	if (new_one)
    488 		find_and_prime_applicable_syntax();
    489 #endif
    490 
    491 	free(realname);
    492 	return TRUE;
    493 }
    494 
    495 /* Mark the current buffer as modified if it isn't already, and
    496  * then update the title bar to display the buffer's new status. */
    497 void set_modified(void)
    498 {
    499 	if (openfile->modified)
    500 		return;
    501 
    502 	openfile->modified = TRUE;
    503 	titlebar(NULL);
    504 
    505 #ifndef NANO_TINY
    506 	if (openfile->lock_filename != NULL)
    507 		write_lockfile(openfile->lock_filename, openfile->filename, TRUE);
    508 #endif
    509 }
    510 
    511 /* Update the title bar and the multiline cache to match the current buffer. */
    512 void prepare_for_display(void)
    513 {
    514 	/* Update the title bar, since the filename may have changed. */
    515 	if (!inhelp)
    516 		titlebar(NULL);
    517 
    518 #ifdef ENABLE_COLOR
    519 	/* Precalculate the data for any multiline coloring regexes. */
    520 	if (!openfile->filetop->multidata)
    521 		precalc_multicolorinfo();
    522 	have_palette = FALSE;
    523 #endif
    524 	refresh_needed = TRUE;
    525 }
    526 
    527 #ifdef ENABLE_MULTIBUFFER
    528 /* Show name of current buffer and its number of lines on the status bar. */
    529 void mention_name_and_linecount(void)
    530 {
    531 	size_t count = openfile->filebot->lineno -
    532 						(openfile->filebot->data[0] == '\0' ? 1 : 0);
    533 
    534 #ifndef NANO_TINY
    535 	if (ISSET(MINIBAR)) {
    536 		report_size = TRUE;
    537 		return;
    538 	} else if (ISSET(ZERO))
    539 		return;
    540 
    541 	if (openfile->fmt > NIX_FILE)
    542 		/* TRANSLATORS: First %s is file name, second %s is file format. */
    543 		statusline(HUSH, P_("%s -- %zu line (%s)", "%s -- %zu lines (%s)", count),
    544 						openfile->filename[0] == '\0' ?
    545 						_("New Buffer") : tail(openfile->filename), count,
    546 						openfile->fmt == DOS_FILE ? _("DOS") : _("Mac"));
    547 	else
    548 #endif
    549 		statusline(HUSH, P_("%s -- %zu line", "%s -- %zu lines", count),
    550 						openfile->filename[0] == '\0' ?
    551 						_("New Buffer") : tail(openfile->filename), count);
    552 }
    553 
    554 /* Update title bar and such after switching to another buffer.*/
    555 void redecorate_after_switch(void)
    556 {
    557 	/* If only one file buffer is open, there is nothing to update. */
    558 	if (openfile == openfile->next) {
    559 		statusline(AHEM, _("No more open file buffers"));
    560 		return;
    561 	}
    562 
    563 #ifndef NANO_TINY
    564 	/* While in a different buffer, the width of the screen may have changed,
    565 	 * so make sure that the starting column for the first row is fitting. */
    566 	ensure_firstcolumn_is_aligned();
    567 #endif
    568 
    569 	/* Update title bar and multiline info to match the current buffer. */
    570 	prepare_for_display();
    571 
    572 	/* Ensure that the main loop will redraw the help lines. */
    573 	currmenu = MMOST;
    574 
    575 	/* Prevent a possible Shift selection from getting cancelled. */
    576 	shift_held = TRUE;
    577 
    578 	/* If the switched-to buffer gave an error during opening, show the message
    579 	 * once; otherwise, indicate on the status bar which file we switched to. */
    580 	if (openfile->errormessage) {
    581 		statusline(ALERT, openfile->errormessage);
    582 		free(openfile->errormessage);
    583 		openfile->errormessage = NULL;
    584 	} else
    585 		mention_name_and_linecount();
    586 }
    587 
    588 /* Switch to the previous entry in the circular list of buffers. */
    589 void switch_to_prev_buffer(void)
    590 {
    591 	openfile = openfile->prev;
    592 	redecorate_after_switch();
    593 }
    594 
    595 /* Switch to the next entry in the circular list of buffers. */
    596 void switch_to_next_buffer(void)
    597 {
    598 	openfile = openfile->next;
    599 	redecorate_after_switch();
    600 }
    601 
    602 /* Remove the current buffer from the circular list of buffers. */
    603 void close_buffer(void)
    604 {
    605 	openfilestruct *orphan = openfile;
    606 
    607 	if (orphan == startfile)
    608 		startfile = startfile->next;
    609 
    610 	orphan->prev->next = orphan->next;
    611 	orphan->next->prev = orphan->prev;
    612 
    613 	free(orphan->filename);
    614 	free_lines(orphan->filetop);
    615 #ifndef NANO_TINY
    616 	free(orphan->statinfo);
    617 	free(orphan->lock_filename);
    618 	/* Free the undo stack. */
    619 	discard_until(NULL);
    620 #endif
    621 	free(orphan->errormessage);
    622 
    623 	openfile = orphan->prev;
    624 	if (openfile == orphan)
    625 		openfile = NULL;
    626 
    627 	free(orphan);
    628 
    629 	/* When just one buffer remains open, show "Exit" in the help lines. */
    630 	if (openfile && openfile == openfile->next)
    631 		exitfunc->tag = exit_tag;
    632 }
    633 #endif /* ENABLE_MULTIBUFFER */
    634 
    635 /* Encode any NUL bytes in the given line of text (of the given length),
    636  * and return a dynamically allocated copy of the resultant string. */
    637 char *encode_data(char *text, size_t length)
    638 {
    639 	recode_NUL_to_LF(text, length);
    640 	text[length] = '\0';
    641 
    642 	return copy_of(text);
    643 }
    644 
    645 /* The number of bytes by which we expand the line buffer while reading. */
    646 #define LUMPSIZE  120
    647 
    648 /* Read the given open file f into the current buffer.  filename should be
    649  * set to the name of the file.  undoable means that undo records should be
    650  * created and that the file does not need to be checked for writability. */
    651 void read_file(FILE *f, int fd, const char *filename, bool undoable)
    652 {
    653 	ssize_t was_lineno = openfile->current->lineno;
    654 		/* The line number where we start the insertion. */
    655 	size_t was_leftedge = 0;
    656 		/* The leftedge where we start the insertion. */
    657 	size_t num_lines = 0;
    658 		/* The number of lines in the file. */
    659 	size_t len = 0;
    660 		/* The length of the current line of the file. */
    661 	size_t bufsize = LUMPSIZE;
    662 		/* The size of the line buffer; increased as needed. */
    663 	char *buf = nmalloc(bufsize);
    664 		/* The buffer in which we assemble each line of the file. */
    665 	linestruct *topline;
    666 		/* The top of the new buffer where we store the read file. */
    667 	linestruct *bottomline;
    668 		/* The bottom of the new buffer. */
    669 	int onevalue;
    670 		/* The current value we read from the file, either a byte or EOF. */
    671 	int errornumber;
    672 		/* The error code, in case an error occurred during reading. */
    673 	bool writable = TRUE;
    674 		/* Whether the file is writable (in case we care). */
    675 #ifndef NANO_TINY
    676 	format_type format = NIX_FILE;
    677 		/* The type of line ending the file uses: Unix, DOS, or Mac. */
    678 
    679 	if (undoable)
    680 		add_undo(INSERT, NULL);
    681 
    682 	if (ISSET(SOFTWRAP))
    683 		was_leftedge = leftedge_for(xplustabs(), openfile->current);
    684 #endif
    685 
    686 	/* Create an empty buffer. */
    687 	topline = make_new_node(NULL);
    688 	bottomline = topline;
    689 
    690 #ifndef NANO_TINY
    691 	block_sigwinch(TRUE);
    692 #endif
    693 
    694 #ifdef HAVE_FLOCKFILE
    695 	/* Lock the file before starting to read it, to avoid the overhead
    696 	 * of locking it for each single byte that we read from it. */
    697 	flockfile(f);
    698 #else
    699 # define getc_unlocked  getc
    700 #endif
    701 
    702 	control_C_was_pressed = FALSE;
    703 
    704 	/* Read in the entire file, byte by byte, line by line. */
    705 	while ((onevalue = getc_unlocked(f)) != EOF) {
    706 		char input = (char)onevalue;
    707 
    708 		if (control_C_was_pressed)
    709 			break;
    710 
    711 		/* When the byte before the current one is a CR and automatic format
    712 		 * conversion has not been switched off, then strip this CR when it's
    713 		 * before a LF OR when the file is in Mac format.  Also, when this is
    714 		 * the first line break, make a note of the format. */
    715 		if (input == '\n') {
    716 #ifndef NANO_TINY
    717 			if (len > 0 && buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) {
    718 				if (num_lines == 0)
    719 					format = DOS_FILE;
    720 				len--;
    721 			}
    722 		} else if ((num_lines == 0 || format == MAC_FILE) &&
    723 					len > 0 && buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) {
    724 			format = MAC_FILE;
    725 			len--;
    726 #endif
    727 		} else {
    728 			/* Store the byte. */
    729 			buf[len] = input;
    730 
    731 			/* Keep track of the total length of the line.  It might have
    732 			 * NUL bytes in it, so we can't just use strlen() later. */
    733 			len++;
    734 
    735 			/* When needed, increase the line-buffer size.  Don't bother
    736 			 * decreasing it -- it gets freed when reading is finished. */
    737 			if (len == bufsize) {
    738 				bufsize += LUMPSIZE;
    739 				buf = nrealloc(buf, bufsize);
    740 			}
    741 
    742 			continue;
    743 		}
    744 
    745 		/* Store the data and make a new line. */
    746 		bottomline->data = encode_data(buf, len);
    747 		bottomline->next = make_new_node(bottomline);
    748 		bottomline = bottomline->next;
    749 		num_lines++;
    750 
    751 		/* Reset the length in preparation for the next line. */
    752 		len = 0;
    753 
    754 #ifndef NANO_TINY
    755 		/* If it was a Mac line, then store the byte after the \r
    756 		 * as the first byte of the next line. */
    757 		if (input != '\n')
    758 			buf[len++] = input;
    759 #endif
    760 	}
    761 
    762 	errornumber = errno;
    763 
    764 #ifdef HAVE_FUNLOCKFILE
    765 	/* We are done with the file, unlock it. */
    766 	funlockfile(f);
    767 #endif
    768 
    769 #ifndef NANO_TINY
    770 	block_sigwinch(FALSE);
    771 
    772 	/* When reading from stdin, restore the terminal and reenter curses mode. */
    773 	if (isendwin()) {
    774 		if (!isatty(STDIN_FILENO))
    775 			reconnect_and_store_state();
    776 		terminal_init();
    777 		doupdate();
    778 	}
    779 #endif
    780 
    781 	/* If there was a real error during the reading, let the user know. */
    782 	if (ferror(f) && errornumber != EINTR && errornumber != 0)
    783 		statusline(ALERT, strerror(errornumber));
    784 
    785 	if (control_C_was_pressed)
    786 		statusline(ALERT, _("Interrupted"));
    787 
    788 	fclose(f);
    789 
    790 	if (fd > 0 && !undoable && !ISSET(VIEW_MODE))
    791 		writable = (access(filename, W_OK) == 0);
    792 
    793 	/* If the file ended with a newline, or it was entirely empty, make the
    794 	 * last line blank.  Otherwise, put the last read data in. */
    795 	if (len == 0)
    796 		bottomline->data = copy_of("");
    797 	else {
    798 #ifndef NANO_TINY
    799 		bool mac_line_needs_newline = FALSE;
    800 
    801 		/* If the final character is a CR and file conversion isn't disabled,
    802 		 * strip this CR and indicate that an extra blank line is needed. */
    803 		if (buf[len - 1] == '\r' && !ISSET(NO_CONVERT)) {
    804 			if (num_lines == 0)
    805 				format = MAC_FILE;
    806 			buf[--len] = '\0';
    807 			mac_line_needs_newline = TRUE;
    808 		}
    809 #endif
    810 		/* Store the data of the final line. */
    811 		bottomline->data = encode_data(buf, len);
    812 		num_lines++;
    813 
    814 #ifndef NANO_TINY
    815 		if (mac_line_needs_newline) {
    816 			bottomline->next = make_new_node(bottomline);
    817 			bottomline = bottomline->next;
    818 			bottomline->data = copy_of("");
    819 		}
    820 #endif
    821 	}
    822 
    823 	free(buf);
    824 
    825 	/* Insert the just read buffer into the current one. */
    826 	ingraft_buffer(topline);
    827 
    828 	/* Set the desired x position at the end of what was inserted. */
    829 	openfile->placewewant = xplustabs();
    830 
    831 	if (!writable)
    832 		statusline(ALERT, _("File '%s' is unwritable"), filename);
    833 	else if ((ISSET(ZERO) || ISSET(MINIBAR)) && !(we_are_running && undoable))
    834 		;  /* No blurb for new buffers with --zero or --mini. */
    835 #ifndef NANO_TINY
    836 	else if (format == MAC_FILE)
    837 		/* TRANSLATORS: Keep the next three messages at most 78 characters. */
    838 		statusline(REMARK, P_("Read %zu line (converted from Mac format)",
    839 						"Read %zu lines (converted from Mac format)",
    840 						num_lines), num_lines);
    841 	else if (format == DOS_FILE)
    842 		statusline(REMARK, P_("Read %zu line (converted from DOS format)",
    843 						"Read %zu lines (converted from DOS format)",
    844 						num_lines), num_lines);
    845 #endif
    846 	else
    847 		statusline(REMARK, P_("Read %zu line", "Read %zu lines",
    848 						num_lines), num_lines);
    849 
    850 	report_size = TRUE;
    851 
    852 	/* If we inserted less than a screenful, don't center the cursor. */
    853 	if (undoable && less_than_a_screenful(was_lineno, was_leftedge)) {
    854 		focusing = FALSE;
    855 #ifdef ENABLE_COLOR
    856 		perturbed = TRUE;
    857 	} else if (undoable) {
    858 		recook = TRUE;
    859 #endif
    860 	}
    861 
    862 #ifndef NANO_TINY
    863 	if (undoable)
    864 		update_undo(INSERT);
    865 
    866 	if (ISSET(MAKE_IT_UNIX))
    867 		openfile->fmt = NIX_FILE;
    868 	else if (openfile->fmt == UNSPECIFIED)
    869 		openfile->fmt = format;
    870 #endif
    871 }
    872 
    873 /* Open the file with the given name.  If the file does not exist, display
    874  * "New File" if new_one is TRUE, and say "File not found" otherwise.
    875  * Return 0 if we say "New File", -1 upon failure, and the obtained file
    876  * descriptor otherwise.  The opened filestream is returned in *f. */
    877 int open_file(const char *filename, bool new_one, FILE **f)
    878 {
    879 	char *full_filename = get_full_path(filename);
    880 	struct stat fileinfo;
    881 	int fd;
    882 
    883 	/* If the absolute path is unusable (due to some component's permissions),
    884 	 * try the given path instead (as it is probably relative). */
    885 	if (full_filename == NULL || stat(full_filename, &fileinfo) == -1)
    886 		full_filename = mallocstrcpy(full_filename, filename);
    887 
    888 	if (stat(full_filename, &fileinfo) == -1) {
    889 		free(full_filename);
    890 
    891 		if (new_one) {
    892 			statusline(REMARK, _("New File"));
    893 			return 0;
    894 		} else {
    895 			statusline(ALERT, _("File \"%s\" not found"), filename);
    896 			return -1;
    897 		}
    898 	}
    899 
    900 #ifndef NANO_TINY
    901 	if (S_ISFIFO(fileinfo.st_mode))
    902 		statusbar(_("Reading from FIFO..."));
    903 
    904 	block_sigwinch(TRUE);
    905 	install_handler_for_Ctrl_C();
    906 #endif
    907 
    908 	/* Try opening the file. */
    909 	fd = open(full_filename, O_RDONLY);
    910 
    911 #ifndef NANO_TINY
    912 	restore_handler_for_Ctrl_C();
    913 	block_sigwinch(FALSE);
    914 #endif
    915 
    916 	if (fd == -1) {
    917 		if (errno == EINTR || errno == 0)
    918 			statusline(ALERT, _("Interrupted"));
    919 		else
    920 			statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno));
    921 	} else {
    922 		/* The file is A-OK.  Associate a stream with it. */
    923 		*f = fdopen(fd, "rb");
    924 
    925 		if (*f == NULL) {
    926 			statusline(ALERT, _("Error reading %s: %s"), filename, strerror(errno));
    927 			close(fd);
    928 			fd = -1;
    929 		} else if (!ISSET(ZERO) || we_are_running)
    930 			statusbar(_("Reading..."));
    931 	}
    932 
    933 	free(full_filename);
    934 
    935 	return fd;
    936 }
    937 
    938 /* This function will return the name of the first available extension
    939  * of a filename (starting with [name][suffix], then [name][suffix].1,
    940  * etc.).  Memory is allocated for the return value.  If no writable
    941  * extension exists, we return "". */
    942 char *get_next_filename(const char *name, const char *suffix)
    943 {
    944 	size_t wholenamelen= strlen(name) + strlen(suffix);
    945 	unsigned long i = 0;
    946 	char *buf;
    947 
    948 	/* Reserve space for: the name plus the suffix plus a dot plus
    949 	 * possibly five digits plus a null byte. */
    950 	buf = nmalloc(wholenamelen + 7);
    951 	sprintf(buf, "%s%s", name, suffix);
    952 
    953 	while (TRUE) {
    954 		struct stat fs;
    955 
    956 		if (stat(buf, &fs) == -1)
    957 			return buf;
    958 
    959 		/* Limit the number of backup files to a hundred thousand. */
    960 		if (++i == 100000)
    961 			break;
    962 
    963 		sprintf(buf + wholenamelen, ".%lu", i);
    964 	}
    965 
    966 	/* There is no possible save file: blank out the filename. */
    967 	*buf = '\0';
    968 
    969 	return buf;
    970 }
    971 
    972 #ifndef NANO_TINY
    973 static pid_t pid_of_command = -1;
    974 		/* The PID of a forked process -- needed when wanting to abort it. */
    975 static pid_t pid_of_sender = -1;
    976 		/* The PID of the process that pipes data to the above process. */
    977 static bool should_pipe = FALSE;
    978 		/* Whether we are piping data to the external command. */
    979 
    980 /* Send an unconditional kill signal to the running external command. */
    981 void cancel_the_command(int signal)
    982 {
    983 #ifdef SIGKILL
    984 	if (pid_of_command > 0)
    985 		kill(pid_of_command, SIGKILL);
    986 	if (should_pipe && pid_of_sender > 0)
    987 		kill(pid_of_sender, SIGKILL);
    988 #endif
    989 }
    990 
    991 /* Send the text that starts at the given line to file descriptor fd. */
    992 void send_data(const linestruct *line, int fd)
    993 {
    994 	FILE *tube = fdopen(fd, "w");
    995 
    996 	if (tube == NULL)
    997 		exit(4);
    998 
    999 	/* Send each line, except a final empty line. */
   1000 	while (line != NULL && (line->next != NULL || line->data[0] != '\0')) {
   1001 		size_t length = recode_LF_to_NUL(line->data);
   1002 
   1003 		if (fwrite(line->data, 1, length, tube) < length)
   1004 			exit(5);
   1005 
   1006 		if (line->next && putc('\n', tube) == EOF)
   1007 			exit(6);
   1008 
   1009 		line = line->next;
   1010 	}
   1011 
   1012 	fclose(tube);
   1013 }
   1014 
   1015 /* Execute the given command in a shell. */
   1016 void execute_command(const char *command)
   1017 {
   1018 #if defined(HAVE_FORK) && defined(HAVE_PIPE) && defined(HAVE_WAITPID)
   1019 	int from_fd[2], to_fd[2];
   1020 		/* The pipes through which text will be written and read. */
   1021 	struct sigaction oldaction, newaction = {{0}};
   1022 		/* Original and temporary handlers for SIGINT. */
   1023 	ssize_t was_lineno = (openfile->mark ? 0 : openfile->current->lineno);
   1024 	int command_status, sender_status;
   1025 	FILE *stream;
   1026 
   1027 	should_pipe = (command[0] == '|');
   1028 
   1029 	/* Create a pipe to read the command's output from, and, if needed,
   1030 	 * a pipe to feed the command's input through. */
   1031 	if (pipe(from_fd) == -1 || (should_pipe && pipe(to_fd) == -1)) {
   1032 		statusline(ALERT, _("Could not create pipe: %s"), strerror(errno));
   1033 		return;
   1034 	}
   1035 
   1036 	/* Fork a child process to run the command in. */
   1037 	if ((pid_of_command = fork()) == 0) {
   1038 		const char *theshell = getenv("SHELL");
   1039 
   1040 		if (theshell == NULL)
   1041 			theshell = (char *)"/bin/sh";
   1042 
   1043 		/* Child: close the unused read end of the output pipe. */
   1044 		close(from_fd[0]);
   1045 
   1046 		/* Connect the write end of the output pipe to the process' output streams. */
   1047 		if (dup2(from_fd[1], STDOUT_FILENO) < 0)
   1048 			exit(3);
   1049 		if (dup2(from_fd[1], STDERR_FILENO) < 0)
   1050 			exit(4);
   1051 
   1052 		/* If the parent sends text, connect the read end of the
   1053 		 * feeding pipe to the child's input stream. */
   1054 		if (should_pipe) {
   1055 			if (dup2(to_fd[0], STDIN_FILENO) < 0)
   1056 				exit(5);
   1057 			close(from_fd[1]);
   1058 			close(to_fd[1]);
   1059 		}
   1060 
   1061 		/* Run the given command inside the preferred shell. */
   1062 		execl(theshell, tail(theshell), "-c", should_pipe ? &command[1] : command, NULL);
   1063 
   1064 		/* If the exec call returns, there was an error. */
   1065 		exit(6);
   1066 	}
   1067 
   1068 	/* Parent: close the unused write end of the pipe. */
   1069 	close(from_fd[1]);
   1070 
   1071 	if (pid_of_command == -1) {
   1072 		statusline(ALERT, _("Could not fork: %s"), strerror(errno));
   1073 		close(from_fd[0]);
   1074 		return;
   1075 	}
   1076 
   1077 	statusbar(_("Executing..."));
   1078 
   1079 	/* If the command starts with "|", pipe buffer or region to the command. */
   1080 	if (should_pipe) {
   1081 		linestruct *was_cutbuffer = cutbuffer;
   1082 		bool whole_buffer = FALSE;
   1083 
   1084 		cutbuffer = NULL;
   1085 
   1086 #ifdef ENABLE_MULTIBUFFER
   1087 		if (ISSET(MULTIBUFFER)) {
   1088 			openfile = openfile->prev;
   1089 			if (openfile->mark)
   1090 				copy_marked_region();
   1091 			else
   1092 				whole_buffer = TRUE;
   1093 		} else
   1094 #endif
   1095 		{
   1096 			/* TRANSLATORS: This one goes with Undid/Redid messages. */
   1097 			add_undo(COUPLE_BEGIN, N_("filtering"));
   1098 			if (openfile->mark == NULL) {
   1099 				openfile->current = openfile->filetop;
   1100 				openfile->current_x = 0;
   1101 			}
   1102 			add_undo(CUT, NULL);
   1103 			do_snip(openfile->mark != NULL, openfile->mark == NULL, FALSE);
   1104 			if (openfile->filetop->next == NULL)
   1105 				openfile->filetop->has_anchor = FALSE;
   1106 			update_undo(CUT);
   1107 		}
   1108 
   1109 		/* Create a separate process for piping the data to the command. */
   1110 		if ((pid_of_sender = fork()) == 0) {
   1111 			send_data(whole_buffer ? openfile->filetop : cutbuffer, to_fd[1]);
   1112 			exit(0);
   1113 		}
   1114 
   1115 		if (pid_of_sender == -1)
   1116 			statusline(ALERT, _("Could not fork: %s"), strerror(errno));
   1117 
   1118 		close(to_fd[0]);
   1119 		close(to_fd[1]);
   1120 
   1121 #ifdef ENABLE_MULTIBUFFER
   1122 		if (ISSET(MULTIBUFFER))
   1123 			openfile = openfile->next;
   1124 #endif
   1125 		free_lines(cutbuffer);
   1126 		cutbuffer = was_cutbuffer;
   1127 	}
   1128 
   1129 	/* Re-enable interpretation of the special control keys so that we get
   1130 	 * SIGINT when Ctrl-C is pressed. */
   1131 	enable_kb_interrupt();
   1132 
   1133 	/* Set up a signal handler so that ^C will terminate the forked process. */
   1134 	newaction.sa_handler = cancel_the_command;
   1135 	newaction.sa_flags = 0;
   1136 	sigaction(SIGINT, &newaction, &oldaction);
   1137 
   1138 	stream = fdopen(from_fd[0], "rb");
   1139 	if (stream == NULL)
   1140 		statusline(ALERT, _("Failed to open pipe: %s"), strerror(errno));
   1141 	else
   1142 		read_file(stream, 0, "pipe", TRUE);
   1143 
   1144 	if (should_pipe && !ISSET(MULTIBUFFER)) {
   1145 		if (was_lineno)
   1146 			goto_line_posx(was_lineno, 0);
   1147 		add_undo(COUPLE_END, N_("filtering"));
   1148 	}
   1149 
   1150 	/* Wait for the external command (and possibly data sender) to terminate. */
   1151 	waitpid(pid_of_command, &command_status, 0);
   1152 	if (should_pipe && pid_of_sender > 0)
   1153 		waitpid(pid_of_sender, &sender_status, 0);
   1154 
   1155 	/* If the command failed, show what the shell reported. */
   1156 	if (WIFEXITED(command_status) == 0 || WEXITSTATUS(command_status))
   1157 		statusline(ALERT, WIFSIGNALED(command_status) ? _("Cancelled") :
   1158 							_("Error: %s"), openfile->current->prev &&
   1159 							strstr(openfile->current->prev->data, ": ") ?
   1160 							strstr(openfile->current->prev->data, ": ") + 2 : "---");
   1161 	else if (should_pipe && pid_of_sender > 0 &&
   1162 				(WIFEXITED(sender_status) == 0 || WEXITSTATUS(sender_status)))
   1163 		statusline(ALERT, _("Piping failed"));
   1164 
   1165 	/* If there was an error, undo and discard what the command did. */
   1166 	if (lastmessage == ALERT) {
   1167 		do_undo();
   1168 		discard_until(openfile->current_undo);
   1169 	}
   1170 
   1171 	/* Restore the original handler for SIGINT. */
   1172 	sigaction(SIGINT, &oldaction, NULL);
   1173 
   1174 	/* Restore the terminal to its desired state, and disable
   1175 	 * interpretation of the special control keys again. */
   1176 	terminal_init();
   1177 #endif
   1178 }
   1179 #endif /* NANO_TINY */
   1180 
   1181 /* Insert a file into the current buffer (or into a new buffer).  But when
   1182  * execute is TRUE, run a command in the shell and insert its output into
   1183  * the buffer, or just run one of the tools listed in the help lines. */
   1184 void insert_a_file_or(bool execute)
   1185 {
   1186 	int response;
   1187 	const char *msg;
   1188 	char *given = copy_of("");
   1189 		/* The last answer the user typed at the status-bar prompt. */
   1190 #ifdef ENABLE_MULTIBUFFER
   1191 	bool was_multibuffer = ISSET(MULTIBUFFER);
   1192 #endif
   1193 
   1194 	/* Display newlines in filenames as ^J. */
   1195 	as_an_at = FALSE;
   1196 
   1197 	/* Reset the flag that is set by the Spell Checker and Linter and such. */
   1198 	ran_a_tool = FALSE;
   1199 
   1200 #ifndef NANO_TINY
   1201 	/* If something was typed at the Execute prompt without being run, restore it. */
   1202 	if (execute && *foretext)
   1203 		given = mallocstrcpy(given, foretext);
   1204 #endif
   1205 
   1206 	while (TRUE) {
   1207 #ifndef NANO_TINY
   1208 		if (execute) {
   1209 #ifdef ENABLE_MULTIBUFFER
   1210 			if (ISSET(MULTIBUFFER))
   1211 				/* TRANSLATORS: The next six messages are prompts. */
   1212 				msg = _("Command to execute in new buffer");
   1213 			else
   1214 #endif
   1215 				msg = _("Command to execute");
   1216 		} else
   1217 #endif
   1218 		{
   1219 #ifdef ENABLE_MULTIBUFFER
   1220 			if (ISSET(MULTIBUFFER))
   1221 #ifndef NANO_TINY
   1222 				if ISSET(NO_CONVERT)
   1223 					msg = _("File to read unconverted into new buffer [from %s]");
   1224 				else
   1225 #endif
   1226 					msg = _("File to read into new buffer [from %s]");
   1227 			else
   1228 #endif
   1229 #ifndef NANO_TINY
   1230 				if ISSET(NO_CONVERT)
   1231 					msg = _("File to insert unconverted [from %s]");
   1232 				else
   1233 #endif
   1234 					msg = _("File to insert [from %s]");
   1235 		}
   1236 
   1237 		present_path = mallocstrcpy(present_path, "./");
   1238 
   1239 		response = do_prompt(execute ? MEXECUTE : MINSERTFILE, given,
   1240 							execute ? &execute_history : NULL,
   1241 							edit_refresh, msg,
   1242 #ifdef ENABLE_OPERATINGDIR
   1243 							operating_dir != NULL ? operating_dir :
   1244 #endif
   1245 							"./");
   1246 
   1247 		/* If we're in multibuffer mode and the filename or command is
   1248 		 * blank, open a new buffer instead of canceling. */
   1249 		if (response == -1 || (response == -2 && !ISSET(MULTIBUFFER))) {
   1250 			statusbar(_("Cancelled"));
   1251 			break;
   1252 		} else {
   1253 			ssize_t was_current_lineno = openfile->current->lineno;
   1254 			size_t was_current_x = openfile->current_x;
   1255 #if !defined(NANO_TINY) || defined(ENABLE_BROWSER) || defined(ENABLE_MULTIBUFFER)
   1256 			functionptrtype function = func_from_key(response);
   1257 #endif
   1258 			given = mallocstrcpy(given, answer);
   1259 
   1260 			if (ran_a_tool)
   1261 				break;
   1262 
   1263 #ifdef ENABLE_MULTIBUFFER
   1264 			if (function == flip_newbuffer) {
   1265 				/* Allow toggling only when not in view mode. */
   1266 				if (!ISSET(VIEW_MODE))
   1267 					TOGGLE(MULTIBUFFER);
   1268 				else
   1269 					beep();
   1270 				continue;
   1271 			}
   1272 #endif
   1273 #ifndef NANO_TINY
   1274 			if (function == flip_convert) {
   1275 				TOGGLE(NO_CONVERT);
   1276 				continue;
   1277 			}
   1278 			if (function == flip_execute) {
   1279 				execute = !execute;
   1280 				continue;
   1281 			}
   1282 			if (function == flip_pipe) {
   1283 				add_or_remove_pipe_symbol_from_answer();
   1284 				given = mallocstrcpy(given, answer);
   1285 				continue;
   1286 			}
   1287 #endif
   1288 #ifdef ENABLE_BROWSER
   1289 			if (function == to_files) {
   1290 				char *chosen = browse_in(answer);
   1291 
   1292 				/* If no file was chosen, go back to the prompt. */
   1293 				if (chosen == NULL)
   1294 					continue;
   1295 
   1296 				free(answer);
   1297 				answer = chosen;
   1298 				response = 0;
   1299 			}
   1300 #endif
   1301 			/* If we don't have a file yet, go back to the prompt. */
   1302 			if (response != 0 && (!ISSET(MULTIBUFFER) || response != -2))
   1303 				continue;
   1304 
   1305 #ifndef NANO_TINY
   1306 			if (execute) {
   1307 #ifdef ENABLE_MULTIBUFFER
   1308 				/* When in multibuffer mode, first open a blank buffer. */
   1309 				if (ISSET(MULTIBUFFER))
   1310 					open_buffer("", TRUE);
   1311 #endif
   1312 				/* If the command is not empty, execute it and read its output
   1313 				 * into the buffer, and add the command to the history list. */
   1314 				if (*answer != '\0') {
   1315 					execute_command(answer);
   1316 #ifdef ENABLE_HISTORIES
   1317 					update_history(&execute_history, answer, PRUNE_DUPLICATE);
   1318 #endif
   1319 				}
   1320 
   1321 #ifdef ENABLE_MULTIBUFFER
   1322 				/* If this is a new buffer, put the cursor at the top. */
   1323 				if (ISSET(MULTIBUFFER)) {
   1324 					openfile->current = openfile->filetop;
   1325 					openfile->current_x = 0;
   1326 					openfile->placewewant = 0;
   1327 
   1328 					set_modified();
   1329 				}
   1330 #endif
   1331 			} else
   1332 #endif /* !NANO_TINY */
   1333 			{
   1334 				/* Make sure the specified path is tilde-expanded. */
   1335 				answer = free_and_assign(answer, real_dir_from_tilde(answer));
   1336 
   1337 				/* Read the file into a new buffer or into current buffer. */
   1338 				open_buffer(answer, ISSET(MULTIBUFFER));
   1339 			}
   1340 
   1341 #ifdef ENABLE_MULTIBUFFER
   1342 			if (ISSET(MULTIBUFFER)) {
   1343 #ifdef ENABLE_HISTORIES
   1344 				if (ISSET(POSITIONLOG)) {
   1345 #ifndef NANO_TINY
   1346 					if (!execute)
   1347 #endif
   1348 						restore_cursor_position_if_any();
   1349 				}
   1350 #endif
   1351 				/* Update title bar and color info for this new buffer. */
   1352 				prepare_for_display();
   1353 			} else
   1354 #endif /* ENABLE_MULTIBUFFER */
   1355 			{
   1356 				/* If the buffer actually changed, mark it as modified. */
   1357 				if (openfile->current->lineno != was_current_lineno ||
   1358 									openfile->current_x != was_current_x)
   1359 					set_modified();
   1360 
   1361 				refresh_needed = TRUE;
   1362 			}
   1363 
   1364 			break;
   1365 		}
   1366 	}
   1367 
   1368 	free(given);
   1369 
   1370 #ifdef ENABLE_MULTIBUFFER
   1371 	if (was_multibuffer)
   1372 		SET(MULTIBUFFER);
   1373 	else
   1374 		UNSET(MULTIBUFFER);
   1375 #endif
   1376 }
   1377 
   1378 /* If the current mode of operation allows it, go insert a file. */
   1379 void do_insertfile(void)
   1380 {
   1381 	if (!in_restricted_mode())
   1382 		insert_a_file_or(FALSE);
   1383 }
   1384 
   1385 #ifndef NANO_TINY
   1386 /* If the current mode of operation allows it, go prompt for a command. */
   1387 void do_execute(void)
   1388 {
   1389 	if (!in_restricted_mode())
   1390 		insert_a_file_or(TRUE);
   1391 }
   1392 #endif
   1393 
   1394 /* For the given bare path (or path plus filename), return the canonical,
   1395  * absolute path (plus filename) when the path exists, and NULL when not. */
   1396 char *get_full_path(const char *origpath)
   1397 {
   1398 	char *untilded, *target, *slash;
   1399 	struct stat fileinfo;
   1400 
   1401 	if (origpath == NULL)
   1402 		return NULL;
   1403 
   1404 	untilded = real_dir_from_tilde(origpath);
   1405 	target = realpath(untilded, NULL);
   1406 	slash = strrchr(untilded, '/');
   1407 
   1408 	/* If realpath() returned NULL, try without the last component,
   1409 	 * as this can be a file that does not exist yet. */
   1410 	if (!target && slash && slash[1]) {
   1411 		*slash = '\0';
   1412 		target = realpath(untilded, NULL);
   1413 
   1414 		/* Upon success, re-add the last component of the original path. */
   1415 		if (target) {
   1416 			target = nrealloc(target, strlen(target) + strlen(slash + 1) + 1);
   1417 			strcat(target, slash + 1);
   1418 		}
   1419 	}
   1420 
   1421 	/* Ensure that a non-apex directory path ends with a slash. */
   1422 	if (target && target[1] && stat(target, &fileinfo) == 0 &&
   1423 								S_ISDIR(fileinfo.st_mode)) {
   1424 		target = nrealloc(target, strlen(target) + 2);
   1425 		strcat(target, "/");
   1426 	}
   1427 
   1428 	free(untilded);
   1429 
   1430 	return target;
   1431 }
   1432 
   1433 /* Check whether the given path refers to a directory that is writable.
   1434  * Return the absolute form of the path on success, and NULL on failure. */
   1435 char *check_writable_directory(const char *path)
   1436 {
   1437 	char *full_path = get_full_path(path);
   1438 
   1439 	if (full_path == NULL)
   1440 		return NULL;
   1441 
   1442 	if (full_path[strlen(full_path) - 1] != '/' || access(full_path, W_OK) != 0) {
   1443 		free(full_path);
   1444 		return NULL;
   1445 	}
   1446 
   1447 	return full_path;
   1448 }
   1449 
   1450 /* Create, safely, a temporary file in the standard temp directory.
   1451  * On success, return the malloc()ed filename, plus the corresponding
   1452  * file stream opened in read-write mode.  On error, return NULL. */
   1453 char *safe_tempfile(FILE **stream)
   1454 {
   1455 	const char *env_dir = getenv("TMPDIR");
   1456 	char *tempdir = NULL, *tempfile_name = NULL;
   1457 	char *extension;
   1458 	int descriptor;
   1459 
   1460 	/* Get the absolute path for the first directory among $TMPDIR
   1461 	 * and P_tmpdir that is writable, otherwise use /tmp/. */
   1462 	if (env_dir != NULL)
   1463 		tempdir = check_writable_directory(env_dir);
   1464 
   1465 	if (tempdir == NULL)
   1466 		tempdir = check_writable_directory(P_tmpdir);
   1467 
   1468 	if (tempdir == NULL)
   1469 		tempdir = copy_of("/tmp/");
   1470 
   1471 	extension = strrchr(openfile->filename, '.');
   1472 
   1473 	if (!extension || strchr(extension, '/'))
   1474 		extension = openfile->filename + strlen(openfile->filename);
   1475 
   1476 	tempfile_name = nrealloc(tempdir, strlen(tempdir) + 12 + strlen(extension));
   1477 	strcat(tempfile_name, "nano.XXXXXX");
   1478 	strcat(tempfile_name, extension);
   1479 
   1480 	descriptor = mkstemps(tempfile_name, strlen(extension));
   1481 
   1482 	*stream = (descriptor > 0) ? fdopen(descriptor, "r+b") : NULL;
   1483 
   1484 	if (*stream == NULL) {
   1485 		if (descriptor > 0)
   1486 			close(descriptor);
   1487 		free(tempfile_name);
   1488 		return NULL;
   1489 	}
   1490 
   1491 	return tempfile_name;
   1492 }
   1493 
   1494 #ifdef ENABLE_OPERATINGDIR
   1495 /* Change to the specified operating directory, when it's valid. */
   1496 void init_operating_dir(void)
   1497 {
   1498 	char *target = get_full_path(operating_dir);
   1499 
   1500 	/* If the operating directory is inaccessible, fail. */
   1501 	if (target == NULL || chdir(target) == -1)
   1502 		die(_("Invalid operating directory: %s\n"), operating_dir);
   1503 
   1504 	free(operating_dir);
   1505 	operating_dir = nrealloc(target, strlen(target) + 1);
   1506 }
   1507 
   1508 /* Check whether the given path is outside of the operating directory.
   1509  * Return TRUE if it is, and FALSE otherwise.  If tabbing is TRUE,
   1510  * incomplete names that can grow into matches for the operating directory
   1511  * are considered to be inside, so that tab completion will work. */
   1512 bool outside_of_confinement(const char *somepath, bool tabbing)
   1513 {
   1514 	bool is_inside, begins_to_be;
   1515 	char *fullpath;
   1516 
   1517 	/* If no operating directory is set, there is nothing to check. */
   1518 	if (operating_dir == NULL)
   1519 		return FALSE;
   1520 
   1521 	fullpath = get_full_path(somepath);
   1522 
   1523 	/* When we can't get an absolute path, it means some directory in the path
   1524 	 * doesn't exist or is unreadable.  When not doing tab completion, somepath
   1525 	 * is what the user typed somewhere.  We don't want to report a non-existent
   1526 	 * directory as being outside the operating directory, so we return FALSE.
   1527 	 * When the user is doing tab completion, then somepath exists but is not
   1528 	 * executable.  So we say it is outside the operating directory. */
   1529 	if (fullpath == NULL)
   1530 		return tabbing;
   1531 
   1532 	is_inside = (strstr(fullpath, operating_dir) == fullpath);
   1533 	begins_to_be = (tabbing && strstr(operating_dir, fullpath) == operating_dir);
   1534 
   1535 	free(fullpath);
   1536 
   1537 	return (!is_inside && !begins_to_be);
   1538 }
   1539 #endif
   1540 
   1541 #ifndef NANO_TINY
   1542 /* Transform the specified backup directory to an absolute path,
   1543  * and verify that it is usable. */
   1544 void init_backup_dir(void)
   1545 {
   1546 	char *target = get_full_path(backup_dir);
   1547 
   1548 	/* If we can't get an absolute path (which means it doesn't exist or
   1549 	 * isn't accessible), or it's not a directory, fail. */
   1550 	if (target == NULL || target[strlen(target) - 1] != '/')
   1551 		die(_("Invalid backup directory: %s\n"), backup_dir);
   1552 
   1553 	free(backup_dir);
   1554 	backup_dir = nrealloc(target, strlen(target) + 1);
   1555 }
   1556 #endif
   1557 
   1558 /* Read all data from `inn`, and write it to `out`.  File `inn` must be open
   1559  * for reading, and `out` for writing.  Return 0 on success, a negative number
   1560  * on read error, and a positive number on write error.  File `inn` is always
   1561  * closed by this function, `out` is closed only if `close_out` is true. */
   1562 int copy_file(FILE *inn, FILE *out, bool close_out)
   1563 {
   1564 	int retval = 0;
   1565 	char buf[BUFSIZ];
   1566 	size_t charsread;
   1567 	int (*flush_out_fnc)(FILE *) = (close_out) ? fclose : fflush;
   1568 
   1569 	do {
   1570 		charsread = fread(buf, 1, BUFSIZ, inn);
   1571 		if (charsread == 0 && ferror(inn)) {
   1572 			retval = -1;
   1573 			break;
   1574 		}
   1575 		if (fwrite(buf, 1, charsread, out) < charsread) {
   1576 			retval = 2;
   1577 			break;
   1578 		}
   1579 	} while (charsread > 0);
   1580 
   1581 	if (fclose(inn) == EOF)
   1582 		retval = -3;
   1583 	if (flush_out_fnc(out) == EOF)
   1584 		retval = 4;
   1585 
   1586 	return retval;
   1587 }
   1588 
   1589 #ifndef NANO_TINY
   1590 /* Create a backup of an existing file.  If the user did not request backups,
   1591  * make a temporary one (trying first in the directory of the original file,
   1592  * then in the user's home directory).  Return TRUE if the save can proceed. */
   1593 bool make_backup_of(char *realname)
   1594 {
   1595 	FILE *original = NULL, *backup_file = NULL;
   1596 	static struct timespec filetime[2];
   1597 	int creation_flags, descriptor;
   1598 	bool second_attempt = FALSE;
   1599 	char *backupname = NULL;
   1600 	int verdict = 0;
   1601 
   1602 	/* Remember the original file's access and modification times. */
   1603 	filetime[0].tv_sec = openfile->statinfo->st_atime;
   1604 	filetime[1].tv_sec = openfile->statinfo->st_mtime;
   1605 
   1606 	statusbar(_("Making backup..."));
   1607 
   1608 	/* If no backup directory was specified, we make a simple backup
   1609 	 * by appending a tilde to the original file name.  Otherwise,
   1610 	 * we create a numbered backup in the specified directory. */
   1611 	if (backup_dir == NULL) {
   1612 		backupname = nmalloc(strlen(realname) + 2);
   1613 		sprintf(backupname, "%s~", realname);
   1614 	} else {
   1615 		char *thename = get_full_path(realname);
   1616 
   1617 		/* If we have a valid absolute path, replace each slash
   1618 		 * in this full path with an exclamation mark.  Otherwise,
   1619 		 * just use the file-name portion of the given path. */
   1620 		if (thename) {
   1621 			for (int i = 0; thename[i] != '\0'; i++)
   1622 				if (thename[i] == '/')
   1623 					thename[i] = '!';
   1624 		} else
   1625 			thename = copy_of(tail(realname));
   1626 
   1627 		backupname = nmalloc(strlen(backup_dir) + strlen(thename) + 1);
   1628 		sprintf(backupname, "%s%s", backup_dir, thename);
   1629 		free(thename);
   1630 
   1631 		thename = get_next_filename(backupname, "~");
   1632 		free(backupname);
   1633 		backupname = thename;
   1634 
   1635 		/* If all numbered backup names are taken, the user must
   1636 		 * be fond of backups.  Thus, without one, do not go on. */
   1637 		if (*backupname == '\0') {
   1638 			statusline(ALERT, _("Too many existing backup files"));
   1639 			free(backupname);
   1640 			return FALSE;
   1641 		}
   1642 	}
   1643 
   1644 	/* Now first try to delete an existing backup file. */
   1645 	if (unlink(backupname) < 0 && errno != ENOENT && !ISSET(INSECURE_BACKUP))
   1646 		goto problem;
   1647 
   1648 	creation_flags = O_WRONLY|O_CREAT|(ISSET(INSECURE_BACKUP) ? O_TRUNC : O_EXCL);
   1649 
   1650 	/* Create the backup file (or truncate the existing one). */
   1651 	descriptor = open(backupname, creation_flags, S_IRUSR|S_IWUSR);
   1652 
   1653   retry:
   1654 	if (descriptor >= 0)
   1655 		backup_file = fdopen(descriptor, "wb");
   1656 
   1657 	if (backup_file == NULL)
   1658 		goto problem;
   1659 
   1660 #ifdef HAVE_FCHOWN
   1661 	/* Try to change owner and group to those of the original file;
   1662 	 * ignore permission errors, as a normal user cannot change the owner. */
   1663 	if (fchown(descriptor, openfile->statinfo->st_uid,
   1664 							openfile->statinfo->st_gid) < 0 && errno != EPERM) {
   1665 		fclose(backup_file);
   1666 		goto problem;
   1667 	}
   1668 #endif
   1669 #ifdef HAVE_FCHMOD
   1670 	/* Set the backup's permissions to those of the original file.
   1671 	 * It is not a security issue if this fails, as we have created
   1672 	 * the file with just read and write permission for the owner. */
   1673 	if (fchmod(descriptor, openfile->statinfo->st_mode) < 0 && errno != EPERM) {
   1674 		fclose(backup_file);
   1675 		goto problem;
   1676 	}
   1677 #endif
   1678 
   1679 	original = fopen(realname, "rb");
   1680 
   1681 	/* If opening succeeded, copy the existing file to the backup. */
   1682 	if (original != NULL)
   1683 		verdict = copy_file(original, backup_file, FALSE);
   1684 
   1685 	if (original == NULL || verdict < 0) {
   1686 		warn_and_briefly_pause(_("Cannot read original file"));
   1687 		fclose(backup_file);
   1688 		goto failure;
   1689 	} else if (verdict > 0) {
   1690 		fclose(backup_file);
   1691 		goto problem;
   1692 	}
   1693 
   1694 	/* Since this backup is a newly created file, explicitly sync it to
   1695 	 * permanent storage before starting to write out the actual file. */
   1696 	if (fflush(backup_file) != 0 || fsync(fileno(backup_file)) != 0) {
   1697 		fclose(backup_file);
   1698 		goto problem;
   1699 	}
   1700 
   1701 	/* Set the backup's timestamps to those of the original file.
   1702 	 * Failure is unimportant: saving the file apparently worked. */
   1703 	IGNORE_CALL_RESULT(futimens(descriptor, filetime));
   1704 
   1705 	if (fclose(backup_file) == 0) {
   1706 		free(backupname);
   1707 		return TRUE;
   1708 	}
   1709 
   1710   problem:
   1711 	get_homedir();
   1712 
   1713 	/* If the first attempt of copying the file failed, try again to HOME. */
   1714 	if (!second_attempt && homedir) {
   1715 		unlink(backupname);
   1716 		free(backupname);
   1717 
   1718 		warn_and_briefly_pause(_("Cannot make regular backup"));
   1719 		warn_and_briefly_pause(_("Trying again in your home directory"));
   1720 		currmenu = MMOST;
   1721 
   1722 		backupname = nmalloc(strlen(homedir) + strlen(tail(realname)) + 9);
   1723 		sprintf(backupname, "%s/%s~XXXXXX", homedir, tail(realname));
   1724 
   1725 		descriptor = mkstemp(backupname);
   1726 		backup_file = NULL;
   1727 
   1728 		second_attempt = TRUE;
   1729 		goto retry;
   1730 	} else
   1731 		warn_and_briefly_pause(_("Cannot make backup"));
   1732 
   1733   failure:
   1734 	warn_and_briefly_pause(strerror(errno));
   1735 	currmenu = MMOST;
   1736 	free(backupname);
   1737 
   1738 	/* If both attempts failed, and it isn't because of lack of disk space,
   1739 	 * ask the user what to do, because if something goes wrong during the
   1740 	 * save of the file itself, its contents may be lost. */
   1741 	/* TRANSLATORS: Try to keep this message at most 76 characters. */
   1742 	if (errno != ENOSPC && ask_user(YESORNO, _("Cannot make backup; "
   1743 							"continue and save actual file? ")) == YES)
   1744 		return TRUE;
   1745 
   1746 	/* TRANSLATORS: The %s is the reason of failure. */
   1747 	statusline(HUSH, _("Cannot make backup: %s"), strerror(errno));
   1748 	return FALSE;
   1749 }
   1750 #endif /* !NANO_TINY */
   1751 
   1752 /* Write the current buffer to disk.  If thefile isn't NULL, we write to a
   1753  * temporary file that is already open.  If normal is FALSE (for a spellcheck
   1754  * or an emergency save, for example), we don't make a backup and don't give
   1755  * feedback.  If method is APPEND or PREPEND, it means we will be appending
   1756  * or prepending instead of overwriting the given file.  If annotate is TRUE
   1757  * and when writing a normal file, we set the current filename and stat info.
   1758  * Return TRUE on success, and FALSE otherwise. */
   1759 bool write_file(const char *name, FILE *thefile, bool normal,
   1760 		kind_of_writing_type method, bool annotate)
   1761 {
   1762 #ifndef NANO_TINY
   1763 	bool is_existing_file;
   1764 		/* Becomes TRUE when the file is non-temporary and exists. */
   1765 	struct stat fileinfo;
   1766 		/* The status fields filled in by statting the file. */
   1767 #endif
   1768 	char *realname = real_dir_from_tilde(name);
   1769 		/* The filename after tilde expansion. */
   1770 	int descriptor = 0;
   1771 		/* The descriptor that gets assigned when opening the file. */
   1772 	char *tempname = NULL;
   1773 		/* The name of the temporary file we use when prepending. */
   1774 	linestruct *line = openfile->filetop;
   1775 		/* An iterator for moving through the lines of the buffer. */
   1776 	size_t lineswritten = 0;
   1777 		/* The number of lines written, for feedback on the status bar. */
   1778 
   1779 #ifdef ENABLE_OPERATINGDIR
   1780 	/* If we're writing a temporary file, we're probably going outside
   1781 	 * the operating directory, so skip the operating directory test. */
   1782 	if (normal && outside_of_confinement(realname, FALSE)) {
   1783 		statusline(ALERT, _("Can't write outside of %s"), operating_dir);
   1784 		goto cleanup_and_exit;
   1785 	}
   1786 #endif
   1787 #ifndef NANO_TINY
   1788 	/* Check whether the file (at the end of the symlink) exists. */
   1789 	is_existing_file = normal && (stat(realname, &fileinfo) != -1);
   1790 
   1791 	/* If we haven't statted this file before (say, the user just specified
   1792 	 * it interactively), stat and save the value now, or else we will chase
   1793 	 * null pointers when we do modtime checks and such during backup. */
   1794 	if (openfile->statinfo == NULL && is_existing_file)
   1795 		stat_with_alloc(realname, &openfile->statinfo);
   1796 
   1797 	/* When the user requested a backup, we do this only if the file exists and
   1798 	 * isn't temporary AND the file has not been modified by someone else since
   1799 	 * we opened it (or we are appending/prepending or writing a selection). */
   1800 	if (ISSET(MAKE_BACKUP) && is_existing_file && !S_ISFIFO(fileinfo.st_mode) &&
   1801 						openfile->statinfo &&
   1802 						(openfile->statinfo->st_mtime == fileinfo.st_mtime ||
   1803 						method != OVERWRITE || openfile->mark)) {
   1804 		if (!make_backup_of(realname))
   1805 			goto cleanup_and_exit;
   1806 	}
   1807 
   1808 	/* When prepending, first copy the existing file to a temporary file. */
   1809 	if (method == PREPEND) {
   1810 		FILE *source = NULL;
   1811 		FILE *target = NULL;
   1812 		int verdict;
   1813 
   1814 		if (is_existing_file && S_ISFIFO(fileinfo.st_mode)) {
   1815 			statusline(ALERT, _("Error writing %s: %s"), realname, "FIFO");
   1816 			goto cleanup_and_exit;
   1817 		}
   1818 
   1819 		source = fopen(realname, "rb");
   1820 
   1821 		if (source == NULL) {
   1822 			statusline(ALERT, _("Error reading %s: %s"), realname, strerror(errno));
   1823 			goto cleanup_and_exit;
   1824 		}
   1825 
   1826 		tempname = safe_tempfile(&target);
   1827 
   1828 		if (tempname == NULL) {
   1829 			statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
   1830 			fclose(source);
   1831 			goto cleanup_and_exit;
   1832 		}
   1833 
   1834 		verdict = copy_file(source, target, TRUE);
   1835 
   1836 		if (verdict < 0) {
   1837 			statusline(ALERT, _("Error reading %s: %s"), realname, strerror(errno));
   1838 			unlink(tempname);
   1839 			goto cleanup_and_exit;
   1840 		} else if (verdict > 0) {
   1841 			statusline(ALERT, _("Error writing temp file: %s"), strerror(errno));
   1842 			unlink(tempname);
   1843 			goto cleanup_and_exit;
   1844 		}
   1845 	}
   1846 
   1847 	if (is_existing_file && S_ISFIFO(fileinfo.st_mode))
   1848 		statusbar(_("Writing to FIFO..."));
   1849 #endif /* !NANO_TINY */
   1850 
   1851 	/* When it's not a temporary file, this is where we open or create it.
   1852 	 * For an emergency file, access is restricted to just the owner. */
   1853 	if (thefile == NULL) {
   1854 		mode_t permissions = (normal ? RW_FOR_ALL : S_IRUSR|S_IWUSR);
   1855 
   1856 #ifndef NANO_TINY
   1857 		block_sigwinch(TRUE);
   1858 		if (normal)
   1859 			install_handler_for_Ctrl_C();
   1860 #endif
   1861 
   1862 		/* Now open the file.  Use O_EXCL for an emergency file. */
   1863 		descriptor = open(realname, O_WRONLY | O_CREAT | ((method == APPEND) ?
   1864 					O_APPEND : (normal ? O_TRUNC : O_EXCL)), permissions);
   1865 
   1866 #ifndef NANO_TINY
   1867 		if (normal)
   1868 			restore_handler_for_Ctrl_C();
   1869 		block_sigwinch(FALSE);
   1870 #endif
   1871 
   1872 		/* If we couldn't open the file, give up. */
   1873 		if (descriptor < 0) {
   1874 			if (errno == EINTR || errno == 0)
   1875 				statusline(ALERT, _("Interrupted"));
   1876 			else
   1877 				statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1878 #ifndef NANO_TINY
   1879 			if (tempname != NULL)
   1880 				unlink(tempname);
   1881 #endif
   1882 			goto cleanup_and_exit;
   1883 		}
   1884 
   1885 		thefile = fdopen(descriptor, (method == APPEND) ? "ab" : "wb");
   1886 
   1887 		if (thefile == NULL) {
   1888 			statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1889 			close(descriptor);
   1890 			goto cleanup_and_exit;
   1891 		}
   1892 	}
   1893 
   1894 	if (normal)
   1895 		statusbar(_("Writing..."));
   1896 
   1897 	while (TRUE) {
   1898 		size_t data_len, wrote;
   1899 
   1900 		/* Decode LFs as the NULs that they are, before writing to disk. */
   1901 		data_len = recode_LF_to_NUL(line->data);
   1902 
   1903 		wrote = fwrite(line->data, 1, data_len, thefile);
   1904 
   1905 		/* Re-encode any embedded NULs as LFs. */
   1906 		recode_NUL_to_LF(line->data, data_len);
   1907 
   1908 		if (wrote < data_len) {
   1909 			statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1910 			fclose(thefile);
   1911 			goto cleanup_and_exit;
   1912 		}
   1913 
   1914 		/* If we've reached the last line of the buffer, don't write a newline
   1915 		 * character after it.  If this last line is empty, it means zero bytes
   1916 		 * are written for it, and we don't count it in the number of lines. */
   1917 		if (line->next == NULL) {
   1918 			if (line->data[0] != '\0')
   1919 				lineswritten++;
   1920 			break;
   1921 		}
   1922 
   1923 #ifndef NANO_TINY
   1924 		if (openfile->fmt == DOS_FILE || openfile->fmt == MAC_FILE) {
   1925 			if (putc('\r', thefile) == EOF) {
   1926 				statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1927 				fclose(thefile);
   1928 				goto cleanup_and_exit;
   1929 			}
   1930 		}
   1931 
   1932 		if (openfile->fmt != MAC_FILE)
   1933 #endif
   1934 			if (putc('\n', thefile) == EOF) {
   1935 				statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1936 				fclose(thefile);
   1937 				goto cleanup_and_exit;
   1938 			}
   1939 
   1940 		line = line->next;
   1941 		lineswritten++;
   1942 	}
   1943 
   1944 #ifndef NANO_TINY
   1945 	/* When prepending, append the temporary file to what we wrote above. */
   1946 	if (method == PREPEND) {
   1947 		FILE *source = fopen(tempname, "rb");
   1948 		int verdict;
   1949 
   1950 		if (source == NULL) {
   1951 			statusline(ALERT, _("Error reading temp file: %s"), strerror(errno));
   1952 			fclose(thefile);
   1953 			goto cleanup_and_exit;
   1954 		}
   1955 
   1956 		verdict = copy_file(source, thefile, FALSE);
   1957 
   1958 		if (verdict < 0) {
   1959 			statusline(ALERT, _("Error reading temp file: %s"), strerror(errno));
   1960 			fclose(thefile);
   1961 			goto cleanup_and_exit;
   1962 		} else if (verdict > 0) {
   1963 			statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1964 			fclose(thefile);
   1965 			goto cleanup_and_exit;
   1966 		}
   1967 
   1968 		unlink(tempname);
   1969 	}
   1970 
   1971 	if (!is_existing_file || !S_ISFIFO(fileinfo.st_mode))
   1972 		/* Ensure the data has reached the disk before reporting it as written. */
   1973 		if (fflush(thefile) != 0 || fsync(fileno(thefile)) != 0) {
   1974 			statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1975 			fclose(thefile);
   1976 			goto cleanup_and_exit;
   1977 		}
   1978 #endif
   1979 
   1980 #if !defined(NANO_TINY) && defined(HAVE_CHMOD) && defined(HAVE_CHOWN)
   1981 	/* Change permissions and owner of an emergency save file to the values
   1982 	 * of the original file, but ignore any failure as we are in a hurry. */
   1983 	if (method == EMERGENCY && descriptor && openfile->statinfo) {
   1984 		IGNORE_CALL_RESULT(fchmod(descriptor, openfile->statinfo->st_mode));
   1985 		IGNORE_CALL_RESULT(fchown(descriptor, openfile->statinfo->st_uid,
   1986 											openfile->statinfo->st_gid));
   1987 	}
   1988 #endif
   1989 
   1990 	if (fclose(thefile) != 0) {
   1991 		statusline(ALERT, _("Error writing %s: %s"), realname, strerror(errno));
   1992 
   1993   cleanup_and_exit:
   1994 #ifndef NANO_TINY
   1995 		if (errno == ENOSPC && normal) {
   1996 			napms(3200); lastmessage = VACUUM;
   1997 			/* TRANSLATORS: This warns for data loss when the disk is full. */
   1998 			statusline(ALERT, _("File on disk has been truncated!"));
   1999 			napms(3200); lastmessage = VACUUM;
   2000 			/* TRANSLATORS: This is a suggestion to the user,
   2001 			 * where "resume" means resuming from suspension.
   2002 			 * Try to keep this at most 76 characters. */
   2003 			statusline(ALERT, _("Maybe ^T^Z, make room on disk, resume, then ^S^X"));
   2004 			stat_with_alloc(realname, &openfile->statinfo);
   2005 		}
   2006 #endif
   2007 		free(tempname);
   2008 		free(realname);
   2009 		return FALSE;
   2010 	}
   2011 
   2012 	/* When having written an entire buffer, update some administrivia. */
   2013 	if (annotate && method == OVERWRITE) {
   2014 		/* If the filename was changed, write a new lockfile when needed,
   2015 		 * and check whether it means a different syntax gets used. */
   2016 		if (strcmp(openfile->filename, realname) != 0) {
   2017 #ifndef NANO_TINY
   2018 			if (openfile->lock_filename != NULL) {
   2019 				delete_lockfile(openfile->lock_filename);
   2020 				free(openfile->lock_filename);
   2021 			}
   2022 
   2023 			if (ISSET(LOCKING))
   2024 				openfile->lock_filename = do_lockfile(realname, FALSE);
   2025 #endif
   2026 			openfile->filename = mallocstrcpy(openfile->filename, realname);
   2027 #ifdef ENABLE_COLOR
   2028 			const char *oldname, *newname;
   2029 
   2030 			oldname = openfile->syntax ? openfile->syntax->name : "";
   2031 			find_and_prime_applicable_syntax();
   2032 			newname = openfile->syntax ? openfile->syntax->name : "";
   2033 
   2034 			/* If the syntax changed, discard and recompute the multidata. */
   2035 			if (strcmp(oldname, newname) != 0) {
   2036 				for (line = openfile->filetop; line != NULL; line = line->next) {
   2037 					free(line->multidata);
   2038 					line->multidata = NULL;
   2039 				}
   2040 
   2041 				precalc_multicolorinfo();
   2042 				have_palette = FALSE;
   2043 				refresh_needed = TRUE;
   2044 			}
   2045 #endif
   2046 		}
   2047 #ifndef NANO_TINY
   2048 		/* Get or update the stat info to reflect the current state. */
   2049 		stat_with_alloc(realname, &openfile->statinfo);
   2050 
   2051 		/* Record at which point in the undo stack the buffer was saved. */
   2052 		openfile->last_saved = openfile->current_undo;
   2053 		openfile->last_action = OTHER;
   2054 #endif
   2055 		openfile->modified = FALSE;
   2056 		titlebar(NULL);
   2057 	}
   2058 
   2059 #ifndef NANO_TINY
   2060 	if (ISSET(MINIBAR) && !ISSET(ZERO) && LINES > 1 && annotate)
   2061 		report_size = TRUE;
   2062 	else
   2063 #endif
   2064 	if (normal)
   2065 		statusline(REMARK, P_("Wrote %zu line", "Wrote %zu lines",
   2066 								lineswritten), lineswritten);
   2067 
   2068 	free(tempname);
   2069 	free(realname);
   2070 
   2071 	return TRUE;
   2072 }
   2073 
   2074 #ifndef NANO_TINY
   2075 /* Write the marked region of the current buffer out to disk.
   2076  * Return TRUE on success and FALSE on error. */
   2077 bool write_region_to_file(const char *name, FILE *stream, bool normal,
   2078 		kind_of_writing_type method)
   2079 {
   2080 	linestruct *birthline, *topline, *botline, *stopper, *afterline;
   2081 	char *was_datastart, saved_byte;
   2082 	size_t top_x, bot_x;
   2083 	bool retval;
   2084 
   2085 	get_region(&topline, &top_x, &botline, &bot_x);
   2086 
   2087 	/* When needed, prepare a magic end line for the region. */
   2088 	if (normal && bot_x > 0 && !ISSET(NO_NEWLINES)) {
   2089 		stopper = make_new_node(botline);
   2090 		stopper->data = copy_of("");
   2091 	} else
   2092 		stopper = NULL;
   2093 
   2094 	/* Make the marked area look like a separate buffer. */
   2095 	afterline = botline->next;
   2096 	botline->next = stopper;
   2097 	saved_byte = botline->data[bot_x];
   2098 	botline->data[bot_x] = '\0';
   2099 	was_datastart = topline->data;
   2100 	topline->data += top_x;
   2101 	birthline = openfile->filetop;
   2102 	openfile->filetop = topline;
   2103 
   2104 	retval = write_file(name, stream, normal, method, NONOTES);
   2105 
   2106 	/* Restore the proper state of the buffer. */
   2107 	openfile->filetop = birthline;
   2108 	topline->data = was_datastart;
   2109 	botline->data[bot_x] = saved_byte;
   2110 	botline->next = afterline;
   2111 
   2112 	if (stopper)
   2113 		delete_node(stopper);
   2114 
   2115 	return retval;
   2116 }
   2117 #endif /* !NANO_TINY */
   2118 
   2119 /* Write the current buffer (or marked region) to disk.  If exiting is TRUE,
   2120  * write the entire buffer regardless of whether the mark is on.  Do not ask
   2121  * for a name when withprompt is FALSE (nor when doing save-on-exit and the
   2122  * buffer already has a name).  Return 0 on error, 1 on success, and 2 when
   2123  * the buffer is to be discarded. */
   2124 int write_it_out(bool exiting, bool withprompt)
   2125 {
   2126 	char *given;
   2127 		/* The filename we offer, or what the user typed so far. */
   2128 	bool maychange = (openfile->filename[0] == '\0');
   2129 		/* Whether it's okay to save the buffer under a different name. */
   2130 	kind_of_writing_type method = OVERWRITE;
   2131 #ifdef ENABLE_EXTRA
   2132 	static bool did_credits = FALSE;
   2133 #endif
   2134 
   2135 	/* Display newlines in filenames as ^J. */
   2136 	as_an_at = FALSE;
   2137 
   2138 #ifndef NANO_TINY
   2139 	given = copy_of((openfile->mark && !exiting) ? "" : openfile->filename);
   2140 #else
   2141 	given = copy_of(openfile->filename);
   2142 #endif
   2143 
   2144 	while (TRUE) {
   2145 		functionptrtype function;
   2146 		const char *msg;
   2147 		int response = 0;
   2148 		int choice = NO;
   2149 #ifndef NANO_TINY
   2150 		const char *formatstr = (openfile->fmt == DOS_FILE) ? _(" [DOS Format]") :
   2151 						(openfile->fmt == MAC_FILE) ? _(" [Mac Format]") : "";
   2152 		const char *backupstr = ISSET(MAKE_BACKUP) ? _(" [Backup]") : "";
   2153 
   2154 		/* When the mark is on, offer to write the selection to disk, but
   2155 		 * not when in restricted mode, because it would allow writing to
   2156 		 * a file not specified on the command line. */
   2157 		if (openfile->mark && !exiting && !ISSET(RESTRICTED))
   2158 			/* TRANSLATORS: The next six strings are prompts. */
   2159 			msg = (method == PREPEND) ? _("Prepend Selection to File") :
   2160 						(method == APPEND) ? _("Append Selection to File") :
   2161 						_("Write Selection to File");
   2162 		else if (method != OVERWRITE)
   2163 			/* TRANSLATORS: Next three prompts are analogous to the above three. */
   2164 			msg = (method == PREPEND) ? _("Prepend to File") : _("Append to File");
   2165 		else
   2166 #endif
   2167 			msg = _("Write to File");
   2168 
   2169 		present_path = mallocstrcpy(present_path, "./");
   2170 
   2171 		/* When we shouldn't prompt, use the existing filename.
   2172 		 * Otherwise, ask for (confirmation of) the filename. */
   2173 		if ((!withprompt || (ISSET(SAVE_ON_EXIT) && exiting)) &&
   2174 								openfile->filename[0] != '\0')
   2175 			answer = mallocstrcpy(answer, openfile->filename);
   2176 		else
   2177 			response = do_prompt(MWRITEFILE, given, NULL,
   2178 						edit_refresh, "%s%s%s", msg,
   2179 #ifndef NANO_TINY
   2180 						formatstr, backupstr
   2181 #else
   2182 						"", ""
   2183 #endif
   2184 						);
   2185 
   2186 		if (response < 0) {
   2187 			statusbar(_("Cancelled"));
   2188 			free(given);
   2189 			return 0;
   2190 		}
   2191 
   2192 		function = func_from_key(response);
   2193 
   2194 		/* Upon request, abandon the buffer. */
   2195 		if (function == discard_buffer) {
   2196 			final_status = 2;  /* ^O^Q makes nano exit with an error. */
   2197 			free(given);
   2198 			return 2;
   2199 		}
   2200 
   2201 		given = mallocstrcpy(given, answer);
   2202 
   2203 #ifdef ENABLE_BROWSER
   2204 		if (function == to_files && !ISSET(RESTRICTED)) {
   2205 			char *chosen = browse_in(answer);
   2206 
   2207 			if (chosen == NULL)
   2208 				continue;
   2209 
   2210 			free(answer);
   2211 			answer = chosen;
   2212 		} else
   2213 #endif
   2214 #ifndef NANO_TINY
   2215 		if (function == dos_format) {
   2216 			openfile->fmt = (openfile->fmt == DOS_FILE) ? NIX_FILE : DOS_FILE;
   2217 			continue;
   2218 		} else if (function == mac_format) {
   2219 			openfile->fmt = (openfile->fmt == MAC_FILE) ? NIX_FILE : MAC_FILE;
   2220 			continue;
   2221 		} else if (function == back_it_up && !ISSET(RESTRICTED)) {
   2222 			TOGGLE(MAKE_BACKUP);
   2223 			continue;
   2224 		} else if ((function == prepend_it || function == append_it) && !ISSET(RESTRICTED)) {
   2225 			if (function == prepend_it)
   2226 				method = (method == PREPEND) ? OVERWRITE : PREPEND;
   2227 			else
   2228 				method = (method == APPEND) ? OVERWRITE : APPEND;
   2229 			if (strcmp(answer, openfile->filename) == 0)
   2230 				given[0] = '\0';
   2231 			continue;
   2232 		} else
   2233 #endif
   2234 		if (function == do_help)
   2235 			continue;
   2236 
   2237 #ifdef ENABLE_EXTRA
   2238 		/* If the user pressed Ctrl-X in the edit window, and answered "Y" at
   2239 		 * the "Save modified buffer?" prompt, and entered "zzy" as filename,
   2240 		 * and this is the first time around, show an Easter egg. */
   2241 		if (exiting && !ISSET(SAVE_ON_EXIT) && openfile->filename[0] == '\0' &&
   2242 						strcmp(answer, "zzy") == 0 && !did_credits) {
   2243 			if (LINES > 5 && COLS > 31) {
   2244 				do_credits();
   2245 				did_credits = TRUE;
   2246 			} else
   2247 				/* TRANSLATORS: Concisely say the screen is too small. */
   2248 				statusline(AHEM, _("Too tiny"));
   2249 
   2250 			free(given);
   2251 			return 0;
   2252 		}
   2253 #endif
   2254 
   2255 		if (method == OVERWRITE) {
   2256 			bool name_exists, do_warning;
   2257 			char *full_answer, *full_filename;
   2258 			struct stat fileinfo;
   2259 
   2260 			full_answer = get_full_path(answer);
   2261 			full_filename = get_full_path(openfile->filename);
   2262 			name_exists = (stat((full_answer == NULL) ?
   2263 								answer : full_answer, &fileinfo) != -1);
   2264 
   2265 			if (openfile->filename[0] == '\0')
   2266 				do_warning = name_exists;
   2267 			else
   2268 				do_warning = (strcmp((full_answer == NULL) ?
   2269 								answer : full_answer, (full_filename == NULL) ?
   2270 								openfile->filename : full_filename) != 0);
   2271 
   2272 			free(full_filename);
   2273 			free(full_answer);
   2274 
   2275 			if (do_warning) {
   2276 				/* When in restricted mode, we aren't allowed to overwrite
   2277 				 * an existing file with the current buffer, nor to change
   2278 				 * the name of the current buffer if it already has one. */
   2279 				if (ISSET(RESTRICTED)) {
   2280 					/* TRANSLATORS: Restricted mode forbids overwriting. */
   2281 					warn_and_briefly_pause(_("File exists -- cannot overwrite"));
   2282 					continue;
   2283 				}
   2284 
   2285 				if (!maychange) {
   2286 #ifndef NANO_TINY
   2287 					if (exiting || !openfile->mark)
   2288 #endif
   2289 					{
   2290 						if (ask_user(YESORNO, _("Save file under "
   2291 												"DIFFERENT NAME? ")) != YES)
   2292 							continue;
   2293 						maychange = TRUE;
   2294 					}
   2295 				}
   2296 
   2297 				if (name_exists) {
   2298 					char *question = _("File \"%s\" exists; OVERWRITE? ");
   2299 					char *name = crop_to_fit(answer, COLS - breadth(question) + 1);
   2300 					char *message = nmalloc(strlen(question) + strlen(name) + 1);
   2301 
   2302 					sprintf(message, question, name);
   2303 
   2304 					choice = ask_user(YESORNO, message);
   2305 
   2306 					free(message);
   2307 					free(name);
   2308 
   2309 					if (choice != YES)
   2310 						continue;
   2311 				}
   2312 			}
   2313 #ifndef NANO_TINY
   2314 			/* Complain if the file exists, the name hasn't changed,
   2315 			 * and the stat information we had before does not match
   2316 			 * what we have now. */
   2317 			else if (name_exists && openfile->statinfo &&
   2318 						(openfile->statinfo->st_mtime < fileinfo.st_mtime ||
   2319 						openfile->statinfo->st_dev != fileinfo.st_dev ||
   2320 						openfile->statinfo->st_ino != fileinfo.st_ino)) {
   2321 
   2322 				warn_and_briefly_pause(_("File on disk has changed"));
   2323 
   2324 				/* TRANSLATORS: Try to keep this at most 76 characters. */
   2325 				choice = ask_user(YESORNO, _("File was modified "
   2326 								"since you opened it; continue saving? "));
   2327 				wipe_statusbar();
   2328 
   2329 				/* When in tool mode and not called by 'savefile',
   2330 				 * overwrite the file right here when requested. */
   2331 				if (ISSET(SAVE_ON_EXIT) && withprompt) {
   2332 					free(given);
   2333 					if (choice == YES)
   2334 						return write_file(openfile->filename, NULL,
   2335 											NORMAL, OVERWRITE, NONOTES);
   2336 					else if (choice == NO)  /* Discard buffer */
   2337 						return 2;
   2338 					else
   2339 						return 0;
   2340 				} else if (choice == CANCEL && exiting) {
   2341 					continue;
   2342 				} else if (choice != YES) {
   2343 					free(given);
   2344 					return 1;
   2345 				}
   2346 			}
   2347 #endif
   2348 		}
   2349 
   2350 		free(given);
   2351 		break;
   2352 	}
   2353 
   2354 	/* When the mark is on (and we've prompted for a name and we're
   2355 	 * not exiting and we're not in restricted mode), then write out
   2356 	 * the marked region; otherwise, write out the whole buffer. */
   2357 #ifndef NANO_TINY
   2358 	if (openfile->mark && withprompt && !exiting && !ISSET(RESTRICTED))
   2359 		return write_region_to_file(answer, NULL, NORMAL, method);
   2360 	else
   2361 #endif
   2362 		return write_file(answer, NULL, NORMAL, method, ANNOTATE);
   2363 }
   2364 
   2365 /* Write the current buffer to disk, or discard it. */
   2366 void do_writeout(void)
   2367 {
   2368 	/* If the user chose to discard the buffer, close it. */
   2369 	if (write_it_out(FALSE, TRUE) == 2)
   2370 		close_and_go();
   2371 }
   2372 
   2373 /* If it has a name, write the current buffer to disk without prompting. */
   2374 void do_savefile(void)
   2375 {
   2376 	if (write_it_out(FALSE, FALSE) == 2)
   2377 		close_and_go();
   2378 }
   2379 
   2380 /* Convert the tilde notation when the given path begins with ~/ or ~user/.
   2381  * Return an allocated string containing the expanded path. */
   2382 char *real_dir_from_tilde(const char *path)
   2383 {
   2384 	char *tilded, *retval;
   2385 	size_t i = 1;
   2386 
   2387 	if (*path != '~')
   2388 		return copy_of(path);
   2389 
   2390 	/* Figure out how much of the string we need to compare. */
   2391 	while (path[i] != '/' && path[i] != '\0')
   2392 		i++;
   2393 
   2394 	if (i == 1) {
   2395 		get_homedir();
   2396 		tilded = copy_of(homedir);
   2397 	} else {
   2398 #ifdef HAVE_PWD_H
   2399 		const struct passwd *userdata;
   2400 
   2401 		tilded = measured_copy(path, i);
   2402 
   2403 		do {
   2404 			userdata = getpwent();
   2405 		} while (userdata && strcmp(userdata->pw_name, tilded + 1) != 0);
   2406 		endpwent();
   2407 
   2408 		if (userdata != NULL)
   2409 			tilded = mallocstrcpy(tilded, userdata->pw_dir);
   2410 #else
   2411 		tilded = copy_of("");
   2412 #endif
   2413 	}
   2414 
   2415 	retval = nmalloc(strlen(tilded) + strlen(path + i) + 1);
   2416 	sprintf(retval, "%s%s", tilded, path + i);
   2417 
   2418 	free(tilded);
   2419 
   2420 	return retval;
   2421 }
   2422 
   2423 #if defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
   2424 /* Our sort routine for file listings.  Sort alphabetically and
   2425  * case-insensitively, and sort directories before filenames. */
   2426 int diralphasort(const void *va, const void *vb)
   2427 {
   2428 	struct stat fileinfo;
   2429 	const char *a = *(const char *const *)va;
   2430 	const char *b = *(const char *const *)vb;
   2431 	bool aisdir = stat(a, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode);
   2432 	bool bisdir = stat(b, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode);
   2433 
   2434 	if (aisdir && !bisdir)
   2435 		return -1;
   2436 	if (!aisdir && bisdir)
   2437 		return 1;
   2438 
   2439 	int difference = mbstrcasecmp(a, b);
   2440 
   2441 	/* If two names are equivalent when ignoring case, compare them bytewise. */
   2442 	if (difference == 0)
   2443 		return strcmp(a, b);
   2444 	else
   2445 		return difference;
   2446 }
   2447 #endif
   2448 
   2449 #ifdef ENABLE_TABCOMP
   2450 /* Return TRUE when the given path is a directory. */
   2451 bool is_dir(const char *path)
   2452 {
   2453 	char *thepath = real_dir_from_tilde(path);
   2454 	struct stat fileinfo;
   2455 	bool retval;
   2456 
   2457 	retval = (stat(thepath, &fileinfo) != -1 && S_ISDIR(fileinfo.st_mode));
   2458 
   2459 	free(thepath);
   2460 
   2461 	return retval;
   2462 }
   2463 
   2464 /* Try to complete the given fragment of given length to a username. */
   2465 char **username_completion(const char *morsel, size_t length, size_t *num_matches)
   2466 {
   2467 	char **matches = NULL;
   2468 #ifdef HAVE_PWD_H
   2469 	const struct passwd *userdata;
   2470 
   2471 	/* Iterate through the entries in the passwd file, and
   2472 	 * add each fitting username to the list of matches. */
   2473 	while ((userdata = getpwent()) != NULL) {
   2474 		if (strncmp(userdata->pw_name, morsel + 1, length - 1) == 0) {
   2475 #ifdef ENABLE_OPERATINGDIR
   2476 			/* Skip directories that are outside of the allowed area. */
   2477 			if (outside_of_confinement(userdata->pw_dir, TRUE))
   2478 				continue;
   2479 #endif
   2480 			matches = nrealloc(matches, (*num_matches + 1) * sizeof(char *));
   2481 			matches[*num_matches] = nmalloc(strlen(userdata->pw_name) + 2);
   2482 			sprintf(matches[*num_matches], "~%s", userdata->pw_name);
   2483 			++(*num_matches);
   2484 		}
   2485 	}
   2486 
   2487 	endpwent();
   2488 #endif
   2489 
   2490 	return matches;
   2491 }
   2492 
   2493 /* The next two functions were adapted from busybox 0.46 (cmdedit.c).
   2494  * Here is the tweaked notice from that file:
   2495  *
   2496  * Termios command-line History and Editing, originally intended for NetBSD.
   2497  * Copyright (C) 1999, 2000
   2498  *      Main code:            Adam Rogoyski <rogoyski@cs.utexas.edu>
   2499  *      Etc:                  Dave Cinege <dcinege@psychosis.com>
   2500  *      Adjusted/rewritten:   Erik Andersen <andersee@debian.org>
   2501  *
   2502  * You may use this code as you wish, so long as the original author(s)
   2503  * are attributed in any redistributions of the source code.
   2504  * This code is 'as is' with no warranty.
   2505  * This code may safely be consumed by a BSD or GPL license. */
   2506 
   2507 /* Try to complete the given fragment to an existing filename. */
   2508 char **filename_completion(const char *morsel, size_t *num_matches)
   2509 {
   2510 	char *dirname = copy_of(morsel);
   2511 	char *slash, *filename;
   2512 	size_t filenamelen;
   2513 	char *fullname = NULL;
   2514 	char **matches = NULL;
   2515 	const struct dirent *entry;
   2516 	DIR *dir;
   2517 
   2518 	/* If there's a / in the name, split out filename and directory parts. */
   2519 	slash = strrchr(dirname, '/');
   2520 	if (slash != NULL) {
   2521 		char *wasdirname = dirname;
   2522 
   2523 		filename = copy_of(++slash);
   2524 		/* Cut off the filename part after the slash. */
   2525 		*slash = '\0';
   2526 		dirname = real_dir_from_tilde(dirname);
   2527 		/* A non-absolute path is relative to the current browser directory. */
   2528 		if (dirname[0] != '/') {
   2529 			dirname = nrealloc(dirname, strlen(present_path) + strlen(wasdirname) + 1);
   2530 			sprintf(dirname, "%s%s", present_path, wasdirname);
   2531 		}
   2532 		free(wasdirname);
   2533 	} else {
   2534 		filename = dirname;
   2535 		dirname = copy_of(present_path);
   2536 	}
   2537 
   2538 	dir = opendir(dirname);
   2539 
   2540 	if (dir == NULL) {
   2541 		beep();
   2542 		free(filename);
   2543 		free(dirname);
   2544 		return NULL;
   2545 	}
   2546 
   2547 	filenamelen = strlen(filename);
   2548 
   2549 	/* Iterate through the filenames in the directory,
   2550 	 * and add each fitting one to the list of matches. */
   2551 	while ((entry = readdir(dir)) != NULL) {
   2552 		if (strncmp(entry->d_name, filename, filenamelen) == 0 &&
   2553 									strcmp(entry->d_name, ".") != 0 &&
   2554 									strcmp(entry->d_name, "..") != 0) {
   2555 			fullname = nrealloc(fullname, strlen(dirname) + strlen(entry->d_name) + 1);
   2556 			sprintf(fullname, "%s%s", dirname, entry->d_name);
   2557 
   2558 #ifdef ENABLE_OPERATINGDIR
   2559 			if (outside_of_confinement(fullname, TRUE))
   2560 				continue;
   2561 #endif
   2562 			if (currmenu == MGOTODIR && !is_dir(fullname))
   2563 				continue;
   2564 
   2565 			matches = nrealloc(matches, (*num_matches + 1) * sizeof(char *));
   2566 			matches[*num_matches] = copy_of(entry->d_name);
   2567 			++(*num_matches);
   2568 		}
   2569 	}
   2570 
   2571 	closedir(dir);
   2572 	free(dirname);
   2573 	free(filename);
   2574 	free(fullname);
   2575 
   2576 	return matches;
   2577 }
   2578 
   2579 /* Do tab completion.  'place' is the position of the status-bar cursor, and
   2580  * 'refresh_func' is the function to be called to refresh the edit window. */
   2581 char *input_tab(char *morsel, size_t *place, void (*refresh_func)(void), bool *listed)
   2582 {
   2583 	size_t num_matches = 0;
   2584 	char **matches = NULL;
   2585 
   2586 	/* If the cursor is not at the end of the fragment, do nothing. */
   2587 	if (morsel[*place] != '\0') {
   2588 		beep();
   2589 		return morsel;
   2590 	}
   2591 
   2592 	/* If the fragment starts with a tilde and contains no slash,
   2593 	 * then try completing it as a username. */
   2594 	if (morsel[0] == '~' && strchr(morsel, '/') == NULL)
   2595 		matches = username_completion(morsel, *place, &num_matches);
   2596 
   2597 	/* If there are no matches yet, try matching against filenames. */
   2598 	if (matches == NULL)
   2599 		matches = filename_completion(morsel, &num_matches);
   2600 
   2601 	/* If possible completions were listed before but none will be listed now... */
   2602 	if (*listed && num_matches < 2) {
   2603 		refresh_func();
   2604 		*listed = FALSE;
   2605 	}
   2606 
   2607 	if (matches == NULL) {
   2608 		beep();
   2609 		return morsel;
   2610 	}
   2611 
   2612 	const char *lastslash = revstrstr(morsel, "/", morsel + *place);
   2613 	size_t length_of_path = (lastslash == NULL) ? 0 : lastslash - morsel + 1;
   2614 	size_t match, common_len = 0;
   2615 	char *shared, *glued;
   2616 	char char1[MAXCHARLEN], char2[MAXCHARLEN];
   2617 	int len1, len2;
   2618 
   2619 	/* Determine the number of characters that all matches have in common. */
   2620 	while (TRUE) {
   2621 		len1 = collect_char(matches[0] + common_len, char1);
   2622 
   2623 		for (match = 1; match < num_matches; match++) {
   2624 			len2 = collect_char(matches[match] + common_len, char2);
   2625 
   2626 			if (len1 != len2 || strncmp(char1, char2, len2) != 0)
   2627 				break;
   2628 		}
   2629 
   2630 		if (match < num_matches || matches[0][common_len] == '\0')
   2631 			break;
   2632 
   2633 		common_len += len1;
   2634 	}
   2635 
   2636 	shared = nmalloc(length_of_path + common_len + 1);
   2637 
   2638 	strncpy(shared, morsel, length_of_path);
   2639 	strncpy(shared + length_of_path, matches[0], common_len);
   2640 
   2641 	common_len += length_of_path;
   2642 	shared[common_len] = '\0';
   2643 
   2644 	/* Cover also the case of the user specifying a relative path. */
   2645 	glued = nmalloc(strlen(present_path) + common_len + 1);
   2646 	sprintf(glued, "%s%s", present_path, shared);
   2647 
   2648 	if (num_matches == 1 && (is_dir(shared) || is_dir(glued)))
   2649 		shared[common_len++] = '/';
   2650 
   2651 	/* If the matches have something in common, copy that part. */
   2652 	if (common_len != *place) {
   2653 		morsel = nrealloc(morsel, common_len + 1);
   2654 		strncpy(morsel, shared, common_len);
   2655 		morsel[common_len] = '\0';
   2656 		*place = common_len;
   2657 	} else if (num_matches == 1)
   2658 		beep();
   2659 
   2660 	/* If there is more than one possible completion, show a sorted list. */
   2661 	if (num_matches > 1) {
   2662 		int lastrow = editwinrows - 1 - (ISSET(ZERO) && LINES > 1 ? 1 : 0);
   2663 		size_t longest_name = 0;
   2664 		size_t nrows, ncols;
   2665 		int row;
   2666 
   2667 		if (!*listed)
   2668 			beep();
   2669 
   2670 		qsort(matches, num_matches, sizeof(char *), diralphasort);
   2671 
   2672 		/* Find the length of the longest name among the matches. */
   2673 		for (match = 0; match < num_matches; match++) {
   2674 			size_t namelen = breadth(matches[match]);
   2675 
   2676 			if (namelen > longest_name)
   2677 				longest_name = namelen;
   2678 		}
   2679 
   2680 		if (longest_name > COLS - 1)
   2681 			longest_name = COLS - 1;
   2682 
   2683 		/* The columns of names will be separated by two spaces,
   2684 		 * but the last column will have just one space after it. */
   2685 		ncols = (COLS + 1) / (longest_name + 2);
   2686 		nrows = (num_matches + ncols - 1) / ncols;
   2687 
   2688 		row = (nrows < lastrow) ? lastrow - nrows : 0;
   2689 
   2690 		/* Blank the edit window and hide the cursor. */
   2691 		blank_edit();
   2692 		curs_set(0);
   2693 
   2694 		/* Now print the list of matches out there. */
   2695 		for (match = 0; match < num_matches; match++) {
   2696 			char *disp;
   2697 
   2698 			wmove(midwin, row, (longest_name + 2) * (match % ncols));
   2699 
   2700 			if (row == lastrow && (match + 1) % ncols == 0 &&
   2701 											match + 1 < num_matches) {
   2702 				waddstr(midwin, _("(more)"));
   2703 				break;
   2704 			}
   2705 
   2706 			disp = display_string(matches[match], 0, longest_name, FALSE, FALSE);
   2707 			waddstr(midwin, disp);
   2708 			free(disp);
   2709 
   2710 			if ((match + 1) % ncols == 0)
   2711 				row++;
   2712 		}
   2713 
   2714 		wnoutrefresh(midwin);
   2715 		*listed = TRUE;
   2716 	}
   2717 
   2718 	free_chararray(matches, num_matches);
   2719 	free(glued);
   2720 	free(shared);
   2721 
   2722 	return morsel;
   2723 }
   2724 #endif /* ENABLE_TABCOMP */