Correct insecure temporary file usage in texindex. [06:01]

Correct insecure temporary file usage in ee. [06:02]
Correct a race condition when setting file permissions, sanitize file
names by default, and fix a buffer overflow when handling files
larger than 4GB in cpio. [06:03]
Fix an error in the handling of IP fragments in ipfw which can cause
a kernel panic. [06:04]

Security:	FreeBSD-SA-06:01.texindex
Security:	FreeBSD-SA-06:02.ee
Security:	FreeBSD-SA-06:03.cpio
Security:	FreeBSD-SA-06:04.ipfw
This commit is contained in:
Colin Percival 2006-01-11 08:02:16 +00:00
parent 40c012dd6d
commit 9ed97bee65
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=154216
11 changed files with 217 additions and 60 deletions

View File

@ -20,7 +20,7 @@ cpio \- copy files to and from archives
[\-\-unconditional] [\-\-verbose] [\-\-block-size=blocks] [\-\-swap-halfwords] [\-\-unconditional] [\-\-verbose] [\-\-block-size=blocks] [\-\-swap-halfwords]
[\-\-io-size=bytes] [\-\-pattern-file=file] [\-\-format=format] [\-\-io-size=bytes] [\-\-pattern-file=file] [\-\-format=format]
[\-\-owner=[user][:.][group]] [\-\-no-preserve-owner] [\-\-message=message] [\-\-owner=[user][:.][group]] [\-\-no-preserve-owner] [\-\-message=message]
[\-\-force\-local] [\-\-no\-absolute\-filenames] [\-\-sparse] [\-\-force\-local] [\-\-absolute\-filenames] [\-\-sparse]
[\-\-only\-verify\-crc] [\-\-quiet] [\-\-rsh-command=command] [\-\-help] [\-\-only\-verify\-crc] [\-\-quiet] [\-\-rsh-command=command] [\-\-help]
[\-\-version] [pattern...] [< archive] [\-\-version] [pattern...] [< archive]

View File

@ -288,7 +288,7 @@ cpio @{-i|--extract@} [-bcdfmnrtsuvBSV] [-C bytes] [-E file]
[--swap-halfwords] [--io-size=bytes] [--pattern-file=file] [--swap-halfwords] [--io-size=bytes] [--pattern-file=file]
[--format=format] [--owner=[user][:.][group]] [--format=format] [--owner=[user][:.][group]]
[--no-preserve-owner] [--message=message] [--help] [--version] [--no-preserve-owner] [--message=message] [--help] [--version]
[-no-absolute-filenames] [--sparse] [-only-verify-crc] [-quiet] [--absolute-filenames] [--sparse] [-only-verify-crc] [-quiet]
[--rsh-command=command] [pattern...] [< archive] [--rsh-command=command] [pattern...] [< archive]
@end example @end example
@ -451,9 +451,9 @@ current volume number (starting at 1).
Show numeric UID and GID instead of translating them into names when using the Show numeric UID and GID instead of translating them into names when using the
@samp{--verbose option}. @samp{--verbose option}.
@item --no-absolute-filenames @item --absolute-filenames
Create all files relative to the current directory in copy-in mode, even Do not strip leading file name components that contain ".." and
if they have an absolute file name in the archive. leading slashes from file names in copy-in mode
@item --no-preserve-owner @item --no-preserve-owner
Do not change the ownership of the files; leave them owned by the user Do not change the ownership of the files; leave them owned by the user

View File

@ -27,6 +27,7 @@
#include "dstring.h" #include "dstring.h"
#include "extern.h" #include "extern.h"
#include "defer.h" #include "defer.h"
#include "dirname.h"
#include <rmt.h> #include <rmt.h>
#ifndef FNM_PATHNAME #ifndef FNM_PATHNAME
#include <fnmatch.h> #include <fnmatch.h>
@ -392,19 +393,26 @@ create_final_defers ()
continue; continue;
} }
if (close (out_file_des) < 0) /*
error (0, errno, "%s", d->header.c_name); * Avoid race condition.
* Set chown and chmod before closing the file desc.
* pvrabec@redhat.com
*/
/* File is now copied; set attributes. */ /* File is now copied; set attributes. */
if (!no_chown_flag) if (!no_chown_flag)
if ((chown (d->header.c_name, if ((fchown (out_file_des,
set_owner_flag ? set_owner : d->header.c_uid, set_owner_flag ? set_owner : d->header.c_uid,
set_group_flag ? set_group : d->header.c_gid) < 0) set_group_flag ? set_group : d->header.c_gid) < 0)
&& errno != EPERM) && errno != EPERM)
error (0, errno, "%s", d->header.c_name); error (0, errno, "%s", d->header.c_name);
/* chown may have turned off some permissions we wanted. */ /* chown may have turned off some permissions we wanted. */
if (chmod (d->header.c_name, (int) d->header.c_mode) < 0) if (fchmod (out_file_des, (int) d->header.c_mode) < 0)
error (0, errno, "%s", d->header.c_name); error (0, errno, "%s", d->header.c_name);
if (close (out_file_des) < 0)
error (0, errno, "%s", d->header.c_name);
if (retain_time_flag) if (retain_time_flag)
{ {
times.actime = times.modtime = d->header.c_mtime; times.actime = times.modtime = d->header.c_mtime;
@ -560,6 +568,25 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
write (out_file_des, "", 1); write (out_file_des, "", 1);
delayed_seek_count = 0; delayed_seek_count = 0;
} }
/*
* Avoid race condition.
* Set chown and chmod before closing the file desc.
* pvrabec@redhat.com
*/
/* File is now copied; set attributes. */
if (!no_chown_flag)
if ((fchown (out_file_des,
set_owner_flag ? set_owner : file_hdr->c_uid,
set_group_flag ? set_group : file_hdr->c_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", file_hdr->c_name);
/* chown may have turned off some permissions we wanted. */
if (fchmod (out_file_des, (int) file_hdr->c_mode) < 0)
error (0, errno, "%s", file_hdr->c_name);
if (close (out_file_des) < 0) if (close (out_file_des) < 0)
error (0, errno, "%s", file_hdr->c_name); error (0, errno, "%s", file_hdr->c_name);
@ -570,18 +597,6 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
file_hdr->c_name, crc, file_hdr->c_chksum); file_hdr->c_name, crc, file_hdr->c_chksum);
} }
/* File is now copied; set attributes. */
if (!no_chown_flag)
if ((chown (file_hdr->c_name,
set_owner_flag ? set_owner : file_hdr->c_uid,
set_group_flag ? set_group : file_hdr->c_gid) < 0)
&& errno != EPERM)
error (0, errno, "%s", file_hdr->c_name);
/* chown may have turned off some permissions we wanted. */
if (chmod (file_hdr->c_name, (int) file_hdr->c_mode) < 0)
error (0, errno, "%s", file_hdr->c_name);
if (retain_time_flag) if (retain_time_flag)
{ {
struct utimbuf times; /* For setting file times. */ struct utimbuf times; /* For setting file times. */
@ -592,7 +607,7 @@ copyin_regular_file (struct new_cpio_header* file_hdr, int in_file_des)
if (utime (file_hdr->c_name, &times) < 0) if (utime (file_hdr->c_name, &times) < 0)
error (0, errno, "%s", file_hdr->c_name); error (0, errno, "%s", file_hdr->c_name);
} }
tape_skip_padding (in_file_des, file_hdr->c_filesize); tape_skip_padding (in_file_des, file_hdr->c_filesize);
if (file_hdr->c_nlink > 1 if (file_hdr->c_nlink > 1
&& (archive_format == arf_newascii || archive_format == arf_crcascii) ) && (archive_format == arf_newascii || archive_format == arf_crcascii) )
@ -1350,6 +1365,53 @@ swab_array (char *ptr, int count)
} }
} }
/* Return a safer suffix of FILE_NAME, or "." if it has no safer
suffix. Check for fully specified file names and other atrocities. */
static const char *
safer_name_suffix (char const *file_name)
{
char const *p;
/* Skip file system prefixes, leading file name components that contain
"..", and leading slashes. */
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (file_name);
for (p = file_name + prefix_len; *p;)
{
if (p[0] == '.' && p[1] == '.' && (ISSLASH (p[2]) || !p[2]))
prefix_len = p + 2 - file_name;
do
{
char c = *p++;
if (ISSLASH (c))
break;
}
while (*p);
}
for (p = file_name + prefix_len; ISSLASH (*p); p++)
continue;
prefix_len = p - file_name;
if (prefix_len)
{
char *prefix = alloca (prefix_len + 1);
memcpy (prefix, file_name, prefix_len);
prefix[prefix_len] = '\0';
error (0, 0, _("Removing leading `%s' from member names"), prefix);
}
if (!*p)
p = ".";
return p;
}
/* Read the collection from standard input and create files /* Read the collection from standard input and create files
in the file system. */ in the file system. */
@ -1460,18 +1522,11 @@ process_copy_in ()
/* Do we have to ignore absolute paths, and if so, does the filename /* Do we have to ignore absolute paths, and if so, does the filename
have an absolute path? */ have an absolute path? */
if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/') if (!abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0])
{ {
char *p; const char *p = safer_name_suffix (file_hdr.c_name);
p = file_hdr.c_name; if (p != file_hdr.c_name)
while (*p == '/')
++p;
if (*p == '\0')
{
strcpy (file_hdr.c_name, ".");
}
else
{ {
/* Debian hack: file_hrd.c_name is sometimes set to /* Debian hack: file_hrd.c_name is sometimes set to
point to static memory by code in tar.c. This point to static memory by code in tar.c. This

View File

@ -303,12 +303,13 @@ write_out_header (struct new_cpio_header *file_hdr, int out_des)
{ {
char ascii_header[112]; char ascii_header[112];
char *magic_string; char *magic_string;
int ret;
if (archive_format == arf_crcascii) if (archive_format == arf_crcascii)
magic_string = "070702"; magic_string = "070702";
else else
magic_string = "070701"; magic_string = "070701";
sprintf (ascii_header, ret = snprintf (ascii_header, sizeof(ascii_header),
"%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx", "%6s%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx%08lx",
magic_string, magic_string,
file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid, file_hdr->c_ino, file_hdr->c_mode, file_hdr->c_uid,
@ -316,6 +317,10 @@ write_out_header (struct new_cpio_header *file_hdr, int out_des)
file_hdr->c_filesize, file_hdr->c_dev_maj, file_hdr->c_dev_min, file_hdr->c_filesize, file_hdr->c_dev_maj, file_hdr->c_dev_min,
file_hdr->c_rdev_maj, file_hdr->c_rdev_min, file_hdr->c_namesize, file_hdr->c_rdev_maj, file_hdr->c_rdev_min, file_hdr->c_namesize,
file_hdr->c_chksum); file_hdr->c_chksum);
if (ret >= sizeof(ascii_header)) {
fprintf(stderr, "Internal overflow, aborting\n");
exit (1);
}
tape_buffered_write (ascii_header, out_des, 110L); tape_buffered_write (ascii_header, out_des, 110L);
/* Write file name to output. */ /* Write file name to output. */
@ -325,6 +330,7 @@ write_out_header (struct new_cpio_header *file_hdr, int out_des)
else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii) else if (archive_format == arf_oldascii || archive_format == arf_hpoldascii)
{ {
char ascii_header[78]; char ascii_header[78];
int ret;
dev_t dev; dev_t dev;
dev_t rdev; dev_t rdev;
@ -365,7 +371,7 @@ write_out_header (struct new_cpio_header *file_hdr, int out_des)
/* Debian hack: The type of dev_t has changed in glibc. Fixed output /* Debian hack: The type of dev_t has changed in glibc. Fixed output
to ensure that a long int is passed to sprintf. This has been to ensure that a long int is passed to sprintf. This has been
reported to "bug-gnu-utils@prep.ai.mit.edu". (1998/5/26) -BEM */ reported to "bug-gnu-utils@prep.ai.mit.edu". (1998/5/26) -BEM */
sprintf (ascii_header, snprintf (ascii_header, sizeof(ascii_header),
"%06ho%06lo%06lo%06lo%06lo%06lo%06lo%06lo%011lo%06lo%011lo", "%06ho%06lo%06lo%06lo%06lo%06lo%06lo%06lo%011lo%06lo%011lo",
file_hdr->c_magic & 0xFFFF, (long) dev & 0xFFFF, file_hdr->c_magic & 0xFFFF, (long) dev & 0xFFFF,
file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF, file_hdr->c_ino & 0xFFFF, file_hdr->c_mode & 0xFFFF,
@ -373,6 +379,10 @@ write_out_header (struct new_cpio_header *file_hdr, int out_des)
file_hdr->c_nlink & 0xFFFF, (long) rdev & 0xFFFF, file_hdr->c_nlink & 0xFFFF, (long) rdev & 0xFFFF,
file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF, file_hdr->c_mtime, file_hdr->c_namesize & 0xFFFF,
file_hdr->c_filesize); file_hdr->c_filesize);
if (ret >= sizeof(ascii_header)) {
fprintf(stderr, "Internal overflow, aborting\n");
exit (1);
}
tape_buffered_write (ascii_header, out_des, 76L); tape_buffered_write (ascii_header, out_des, 76L);
/* Write file name to output. */ /* Write file name to output. */
@ -508,6 +518,14 @@ process_copy_out ()
file_hdr.c_dev_maj = major (file_stat.st_dev); file_hdr.c_dev_maj = major (file_stat.st_dev);
file_hdr.c_dev_min = minor (file_stat.st_dev); file_hdr.c_dev_min = minor (file_stat.st_dev);
file_hdr.c_ino = file_stat.st_ino; file_hdr.c_ino = file_stat.st_ino;
/* Skip files larger than 4GB which will cause problems on
64bit platforms (and just not work on 32bit). */
if (file_stat.st_size > 0xffffffff) {
error (0, 0, "%s: skipping >4GB file", input_name.ds_string);
continue;
}
/* For POSIX systems that don't define the S_IF macros, /* For POSIX systems that don't define the S_IF macros,
we can't assume that S_ISfoo means the standard Unix we can't assume that S_ISfoo means the standard Unix
S_IFfoo bit(s) are set. So do it manually, with a S_IFfoo bit(s) are set. So do it manually, with a

View File

@ -183,19 +183,25 @@ process_copy_pass ()
} }
if (close (in_file_des) < 0) if (close (in_file_des) < 0)
error (0, errno, "%s", input_name.ds_string); error (0, errno, "%s", input_name.ds_string);
if (close (out_file_des) < 0) /*
error (0, errno, "%s", output_name.ds_string); * Avoid race condition.
* Set chown and chmod before closing the file desc.
* pvrabec@redhat.com
*/
/* Set the attributes of the new file. */ /* Set the attributes of the new file. */
if (!no_chown_flag) if (!no_chown_flag)
if ((chown (output_name.ds_string, if ((fchown (out_file_des,
set_owner_flag ? set_owner : in_file_stat.st_uid, set_owner_flag ? set_owner : in_file_stat.st_uid,
set_group_flag ? set_group : in_file_stat.st_gid) < 0) set_group_flag ? set_group : in_file_stat.st_gid) < 0)
&& errno != EPERM) && errno != EPERM)
error (0, errno, "%s", output_name.ds_string); error (0, errno, "%s", output_name.ds_string);
/* chown may have turned off some permissions we wanted. */ /* chown may have turned off some permissions we wanted. */
if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0) if (fchmod (out_file_des, in_file_stat.st_mode) < 0)
error (0, errno, "%s", output_name.ds_string); error (0, errno, "%s", output_name.ds_string);
if (close (out_file_des) < 0)
error (0, errno, "%s", output_name.ds_string);
if (reset_time_flag) if (reset_time_flag)
{ {
times.actime = in_file_stat.st_atime; times.actime = in_file_stat.st_atime;

View File

@ -46,7 +46,7 @@ extern int no_chown_flag;
extern int sparse_flag; extern int sparse_flag;
extern int quiet_flag; extern int quiet_flag;
extern int only_verify_crc_flag; extern int only_verify_crc_flag;
extern int no_abs_paths_flag; extern int abs_paths_flag;
extern unsigned int warn_option; extern unsigned int warn_option;
/* Values for warn_option */ /* Values for warn_option */

View File

@ -100,7 +100,7 @@ int quiet_flag = false;
int only_verify_crc_flag = false; int only_verify_crc_flag = false;
/* If true, don't use any absolute paths, prefix them by `./'. */ /* If true, don't use any absolute paths, prefix them by `./'. */
int no_abs_paths_flag = false; int abs_paths_flag = false;
#ifdef DEBUG_CPIO #ifdef DEBUG_CPIO
/* If true, print debugging information. */ /* If true, print debugging information. */

View File

@ -43,6 +43,7 @@
enum cpio_options { enum cpio_options {
NO_ABSOLUTE_FILENAMES_OPTION=256, NO_ABSOLUTE_FILENAMES_OPTION=256,
ABSOLUTE_FILENAMES_OPTION,
NO_PRESERVE_OWNER_OPTION, NO_PRESERVE_OWNER_OPTION,
ONLY_VERIFY_CRC_OPTION, ONLY_VERIFY_CRC_OPTION,
RENAME_BATCH_FILE_OPTION, RENAME_BATCH_FILE_OPTION,
@ -136,6 +137,8 @@ static struct argp_option options[] = {
N_("In copy-in mode, read additional patterns specifying filenames to extract or list from FILE"), 210}, N_("In copy-in mode, read additional patterns specifying filenames to extract or list from FILE"), 210},
{"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0, {"no-absolute-filenames", NO_ABSOLUTE_FILENAMES_OPTION, 0, 0,
N_("Create all files relative to the current directory"), 210}, N_("Create all files relative to the current directory"), 210},
{"absolute-filenames", ABSOLUTE_FILENAMES_OPTION, 0, 0,
N_("do not strip leading file name components that contain \"..\" and leading slashes from file names"), 210},
{"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0, {"only-verify-crc", ONLY_VERIFY_CRC_OPTION, 0, 0,
N_("When reading a CRC format archive in copy-in mode, only verify the CRC's of each file in the archive, don't actually extract the files"), 210}, N_("When reading a CRC format archive in copy-in mode, only verify the CRC's of each file in the archive, don't actually extract the files"), 210},
{"rename", 'r', 0, 0, {"rename", 'r', 0, 0,
@ -394,7 +397,11 @@ crc newc odc bin ustar tar (all-caps also recognized)"), arg);
break; break;
case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */ case NO_ABSOLUTE_FILENAMES_OPTION: /* --no-absolute-filenames */
no_abs_paths_flag = true; abs_paths_flag = false;
break;
case ABSOLUTE_FILENAMES_OPTION: /* --absolute-filenames */
abs_paths_flag = true;
break; break;
case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */ case NO_PRESERVE_OWNER_OPTION: /* --no-preserve-owner */
@ -633,7 +640,7 @@ process_args (int argc, char *argv[])
_("--append is used but no archive file name is given (use -F or -O options"))); _("--append is used but no archive file name is given (use -F or -O options")));
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create"); CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--create");
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames", "--create"); CHECK_USAGE(abs_paths_flag, "--absolute-pathnames", "--create");
CHECK_USAGE(input_archive_name, "-I", "--create"); CHECK_USAGE(input_archive_name, "-I", "--create");
if (archive_name && output_archive_name) if (archive_name && output_archive_name)
USAGE_ERROR ((0, 0, _("Both -O and -F are used in copy-out mode"))); USAGE_ERROR ((0, 0, _("Both -O and -F are used in copy-out mode")));
@ -660,7 +667,7 @@ process_args (int argc, char *argv[])
CHECK_USAGE(rename_flag, "--rename", "--pass-through"); CHECK_USAGE(rename_flag, "--rename", "--pass-through");
CHECK_USAGE(append_flag, "--append", "--pass-through"); CHECK_USAGE(append_flag, "--append", "--pass-through");
CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through"); CHECK_USAGE(rename_batch_file, "--rename-batch-file", "--pass-through");
CHECK_USAGE(no_abs_paths_flag, "--no-absolute-pathnames", CHECK_USAGE(abs_paths_flag, "--absolute-pathnames",
"--pass-through"); "--pass-through");
CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through"); CHECK_USAGE(to_stdout_option, "--to-stdout", "--pass-through");

View File

@ -384,17 +384,33 @@ For more information about these matters, see the files named COPYING.\n"));
usage (1); usage (1);
} }
static char **tv;
static int tv_alloc;
static int tv_used;
static int
findtempname (char *tempname)
{
int i;
for (i = 0; i < tv_used; i++)
if (strcmp (tv[i], tempname) == 0)
return (1);
return (0);
}
/* Return a name for temporary file COUNT. */ /* Return a name for temporary file COUNT. */
static char * static char *
maketempname (int count) maketempname (int count)
{ {
static char *tempbase = NULL; static char *tempbase = NULL;
char *tempname;
char tempsuffix[10]; char tempsuffix[10];
int fd;
if (!tempbase) if (!tempbase)
{ {
int fd;
tempbase = concat (tempdir, "txidxXXXXXX"); tempbase = concat (tempdir, "txidxXXXXXX");
fd = mkstemp (tempbase); fd = mkstemp (tempbase);
@ -403,7 +419,52 @@ maketempname (int count)
} }
sprintf (tempsuffix, ".%d", count); sprintf (tempsuffix, ".%d", count);
return concat (tempbase, tempsuffix); tempname = concat (tempbase, tempsuffix);
/*
* The open logic becomes a bit convoluted. If open(2) fails due to EEXIST,
* it's likely because somebody attempted to race us, or because we have
* already created this file.
*/
fd = open (tempname, O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd == -1)
{
/*
* If errno is not EEXIST, then open failed for some other reason, so
* we should terminate. If errno == EEXIST AND we didn't create this
* file, terminate. Otherwise, it's safe to say that errno == EEXIST
* because we already created it, in this event, we can just return.
*/
if (errno != EEXIST ||
(errno == EEXIST && findtempname (tempname) == 0))
pfatal_with_name (tempname);
return (tempname);
}
else if (fd > 0)
{
close (fd);
}
if (tv == NULL)
{
tv_alloc = 16;
tv = calloc (tv_alloc, sizeof (char *));
if (tv == NULL)
{
fprintf (stderr, "calloc failed\n");
exit (1);
}
}
else if (tv_used == tv_alloc)
{
tv_alloc += 4;
tv = realloc (tv, tv_alloc * sizeof (char *));
if (tv == NULL)
{
fprintf (stderr, "realloc failed");
exit (1);
}
}
tv[tv_used++] = strdup (tempname);
return tempname;
} }

View File

@ -3054,7 +3054,7 @@ do { \
* if the packet is not ICMP (or is an ICMP * if the packet is not ICMP (or is an ICMP
* query), and it is not multicast/broadcast. * query), and it is not multicast/broadcast.
*/ */
if (hlen > 0 && is_ipv4 && if (hlen > 0 && is_ipv4 && offset == 0 &&
(proto != IPPROTO_ICMP || (proto != IPPROTO_ICMP ||
is_icmp_query(ICMP(ulp))) && is_icmp_query(ICMP(ulp))) &&
!(m->m_flags & (M_BCAST|M_MCAST)) && !(m->m_flags & (M_BCAST|M_MCAST)) &&

View File

@ -300,7 +300,7 @@ void finish P_((void));
int quit P_((int noverify)); int quit P_((int noverify));
void edit_abort P_((int arg)); void edit_abort P_((int arg));
void delete_text P_((void)); void delete_text P_((void));
int write_file P_((char *file_name)); int write_file P_((char *file_name, int warn_if_exists));
int search P_((int display_message)); int search P_((int display_message));
void search_prompt P_((void)); void search_prompt P_((void));
void del_char P_((void)); void del_char P_((void));
@ -1688,7 +1688,7 @@ char *cmd_str1;
cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE); cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE);
} }
tmp_file = resolve_name(cmd_str); tmp_file = resolve_name(cmd_str);
write_file(tmp_file); write_file(tmp_file, 1);
if (tmp_file != cmd_str) if (tmp_file != cmd_str)
free(tmp_file); free(tmp_file);
} }
@ -2395,7 +2395,7 @@ finish() /* prepare to exit edit session */
file_name = tmp_file; file_name = tmp_file;
} }
if (write_file(file_name)) if (write_file(file_name, 1))
{ {
text_changes = FALSE; text_changes = FALSE;
quit(0); quit(0);
@ -2472,8 +2472,9 @@ delete_text()
} }
int int
write_file(file_name) write_file(file_name, warn_if_exists)
char *file_name; char *file_name;
int warn_if_exists;
{ {
char cr; char cr;
char *tmp_point; char *tmp_point;
@ -2483,7 +2484,8 @@ char *file_name;
int write_flag = TRUE; int write_flag = TRUE;
charac = lines = 0; charac = lines = 0;
if ((in_file_name == NULL) || strcmp(in_file_name, file_name)) if (warn_if_exists &&
((in_file_name == NULL) || strcmp(in_file_name, file_name)))
{ {
if ((temp_fp = fopen(file_name, "r"))) if ((temp_fp = fopen(file_name, "r")))
{ {
@ -3725,7 +3727,7 @@ int arg;
{ {
string = get_string(file_write_prompt_str, TRUE); string = get_string(file_write_prompt_str, TRUE);
tmp_file = resolve_name(string); tmp_file = resolve_name(string);
write_file(tmp_file); write_file(tmp_file, 1);
if (tmp_file != string) if (tmp_file != string)
free(tmp_file); free(tmp_file);
free(string); free(string);
@ -3762,7 +3764,7 @@ int arg;
string = tmp_file; string = tmp_file;
} }
} }
if (write_file(string)) if (write_file(string, 1))
{ {
in_file_name = string; in_file_name = string;
text_changes = FALSE; text_changes = FALSE;
@ -4375,17 +4377,25 @@ spell_op() /* check spelling of words in the editor */
void void
ispell_op() ispell_op()
{ {
char name[128]; char template[128], *name;
char string[256]; char string[256];
int pid; int fd;
if (restrict_mode()) if (restrict_mode())
{ {
return; return;
} }
pid = getpid(); (void)sprintf(template, "/tmp/ee.XXXXXXXX");
sprintf(name, "/tmp/ee.%d", pid); name = mktemp(&template[0]);
if (write_file(name)) fd = open(name, O_CREAT | O_EXCL | O_RDWR, 0600);
if (fd < 0) {
wmove(com_win, 0, 0);
wprintw(com_win, create_file_fail_msg, name);
wrefresh(com_win);
return;
}
close(fd);
if (write_file(name, 0))
{ {
sprintf(string, "ispell %s", name); sprintf(string, "ispell %s", name);
sh_command(string); sh_command(string);