summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/cvs/emx
diff options
context:
space:
mode:
authorThorsten Lockert <tholo@cvs.openbsd.org>1998-02-22 08:23:05 +0000
committerThorsten Lockert <tholo@cvs.openbsd.org>1998-02-22 08:23:05 +0000
commit8996000ce3abfb3bf3ba9371f93dbb36605526e6 (patch)
tree18978064e57450121f0e4877713ae12ee2980e3e /gnu/usr.bin/cvs/emx
parent8b617ad77948342faf0917e268e4d001047fec35 (diff)
Latest version from Cyclic
Diffstat (limited to 'gnu/usr.bin/cvs/emx')
-rw-r--r--gnu/usr.bin/cvs/emx/ChangeLog72
-rw-r--r--gnu/usr.bin/cvs/emx/Makefile.in87
-rw-r--r--gnu/usr.bin/cvs/emx/README14
-rw-r--r--gnu/usr.bin/cvs/emx/config.h15
-rw-r--r--gnu/usr.bin/cvs/emx/filesubr.c812
-rw-r--r--gnu/usr.bin/cvs/emx/options.h70
-rw-r--r--gnu/usr.bin/cvs/emx/savecwd.c141
-rw-r--r--gnu/usr.bin/cvs/emx/startserver.c84
-rw-r--r--gnu/usr.bin/cvs/emx/stripslash.c27
-rw-r--r--gnu/usr.bin/cvs/emx/system.c91
10 files changed, 1316 insertions, 97 deletions
diff --git a/gnu/usr.bin/cvs/emx/ChangeLog b/gnu/usr.bin/cvs/emx/ChangeLog
index 58f937137fb..3533866df6c 100644
--- a/gnu/usr.bin/cvs/emx/ChangeLog
+++ b/gnu/usr.bin/cvs/emx/ChangeLog
@@ -1,3 +1,75 @@
+Tue Jan 13 13:17:33 1998 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * options.h (DIFF, RCSBIN_DFLT): Remove; no longer used.
+
+Wed Dec 31 10:56:39 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * config.h, filesubr.c (convert_file): Remove; no longer used
+ (except for BROKEN_READWRITE_CONVERSION which doesn't apply).
+
+Sat Dec 27 16:57:41 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * options.h (HAVE_RCS5): Remove; no longer used.
+
+ * config.h (LINES_CRLF_TERMINATED): Remove; no longer used.
+
+Tue Dec 23 08:28:44 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * README: Change bug-cvs address from prep.ai.mit.edu to gnu.org
+ per email from Martin Hamilton.
+
+Sat Nov 29 22:20:42 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * options.h: Remove declaration of getwd; see lib/ChangeLog for
+ rationale.
+
+Fri Nov 14 13:37:33 1997 Abe Feldman and Jim Kingdon
+
+ * savecwd.c: New file, copied from lib/savecwd.c except it calls
+ _chdir2 not chdir.
+ * Makefile.in: Put savecwd in emx directory not lib directory.
+
+Tue Nov 4 18:20:08 1997 Abe Feldman <feldman@cyclic.com>
+ and Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in: Adjust to add diff directory.
+
+Sun Sep 7 19:49:36 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * system.c (os2_stat): Adjust comment to reflect removal of
+ same_directories from src/root.c.
+
+Sat Sep 06 14:45:13 1997 Jim Kingdon
+
+ * Makefile.in: Add a cvs-static.exe rule for generating
+ executables which don't need emx.dll (doesn't work yet).
+
+Fri Sep 05 12:21:56 1997 Jim Kingdon
+
+ * filesubr.c (xchmod): Replace with "attrib"-based code from
+ os2/filesubr.c.
+ * config.h (CHMOD_BROKEN): Define.
+
+Wed Jul 30 15:35:33 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in: In comment about Makefile rule, remove note about
+ this not being a problem for os2/Makefile.in. It is a problem
+ there too.
+
+ * README: Add note about srcdir and top_srcdir.
+
+Mon Jul 21 15:36:48 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in (DISTFILES): Makefile is not in srcdir.
+
+Wed Jun 18 12:07:25 1997 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in (OS2_SOURCES): Fix comment so this is not commented
+ out. Remove windows-NT/rcmd.c; the make dist for the windows-NT
+ directory can take care of that one.
+
+ * Makefile.in, README: Add comments about Makefile rule.
+
Tue Jun 17 14:44:02 1997 Jim Kingdon (unknown@beezley)
* rcmd.c: Removed; no longer used.
diff --git a/gnu/usr.bin/cvs/emx/Makefile.in b/gnu/usr.bin/cvs/emx/Makefile.in
index f2e50167434..eff256490f5 100644
--- a/gnu/usr.bin/cvs/emx/Makefile.in
+++ b/gnu/usr.bin/cvs/emx/Makefile.in
@@ -17,7 +17,7 @@ top_srcdir = @top_srcdir@
lib_dir = ${top_srcdir}/lib
cvs_srcdir = ${top_srcdir}/src
-
+diff_srcdir = ${top_srcdir}/diff
zlib_dir = ${top_srcdir}/zlib
# Do we need these?
@@ -26,6 +26,7 @@ zlib_dir = ${top_srcdir}/zlib
# Used to say -lufc, but that would only be needed for crypt().
LIB = -lsocket
+
CINC =
# This says we are building an object file, not a full executable.
OBJ_CFLAGS = -c
@@ -55,13 +56,18 @@ COMMON_HEADERS = \
${cvs_srcdir}/server.h \
${cvs_srcdir}/error.h
+# headers in ../diff
+DIFF_HEADERS = \
+ ${diff_srcdir}/cmpbuf.h \
+ ${diff_srcdir}/diff.h \
+ ${diff_srcdir}/system.h
+
# sources specific to OS/2
-# was ${srcdir}/rcmd.c \
OS2_SOURCES = \
${srcdir}/filesubr.c \
${srcdir}/startserver.c \
${srcdir}/stripslash.c \
- ${top_srcdir}/windows-NT/rcmd.c \
+ ${srcdir}/savecwd.c \
${srcdir}/system.c
# sources we use from the common src dir, ../src
@@ -121,6 +127,22 @@ COMMON_SOURCES = \
${cvs_srcdir}/zlib.c
# end of $COMMON_SOURCES
+# sources in ../diff
+DIFF_SOURCES = \
+ ${diff_srcdir}/analyze.c \
+ ${diff_srcdir}/cmpbuf.c \
+ ${diff_srcdir}/context.c \
+ ${diff_srcdir}/diff.c \
+ ${diff_srcdir}/diff3.c \
+ ${diff_srcdir}/dir.c \
+ ${diff_srcdir}/ed.c \
+ ${diff_srcdir}/ifdef.c \
+ ${diff_srcdir}/io.c \
+ ${diff_srcdir}/normal.c \
+ ${diff_srcdir}/side.c \
+ ${diff_srcdir}/util.c \
+ ${diff_srcdir}/version.c
+
# sources from ../lib
# FIXME: Is this used anywhere? I don't think it is.
LIB_SOURCES = \
@@ -131,7 +153,6 @@ LIB_SOURCES = \
${lib_dir}/getopt1.c \
${lib_dir}/md5.c \
${lib_dir}/regex.c \
- ${lib_dir}/savecwd.c \
${lib_dir}/sighandle.c \
${lib_dir}/valloc.c \
${lib_dir}/yesno.c \
@@ -144,6 +165,7 @@ OS2_OBJECTS = \
${srcdir}/startserver.o \
${srcdir}/stripslash.o \
${top_srcdir}/windows-NT/rcmd.o \
+ ${srcdir}/savecwd.o \
${srcdir}/system.o
# object files from ../src
@@ -202,6 +224,22 @@ COMMON_OBJECTS = \
${cvs_srcdir}/zlib.o
# end of $COMMON_OBJECTS
+# object files in ../diff
+DIFF_OBJECTS = \
+ ${diff_srcdir}/analyze.o \
+ ${diff_srcdir}/cmpbuf.o \
+ ${diff_srcdir}/context.o \
+ ${diff_srcdir}/diff.o \
+ ${diff_srcdir}/diff3.o \
+ ${diff_srcdir}/dir.o \
+ ${diff_srcdir}/ed.o \
+ ${diff_srcdir}/ifdef.o \
+ ${diff_srcdir}/io.o \
+ ${diff_srcdir}/normal.o \
+ ${diff_srcdir}/side.o \
+ ${diff_srcdir}/util.o \
+ ${diff_srcdir}/version.o
+
# objects from ../lib
LIB_OBJECTS = \
${lib_dir}/vasprintf.o \
@@ -211,7 +249,6 @@ LIB_OBJECTS = \
${lib_dir}/getopt1.o \
${lib_dir}/md5.o \
${lib_dir}/regex.o \
- ${lib_dir}/savecwd.o \
${lib_dir}/sighandle.o \
${lib_dir}/valloc.o \
${lib_dir}/yesno.o \
@@ -232,14 +269,15 @@ ZLIB_OBJECTS = ${zlib_dir}/adler32.o \
${zlib_dir}/infutil.o \
${zlib_dir}/inffast.o
-SOURCES = ${COMMON_SOURCES} ${LIB_SOURCES} ${OS2_SOURCES}
-HEADERS = ${COMMON_HEADERS} ${OS2_HEADERS}
-OBJECTS = ${COMMON_OBJECTS} ${LIB_OBJECTS} ${OS2_OBJECTS} ${ZLIB_OBJECTS}
+SOURCES = ${COMMON_SOURCES} ${LIB_SOURCES} ${OS2_SOURCES} ${DIFF_SOURCES}
+HEADERS = ${COMMON_HEADERS} ${OS2_HEADERS} ${DIFF_HEADERS}
+OBJECTS = ${COMMON_OBJECTS} ${LIB_OBJECTS} ${OS2_OBJECTS} ${DIFF_OBJECTS} \
+ ${ZLIB_OBJECTS}
DISTFILES = ${OS2_HEADERS} ${OS2_SOURCES} \
${srcdir}/README ${srcdir}/ChangeLog \
${srcdir}/Makefile.in ${srcdir}/.cvsignore \
- ${srcdir}/Makefile
+ Makefile
all:
@@ -274,6 +312,7 @@ dist-dir:
clean:
rm -f cvs.exe cvs.out
rm -f ${srcdir}/*.o
+ rm -f ${diff_srcdir}/*.o
rm -f ${lib_dir}/*.o ${lib_dir}/*.a
rm -f ${zlib_dir}/*.o ${zlib_dir}/*.a
rm -f ${cvs_srcdir}/*.o
@@ -281,6 +320,7 @@ clean:
clean-cvs:
del cvs.exe cvs.out
del $(subst /,\,${srcdir}/*.o)
+ del $(subst /,\,${diff_srcdir}/*.o)
del $(subst /,\,${lib_dir}/*.o ${lib_dir}/*.a)
del $(subst /,\,${zlib_dir}/*.o ${zlib_dir}/*.a)
del $(subst /,\,${cvs_srcdir}/*.o)
@@ -297,13 +337,40 @@ ${lib_dir}/libcvs.a: $(LIB_OBJECTS)
${zlib_dir}/libz.a: $(ZLIB_OBJECTS)
$(AR) cr $@ $(ZLIB_OBJECTS)
+# Eventually probably static linking (cvs-static.exe) will be the
+# default, but even so we'll want to preserve this rule so we can
+# create a dynamically linked executable when we want coredumps.
cvs.exe: ${OBJECTS} ${lib_dir}/libcvs.a ${zlib_dir}/libz.a
- gcc $(COMMON_OBJECTS) $(OS2_OBJECTS) ${lib_dir}/libcvs.a ${zlib_dir}/libz.a $(LIB) -o cvs.out
+ gcc $(COMMON_OBJECTS) $(OS2_OBJECTS) ${DIFF_OBJECTS} ${lib_dir}/libcvs.a ${zlib_dir}/libz.a $(LIB) -o cvs.out
emxbind -w -o $@.exe cvs.out
+${lib_dir}/libcvs.lib: ${lib_dir}/libcvs.a
+ emxomf ${lib_dir}/libcvs.a
+
+${zlib_dir}/libz.lib: ${zlib_dir}/libz.a
+ emxomf ${zlib_dir}/libz.a
+
+# Where do -Zomf -Zsys go? When we compile the .o's?
+# When I tried this rule, I had problems with (1) could not find
+# socket.lib. Hmm. I thought I converted it from socket.a
+# in the EMX distribution. Probably my EMX installation at fault.
+# (2) could not find miscellaneous system routines like strerror.
+# This might be a matter of learning to live without them (EMX
+# doc is supposed to describe which are present and which are not).
+# (3) some linker errors like no stack and the like. Maybe I am
+# missing some options?
+cvs-static.exe: ${OBJECTS} ${lib_dir}/libcvs.lib ${zlib_dir}/libz.lib
+ emxomf ${OBJECTS}
+ emxomfld -o $@ $(subst .o,.obj,${OBJECTS}) \
+ ${lib_dir}/libcvs.lib ${zlib_dir}/libz.lib ${LIB}
+
# cvs.o: ${OBJECTS} ${SOURCES} ${HEADERS}
subdir = emx
+# Hmm. This rule wants to exist on unix, so that "make dist" works.
+# And it doesn't want to exist on OS/2, because configure doesn't
+# run on OS/2 and so ../config.status won't exist. For now we just
+# say, in emx/README, that people will need to comment it out.
Makefile: ../config.status $(srcdir)/Makefile.in
cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
diff --git a/gnu/usr.bin/cvs/emx/README b/gnu/usr.bin/cvs/emx/README
index 9b82e81d01d..5483e6a62d5 100644
--- a/gnu/usr.bin/cvs/emx/README
+++ b/gnu/usr.bin/cvs/emx/README
@@ -42,10 +42,14 @@ To compile CVS for OS/2, you must install the following packages:
All packages can be found on ftp://ftp.leo.org/pub/comp/os/os2/leo/gnu
(You may also try http://www.leo.org/pub/comp/os/os2/leo/gnu).
-Change to the `emx' directory, do "make" and get emx\cvs.exe. Assuming
-you have edited the `install_dir' variable in the Makefile, you may type
-"make install-cvs" to put cvs.exe in the right place. You may also "make
-clean-cvs" to clean up object and library files.
+Change to the `emx' directory, do "make" and get emx\cvs.exe. I had
+to comment out the "Makefile" rule in emx/Makefile to avoid a
+complaint about ../config.status not existing. You also might need to
+edit srcdir to be "." and top_srcdir to be "..".
+
+Assuming you have edited the `install_dir' variable in the Makefile,
+you may type "make install-cvs" to put cvs.exe in the right place.
+You may also "make clean-cvs" to clean up object and library files.
The cvs.exe generated will require emx.dll to run. You can try
compiling with -Zomf -Zsys to generate a cvs.exe without this
@@ -63,4 +67,4 @@ them.
You will get about 5 warnings in lib/regex.c concerning "unused variable
destination". Ignore them.
-Report bugs to tepting@swol.de and bug-cvs@prep.ai.mit.edu.
+Report bugs to tepting@swol.de and bug-cvs@gnu.org.
diff --git a/gnu/usr.bin/cvs/emx/config.h b/gnu/usr.bin/cvs/emx/config.h
index f9ec55f7672..380e73e4e19 100644
--- a/gnu/usr.bin/cvs/emx/config.h
+++ b/gnu/usr.bin/cvs/emx/config.h
@@ -257,18 +257,6 @@ extern int fncmp (const char *n1, const char *n2);
definition for this. */
extern void fnfold (char *FILENAME);
-/* #define this if your system terminates lines in text files with
- CRLF instead of plain LF, and your I/O functions automatically
- translate between using LF in memory and CRLF on disk, unless you
- specifically tell them not to. */
-#define LINES_CRLF_TERMINATED 1
-
-/* Read data from INFILE, and copy it to OUTFILE.
- Open INFILE using INFLAGS, and OUTFILE using OUTFLAGS.
- This is useful for converting between CRLF and LF line formats. */
-extern void convert_file (char *INFILE, int INFLAGS,
- char *OUTFILE, int OUTFLAGS);
-
/* This is where old bits go to die under OS/2 as well as WinNT. */
#define DEVNULL "nul"
@@ -323,3 +311,6 @@ extern int os2_fnmatch(const char *pattern, const char *name, int flags);
/* See above; we can't use rsh without -b. */
#define RSH_NOT_TRANSPARENT 1
+
+/* See discussion at xchmod in filesubr.c. */
+#define CHMOD_BROKEN 1
diff --git a/gnu/usr.bin/cvs/emx/filesubr.c b/gnu/usr.bin/cvs/emx/filesubr.c
new file mode 100644
index 00000000000..6b96a1b0c76
--- /dev/null
+++ b/gnu/usr.bin/cvs/emx/filesubr.c
@@ -0,0 +1,812 @@
+/* filesubr.c --- subroutines for dealing with files
+ Jim Blandy <jimb@cyclic.com>
+
+ This file is part of GNU CVS.
+
+ GNU CVS is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ 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. See the
+ GNU General Public License for more details. */
+
+/* These functions were moved out of subr.c because they need different
+ definitions under operating systems (like, say, Windows NT) with different
+ file system semantics. */
+
+#include "cvs.h"
+#include <sys/param.h>
+
+/*
+ * I don't know of a convenient way to test this at configure time, or else
+ * I'd certainly do it there.
+ */
+#if defined(NeXT)
+#define LOSING_TMPNAM_FUNCTION
+#endif
+
+static int deep_remove_dir PROTO((const char *path));
+
+/*
+ * Copies "from" to "to".
+ */
+void
+copy_file (from, to)
+ const char *from;
+ const char *to;
+{
+ struct stat sb;
+ struct utimbuf t;
+ int fdin, fdout;
+
+ if (trace)
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> copy(%s,%s)\n",
+ (server_active) ? 'S' : ' ', from, to);
+#else
+ (void) fprintf (stderr, "-> copy(%s,%s)\n", from, to);
+#endif
+ if (noexec)
+ return;
+
+ if ((fdin = open (from, O_RDONLY | O_BINARY)) < 0)
+ error (1, errno, "cannot open %s for copying", from);
+ if (fstat (fdin, &sb) < 0)
+ error (1, errno, "cannot fstat %s", from);
+ if ((fdout = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,
+ (int) sb.st_mode & 07777)) < 0)
+ error (1, errno, "cannot create %s for copying", to);
+ if (sb.st_size > 0)
+ {
+ char buf[BUFSIZ];
+ int n;
+
+ for (;;)
+ {
+ n = read (fdin, buf, sizeof(buf));
+ if (n == -1)
+ {
+#ifdef EINTR
+ if (errno == EINTR)
+ continue;
+#endif
+ error (1, errno, "cannot read file %s for copying", from);
+ }
+ else if (n == 0)
+ break;
+
+ if (write(fdout, buf, n) != n) {
+ error (1, errno, "cannot write file %s for copying", to);
+ }
+ }
+
+#ifdef HAVE_FSYNC
+ if (fsync (fdout))
+ error (1, errno, "cannot fsync file %s after copying", to);
+#endif
+ }
+
+ if (close (fdin) < 0)
+ error (0, errno, "cannot close %s", from);
+ if (close (fdout) < 0)
+ error (1, errno, "cannot close %s", to);
+
+ /* now, set the times for the copied file to match those of the original */
+ memset ((char *) &t, 0, sizeof (t));
+ t.actime = sb.st_atime;
+ t.modtime = sb.st_mtime;
+ (void) utime (to, &t);
+}
+
+/* FIXME-krp: these functions would benefit from caching the char * &
+ stat buf. */
+
+/*
+ * Returns non-zero if the argument file is a directory, or is a symbolic
+ * link which points to a directory.
+ */
+int
+isdir (file)
+ const char *file;
+{
+ struct stat sb;
+
+ if (stat (file, &sb) < 0)
+ return (0);
+ return (S_ISDIR (sb.st_mode));
+}
+
+/*
+ * Returns non-zero if the argument file is a symbolic link.
+ */
+int
+islink (file)
+ const char *file;
+{
+#ifdef S_ISLNK
+ struct stat sb;
+
+ if (lstat (file, &sb) < 0)
+ return (0);
+ return (S_ISLNK (sb.st_mode));
+#else
+ return (0);
+#endif
+}
+
+/*
+ * Returns non-zero if the argument file exists.
+ */
+int
+isfile (file)
+ const char *file;
+{
+ return isaccessible(file, F_OK);
+}
+
+/*
+ * Returns non-zero if the argument file is readable.
+ */
+int
+isreadable (file)
+ const char *file;
+{
+ return isaccessible(file, R_OK);
+}
+
+/*
+ * Returns non-zero if the argument file is writable.
+ */
+int
+iswritable (file)
+ const char *file;
+{
+ return isaccessible(file, W_OK);
+}
+
+/*
+ * Returns non-zero if the argument file is accessable according to
+ * mode. If compiled with SETXID_SUPPORT also works if cvs has setxid
+ * bits set.
+ */
+int
+isaccessible (file, mode)
+ const char *file;
+ const int mode;
+{
+#ifdef SETXID_SUPPORT
+ struct stat sb;
+ int umask = 0;
+ int gmask = 0;
+ int omask = 0;
+ int uid;
+
+ if (stat(file, &sb) == -1)
+ return 0;
+ if (mode == F_OK)
+ return 1;
+
+ uid = geteuid();
+ if (uid == 0) /* superuser */
+ {
+ if (mode & X_OK)
+ return sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH);
+ else
+ return 1;
+ }
+
+ if (mode & R_OK)
+ {
+ umask |= S_IRUSR;
+ gmask |= S_IRGRP;
+ omask |= S_IROTH;
+ }
+ if (mode & W_OK)
+ {
+ umask |= S_IWUSR;
+ gmask |= S_IWGRP;
+ omask |= S_IWOTH;
+ }
+ if (mode & X_OK)
+ {
+ umask |= S_IXUSR;
+ gmask |= S_IXGRP;
+ omask |= S_IXOTH;
+ }
+
+ if (sb.st_uid == uid)
+ return (sb.st_mode & umask) == umask;
+ else if (sb.st_gid == getegid())
+ return (sb.st_mode & gmask) == gmask;
+ else
+ return (sb.st_mode & omask) == omask;
+#else
+ return access(file, mode) == 0;
+#endif
+}
+
+/*
+ * Open a file and die if it fails
+ */
+FILE *
+open_file (name, mode)
+ const char *name;
+ const char *mode;
+{
+ FILE *fp;
+
+ if ((fp = fopen (name, mode)) == NULL)
+ error (1, errno, "cannot open %s", name);
+ return (fp);
+}
+
+/*
+ * Make a directory and die if it fails
+ */
+void
+make_directory (name)
+ const char *name;
+{
+ struct stat sb;
+
+ if (stat (name, &sb) == 0 && (!S_ISDIR (sb.st_mode)))
+ error (0, 0, "%s already exists but is not a directory", name);
+ if (!noexec && mkdir (name, 0777) < 0)
+ error (1, errno, "cannot make directory %s", name);
+}
+
+/*
+ * Make a path to the argument directory, printing a message if something
+ * goes wrong.
+ */
+void
+make_directories (name)
+ const char *name;
+{
+ char *cp;
+
+ if (noexec)
+ return;
+
+ if (mkdir (name, 0777) == 0 || errno == EEXIST)
+ return;
+ if (! existence_error (errno))
+ {
+ error (0, errno, "cannot make path to %s", name);
+ return;
+ }
+ if ((cp = strrchr (name, '/')) == NULL)
+ return;
+ *cp = '\0';
+ make_directories (name);
+ *cp++ = '/';
+ if (*cp == '\0')
+ return;
+ (void) mkdir (name, 0777);
+}
+
+/* Create directory NAME if it does not already exist; fatal error for
+ other errors. Returns 0 if directory was created; 1 if it already
+ existed. */
+int
+mkdir_if_needed (name)
+ char *name;
+{
+ if (mkdir (name, 0777) < 0)
+ {
+ if (errno != EEXIST)
+ error (1, errno, "cannot make directory %s", name);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Change the mode of a file, either adding write permissions, or removing
+ * all write permissions. Either change honors the current umask setting.
+ * The EMX doc (0.9c, emxlib.doc) says that chmod sets/clears the readonly
+ * bit. But it always seemed to be a noop when I tried it. Therefore,
+ * I've copied over the "attrib" code from os2/filesubr.c.
+ */
+void
+xchmod (fname, writable)
+ char *fname;
+ int writable;
+{
+ char *attrib_cmd;
+ char *attrib_option;
+ char *whole_cmd;
+ char *p;
+ char *q;
+
+ if (!isfile (fname))
+ {
+ error (0, 0, "cannot change mode of file %s; it does not exist",
+ fname);
+ return;
+ }
+
+ attrib_cmd = "attrib "; /* No, really? */
+
+ if (writable)
+ attrib_option = "-r "; /* make writeable */
+ else
+ attrib_option = "+r "; /* make read-only */
+
+ whole_cmd = xmalloc (strlen (attrib_cmd)
+ + strlen (attrib_option)
+ + strlen (fname)
+ + 1);
+
+ strcpy (whole_cmd, attrib_cmd);
+ strcat (whole_cmd, attrib_option);
+
+ /* Copy fname to the end of whole_cmd, translating / to \.
+ Attrib doesn't take / but many parts of CVS rely
+ on being able to use it. */
+ p = whole_cmd + strlen (whole_cmd);
+ q = fname;
+ while (*q)
+ {
+ if (*q == '/')
+ *p++ = '\\';
+ else
+ *p++ = *q;
+ ++q;
+ }
+ *p = '\0';
+
+ system (whole_cmd);
+ free (whole_cmd);
+}
+
+/*
+ * Rename a file and die if it fails
+ */
+void
+rename_file (from, to)
+ const char *from;
+ const char *to;
+{
+ if (trace)
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> rename(%s,%s)\n",
+ (server_active) ? 'S' : ' ', from, to);
+#else
+ (void) fprintf (stderr, "-> rename(%s,%s)\n", from, to);
+#endif
+ if (noexec)
+ return;
+
+ unlink_file (to);
+ if (rename (from, to) != 0)
+ error (1, errno, "cannot rename file %s to %s", from, to);
+}
+
+/*
+ * link a file, if possible. Warning: the Windows NT version of this
+ * function just copies the file, so only use this function in ways
+ * that can deal with either a link or a copy.
+ */
+int
+link_file (from, to)
+ const char *from;
+ const char *to;
+{
+ if (trace)
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> link(%s,%s)\n",
+ (server_active) ? 'S' : ' ', from, to);
+#else
+ (void) fprintf (stderr, "-> link(%s,%s)\n", from, to);
+#endif
+ if (noexec)
+ return (0);
+
+ copy_file (from, to);
+ return 0;
+}
+
+/*
+ * unlink a file, if possible.
+ */
+int
+unlink_file (f)
+ const char *f;
+{
+ if (trace)
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> unlink(%s)\n",
+ (server_active) ? 'S' : ' ', f);
+#else
+ (void) fprintf (stderr, "-> unlink(%s)\n", f);
+#endif
+ if (noexec)
+ return (0);
+
+ if (isfile (f))
+ xchmod ((char *)f, 1);
+ return (unlink (f));
+}
+
+/*
+ * Unlink a file or dir, if possible. If it is a directory do a deep
+ * removal of all of the files in the directory. Return -1 on error
+ * (in which case errno is set).
+ */
+int
+unlink_file_dir (f)
+ const char *f;
+{
+ if (trace)
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> unlink_file_dir(%s)\n",
+ (server_active) ? 'S' : ' ', f);
+#else
+ (void) fprintf (stderr, "-> unlink_file_dir(%s)\n", f);
+#endif
+ if (noexec)
+ return (0);
+
+ /* For at least some unices, if root tries to unlink() a directory,
+ instead of doing something rational like returning EISDIR,
+ the system will gleefully go ahead and corrupt the filesystem.
+ So we first call isdir() to see if it is OK to call unlink(). This
+ doesn't quite work--if someone creates a directory between the
+ call to isdir() and the call to unlink(), we'll still corrupt
+ the filesystem. Where is the Unix Haters Handbook when you need
+ it? */
+ if (isdir(f))
+ return deep_remove_dir(f);
+ else
+ {
+ if (unlink (f) != 0)
+ return -1;
+ }
+ /* We were able to remove the file from the disk */
+ return 0;
+}
+
+/* Remove a directory and everything it contains. Returns 0 for
+ * success, -1 for failure (in which case errno is set).
+ */
+
+static int
+deep_remove_dir (path)
+ const char *path;
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char buf[PATH_MAX];
+
+ if (rmdir (path) != 0)
+ {
+ if (errno == ENOTEMPTY
+ || errno == EEXIST
+ /* Ugly workaround for ugly AIX 4.1 (and 3.2) header bug
+ (it defines ENOTEMPTY and EEXIST to 17 but actually
+ returns 87). */
+ || (ENOTEMPTY == 17 && EEXIST == 17 && errno == 87))
+ {
+ if ((dirp = opendir (path)) == NULL)
+ /* If unable to open the directory return
+ * an error
+ */
+ return -1;
+
+ while ((dp = readdir (dirp)) != NULL)
+ {
+ if (strcmp (dp->d_name, ".") == 0 ||
+ strcmp (dp->d_name, "..") == 0)
+ continue;
+
+ sprintf (buf, "%s/%s", path, dp->d_name);
+
+ /* See comment in unlink_file_dir explanation of why we use
+ isdir instead of just calling unlink and checking the
+ status. */
+ if (isdir(buf))
+ {
+ if (deep_remove_dir(buf))
+ {
+ closedir(dirp);
+ return -1;
+ }
+ }
+ else
+ {
+ if (unlink (buf) != 0)
+ {
+ closedir(dirp);
+ return -1;
+ }
+ }
+ }
+ closedir (dirp);
+ return rmdir (path);
+ }
+ else
+ return -1;
+ }
+
+ /* Was able to remove the directory return 0 */
+ return 0;
+}
+
+/* Read NCHARS bytes from descriptor FD into BUF.
+ Return the number of characters successfully read.
+ The number returned is always NCHARS unless end-of-file or error. */
+static size_t
+block_read (fd, buf, nchars)
+ int fd;
+ char *buf;
+ size_t nchars;
+{
+ char *bp = buf;
+ size_t nread;
+
+ do
+ {
+ nread = read (fd, bp, nchars);
+ if (nread == (size_t)-1)
+ {
+#ifdef EINTR
+ if (errno == EINTR)
+ continue;
+#endif
+ return (size_t)-1;
+ }
+
+ if (nread == 0)
+ break;
+
+ bp += nread;
+ nchars -= nread;
+ } while (nchars != 0);
+
+ return bp - buf;
+}
+
+
+/*
+ * Compare "file1" to "file2". Return non-zero if they don't compare exactly.
+ */
+int
+xcmp (file1, file2)
+ const char *file1;
+ const char *file2;
+{
+ char *buf1, *buf2;
+ struct stat sb1, sb2;
+ int fd1, fd2;
+ int ret;
+
+ if ((fd1 = open (file1, O_RDONLY | O_BINARY)) < 0)
+ error (1, errno, "cannot open file %s for comparing", file1);
+ if ((fd2 = open (file2, O_RDONLY | O_BINARY)) < 0)
+ error (1, errno, "cannot open file %s for comparing", file2);
+ if (fstat (fd1, &sb1) < 0)
+ error (1, errno, "cannot fstat %s", file1);
+ if (fstat (fd2, &sb2) < 0)
+ error (1, errno, "cannot fstat %s", file2);
+
+ /* A generic file compare routine might compare st_dev & st_ino here
+ to see if the two files being compared are actually the same file.
+ But that won't happen in CVS, so we won't bother. */
+
+ if (sb1.st_size != sb2.st_size)
+ ret = 1;
+ else if (sb1.st_size == 0)
+ ret = 0;
+ else
+ {
+ /* FIXME: compute the optimal buffer size by computing the least
+ common multiple of the files st_blocks field */
+ size_t buf_size = 8 * 1024;
+ size_t read1;
+ size_t read2;
+
+ buf1 = xmalloc (buf_size);
+ buf2 = xmalloc (buf_size);
+
+ do
+ {
+ read1 = block_read (fd1, buf1, buf_size);
+ if (read1 == (size_t)-1)
+ error (1, errno, "cannot read file %s for comparing", file1);
+
+ read2 = block_read (fd2, buf2, buf_size);
+ if (read2 == (size_t)-1)
+ error (1, errno, "cannot read file %s for comparing", file2);
+
+ /* assert (read1 == read2); */
+
+ ret = memcmp(buf1, buf2, read1);
+ } while (ret == 0 && read1 == buf_size);
+
+ free (buf1);
+ free (buf2);
+ }
+
+ (void) close (fd1);
+ (void) close (fd2);
+ return (ret);
+}
+
+
+/* Just in case this implementation does not define this. */
+#ifndef L_tmpnam
+#define L_tmpnam 50
+#endif
+
+
+#ifdef LOSING_TMPNAM_FUNCTION
+char *
+cvs_temp_name ()
+{
+ char value[L_tmpnam + 1];
+
+ /* FIXME: Should be using TMPDIR. */
+ strcpy (value, "/tmp/cvsXXXXXX");
+ mktemp (value);
+ return xstrdup (value);
+}
+#else
+/* Generate a unique temporary filename. Returns a pointer to a newly
+ malloc'd string containing the name. Returns successfully or not at
+ all. */
+char *
+cvs_temp_name ()
+{
+ char value[L_tmpnam + 1];
+ char *retval;
+
+ /* FIXME: should be using TMPDIR, perhaps by using tempnam on systems
+ which have it. */
+ retval = tmpnam (value);
+ if (retval == NULL)
+ error (1, errno, "cannot generate temporary filename");
+ return xstrdup (retval);
+}
+#endif
+
+
+/* Return non-zero iff FILENAME is absolute.
+ Trivial under Unix, but more complicated under other systems.
+ Under EMX let _fnisabs do all this work. */
+int
+isabsolute (filename)
+ const char *filename;
+{
+ return _fnisabs(filename);
+}
+
+
+/* Return a pointer into PATH's last component. */
+char *
+last_component (path)
+ char *path;
+{
+ char *last;
+
+ /* We can't be sure here if 'path' is already slashified. */
+ _fnslashify (path);
+
+ last = strrchr (path, '/');
+
+ if (last)
+ return last + 1;
+ else
+ return path;
+}
+
+/* Return the home directory. Returns a pointer to storage
+ managed by this function or its callees (currently getenv).
+ This function will return the same thing every time it is
+ called. */
+char *
+get_homedir ()
+{
+ static char *home = NULL;
+ char *env = getenv ("HOME");
+ struct passwd *pw;
+
+ if (home != NULL)
+ return home;
+
+ if (env)
+ home = env;
+ else if ((pw = (struct passwd *) getpwuid (getuid ()))
+ && pw->pw_dir)
+ home = xstrdup (pw->pw_dir);
+ else
+ return 0;
+
+ return home;
+}
+
+/* See cvs.h for description. On unix this does nothing, because the
+ shell expands the wildcards. Under EMX, use _fnexplode to get the
+ expanded filenames */
+void
+expand_wild (argc, argv, pargc, pargv)
+ int argc;
+ char **argv;
+ int *pargc;
+ char ***pargv;
+{
+ int i;
+ *pargc = argc;
+ *pargv = (char **) xmalloc (argc * sizeof (char *));
+ for (i = 0; i < argc; ++i)
+ (*pargv)[i] = xstrdup (argv[i]);
+}
+
+unsigned char
+OS2_filename_classes[] =
+{
+ 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
+ 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
+ 0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
+ 0x20,0x21,0x22,0x23, 0x24,0x25,0x26,0x27,
+ 0x28,0x29,0x2a,0x2b, 0x2c,0x2d,0x2e,0x2f,
+ 0x30,0x31,0x32,0x33, 0x34,0x35,0x36,0x37,
+ 0x38,0x39,0x3a,0x3b, 0x3c,0x3d,0x3e,0x3f,
+ 0x40,0x61,0x62,0x63, 0x64,0x65,0x66,0x67,
+ 0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
+ 0x70,0x71,0x72,0x73, 0x74,0x75,0x76,0x77,
+ 0x78,0x79,0x7a,0x5b, 0x2f,0x5d,0x5e,0x5f,
+ 0x60,0x61,0x62,0x63, 0x64,0x65,0x66,0x67,
+ 0x68,0x69,0x6a,0x6b, 0x6c,0x6d,0x6e,0x6f,
+ 0x70,0x71,0x72,0x73, 0x74,0x75,0x76,0x77,
+ 0x78,0x79,0x7a,0x7b, 0x7c,0x7d,0x7e,0x7f,
+ 0x80,0x81,0x82,0x83, 0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8a,0x8b, 0x8c,0x8d,0x8e,0x8f,
+ 0x90,0x91,0x92,0x93, 0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9a,0x9b, 0x9c,0x9d,0x9e,0x9f,
+ 0xa0,0xa1,0xa2,0xa3, 0xa4,0xa5,0xa6,0xa7,
+ 0xa8,0xa9,0xaa,0xab, 0xac,0xad,0xae,0xaf,
+ 0xb0,0xb1,0xb2,0xb3, 0xb4,0xb5,0xb6,0xb7,
+ 0xb8,0xb9,0xba,0xbb, 0xbc,0xbd,0xbe,0xbf,
+ 0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
+ 0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
+ 0xd0,0xd1,0xd2,0xd3, 0xd4,0xd5,0xd6,0xd7,
+ 0xd8,0xd9,0xda,0xdb, 0xdc,0xdd,0xde,0xdf,
+ 0xe0,0xe1,0xe2,0xe3, 0xe4,0xe5,0xe6,0xe7,
+ 0xe8,0xe9,0xea,0xeb, 0xec,0xed,0xee,0xef,
+ 0xf0,0xf1,0xf2,0xf3, 0xf4,0xf5,0xf6,0xf7,
+ 0xf8,0xf9,0xfa,0xfb, 0xfc,0xfd,0xfe,0xff,
+};
+
+
+/* Like strcmp, but with the appropriate tweaks for file names.
+ Under OS/2, filenames are case-insensitive but case-preserving, and
+ both \ and / are path element separators. */
+int
+fncmp (const char *n1, const char *n2)
+{
+ char fn1[MAXNAMLEN], fn2[MAXNAMLEN];
+
+ strcpy (fn1, n1); _fnslashify(fn1);
+ strcpy (fn2, n2); _fnslashify(fn2);
+
+ return _fncmp ((unsigned char *) fn1, (unsigned char *) fn2);
+}
+
+
+/* Fold characters in FILENAME to their canonical forms.
+ If FOLD_FN_CHAR is not #defined, the system provides a default
+ definition for this. */
+void
+fnfold (char *filename)
+{
+ while (*filename)
+ {
+ *filename = FOLD_FN_CHAR (*filename);
+ filename++;
+ }
+}
diff --git a/gnu/usr.bin/cvs/emx/options.h b/gnu/usr.bin/cvs/emx/options.h
index add2795763d..c247ccb155c 100644
--- a/gnu/usr.bin/cvs/emx/options.h
+++ b/gnu/usr.bin/cvs/emx/options.h
@@ -17,19 +17,6 @@
*/
/*
- * CVS provides the most features when used in conjunction with the
- * Version-5 release of RCS. Thus, it is the default. This also
- * assumes that GNU diff Version-1.15 is being used as well -- you
- * will have to configure your RCS V5 release separately to make this
- * the case. If you do not have RCS V5 and GNU diff V1.15, comment out
- * this define. You should not try mixing and matching other
- * combinations of these tools.
- */
-#ifndef HAVE_RCS5
-#define HAVE_RCS5
-#endif
-
-/*
* For portability and heterogeneity reasons, CVS is shipped by
* default using my own text-file version of the ndbm database library
* in the src/myndbm.c file. If you want better performance and are
@@ -41,23 +28,6 @@
#endif
/*
- * The "diff" program to execute when creating patch output. This
- * "diff" must support the "-c" option for context diffing. Specify a
- * full pathname if your site wants to use a particular diff. Note
- * that unlike the diff used with RCS, you *must not* supply -a here
- * (doing so will cause the server to generate patches which patch
- * cannot handle in some cases).
- *
- * NOTE: this program is only used for the ``patch'' sub-command (and
- * for ``update'' if you are using the server). The other commands
- * use rcsdiff which will use whatever version of diff was specified
- * when rcsdiff was built on your system.
- */
-#ifndef DIFF
-#define DIFF "diff"
-#endif
-
-/*
* The "patch" program to run when using the CVS server and accepting
* patches across the network. Specify a full pathname if your site
* wants to use a particular patch.
@@ -66,41 +36,6 @@
#define PATCH_PROGRAM "patch"
#endif
-/*
- * By default, RCS programs are executed with the shell or through
- * execlp(), so the user's PATH environment variable is searched. If
- * you'd like to bind all RCS programs to a certain directory (perhaps
- * one not in most people's PATH) then set the default in RCSBIN_DFLT.
- * Note that setting this here will cause all RCS programs to be
- * executed from this directory, unless the user overrides the default
- * with the RCSBIN environment variable or the "-b" option to CVS.
- *
- * If you use the password-authenticating server, then you need to
- * make sure that the server can find the RCS programs to invoke them.
- * The authenticating server starts out running as root, and then
- * switches to run as the appropriate user once authentication is
- * complete. But no actual shell is ever started by that user, so the
- * PATH environment variable may not contain the directory with the
- * RCS binaries, even though if that user logged in normally, PATH
- * would include the directory.
- *
- * One way to solve this problem is to set RCSBIN_DFLT here. An
- * alternative is to make sure that root has the right directory in
- * its path already. Another, probably better alternative is to
- * specify -b in /etc/inetd.conf.
- *
- * You may also have to set RCSBIN_DFLT here if there's no global
- * start-up script run for users by rshd and your RCS programs are not
- * in a directory in the default PATH assigned by rshd.
- *
- * This define should be either the empty string ("") or a full
- * pathname to the directory containing all the installed programs
- * from the RCS distribution.
- */
-#ifndef RCSBIN_DFLT
-#define RCSBIN_DFLT ""
-#endif
-
/* Directory used for storing temporary files, if not overridden by
environment variables or the -T global option. There should be little
need to change this (-T is a better mechanism if you need to use a
@@ -262,8 +197,3 @@
#ifndef STDC_HEADERS
extern void exit ();
#endif
-
-#ifndef getwd
-extern char *getwd ();
-#endif
-
diff --git a/gnu/usr.bin/cvs/emx/savecwd.c b/gnu/usr.bin/cvs/emx/savecwd.c
new file mode 100644
index 00000000000..a0951a8188f
--- /dev/null
+++ b/gnu/usr.bin/cvs/emx/savecwd.c
@@ -0,0 +1,141 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#else
+# include <sys/file.h>
+#endif
+
+#ifdef HAVE_DIRECT_H
+# include <direct.h>
+#endif
+
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif
+
+#include <errno.h>
+# ifndef errno
+extern int errno;
+#endif
+
+#include "savecwd.h"
+#include "error.h"
+
+char *xgetwd __PROTO((void));
+
+/* Record the location of the current working directory in CWD so that
+ the program may change to other directories and later use restore_cwd
+ to return to the recorded location. This function may allocate
+ space using malloc (via xgetwd) or leave a file descriptor open;
+ use free_cwd to perform the necessary free or close. Upon failure,
+ no memory is allocated, any locally opened file descriptors are
+ closed; return non-zero -- in that case, free_cwd need not be
+ called, but doing so is ok. Otherwise, return zero. */
+
+int
+save_cwd (cwd)
+ struct saved_cwd *cwd;
+{
+ static int have_working_fchdir = 1;
+
+ cwd->desc = -1;
+ cwd->name = NULL;
+
+ if (have_working_fchdir)
+ {
+#ifdef HAVE_FCHDIR
+ cwd->desc = open (".", O_RDONLY);
+ if (cwd->desc < 0)
+ {
+ error (0, errno, "cannot open current directory");
+ return 1;
+ }
+
+# if __sun__ || sun
+ /* On SunOS 4, fchdir returns EINVAL if accounting is enabled,
+ so we have to fall back to chdir. */
+ if (fchdir (cwd->desc))
+ {
+ if (errno == EINVAL)
+ {
+ close (cwd->desc);
+ cwd->desc = -1;
+ have_working_fchdir = 0;
+ }
+ else
+ {
+ error (0, errno, "current directory");
+ close (cwd->desc);
+ cwd->desc = -1;
+ return 1;
+ }
+ }
+# endif /* __sun__ || sun */
+#else
+#define fchdir(x) (abort (), 0)
+ have_working_fchdir = 0;
+#endif
+ }
+
+ if (!have_working_fchdir)
+ {
+ cwd->name = xgetwd ();
+ if (cwd->name == NULL)
+ {
+ error (0, errno, "cannot get current directory");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Change to recorded location, CWD, in directory hierarchy.
+ If "saved working directory", NULL))
+ */
+
+int
+restore_cwd (cwd, dest)
+ const struct saved_cwd *cwd;
+ const char *dest;
+{
+ int fail = 0;
+ if (cwd->desc >= 0)
+ {
+ if (fchdir (cwd->desc))
+ {
+ error (0, errno, "cannot return to %s",
+ (dest ? dest : "saved working directory"));
+ fail = 1;
+ }
+ }
+ else if (_chdir2 (cwd->name) < 0)
+ {
+ error (0, errno, "%s", cwd->name);
+ fail = 1;
+ }
+ return fail;
+}
+
+void
+free_cwd (cwd)
+ struct saved_cwd *cwd;
+{
+ if (cwd->desc >= 0)
+ close (cwd->desc);
+ if (cwd->name)
+ free (cwd->name);
+}
+
diff --git a/gnu/usr.bin/cvs/emx/startserver.c b/gnu/usr.bin/cvs/emx/startserver.c
new file mode 100644
index 00000000000..ae26c4e5446
--- /dev/null
+++ b/gnu/usr.bin/cvs/emx/startserver.c
@@ -0,0 +1,84 @@
+/* This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ 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. See the
+ GNU General Public License for more details. */
+
+#include <assert.h>
+#include "cvs.h"
+#include "rcmd.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include "options.h"
+
+static char *cvs_server;
+static char *command;
+
+extern int trace;
+
+void
+os2_start_server (int *tofd, int *fromfd,
+ char *client_user,
+ char *server_user,
+ char *server_host,
+ char *server_cvsroot)
+{
+ int fd, port;
+ char *portenv;
+ struct servent *sptr;
+ const char *rcmd_host = (const char *) server_host;
+
+ if (! (cvs_server = getenv ("CVS_SERVER")))
+ cvs_server = "cvs";
+ command = xmalloc (strlen (cvs_server)
+ + strlen (server_cvsroot)
+ + 50);
+ sprintf (command, "%s server", cvs_server);
+
+ portenv = getenv ("CVS_RCMD_PORT");
+ if (portenv)
+ port = atoi (portenv);
+ else if ((sptr = getservbyname ("shell", "tcp")) != NULL)
+ port = sptr->s_port;
+ else
+ port = 514; /* shell/tcp */
+
+ if (trace)
+ {
+ fprintf (stderr, "os2_start_server(): connecting to %s:%d\n",
+ server_host, port);
+ fprintf (stderr, "local_user = %s, remote_user = %s, CVSROOT = %s\n",
+ client_user, (server_user ? server_user : client_user),
+ server_cvsroot);
+ }
+
+ fd = rcmd (&rcmd_host, port,
+ client_user,
+ (server_user ? server_user : client_user),
+ command, 0);
+
+ if (fd < 0)
+ error (1, errno, "cannot start server via rcmd()");
+
+ *tofd = fd;
+ *fromfd = fd;
+ free (command);
+}
+
+void
+os2_shutdown_server (int fd)
+{
+ /* FIXME: shutdown on files seems to have no bad effects */
+ if (shutdown (fd, 2) < 0 && errno != ENOTSOCK)
+ error (1, 0, "couldn't shutdown server connection");
+ if (close (fd) < 0)
+ error (1, 0, "couldn't close server connection");
+}
+
diff --git a/gnu/usr.bin/cvs/emx/stripslash.c b/gnu/usr.bin/cvs/emx/stripslash.c
new file mode 100644
index 00000000000..a68763d5733
--- /dev/null
+++ b/gnu/usr.bin/cvs/emx/stripslash.c
@@ -0,0 +1,27 @@
+/* stripslash.c -- remove trailing slashes from a string
+ Copyright (C) 1990 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ 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. See the
+ GNU General Public License for more details. */
+
+#include <string.h>
+
+/* Remove trailing slashes from PATH. */
+
+void
+strip_trailing_slashes (path)
+ char *path;
+{
+ int last;
+
+ last = strlen (path) - 1;
+ while (last > 0 && (path[last] == '/' || path[last] == '\\'))
+ path[last--] = '\0';
+}
diff --git a/gnu/usr.bin/cvs/emx/system.c b/gnu/usr.bin/cvs/emx/system.c
new file mode 100644
index 00000000000..f4481b371dd
--- /dev/null
+++ b/gnu/usr.bin/cvs/emx/system.c
@@ -0,0 +1,91 @@
+/* This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ 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. See the
+ GNU General Public License for more details. */
+
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <fnmatch.h>
+
+
+/* Expand wildcards in argv. We probably should be expanding wildcards
+ via expand_wild instead; that way we could expand only filenames and
+ not tag names and the like. */
+
+void
+os2_initialize (pargc, pargv)
+ int *pargc;
+ char **pargv[];
+{
+ _wildcard (pargc, pargv);
+}
+
+
+/* Modifies 'stat' so that always the same inode is returned. EMX never
+ returns the same value for st_ino. Without this modification,
+ release_delete in module src/release.c refuses to work. Care must
+ be taken if someone is using the value of st_ino (but as far as I know,
+ no callers are). */
+
+int
+os2_stat (name, buffer)
+ const char *name;
+ struct stat *buffer;
+{
+ int rc = stat (name, buffer);
+
+ /* There are no inodes on OS/2. */
+ buffer->st_ino = 42;
+
+ return rc;
+}
+
+
+/* We must not only change the directory, but also the current drive.
+ Otherwise it is be impossible to have the working directory and the
+ repository on different drives. */
+
+int
+os2_chdir (name)
+ const char *name;
+{
+ return _chdir2 (name);
+}
+
+
+/* getwd must return a drive specification. */
+
+char *
+xgetwd ()
+{
+ return _getcwd2 (NULL, 1);
+}
+
+
+/* fnmatch must recognize OS/2 filename conventions: Filename case
+ must be preserved, but ignored in searches. It would perhaps be better
+ to just have CVS pick how to match based on FILENAMES_CASE_INSENSITIVE
+ or something rather than having an OS/2-specific version of CVS_FNMATCH.
+ Note that lib/fnmatch.c uses FOLD_FN_CHAR; that is how we get
+ case-insensitivity on NT (and VMS, I think). */
+
+#define _FNM_OS2 1
+#define _FNM_IGNORECASE 128
+
+int
+os2_fnmatch (pattern, name, flags)
+ const char *pattern;
+ const char *name;
+ int flags;
+{
+ return fnmatch (pattern, name, _FNM_IGNORECASE | _FNM_OS2 | flags);
+}