summaryrefslogtreecommitdiff
path: root/usr.bin/patch
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>2006-06-26 17:25:23 +0000
committercvs2svn <cvs2svn@FreeBSD.org>2006-06-26 17:25:23 +0000
commiteb5270bf8fb2f273b3a610d551484384417ac307 (patch)
tree3abcd9cb9fc2eae412e6cb927b04ecc4db559d3e /usr.bin/patch
parent257c55772da29a31a2986189e9cff6b3d3b1516d (diff)
Notes
Diffstat (limited to 'usr.bin/patch')
-rw-r--r--usr.bin/patch/Makefile6
-rw-r--r--usr.bin/patch/README123
-rw-r--r--usr.bin/patch/backupfile.c238
-rw-r--r--usr.bin/patch/backupfile.h38
-rw-r--r--usr.bin/patch/common.h114
-rw-r--r--usr.bin/patch/inp.c473
-rw-r--r--usr.bin/patch/inp.h31
-rw-r--r--usr.bin/patch/patch.1641
-rw-r--r--usr.bin/patch/patch.c974
-rw-r--r--usr.bin/patch/pathnames.h11
-rw-r--r--usr.bin/patch/pch.c1549
-rw-r--r--usr.bin/patch/pch.h56
-rw-r--r--usr.bin/patch/util.c425
-rw-r--r--usr.bin/patch/util.h47
14 files changed, 0 insertions, 4726 deletions
diff --git a/usr.bin/patch/Makefile b/usr.bin/patch/Makefile
deleted file mode 100644
index 9c54a925f50d5..0000000000000
--- a/usr.bin/patch/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# $OpenBSD: Makefile,v 1.3 2003/07/18 02:00:09 deraadt Exp $
-
-PROG= patch
-SRCS= patch.c pch.c inp.c util.c backupfile.c
-
-.include <bsd.prog.mk>
diff --git a/usr.bin/patch/README b/usr.bin/patch/README
deleted file mode 100644
index 72c10644d17a4..0000000000000
--- a/usr.bin/patch/README
+++ /dev/null
@@ -1,123 +0,0 @@
-this version modified to fit in with the 386bsd release.
-this isn't gnu software, so we're not obligated to give
-you the original sources -- if you want them, get them
-from prep.ai.mit.edu:pub/gnu/patch-2.0.12u8.tar.z
-
- -- cgd
-
-#######################################################################
-
-
-This version of patch contains modifications made by the Free Software
-Foundation, summarized in the file ChangeLog. Primarily they are to
-support the unified context diff format that GNU diff can produce, and
-to support making GNU Emacs-style backup files. They also include
-fixes for some bugs.
-
-There are two GNU variants of patch: this one, which retains Larry
-Wall's interactive Configure script and has patchlevels starting with
-`12u'; and another one that has a GNU-style non-interactive configure
-script and accepts long-named options, and has patchlevels starting
-with `12g'. Unlike the 12g variant, the 12u variant contains no
-copylefted code, for the paranoid. The two variants are otherwise the
-same. They should be available from the same places.
-
-The FSF is distributing this version of patch independently because as
-of this writing, Larry Wall has not released a new version of patch
-since mid-1988. I have heard that he has been too busy working on
-other things, like Perl.
-
-Here is a wish list of some projects to improve patch:
-
-1. Correctly handle files and patchfiles that contain NUL characters.
-This is hard to do straightforwardly; it would be less work to
-adopt a kind of escape encoding internally.
-Let ESC be a "control prefix". ESC @ stands for NUL. ESC [ stands for ESC.
-You need to crunch this when reading input (replace fgets),
-and when writing the output file (replace fputs),
-but otherwise everything can go along as it does now.
-Be careful to handle reject files correctly;
-I think they are currently created using `write', not `fputs'.
-
-2. Correctly handle patches produced by GNU diff for files that do
-not end with a newline.
-
-Please send bug reports for this version of patch to
-bug-gnu-utils@prep.ai.mit.edu as well as to Larry Wall (lwall@netlabs.com).
- --djm@gnu.ai.mit.edu (David MacKenzie)
-
- Patch Kit, Version 2.0
-
- Copyright (c) 1988, Larry Wall
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following condition
-is met:
- 1. Redistributions of source code must retain the above copyright
- notice, this condition and the following disclaimer.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGE.
---------------------------------------------------------------------------
-
-Please read all the directions below before you proceed any further, and
-then follow them carefully. Failure to do so may void your warranty. :-)
-
-After you have unpacked your kit, you should have all the files listed
-in MANIFEST.
-
-Installation
-
-1) Run Configure. This will figure out various things about your system.
- Some things Configure will figure out for itself, other things it will
- ask you about. It will then proceed to make config.h, config.sh, and
- Makefile.
-
- You might possibly have to trim # comments from the front of Configure
- if your sh doesn't handle them, but all other # comments will be taken
- care of.
-
- If you don't have sh, you'll have to rip the prototype of config.h out
- of Configure and generate the defines by hand.
-
-2) Glance through config.h to make sure system dependencies are correct.
- Most of them should have been taken care of by running the
- Configure script.
-
- If you have any additional changes to make to the C definitions, they
- can be done in the Makefile, or in config.h. Bear in mind that they may
- get undone next time you run Configure.
-
-3) make
-
- This will attempt to make patch in the current directory.
-
-4) make install
-
- This will put patch into a public directory (normally /usr/local/bin).
- It will also try to put the man pages in a reasonable place. It will not
- nroff the man page, however.
-
-5) Read the manual entry before running patch.
-
-6) IMPORTANT! Help save the world! Communicate any problems and
- suggested patches to me, lwall@netlabs.com (Larry Wall),
- so we can keep the world in sync. If you have a problem, there's
- someone else out there who either has had or will have the same problem.
-
- If possible, send in patches such that the patch program will apply them.
- Context diffs are the best, then normal diffs. Don't send ed scripts--
- I've probably changed my copy since the version you have.
-
- Watch for patch patches in comp.sources.bugs. Patches will generally be
- in a form usable by the patch program. Your current patch level
- is shown in patchlevel.h.
diff --git a/usr.bin/patch/backupfile.c b/usr.bin/patch/backupfile.c
deleted file mode 100644
index 5863e9b1b147f..0000000000000
--- a/usr.bin/patch/backupfile.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* $OpenBSD: backupfile.c,v 1.17 2003/08/01 20:30:48 otto Exp $ */
-
-/*
- * backupfile.c -- make Emacs style backup file names Copyright (C) 1990 Free
- * Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * without restriction.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/*
- * David MacKenzie <djm@ai.mit.edu>. Some algorithms adapted from GNU Emacs.
- */
-
-#ifndef lint
-static const char rcsid[] = "$OpenBSD: backupfile.c,v 1.17 2003/08/01 20:30:48 otto Exp $";
-#endif /* not lint */
-
-#include <ctype.h>
-#include <dirent.h>
-#include <libgen.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "backupfile.h"
-
-
-#define ISDIGIT(c) (isascii (c) && isdigit (c))
-
-/* Which type of backup file names are generated. */
-enum backup_type backup_type = none;
-
-/*
- * The extension added to file names to produce a simple (as opposed to
- * numbered) backup file name.
- */
-char *simple_backup_suffix = "~";
-
-static char *concat(const char *, const char *);
-static char *make_version_name(const char *, int);
-static int max_backup_version(const char *, const char *);
-static int version_number(const char *, const char *, int);
-static int argmatch(const char *, const char **);
-static void invalid_arg(const char *, const char *, int);
-
-/*
- * Return the name of the new backup file for file FILE, allocated with
- * malloc. Return 0 if out of memory. FILE must not end with a '/' unless it
- * is the root directory. Do not call this function if backup_type == none.
- */
-char *
-find_backup_file_name(const char *file)
-{
- char *dir, *base_versions;
- int highest_backup;
-
- if (backup_type == simple)
- return concat(file, simple_backup_suffix);
- base_versions = concat(basename(file), ".~");
- if (base_versions == NULL)
- return NULL;
- dir = dirname(file);
- if (dir == NULL) {
- free(base_versions);
- return NULL;
- }
- highest_backup = max_backup_version(base_versions, dir);
- free(base_versions);
- if (backup_type == numbered_existing && highest_backup == 0)
- return concat(file, simple_backup_suffix);
- return make_version_name(file, highest_backup + 1);
-}
-
-/*
- * Return the number of the highest-numbered backup file for file FILE in
- * directory DIR. If there are no numbered backups of FILE in DIR, or an
- * error occurs reading DIR, return 0. FILE should already have ".~" appended
- * to it.
- */
-static int
-max_backup_version(const char *file, const char *dir)
-{
- DIR *dirp;
- struct dirent *dp;
- int highest_version, this_version, file_name_length;
-
- dirp = opendir(dir);
- if (dirp == NULL)
- return 0;
-
- highest_version = 0;
- file_name_length = strlen(file);
-
- while ((dp = readdir(dirp)) != NULL) {
- if (dp->d_namlen <= file_name_length)
- continue;
-
- this_version = version_number(file, dp->d_name, file_name_length);
- if (this_version > highest_version)
- highest_version = this_version;
- }
- closedir(dirp);
- return highest_version;
-}
-
-/*
- * Return a string, allocated with malloc, containing "FILE.~VERSION~".
- * Return 0 if out of memory.
- */
-static char *
-make_version_name(const char *file, int version)
-{
- char *backup_name;
-
- if (asprintf(&backup_name, "%s.~%d~", file, version) == -1)
- return NULL;
- return backup_name;
-}
-
-/*
- * If BACKUP is a numbered backup of BASE, return its version number;
- * otherwise return 0. BASE_LENGTH is the length of BASE. BASE should
- * already have ".~" appended to it.
- */
-static int
-version_number(const char *base, const char *backup, int base_length)
-{
- int version;
- const char *p;
-
- version = 0;
- if (!strncmp(base, backup, base_length) && ISDIGIT(backup[base_length])) {
- for (p = &backup[base_length]; ISDIGIT(*p); ++p)
- version = version * 10 + *p - '0';
- if (p[0] != '~' || p[1])
- version = 0;
- }
- return version;
-}
-
-/*
- * Return the newly-allocated concatenation of STR1 and STR2. If out of
- * memory, return 0.
- */
-static char *
-concat(const char *str1, const char *str2)
-{
- char *newstr;
-
- if (asprintf(&newstr, "%s%s", str1, str2) == -1)
- return NULL;
- return newstr;
-}
-
-/*
- * If ARG is an unambiguous match for an element of the null-terminated array
- * OPTLIST, return the index in OPTLIST of the matched element, else -1 if it
- * does not match any element or -2 if it is ambiguous (is a prefix of more
- * than one element).
- */
-static int
-argmatch(const char *arg, const char **optlist)
-{
- int i; /* Temporary index in OPTLIST. */
- size_t arglen; /* Length of ARG. */
- int matchind = -1; /* Index of first nonexact match. */
- int ambiguous = 0; /* If nonzero, multiple nonexact match(es). */
-
- arglen = strlen(arg);
-
- /* Test all elements for either exact match or abbreviated matches. */
- for (i = 0; optlist[i]; i++) {
- if (!strncmp(optlist[i], arg, arglen)) {
- if (strlen(optlist[i]) == arglen)
- /* Exact match found. */
- return i;
- else if (matchind == -1)
- /* First nonexact match found. */
- matchind = i;
- else
- /* Second nonexact match found. */
- ambiguous = 1;
- }
- }
- if (ambiguous)
- return -2;
- else
- return matchind;
-}
-
-/*
- * Error reporting for argmatch. KIND is a description of the type of entity
- * that was being matched. VALUE is the invalid value that was given. PROBLEM
- * is the return value from argmatch.
- */
-static void
-invalid_arg(const char *kind, const char *value, int problem)
-{
- fprintf(stderr, "patch: ");
- if (problem == -1)
- fprintf(stderr, "invalid");
- else /* Assume -2. */
- fprintf(stderr, "ambiguous");
- fprintf(stderr, " %s `%s'\n", kind, value);
-}
-
-static const char *backup_args[] = {
- "never", "simple", "nil", "existing", "t", "numbered", 0
-};
-
-static enum backup_type backup_types[] = {
- simple, simple, numbered_existing,
- numbered_existing, numbered, numbered
-};
-
-/*
- * Return the type of backup indicated by VERSION. Unique abbreviations are
- * accepted.
- */
-enum backup_type
-get_version(const char *version)
-{
- int i;
-
- if (version == NULL || *version == '\0')
- return numbered_existing;
- i = argmatch(version, backup_args);
- if (i >= 0)
- return backup_types[i];
- invalid_arg("version control type", version, i);
- exit(2);
-}
diff --git a/usr.bin/patch/backupfile.h b/usr.bin/patch/backupfile.h
deleted file mode 100644
index 7c20ddb4bc557..0000000000000
--- a/usr.bin/patch/backupfile.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* $OpenBSD: backupfile.h,v 1.6 2003/07/28 18:35:36 otto Exp $ */
-
-/*
- * backupfile.h -- declarations for making Emacs style backup file names
- * Copyright (C) 1990 Free Software Foundation, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * without restriction.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.
- *
- */
-
-/* When to make backup files. */
-enum backup_type {
- /* Never make backups. */
- none,
-
- /* Make simple backups of every file. */
- simple,
-
- /*
- * Make numbered backups of files that already have numbered backups,
- * and simple backups of the others.
- */
- numbered_existing,
-
- /* Make numbered backups of every file. */
- numbered
-};
-
-extern enum backup_type backup_type;
-extern char *simple_backup_suffix;
-
-char *find_backup_file_name(const char *file);
-enum backup_type get_version(const char *version);
diff --git a/usr.bin/patch/common.h b/usr.bin/patch/common.h
deleted file mode 100644
index 4101a5757470d..0000000000000
--- a/usr.bin/patch/common.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* $OpenBSD: common.h,v 1.25 2003/10/31 20:20:45 millert Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-#include <stdbool.h>
-
-#define DEBUGGING
-
-/* constants */
-
-#define MAXHUNKSIZE 100000 /* is this enough lines? */
-#define INITHUNKMAX 125 /* initial dynamic allocation size */
-#define MAXLINELEN 8192
-#define BUFFERSIZE 1024
-
-#define SCCSPREFIX "s."
-#define GET "get -e %s"
-#define SCCSDIFF "get -p %s | diff - %s >/dev/null"
-
-#define RCSSUFFIX ",v"
-#define CHECKOUT "co -l %s"
-#define RCSDIFF "rcsdiff %s > /dev/null"
-
-#define ORIGEXT ".orig"
-#define REJEXT ".rej"
-
-/* handy definitions */
-
-#define strNE(s1,s2) (strcmp(s1, s2))
-#define strEQ(s1,s2) (!strcmp(s1, s2))
-#define strnNE(s1,s2,l) (strncmp(s1, s2, l))
-#define strnEQ(s1,s2,l) (!strncmp(s1, s2, l))
-
-/* typedefs */
-
-typedef long LINENUM; /* must be signed */
-
-/* globals */
-
-extern int filemode;
-
-extern char buf[MAXLINELEN];/* general purpose buffer */
-
-extern bool using_plan_a; /* try to keep everything in memory */
-extern bool out_of_mem; /* ran out of memory in plan a */
-
-#define MAXFILEC 2
-
-extern char *filearg[MAXFILEC];
-extern bool ok_to_create_file;
-extern char *outname;
-extern char *origprae;
-
-extern char *TMPOUTNAME;
-extern char *TMPINNAME;
-extern char *TMPREJNAME;
-extern char *TMPPATNAME;
-extern bool toutkeep;
-extern bool trejkeep;
-
-#ifdef DEBUGGING
-extern int debug;
-#endif
-
-extern bool force;
-extern bool batch;
-extern bool verbose;
-extern bool reverse;
-extern bool noreverse;
-extern bool skip_rest_of_patch;
-extern int strippath;
-extern bool canonicalize;
-/* TRUE if -C was specified on command line. */
-extern bool check_only;
-extern bool warn_on_invalid_line;
-extern bool last_line_missing_eol;
-
-
-#define CONTEXT_DIFF 1
-#define NORMAL_DIFF 2
-#define ED_DIFF 3
-#define NEW_CONTEXT_DIFF 4
-#define UNI_DIFF 5
-
-extern int diff_type;
-extern char *revision; /* prerequisite revision, if any */
-extern LINENUM input_lines; /* how long is input file in lines */
-
-extern int posix;
-
diff --git a/usr.bin/patch/inp.c b/usr.bin/patch/inp.c
deleted file mode 100644
index 3326843ad0080..0000000000000
--- a/usr.bin/patch/inp.c
+++ /dev/null
@@ -1,473 +0,0 @@
-/* $OpenBSD: inp.c,v 1.31 2003/12/08 22:44:18 mickey Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-#ifndef lint
-static const char rcsid[] = "$OpenBSD: inp.c,v 1.31 2003/12/08 22:44:18 mickey Exp $";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include <ctype.h>
-#include <libgen.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "common.h"
-#include "util.h"
-#include "pch.h"
-#include "inp.h"
-
-
-/* Input-file-with-indexable-lines abstract type */
-
-static off_t i_size; /* size of the input file */
-static char *i_womp; /* plan a buffer for entire file */
-static char **i_ptr; /* pointers to lines in i_womp */
-
-static int tifd = -1; /* plan b virtual string array */
-static char *tibuf[2]; /* plan b buffers */
-static LINENUM tiline[2] = {-1, -1}; /* 1st line in each buffer */
-static LINENUM lines_per_buf; /* how many lines per buffer */
-static int tireclen; /* length of records in tmp file */
-
-static bool rev_in_string(const char *);
-static bool reallocate_lines(size_t *);
-
-/* returns false if insufficient memory */
-static bool plan_a(const char *);
-
-static void plan_b(const char *);
-
-/* New patch--prepare to edit another file. */
-
-void
-re_input(void)
-{
- if (using_plan_a) {
- i_size = 0;
- free(i_ptr);
- i_ptr = NULL;
- if (i_womp != NULL) {
- munmap(i_womp, i_size);
- i_womp = NULL;
- }
- } else {
- using_plan_a = true; /* maybe the next one is smaller */
- close(tifd);
- tifd = -1;
- free(tibuf[0]);
- free(tibuf[1]);
- tibuf[0] = tibuf[1] = NULL;
- tiline[0] = tiline[1] = -1;
- tireclen = 0;
- }
-}
-
-/* Constuct the line index, somehow or other. */
-
-void
-scan_input(const char *filename)
-{
- if (!plan_a(filename))
- plan_b(filename);
- if (verbose) {
- say("Patching file %s using Plan %s...\n", filename,
- (using_plan_a ? "A" : "B"));
- }
-}
-
-static bool
-reallocate_lines(size_t *lines_allocated)
-{
- char **p;
- size_t new_size;
-
- new_size = *lines_allocated * 3 / 2;
- p = realloc(i_ptr, (new_size + 2) * sizeof(char *));
- if (p == NULL) { /* shucks, it was a near thing */
- munmap(i_womp, i_size);
- i_womp = NULL;
- free(i_ptr);
- i_ptr = NULL;
- *lines_allocated = 0;
- return false;
- }
- *lines_allocated = new_size;
- i_ptr = p;
- return true;
-}
-
-/* Try keeping everything in memory. */
-
-static bool
-plan_a(const char *filename)
-{
- int ifd, statfailed;
- char *p, *s, lbuf[MAXLINELEN];
- LINENUM iline;
- struct stat filestat;
- off_t i;
- ptrdiff_t sz;
- size_t lines_allocated;
-
-#ifdef DEBUGGING
- if (debug & 8)
- return false;
-#endif
-
- if (filename == NULL || *filename == '\0')
- return false;
-
- statfailed = stat(filename, &filestat);
- if (statfailed && ok_to_create_file) {
- if (verbose)
- say("(Creating file %s...)\n", filename);
-
- /*
- * in check_patch case, we still display `Creating file' even
- * though we're not. The rule is that -C should be as similar
- * to normal patch behavior as possible
- */
- if (check_only)
- return true;
- makedirs(filename, true);
- close(creat(filename, 0666));
- statfailed = stat(filename, &filestat);
- }
- if (statfailed && check_only)
- fatal("%s not found, -C mode, can't probe further\n", filename);
- /* For nonexistent or read-only files, look for RCS or SCCS versions. */
- if (statfailed ||
- /* No one can write to it. */
- (filestat.st_mode & 0222) == 0 ||
- /* I can't write to it. */
- ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
- char *cs = NULL, *filebase, *filedir;
- struct stat cstat;
-
- filebase = basename(filename);
- filedir = dirname(filename);
-
- /* Leave room in lbuf for the diff command. */
- s = lbuf + 20;
-
-#define try(f, a1, a2, a3) \
- (snprintf(s, sizeof lbuf - 20, f, a1, a2, a3), stat(s, &cstat) == 0)
-
- if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
- try("%s/RCS/%s%s", filedir, filebase, "") ||
- try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
- snprintf(buf, sizeof buf, CHECKOUT, filename);
- snprintf(lbuf, sizeof lbuf, RCSDIFF, filename);
- cs = "RCS";
- } else if (try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
- try("%s/%s%s", filedir, SCCSPREFIX, filebase)) {
- snprintf(buf, sizeof buf, GET, s);
- snprintf(lbuf, sizeof lbuf, SCCSDIFF, s, filename);
- cs = "SCCS";
- } else if (statfailed)
- fatal("can't find %s\n", filename);
- /*
- * else we can't write to it but it's not under a version
- * control system, so just proceed.
- */
- if (cs) {
- if (!statfailed) {
- if ((filestat.st_mode & 0222) != 0)
- /* The owner can write to it. */
- fatal("file %s seems to be locked "
- "by somebody else under %s\n",
- filename, cs);
- /*
- * It might be checked out unlocked. See if
- * it's safe to check out the default version
- * locked.
- */
- if (verbose)
- say("Comparing file %s to default "
- "%s version...\n",
- filename, cs);
- if (system(lbuf))
- fatal("can't check out file %s: "
- "differs from default %s version\n",
- filename, cs);
- }
- if (verbose)
- say("Checking out file %s from %s...\n",
- filename, cs);
- if (system(buf) || stat(filename, &filestat))
- fatal("can't check out file %s from %s\n",
- filename, cs);
- }
- }
- filemode = filestat.st_mode;
- if (!S_ISREG(filemode))
- fatal("%s is not a normal file--can't patch\n", filename);
- i_size = filestat.st_size;
- if (out_of_mem) {
- set_hunkmax(); /* make sure dynamic arrays are allocated */
- out_of_mem = false;
- return false; /* force plan b because plan a bombed */
- }
- if (i_size > SIZE_MAX) {
- say("block too large to mmap\n");
- return false;
- }
- if ((ifd = open(filename, O_RDONLY)) < 0)
- pfatal("can't open file %s", filename);
-
- i_womp = mmap(NULL, i_size, PROT_READ, MAP_PRIVATE, ifd, 0);
- if (i_womp == MAP_FAILED) {
- perror("mmap failed");
- i_womp = NULL;
- close(ifd);
- return false;
- }
-
- close(ifd);
- if (i_size)
- madvise(i_womp, i_size, MADV_SEQUENTIAL);
-
- /* estimate the number of lines */
- lines_allocated = i_size / 25;
- if (lines_allocated < 100)
- lines_allocated = 100;
-
- if (!reallocate_lines(&lines_allocated))
- return false;
-
- /* now scan the buffer and build pointer array */
- iline = 1;
- i_ptr[iline] = i_womp;
- /* test for NUL too, to maintain the behavior of the original code */
- for (s = i_womp, i = 0; i < i_size && *s != '\0'; s++, i++) {
- if (*s == '\n') {
- if (iline == lines_allocated) {
- if (!reallocate_lines(&lines_allocated))
- return false;
- }
- /* these are NOT NUL terminated */
- i_ptr[++iline] = s + 1;
- }
- }
- /* if the last line contains no EOL, append one */
- if (i_size > 0 && i_womp[i_size - 1] != '\n') {
- last_line_missing_eol = true;
- /* fix last line */
- sz = s - i_ptr[iline];
- p = malloc(sz + 1);
- if (p == NULL) {
- free(i_ptr);
- i_ptr = NULL;
- munmap(i_womp, i_size);
- i_womp = NULL;
- return false;
- }
-
- memcpy(p, i_ptr[iline], sz);
- p[sz] = '\n';
- i_ptr[iline] = p;
- /* count the extra line and make it point to some valid mem */
- i_ptr[++iline] = "";
- } else
- last_line_missing_eol = false;
-
- input_lines = iline - 1;
-
- /* now check for revision, if any */
-
- if (revision != NULL) {
- if (!rev_in_string(i_womp)) {
- if (force) {
- if (verbose)
- say("Warning: this file doesn't appear "
- "to be the %s version--patching anyway.\n",
- revision);
- } else if (batch) {
- fatal("this file doesn't appear to be the "
- "%s version--aborting.\n",
- revision);
- } else {
- ask("This file doesn't appear to be the "
- "%s version--patch anyway? [n] ",
- revision);
- if (*buf != 'y')
- fatal("aborted\n");
- }
- } else if (verbose)
- say("Good. This file appears to be the %s version.\n",
- revision);
- }
- return true; /* plan a will work */
-}
-
-/* Keep (virtually) nothing in memory. */
-
-static void
-plan_b(const char *filename)
-{
- FILE *ifp;
- int i = 0, j, maxlen = 1;
- char *p;
- bool found_revision = (revision == NULL);
-
- using_plan_a = false;
- if ((ifp = fopen(filename, "r")) == NULL)
- pfatal("can't open file %s", filename);
- (void) unlink(TMPINNAME);
- if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
- pfatal("can't open file %s", TMPINNAME);
- while (fgets(buf, sizeof buf, ifp) != NULL) {
- if (revision != NULL && !found_revision && rev_in_string(buf))
- found_revision = true;
- if ((i = strlen(buf)) > maxlen)
- maxlen = i; /* find longest line */
- }
- last_line_missing_eol = i > 0 && buf[i - 1] != '\n';
- if (last_line_missing_eol && maxlen == i)
- maxlen++;
-
- if (revision != NULL) {
- if (!found_revision) {
- if (force) {
- if (verbose)
- say("Warning: this file doesn't appear "
- "to be the %s version--patching anyway.\n",
- revision);
- } else if (batch) {
- fatal("this file doesn't appear to be the "
- "%s version--aborting.\n",
- revision);
- } else {
- ask("This file doesn't appear to be the %s "
- "version--patch anyway? [n] ",
- revision);
- if (*buf != 'y')
- fatal("aborted\n");
- }
- } else if (verbose)
- say("Good. This file appears to be the %s version.\n",
- revision);
- }
- fseek(ifp, 0L, SEEK_SET); /* rewind file */
- lines_per_buf = BUFFERSIZE / maxlen;
- tireclen = maxlen;
- tibuf[0] = malloc(BUFFERSIZE + 1);
- if (tibuf[0] == NULL)
- fatal("out of memory\n");
- tibuf[1] = malloc(BUFFERSIZE + 1);
- if (tibuf[1] == NULL)
- fatal("out of memory\n");
- for (i = 1;; i++) {
- p = tibuf[0] + maxlen * (i % lines_per_buf);
- if (i % lines_per_buf == 0) /* new block */
- if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
- pfatal("can't write temp file");
- if (fgets(p, maxlen + 1, ifp) == NULL) {
- input_lines = i - 1;
- if (i % lines_per_buf != 0)
- if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
- pfatal("can't write temp file");
- break;
- }
- j = strlen(p);
- /* These are '\n' terminated strings, so no need to add a NUL */
- if (j == 0 || p[j - 1] != '\n')
- p[j] = '\n';
- }
- fclose(ifp);
- close(tifd);
- if ((tifd = open(TMPINNAME, O_RDONLY)) < 0)
- pfatal("can't reopen file %s", TMPINNAME);
-}
-
-/*
- * Fetch a line from the input file, \n terminated, not necessarily \0.
- */
-char *
-ifetch(LINENUM line, int whichbuf)
-{
- if (line < 1 || line > input_lines) {
- if (warn_on_invalid_line) {
- say("No such line %ld in input file, ignoring\n", line);
- warn_on_invalid_line = false;
- }
- return NULL;
- }
- if (using_plan_a)
- return i_ptr[line];
- else {
- LINENUM offline = line % lines_per_buf;
- LINENUM baseline = line - offline;
-
- if (tiline[0] == baseline)
- whichbuf = 0;
- else if (tiline[1] == baseline)
- whichbuf = 1;
- else {
- tiline[whichbuf] = baseline;
-
- lseek(tifd, (off_t) (baseline / lines_per_buf *
- BUFFERSIZE), SEEK_SET);
-
- if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
- pfatal("error reading tmp file %s", TMPINNAME);
- }
- return tibuf[whichbuf] + (tireclen * offline);
- }
-}
-
-/*
- * True if the string argument contains the revision number we want.
- */
-static bool
-rev_in_string(const char *string)
-{
- const char *s;
- int patlen;
-
- if (revision == NULL)
- return true;
- patlen = strlen(revision);
- if (strnEQ(string, revision, patlen) && isspace(string[patlen]))
- return true;
- for (s = string; *s; s++) {
- if (isspace(*s) && strnEQ(s + 1, revision, patlen) &&
- isspace(s[patlen + 1])) {
- return true;
- }
- }
- return false;
-}
diff --git a/usr.bin/patch/inp.h b/usr.bin/patch/inp.h
deleted file mode 100644
index aa66208fdc8b2..0000000000000
--- a/usr.bin/patch/inp.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* $OpenBSD: inp.h,v 1.8 2003/08/15 08:00:51 otto Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-void re_input(void);
-void scan_input(const char *);
-char *ifetch(LINENUM, int);
diff --git a/usr.bin/patch/patch.1 b/usr.bin/patch/patch.1
deleted file mode 100644
index 9d12b8b12bd77..0000000000000
--- a/usr.bin/patch/patch.1
+++ /dev/null
@@ -1,641 +0,0 @@
-.\" $OpenBSD: patch.1,v 1.17 2003/10/31 20:20:45 millert Exp $
-.\" Copyright 1986, Larry Wall
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following condition
-.\" is met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this condition and the following disclaimer.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.Dd July 23, 2003
-.Dt PATCH 1
-.Os
-.Sh NAME
-.Nm patch
-.Nd apply a diff file to an original
-.Sh SYNOPSIS
-.Nm patch
-.Op Cm options
-.Op Ar origfile Op Ar patchfile
-.Nm patch
-.Pf \*(Lt Ar patchfile
-.Sh DESCRIPTION
-.Nm
-will take a patch file containing any of the four forms of difference
-listing produced by the
-.Xr diff 1
-program and apply those differences to an original file,
-producing a patched version.
-If
-.Ar patchfile
-is omitted, or is a hyphen, the patch will be read from the standard input.
-.Pp
-.Nm
-will attempt to determine the type of the diff listing, unless over-ruled by a
-.Fl c ,
-.Fl e ,
-.Fl n ,
-or
-.Fl u
-option.
-Context diffs (old-style, new-style, and unified) and
-normal diffs are applied directly by the
-.Nm
-program itself, whereas ed diffs are simply fed to the
-.Xr ed 1
-editor via a pipe.
-.Pp
-If the
-.Ar patchfile
-contains more than one patch,
-.Nm
-will try to apply each of them as if they came from separate patch files.
-This means, among other things, that it is assumed that the name of the file
-to patch must be determined for each diff listing, and that the garbage before
-each diff listing will be examined for interesting things such as file names
-and revision level (see the section on
-.Sx Filename Determination
-below).
-.Pp
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl b , Fl Fl backup
-Save a backup copy of the file before it is modified.
-By default the original file is saved with a backup extension of
-.Qq .orig
-unless the file already has a numbered backup, in which case a numbered
-backup is made.
-This is equivalent to specifying
-.Qo Fl V Ar existing Qc .
-This option is currently the default but that will change in a future release.
-.It Fl B , Fl Fl prefix
-Causes the next argument to be interpreted as a prefix to the backup file
-name.
-If this argument is specified, any argument to
-.Fl z
-will be ignored.
-.It Fl c , Fl Fl context
-Forces
-.Nm
-to interpret the patch file as a context diff.
-.It Fl C , Fl Fl check
-Checks that the patch would apply cleanly, but does not modify anything.
-.It Fl d , Fl Fl directory
-Causes
-.Nm
-to interpret the next argument as a directory, and
-.Xr cd 1
-to it before doing anything else.
-.It Fl D , Fl Fl ifdef
-Causes
-.Nm
-to use the
-.Qq #ifdef...#endif
-construct to mark changes.
-The argument following will be used as the differentiating symbol.
-Note that, unlike the C compiler, there must be a space between the
-.Fl D
-and the argument.
-.It Fl e , Fl Fl ed
-Forces
-.Nm
-to interpret the patch file as an
-.Xr ed 1
-script.
-.It Fl E , Fl Fl remove-empty-files
-Causes
-.Nm
-to remove output files that are empty after the patches have been applied.
-This option is useful when applying patches that create or remove files.
-.It Fl f , Fl Fl force
-Forces
-.Nm
-to assume that the user knows exactly what he or she is doing, and to not
-ask any questions.
-It assumes the following:
-skip patches for which a file to patch can't be found;
-patch files even though they have the wrong version for the
-.Qq Prereq:
-line in the patch;
-and assume that patches are not reversed even if they look like they are.
-This option does not suppress commentary; use
-.Fl s
-for that.
-.It Xo
-.Fl F Ns Aq Ar number ,
-.Fl Fl fuzz Aq Ar number
-.Xc
-Sets the maximum fuzz factor.
-This option only applies to context diffs, and causes
-.Nm
-to ignore up to that many lines in looking for places to install a hunk.
-Note that a larger fuzz factor increases the odds of a faulty patch.
-The default fuzz factor is 2, and it may not be set to more than
-the number of lines of context in the context diff, ordinarily 3.
-.It Fl i , Fl Fl input
-Causes the next argument to be interpreted as the input file name
-(i.e. a patchfile).
-This option may be specified multiple times.
-.It Fl l , Fl Fl ignore-whitespace
-Causes the pattern matching to be done loosely, in case the tabs and
-spaces have been munged in your input file.
-Any sequence of whitespace in the pattern line will match any sequence
-in the input file.
-Normal characters must still match exactly.
-Each line of the context must still match a line in the input file.
-.It Fl n , Fl Fl normal
-Forces
-.Nm
-to interpret the patch file as a normal diff.
-.It Fl N , Fl Fl forward
-Causes
-.Nm
-to ignore patches that it thinks are reversed or already applied.
-See also
-.Fl R .
-.It Fl o , Fl Fl output
-Causes the next argument to be interpreted as the output file name.
-.It Xo
-.Fl p Ns Aq Ar number ,
-.Fl Fl strip Aq Ar number
-.Xc
-Sets the pathname strip count,
-which controls how pathnames found in the patch file are treated,
-in case you keep your files in a different directory than the person who sent
-out the patch.
-The strip count specifies how many slashes are to be stripped from
-the front of the pathname.
-(Any intervening directory names also go away.)
-For example, supposing the file name in the patch file was
-.Pa /u/howard/src/blurfl/blurfl.c :
-.Pp
-Setting
-.Fl p Ns Ar 0
-gives the entire pathname unmodified.
-.Pp
-.Fl p Ns Ar 1
-gives
-.Pp
-.D1 Pa u/howard/src/blurfl/blurfl.c
-.Pp
-without the leading slash.
-.Pp
-.Fl p Ns Ar 4
-gives
-.Pp
-.D1 Pa blurfl/blurfl.c
-.Pp
-Not specifying
-.Fl p
-at all just gives you
-.Pa blurfl.c ,
-unless all of the directories in the leading path
-.Pq Pa u/howard/src/blurfl
-exist and that path is relative,
-in which case you get the entire pathname unmodified.
-Whatever you end up with is looked for either in the current directory,
-or the directory specified by the
-.Fl d
-option.
-.It Fl r , Fl Fl reject-file
-Causes the next argument to be interpreted as the reject file name.
-.It Fl R , Fl Fl reverse
-Tells
-.Nm
-that this patch was created with the old and new files swapped.
-(Yes, I'm afraid that does happen occasionally, human nature being what it
-is.)
-.Nm
-will attempt to swap each hunk around before applying it.
-Rejects will come out in the swapped format.
-The
-.Fl R
-option will not work with ed diff scripts because there is too little
-information to reconstruct the reverse operation.
-.Pp
-If the first hunk of a patch fails,
-.Nm
-will reverse the hunk to see if it can be applied that way.
-If it can, you will be asked if you want to have the
-.Fl R
-option set.
-If it can't, the patch will continue to be applied normally.
-(Note: this method cannot detect a reversed patch if it is a normal diff
-and if the first command is an append (i.e. it should have been a delete)
-since appends always succeed, due to the fact that a null context will match
-anywhere.
-Luckily, most patches add or change lines rather than delete them, so most
-reversed normal diffs will begin with a delete, which will fail, triggering
-the heuristic.)
-.It Xo
-.Fl s , Fl Fl quiet ,
-.Fl Fl silent
-.Xc
-Makes
-.Nm
-do its work silently, unless an error occurs.
-.It Fl t , Fl Fl batch
-Similar to
-.Fl f ,
-in that it suppresses questions, but makes some different assumptions:
-skip patches for which a file to patch can't be found (the same as
-.Fl f ) ;
-skip patches for which the file has the wrong version for the
-.Qq Prereq:
-line in the patch;
-and assume that patches are reversed if they look like they are.
-.It Fl u , Fl Fl unified
-Forces
-.Nm
-to interpret the patch file as a unified context diff (a unidiff).
-.It Fl v , Fl Fl version
-Causes
-.Nm
-to print out its revision header and patch level.
-.It Fl V , Fl Fl version-control
-Causes the next argument to be interpreted as a method for creating
-backup file names.
-The type of backups made can also be given in the
-.Ev PATCH_VERSION_CONTROL
-or
-.Ev VERSION_CONTROL
-environment variables, which are overridden by this option.
-The
-.Fl B
-option overrides this option, causing the prefix to always be used for
-making backup file names.
-The values of the
-.Ev PATCH_VERSION_CONTROL
-and
-.Ev VERSION_CONTROL
-environment variables and the argument to the
-.Fl V
-option are like the GNU Emacs
-.Dq version-control
-variable; they also recognize synonyms that are more descriptive.
-The valid values are (unique abbreviations are accepted):
-.Bl -tag -width Ds -offset indent
-.It t , numbered
-Always make numbered backups.
-.It nil , existing
-Make numbered backups of files that already have them,
-simple backups of the others.
-.It never , simple
-Always make simple backups.
-.El
-.It Xo
-.Fl x Ns Aq Ar number ,
-.Fl Fl debug Aq Ar number
-.Xc
-Sets internal debugging flags, and is of interest only to
-.Nm
-patchers.
-.It Fl z , Fl Fl suffix
-Causes the next argument to be interpreted as the backup extension, to be
-used in place of
-.Qq .orig .
-.It Fl Fl posix
-Enables strict
-.St -p1003.2
-conformance, specifically:
-.Bl -enum
-.It
-Backup files are not created unless the
-.Fl b
-option is specified.
-.It
-If unspecified, the file name used is the first of the old, new and
-index files that exists.
-.El
-.El
-.Ss Patch Application
-.Nm
-will try to skip any leading garbage, apply the diff,
-and then skip any trailing garbage.
-Thus you could feed an article or message containing a
-diff listing to
-.Nm patch ,
-and it should work.
-If the entire diff is indented by a consistent amount,
-this will be taken into account.
-.Pp
-With context diffs, and to a lesser extent with normal diffs,
-.Nm
-can detect when the line numbers mentioned in the patch are incorrect,
-and will attempt to find the correct place to apply each hunk of the patch.
-As a first guess, it takes the line number mentioned for the hunk, plus or
-minus any offset used in applying the previous hunk.
-If that is not the correct place,
-.Nm
-will scan both forwards and backwards for a set of lines matching the context
-given in the hunk.
-First
-.Nm
-looks for a place where all lines of the context match.
-If no such place is found, and it's a context diff, and the maximum fuzz factor
-is set to 1 or more, then another scan takes place ignoring the first and last
-line of context.
-If that fails, and the maximum fuzz factor is set to 2 or more,
-the first two and last two lines of context are ignored,
-and another scan is made.
-.Pq The default maximum fuzz factor is 2.
-.Pp
-If
-.Nm
-cannot find a place to install that hunk of the patch, it will put the hunk
-out to a reject file, which normally is the name of the output file plus
-.Qq .rej .
-(Note that the rejected hunk will come out in context diff form whether the
-input patch was a context diff or a normal diff.
-If the input was a normal diff, many of the contexts will simply be null.)
-The line numbers on the hunks in the reject file may be different than
-in the patch file: they reflect the approximate location patch thinks the
-failed hunks belong in the new file rather than the old one.
-.Pp
-As each hunk is completed, you will be told whether the hunk succeeded or
-failed, and which line (in the new file)
-.Nm
-thought the hunk should go on.
-If this is different from the line number specified in the diff,
-you will be told the offset.
-A single large offset MAY be an indication that a hunk was installed in the
-wrong place.
-You will also be told if a fuzz factor was used to make the match, in which
-case you should also be slightly suspicious.
-.Ss Filename Determination
-If no original file is specified on the command line,
-.Nm
-will try to figure out from the leading garbage what the name of the file
-to edit is.
-When checking a prospective file name, pathname components are stripped
-as specified by the
-.Fl p
-option and the file's existence and writability are checked relative
-to the current working directory (or the directory specified by the
-.Fl d
-option).
-.Pp
-If the diff is a context or unified diff,
-.Nm
-is able to determine the old and new file names from the diff header.
-For context diffs, the
-.Dq old
-file is specified in the line beginning with
-.Qq ***
-and the
-.Dq new
-file is specified in the line beginning with
-.Qq --- .
-For a unified diff, the
-.Dq old
-file is specified in the line beginning with
-.Qq ---
-and the
-.Dq new
-file is specified in the line beginning with
-.Qq +++ .
-If there is an
-.Qq Index:
-line in the leading garbage (regardless of the diff type),
-.Nm
-will use the file name from that line as the
-.Dq index
-file.
-.Pp
-.Nm
-will choose the file name by performing the following steps, with the first
-match used:
-.Bl -enum
-.It
-If
-.Nm
-is operating in strict
-.St -p1003.2
-mode, the first of the
-.Dq old ,
-.Dq new
-and
-.Dq index
-file names that exist is used.
-Otherwise,
-.Nm
-will examine either the
-.Dq old
-and
-.Dq new
-file names or, for a non-context diff, the
-.Dq index
-file name, and choose the file name with the fewest path components,
-the shortest basename, and the shortest total file name length (in that order).
-.It
-If no file exists,
-.Nm
-checks for the existence of the files in an SCCS or RCS directory
-(using the appropriate prefix or suffix) using the criteria specified
-above.
-If found,
-.Nm
-will attempt to get or check out the file.
-.It
-If no suitable file was found to patch, the patch file is a context or
-unified diff, and the old file was zero length, the new file name is
-created and used.
-.It
-If the file name still cannot be determined,
-.Nm
-will prompt the user for the file name to use.
-.El
-.Pp
-Additionally, if the leading garbage contains a
-.Qq Prereq:\ \&
-line,
-.Nm
-will take the first word from the prerequisites line (normally a version
-number) and check the input file to see if that word can be found.
-If not,
-.Nm
-will ask for confirmation before proceeding.
-.Pp
-The upshot of all this is that you should be able to say, while in a news
-interface, the following:
-.Pp
-.Dl | patch -d /usr/src/local/blurfl
-.Pp
-and patch a file in the blurfl directory directly from the article containing
-the patch.
-.Ss Backup Files
-By default, the patched version is put in place of the original, with
-the original file backed up to the same name with the extension
-.Qq .orig ,
-or as specified by the
-.Fl B ,
-.Fl V ,
-or
-.Fl z
-options.
-The extension used for making backup files may also be specified in the
-.Ev SIMPLE_BACKUP_SUFFIX
-environment variable, which is overridden by the options above.
-.Pp
-If the backup file is a symbolic or hard link to the original file,
-.Nm
-creates a new backup file name by changing the first lowercase letter
-in the last component of the file's name into uppercase.
-If there are no more lowercase letters in the name,
-it removes the first character from the name.
-It repeats this process until it comes up with a
-backup file that does not already exist or is not linked to the original file.
-.Pp
-You may also specify where you want the output to go with the
-.Fl o
-option; if that file already exists, it is backed up first.
-.Ss Notes For Patch Senders
-There are several things you should bear in mind if you are going to
-be sending out patches:
-.Pp
-First, you can save people a lot of grief by keeping a
-.Pa patchlevel.h
-file which is patched to increment the patch level as the first diff in the
-patch file you send out.
-If you put a
-.Qq Prereq:
-line in with the patch, it won't let them apply
-patches out of order without some warning.
-.Pp
-Second, make sure you've specified the file names right, either in a
-context diff header, or with an
-.Qq Index:
-line.
-If you are patching something in a subdirectory, be sure to tell the patch
-user to specify a
-.Fl p
-option as needed.
-.Pp
-Third, you can create a file by sending out a diff that compares a
-null file to the file you want to create.
-This will only work if the file you want to create doesn't exist already in
-the target directory.
-.Pp
-Fourth, take care not to send out reversed patches, since it makes people wonder
-whether they already applied the patch.
-.Pp
-Fifth, while you may be able to get away with putting 582 diff listings into
-one file, it is probably wiser to group related patches into separate files in
-case something goes haywire.
-.Sh ENVIRONMENT
-.Bl -tag -width "PATCH_VERSION_CONTROL" -compact
-.It Ev POSIXLY_CORRECT
-When set,
-.Nm
-behaves as if the
-.Fl Fl posix
-option has been specified.
-.It Ev SIMPLE_BACKUP_SUFFIX
-Extension to use for backup file names instead of
-.Qq .orig .
-.It Ev TMPDIR
-Directory to put temporary files in; default is
-.Pa /tmp .
-.It Ev PATCH_VERSION_CONTROL
-Selects when numbered backup files are made.
-.It Ev VERSION_CONTROL
-Same as
-.Ev PATCH_VERSION_CONTROL .
-.El
-.Sh FILES
-.Bl -tag -width "$TMPDIR/patch*" -compact
-.It Pa $TMPDIR/patch*
-.Nm
-temporary files
-.It Pa /dev/tty
-used to read input when
-.Nm
-prompts the user
-.El
-.Sh DIAGNOSTICS
-Too many to list here, but generally indicative that
-.Nm
-couldn't parse your patch file.
-.Pp
-The message
-.Qq Hmm...
-indicates that there is unprocessed text in the patch file and that
-.Nm
-is attempting to intuit whether there is a patch in that text and, if so,
-what kind of patch it is.
-.Pp
-The
-.Nm
-utility exits with one of the following values:
-.Pp
-.Bl -tag -width Ds -compact -offset indent
-.It \&0
-Successful completion.
-.It \&1
-One or more lines were written to a reject file.
-.It \*[Gt]\&1
-An error occurred.
-.El
-.Pp
-When applying a set of patches in a loop it behooves you to check this
-exit status so you don't apply a later patch to a partially patched file.
-.Sh SEE ALSO
-.Xr diff 1
-.Sh AUTHORS
-.An Larry Wall
-with many other contributors.
-.Sh CAVEATS
-.Nm
-cannot tell if the line numbers are off in an ed script, and can only detect
-bad line numbers in a normal diff when it finds a
-.Qq change
-or a
-.Qq delete
-command.
-A context diff using fuzz factor 3 may have the same problem.
-Until a suitable interactive interface is added, you should probably do
-a context diff in these cases to see if the changes made sense.
-Of course, compiling without errors is a pretty good indication that the patch
-worked, but not always.
-.Pp
-.Nm
-usually produces the correct results, even when it has to do a lot of
-guessing.
-However, the results are guaranteed to be correct only when the patch is
-applied to exactly the same version of the file that the patch was
-generated from.
-.Sh BUGS
-Could be smarter about partial matches, excessively deviant offsets and
-swapped code, but that would take an extra pass.
-.Pp
-Check patch mode
-.Pq Fl C
-will fail if you try to check several patches in succession that build on
-each other.
-The entire
-.Nm
-code would have to be restructured to keep temporary files around so that it
-can handle this situation.
-.Pp
-If code has been duplicated (for instance with #ifdef OLDCODE ... #else ...
-#endif),
-.Nm
-is incapable of patching both versions, and, if it works at all, will likely
-patch the wrong one, and tell you that it succeeded to boot.
-.Pp
-If you apply a patch you've already applied,
-.Nm
-will think it is a reversed patch, and offer to un-apply the patch.
-This could be construed as a feature.
diff --git a/usr.bin/patch/patch.c b/usr.bin/patch/patch.c
deleted file mode 100644
index 7b754871ba9bf..0000000000000
--- a/usr.bin/patch/patch.c
+++ /dev/null
@@ -1,974 +0,0 @@
-/* $OpenBSD: patch.c,v 1.41 2004/07/09 19:13:46 otto Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-#ifndef lint
-static const char rcsid[] = "$OpenBSD: patch.c,v 1.41 2004/07/09 19:13:46 otto Exp $";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <ctype.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "common.h"
-#include "util.h"
-#include "pch.h"
-#include "inp.h"
-#include "backupfile.h"
-#include "pathnames.h"
-
-int filemode = 0644;
-
-char buf[MAXLINELEN]; /* general purpose buffer */
-
-bool using_plan_a = true; /* try to keep everything in memory */
-bool out_of_mem = false; /* ran out of memory in plan a */
-
-#define MAXFILEC 2
-
-char *filearg[MAXFILEC];
-bool ok_to_create_file = false;
-char *outname = NULL;
-char *origprae = NULL;
-char *TMPOUTNAME;
-char *TMPINNAME;
-char *TMPREJNAME;
-char *TMPPATNAME;
-bool toutkeep = false;
-bool trejkeep = false;
-bool warn_on_invalid_line;
-bool last_line_missing_eol;
-
-#ifdef DEBUGGING
-int debug = 0;
-#endif
-
-bool force = false;
-bool batch = false;
-bool verbose = true;
-bool reverse = false;
-bool noreverse = false;
-bool skip_rest_of_patch = false;
-int strippath = 957;
-bool canonicalize = false;
-bool check_only = false;
-int diff_type = 0;
-char *revision = NULL; /* prerequisite revision, if any */
-LINENUM input_lines = 0; /* how long is input file in lines */
-int posix = 0; /* strict POSIX mode? */
-
-static void reinitialize_almost_everything(void);
-static void get_some_switches(void);
-static LINENUM locate_hunk(LINENUM);
-static void abort_hunk(void);
-static void apply_hunk(LINENUM);
-static void init_output(const char *);
-static void init_reject(const char *);
-static void copy_till(LINENUM, bool);
-static void spew_output(void);
-static void dump_line(LINENUM, bool);
-static bool patch_match(LINENUM, LINENUM, LINENUM);
-static bool similar(const char *, const char *, int);
-static __dead void usage(void);
-
-/* true if -E was specified on command line. */
-static bool remove_empty_files = false;
-
-/* true if -R was specified on command line. */
-static bool reverse_flag_specified = false;
-
-/* buffer holding the name of the rejected patch file. */
-static char rejname[NAME_MAX + 1];
-
-/* buffer for stderr */
-static char serrbuf[BUFSIZ];
-
-/* how many input lines have been irretractibly output */
-static LINENUM last_frozen_line = 0;
-
-static int Argc; /* guess */
-static char **Argv;
-static int Argc_last; /* for restarting plan_b */
-static char **Argv_last;
-
-static FILE *ofp = NULL; /* output file pointer */
-static FILE *rejfp = NULL; /* reject file pointer */
-
-static int filec = 0; /* how many file arguments? */
-static LINENUM last_offset = 0;
-static LINENUM maxfuzz = 2;
-
-/* patch using ifdef, ifndef, etc. */
-static bool do_defines = false;
-/* #ifdef xyzzy */
-static char if_defined[128];
-/* #ifndef xyzzy */
-static char not_defined[128];
-/* #else */
-static const char else_defined[] = "#else\n";
-/* #endif xyzzy */
-static char end_defined[128];
-
-
-/* Apply a set of diffs as appropriate. */
-
-int
-main(int argc, char *argv[])
-{
- int error = 0, hunk, failed, patch_seen = 0, i, fd;
- LINENUM where = 0, newwhere, fuzz, mymaxfuzz;
- const char *tmpdir;
- char *v;
-
- setbuf(stderr, serrbuf);
- for (i = 0; i < MAXFILEC; i++)
- filearg[i] = NULL;
-
- /* Cons up the names of the temporary files. */
- if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
- tmpdir = _PATH_TMP;
- for (i = strlen(tmpdir) - 1; i > 0 && tmpdir[i] == '/'; i--)
- ;
- i++;
- if (asprintf(&TMPOUTNAME, "%.*s/patchoXXXXXXXXXX", i, tmpdir) == -1)
- fatal("cannot allocate memory");
- if ((fd = mkstemp(TMPOUTNAME)) < 0)
- pfatal("can't create %s", TMPOUTNAME);
- close(fd);
-
- if (asprintf(&TMPINNAME, "%.*s/patchiXXXXXXXXXX", i, tmpdir) == -1)
- fatal("cannot allocate memory");
- if ((fd = mkstemp(TMPINNAME)) < 0)
- pfatal("can't create %s", TMPINNAME);
- close(fd);
-
- if (asprintf(&TMPREJNAME, "%.*s/patchrXXXXXXXXXX", i, tmpdir) == -1)
- fatal("cannot allocate memory");
- if ((fd = mkstemp(TMPREJNAME)) < 0)
- pfatal("can't create %s", TMPREJNAME);
- close(fd);
-
- if (asprintf(&TMPPATNAME, "%.*s/patchpXXXXXXXXXX", i, tmpdir) == -1)
- fatal("cannot allocate memory");
- if ((fd = mkstemp(TMPPATNAME)) < 0)
- pfatal("can't create %s", TMPPATNAME);
- close(fd);
-
- v = getenv("SIMPLE_BACKUP_SUFFIX");
- if (v)
- simple_backup_suffix = v;
- else
- simple_backup_suffix = ORIGEXT;
-
- /* parse switches */
- Argc = argc;
- Argv = argv;
- get_some_switches();
-
- if (backup_type == none) {
- if ((v = getenv("PATCH_VERSION_CONTROL")) == NULL)
- v = getenv("VERSION_CONTROL");
- if (v != NULL || !posix)
- backup_type = get_version(v); /* OK to pass NULL. */
- }
-
- /* make sure we clean up /tmp in case of disaster */
- set_signals(0);
-
- for (open_patch_file(filearg[1]); there_is_another_patch();
- reinitialize_almost_everything()) {
- /* for each patch in patch file */
-
- patch_seen = true;
- warn_on_invalid_line = true;
-
- if (outname == NULL)
- outname = savestr(filearg[0]);
-
- /* for ed script just up and do it and exit */
- if (diff_type == ED_DIFF) {
- do_ed_script();
- continue;
- }
- /* initialize the patched file */
- if (!skip_rest_of_patch)
- init_output(TMPOUTNAME);
-
- /* initialize reject file */
- init_reject(TMPREJNAME);
-
- /* find out where all the lines are */
- if (!skip_rest_of_patch)
- scan_input(filearg[0]);
-
- /* from here on, open no standard i/o files, because malloc */
- /* might misfire and we can't catch it easily */
-
- /* apply each hunk of patch */
- hunk = 0;
- failed = 0;
- out_of_mem = false;
- while (another_hunk()) {
- hunk++;
- fuzz = 0;
- mymaxfuzz = pch_context();
- if (maxfuzz < mymaxfuzz)
- mymaxfuzz = maxfuzz;
- if (!skip_rest_of_patch) {
- do {
- where = locate_hunk(fuzz);
- if (hunk == 1 && where == 0 && !force) {
- /* dwim for reversed patch? */
- if (!pch_swap()) {
- if (fuzz == 0)
- say("Not enough memory to try swapped hunk! Assuming unswapped.\n");
- continue;
- }
- reverse = !reverse;
- /* try again */
- where = locate_hunk(fuzz);
- if (where == 0) {
- /* didn't find it swapped */
- if (!pch_swap())
- /* put it back to normal */
- fatal("lost hunk on alloc error!\n");
- reverse = !reverse;
- } else if (noreverse) {
- if (!pch_swap())
- /* put it back to normal */
- fatal("lost hunk on alloc error!\n");
- reverse = !reverse;
- say("Ignoring previously applied (or reversed) patch.\n");
- skip_rest_of_patch = true;
- } else if (batch) {
- if (verbose)
- say("%seversed (or previously applied) patch detected! %s -R.",
- reverse ? "R" : "Unr",
- reverse ? "Assuming" : "Ignoring");
- } else {
- ask("%seversed (or previously applied) patch detected! %s -R? [y] ",
- reverse ? "R" : "Unr",
- reverse ? "Assume" : "Ignore");
- if (*buf == 'n') {
- ask("Apply anyway? [n] ");
- if (*buf != 'y')
- skip_rest_of_patch = true;
- where = 0;
- reverse = !reverse;
- if (!pch_swap())
- /* put it back to normal */
- fatal("lost hunk on alloc error!\n");
- }
- }
- }
- } while (!skip_rest_of_patch && where == 0 &&
- ++fuzz <= mymaxfuzz);
-
- if (skip_rest_of_patch) { /* just got decided */
- fclose(ofp);
- ofp = NULL;
- }
- }
- newwhere = pch_newfirst() + last_offset;
- if (skip_rest_of_patch) {
- abort_hunk();
- failed++;
- if (verbose)
- say("Hunk #%d ignored at %ld.\n",
- hunk, newwhere);
- } else if (where == 0) {
- abort_hunk();
- failed++;
- if (verbose)
- say("Hunk #%d failed at %ld.\n",
- hunk, newwhere);
- } else {
- apply_hunk(where);
- if (verbose) {
- say("Hunk #%d succeeded at %ld",
- hunk, newwhere);
- if (fuzz != 0)
- say(" with fuzz %ld", fuzz);
- if (last_offset)
- say(" (offset %ld line%s)",
- last_offset,
- last_offset == 1L ? "" : "s");
- say(".\n");
- }
- }
- }
-
- if (out_of_mem && using_plan_a) {
- Argc = Argc_last;
- Argv = Argv_last;
- say("\n\nRan out of memory using Plan A--trying again...\n\n");
- if (ofp)
- fclose(ofp);
- ofp = NULL;
- if (rejfp)
- fclose(rejfp);
- rejfp = NULL;
- continue;
- }
- if (hunk == 0)
- fatal("Internal error: hunk should not be 0\n");
-
- /* finish spewing out the new file */
- if (!skip_rest_of_patch)
- spew_output();
-
- /* and put the output where desired */
- ignore_signals();
- if (!skip_rest_of_patch) {
- struct stat statbuf;
- char *realout = outname;
-
- if (!check_only) {
- if (move_file(TMPOUTNAME, outname) < 0) {
- toutkeep = true;
- realout = TMPOUTNAME;
- chmod(TMPOUTNAME, filemode);
- } else
- chmod(outname, filemode);
-
- if (remove_empty_files &&
- stat(realout, &statbuf) == 0 &&
- statbuf.st_size == 0) {
- if (verbose)
- say("Removing %s (empty after patching).\n",
- realout);
- unlink(realout);
- }
- }
- }
- fclose(rejfp);
- rejfp = NULL;
- if (failed) {
- error = 1;
- if (*rejname == '\0') {
- if (strlcpy(rejname, outname,
- sizeof(rejname)) >= sizeof(rejname))
- fatal("filename %s is too long\n", outname);
- if (strlcat(rejname, REJEXT,
- sizeof(rejname)) >= sizeof(rejname))
- fatal("filename %s is too long\n", outname);
- }
- if (skip_rest_of_patch) {
- say("%d out of %d hunks ignored--saving rejects to %s\n",
- failed, hunk, rejname);
- } else {
- say("%d out of %d hunks failed--saving rejects to %s\n",
- failed, hunk, rejname);
- }
- if (!check_only && move_file(TMPREJNAME, rejname) < 0)
- trejkeep = true;
- }
- set_signals(1);
- }
- my_exit(error);
- /* NOTREACHED */
-}
-
-/* Prepare to find the next patch to do in the patch file. */
-
-static void
-reinitialize_almost_everything(void)
-{
- re_patch();
- re_input();
-
- input_lines = 0;
- last_frozen_line = 0;
-
- filec = 0;
- if (!out_of_mem) {
- free(filearg[0]);
- filearg[0] = NULL;
- }
-
- free(outname);
- outname = NULL;
-
- last_offset = 0;
- diff_type = 0;
-
- free(revision);
- revision = NULL;
-
- reverse = reverse_flag_specified;
- skip_rest_of_patch = false;
-
- get_some_switches();
-}
-
-/* Process switches and filenames. */
-
-static void
-get_some_switches(void)
-{
- const char *options = "b::B:cCd:D:eEfF:i:lnNo:p:r:RstuvV:x:z:";
- static struct option longopts[] = {
- {"backup", no_argument, 0, 'b'},
- {"batch", no_argument, 0, 't'},
- {"check", no_argument, 0, 'C'},
- {"context", no_argument, 0, 'c'},
- {"debug", required_argument, 0, 'x'},
- {"directory", required_argument, 0, 'd'},
- {"ed", no_argument, 0, 'e'},
- {"force", no_argument, 0, 'f'},
- {"forward", no_argument, 0, 'N'},
- {"fuzz", required_argument, 0, 'F'},
- {"ifdef", required_argument, 0, 'D'},
- {"input", required_argument, 0, 'i'},
- {"ignore-whitespace", no_argument, 0, 'l'},
- {"normal", no_argument, 0, 'n'},
- {"output", required_argument, 0, 'o'},
- {"prefix", required_argument, 0, 'B'},
- {"quiet", no_argument, 0, 's'},
- {"reject-file", required_argument, 0, 'r'},
- {"remove-empty-files", no_argument, 0, 'E'},
- {"reverse", no_argument, 0, 'R'},
- {"silent", no_argument, 0, 's'},
- {"strip", required_argument, 0, 'p'},
- {"suffix", required_argument, 0, 'z'},
- {"unified", no_argument, 0, 'u'},
- {"version", no_argument, 0, 'v'},
- {"version-control", required_argument, 0, 'V'},
- {"posix", no_argument, &posix, 1},
- {NULL, 0, 0, 0}
- };
- int ch;
-
- rejname[0] = '\0';
- Argc_last = Argc;
- Argv_last = Argv;
- if (!Argc)
- return;
- optreset = optind = 1;
- while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) {
- switch (ch) {
- case 'b':
- if (backup_type == none)
- backup_type = numbered_existing;
- if (optarg == NULL)
- break;
- if (verbose)
- say("Warning, the ``-b suffix'' option has been"
- " obsoleted by the -z option.\n");
- /* FALLTHROUGH */
- case 'z':
- /* must directly follow 'b' case for backwards compat */
- simple_backup_suffix = savestr(optarg);
- break;
- case 'B':
- origprae = savestr(optarg);
- break;
- case 'c':
- diff_type = CONTEXT_DIFF;
- break;
- case 'C':
- check_only = true;
- break;
- case 'd':
- if (chdir(optarg) < 0)
- pfatal("can't cd to %s", optarg);
- break;
- case 'D':
- do_defines = true;
- if (!isalpha(*optarg) && *optarg != '_')
- fatal("argument to -D is not an identifier\n");
- snprintf(if_defined, sizeof if_defined,
- "#ifdef %s\n", optarg);
- snprintf(not_defined, sizeof not_defined,
- "#ifndef %s\n", optarg);
- snprintf(end_defined, sizeof end_defined,
- "#endif /* %s */\n", optarg);
- break;
- case 'e':
- diff_type = ED_DIFF;
- break;
- case 'E':
- remove_empty_files = true;
- break;
- case 'f':
- force = true;
- break;
- case 'F':
- maxfuzz = atoi(optarg);
- break;
- case 'i':
- if (++filec == MAXFILEC)
- fatal("too many file arguments\n");
- filearg[filec] = savestr(optarg);
- break;
- case 'l':
- canonicalize = true;
- break;
- case 'n':
- diff_type = NORMAL_DIFF;
- break;
- case 'N':
- noreverse = true;
- break;
- case 'o':
- outname = savestr(optarg);
- break;
- case 'p':
- strippath = atoi(optarg);
- break;
- case 'r':
- if (strlcpy(rejname, optarg,
- sizeof(rejname)) >= sizeof(rejname))
- fatal("argument for -r is too long\n");
- break;
- case 'R':
- reverse = true;
- reverse_flag_specified = true;
- break;
- case 's':
- verbose = false;
- break;
- case 't':
- batch = true;
- break;
- case 'u':
- diff_type = UNI_DIFF;
- break;
- case 'v':
- version();
- break;
- case 'V':
- backup_type = get_version(optarg);
- break;
-#ifdef DEBUGGING
- case 'x':
- debug = atoi(optarg);
- break;
-#endif
- default:
- if (ch != '\0')
- usage();
- break;
- }
- }
- Argc -= optind;
- Argv += optind;
-
- if (Argc > 0) {
- filearg[0] = savestr(*Argv++);
- Argc--;
- while (Argc > 0) {
- if (++filec == MAXFILEC)
- fatal("too many file arguments\n");
- filearg[filec] = savestr(*Argv++);
- Argc--;
- }
- }
-
- if (getenv("POSIXLY_CORRECT") != NULL)
- posix = 1;
-}
-
-static __dead void
-usage(void)
-{
- fprintf(stderr,
-"usage: patch [-bcCeEflnNRstuv] [-B backup-prefix] [-d directory] [-D symbol]\n"
-" [-F max-fuzz] [-i patchfile] [-o out-file] [-p strip-count]\n"
-" [-r rej-name] [-V {numbered,existing,simple}] [-z backup-ext]\n"
-" [origfile [patchfile]]\n");
- my_exit(EXIT_SUCCESS);
-}
-
-/*
- * Attempt to find the right place to apply this hunk of patch.
- */
-static LINENUM
-locate_hunk(LINENUM fuzz)
-{
- LINENUM first_guess = pch_first() + last_offset;
- LINENUM offset;
- LINENUM pat_lines = pch_ptrn_lines();
- LINENUM max_pos_offset = input_lines - first_guess - pat_lines + 1;
- LINENUM max_neg_offset = first_guess - last_frozen_line - 1 + pch_context();
-
- if (pat_lines == 0) { /* null range matches always */
- if (verbose && fuzz == 0 && (diff_type == CONTEXT_DIFF
- || diff_type == NEW_CONTEXT_DIFF
- || diff_type == UNI_DIFF)) {
- say("Empty context always matches.\n");
- }
- if (diff_type == CONTEXT_DIFF
- || diff_type == NEW_CONTEXT_DIFF
- || diff_type == UNI_DIFF) {
- if (fuzz == 0)
- return (input_lines == 0 ? first_guess : 0);
- } else
- return (first_guess);
- }
- if (max_neg_offset >= first_guess) /* do not try lines < 0 */
- max_neg_offset = first_guess - 1;
- if (first_guess <= input_lines && patch_match(first_guess, 0, fuzz))
- return first_guess;
- for (offset = 1; ; offset++) {
- bool check_after = (offset <= max_pos_offset);
- bool check_before = (offset <= max_neg_offset);
-
- if (check_after && patch_match(first_guess, offset, fuzz)) {
-#ifdef DEBUGGING
- if (debug & 1)
- say("Offset changing from %ld to %ld\n",
- last_offset, offset);
-#endif
- last_offset = offset;
- return first_guess + offset;
- } else if (check_before && patch_match(first_guess, -offset, fuzz)) {
-#ifdef DEBUGGING
- if (debug & 1)
- say("Offset changing from %ld to %ld\n",
- last_offset, -offset);
-#endif
- last_offset = -offset;
- return first_guess - offset;
- } else if (!check_before && !check_after)
- return 0;
- }
-}
-
-/* We did not find the pattern, dump out the hunk so they can handle it. */
-
-static void
-abort_hunk(void)
-{
- LINENUM i;
- const LINENUM pat_end = pch_end();
- /*
- * add in last_offset to guess the same as the previous successful
- * hunk
- */
- const LINENUM oldfirst = pch_first() + last_offset;
- const LINENUM newfirst = pch_newfirst() + last_offset;
- const LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
- const LINENUM newlast = newfirst + pch_repl_lines() - 1;
- const char *stars = (diff_type >= NEW_CONTEXT_DIFF ? " ****" : "");
- const char *minuses = (diff_type >= NEW_CONTEXT_DIFF ? " ----" : " -----");
-
- fprintf(rejfp, "***************\n");
- for (i = 0; i <= pat_end; i++) {
- switch (pch_char(i)) {
- case '*':
- if (oldlast < oldfirst)
- fprintf(rejfp, "*** 0%s\n", stars);
- else if (oldlast == oldfirst)
- fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
- else
- fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst,
- oldlast, stars);
- break;
- case '=':
- if (newlast < newfirst)
- fprintf(rejfp, "--- 0%s\n", minuses);
- else if (newlast == newfirst)
- fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
- else
- fprintf(rejfp, "--- %ld,%ld%s\n", newfirst,
- newlast, minuses);
- break;
- case '\n':
- fprintf(rejfp, "%s", pfetch(i));
- break;
- case ' ':
- case '-':
- case '+':
- case '!':
- fprintf(rejfp, "%c %s", pch_char(i), pfetch(i));
- break;
- default:
- fatal("fatal internal error in abort_hunk\n");
- }
- }
-}
-
-/* We found where to apply it (we hope), so do it. */
-
-static void
-apply_hunk(LINENUM where)
-{
- LINENUM old = 1;
- const LINENUM lastline = pch_ptrn_lines();
- LINENUM new = lastline + 1;
-#define OUTSIDE 0
-#define IN_IFNDEF 1
-#define IN_IFDEF 2
-#define IN_ELSE 3
- int def_state = OUTSIDE;
- const LINENUM pat_end = pch_end();
-
- where--;
- while (pch_char(new) == '=' || pch_char(new) == '\n')
- new++;
-
- while (old <= lastline) {
- if (pch_char(old) == '-') {
- copy_till(where + old - 1, false);
- if (do_defines) {
- if (def_state == OUTSIDE) {
- fputs(not_defined, ofp);
- def_state = IN_IFNDEF;
- } else if (def_state == IN_IFDEF) {
- fputs(else_defined, ofp);
- def_state = IN_ELSE;
- }
- fputs(pfetch(old), ofp);
- }
- last_frozen_line++;
- old++;
- } else if (new > pat_end) {
- break;
- } else if (pch_char(new) == '+') {
- copy_till(where + old - 1, false);
- if (do_defines) {
- if (def_state == IN_IFNDEF) {
- fputs(else_defined, ofp);
- def_state = IN_ELSE;
- } else if (def_state == OUTSIDE) {
- fputs(if_defined, ofp);
- def_state = IN_IFDEF;
- }
- }
- fputs(pfetch(new), ofp);
- new++;
- } else if (pch_char(new) != pch_char(old)) {
- say("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n",
- pch_hunk_beg() + old,
- pch_hunk_beg() + new);
-#ifdef DEBUGGING
- say("oldchar = '%c', newchar = '%c'\n",
- pch_char(old), pch_char(new));
-#endif
- my_exit(2);
- } else if (pch_char(new) == '!') {
- copy_till(where + old - 1, false);
- if (do_defines) {
- fputs(not_defined, ofp);
- def_state = IN_IFNDEF;
- }
- while (pch_char(old) == '!') {
- if (do_defines) {
- fputs(pfetch(old), ofp);
- }
- last_frozen_line++;
- old++;
- }
- if (do_defines) {
- fputs(else_defined, ofp);
- def_state = IN_ELSE;
- }
- while (pch_char(new) == '!') {
- fputs(pfetch(new), ofp);
- new++;
- }
- } else {
- if (pch_char(new) != ' ')
- fatal("Internal error: expected ' '\n");
- old++;
- new++;
- if (do_defines && def_state != OUTSIDE) {
- fputs(end_defined, ofp);
- def_state = OUTSIDE;
- }
- }
- }
- if (new <= pat_end && pch_char(new) == '+') {
- copy_till(where + old - 1, false);
- if (do_defines) {
- if (def_state == OUTSIDE) {
- fputs(if_defined, ofp);
- def_state = IN_IFDEF;
- } else if (def_state == IN_IFNDEF) {
- fputs(else_defined, ofp);
- def_state = IN_ELSE;
- }
- }
- while (new <= pat_end && pch_char(new) == '+') {
- fputs(pfetch(new), ofp);
- new++;
- }
- }
- if (do_defines && def_state != OUTSIDE) {
- fputs(end_defined, ofp);
- }
-}
-
-/*
- * Open the new file.
- */
-static void
-init_output(const char *name)
-{
- ofp = fopen(name, "w");
- if (ofp == NULL)
- pfatal("can't create %s", name);
-}
-
-/*
- * Open a file to put hunks we can't locate.
- */
-static void
-init_reject(const char *name)
-{
- rejfp = fopen(name, "w");
- if (rejfp == NULL)
- pfatal("can't create %s", name);
-}
-
-/*
- * Copy input file to output, up to wherever hunk is to be applied.
- * If endoffile is true, treat the last line specially since it may
- * lack a newline.
- */
-static void
-copy_till(LINENUM lastline, bool endoffile)
-{
- if (last_frozen_line > lastline)
- fatal("misordered hunks! output would be garbled\n");
- while (last_frozen_line < lastline) {
- if (++last_frozen_line == lastline && endoffile)
- dump_line(last_frozen_line, !last_line_missing_eol);
- else
- dump_line(last_frozen_line, true);
- }
-}
-
-/*
- * Finish copying the input file to the output file.
- */
-static void
-spew_output(void)
-{
-#ifdef DEBUGGING
- if (debug & 256)
- say("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
-#endif
- if (input_lines)
- copy_till(input_lines, true); /* dump remainder of file */
- fclose(ofp);
- ofp = NULL;
-}
-
-/*
- * Copy one line from input to output.
- */
-static void
-dump_line(LINENUM line, bool write_newline)
-{
- char *s;
-
- s = ifetch(line, 0);
- if (s == NULL)
- return;
- /* Note: string is not NUL terminated. */
- for (; *s != '\n'; s++)
- putc(*s, ofp);
- if (write_newline)
- putc('\n', ofp);
-}
-
-/*
- * Does the patch pattern match at line base+offset?
- */
-static bool
-patch_match(LINENUM base, LINENUM offset, LINENUM fuzz)
-{
- LINENUM pline = 1 + fuzz;
- LINENUM iline;
- LINENUM pat_lines = pch_ptrn_lines() - fuzz;
- const char *ilineptr;
- const char *plineptr;
- short plinelen;
-
- for (iline = base + offset + fuzz; pline <= pat_lines; pline++, iline++) {
- ilineptr = ifetch(iline, offset >= 0);
- if (ilineptr == NULL)
- return false;
- plineptr = pfetch(pline);
- plinelen = pch_line_len(pline);
- if (canonicalize) {
- if (!similar(ilineptr, plineptr, plinelen))
- return false;
- } else if (strnNE(ilineptr, plineptr, plinelen))
- return false;
- if (iline == input_lines) {
- /*
- * We are looking at the last line of the file.
- * If the file has no eol, the patch line should
- * not have one either and vice-versa. Note that
- * plinelen > 0.
- */
- if (last_line_missing_eol) {
- if (plineptr[plinelen - 1] == '\n')
- return false;
- } else {
- if (plineptr[plinelen - 1] != '\n')
- return false;
- }
- }
- }
- return true;
-}
-
-/*
- * Do two lines match with canonicalized white space?
- */
-static bool
-similar(const char *a, const char *b, int len)
-{
- while (len) {
- if (isspace(*b)) { /* whitespace (or \n) to match? */
- if (!isspace(*a)) /* no corresponding whitespace? */
- return false;
- while (len && isspace(*b) && *b != '\n')
- b++, len--; /* skip pattern whitespace */
- while (isspace(*a) && *a != '\n')
- a++; /* skip target whitespace */
- if (*a == '\n' || *b == '\n')
- return (*a == *b); /* should end in sync */
- } else if (*a++ != *b++) /* match non-whitespace chars */
- return false;
- else
- len--; /* probably not necessary */
- }
- return true; /* actually, this is not reached */
- /* since there is always a \n */
-}
diff --git a/usr.bin/patch/pathnames.h b/usr.bin/patch/pathnames.h
deleted file mode 100644
index 397e3fabe372f..0000000000000
--- a/usr.bin/patch/pathnames.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* $OpenBSD: pathnames.h,v 1.1 2003/07/29 20:10:17 millert Exp $ */
-
-/*
- * Placed in the public domain by Todd C. Miller <Todd.Miller@courtesan.com>
- * on July 29, 2003.
- */
-
-#include <paths.h>
-
-#define _PATH_ED "/bin/ed"
-#define _PATH_MKDIR "/bin/mkdir"
diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c
deleted file mode 100644
index bfdb176301007..0000000000000
--- a/usr.bin/patch/pch.c
+++ /dev/null
@@ -1,1549 +0,0 @@
-/* $OpenBSD: pch.c,v 1.34 2004/07/09 19:13:46 otto Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-#ifndef lint
-static const char rcsid[] = "$OpenBSD: pch.c,v 1.34 2004/07/09 19:13:46 otto Exp $";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <libgen.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "common.h"
-#include "util.h"
-#include "pch.h"
-#include "pathnames.h"
-
-/* Patch (diff listing) abstract type. */
-
-static long p_filesize; /* size of the patch file */
-static LINENUM p_first; /* 1st line number */
-static LINENUM p_newfirst; /* 1st line number of replacement */
-static LINENUM p_ptrn_lines; /* # lines in pattern */
-static LINENUM p_repl_lines; /* # lines in replacement text */
-static LINENUM p_end = -1; /* last line in hunk */
-static LINENUM p_max; /* max allowed value of p_end */
-static LINENUM p_context = 3; /* # of context lines */
-static LINENUM p_input_line = 0; /* current line # from patch file */
-static char **p_line = NULL;/* the text of the hunk */
-static short *p_len = NULL; /* length of each line */
-static char *p_char = NULL; /* +, -, and ! */
-static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */
-static int p_indent; /* indent to patch */
-static LINENUM p_base; /* where to intuit this time */
-static LINENUM p_bline; /* line # of p_base */
-static LINENUM p_start; /* where intuit found a patch */
-static LINENUM p_sline; /* and the line number for it */
-static LINENUM p_hunk_beg; /* line number of current hunk */
-static LINENUM p_efake = -1; /* end of faked up lines--don't free */
-static LINENUM p_bfake = -1; /* beg of faked up lines */
-static FILE *pfp = NULL; /* patch file pointer */
-static char *bestguess = NULL; /* guess at correct filename */
-
-static void grow_hunkmax(void);
-static int intuit_diff_type(void);
-static void next_intuit_at(LINENUM, LINENUM);
-static void skip_to(LINENUM, LINENUM);
-static char *pgets(char *, int, FILE *);
-static char *best_name(const struct file_name *, bool);
-static char *posix_name(const struct file_name *, bool);
-static size_t num_components(const char *);
-
-/*
- * Prepare to look for the next patch in the patch file.
- */
-void
-re_patch(void)
-{
- p_first = 0;
- p_newfirst = 0;
- p_ptrn_lines = 0;
- p_repl_lines = 0;
- p_end = (LINENUM) - 1;
- p_max = 0;
- p_indent = 0;
-}
-
-/*
- * Open the patch file at the beginning of time.
- */
-void
-open_patch_file(const char *filename)
-{
- struct stat filestat;
-
- if (filename == NULL || *filename == '\0' || strEQ(filename, "-")) {
- pfp = fopen(TMPPATNAME, "w");
- if (pfp == NULL)
- pfatal("can't create %s", TMPPATNAME);
- while (fgets(buf, sizeof buf, stdin) != NULL)
- fputs(buf, pfp);
- fclose(pfp);
- filename = TMPPATNAME;
- }
- pfp = fopen(filename, "r");
- if (pfp == NULL)
- pfatal("patch file %s not found", filename);
- fstat(fileno(pfp), &filestat);
- p_filesize = filestat.st_size;
- next_intuit_at(0L, 1L); /* start at the beginning */
- set_hunkmax();
-}
-
-/*
- * Make sure our dynamically realloced tables are malloced to begin with.
- */
-void
-set_hunkmax(void)
-{
- if (p_line == NULL)
- p_line = malloc((size_t) hunkmax * sizeof(char *));
- if (p_len == NULL)
- p_len = malloc((size_t) hunkmax * sizeof(short));
- if (p_char == NULL)
- p_char = malloc((size_t) hunkmax * sizeof(char));
-}
-
-/*
- * Enlarge the arrays containing the current hunk of patch.
- */
-static void
-grow_hunkmax(void)
-{
- int new_hunkmax;
- char **new_p_line;
- short *new_p_len;
- char *new_p_char;
-
- new_hunkmax = hunkmax * 2;
-
- if (p_line == NULL || p_len == NULL || p_char == NULL)
- fatal("Internal memory allocation error\n");
-
- new_p_line = realloc(p_line, new_hunkmax * sizeof(char *));
- if (new_p_line == NULL)
- free(p_line);
-
- new_p_len = realloc(p_len, new_hunkmax * sizeof(short));
- if (new_p_len == NULL)
- free(p_len);
-
- new_p_char = realloc(p_char, new_hunkmax * sizeof(char));
- if (new_p_char == NULL)
- free(p_char);
-
- p_char = new_p_char;
- p_len = new_p_len;
- p_line = new_p_line;
-
- if (p_line != NULL && p_len != NULL && p_char != NULL) {
- hunkmax = new_hunkmax;
- return;
- }
-
- if (!using_plan_a)
- fatal("out of memory\n");
- out_of_mem = true; /* whatever is null will be allocated again */
- /* from within plan_a(), of all places */
-}
-
-/* True if the remainder of the patch file contains a diff of some sort. */
-
-bool
-there_is_another_patch(void)
-{
- bool exists = false;
-
- if (p_base != 0L && p_base >= p_filesize) {
- if (verbose)
- say("done\n");
- return false;
- }
- if (verbose)
- say("Hmm...");
- diff_type = intuit_diff_type();
- if (!diff_type) {
- if (p_base != 0L) {
- if (verbose)
- say(" Ignoring the trailing garbage.\ndone\n");
- } else
- say(" I can't seem to find a patch in there anywhere.\n");
- return false;
- }
- if (verbose)
- say(" %sooks like %s to me...\n",
- (p_base == 0L ? "L" : "The next patch l"),
- diff_type == UNI_DIFF ? "a unified diff" :
- diff_type == CONTEXT_DIFF ? "a context diff" :
- diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
- diff_type == NORMAL_DIFF ? "a normal diff" :
- "an ed script");
- if (p_indent && verbose)
- say("(Patch is indented %d space%s.)\n", p_indent,
- p_indent == 1 ? "" : "s");
- skip_to(p_start, p_sline);
- while (filearg[0] == NULL) {
- if (force || batch) {
- say("No file to patch. Skipping...\n");
- filearg[0] = savestr(bestguess);
- skip_rest_of_patch = true;
- return true;
- }
- ask("File to patch: ");
- if (*buf != '\n') {
- free(bestguess);
- bestguess = savestr(buf);
- filearg[0] = fetchname(buf, &exists, 0);
- }
- if (!exists) {
- ask("No file found--skip this patch? [n] ");
- if (*buf != 'y')
- continue;
- if (verbose)
- say("Skipping patch...\n");
- free(filearg[0]);
- filearg[0] = fetchname(bestguess, &exists, 0);
- skip_rest_of_patch = true;
- return true;
- }
- }
- return true;
-}
-
-/* Determine what kind of diff is in the remaining part of the patch file. */
-
-static int
-intuit_diff_type(void)
-{
- long this_line = 0, previous_line;
- long first_command_line = -1;
- LINENUM fcl_line = -1;
- bool last_line_was_command = false, this_is_a_command = false;
- bool stars_last_line = false, stars_this_line = false;
- char *s, *t;
- int indent, retval;
- struct file_name names[MAX_FILE];
-
- memset(names, 0, sizeof(names));
- ok_to_create_file = false;
- fseek(pfp, p_base, SEEK_SET);
- p_input_line = p_bline - 1;
- for (;;) {
- previous_line = this_line;
- last_line_was_command = this_is_a_command;
- stars_last_line = stars_this_line;
- this_line = ftell(pfp);
- indent = 0;
- p_input_line++;
- if (fgets(buf, sizeof buf, pfp) == NULL) {
- if (first_command_line >= 0L) {
- /* nothing but deletes!? */
- p_start = first_command_line;
- p_sline = fcl_line;
- retval = ED_DIFF;
- goto scan_exit;
- } else {
- p_start = this_line;
- p_sline = p_input_line;
- retval = 0;
- goto scan_exit;
- }
- }
- for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
- if (*s == '\t')
- indent += 8 - (indent % 8);
- else
- indent++;
- }
- for (t = s; isdigit(*t) || *t == ','; t++)
- ;
- this_is_a_command = (isdigit(*s) &&
- (*t == 'd' || *t == 'c' || *t == 'a'));
- if (first_command_line < 0L && this_is_a_command) {
- first_command_line = this_line;
- fcl_line = p_input_line;
- p_indent = indent; /* assume this for now */
- }
- if (!stars_last_line && strnEQ(s, "*** ", 4))
- names[OLD_FILE].path = fetchname(s + 4,
- &names[OLD_FILE].exists, strippath);
- else if (strnEQ(s, "--- ", 4))
- names[NEW_FILE].path = fetchname(s + 4,
- &names[NEW_FILE].exists, strippath);
- else if (strnEQ(s, "+++ ", 4))
- /* pretend it is the old name */
- names[OLD_FILE].path = fetchname(s + 4,
- &names[OLD_FILE].exists, strippath);
- else if (strnEQ(s, "Index:", 6))
- names[INDEX_FILE].path = fetchname(s + 6,
- &names[INDEX_FILE].exists, strippath);
- else if (strnEQ(s, "Prereq:", 7)) {
- for (t = s + 7; isspace(*t); t++)
- ;
- revision = savestr(t);
- for (t = revision; *t && !isspace(*t); t++)
- ;
- *t = '\0';
- if (*revision == '\0') {
- free(revision);
- revision = NULL;
- }
- }
- if ((!diff_type || diff_type == ED_DIFF) &&
- first_command_line >= 0L &&
- strEQ(s, ".\n")) {
- p_indent = indent;
- p_start = first_command_line;
- p_sline = fcl_line;
- retval = ED_DIFF;
- goto scan_exit;
- }
- if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) {
- if (strnEQ(s + 4, "0,0", 3))
- ok_to_create_file = true;
- p_indent = indent;
- p_start = this_line;
- p_sline = p_input_line;
- retval = UNI_DIFF;
- goto scan_exit;
- }
- stars_this_line = strnEQ(s, "********", 8);
- if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
- strnEQ(s, "*** ", 4)) {
- if (atol(s + 4) == 0)
- ok_to_create_file = true;
- /*
- * If this is a new context diff the character just
- * before the newline is a '*'.
- */
- while (*s != '\n')
- s++;
- p_indent = indent;
- p_start = previous_line;
- p_sline = p_input_line - 1;
- retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
- goto scan_exit;
- }
- if ((!diff_type || diff_type == NORMAL_DIFF) &&
- last_line_was_command &&
- (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) {
- p_start = previous_line;
- p_sline = p_input_line - 1;
- p_indent = indent;
- retval = NORMAL_DIFF;
- goto scan_exit;
- }
- }
-scan_exit:
- if (retval == UNI_DIFF) {
- /* unswap old and new */
- struct file_name tmp = names[OLD_FILE];
- names[OLD_FILE] = names[NEW_FILE];
- names[NEW_FILE] = tmp;
- }
- if (filearg[0] == NULL) {
- if (posix)
- filearg[0] = posix_name(names, ok_to_create_file);
- else {
- /* Ignore the Index: name for context diffs, like GNU */
- if (names[OLD_FILE].path != NULL ||
- names[NEW_FILE].path != NULL) {
- free(names[INDEX_FILE].path);
- names[INDEX_FILE].path = NULL;
- }
- filearg[0] = best_name(names, ok_to_create_file);
- }
- }
-
- free(bestguess);
- bestguess = NULL;
- if (filearg[0] != NULL)
- bestguess = savestr(filearg[0]);
- else if (!ok_to_create_file) {
- /*
- * We don't want to create a new file but we need a
- * filename to set bestguess. Avoid setting filearg[0]
- * so the file is not created automatically.
- */
- if (posix)
- bestguess = posix_name(names, true);
- else
- bestguess = best_name(names, true);
- }
- free(names[OLD_FILE].path);
- free(names[NEW_FILE].path);
- free(names[INDEX_FILE].path);
- return retval;
-}
-
-/*
- * Remember where this patch ends so we know where to start up again.
- */
-static void
-next_intuit_at(LINENUM file_pos, LINENUM file_line)
-{
- p_base = file_pos;
- p_bline = file_line;
-}
-
-/*
- * Basically a verbose fseek() to the actual diff listing.
- */
-static void
-skip_to(LINENUM file_pos, LINENUM file_line)
-{
- char *ret;
-
- if (p_base > file_pos)
- fatal("Internal error: seek %ld>%ld\n", p_base, file_pos);
- if (verbose && p_base < file_pos) {
- fseek(pfp, p_base, SEEK_SET);
- say("The text leading up to this was:\n--------------------------\n");
- while (ftell(pfp) < file_pos) {
- ret = fgets(buf, sizeof buf, pfp);
- if (ret == NULL)
- fatal("Unexpected end of file\n");
- say("|%s", buf);
- }
- say("--------------------------\n");
- } else
- fseek(pfp, file_pos, SEEK_SET);
- p_input_line = file_line - 1;
-}
-
-/* Make this a function for better debugging. */
-static void
-malformed(void)
-{
- fatal("malformed patch at line %ld: %s", p_input_line, buf);
- /* about as informative as "Syntax error" in C */
-}
-
-/*
- * True if the line has been discarded (i.e. it is a line saying
- * "\ No newline at end of file".)
- */
-static bool
-remove_special_line(void)
-{
- int c;
-
- c = fgetc(pfp);
- if (c == '\\') {
- do {
- c = fgetc(pfp);
- } while (c != EOF && c != '\n');
-
- return true;
- }
- if (c != EOF)
- fseek(pfp, -1L, SEEK_CUR);
-
- return false;
-}
-
-/*
- * True if there is more of the current diff listing to process.
- */
-bool
-another_hunk(void)
-{
- long line_beginning; /* file pos of the current line */
- LINENUM repl_beginning; /* index of --- line */
- LINENUM fillcnt; /* #lines of missing ptrn or repl */
- LINENUM fillsrc; /* index of first line to copy */
- LINENUM filldst; /* index of first missing line */
- bool ptrn_spaces_eaten; /* ptrn was slightly misformed */
- bool repl_could_be_missing; /* no + or ! lines in this hunk */
- bool repl_missing; /* we are now backtracking */
- long repl_backtrack_position; /* file pos of first repl line */
- LINENUM repl_patch_line; /* input line number for same */
- LINENUM ptrn_copiable; /* # of copiable lines in ptrn */
- char *s, *ret;
- int context = 0;
-
- while (p_end >= 0) {
- if (p_end == p_efake)
- p_end = p_bfake; /* don't free twice */
- else
- free(p_line[p_end]);
- p_end--;
- }
- p_efake = -1;
-
- p_max = hunkmax; /* gets reduced when --- found */
- if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
- line_beginning = ftell(pfp);
- repl_beginning = 0;
- fillcnt = 0;
- ptrn_spaces_eaten = false;
- repl_could_be_missing = true;
- repl_missing = false;
- repl_backtrack_position = 0;
- ptrn_copiable = 0;
-
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL || strnNE(buf, "********", 8)) {
- next_intuit_at(line_beginning, p_input_line);
- return false;
- }
- p_context = 100;
- p_hunk_beg = p_input_line + 1;
- while (p_end < p_max) {
- line_beginning = ftell(pfp);
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL) {
- if (p_max - p_end < 4) {
- /* assume blank lines got chopped */
- strlcpy(buf, " \n", sizeof buf);
- } else {
- if (repl_beginning && repl_could_be_missing) {
- repl_missing = true;
- goto hunk_done;
- }
- fatal("unexpected end of file in patch\n");
- }
- }
- p_end++;
- if (p_end >= hunkmax)
- fatal("Internal error: hunk larger than hunk "
- "buffer size");
- p_char[p_end] = *buf;
- p_line[p_end] = NULL;
- switch (*buf) {
- case '*':
- if (strnEQ(buf, "********", 8)) {
- if (repl_beginning && repl_could_be_missing) {
- repl_missing = true;
- goto hunk_done;
- } else
- fatal("unexpected end of hunk "
- "at line %ld\n",
- p_input_line);
- }
- if (p_end != 0) {
- if (repl_beginning && repl_could_be_missing) {
- repl_missing = true;
- goto hunk_done;
- }
- fatal("unexpected *** at line %ld: %s",
- p_input_line, buf);
- }
- context = 0;
- p_line[p_end] = savestr(buf);
- if (out_of_mem) {
- p_end--;
- return false;
- }
- for (s = buf; *s && !isdigit(*s); s++)
- ;
- if (!*s)
- malformed();
- if (strnEQ(s, "0,0", 3))
- memmove(s, s + 2, strlen(s + 2) + 1);
- p_first = (LINENUM) atol(s);
- while (isdigit(*s))
- s++;
- if (*s == ',') {
- for (; *s && !isdigit(*s); s++)
- ;
- if (!*s)
- malformed();
- p_ptrn_lines = ((LINENUM) atol(s)) - p_first + 1;
- } else if (p_first)
- p_ptrn_lines = 1;
- else {
- p_ptrn_lines = 0;
- p_first = 1;
- }
-
- /* we need this much at least */
- p_max = p_ptrn_lines + 6;
- while (p_max >= hunkmax)
- grow_hunkmax();
- p_max = hunkmax;
- break;
- case '-':
- if (buf[1] == '-') {
- if (repl_beginning ||
- (p_end != p_ptrn_lines + 1 +
- (p_char[p_end - 1] == '\n'))) {
- if (p_end == 1) {
- /*
- * `old' lines were omitted;
- * set up to fill them in
- * from 'new' context lines.
- */
- p_end = p_ptrn_lines + 1;
- fillsrc = p_end + 1;
- filldst = 1;
- fillcnt = p_ptrn_lines;
- } else {
- if (repl_beginning) {
- if (repl_could_be_missing) {
- repl_missing = true;
- goto hunk_done;
- }
- fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n",
- p_input_line, p_hunk_beg + repl_beginning);
- } else {
- fatal("%s \"---\" at line %ld--check line numbers at line %ld\n",
- (p_end <= p_ptrn_lines
- ? "Premature"
- : "Overdue"),
- p_input_line, p_hunk_beg);
- }
- }
- }
- repl_beginning = p_end;
- repl_backtrack_position = ftell(pfp);
- repl_patch_line = p_input_line;
- p_line[p_end] = savestr(buf);
- if (out_of_mem) {
- p_end--;
- return false;
- }
- p_char[p_end] = '=';
- for (s = buf; *s && !isdigit(*s); s++)
- ;
- if (!*s)
- malformed();
- p_newfirst = (LINENUM) atol(s);
- while (isdigit(*s))
- s++;
- if (*s == ',') {
- for (; *s && !isdigit(*s); s++)
- ;
- if (!*s)
- malformed();
- p_repl_lines = ((LINENUM) atol(s)) -
- p_newfirst + 1;
- } else if (p_newfirst)
- p_repl_lines = 1;
- else {
- p_repl_lines = 0;
- p_newfirst = 1;
- }
- p_max = p_repl_lines + p_end;
- if (p_max > MAXHUNKSIZE)
- fatal("hunk too large (%ld lines) at line %ld: %s",
- p_max, p_input_line, buf);
- while (p_max >= hunkmax)
- grow_hunkmax();
- if (p_repl_lines != ptrn_copiable &&
- (p_context != 0 || p_repl_lines != 1))
- repl_could_be_missing = false;
- break;
- }
- goto change_line;
- case '+':
- case '!':
- repl_could_be_missing = false;
- change_line:
- if (buf[1] == '\n' && canonicalize)
- strlcpy(buf + 1, " \n", sizeof buf - 1);
- if (!isspace(buf[1]) && buf[1] != '>' &&
- buf[1] != '<' &&
- repl_beginning && repl_could_be_missing) {
- repl_missing = true;
- goto hunk_done;
- }
- if (context >= 0) {
- if (context < p_context)
- p_context = context;
- context = -1000;
- }
- p_line[p_end] = savestr(buf + 2);
- if (out_of_mem) {
- p_end--;
- return false;
- }
- if (p_end == p_ptrn_lines) {
- if (remove_special_line()) {
- int len;
-
- len = strlen(p_line[p_end]) - 1;
- (p_line[p_end])[len] = 0;
- }
- }
- break;
- case '\t':
- case '\n': /* assume the 2 spaces got eaten */
- if (repl_beginning && repl_could_be_missing &&
- (!ptrn_spaces_eaten ||
- diff_type == NEW_CONTEXT_DIFF)) {
- repl_missing = true;
- goto hunk_done;
- }
- p_line[p_end] = savestr(buf);
- if (out_of_mem) {
- p_end--;
- return false;
- }
- if (p_end != p_ptrn_lines + 1) {
- ptrn_spaces_eaten |= (repl_beginning != 0);
- context++;
- if (!repl_beginning)
- ptrn_copiable++;
- p_char[p_end] = ' ';
- }
- break;
- case ' ':
- if (!isspace(buf[1]) &&
- repl_beginning && repl_could_be_missing) {
- repl_missing = true;
- goto hunk_done;
- }
- context++;
- if (!repl_beginning)
- ptrn_copiable++;
- p_line[p_end] = savestr(buf + 2);
- if (out_of_mem) {
- p_end--;
- return false;
- }
- break;
- default:
- if (repl_beginning && repl_could_be_missing) {
- repl_missing = true;
- goto hunk_done;
- }
- malformed();
- }
- /* set up p_len for strncmp() so we don't have to */
- /* assume null termination */
- if (p_line[p_end])
- p_len[p_end] = strlen(p_line[p_end]);
- else
- p_len[p_end] = 0;
- }
-
-hunk_done:
- if (p_end >= 0 && !repl_beginning)
- fatal("no --- found in patch at line %ld\n", pch_hunk_beg());
-
- if (repl_missing) {
-
- /* reset state back to just after --- */
- p_input_line = repl_patch_line;
- for (p_end--; p_end > repl_beginning; p_end--)
- free(p_line[p_end]);
- fseek(pfp, repl_backtrack_position, SEEK_SET);
-
- /* redundant 'new' context lines were omitted - set */
- /* up to fill them in from the old file context */
- if (!p_context && p_repl_lines == 1) {
- p_repl_lines = 0;
- p_max--;
- }
- fillsrc = 1;
- filldst = repl_beginning + 1;
- fillcnt = p_repl_lines;
- p_end = p_max;
- } else if (!p_context && fillcnt == 1) {
- /* the first hunk was a null hunk with no context */
- /* and we were expecting one line -- fix it up. */
- while (filldst < p_end) {
- p_line[filldst] = p_line[filldst + 1];
- p_char[filldst] = p_char[filldst + 1];
- p_len[filldst] = p_len[filldst + 1];
- filldst++;
- }
-#if 0
- repl_beginning--; /* this doesn't need to be fixed */
-#endif
- p_end--;
- p_first++; /* do append rather than insert */
- fillcnt = 0;
- p_ptrn_lines = 0;
- }
- if (diff_type == CONTEXT_DIFF &&
- (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) {
- if (verbose)
- say("%s\n%s\n%s\n",
- "(Fascinating--this is really a new-style context diff but without",
- "the telltale extra asterisks on the *** line that usually indicate",
- "the new style...)");
- diff_type = NEW_CONTEXT_DIFF;
- }
- /* if there were omitted context lines, fill them in now */
- if (fillcnt) {
- p_bfake = filldst; /* remember where not to free() */
- p_efake = filldst + fillcnt - 1;
- while (fillcnt-- > 0) {
- while (fillsrc <= p_end && p_char[fillsrc] != ' ')
- fillsrc++;
- if (fillsrc > p_end)
- fatal("replacement text or line numbers mangled in hunk at line %ld\n",
- p_hunk_beg);
- p_line[filldst] = p_line[fillsrc];
- p_char[filldst] = p_char[fillsrc];
- p_len[filldst] = p_len[fillsrc];
- fillsrc++;
- filldst++;
- }
- while (fillsrc <= p_end && fillsrc != repl_beginning &&
- p_char[fillsrc] != ' ')
- fillsrc++;
-#ifdef DEBUGGING
- if (debug & 64)
- printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
- fillsrc, filldst, repl_beginning, p_end + 1);
-#endif
- if (fillsrc != p_end + 1 && fillsrc != repl_beginning)
- malformed();
- if (filldst != p_end + 1 && filldst != repl_beginning)
- malformed();
- }
- if (p_line[p_end] != NULL) {
- if (remove_special_line()) {
- p_len[p_end] -= 1;
- (p_line[p_end])[p_len[p_end]] = 0;
- }
- }
- } else if (diff_type == UNI_DIFF) {
- long line_beginning = ftell(pfp); /* file pos of the current line */
- LINENUM fillsrc; /* index of old lines */
- LINENUM filldst; /* index of new lines */
- char ch;
-
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL || strnNE(buf, "@@ -", 4)) {
- next_intuit_at(line_beginning, p_input_line);
- return false;
- }
- s = buf + 4;
- if (!*s)
- malformed();
- p_first = (LINENUM) atol(s);
- while (isdigit(*s))
- s++;
- if (*s == ',') {
- p_ptrn_lines = (LINENUM) atol(++s);
- while (isdigit(*s))
- s++;
- } else
- p_ptrn_lines = 1;
- if (*s == ' ')
- s++;
- if (*s != '+' || !*++s)
- malformed();
- p_newfirst = (LINENUM) atol(s);
- while (isdigit(*s))
- s++;
- if (*s == ',') {
- p_repl_lines = (LINENUM) atol(++s);
- while (isdigit(*s))
- s++;
- } else
- p_repl_lines = 1;
- if (*s == ' ')
- s++;
- if (*s != '@')
- malformed();
- if (!p_ptrn_lines)
- p_first++; /* do append rather than insert */
- p_max = p_ptrn_lines + p_repl_lines + 1;
- while (p_max >= hunkmax)
- grow_hunkmax();
- fillsrc = 1;
- filldst = fillsrc + p_ptrn_lines;
- p_end = filldst + p_repl_lines;
- snprintf(buf, sizeof buf, "*** %ld,%ld ****\n", p_first,
- p_first + p_ptrn_lines - 1);
- p_line[0] = savestr(buf);
- if (out_of_mem) {
- p_end = -1;
- return false;
- }
- p_char[0] = '*';
- snprintf(buf, sizeof buf, "--- %ld,%ld ----\n", p_newfirst,
- p_newfirst + p_repl_lines - 1);
- p_line[filldst] = savestr(buf);
- if (out_of_mem) {
- p_end = 0;
- return false;
- }
- p_char[filldst++] = '=';
- p_context = 100;
- context = 0;
- p_hunk_beg = p_input_line + 1;
- while (fillsrc <= p_ptrn_lines || filldst <= p_end) {
- line_beginning = ftell(pfp);
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL) {
- if (p_max - filldst < 3) {
- /* assume blank lines got chopped */
- strlcpy(buf, " \n", sizeof buf);
- } else {
- fatal("unexpected end of file in patch\n");
- }
- }
- if (*buf == '\t' || *buf == '\n') {
- ch = ' '; /* assume the space got eaten */
- s = savestr(buf);
- } else {
- ch = *buf;
- s = savestr(buf + 1);
- }
- if (out_of_mem) {
- while (--filldst > p_ptrn_lines)
- free(p_line[filldst]);
- p_end = fillsrc - 1;
- return false;
- }
- switch (ch) {
- case '-':
- if (fillsrc > p_ptrn_lines) {
- free(s);
- p_end = filldst - 1;
- malformed();
- }
- p_char[fillsrc] = ch;
- p_line[fillsrc] = s;
- p_len[fillsrc++] = strlen(s);
- if (fillsrc > p_ptrn_lines) {
- if (remove_special_line()) {
- p_len[fillsrc - 1] -= 1;
- s[p_len[fillsrc - 1]] = 0;
- }
- }
- break;
- case '=':
- ch = ' ';
- /* FALL THROUGH */
- case ' ':
- if (fillsrc > p_ptrn_lines) {
- free(s);
- while (--filldst > p_ptrn_lines)
- free(p_line[filldst]);
- p_end = fillsrc - 1;
- malformed();
- }
- context++;
- p_char[fillsrc] = ch;
- p_line[fillsrc] = s;
- p_len[fillsrc++] = strlen(s);
- s = savestr(s);
- if (out_of_mem) {
- while (--filldst > p_ptrn_lines)
- free(p_line[filldst]);
- p_end = fillsrc - 1;
- return false;
- }
- if (fillsrc > p_ptrn_lines) {
- if (remove_special_line()) {
- p_len[fillsrc - 1] -= 1;
- s[p_len[fillsrc - 1]] = 0;
- }
- }
- /* FALL THROUGH */
- case '+':
- if (filldst > p_end) {
- free(s);
- while (--filldst > p_ptrn_lines)
- free(p_line[filldst]);
- p_end = fillsrc - 1;
- malformed();
- }
- p_char[filldst] = ch;
- p_line[filldst] = s;
- p_len[filldst++] = strlen(s);
- if (fillsrc > p_ptrn_lines) {
- if (remove_special_line()) {
- p_len[filldst - 1] -= 1;
- s[p_len[filldst - 1]] = 0;
- }
- }
- break;
- default:
- p_end = filldst;
- malformed();
- }
- if (ch != ' ' && context > 0) {
- if (context < p_context)
- p_context = context;
- context = -1000;
- }
- } /* while */
- } else { /* normal diff--fake it up */
- char hunk_type;
- int i;
- LINENUM min, max;
- long line_beginning = ftell(pfp);
-
- p_context = 0;
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL || !isdigit(*buf)) {
- next_intuit_at(line_beginning, p_input_line);
- return false;
- }
- p_first = (LINENUM) atol(buf);
- for (s = buf; isdigit(*s); s++)
- ;
- if (*s == ',') {
- p_ptrn_lines = (LINENUM) atol(++s) - p_first + 1;
- while (isdigit(*s))
- s++;
- } else
- p_ptrn_lines = (*s != 'a');
- hunk_type = *s;
- if (hunk_type == 'a')
- p_first++; /* do append rather than insert */
- min = (LINENUM) atol(++s);
- for (; isdigit(*s); s++)
- ;
- if (*s == ',')
- max = (LINENUM) atol(++s);
- else
- max = min;
- if (hunk_type == 'd')
- min++;
- p_end = p_ptrn_lines + 1 + max - min + 1;
- if (p_end > MAXHUNKSIZE)
- fatal("hunk too large (%ld lines) at line %ld: %s",
- p_end, p_input_line, buf);
- while (p_end >= hunkmax)
- grow_hunkmax();
- p_newfirst = min;
- p_repl_lines = max - min + 1;
- snprintf(buf, sizeof buf, "*** %ld,%ld\n", p_first,
- p_first + p_ptrn_lines - 1);
- p_line[0] = savestr(buf);
- if (out_of_mem) {
- p_end = -1;
- return false;
- }
- p_char[0] = '*';
- for (i = 1; i <= p_ptrn_lines; i++) {
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL)
- fatal("unexpected end of file in patch at line %ld\n",
- p_input_line);
- if (*buf != '<')
- fatal("< expected at line %ld of patch\n",
- p_input_line);
- p_line[i] = savestr(buf + 2);
- if (out_of_mem) {
- p_end = i - 1;
- return false;
- }
- p_len[i] = strlen(p_line[i]);
- p_char[i] = '-';
- }
-
- if (remove_special_line()) {
- p_len[i - 1] -= 1;
- (p_line[i - 1])[p_len[i - 1]] = 0;
- }
- if (hunk_type == 'c') {
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL)
- fatal("unexpected end of file in patch at line %ld\n",
- p_input_line);
- if (*buf != '-')
- fatal("--- expected at line %ld of patch\n",
- p_input_line);
- }
- snprintf(buf, sizeof(buf), "--- %ld,%ld\n", min, max);
- p_line[i] = savestr(buf);
- if (out_of_mem) {
- p_end = i - 1;
- return false;
- }
- p_char[i] = '=';
- for (i++; i <= p_end; i++) {
- ret = pgets(buf, sizeof buf, pfp);
- p_input_line++;
- if (ret == NULL)
- fatal("unexpected end of file in patch at line %ld\n",
- p_input_line);
- if (*buf != '>')
- fatal("> expected at line %ld of patch\n",
- p_input_line);
- p_line[i] = savestr(buf + 2);
- if (out_of_mem) {
- p_end = i - 1;
- return false;
- }
- p_len[i] = strlen(p_line[i]);
- p_char[i] = '+';
- }
-
- if (remove_special_line()) {
- p_len[i - 1] -= 1;
- (p_line[i - 1])[p_len[i - 1]] = 0;
- }
- }
- if (reverse) /* backwards patch? */
- if (!pch_swap())
- say("Not enough memory to swap next hunk!\n");
-#ifdef DEBUGGING
- if (debug & 2) {
- int i;
- char special;
-
- for (i = 0; i <= p_end; i++) {
- if (i == p_ptrn_lines)
- special = '^';
- else
- special = ' ';
- fprintf(stderr, "%3d %c %c %s", i, p_char[i],
- special, p_line[i]);
- fflush(stderr);
- }
- }
-#endif
- if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */
- p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */
- return true;
-}
-
-/*
- * Input a line from the patch file, worrying about indentation.
- */
-static char *
-pgets(char *bf, int sz, FILE *fp)
-{
- char *s, *ret = fgets(bf, sz, fp);
- int indent = 0;
-
- if (p_indent && ret != NULL) {
- for (s = buf;
- indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X');
- s++) {
- if (*s == '\t')
- indent += 8 - (indent % 7);
- else
- indent++;
- }
- if (buf != s && strlcpy(buf, s, sizeof(buf)) >= sizeof(buf))
- fatal("buffer too small in pgets()\n");
- }
- return ret;
-}
-
-/*
- * Reverse the old and new portions of the current hunk.
- */
-bool
-pch_swap(void)
-{
- char **tp_line; /* the text of the hunk */
- short *tp_len; /* length of each line */
- char *tp_char; /* +, -, and ! */
- LINENUM i;
- LINENUM n;
- bool blankline = false;
- char *s;
-
- i = p_first;
- p_first = p_newfirst;
- p_newfirst = i;
-
- /* make a scratch copy */
-
- tp_line = p_line;
- tp_len = p_len;
- tp_char = p_char;
- p_line = NULL; /* force set_hunkmax to allocate again */
- p_len = NULL;
- p_char = NULL;
- set_hunkmax();
- if (p_line == NULL || p_len == NULL || p_char == NULL) {
-
- free(p_line);
- p_line = tp_line;
- free(p_len);
- p_len = tp_len;
- free(p_char);
- p_char = tp_char;
- return false; /* not enough memory to swap hunk! */
- }
- /* now turn the new into the old */
-
- i = p_ptrn_lines + 1;
- if (tp_char[i] == '\n') { /* account for possible blank line */
- blankline = true;
- i++;
- }
- if (p_efake >= 0) { /* fix non-freeable ptr range */
- if (p_efake <= i)
- n = p_end - i + 1;
- else
- n = -i;
- p_efake += n;
- p_bfake += n;
- }
- for (n = 0; i <= p_end; i++, n++) {
- p_line[n] = tp_line[i];
- p_char[n] = tp_char[i];
- if (p_char[n] == '+')
- p_char[n] = '-';
- p_len[n] = tp_len[i];
- }
- if (blankline) {
- i = p_ptrn_lines + 1;
- p_line[n] = tp_line[i];
- p_char[n] = tp_char[i];
- p_len[n] = tp_len[i];
- n++;
- }
- if (p_char[0] != '=')
- fatal("Malformed patch at line %ld: expected '=' found '%c'\n",
- p_input_line, p_char[0]);
- p_char[0] = '*';
- for (s = p_line[0]; *s; s++)
- if (*s == '-')
- *s = '*';
-
- /* now turn the old into the new */
-
- if (p_char[0] != '*')
- fatal("Malformed patch at line %ld: expected '*' found '%c'\n",
- p_input_line, p_char[0]);
- tp_char[0] = '=';
- for (s = tp_line[0]; *s; s++)
- if (*s == '*')
- *s = '-';
- for (i = 0; n <= p_end; i++, n++) {
- p_line[n] = tp_line[i];
- p_char[n] = tp_char[i];
- if (p_char[n] == '-')
- p_char[n] = '+';
- p_len[n] = tp_len[i];
- }
-
- if (i != p_ptrn_lines + 1)
- fatal("Malformed patch at line %ld: expected %ld lines, "
- "got %ld\n",
- p_input_line, p_ptrn_lines + 1, i);
-
- i = p_ptrn_lines;
- p_ptrn_lines = p_repl_lines;
- p_repl_lines = i;
-
- free(tp_line);
- free(tp_len);
- free(tp_char);
-
- return true;
-}
-
-/*
- * Return the specified line position in the old file of the old context.
- */
-LINENUM
-pch_first(void)
-{
- return p_first;
-}
-
-/*
- * Return the number of lines of old context.
- */
-LINENUM
-pch_ptrn_lines(void)
-{
- return p_ptrn_lines;
-}
-
-/*
- * Return the probable line position in the new file of the first line.
- */
-LINENUM
-pch_newfirst(void)
-{
- return p_newfirst;
-}
-
-/*
- * Return the number of lines in the replacement text including context.
- */
-LINENUM
-pch_repl_lines(void)
-{
- return p_repl_lines;
-}
-
-/*
- * Return the number of lines in the whole hunk.
- */
-LINENUM
-pch_end(void)
-{
- return p_end;
-}
-
-/*
- * Return the number of context lines before the first changed line.
- */
-LINENUM
-pch_context(void)
-{
- return p_context;
-}
-
-/*
- * Return the length of a particular patch line.
- */
-short
-pch_line_len(LINENUM line)
-{
- return p_len[line];
-}
-
-/*
- * Return the control character (+, -, *, !, etc) for a patch line.
- */
-char
-pch_char(LINENUM line)
-{
- return p_char[line];
-}
-
-/*
- * Return a pointer to a particular patch line.
- */
-char *
-pfetch(LINENUM line)
-{
- return p_line[line];
-}
-
-/*
- * Return where in the patch file this hunk began, for error messages.
- */
-LINENUM
-pch_hunk_beg(void)
-{
- return p_hunk_beg;
-}
-
-/*
- * Apply an ed script by feeding ed itself.
- */
-void
-do_ed_script(void)
-{
- char *t;
- long beginning_of_this_line;
- FILE *pipefp;
-
- pipefp = NULL;
- if (!skip_rest_of_patch) {
- if (copy_file(filearg[0], TMPOUTNAME) < 0) {
- unlink(TMPOUTNAME);
- fatal("can't create temp file %s", TMPOUTNAME);
- }
- snprintf(buf, sizeof buf, "%s%s%s", _PATH_ED,
- verbose ? " " : " -s ", TMPOUTNAME);
- pipefp = popen(buf, "w");
- }
- for (;;) {
- beginning_of_this_line = ftell(pfp);
- if (pgets(buf, sizeof buf, pfp) == NULL) {
- next_intuit_at(beginning_of_this_line, p_input_line);
- break;
- }
- p_input_line++;
- for (t = buf; isdigit(*t) || *t == ','; t++)
- ;
- /* POSIX defines allowed commands as {a,c,d,i,s} */
- if (isdigit(*buf) && (*t == 'a' || *t == 'c' || *t == 'd' ||
- *t == 'i' || *t == 's')) {
- if (pipefp != NULL)
- fputs(buf, pipefp);
- if (*t != 'd') {
- while (pgets(buf, sizeof buf, pfp) != NULL) {
- p_input_line++;
- if (pipefp != NULL)
- fputs(buf, pipefp);
- if (strEQ(buf, ".\n"))
- break;
- }
- }
- } else {
- next_intuit_at(beginning_of_this_line, p_input_line);
- break;
- }
- }
- if (pipefp == NULL)
- return;
- fprintf(pipefp, "w\n");
- fprintf(pipefp, "q\n");
- fflush(pipefp);
- pclose(pipefp);
- ignore_signals();
- if (!check_only) {
- if (move_file(TMPOUTNAME, outname) < 0) {
- toutkeep = true;
- chmod(TMPOUTNAME, filemode);
- } else
- chmod(outname, filemode);
- }
- set_signals(1);
-}
-
-/*
- * Choose the name of the file to be patched based on POSIX rules.
- * NOTE: the POSIX rules are amazingly stupid and we only follow them
- * if the user specified --posix or set POSIXLY_CORRECT.
- */
-static char *
-posix_name(const struct file_name *names, bool assume_exists)
-{
- char *path = NULL;
- int i;
-
- /*
- * POSIX states that the filename will be chosen from one
- * of the old, new and index names (in that order) if
- * the file exists relative to CWD after -p stripping.
- */
- for (i = 0; i < MAX_FILE; i++) {
- if (names[i].path != NULL && names[i].exists) {
- path = names[i].path;
- break;
- }
- }
- if (path == NULL && !assume_exists) {
- /*
- * No files found, look for something we can checkout from
- * RCS/SCCS dirs. Same order as above.
- */
- for (i = 0; i < MAX_FILE; i++) {
- if (names[i].path != NULL &&
- (path = checked_in(names[i].path)) != NULL)
- break;
- }
- /*
- * Still no match? Check to see if the diff could be creating
- * a new file.
- */
- if (path == NULL && ok_to_create_file &&
- names[NEW_FILE].path != NULL)
- path = names[NEW_FILE].path;
- }
-
- return path ? savestr(path) : NULL;
-}
-
-/*
- * Choose the name of the file to be patched based the "best" one
- * available.
- */
-static char *
-best_name(const struct file_name *names, bool assume_exists)
-{
- size_t min_components, min_baselen, min_len, tmp;
- char *best = NULL;
- int i;
-
- /*
- * The "best" name is the one with the fewest number of path
- * components, the shortest basename length, and the shortest
- * overall length (in that order). We only use the Index: file
- * if neither of the old or new files could be intuited from
- * the diff header.
- */
- min_components = min_baselen = min_len = SIZE_MAX;
- for (i = INDEX_FILE; i >= OLD_FILE; i--) {
- if (names[i].path == NULL ||
- (!names[i].exists && !assume_exists))
- continue;
- if ((tmp = num_components(names[i].path)) > min_components)
- continue;
- min_components = tmp;
- if ((tmp = strlen(basename(names[i].path))) > min_baselen)
- continue;
- min_baselen = tmp;
- if ((tmp = strlen(names[i].path)) > min_len)
- continue;
- min_len = tmp;
- best = names[i].path;
- }
- if (best == NULL) {
- /*
- * No files found, look for something we can checkout from
- * RCS/SCCS dirs. Logic is identical to that above...
- */
- min_components = min_baselen = min_len = SIZE_MAX;
- for (i = INDEX_FILE; i >= OLD_FILE; i--) {
- if (names[i].path == NULL ||
- checked_in(names[i].path) == NULL)
- continue;
- if ((tmp = num_components(names[i].path)) > min_components)
- continue;
- min_components = tmp;
- if ((tmp = strlen(basename(names[i].path))) > min_baselen)
- continue;
- min_baselen = tmp;
- if ((tmp = strlen(names[i].path)) > min_len)
- continue;
- min_len = tmp;
- best = names[i].path;
- }
- /*
- * Still no match? Check to see if the diff could be creating
- * a new file.
- */
- if (best == NULL && ok_to_create_file &&
- names[NEW_FILE].path != NULL)
- best = names[NEW_FILE].path;
- }
-
- return best ? savestr(best) : NULL;
-}
-
-static size_t
-num_components(const char *path)
-{
- size_t n;
- const char *cp;
-
- for (n = 0, cp = path; (cp = strchr(cp, '/')) != NULL; n++, cp++) {
- while (*cp == '/')
- cp++; /* skip consecutive slashes */
- }
- return n;
-}
diff --git a/usr.bin/patch/pch.h b/usr.bin/patch/pch.h
deleted file mode 100644
index b7bf8e8a224ec..0000000000000
--- a/usr.bin/patch/pch.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* $OpenBSD: pch.h,v 1.9 2003/10/31 20:20:45 millert Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-#define OLD_FILE 0
-#define NEW_FILE 1
-#define INDEX_FILE 2
-#define MAX_FILE 3
-
-struct file_name {
- char *path;
- bool exists;
-};
-
-void re_patch(void);
-void open_patch_file(const char *);
-void set_hunkmax(void);
-bool there_is_another_patch(void);
-bool another_hunk(void);
-bool pch_swap(void);
-char *pfetch(LINENUM);
-short pch_line_len(LINENUM);
-LINENUM pch_first(void);
-LINENUM pch_ptrn_lines(void);
-LINENUM pch_newfirst(void);
-LINENUM pch_repl_lines(void);
-LINENUM pch_end(void);
-LINENUM pch_context(void);
-LINENUM pch_hunk_beg(void);
-char pch_char(LINENUM);
-char *pfetch(LINENUM);
-void do_ed_script(void);
diff --git a/usr.bin/patch/util.c b/usr.bin/patch/util.c
deleted file mode 100644
index 23a22b17078f5..0000000000000
--- a/usr.bin/patch/util.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/* $OpenBSD: util.c,v 1.27 2003/10/31 20:20:45 millert Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-#ifndef lint
-static const char rcsid[] = "$OpenBSD: util.c,v 1.27 2003/10/31 20:20:45 millert Exp $";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <paths.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "common.h"
-#include "util.h"
-#include "backupfile.h"
-#include "pathnames.h"
-
-
-/* Rename a file, copying it if necessary. */
-
-int
-move_file(const char *from, const char *to)
-{
- int fromfd;
- ssize_t i;
-
- /* to stdout? */
-
- if (strEQ(to, "-")) {
-#ifdef DEBUGGING
- if (debug & 4)
- say("Moving %s to stdout.\n", from);
-#endif
- fromfd = open(from, O_RDONLY);
- if (fromfd < 0)
- pfatal("internal error, can't reopen %s", from);
- while ((i = read(fromfd, buf, sizeof buf)) > 0)
- if (write(STDOUT_FILENO, buf, i) != i)
- pfatal("write failed");
- close(fromfd);
- return 0;
- }
- if (backup_file(to) < 0) {
- say("Can't backup %s, output is in %s: %s\n", to, from,
- strerror(errno));
- return -1;
- }
-#ifdef DEBUGGING
- if (debug & 4)
- say("Moving %s to %s.\n", from, to);
-#endif
- if (rename(from, to) < 0) {
- if (errno != EXDEV || copy_file(from, to) < 0) {
- say("Can't create %s, output is in %s: %s\n",
- to, from, strerror(errno));
- return -1;
- }
- }
- return 0;
-}
-
-/* Backup the original file. */
-
-int
-backup_file(const char *orig)
-{
- struct stat filestat;
- char bakname[MAXPATHLEN], *s, *simplename;
- dev_t orig_device;
- ino_t orig_inode;
-
- if (backup_type == none || stat(orig, &filestat) != 0)
- return 0; /* nothing to do */
- orig_device = filestat.st_dev;
- orig_inode = filestat.st_ino;
-
- if (origprae) {
- if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
- strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
- fatal("filename %s too long for buffer\n", origprae);
- } else {
- if ((s = find_backup_file_name(orig)) == NULL)
- fatal("out of memory\n");
- if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
- fatal("filename %s too long for buffer\n", s);
- free(s);
- }
-
- if ((simplename = strrchr(bakname, '/')) != NULL)
- simplename = simplename + 1;
- else
- simplename = bakname;
-
- /*
- * Find a backup name that is not the same file. Change the
- * first lowercase char into uppercase; if that isn't
- * sufficient, chop off the first char and try again.
- */
- while (stat(bakname, &filestat) == 0 &&
- orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
- /* Skip initial non-lowercase chars. */
- for (s = simplename; *s && !islower(*s); s++)
- ;
- if (*s)
- *s = toupper(*s);
- else
- memmove(simplename, simplename + 1,
- strlen(simplename + 1) + 1);
- }
-#ifdef DEBUGGING
- if (debug & 4)
- say("Moving %s to %s.\n", orig, bakname);
-#endif
- if (rename(orig, bakname) < 0) {
- if (errno != EXDEV || copy_file(orig, bakname) < 0)
- return -1;
- }
- return 0;
-}
-
-/*
- * Copy a file.
- */
-int
-copy_file(const char *from, const char *to)
-{
- int tofd, fromfd;
- ssize_t i;
-
- tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
- if (tofd < 0)
- return -1;
- fromfd = open(from, O_RDONLY, 0);
- if (fromfd < 0)
- pfatal("internal error, can't reopen %s", from);
- while ((i = read(fromfd, buf, sizeof buf)) > 0)
- if (write(tofd, buf, i) != i)
- pfatal("write to %s failed", to);
- close(fromfd);
- close(tofd);
- return 0;
-}
-
-/*
- * Allocate a unique area for a string.
- */
-char *
-savestr(const char *s)
-{
- char *rv;
-
- if (!s)
- s = "Oops";
- rv = strdup(s);
- if (rv == NULL) {
- if (using_plan_a)
- out_of_mem = true;
- else
- fatal("out of memory\n");
- }
- return rv;
-}
-
-/*
- * Vanilla terminal output (buffered).
- */
-void
-say(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fflush(stderr);
-}
-
-/*
- * Terminal output, pun intended.
- */
-void
-fatal(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- fprintf(stderr, "patch: **** ");
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- my_exit(2);
-}
-
-/*
- * Say something from patch, something from the system, then silence . . .
- */
-void
-pfatal(const char *fmt, ...)
-{
- va_list ap;
- int errnum = errno;
-
- fprintf(stderr, "patch: **** ");
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, ": %s\n", strerror(errnum));
- my_exit(2);
-}
-
-/*
- * Get a response from the user via /dev/tty
- */
-void
-ask(const char *fmt, ...)
-{
- va_list ap;
- ssize_t nr;
- static int ttyfd = -1;
-
- va_start(ap, fmt);
- vfprintf(stdout, fmt, ap);
- va_end(ap);
- fflush(stdout);
- if (ttyfd < 0)
- ttyfd = open(_PATH_TTY, O_RDONLY);
- if (ttyfd >= 0) {
- if ((nr = read(ttyfd, buf, sizeof(buf))) > 0 &&
- buf[nr - 1] == '\n')
- buf[nr - 1] = '\0';
- }
- if (ttyfd < 0 || nr <= 0) {
- /* no tty or error reading, pretend user entered 'return' */
- putchar('\n');
- buf[0] = '\0';
- }
-}
-
-/*
- * How to handle certain events when not in a critical region.
- */
-void
-set_signals(int reset)
-{
- static sig_t hupval, intval;
-
- if (!reset) {
- hupval = signal(SIGHUP, SIG_IGN);
- if (hupval != SIG_IGN)
- hupval = (sig_t) my_exit;
- intval = signal(SIGINT, SIG_IGN);
- if (intval != SIG_IGN)
- intval = (sig_t) my_exit;
- }
- signal(SIGHUP, hupval);
- signal(SIGINT, intval);
-}
-
-/*
- * How to handle certain events when in a critical region.
- */
-void
-ignore_signals(void)
-{
- signal(SIGHUP, SIG_IGN);
- signal(SIGINT, SIG_IGN);
-}
-
-/*
- * Make sure we'll have the directories to create a file. If `striplast' is
- * true, ignore the last element of `filename'.
- */
-
-void
-makedirs(const char *filename, bool striplast)
-{
- char *tmpbuf;
-
- if ((tmpbuf = strdup(filename)) == NULL)
- fatal("out of memory\n");
-
- if (striplast) {
- char *s = strrchr(tmpbuf, '/');
- if (s == NULL)
- return; /* nothing to be done */
- *s = '\0';
- }
- if (snprintf(buf, sizeof(buf), "%s -p %s", _PATH_MKDIR, tmpbuf)
- >= sizeof(buf))
- fatal("buffer too small to hold %.20s...\n", tmpbuf);
-
- if (system(buf))
- pfatal("%.40s failed", buf);
-}
-
-/*
- * Make filenames more reasonable.
- */
-char *
-fetchname(const char *at, bool *exists, int strip_leading)
-{
- char *fullname, *name, *t;
- int sleading;
- struct stat filestat;
-
- if (at == NULL || *at == '\0')
- return NULL;
- while (isspace(*at))
- at++;
-#ifdef DEBUGGING
- if (debug & 128)
- say("fetchname %s %d\n", at, strip_leading);
-#endif
- /* So files can be created by diffing against /dev/null. */
- if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1))
- return NULL;
- name = fullname = t = savestr(at);
-
- /* Strip off up to `strip_leading' path components and NUL terminate. */
- for (sleading = strip_leading; *t != '\0' && !isspace(*t); t++) {
- if (t[0] == '/' && t[1] != '/' && t[1] != '\0')
- if (--sleading >= 0)
- name = t + 1;
- }
- *t = '\0';
-
- /*
- * If no -p option was given (957 is the default value!), we were
- * given a relative pathname, and the leading directories that we
- * just stripped off all exist, put them back on.
- */
- if (strip_leading == 957 && name != fullname && *fullname != '/') {
- name[-1] = '\0';
- if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
- name[-1] = '/';
- name = fullname;
- }
- }
- name = savestr(name);
- free(fullname);
-
- *exists = stat(name, &filestat) == 0;
- return name;
-}
-
-/*
- * Takes the name returned by fetchname and looks in RCS/SCCS directories
- * for a checked in version.
- */
-char *
-checked_in(char *file)
-{
- char *filebase, *filedir, tmpbuf[MAXPATHLEN];
- struct stat filestat;
-
- filebase = basename(file);
- filedir = dirname(file);
-
-#define try(f, a1, a2, a3) \
-(snprintf(tmpbuf, sizeof tmpbuf, f, a1, a2, a3), stat(tmpbuf, &filestat) == 0)
-
- if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
- try("%s/RCS/%s%s", filedir, filebase, "") ||
- try("%s/%s%s", filedir, filebase, RCSSUFFIX) ||
- try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
- try("%s/%s%s", filedir, SCCSPREFIX, filebase))
- return file;
-
- return NULL;
-}
-
-void
-version(void)
-{
- fprintf(stderr, "Patch version 2.0-12u8-OpenBSD\n");
- my_exit(EXIT_SUCCESS);
-}
-
-/*
- * Exit with cleanup.
- */
-void
-my_exit(int status)
-{
- unlink(TMPINNAME);
- if (!toutkeep)
- unlink(TMPOUTNAME);
- if (!trejkeep)
- unlink(TMPREJNAME);
- unlink(TMPPATNAME);
- exit(status);
-}
diff --git a/usr.bin/patch/util.h b/usr.bin/patch/util.h
deleted file mode 100644
index 0ec187028b9b1..0000000000000
--- a/usr.bin/patch/util.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $OpenBSD: util.h,v 1.12 2003/10/31 20:20:45 millert Exp $ */
-
-/*
- * patch - a program to apply diffs to original files
- *
- * Copyright 1986, Larry Wall
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following condition is met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this condition and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * -C option added in 1998, original code by Marc Espie, based on FreeBSD
- * behaviour
- */
-
-char *fetchname(const char *, bool *, int);
-char *checked_in(char *);
-int backup_file(const char *);
-int move_file(const char *, const char *);
-int copy_file(const char *, const char *);
-void say(const char *, ...)
- __attribute__((__format__(__printf__, 1, 2)));
-void fatal(const char *, ...)
- __attribute__((__format__(__printf__, 1, 2)));
-void pfatal(const char *, ...)
- __attribute__((__format__(__printf__, 1, 2)));
-void ask(const char *, ...)
- __attribute__((__format__(__printf__, 1, 2)));
-char *savestr(const char *);
-void set_signals(int);
-void ignore_signals(void);
-void makedirs(const char *, bool);
-void version(void);
-void my_exit(int) __attribute__((noreturn));