summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/cvs/os2
diff options
context:
space:
mode:
authorThorsten Lockert <tholo@cvs.openbsd.org>1996-01-30 00:19:41 +0000
committerThorsten Lockert <tholo@cvs.openbsd.org>1996-01-30 00:19:41 +0000
commitde069631fd3bce2e513ee8613a94038f23afe1b3 (patch)
tree0b8d9d99cdfb52e8d0c3f85c45859a42ed004bd3 /gnu/usr.bin/cvs/os2
parent2b9936f3f7ab47a89436d4fa3b70e4c09dd2398e (diff)
Upgrade to 1.7.1 snapshot
Diffstat (limited to 'gnu/usr.bin/cvs/os2')
-rw-r--r--gnu/usr.bin/cvs/os2/.cvsignore3
-rw-r--r--gnu/usr.bin/cvs/os2/ChangeLog589
-rw-r--r--gnu/usr.bin/cvs/os2/Makefile.in303
-rw-r--r--gnu/usr.bin/cvs/os2/README31
-rw-r--r--gnu/usr.bin/cvs/os2/dirent.c180
-rw-r--r--gnu/usr.bin/cvs/os2/dirent.h50
-rw-r--r--gnu/usr.bin/cvs/os2/filesubr.c737
-rw-r--r--gnu/usr.bin/cvs/os2/getdate.c1578
-rw-r--r--gnu/usr.bin/cvs/os2/getpass.c25
-rw-r--r--gnu/usr.bin/cvs/os2/mkdir.c17
-rw-r--r--gnu/usr.bin/cvs/os2/options.h276
-rw-r--r--gnu/usr.bin/cvs/os2/popen.c380
-rw-r--r--gnu/usr.bin/cvs/os2/popen.h6
-rw-r--r--gnu/usr.bin/cvs/os2/porttcp.c227
-rw-r--r--gnu/usr.bin/cvs/os2/pwd.c205
-rw-r--r--gnu/usr.bin/cvs/os2/pwd.h77
-rw-r--r--gnu/usr.bin/cvs/os2/rcmd.c66
-rw-r--r--gnu/usr.bin/cvs/os2/rcmd.h30
-rw-r--r--gnu/usr.bin/cvs/os2/run.c602
-rw-r--r--gnu/usr.bin/cvs/os2/strippath.c60
-rw-r--r--gnu/usr.bin/cvs/os2/stripslash.c31
-rw-r--r--gnu/usr.bin/cvs/os2/tcpip.h107
-rw-r--r--gnu/usr.bin/cvs/os2/test-makefile40
-rw-r--r--gnu/usr.bin/cvs/os2/waitpid.c36
24 files changed, 5656 insertions, 0 deletions
diff --git a/gnu/usr.bin/cvs/os2/.cvsignore b/gnu/usr.bin/cvs/os2/.cvsignore
new file mode 100644
index 00000000000..fc6daa165c6
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/.cvsignore
@@ -0,0 +1,3 @@
+Makefile
+cvs.exe
+icc.in
diff --git a/gnu/usr.bin/cvs/os2/ChangeLog b/gnu/usr.bin/cvs/os2/ChangeLog
new file mode 100644
index 00000000000..0a6070f4b08
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/ChangeLog
@@ -0,0 +1,589 @@
+Sun Jan 28 12:31:03 1996 Jim Kingdon (kingdon@beezley)
+
+ * filesubr.c (unlink_file): Use xchmod, not chmod, to make the
+ file read-write.
+ (xchmod): Translate / to \ in file name. If file doesn't exist,
+ return ENOENT rather than passing it to attrib (which will print an
+ error message).
+
+Sun Jan 28 01:51:27 1996 Jim Kingdon (kingdon@beezley)
+
+ * config.h: Fix unclosed comment.
+
+Sun Jan 28 00:16:58 1996 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * filesubr.c (xchmod): rewritten for OS/2.
+
+Sat Jan 27 16:18:20 1996 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * config.h (CHMOD_BROKEN): define to 1.
+
+ * filesubr.c (rename_file): rename() returns non-zero error codes,
+ not necessarily negative.
+
+Fri Jan 26 00:52:12 1996 unknown (unknown@beezley)
+
+ * filesubr.c (copy_file): Open the file we are writing, not
+ just the one we are reading, in binary mode.
+
+Thu Jan 18 14:53:58 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in (CFLAGS): Don't use +=. This makefile must be
+ portable because it is used on all platforms (e.g. for "make dist").
+
+Thu Jan 11 12:04:42 1996 Norbert Kiesel <nk@col.sw-ley.de>
+
+ * options.h: remove CVS_NOADMIN
+
+Wed Jan 10 15:56:46 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * options.h, config.h: moved NO_SOCKET_TO_FD definition from
+ options.h to config.h, which is where it belongs.
+
+Tue Jan 9 16:43:15 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * run.c (sleep): commented out this definition.
+ * config.h: #define sleep() in terms of DosSleep(), unless sleep()
+ is defined already. Normally it's defined in
+ tcpip/include/utils.h, however on beezley that definition is
+ commented out for some reason.
+ Don't prototype sleep().
+
+Tue Jan 9 16:22:35 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * .cvsignore: Add cvs.exe and icc.in.
+
+Tue Jan 09 16:43:59 1996 Jim Kingdon (kingdon@beezley.cyclic.com)
+
+ * filesubr.c (link_file): New function (copied from
+ ../windows-NT/filesubr.c)
+
+Fri Jan 5 17:03:09 1996 Karl Fogel <kfogel@floss.red-bean.com>
+
+ * Makefile.in: "lib_dir", not "libdir", to avoid conflict with
+ top-level Makefile.
+
+Mon Jan 1 22:59:46 1996 Jim Kingdon <kingdon@harvey.cyclic.com>
+
+ * Makefile.in (DISTFILES): Makefile is not in srcdir.
+
+Sat Dec 23 23:08:43 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * README: adjust for below change.
+
+ * Makefile.in (install-cvs): replaces `install', which must remain
+ a dummy rule so it will work under Unix.
+
+Wed Dec 20 15:18:06 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in: build scramble.obj.
+
+Mon Dec 18 22:49:28 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Reverted all changes between Mon Dec 18 14:54:04 1995 and
+ present, non-inclusive.
+
+Mon Dec 18 21:59:07 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * getpass.c: removed -- getpass() lives in os2/login.c now.
+
+ * cvslogin.c: filled in.
+
+ * login.c: new file.
+
+ * Makefile.in: moved login.c and login.obj from COMMON to OS2
+ section.
+
+Mon Dec 18 19:55:43 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * cvslogin.c: added long explanatory comment.
+
+Mon Dec 18 18:13:57 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (DISTFILES): include cvslogin.c.
+
+Mon Dec 18 18:07:26 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * README: updated.
+
+ * Makefile.in (cvslogin.exe): new rule.
+ (install): new rule.
+ (install_dir): new var.
+
+ * cvslogin.c: new file.
+
+Mon Dec 18 14:54:04 1995 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * getpass.c (getpass): removed debugging garbage.
+
+ * options.h (NO_SOCKET_TO_FD): fixed comment (Windows 95, not NT,
+ has this problem).
+ (AUTH_CLIENT_SUPPORT): on by default.
+
+ * porttcp.c (SockStrError): fixed typo.
+ (IbmSockSend): `Buffer' arg is const void * again.
+ (IbmSockRecv): `Buffer' arg is const void * again.
+
+ * tcpip.h (send): move send/recv redef section farther down to
+ avoid type conflicts with the real send() and recv().
+ (IbmSockSend, IbmSockRecv): adjust prototype.
+
+Mon Dec 18 12:31:22 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * tcpip.h: reformatted.
+ (send, recv): redefine to IbmSockSend and IbmSockRecv.
+
+ * porttcp.c: reformatted.
+
+Mon Dec 18 04:59:52 1995 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * tcpip.h (send, recv): don't define these to be anything else.
+
+ * porttcp.c (IbmSockSend, IbmSockRecv): make `Buffer' argument
+ char * instead of void *, to evade an over-eager compiler.
+
+Sun Dec 17 21:16:17 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * options.h (NO_SOCKET_TO_FD): define to 1.
+
+Sat Dec 16 21:31:02 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * run.c: mark unimplemented routines more clearly. Hopefully I'll
+ get time to implement them soon.
+
+Fri Dec 15 17:50:17 1995 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * tcpip.h, porttcp.c: new files.
+
+ * makefile.in: added new files (for the "cvs watch" and "cvs edit"
+ commands just checked in by Jim Kingdon).
+
+Thu Dec 14 12:18:20 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * config.h (RSH_NEEDS_BINARY_FLAG): define to 1.
+
+ * run.c (filter_stream_through_program): die, rather than return
+ -1, if spawn failed.
+
+ * options.h (AUTH_CLIENT_SUPPORT): leave unset by default.
+
+Wed Dec 13 21:31:10 1995 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * waitpid.c (waitpid): Don't deal specially with statusp after all.
+ The problem lies elsewhere.
+
+Wed Dec 13 20:58:12 1995 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * waitpid.c (waitpid): oops, make sure there is storage for
+ local_statusp.
+ Don't assign to *statusp if statusp is NULL.
+
+Wed Dec 13 19:52:08 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * waitpid.c (waitpid): be more careful about child's exit status,
+ and about return status of this function.
+
+Wed Dec 13 20:10:50 1995 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * makefile.in (clean): pass /NOE to the linker, to avoid duplicate
+ symbols when linking with setargv.obj.
+
+Wed Dec 13 18:44:47 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (ARGVLIB): new lib, link with this so command-line
+ wildcard expansion works. No, I'm not making this up.
+
+Tue Dec 12 20:43:56 1995 Karl Fogel (kfogel@floss.cyclic.com)
+
+ * getpass.c (getpass): new file and function.
+
+ * options.h: prototype getpass() for OS/2.
+
+ * makefile.in: include new file getpass.c.
+
+Tue Dec 12 19:21:05 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * options.h (RCSBIN_DFLT): expand comment.
+ (AUTH_CLIENT_SUPPORT, AUTH_SERVER_SUPPORT): replace obsolete
+ CVS_AUTH_CLIENT_SUPPORT and CVS_AUTH_SERVER_SUPPORT.
+
+Mon Dec 11 16:03:01 1995 Karl Fogel (kfogel@beezley.cyclic.com)
+
+ * makefile.in: removed various and sundry cruft...
+
+Mon Dec 11 15:57:03 1995 Karl Fogel (kfogel@beezley.cyclic.com)
+
+ * Removed cvs.exe; we don't need to keep the binary in the
+ repository, now that binary file handling has been tested.
+
+Mon Dec 11 15:53:51 1995 Karl Fogel (kfogel@beezley.cyclic.com)
+
+ * rcmd.c (init_sockets): use sock_init(), not SockInit().
+
+Mon Dec 11 12:43:35 1995 Adam Glass <adamg@microsoft.com>
+
+ * config.h: Remove NEED_CALL_SOCKINIT macro in favor of the more
+ generic INITIALIZE_SOCKET_SUBSYSTEM.
+ * rcmd.c: Move old NEED_CALL_SOCKINIT code here and wrap it in a
+ function, i.e init_sockets()
+
+Sat Dec 09 21:16:09 1995 Karl Fogel (kfogel@beezley.cyclic.com)
+
+ * Added cvs.exe, mainly to test binary file handling. Once we
+ know it works, we can remove it.
+
+Sat Dec 09 15:29:16 1995 Karl Fogel (kfogel@beezley.cyclic.com)
+
+ * options.h (DIFF, GREP): don't expect autoconf to help us out.
+
+Sat Dec 09 15:05:41 1995 Karl Fogel (kfogel@beezley.cyclic.com)
+
+ * makefile.in (libdir): Fixed.
+
+ * options.h: define CVS_AUTH_CLIENT_SUPPORT and
+ CVS_AUTH_SERVER_SUPPORT, instead of CVS_LOGIN.
+
+Thu Dec 7 14:49:16 1995 Jim Meyering (meyering@comco.com)
+
+ * filesubr.c (isaccessible): Rename from isaccessable.
+
+Mon Dec 4 11:28:10 1995 Norbert Kiesel <nk@col.sw-ley.de>
+
+ * Makefile.in (DISTFILES): prefix all filenames with
+ ${srcdir}${PS}
+ (dist-dir): remove ${srcdir}${PS} (some files already had this
+ prefix, now all have it)
+
+Fri Dec 1 14:29:44 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (srcdir, libdir, cvs_srcdir): use autoconf vars.
+ (dist-dir): use above vars now that they are autoconf-friendly.
+ (clean): same.
+
+Thu Nov 30 18:09:50 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * waitpid.c (waitpid): if _cwait() returns -1, test errno. If
+ ECHILD, then just return pid, else return -1. This is for OS/2,
+ which doesn't have zombie processes, or any other way of
+ remembering a child process after it exits, as far as I can tell.
+
+ * run.c (close_on_exec): don't error, just silently do nothing.
+
+ * Makefile.in: use src/client.c, not os2/client.c.
+
+ * config.h (EXECUTE_PERMISSION_LOSES): define to 1 (see
+ src/client.c for why).
+ (START_RSH_WITH_POPEN_RW): define to 1 (see src/client.c).
+
+Wed Nov 29 16:34:34 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * client.c (start_server): declare pipes[] as int, not FILE *.
+ Kinda nice that it worked anyway, but scary. Ugh.
+
+Wed Nov 22 11:29:11 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * config.h (KFF_DEBUG): expand to nothing; we don't want to print
+ out debugging messages in a production copy.
+
+Tue Nov 21 17:36:16 1995 unknown (unknown@beezley)
+
+ * popen.c: #include <fcntl.h>.
+
+Tue Nov 21 16:18:37 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * popen.h (popenRW): prototype popenRW()... why wasn't I doing
+ this before?
+
+ * client.c (start_server): set tofd and fromfd with popenRW, now
+ that it handles int file descriptors.
+ Log to a file if asked, now that we have
+ filter_stream_through_program().
+
+ * popen.c (popenRW): put int file descriptors into the `pipes'
+ array, not FILE *'s. We'll fdopen in start_server, just like
+ the good old days.
+
+Tue Nov 21 16:34:37 1995 unknown (unknown@beezley)
+
+ * run.c (filter_stream_through_program): defined for OS/2.
+
+ * client.c (start_server): pass a char **argv to popenRW and get a
+ pid in return (instead of a return code).
+
+ * popen.c (popenRW): use a char **argv and spawnvp(), instead of a
+ char *command and DosExecPgm().
+
+Mon Nov 20 23:31:54 1995 unknown (unknown@beezley)
+
+ * filesubr.c (convert_file): pass (S_IREAD | S_IWRITE) to open();
+ we need it if O_CREAT, and it won't hurt if not.
+
+Sun Nov 19 13:43:02 1995 unknown (unknown@beezley)
+
+ * makefile.in (clean): remove obj files in src/ and lib/ dirs too.
+
+Sun Nov 19 12:35:08 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * client.c (start_server): took out old debug statements.
+
+ * dirent.c, dirent.h: took out ^M's.
+
+Sat Nov 18 13:39:06 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * client.c (start_server): took out debug statements.
+
+ * filesubr.c (make_directories): compare errno to EACCESS, not
+ EEXIST, to see if the dir already exists.
+
+ * client.c, filesubr.c: Use new macro `existence_error', instead
+ of comparing errno to ENOENT directly.
+
+ * popen.c (popenRW): fixed misleading comment.
+
+ * client.c:
+ (rsh_pid): no more need for this var; the handle-to-PID library in
+ popen.c manages PID's for us now.
+ (start_rsh_server): removed this func, since we don't use it -- we
+ do use `rsh', but we call it directly from popenRW().
+ (get_responses_and_close): removed cruft that doesn't apply to
+ this port -- i.e., blocks conditional on HAVE_KERBEROS or
+ RSH_NOT_TRANSPARENT.
+ (start_server): Just check return code, instead of recording
+ rsh_pid.
+
+Fri Nov 17 21:13:22 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * client.c (call_in_directory): Ask EACCESS even though we're
+ looking for EEXIST. That's just The Way Things Are Done here,
+ apparently. Ick.
+
+ * getdate.c: took out some cruft that the more portable versions
+ need.
+
+ * Makefile.in: use getdate.c from os2/ subdir, not lib/.
+ We don't use startserver.c anymore, so don't build it.
+
+ * client.c (change_mode): never set anything executable, until we
+ understand what that means in OS/2.
+
+ * config.h (NEED_DECOY_PERMISSIONS): define to 1 (& see
+ system.h).
+
+Fri Nov 17 15:02:05 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * client.c: fixed up more error codes.
+
+ * client.c: (send_repository): take into account the cornucopia of
+ error codes so generously offered by OS/2.
+
+Fri Nov 17 14:53:22 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * client.c, client.h: new files, copied from ../src/.
+
+ * config.h (HAVE_POPEN_RW): don't define this anymore, since we'll
+ just be using our own version of client.c.
+
+ * Makefile.in: reflect the fact that os2/client.c is now used
+ instead of src/client.c.
+
+Thu Nov 16 21:47:22 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * startserver.c: removed. We don't need this anymore.
+
+ * config.h (RSH_NOT_TRANSPARENT): undef this. We have a
+ transparent rsh.
+ (HAVE_POPEN_RW): define to 1.
+
+ * popen.c (popenRW): open writing and reading streams in binary
+ mode (i.e., "wb" and "rb").
+
+ * Makefile.in (clean): use `rm' not `del' to remove files.
+
+Wed Nov 15 15:21:53 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * config.h: don't prototype gethostname() here anymore.
+ (USE_OWN_TCPIP_H): define to 1.
+ (NEED_CALL_SOCKINIT): define to 1.
+ (KFF_DEBUG): debugging macro.
+
+Tue Nov 14 12:20:22 1995 Greg A. Woods <woods@most.weird.com>
+
+ * .cvsignore: "Makefile" generated by ../configure
+
+Mon Nov 13 13:21:43 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (PS): note to maintainers about this var.
+
+Mon Nov 13 07:28:04 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * README: updated.
+
+ * rcmd.c: #include <stdio.h>.
+
+ * Makefile.in: Include lib/regex, lib/getdate, strippath.
+ (PS): default to "/", since we always "make dist" on Unix
+ systems.
+ Ahem, "save-cwd" with a hyphen, not an underscore. Oops.
+
+ * strippath.c: new file.
+
+ * popen.c: set DIAGNOSTIC off. Reformat for readability.
+
+ * popen.h: new file.
+
+ * config.h (USE_OWN_POPEN): define to 1.
+
+ * run.c (Popen): make this work now that we have popen().
+
+Mon Nov 13 01:23:27 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in:
+ (cvs.exe): broke up OBJECTS into components to create icc.in in
+ more steps. OBJECTS had gotten so big that it formed too long a
+ command line all by itself. Sheesh.
+ Include stripslash (see below), lib/save_cwd, lib/sighandle,
+ lib/yesno, startserver (see below), rcmd (see below), lib/xgetwd,
+ lib/md5, waitpid (see below), lib/fnmatch, popen (see below).
+
+ * popen.c, rcmd.c, rcmd.h, startserver.c, stripslash.c, waitpid.c:
+ New files.
+
+ * run.c (close_on_exec): new func (skeleton).
+ (sleep): new func (OS/2 doesn't seem to have this).
+
+ * pwd.c (getlogin): Don't call win32getlogin(), obviously.
+
+ * config.h (W_OK, R_OK, X_OK, F_OK): define masks for access().
+ Include <process.h> for getpid().
+
+ * filesubr.c (isaccessable): define. Don't know why I left it out
+ before. For that matter, I don't know how the Windows NT port
+ gets along without it. Hmmm.
+
+Sat Nov 11 15:00:01 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in: Use backslashes in pathnames, so ICC doesn't
+ mistake them for options.
+
+ * run.c (run_setup): cleared away Windows NT stuff, left skeleton
+ functions that just complain and die for now.
+ (run_exec): correctly check return of spawn under OS/2; return
+ child's exit status.
+ (run_args): declare as returning void, in agreement with cvs.h.
+
+Fri Nov 10 14:21:14 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (COMMON_SOURCES, COMMON_OBJECTS): removed filesubr
+ and run, since we have OS/2-specific versions of them now.
+ (DISTFILES): Include Makefile in distribution, since people won't
+ be running configure on their OS/2 systems.
+ (LIB_SOURCES, LIB_OBJECTS): new vars; we'll just build stuff in
+ the lib directory and link it in directly.
+ Made rules for compiling objects and for the full executable.
+ (SHELL): got rid of this var, no need for it here.
+ Use a pattern rule for obj files.
+ Some other minor tweaks for OS/2.
+
+ * threads.c: new file.
+
+Wed Nov 8 11:14:46 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * run.c: include <stdarg.h> and <stdio.h>.
+ Change all VA_START to va_start.
+ Don't ask HAVE_VPRINTF -- this is an OS/2-specific file and we can
+ take things for granted.
+ Started simplifying old NT `HANDLE' code.
+
+ * Makefile.in (OS2_SOURCES): added run.c.
+
+ * run.c: new file, copied from ../windows-NT/run.c. Started
+ making changes for OS/2.
+
+ * test-makefile (all): don't bother to echo $CFLAGS; we can just
+ read the compilation command.
+
+ * filesubr.c (unlink_file): make this work on OS/2.
+ (unlink_file_dir): don't ask if errno == EISDIR. We ain't
+ got EISDIR in OS/2.
+ (deep_remove_dir): use EACCESS to determine if directory
+ nonempty. We ain't got ENOTEMPTY in OS/2.
+ (that_swing): removed references. We ain't got that_swing in
+ OS/2.
+ (rename_file): just use unlink_file(); move to after definition of
+ unlink_file() so we don't have to deal with IBM C/C++'s strange
+ prototyping rituals.
+ (link_file): removed this function -- no one uses it anymore.
+ It still exists in src/filesubr.c, though.
+ (OS2_filename_classes): new table (well, old table, new name).
+ All references changed.
+
+ * config.h (HAVE_SYS_UTIME_H): define to 1.
+
+ * options.h: undef SETXID_SUPPORT, to correspond with Norbert
+ Kiesel's recent change to ../src/options.h.in, etc.
+
+Mon Nov 6 16:29:00 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * test-makefile (CFLAGS): -DHAVE_CONFIG_H -- this turns out to be
+ important for stuff in lib/.
+ Other trivial changes.
+
+ * config.h (HAVE_DIRENT_H): define to 1, now that we have our own
+ dirent.h and dirent.c.
+
+ * Makefile.in (OS2_SOURCES): added filesubr.c; this may not be
+ permanent.
+
+Sun Nov 5 16:17:33 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (OS2_HEADERS, OS2_SOURCES): added dirent.h and
+ dirent.c, respectively.
+
+ * dirent.c, dirent.h: new files.
+
+Sat Oct 28 14:41:38 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (DISTFILES): include `test-makefile'.
+
+ * test-makefile: new file; to be removed when the port is done.
+
+Fri Oct 27 13:03:28 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (OS2_HEADERS, OS2_SOURCES): adjust as necessary for
+ below changes.
+
+ * config.h: oops, don't forget second argument, MODE.
+
+ * mkdir.c (os2_mkdir): new file, new function.
+ Can probably be merged with wnt_mkdir at some point.
+
+ * config.h (ALLOCA_IN_STDLIB): new #define.
+
+ * pwd.h, pwd.c: new files (for now, copied from ../windows-NT
+ directory. We'll modify/merge them as necessary.)
+
+ * config.h: don't use __stdcall in declaration of gethostname().
+
+ * Makefile.in (DISTFILES): include config.h and options.h.
+
+Wed Oct 25 12:52:54 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * config.h: new file; will maintain by hand.
+ Made first pass through to cast it into OS/2-ish condition.
+
+ * Makefile.in: started adding lots of OS/2 gunk.
+ Took out autoconf stuff; just don't want to fool around with that
+ until after it compiles on beezley.
+ (cvs.exe): moved this rule to bottom.
+
+Tue Oct 24 13:51:05 1995 Norbert Kiesel <nk@col.sw-ley.de>
+
+ * Makefile.in: add autoconf variables
+
+ * Makefile.in (dist): use $(srcdir)
+
+Mon Oct 23 17:37:36 1995 Karl Fogel <kfogel@floss.cyclic.com>
+
+ * Makefile.in (clean): new rule.
+
+ * init os2 directory. Made dummy Makefile.in, README.
diff --git a/gnu/usr.bin/cvs/os2/Makefile.in b/gnu/usr.bin/cvs/os2/Makefile.in
new file mode 100644
index 00000000000..dfa66b4fd80
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/Makefile.in
@@ -0,0 +1,303 @@
+# Makefile for OS/2. Generated from Makefile.in when CVS is
+# configured for a dist-build. Configure never gets run on OS/2, so
+# we must include the generated Makefile in the distribution. See the
+# `dist-dir' rule.
+
+project: cvs.exe
+# .SUFFIXES .c .obj .exe
+
+# path slash
+# Maintainers: always leave this set to "/", because `make dist' has
+# to work on Unix systems. See os2/README to find out why we have
+# this var.
+SL = /
+
+# Directory in which to install executables.
+install_dir = s:${SL}gnu${SL}util
+
+# srcdir is usually "."
+srcdir = @srcdir@
+
+# top_srcdir is usually ".."
+top_srcdir = @top_srcdir@
+
+lib_dir = @top_srcdir@${SL}lib
+cvs_srcdir = @top_srcdir@${SL}src
+
+# Do we need these?
+# prefix = /usr/local
+# exec_prefix = ${prefix}
+
+# taken straight from the example project
+LIB = s:${SL}ibmcpp${SL}lib;s:${SL}toolkt21${SL}os2lib;
+CINC = -Is:${SL}ibmcpp${SL}include -Is:${SL}toolkt21${SL}c${SL}os2h
+# This says we are building an object file, not a full executable.
+OBJ_CFLAGS = -C+
+CFLAGS = -W3 -Wpro+rea+tru+use+ -Ti+ -Ss+ -Gd+ -Gm+ -G4 -Q+ -Sm ${CINC} \
+ -I${srcdir} -I${lib_dir} -I${cvs_srcdir} \
+ -DIBM_CPP -DHAVE_CONFIG_H \
+ -DTCPIP_IBM -Is:${SL}ibmtcpip${SL}include
+
+# needed to make command-line wildcard expansion work right. That's
+# right, DOS-descendants handle this from the program, not the shell.
+ARGVLIB = s:${SL}ibmcpp${SL}lib${SL}setargv.obj
+
+# TCP/IP stuff
+TCPIPLIB = s:${SL}ibmtcpip${SL}lib${SL}tcp32dll.lib s:${SL}ibmtcpip${SL}lib${SL}so32dll.lib
+
+
+# headers specific to OS/2
+
+# We list OS2_HEADERS so we know what to include when we make dist-dir
+# here.
+OS2_HEADERS = \
+ ${srcdir}${SL}tcpip.h \
+ ${srcdir}${SL}config.h \
+ ${srcdir}${SL}options.h \
+ ${srcdir}${SL}pwd.h \
+ ${srcdir}${SL}dirent.h \
+ ${srcdir}${SL}rcmd.h \
+ ${srcdir}${SL}popen.h
+
+# headers we use from the common src dir, ..${SL}src
+COMMON_HEADERS = \
+ ${cvs_srcdir}${SL}client.h \
+ ${cvs_srcdir}${SL}cvs.h \
+ ${cvs_srcdir}${SL}rcs.h \
+ ${cvs_srcdir}${SL}hash.h \
+ ${cvs_srcdir}${SL}myndbm.h \
+ ${cvs_srcdir}${SL}patchlevel.h \
+ ${cvs_srcdir}${SL}update.h \
+ ${cvs_srcdir}${SL}server.h \
+ ${cvs_srcdir}${SL}error.h
+
+# sources specific to OS/2
+OS2_SOURCES = \
+ ${srcdir}${SL}mkdir.c \
+ ${srcdir}${SL}pwd.c \
+ ${srcdir}${SL}filesubr.c \
+ ${srcdir}${SL}dirent.c \
+ ${srcdir}${SL}run.c \
+ ${srcdir}${SL}stripslash.c \
+ ${srcdir}${SL}rcmd.c \
+ ${srcdir}${SL}waitpid.c \
+ ${srcdir}${SL}popen.c \
+ ${srcdir}${SL}porttcp.c \
+ ${srcdir}${SL}strippath.c \
+ ${srcdir}${SL}getdate.c \
+ ${srcdir}${SL}getpass.c
+
+# sources we use from the common src dir, ..${SL}src
+COMMON_SOURCES = \
+ ${cvs_srcdir}${SL}add.c \
+ ${cvs_srcdir}${SL}admin.c \
+ ${cvs_srcdir}${SL}checkin.c \
+ ${cvs_srcdir}${SL}checkout.c \
+ ${cvs_srcdir}${SL}classify.c \
+ ${cvs_srcdir}${SL}client.c \
+ ${cvs_srcdir}${SL}commit.c \
+ ${cvs_srcdir}${SL}create_adm.c \
+ ${cvs_srcdir}${SL}cvsrc.c \
+ ${cvs_srcdir}${SL}diff.c \
+ ${cvs_srcdir}${SL}edit.c \
+ ${cvs_srcdir}${SL}entries.c \
+ ${cvs_srcdir}${SL}error.c \
+ ${cvs_srcdir}${SL}expand_path.c \
+ ${cvs_srcdir}${SL}fileattr.c \
+ ${cvs_srcdir}${SL}find_names.c \
+ ${cvs_srcdir}${SL}hash.c \
+ ${cvs_srcdir}${SL}history.c \
+ ${cvs_srcdir}${SL}ignore.c \
+ ${cvs_srcdir}${SL}import.c \
+ ${cvs_srcdir}${SL}lock.c \
+ ${cvs_srcdir}${SL}log.c \
+ ${cvs_srcdir}${SL}login.c \
+ ${cvs_srcdir}${SL}logmsg.c \
+ ${cvs_srcdir}${SL}main.c \
+ ${cvs_srcdir}${SL}modules.c \
+ ${cvs_srcdir}${SL}myndbm.c \
+ ${cvs_srcdir}${SL}no_diff.c \
+ ${cvs_srcdir}${SL}parseinfo.c \
+ ${cvs_srcdir}${SL}patch.c \
+ ${cvs_srcdir}${SL}rcs.c \
+ ${cvs_srcdir}${SL}rcscmds.c \
+ ${cvs_srcdir}${SL}recurse.c \
+ ${cvs_srcdir}${SL}release.c \
+ ${cvs_srcdir}${SL}remove.c \
+ ${cvs_srcdir}${SL}repos.c \
+ ${cvs_srcdir}${SL}root.c \
+ ${cvs_srcdir}${SL}rtag.c \
+ ${cvs_srcdir}${SL}scramble.c \
+ ${cvs_srcdir}${SL}server.c \
+ ${cvs_srcdir}${SL}status.c \
+ ${cvs_srcdir}${SL}subr.c \
+ ${cvs_srcdir}${SL}tag.c \
+ ${cvs_srcdir}${SL}update.c \
+ ${cvs_srcdir}${SL}watch.c \
+ ${cvs_srcdir}${SL}wrapper.c \
+ ${cvs_srcdir}${SL}vers_ts.c \
+ ${cvs_srcdir}${SL}version.c
+# end of $COMMON_SOURCES
+
+# sources from ..${SL}lib
+LIB_SOURCES = \
+ ${lib_dir}${SL}getopt.c \
+ ${lib_dir}${SL}getopt1.c \
+ ${lib_dir}${SL}getline.c \
+ ${lib_dir}${SL}getwd.c \
+ ${lib_dir}${SL}save-cwd.c \
+ ${lib_dir}${SL}sighandle.c \
+ ${lib_dir}${SL}yesno.c \
+ ${lib_dir}${SL}xgetwd.c \
+ ${lib_dir}${SL}md5.c \
+ ${lib_dir}${SL}fnmatch.c \
+ ${lib_dir}${SL}regex.c
+
+# object files from OS/2 sources
+OS2_OBJECTS = \
+ ${srcdir}${SL}mkdir.obj \
+ ${srcdir}${SL}pwd.obj \
+ ${srcdir}${SL}filesubr.obj \
+ ${srcdir}${SL}dirent.obj \
+ ${srcdir}${SL}run.obj \
+ ${srcdir}${SL}stripslash.obj \
+ ${srcdir}${SL}rcmd.obj \
+ ${srcdir}${SL}waitpid.obj \
+ ${srcdir}${SL}popen.obj \
+ ${srcdir}${SL}porttcp.obj \
+ ${srcdir}${SL}strippath.obj \
+ ${srcdir}${SL}getdate.obj \
+ ${srcdir}${SL}getpass.obj
+
+# object files from ..${SL}src
+COMMON_OBJECTS = \
+ ${cvs_srcdir}${SL}add.obj \
+ ${cvs_srcdir}${SL}admin.obj \
+ ${cvs_srcdir}${SL}checkin.obj \
+ ${cvs_srcdir}${SL}checkout.obj \
+ ${cvs_srcdir}${SL}classify.obj \
+ ${cvs_srcdir}${SL}client.obj \
+ ${cvs_srcdir}${SL}commit.obj \
+ ${cvs_srcdir}${SL}create_adm.obj \
+ ${cvs_srcdir}${SL}cvsrc.obj \
+ ${cvs_srcdir}${SL}diff.obj \
+ ${cvs_srcdir}${SL}edit.obj \
+ ${cvs_srcdir}${SL}entries.obj \
+ ${cvs_srcdir}${SL}error.obj \
+ ${cvs_srcdir}${SL}expand_path.obj \
+ ${cvs_srcdir}${SL}fileattr.obj \
+ ${cvs_srcdir}${SL}find_names.obj \
+ ${cvs_srcdir}${SL}hash.obj \
+ ${cvs_srcdir}${SL}history.obj \
+ ${cvs_srcdir}${SL}ignore.obj \
+ ${cvs_srcdir}${SL}import.obj \
+ ${cvs_srcdir}${SL}lock.obj \
+ ${cvs_srcdir}${SL}log.obj \
+ ${cvs_srcdir}${SL}login.obj \
+ ${cvs_srcdir}${SL}logmsg.obj \
+ ${cvs_srcdir}${SL}main.obj \
+ ${cvs_srcdir}${SL}modules.obj \
+ ${cvs_srcdir}${SL}myndbm.obj \
+ ${cvs_srcdir}${SL}no_diff.obj \
+ ${cvs_srcdir}${SL}parseinfo.obj \
+ ${cvs_srcdir}${SL}patch.obj \
+ ${cvs_srcdir}${SL}rcs.obj \
+ ${cvs_srcdir}${SL}rcscmds.obj \
+ ${cvs_srcdir}${SL}recurse.obj \
+ ${cvs_srcdir}${SL}release.obj \
+ ${cvs_srcdir}${SL}remove.obj \
+ ${cvs_srcdir}${SL}repos.obj \
+ ${cvs_srcdir}${SL}root.obj \
+ ${cvs_srcdir}${SL}rtag.obj \
+ ${cvs_srcdir}${SL}scramble.obj \
+ ${cvs_srcdir}${SL}server.obj \
+ ${cvs_srcdir}${SL}status.obj \
+ ${cvs_srcdir}${SL}subr.obj \
+ ${cvs_srcdir}${SL}tag.obj \
+ ${cvs_srcdir}${SL}update.obj \
+ ${cvs_srcdir}${SL}watch.obj \
+ ${cvs_srcdir}${SL}wrapper.obj \
+ ${cvs_srcdir}${SL}vers_ts.obj \
+ ${cvs_srcdir}${SL}version.obj
+# end of $COMMON_OBJECTS
+
+# objects from ..${SL}lib
+LIB_OBJECTS = \
+ ${lib_dir}${SL}getopt.obj \
+ ${lib_dir}${SL}getopt1.obj \
+ ${lib_dir}${SL}getline.obj \
+ ${lib_dir}${SL}getwd.obj \
+ ${lib_dir}${SL}save-cwd.obj \
+ ${lib_dir}${SL}sighandle.obj \
+ ${lib_dir}${SL}yesno.obj \
+ ${lib_dir}${SL}xgetwd.obj \
+ ${lib_dir}${SL}md5.obj \
+ ${lib_dir}${SL}fnmatch.obj \
+ ${lib_dir}${SL}regex.obj
+
+SOURCES = ${COMMON_SOURCES} ${LIB_SOURCES} ${OS2_SOURCES}
+HEADERS = ${COMMON_HEADERS} ${OS2_HEADERS}
+OBJECTS = ${COMMON_OBJECTS} ${LIB_OBJECTS} ${OS2_OBJECTS}
+
+DISTFILES = ${OS2_HEADERS} ${OS2_SOURCES} \
+ ${srcdir}${SL}README ${srcdir}${SL}ChangeLog \
+ ${srcdir}${SL}Makefile.in ${srcdir}${SL}.cvsignore \
+ ${srcdir}${SL}test-makefile Makefile
+
+all:
+
+.PHONY: all install uninstall
+all install uninstall:
+
+.PHONY: tags TAGS
+tags TAGS:
+
+.PHONY: ls
+ls:
+ @echo ${DISTFILES}
+
+.PHONY: clean distclean realclean mostlyclean
+clean distclean realclean mostlyclean:
+
+.PHONY: lint
+lint:
+
+.PHONY: dist-dir
+dist-dir:
+ mkdir ${DISTDIR}
+ for i in ${DISTFILES}; do \
+ ln $${i} ${DISTDIR}; \
+ done
+
+# We don't have a real distclean or anything like that, but at least
+# we can get rid of the obj files and cvs.exe.
+clean:
+ rm -f cvs.exe
+ rm -f ${srcdir}${SL}*.obj
+ rm -f ${lib_dir}${SL}*.obj
+ rm -f ${cvs_srcdir}${SL}*.obj
+
+install-cvs: cvs.exe
+ cp ${srcdir}${SL}cvs.exe ${install_dir}${SL}cvs.exe
+
+%.obj: %.c
+ icc ${OBJ_CFLAGS} ${CFLAGS} /Fo$@ $*.c
+
+# There seems to be no ICC option for specifying library locations, so
+# we must `set' the path in the compilation environment. Urgkle.
+cvs.exe: ${OBJECTS}
+ echo Creating icc.in...
+ echo -Q+ -Ti+ -Fe$@ -B"/batch" -B"/NOE" > icc.in
+ echo ${OS2_OBJECTS} >> icc.in
+ echo ${LIB_OBJECTS} >> icc.in
+ echo ${COMMON_OBJECTS} >> icc.in
+ echo ${TCPIPLIB} >> icc.in
+ echo ${ARGVLIB} >> icc.in
+ echo Creating icc.in... done.
+ set LIB=${LIB} & icc @icc.in
+
+# cvs.obj: ${OBJECTS} ${SOURCES} ${HEADERS}
+
+subdir = os2
+Makefile: ../config.status $(srcdir)/Makefile.in
+ cd .. && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status
diff --git a/gnu/usr.bin/cvs/os2/README b/gnu/usr.bin/cvs/os2/README
new file mode 100644
index 00000000000..50ed61625fd
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/README
@@ -0,0 +1,31 @@
+ This port requires IBM C/C++ and the IBM TCPIP library.
+You'll need to edit the makefile to reflect your system's paths
+(unless you're our customer for this port, in which case the paths
+are correct because we did the port on your machine. :-) ).
+
+ I'm having some weird problem with "\" vs. "/". If I build
+with "\" as the path separator in the makefile, the compiler dumps
+core. Go figure. If I build with "/" as the path separator, the
+object files compile fine but the linker thinks the "/" is indicating
+options and gets all confused (though at least it doesn't dump core).
+
+ Right now the solution is to have a makefile variable called
+SL, which must be set to "/" for the first invocation of make and "\"
+for the second (the first pass will successfully build the object
+files, but you can expect it do die with "unknown options" errors at
+link time).
+
+ $SL is defined near the top of the makefile. If you're going
+to set $SL in the makefile itself, make sure to quote it ("\\"). On
+the command line (i.e., "make SL=\"), I believe just one will do.
+
+ That should be all -- edit the makefile, do "make" twice
+(changing $SL the second time), and get os2\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 will get warnings during the compilation; ignore them.
+Report bugs to <bug-cvs@prep.ai.mit.edu>.
+
+-Karl
+ <kfogel@cyclic.com>
diff --git a/gnu/usr.bin/cvs/os2/dirent.c b/gnu/usr.bin/cvs/os2/dirent.c
new file mode 100644
index 00000000000..01bd92f56e7
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/dirent.c
@@ -0,0 +1,180 @@
+/*
+ * Author: Bob Withers
+ * Copyright (c) 1993, All Rights Reserved
+ *
+ * NOTICE
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * The author makes no representations about the suitability of this
+ * software for any purpose. This software is provided ``as is''
+ * without express or implied warranty.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#define INCL_DOSFILEMGR
+#define INCL_DOSERRORS
+#include <os2.h>
+
+#include "dirent.h"
+
+
+#define DIRENT_INCR 25
+
+
+DIR *opendir(char *filename)
+{
+ auto size_t len;
+ auto DIR *dirp;
+ auto char *p;
+ auto HDIR hdir;
+
+#ifdef OS2_16
+ auto USHORT rc; /* for 16 bit OS/2 */
+ auto FILEFINDBUF ff;
+ auto USHORT cnt;
+#else
+ auto APIRET rc; /* for 32 bit OS/2 */
+ auto FILEFINDBUF3 ff;
+ auto ULONG cnt;
+#endif /* OS2_16 */
+
+ if (NULL == filename || '\0' == filename[0])
+ filename = ".";
+
+ dirp = malloc(sizeof(*dirp));
+ if (NULL == dirp)
+ return(NULL);
+
+ len = strlen(filename);
+ dirp->dirname = malloc(len + 5);
+ if (NULL == dirp->dirname)
+ {
+ free(dirp);
+ return(NULL);
+ }
+
+ dirp->max_ent = 0;
+ dirp->tot_ent = 0;
+ dirp->cur_ent = 0;
+ dirp->entp = NULL;
+ strcpy(dirp->dirname, filename);
+ for (p = dirp->dirname; *p; ++p)
+ {
+ if ('/' == *p)
+ *p = '\\';
+ }
+
+ if ('\\' != dirp->dirname[len - 1])
+ strcat(dirp->dirname, "\\");
+
+ strcat(dirp->dirname, "*.*");
+
+ hdir = HDIR_SYSTEM;
+ cnt = 1;
+ rc = DosFindFirst(dirp->dirname, &hdir,
+ FILE_NORMAL | FILE_READONLY | FILE_HIDDEN |
+ FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,
+ &ff, sizeof(ff), &cnt, FIL_STANDARD);
+
+ while (NO_ERROR == rc)
+ {
+ auto struct dirent *entp;
+
+ if (dirp->tot_ent >= dirp->max_ent)
+ {
+ auto struct dirent **p;
+
+ dirp->max_ent += DIRENT_INCR;
+ p = realloc(dirp->entp, dirp->max_ent * sizeof(entp));
+ if (NULL == p)
+ {
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ dirp->entp = p;
+ }
+
+ entp = malloc(sizeof(*entp) + (size_t) ff.cchName);
+ if (NULL == entp)
+ {
+ rc = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+
+ entp->d_ino = 0;
+ entp->d_off = dirp->tot_ent;
+ entp->d_namlen = (unsigned short) ff.cchName;
+ memcpy(entp->d_name, ff.achName, entp->d_namlen);
+ entp->d_name[entp->d_namlen] = '\0';
+ dirp->entp[dirp->tot_ent++] = entp;
+
+ cnt = 1;
+ rc = DosFindNext(hdir, &ff, sizeof(ff), &cnt);
+ }
+
+ DosFindClose(hdir);
+ if (ERROR_NO_MORE_FILES == rc)
+ return(dirp);
+
+ closedir(dirp);
+ return(NULL);
+}
+
+
+struct dirent *readdir(DIR *dirp)
+{
+ if (dirp->cur_ent < 0 || dirp->cur_ent >= dirp->tot_ent)
+ return(NULL);
+
+ return(dirp->entp[dirp->cur_ent++]);
+}
+
+
+long telldir(DIR *dirp)
+{
+ return((long) dirp->cur_ent);
+}
+
+
+void seekdir(DIR *dirp, long loc)
+{
+ dirp->cur_ent = (int) loc;
+ return;
+}
+
+
+void rewinddir(DIR *dirp)
+{
+ dirp->cur_ent = 0;
+ return;
+}
+
+
+void closedir(DIR *dirp)
+{
+ if (dirp)
+ {
+ if (dirp->dirname)
+ free(dirp->dirname);
+
+ if (dirp->entp)
+ {
+ register int i;
+
+ for (i = 0; i < dirp->tot_ent; ++i)
+ free(dirp->entp[i]);
+
+ free(dirp->entp);
+ }
+ }
+
+ return;
+}
diff --git a/gnu/usr.bin/cvs/os2/dirent.h b/gnu/usr.bin/cvs/os2/dirent.h
new file mode 100644
index 00000000000..bc218b5fdc6
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/dirent.h
@@ -0,0 +1,50 @@
+/*
+ * Author: Bob Withers
+ * Copyright (c) 1993, All Rights Reserved
+ *
+ * NOTICE
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby granted
+ * provided that the above copyright notice appears in all copies and
+ * that both the copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * The author makes no representations about the suitability of this
+ * software for any purpose. This software is provided ``as is''
+ * without express or implied warranty.
+ */
+
+#ifndef DIRENT_H
+#define DIRENT_H
+
+/* Unix style directory(3C) support for OS/2 V2.x */
+
+struct dirent
+{
+ long d_ino; /* not used in this implementation */
+ long d_off; /* not used in this implementation */
+ unsigned short d_namlen;
+ char d_name[1];
+};
+
+
+struct S_Dir
+{
+ char *dirname;
+ int max_ent;
+ int tot_ent;
+ int cur_ent;
+ struct dirent **entp;
+};
+typedef struct S_Dir DIR;
+
+
+DIR * opendir(char *filename);
+struct dirent * readdir(DIR *dirp);
+long telldir(DIR *dirp);
+void seekdir(DIR *dirp, long loc);
+void rewinddir(DIR *dirp);
+void closedir(DIR *dirp);
+
+#endif /* DIRENT_H */
diff --git a/gnu/usr.bin/cvs/os2/filesubr.c b/gnu/usr.bin/cvs/os2/filesubr.c
new file mode 100644
index 00000000000..849915afa3a
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/filesubr.c
@@ -0,0 +1,737 @@
+/* filesubr.c --- subroutines for dealing with files under OS/2
+ Jim Blandy <jimb@cyclic.com> and Karl Fogel <kfogel@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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* 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 <io.h>
+
+#include "cvs.h"
+
+#ifndef lint
+static const char rcsid[] = "$CVSid:$";
+USE(rcsid);
+#endif
+
+/*
+ * I don't know of a convenient way to test this at configure time, or else
+ * I'd certainly do it there. -JimB
+ */
+#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);
+}
+
+/*
+ * 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;
+{
+ copy_file (from, to);
+ return 0;
+}
+
+/* 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;
+{
+ struct stat sb;
+
+ if (stat (file, &sb) < 0)
+ return (0);
+ return (1);
+}
+
+/*
+ * Returns non-zero if the argument file is readable.
+ * XXX - must be careful if "cvs" is ever made setuid!
+ */
+int
+isreadable (file)
+ const char *file;
+{
+ return (access (file, R_OK) != -1);
+}
+
+/*
+ * Returns non-zero if the argument file is writable
+ * XXX - muct be careful if "cvs" is ever made setuid!
+ */
+int
+iswritable (file)
+ const char *file;
+{
+ return (access (file, W_OK) != -1);
+}
+
+/*
+ * 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;
+{
+ return access(file, mode) == 0;
+}
+
+
+/*
+ * 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 buf;
+
+ if (stat (name, &buf) == 0 && (!S_ISDIR (buf.st_mode)))
+ error (0, 0, "%s already exists but is not a directory", name);
+ if (!noexec && mkdir (name) < 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) == 0 || errno == EACCESS)
+ 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);
+}
+
+/*
+ * Change the mode of a file, either adding write permissions, or removing
+ * all write permissions. Adding write permissions honors the current umask
+ * setting.
+ */
+void
+xchmod (fname, writable)
+ char *fname;
+ int writable;
+{
+ char *attrib_cmd;
+ char *attrib_option;
+ char *whole_cmd;
+ char *p;
+ char *q;
+
+ if (!isfile (fname))
+ return ENOENT;
+
+ 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);
+}
+
+
+/* Read the value of a symbolic link.
+ Under OS/2, this function always returns EINVAL. */
+int
+readlink (char *path, char *buf, int buf_size)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+/*
+ * 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);
+
+ /* Win32 unlink is stupid - it fails if the file is read-only.
+ * OS/2 is similarly stupid. It does have a remove() function,
+ * but the documentation does not make clear why remove() is or
+ * isn't preferable to unlink(). I'll use unlink() because the
+ * name is closer to our interface, what the heck. Also, we know
+ * unlink()'s error code when trying to remove a directory.
+ */
+ xchmod (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);
+
+ if (unlink_file (f) != 0)
+ {
+ /* under OS/2, unlink returns EACCESS if the path
+ is a directory. */
+ if (errno == EACCESS)
+ return deep_remove_dir (f);
+ else
+ /* The file wasn't a directory and some other
+ * error occured
+ */
+ 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 && errno == EACCESS )
+ {
+ 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);
+
+ if (unlink_file (buf) != 0 )
+ {
+ if (errno == EACCES)
+ {
+ if (deep_remove_dir (buf))
+ {
+ closedir (dirp);
+ return -1;
+ }
+ }
+ else
+ {
+ /* buf isn't a directory, or there are
+ * some sort of permision problems
+ */
+ closedir (dirp);
+ return -1;
+ }
+ }
+ }
+ closedir (dirp);
+ return rmdir (path);
+ }
+ /* Was able to remove the directory return 0 */
+ return 0;
+}
+
+
+/*
+ * 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);
+}
+
+
+/* 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);
+}
+
+
+/* The equivalence class mapping for filenames.
+ OS/2 filenames are case-insensitive, but case-preserving. Both /
+ and \ are path element separators.
+ Thus, this table maps both upper and lower case to lower case, and
+ both / and \ to /.
+
+ Much thanks to Jim Blandy, who already invented this wheel in the
+ Windows NT port. */
+
+#if 0
+main ()
+{
+ int c;
+
+ for (c = 0; c < 256; c++)
+ {
+ int t;
+
+ if (c == '\\')
+ t = '/';
+ else
+ t = tolower (c);
+
+ if ((c & 0x7) == 0x0)
+ printf (" ");
+ printf ("0x%02x,", t);
+ if ((c & 0x7) == 0x7)
+ putchar ('\n');
+ else if ((c & 0x7) == 0x3)
+ putchar (' ');
+ }
+}
+#endif
+
+
+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)
+{
+ while (*n1 && *n2
+ && (OS2_filename_classes[(unsigned char) *n1]
+ == OS2_filename_classes[(unsigned char) *n2]))
+ n1++, n2++;
+ return (OS2_filename_classes[(unsigned char) *n1]
+ - OS2_filename_classes[(unsigned char) *n1]);
+}
+
+/* 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++;
+ }
+}
+
+
+/* Return non-zero iff FILENAME is absolute.
+ Trivial under Unix, but more complicated under other systems. */
+int
+isabsolute (filename)
+ const char *filename;
+{
+ return (ISDIRSEP (filename[0])
+ || (filename[0] != '\0'
+ && filename[1] == ':'
+ && ISDIRSEP (filename[2])));
+}
+
+/* Return a pointer into PATH's last component. */
+char *
+last_component (char *path)
+{
+ char *scan;
+ char *last = 0;
+
+ for (scan = path; *scan; scan++)
+ if (ISDIRSEP (*scan))
+ last = scan;
+
+ if (last)
+ return last + 1;
+ else
+ return path;
+}
+
+
+/* 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. */
+void
+convert_file (char *infile, int inflags,
+ char *outfile, int outflags)
+{
+ int infd, outfd;
+ char buf[8192];
+ int len;
+
+ if ((infd = open (infile, inflags, S_IREAD | S_IWRITE)) < 0)
+ error (1, errno, "couldn't read %s", infile);
+ if ((outfd = open (outfile, outflags, S_IREAD | S_IWRITE)) < 0)
+ error (1, errno, "couldn't write %s", outfile);
+
+ while ((len = read (infd, buf, sizeof (buf))) > 0)
+ if (write (outfd, buf, len) < 0)
+ error (1, errno, "error writing %s", outfile);
+ if (len < 0)
+ error (1, errno, "error reading %s", infile);
+
+ if (close (outfd) < 0)
+ error (0, errno, "warning: couldn't close %s", outfile);
+ if (close (infd) < 0)
+ error (0, errno, "warning: couldn't close %s", infile);
+}
diff --git a/gnu/usr.bin/cvs/os2/getdate.c b/gnu/usr.bin/cvs/os2/getdate.c
new file mode 100644
index 00000000000..dcfcdf39e9c
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/getdate.c
@@ -0,0 +1,1578 @@
+/* stolen from lib/getdate.c */
+
+#include "config.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/* The code at the top of get_date which figures out the offset of the
+ current time zone checks various CPP symbols to see if special
+ tricks are need, but defaults to using the gettimeofday system call.
+ Include <sys/time.h> if that will be used. */
+
+#if defined(vms)
+
+#include <types.h>
+#include <time.h>
+
+#else
+
+#include <sys/types.h>
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef timezone
+#undef timezone /* needed for sgi */
+#endif
+
+#if defined(HAVE_SYS_TIMEB_H)
+#include <sys/timeb.h>
+#else
+/*
+** We use the obsolete `struct timeb' as part of our interface!
+** Since the system doesn't have it, we define it here;
+** our callers must do likewise.
+*/
+struct timeb {
+ time_t time; /* Seconds since the epoch */
+ unsigned short millitm; /* Field not used */
+ short timezone; /* Minutes west of GMT */
+ short dstflag; /* Field not used */
+};
+#endif /* defined(HAVE_SYS_TIMEB_H) */
+
+#endif /* defined(vms) */
+
+#if defined (STDC_HEADERS) || defined (USG)
+#include <string.h>
+#endif
+
+/* Some old versions of bison generate parsers that use bcopy.
+ That loses on systems that don't provide the function, so we have
+ to redefine it here. */
+#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
+#define bcopy(from, to, len) memcpy ((to), (from), (len))
+#endif
+
+#if defined (STDC_HEADERS)
+#include <stdlib.h>
+#endif
+
+#if defined (HAVE_ALLOCA_H)
+#include <alloca.h>
+#endif
+
+extern struct tm *gmtime();
+extern struct tm *localtime();
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+#if !defined(lint) && !defined(SABER)
+static char RCS[] = "$CVSid: @(#)getdate.y 1.11 94/09/21 $";
+#endif /* !defined(lint) && !defined(SABER) */
+
+static int yylex ();
+static int yyerror ();
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+
+/*
+** An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+ char *name;
+ int type;
+ time_t value;
+} TABLE;
+
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static MERIDIAN yyMeridian;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+
+typedef union {
+ time_t Number;
+ enum _MERIDIAN Meridian;
+} YYSTYPE;
+# define tAGO 257
+# define tDAY 258
+# define tDAYZONE 259
+# define tID 260
+# define tMERIDIAN 261
+# define tMINUTE_UNIT 262
+# define tMONTH 263
+# define tMONTH_UNIT 264
+# define tSEC_UNIT 265
+# define tSNUMBER 266
+# define tUNUMBER 267
+# define tZONE 268
+# define tDST 269
+#define yyclearin yychar = -1
+#define yyerrok yyerrflag = 0
+extern int yychar;
+extern int yyerrflag;
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 150
+#endif
+YYSTYPE yylval, yyval;
+# define YYERRCODE 256
+
+
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+ { "january", tMONTH, 1 },
+ { "february", tMONTH, 2 },
+ { "march", tMONTH, 3 },
+ { "april", tMONTH, 4 },
+ { "may", tMONTH, 5 },
+ { "june", tMONTH, 6 },
+ { "july", tMONTH, 7 },
+ { "august", tMONTH, 8 },
+ { "september", tMONTH, 9 },
+ { "sept", tMONTH, 9 },
+ { "october", tMONTH, 10 },
+ { "november", tMONTH, 11 },
+ { "december", tMONTH, 12 },
+ { "sunday", tDAY, 0 },
+ { "monday", tDAY, 1 },
+ { "tuesday", tDAY, 2 },
+ { "tues", tDAY, 2 },
+ { "wednesday", tDAY, 3 },
+ { "wednes", tDAY, 3 },
+ { "thursday", tDAY, 4 },
+ { "thur", tDAY, 4 },
+ { "thurs", tDAY, 4 },
+ { "friday", tDAY, 5 },
+ { "saturday", tDAY, 6 },
+ { NULL }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+ { "year", tMONTH_UNIT, 12 },
+ { "month", tMONTH_UNIT, 1 },
+ { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
+ { "week", tMINUTE_UNIT, 7 * 24 * 60 },
+ { "day", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "hour", tMINUTE_UNIT, 60 },
+ { "minute", tMINUTE_UNIT, 1 },
+ { "min", tMINUTE_UNIT, 1 },
+ { "second", tSEC_UNIT, 1 },
+ { "sec", tSEC_UNIT, 1 },
+ { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+ { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
+ { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
+ { "today", tMINUTE_UNIT, 0 },
+ { "now", tMINUTE_UNIT, 0 },
+ { "last", tUNUMBER, -1 },
+ { "this", tMINUTE_UNIT, 0 },
+ { "next", tUNUMBER, 2 },
+ { "first", tUNUMBER, 1 },
+/* { "second", tUNUMBER, 2 }, */
+ { "third", tUNUMBER, 3 },
+ { "fourth", tUNUMBER, 4 },
+ { "fifth", tUNUMBER, 5 },
+ { "sixth", tUNUMBER, 6 },
+ { "seventh", tUNUMBER, 7 },
+ { "eighth", tUNUMBER, 8 },
+ { "ninth", tUNUMBER, 9 },
+ { "tenth", tUNUMBER, 10 },
+ { "eleventh", tUNUMBER, 11 },
+ { "twelfth", tUNUMBER, 12 },
+ { "ago", tAGO, 1 },
+ { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+#if 0
+ { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
+ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR(1) }, /* Central European */
+ { "met", tZONE, -HOUR(1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+#if 0
+ { "it", tZONE, -HOUR(3.5) },/* Iran */
+#endif
+ { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+#if 0
+ { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
+#endif
+ { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Stanard, and SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
+ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+#if 0
+ { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+ { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
+#if 0
+ { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { NULL }
+};
+
+/* Military timezone table. */
+static TABLE const MilitaryTable[] = {
+ { "a", tZONE, HOUR( 1) },
+ { "b", tZONE, HOUR( 2) },
+ { "c", tZONE, HOUR( 3) },
+ { "d", tZONE, HOUR( 4) },
+ { "e", tZONE, HOUR( 5) },
+ { "f", tZONE, HOUR( 6) },
+ { "g", tZONE, HOUR( 7) },
+ { "h", tZONE, HOUR( 8) },
+ { "i", tZONE, HOUR( 9) },
+ { "k", tZONE, HOUR( 10) },
+ { "l", tZONE, HOUR( 11) },
+ { "m", tZONE, HOUR( 12) },
+ { "n", tZONE, HOUR(- 1) },
+ { "o", tZONE, HOUR(- 2) },
+ { "p", tZONE, HOUR(- 3) },
+ { "q", tZONE, HOUR(- 4) },
+ { "r", tZONE, HOUR(- 5) },
+ { "s", tZONE, HOUR(- 6) },
+ { "t", tZONE, HOUR(- 7) },
+ { "u", tZONE, HOUR(- 8) },
+ { "v", tZONE, HOUR(- 9) },
+ { "w", tZONE, HOUR(-10) },
+ { "x", tZONE, HOUR(-11) },
+ { "y", tZONE, HOUR(-12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL }
+};
+
+
+
+
+/* ARGSUSED */
+static int
+yyerror(s)
+ char *s;
+{
+ return 0;
+}
+
+
+static time_t
+ToSeconds(Hours, Minutes, Seconds, Meridian)
+ time_t Hours;
+ time_t Minutes;
+ time_t Seconds;
+ MERIDIAN Meridian;
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+ default:
+ abort ();
+ }
+ /* NOTREACHED */
+}
+
+
+static time_t
+Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
+ time_t Month;
+ time_t Day;
+ time_t Year;
+ time_t Hours;
+ time_t Minutes;
+ time_t Seconds;
+ MERIDIAN Meridian;
+ DSTMODE DSTmode;
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 0)
+ Year = -Year;
+ if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ if (Year < EPOCH || Year > 1999
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month])
+ return -1;
+
+ for (Julian = Day - 1, i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(Start, Future)
+ time_t Start;
+ time_t Future;
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(Start, DayOrdinal, DayNumber)
+ time_t Start;
+ time_t DayOrdinal;
+ time_t DayNumber;
+{
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(Start, RelMonth)
+ time_t Start;
+ time_t RelMonth;
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(buff)
+ char *buff;
+{
+ register char *p;
+ register char *q;
+ register const TABLE *tp;
+ int i;
+ int abbrev;
+
+ /* Make it lowercase. */
+ for (p = buff; *p; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+
+ if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
+
+ /* See if we have an abbreviation for a month. */
+ if (strlen(buff) == 3)
+ abbrev = 1;
+ else if (strlen(buff) == 4 && buff[3] == '.') {
+ abbrev = 1;
+ buff[3] = '\0';
+ }
+ else
+ abbrev = 0;
+
+ for (tp = MonthDayTable; tp->name; tp++) {
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ if (strcmp(buff, "dst") == 0)
+ return tDST;
+
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Strip off any plural and try the units table again. */
+ i = strlen(buff) - 1;
+ if (buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
+ }
+
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && isalpha(*buff)) {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ /* Drop out any periods and try the timezone table again. */
+ for (i = 0, p = q = buff; *q; q++)
+ if (*q != '.')
+ *p++ = *q;
+ else
+ i++;
+ *p = '\0';
+ if (i)
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ return tID;
+}
+
+
+static int
+yylex()
+{
+ register char c;
+ register char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for ( ; ; ) {
+ while (isspace(*yyInput))
+ yyInput++;
+
+ if (isdigit(c = *yyInput) || c == '-' || c == '+') {
+ if (c == '-' || c == '+') {
+ sign = c == '-' ? -1 : 1;
+ if (!isdigit(*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ for (yylval.Number = 0; isdigit(c = *yyInput++); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ if (sign < 0)
+ yylval.Number = -yylval.Number;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ if (isalpha(c)) {
+ for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord(buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm (a, b)
+ struct tm *a, *b;
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t
+get_date(p, now)
+ char *p;
+ struct timeb *now;
+{
+ struct tm *tm, gmt;
+ struct timeb ftz;
+ time_t Start;
+ time_t tod;
+
+ yyInput = p;
+ if (now == NULL) {
+ now = &ftz;
+ (void)time(&ftz.time);
+
+ if (! (tm = gmtime (&ftz.time)))
+ return -1;
+ gmt = *tm; /* Make a copy, in case localtime modifies *tm. */
+
+ if (! (tm = localtime (&ftz.time)))
+ return -1;
+
+ ftz.timezone = difftm (&gmt, tm) / 60;
+ if(tm->tm_isdst)
+ ftz.timezone += 60;
+ }
+
+ tm = localtime(&now->time);
+ yyYear = tm->tm_year;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+ yyTimezone = now->timezone;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = MER24;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+ yyMeridian, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ }
+ else {
+ Start = now->time;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's distinguishable
+ * from the error return value. (Alternately could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+/* ARGSUSED */
+int
+main(ac, av)
+ int ac;
+ char *av[];
+{
+ char buff[128];
+ time_t d;
+
+ (void)printf("Enter date, or blank line to exit.\n\t> ");
+ (void)fflush(stdout);
+ while (gets(buff) && buff[0]) {
+ d = get_date(buff, (struct timeb *)NULL);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("%s", ctime(&d));
+ (void)printf("\t> ");
+ (void)fflush(stdout);
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
+int yyexca[] ={
+-1, 1,
+ 0, -1,
+ -2, 0,
+ };
+# define YYNPROD 42
+# define YYLAST 228
+int yyact[]={
+
+ 13, 11, 22, 28, 16, 12, 18, 17, 15, 9,
+ 10, 38, 39, 20, 48, 44, 47, 46, 36, 43,
+ 50, 32, 35, 34, 33, 29, 37, 31, 41, 45,
+ 40, 30, 14, 8, 7, 6, 5, 4, 3, 2,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 49, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 21, 0, 0, 19, 25, 24, 27,
+ 26, 23, 44, 0, 0, 0, 0, 42 };
+int yypact[]={
+
+ -1000, -258, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -45,
+ -266, -1000, -242, -13, -230, -241, -1000, -1000, -1000, -1000,
+ -245, -1000, -249, -240, -255, -1000, -1000, -1000, -1000, -14,
+ -1000, -1000, -1000, -1000, -1000, -39, -18, -1000, -1000, -1000,
+ -250, -1000, -1000, -251, -1000, -253, -1000, -246, -1000, -1000,
+ -1000 };
+int yypgo[]={
+
+ 0, 28, 40, 39, 38, 37, 36, 35, 34, 33,
+ 32 };
+int yyr1[]={
+
+ 0, 2, 2, 3, 3, 3, 3, 3, 3, 4,
+ 4, 4, 4, 4, 5, 5, 5, 7, 7, 7,
+ 6, 6, 6, 6, 6, 6, 6, 6, 8, 8,
+ 10, 10, 10, 10, 10, 10, 10, 10, 10, 9,
+ 1, 1 };
+int yyr2[]={
+
+ 0, 0, 4, 3, 3, 3, 3, 3, 2, 5,
+ 9, 9, 13, 13, 3, 3, 5, 3, 5, 5,
+ 7, 11, 7, 7, 5, 9, 5, 7, 5, 2,
+ 5, 5, 3, 5, 5, 3, 5, 5, 3, 3,
+ 1, 3 };
+int yychk[]={
+
+ -1000, -2, -3, -4, -5, -6, -7, -8, -9, 267,
+ 268, 259, 263, 258, -10, 266, 262, 265, 264, 261,
+ 58, 258, 47, 266, 263, 262, 265, 264, 269, 267,
+ 44, 257, 262, 265, 264, 267, 267, 266, 266, 267,
+ 44, -1, 266, 58, 261, 47, 267, 267, 267, -1,
+ 266 };
+int yydef[]={
+
+ 1, -2, 2, 3, 4, 5, 6, 7, 8, 39,
+ 14, 15, 0, 17, 29, 0, 32, 35, 38, 9,
+ 0, 19, 0, 0, 26, 30, 34, 37, 16, 24,
+ 18, 28, 31, 33, 36, 40, 20, 22, 23, 27,
+ 0, 10, 11, 0, 41, 0, 25, 40, 21, 12,
+ 13 };
+typedef struct { char *t_name; int t_val; } yytoktype;
+#ifndef YYDEBUG
+# define YYDEBUG 0 /* don't allow debugging */
+#endif
+
+#if YYDEBUG
+
+yytoktype yytoks[] =
+{
+ "tAGO", 257,
+ "tDAY", 258,
+ "tDAYZONE", 259,
+ "tID", 260,
+ "tMERIDIAN", 261,
+ "tMINUTE_UNIT", 262,
+ "tMONTH", 263,
+ "tMONTH_UNIT", 264,
+ "tSEC_UNIT", 265,
+ "tSNUMBER", 266,
+ "tUNUMBER", 267,
+ "tZONE", 268,
+ "tDST", 269,
+ "-unknown-", -1 /* ends search */
+};
+
+char * yyreds[] =
+{
+ "-no such reduction-",
+ "spec : /* empty */",
+ "spec : spec item",
+ "item : time",
+ "item : zone",
+ "item : date",
+ "item : day",
+ "item : rel",
+ "item : number",
+ "time : tUNUMBER tMERIDIAN",
+ "time : tUNUMBER ':' tUNUMBER o_merid",
+ "time : tUNUMBER ':' tUNUMBER tSNUMBER",
+ "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
+ "time : tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER",
+ "zone : tZONE",
+ "zone : tDAYZONE",
+ "zone : tZONE tDST",
+ "day : tDAY",
+ "day : tDAY ','",
+ "day : tUNUMBER tDAY",
+ "date : tUNUMBER '/' tUNUMBER",
+ "date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
+ "date : tUNUMBER tSNUMBER tSNUMBER",
+ "date : tUNUMBER tMONTH tSNUMBER",
+ "date : tMONTH tUNUMBER",
+ "date : tMONTH tUNUMBER ',' tUNUMBER",
+ "date : tUNUMBER tMONTH",
+ "date : tUNUMBER tMONTH tUNUMBER",
+ "rel : relunit tAGO",
+ "rel : relunit",
+ "relunit : tUNUMBER tMINUTE_UNIT",
+ "relunit : tSNUMBER tMINUTE_UNIT",
+ "relunit : tMINUTE_UNIT",
+ "relunit : tSNUMBER tSEC_UNIT",
+ "relunit : tUNUMBER tSEC_UNIT",
+ "relunit : tSEC_UNIT",
+ "relunit : tSNUMBER tMONTH_UNIT",
+ "relunit : tUNUMBER tMONTH_UNIT",
+ "relunit : tMONTH_UNIT",
+ "number : tUNUMBER",
+ "o_merid : /* empty */",
+ "o_merid : tMERIDIAN",
+};
+#endif /* YYDEBUG */
+/* @(#)yaccpar 1.10 89/04/04 SMI; from S5R3 1.10 */
+
+/*
+** Skeleton parser driver for yacc output
+*/
+
+/*
+** yacc user known macros and defines
+*/
+#define YYERROR goto yyerrlab
+#define YYACCEPT { free(yys); free(yyv); return(0); }
+#define YYABORT { free(yys); free(yyv); return(1); }
+#define YYBACKUP( newtoken, newvalue )\
+{\
+ if ( yychar >= 0 || ( yyr2[ yytmp ] >> 1 ) != 1 )\
+ {\
+ yyerror( "syntax error - cannot backup" );\
+ goto yyerrlab;\
+ }\
+ yychar = newtoken;\
+ yystate = *yyps;\
+ yylval = newvalue;\
+ goto yynewstate;\
+}
+#define YYRECOVERING() (!!yyerrflag)
+#ifndef YYDEBUG
+# define YYDEBUG 1 /* make debugging available */
+#endif
+
+/*
+** user known globals
+*/
+int yydebug; /* set to 1 to get debugging */
+
+/*
+** driver internal defines
+*/
+#define YYFLAG (-1000)
+
+/*
+** static variables used by the parser
+*/
+static YYSTYPE *yyv; /* value stack */
+static int *yys; /* state stack */
+
+static YYSTYPE *yypv; /* top of value stack */
+static int *yyps; /* top of state stack */
+
+static int yystate; /* current state */
+static int yytmp; /* extra var (lasts between blocks) */
+
+int yynerrs; /* number of errors */
+
+int yyerrflag; /* error recovery flag */
+int yychar; /* current input token number */
+
+
+/*
+** yyparse - return 0 if worked, 1 if syntax error not recovered from
+*/
+int
+yyparse()
+{
+ register YYSTYPE *yypvt; /* top of value stack for $vars */
+ unsigned yymaxdepth = YYMAXDEPTH;
+
+ /*
+ ** Initialize externals - yyparse may be called more than once
+ */
+ yyv = (YYSTYPE*)malloc(yymaxdepth*sizeof(YYSTYPE));
+ yys = (int*)malloc(yymaxdepth*sizeof(int));
+ if (!yyv || !yys)
+ {
+ yyerror( "out of memory" );
+ return(1);
+ }
+ yypv = &yyv[-1];
+ yyps = &yys[-1];
+ yystate = 0;
+ yytmp = 0;
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = -1;
+
+ goto yystack;
+ {
+ register YYSTYPE *yy_pv; /* top of value stack */
+ register int *yy_ps; /* top of state stack */
+ register int yy_state; /* current state */
+ register int yy_n; /* internal state number info */
+
+ /*
+ ** get globals into registers.
+ ** branch to here only if YYBACKUP was called.
+ */
+ yynewstate:
+ yy_pv = yypv;
+ yy_ps = yyps;
+ yy_state = yystate;
+ goto yy_newstate;
+
+ /*
+ ** get globals into registers.
+ ** either we just started, or we just finished a reduction
+ */
+ yystack:
+ yy_pv = yypv;
+ yy_ps = yyps;
+ yy_state = yystate;
+
+ /*
+ ** top of for (;;) loop while no reductions done
+ */
+ yy_stack:
+ /*
+ ** put a state and value onto the stacks
+ */
+#if YYDEBUG
+ /*
+ ** if debugging, look up token value in list of value vs.
+ ** name pairs. 0 and negative (-1) are special values.
+ ** Note: linear search is used since time is not a real
+ ** consideration while debugging.
+ */
+ if ( yydebug )
+ {
+ register int yy_i;
+
+ (void)printf( "State %d, token ", yy_state );
+ if ( yychar == 0 )
+ (void)printf( "end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "-none-\n" );
+ else
+ {
+ for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val == yychar )
+ break;
+ }
+ (void)printf( "%s\n", yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ if ( ++yy_ps >= &yys[ yymaxdepth ] ) /* room on stack? */
+ {
+ /*
+ ** reallocate and recover. Note that pointers
+ ** have to be reset, or bad things will happen
+ */
+ int yyps_index = (yy_ps - yys);
+ int yypv_index = (yy_pv - yyv);
+ int yypvt_index = (yypvt - yyv);
+ yymaxdepth += YYMAXDEPTH;
+ yyv = (YYSTYPE*)realloc((char*)yyv,
+ yymaxdepth * sizeof(YYSTYPE));
+ yys = (int*)realloc((char*)yys,
+ yymaxdepth * sizeof(int));
+ if (!yyv || !yys)
+ {
+ yyerror( "yacc stack overflow" );
+ return(1);
+ }
+ yy_ps = yys + yyps_index;
+ yy_pv = yyv + yypv_index;
+ yypvt = yyv + yypvt_index;
+ }
+ *yy_ps = yy_state;
+ *++yy_pv = yyval;
+
+ /*
+ ** we have a new state - find out what to do
+ */
+ yy_newstate:
+ if ( ( yy_n = yypact[ yy_state ] ) <= YYFLAG )
+ goto yydefault; /* simple state */
+#if YYDEBUG
+ /*
+ ** if debugging, need to mark whether new token grabbed
+ */
+ yytmp = yychar < 0;
+#endif
+ if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
+ yychar = 0; /* reached EOF */
+#if YYDEBUG
+ if ( yydebug && yytmp )
+ {
+ register int yy_i;
+
+ (void)printf( "Received token " );
+ if ( yychar == 0 )
+ (void)printf( "end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "-none-\n" );
+ else
+ {
+ for ( yy_i = 0; yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val == yychar )
+ break;
+ }
+ (void)printf( "%s\n", yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ if ( ( ( yy_n += yychar ) < 0 ) || ( yy_n >= YYLAST ) )
+ goto yydefault;
+ if ( yychk[ yy_n = yyact[ yy_n ] ] == yychar ) /*valid shift*/
+ {
+ yychar = -1;
+ yyval = yylval;
+ yy_state = yy_n;
+ if ( yyerrflag > 0 )
+ yyerrflag--;
+ goto yy_stack;
+ }
+
+ yydefault:
+ if ( ( yy_n = yydef[ yy_state ] ) == -2 )
+ {
+#if YYDEBUG
+ yytmp = yychar < 0;
+#endif
+ if ( ( yychar < 0 ) && ( ( yychar = yylex() ) < 0 ) )
+ yychar = 0; /* reached EOF */
+#if YYDEBUG
+ if ( yydebug && yytmp )
+ {
+ register int yy_i;
+
+ (void)printf( "Received token " );
+ if ( yychar == 0 )
+ (void)printf( "end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "-none-\n" );
+ else
+ {
+ for ( yy_i = 0;
+ yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val
+ == yychar )
+ {
+ break;
+ }
+ }
+ (void)printf( "%s\n", yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ /*
+ ** look through exception table
+ */
+ {
+ register int *yyxi = yyexca;
+
+ while ( ( *yyxi != -1 ) ||
+ ( yyxi[1] != yy_state ) )
+ {
+ yyxi += 2;
+ }
+ while ( ( *(yyxi += 2) >= 0 ) &&
+ ( *yyxi != yychar ) )
+ ;
+ if ( ( yy_n = yyxi[1] ) < 0 )
+ YYACCEPT;
+ }
+ }
+
+ /*
+ ** check for syntax error
+ */
+ if ( yy_n == 0 ) /* have an error */
+ {
+ /* no worry about speed here! */
+ switch ( yyerrflag )
+ {
+ case 0: /* new error */
+ yyerror( "syntax error" );
+ goto skip_init;
+ yyerrlab:
+ /*
+ ** get globals into registers.
+ ** we have a user generated syntax type error
+ */
+ yy_pv = yypv;
+ yy_ps = yyps;
+ yy_state = yystate;
+ yynerrs++;
+ skip_init:
+ case 1:
+ case 2: /* incompletely recovered error */
+ /* try again... */
+ yyerrflag = 3;
+ /*
+ ** find state where "error" is a legal
+ ** shift action
+ */
+ while ( yy_ps >= yys )
+ {
+ yy_n = yypact[ *yy_ps ] + YYERRCODE;
+ if ( yy_n >= 0 && yy_n < YYLAST &&
+ yychk[yyact[yy_n]] == YYERRCODE) {
+ /*
+ ** simulate shift of "error"
+ */
+ yy_state = yyact[ yy_n ];
+ goto yy_stack;
+ }
+ /*
+ ** current state has no shift on
+ ** "error", pop stack
+ */
+#if YYDEBUG
+# define _POP_ "Error recovery pops state %d, uncovers state %d\n"
+ if ( yydebug )
+ (void)printf( _POP_, *yy_ps,
+ yy_ps[-1] );
+# undef _POP_
+#endif
+ yy_ps--;
+ yy_pv--;
+ }
+ /*
+ ** there is no state on stack with "error" as
+ ** a valid shift. give up.
+ */
+ YYABORT;
+ case 3: /* no shift yet; eat a token */
+#if YYDEBUG
+ /*
+ ** if debugging, look up token in list of
+ ** pairs. 0 and negative shouldn't occur,
+ ** but since timing doesn't matter when
+ ** debugging, it doesn't hurt to leave the
+ ** tests here.
+ */
+ if ( yydebug )
+ {
+ register int yy_i;
+
+ (void)printf( "Error recovery discards " );
+ if ( yychar == 0 )
+ (void)printf( "token end-of-file\n" );
+ else if ( yychar < 0 )
+ (void)printf( "token -none-\n" );
+ else
+ {
+ for ( yy_i = 0;
+ yytoks[yy_i].t_val >= 0;
+ yy_i++ )
+ {
+ if ( yytoks[yy_i].t_val
+ == yychar )
+ {
+ break;
+ }
+ }
+ (void)printf( "token %s\n",
+ yytoks[yy_i].t_name );
+ }
+ }
+#endif /* YYDEBUG */
+ if ( yychar == 0 ) /* reached EOF. quit */
+ YYABORT;
+ yychar = -1;
+ goto yy_newstate;
+ }
+ }/* end if ( yy_n == 0 ) */
+ /*
+ ** reduction by production yy_n
+ ** put stack tops, etc. so things right after switch
+ */
+#if YYDEBUG
+ /*
+ ** if debugging, print the string that is the user's
+ ** specification of the reduction which is just about
+ ** to be done.
+ */
+ if ( yydebug )
+ (void)printf( "Reduce by (%d) \"%s\"\n",
+ yy_n, yyreds[ yy_n ] );
+#endif
+ yytmp = yy_n; /* value to switch over */
+ yypvt = yy_pv; /* $vars top of value stack */
+ /*
+ ** Look in goto table for next state
+ ** Sorry about using yy_state here as temporary
+ ** register variable, but why not, if it works...
+ ** If yyr2[ yy_n ] doesn't have the low order bit
+ ** set, then there is no action to be done for
+ ** this reduction. So, no saving & unsaving of
+ ** registers done. The only difference between the
+ ** code just after the if and the body of the if is
+ ** the goto yy_stack in the body. This way the test
+ ** can be made before the choice of what to do is needed.
+ */
+ {
+ /* length of production doubled with extra bit */
+ register int yy_len = yyr2[ yy_n ];
+
+ if ( !( yy_len & 01 ) )
+ {
+ yy_len >>= 1;
+ yyval = ( yy_pv -= yy_len )[1]; /* $$ = $1 */
+ yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
+ *( yy_ps -= yy_len ) + 1;
+ if ( yy_state >= YYLAST ||
+ yychk[ yy_state =
+ yyact[ yy_state ] ] != -yy_n )
+ {
+ yy_state = yyact[ yypgo[ yy_n ] ];
+ }
+ goto yy_stack;
+ }
+ yy_len >>= 1;
+ yyval = ( yy_pv -= yy_len )[1]; /* $$ = $1 */
+ yy_state = yypgo[ yy_n = yyr1[ yy_n ] ] +
+ *( yy_ps -= yy_len ) + 1;
+ if ( yy_state >= YYLAST ||
+ yychk[ yy_state = yyact[ yy_state ] ] != -yy_n )
+ {
+ yy_state = yyact[ yypgo[ yy_n ] ];
+ }
+ }
+ /* save until reenter driver code */
+ yystate = yy_state;
+ yyps = yy_ps;
+ yypv = yy_pv;
+ }
+ /*
+ ** code supplied by user is placed in this switch
+ */
+ switch( yytmp )
+ {
+
+case 3:
+{
+ yyHaveTime++;
+ } break;
+case 4:
+{
+ yyHaveZone++;
+ } break;
+case 5:
+{
+ yyHaveDate++;
+ } break;
+case 6:
+{
+ yyHaveDay++;
+ } break;
+case 7:
+{
+ yyHaveRel++;
+ } break;
+case 9:
+{
+ yyHour = yypvt[-1].Number;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = yypvt[-0].Meridian;
+ } break;
+case 10:
+{
+ yyHour = yypvt[-3].Number;
+ yyMinutes = yypvt[-1].Number;
+ yySeconds = 0;
+ yyMeridian = yypvt[-0].Meridian;
+ } break;
+case 11:
+{
+ yyHour = yypvt[-3].Number;
+ yyMinutes = yypvt[-1].Number;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - (yypvt[-0].Number % 100 + (yypvt[-0].Number / 100) * 60);
+ } break;
+case 12:
+{
+ yyHour = yypvt[-5].Number;
+ yyMinutes = yypvt[-3].Number;
+ yySeconds = yypvt[-1].Number;
+ yyMeridian = yypvt[-0].Meridian;
+ } break;
+case 13:
+{
+ yyHour = yypvt[-5].Number;
+ yyMinutes = yypvt[-3].Number;
+ yySeconds = yypvt[-1].Number;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - (yypvt[-0].Number % 100 + (yypvt[-0].Number / 100) * 60);
+ } break;
+case 14:
+{
+ yyTimezone = yypvt[-0].Number;
+ yyDSTmode = DSToff;
+ } break;
+case 15:
+{
+ yyTimezone = yypvt[-0].Number;
+ yyDSTmode = DSTon;
+ } break;
+case 16:
+{
+ yyTimezone = yypvt[-1].Number;
+ yyDSTmode = DSTon;
+ } break;
+case 17:
+{
+ yyDayOrdinal = 1;
+ yyDayNumber = yypvt[-0].Number;
+ } break;
+case 18:
+{
+ yyDayOrdinal = 1;
+ yyDayNumber = yypvt[-1].Number;
+ } break;
+case 19:
+{
+ yyDayOrdinal = yypvt[-1].Number;
+ yyDayNumber = yypvt[-0].Number;
+ } break;
+case 20:
+{
+ yyMonth = yypvt[-2].Number;
+ yyDay = yypvt[-0].Number;
+ } break;
+case 21:
+{
+ yyMonth = yypvt[-4].Number;
+ yyDay = yypvt[-2].Number;
+ yyYear = yypvt[-0].Number;
+ } break;
+case 22:
+{
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = yypvt[-2].Number;
+ yyMonth = -yypvt[-1].Number;
+ yyDay = -yypvt[-0].Number;
+ } break;
+case 23:
+{
+ /* e.g. 17-JUN-1992. */
+ yyDay = yypvt[-2].Number;
+ yyMonth = yypvt[-1].Number;
+ yyYear = -yypvt[-0].Number;
+ } break;
+case 24:
+{
+ yyMonth = yypvt[-1].Number;
+ yyDay = yypvt[-0].Number;
+ } break;
+case 25:
+{
+ yyMonth = yypvt[-3].Number;
+ yyDay = yypvt[-2].Number;
+ yyYear = yypvt[-0].Number;
+ } break;
+case 26:
+{
+ yyMonth = yypvt[-0].Number;
+ yyDay = yypvt[-1].Number;
+ } break;
+case 27:
+{
+ yyMonth = yypvt[-1].Number;
+ yyDay = yypvt[-2].Number;
+ yyYear = yypvt[-0].Number;
+ } break;
+case 28:
+{
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ } break;
+case 30:
+{
+ yyRelSeconds += yypvt[-1].Number * yypvt[-0].Number * 60L;
+ } break;
+case 31:
+{
+ yyRelSeconds += yypvt[-1].Number * yypvt[-0].Number * 60L;
+ } break;
+case 32:
+{
+ yyRelSeconds += yypvt[-0].Number * 60L;
+ } break;
+case 33:
+{
+ yyRelSeconds += yypvt[-1].Number;
+ } break;
+case 34:
+{
+ yyRelSeconds += yypvt[-1].Number;
+ } break;
+case 35:
+{
+ yyRelSeconds++;
+ } break;
+case 36:
+{
+ yyRelMonth += yypvt[-1].Number * yypvt[-0].Number;
+ } break;
+case 37:
+{
+ yyRelMonth += yypvt[-1].Number * yypvt[-0].Number;
+ } break;
+case 38:
+{
+ yyRelMonth += yypvt[-0].Number;
+ } break;
+case 39:
+{
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = yypvt[-0].Number;
+ else {
+ if(yypvt[-0].Number>10000) {
+ yyHaveDate++;
+ yyDay= (yypvt[-0].Number)%100;
+ yyMonth= (yypvt[-0].Number/100)%100;
+ yyYear = yypvt[-0].Number/10000;
+ }
+ else {
+ yyHaveTime++;
+ if (yypvt[-0].Number < 100) {
+ yyHour = yypvt[-0].Number;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = yypvt[-0].Number / 100;
+ yyMinutes = yypvt[-0].Number % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ }
+ } break;
+case 40:
+{
+ yyval.Meridian = MER24;
+ } break;
+case 41:
+{
+ yyval.Meridian = yypvt[-0].Meridian;
+ } break;
+ }
+ goto yystack; /* reset registers in driver code */
+}
diff --git a/gnu/usr.bin/cvs/os2/getpass.c b/gnu/usr.bin/cvs/os2/getpass.c
new file mode 100644
index 00000000000..b1113aedfc2
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/getpass.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <string.h>
+#include "cvs.h"
+
+char *
+getpass (char *prompt)
+{
+ static char passbuf[30];
+ int i;
+ char *p;
+ int ch;
+
+ printf ("%s", prompt);
+ fflush (stdout);
+
+ p = passbuf, i = 0;
+ while (((ch = getchar ()) != '\n') && (ch != EOF))
+ {
+ if (i++ < 24)
+ *p++ = ch;
+ }
+ *p = '\0';
+
+ return passbuf;
+}
diff --git a/gnu/usr.bin/cvs/os2/mkdir.c b/gnu/usr.bin/cvs/os2/mkdir.c
new file mode 100644
index 00000000000..2c9df546847
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/mkdir.c
@@ -0,0 +1,17 @@
+/* mkdir.c --- mkdir for OS/2
+ Karl Fogel <kfogel@cyclic.com> --- October 1995 */
+
+#include <assert.h>
+
+#include "cvs.h"
+
+int
+os2_mkdir (const char *path, int mode)
+{
+ /* This is true for all extant calls to CVS_MKDIR. If
+ someone adds a call that uses something else later,
+ we should tweak this function to handle that. */
+ assert (mode == 0777);
+
+ return mkdir (path);
+}
diff --git a/gnu/usr.bin/cvs/os2/options.h b/gnu/usr.bin/cvs/os2/options.h
new file mode 100644
index 00000000000..d0bbac10cb3
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/options.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 1992, Brian Berliner and Jeff Polk
+ * Copyright (c) 1989-1992, Brian Berliner
+ *
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS 1.4 kit.
+ *
+ * This file holds (most of) the configuration tweaks that can be made to
+ * customize CVS for your site. CVS comes configured for a typical SunOS 4.x
+ * environment. The comments for each configurable item are intended to be
+ * self-explanatory. All #defines are tested first to see if an over-riding
+ * option was specified on the "make" command line.
+ *
+ * If special libraries are needed, you will have to edit the Makefile.in file
+ * or the configure script directly. Sorry.
+ */
+
+/*
+ * 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
+
+/*
+ * If, before installing this version of CVS, you were running RCS V4 AND you
+ * are installing this CVS and RCS V5 and GNU diff 1.15 all at the same time,
+ * you should turn on the following define. It only exists to try to do
+ * reasonable things with your existing checked out files when you upgrade to
+ * RCS V5, since the keyword expansion formats have changed with RCS V5.
+ *
+ * If you already have been running with RCS5, or haven't been running with CVS
+ * yet at all, or are sticking with RCS V4 for now, leave the commented out.
+ */
+#ifndef HAD_RCS4
+/* #define HAD_RCS4 */
+#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 not concerned about
+ * heterogeneous hosts accessing your modules file, turn this option off.
+ */
+#ifndef MY_NDBM
+#define MY_NDBM
+#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. If you are
+ * using the GNU version of diff (version 1.15 or later), this should
+ * be "diff -a".
+ *
+ * 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 "grep" program to execute when checking to see if a merged file had
+ * any conflicts. This "grep" must support the "-s" option and a standard
+ * regular expression as an argument. Specify a full pathname if your site
+ * wants to use a particular grep.
+ */
+
+#ifndef GREP
+#define GREP "grep"
+#endif
+
+/*
+ * The "rm" program to execute when pruning directories that are not part of
+ * a release. This "rm" must support the "-fr" options. Specify a full
+ * pathname if your site wants to use a particular rm.
+ */
+#ifndef RM
+#define RM "rm"
+#endif
+
+/*
+ * The "sort" program to execute when displaying the module database. Specify
+ * a full pathname if your site wants to use a particular sort.
+ */
+#ifndef SORT
+#define SORT "sort"
+#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.
+ */
+#ifndef PATCH_PROGRAM
+#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're compiling the authenticating server (see
+ * AUTH_SERVER_SUPPORT farther down), then you probably want to set
+ * RCSBIN_DFLT. The authenticating server starts out running as root,
+ * and then switches to run as the appropriate user once
+ * authentication is complete. No 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. An alternative to setting RCSBIN_DFLT
+ * is to make sure that root has the right directory in its path
+ * already.
+ *
+ * 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
+
+/*
+ * The default editor to use, if one does not specify the "-e" option to cvs,
+ * or does not have an EDITOR environment variable. I set this to just "vi",
+ * and use the shell to find where "vi" actually is. This allows sites with
+ * /usr/bin/vi or /usr/ucb/vi to work equally well (assuming that your PATH
+ * is reasonable).
+ *
+ * The notepad program seems to be Windows NT's bare-bones text editor.
+ */
+#ifndef EDITOR_DFLT
+#define EDITOR_DFLT "notepad"
+#endif
+
+/*
+ * The default umask to use when creating or otherwise setting file or
+ * directory permissions in the repository. Must be a value in the
+ * range of 0 through 0777. For example, a value of 002 allows group
+ * rwx access and world rx access; a value of 007 allows group rwx
+ * access but no world access. This value is overridden by the value
+ * of the CVSUMASK environment variable, which is interpreted as an
+ * octal number.
+ */
+#ifndef UMASK_DFLT
+#define UMASK_DFLT 002
+#endif
+
+/*
+ * The cvs admin command is restricted to the members of the group
+ * CVS_ADMIN_GROUP. If this group does not exist, all users are
+ * allowed to run cvs admin. To disable the cvs admin for all users,
+ * create an empty group CVS_ADMIN_GROUP. To disable access control for
+ * cvs admin, comment out the define below.
+ *
+ * Under Windows NT and OS/2, this must not be used because it tries
+ * to include <grp.h>.
+ */
+#ifdef CVS_ADMIN_GROUP
+/* #define CVS_ADMIN_GROUP "cvsadmin" */
+#endif
+
+/*
+ * The Repository file holds the path to the directory within the source
+ * repository that contains the RCS ,v files for each CVS working directory.
+ * This path is either a full-path or a path relative to CVSROOT.
+ *
+ * The only advantage that I can see to having a relative path is that One can
+ * change the physical location of the master source repository, change one's
+ * CVSROOT environment variable, and CVS will work without problems. I
+ * recommend using full-paths.
+ */
+#ifndef RELATIVE_REPOS
+/* #define RELATIVE_REPOS */
+#endif
+
+/*
+ * When committing or importing files, you must enter a log message.
+ * Normally, you can do this either via the -m flag on the command line or an
+ * editor will be started for you. If you like to use logging templates (the
+ * rcsinfo file within the $CVSROOT/CVSROOT directory), you might want to
+ * force people to use the editor even if they specify a message with -m.
+ * Enabling FORCE_USE_EDITOR will cause the -m message to be appended to the
+ * temp file when the editor is started.
+ */
+#ifndef FORCE_USE_EDITOR
+/* #define FORCE_USE_EDITOR */
+#endif
+
+/*
+ * When locking the repository, some sites like to remove locks and assume
+ * the program that created them went away if the lock has existed for a long
+ * time. This used to be the default for previous versions of CVS. CVS now
+ * attempts to be much more robust, so lock files should not be left around
+ * by mistake. The new behaviour will never remove old locks (they must now
+ * be removed by hand). Enabling CVS_FUDGELOCKS will cause CVS to remove
+ * locks that are older than CVSLCKAGE seconds.
+ * Use of this option is NOT recommended.
+ */
+#ifndef CVS_FUDGELOCKS
+/* #define CVS_FUDGELOCKS */
+#endif
+
+/*
+ * When committing a permanent change, CVS and RCS make a log entry of
+ * who committed the change. If you are committing the change logged in
+ * as "root" (not under "su" or other root-priv giving program), CVS/RCS
+ * cannot determine who is actually making the change.
+ *
+ * As such, by default, CVS disallows changes to be committed by users
+ * logged in as "root". You can disable this option by commenting
+ * out the lines below.
+ *
+ * Under Windows NT, privileges are associated with groups, not users,
+ * so the case in which someone has logged in as root does not occur.
+ * Thus, there is no need for this hack.
+ *
+ * todo: I don't know about OS/2 yet. -kff
+ */
+#undef CVS_BADROOT
+
+/*
+ * The "cvs diff" command accepts all the single-character options that GNU
+ * diff (1.15) accepts. Except -D. GNU diff uses -D as a way to put
+ * cpp-style #define's around the output differences. CVS, by default, uses
+ * -D to specify a free-form date (like "cvs diff -D '1 week ago'"). If
+ * you would prefer that the -D option of "cvs diff" work like the GNU diff
+ * option, then comment out this define.
+ */
+#ifndef CVS_DIFFDATE
+#define CVS_DIFFDATE
+#endif
+
+/*
+ * define this to enable the SETXID support (see FAQ 4D.13)
+ * [ We have no such thing under OS/2, so far as I know. ]
+ */
+#undef SETXID_SUPPORT
+
+/*
+ * Under OS/2, we build the authenticated client by default.
+ * But not the server, because there is no server support for OS/2
+ * yet.
+ */
+#define AUTH_CLIENT_SUPPORT 1
+/* #define AUTH_SERVER_SUPPORT 1 */
+
+/* End of CVS configuration section */
+
+/*
+ * Externs that are included in libc, but are used frequently enough to
+ * warrant defining here.
+ */
+#ifndef STDC_HEADERS
+extern void exit ();
+#endif
+
+#ifndef getwd
+extern char *getwd ();
+#endif
+
+#ifdef AUTH_CLIENT_SUPPORT
+char *getpass (char *passbuf);
+#endif /* AUTH_CLIENT_SUPPORT */
diff --git a/gnu/usr.bin/cvs/os2/popen.c b/gnu/usr.bin/cvs/os2/popen.c
new file mode 100644
index 00000000000..9f8199764d5
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/popen.c
@@ -0,0 +1,380 @@
+/* popen.c -- popen/pclose for OS/2. */
+
+/* Set to 0 for distribution.
+ Search for "DIAGNOSTIC" in the code to see what it's for. */
+#define DIAGNOSTIC 0
+
+#define INCL_DOSQUEUES
+#define INCL_DOSPROCESS
+#define INCL_DOSSESMGR
+#include <os2.h>
+#include <process.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+
+#define LL_VAL ULONG
+#define LL_KEY PID /* also ULONG, really */
+
+
+#define STDIN 0
+#define STDOUT 1
+#define STDERR 2
+
+/* ********************************************************************* *
+ * *
+ * First, a little linked-list library to help keep track of pipes: *
+ * *
+ * ********************************************************************* */
+
+/* Map integer PID's onto integer termination codes. */
+struct pid_list
+{
+ HFILE pid; /* key */
+ ULONG term_code; /* val */
+ struct pid_list *next; /* duh */
+};
+
+static struct pid_list *pid_ll = (struct pid_list *) NULL;
+
+/* The ll_*() functions all make use of the global var `pid_ll'. */
+
+void
+ll_insert (HFILE key, ULONG val)
+{
+ struct pid_list *new;
+ new = (struct pid_list *) malloc (sizeof (*new));
+
+ new->pid = key;
+ new->term_code = val;
+ new->next = pid_ll;
+
+ pid_ll = new;
+}
+
+
+void
+ll_delete (int key)
+{
+ struct pid_list *this, *last;
+
+ this = pid_ll;
+ last = (struct pid_list *) NULL;
+
+ while (this)
+ {
+ if (this->pid == key)
+ {
+ /* Delete this node and leave. */
+ if (last)
+ last->next = this->next;
+ else
+ pid_ll = this->next;
+ free (this);
+ return;
+ }
+
+ /* Else no match, so try the next one. */
+ last = this;
+ this = this->next;
+ }
+}
+
+ULONG
+ll_lookup (HFILE key)
+{
+ struct pid_list *this = pid_ll;
+
+ while (this)
+ {
+ if (this->pid == key)
+ return this->term_code;
+
+ /* Else no match, so try the next one. */
+ this = this->next;
+ }
+
+ /* Zero is special in this context anyway. */
+ return 0;
+}
+
+#if DIAGNOSTIC
+ULONG
+ll_length ()
+{
+ struct pid_list *this = pid_ll;
+ unsigned long int len;
+
+ for (len = 0; this; len++)
+ this = this->next;
+
+ return len;
+}
+
+ULONG
+ll_print ()
+{
+ struct pid_list *this = pid_ll;
+ unsigned long int i;
+
+ for (i = 0; this; i++)
+ {
+ printf ("pid_ll[%d] == (%5d --> %5d)\n",
+ i, this->pid, this->term_code);
+ this = this->next;
+ }
+
+ if (i == 0)
+ printf ("No entries.\n");
+
+ return i;
+}
+#endif /* DIAGNOSTIC */
+
+/* ********************************************************************* *
+ * *
+ * End of linked-list library, beginning of popen/pclose: *
+ * *
+ * ********************************************************************* */
+
+/*
+ * Routine: popen
+ * Returns: FILE pointer to pipe.
+ * Action : Exec program connected via pipe, connect a FILE * to the
+ * pipe and return it.
+ * Params : Command - Program to run
+ * Mode - Mode to open pipe. "r" implies pipe is connected
+ * to the programs stdout, "w" connects to stdin.
+ */
+FILE *
+popen (const char *Command, const char *Mode)
+{
+ HFILE End1, End2, Std, Old1, Old2, Tmp;
+
+ FILE *File;
+
+ char Fail[256],
+ *Args,
+ CmdLine[256],
+ *CmdExe;
+
+ RESULTCODES
+ Result;
+
+ int Rc;
+
+ if (DosCreatePipe (&End1, &End2, 4096))
+ return NULL;
+
+ Std = (*Mode == 'w') ? STDIN : STDOUT ;
+ if (Std == STDIN)
+ {
+ Tmp = End1; End1 = End2; End2 = Tmp;
+ }
+
+ Old1 = -1; /* save stdin or stdout */
+ DosDupHandle (Std, &Old1);
+ DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
+ Tmp = Std; /* redirect stdin or stdout */
+ DosDupHandle (End2, &Tmp);
+
+ if (Std == 1)
+ {
+ Old2 = -1; /* save stderr */
+ DosDupHandle (STDERR, &Old2);
+ DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
+ Tmp = STDERR;
+ DosDupHandle (End2, &Tmp);
+ }
+
+ DosClose (End2);
+ DosSetFHState (End1, OPEN_FLAGS_NOINHERIT);
+
+ if ((CmdExe = getenv ("COMSPEC")) == NULL )
+ CmdExe = "cmd.exe";
+
+ strcpy (CmdLine, CmdExe);
+ Args = CmdLine + strlen (CmdLine) + 1; /* skip zero */
+ strcpy (Args, "/c ");
+ strcat (Args, Command);
+ Args[strlen (Args) + 1] = '\0'; /* two zeroes */
+ Rc = DosExecPgm (Fail, sizeof (Fail), EXEC_ASYNCRESULT,
+ (unsigned char *) CmdLine, 0, &Result,
+ (unsigned char *) CmdExe);
+
+ Tmp = Std; /* restore stdin or stdout */
+ DosDupHandle (Old1, &Tmp);
+ DosClose (Old1);
+
+ if (Std == STDOUT)
+ {
+ Tmp = STDERR; /* restore stderr */
+ DosDupHandle (Old2, &Tmp);
+ DosClose (Old2);
+ }
+
+ if (Rc)
+ {
+ DosClose (End1);
+ return NULL;
+ }
+
+ File = fdopen (End1, Mode);
+ ll_insert ((LL_KEY) End1, (LL_VAL) Result.codeTerminate);
+
+ return File;
+}
+
+
+/*
+ * Routine: popenRW
+ * Returns: PID of child process
+ * Action : Exec program connected via pipe, connect int fd's to
+ * both the stdin and stdout of the process.
+ * Params : Command - Program to run
+ * Pipes - Array of 2 ints to store the pipe descriptors
+ * Pipe[0] writes to child's stdin,
+ * Pipe[1] reads from child's stdout/stderr
+ */
+int
+popenRW (const char **argv, int *pipes)
+{
+ HFILE Out1, Out2, In1, In2;
+ HFILE Old0 = -1, Old1 = -1, Old2 = -1, Tmp;
+
+ PID pid;
+
+ if (DosCreatePipe (&Out2, &Out1, 4096))
+ return FALSE;
+
+ if (DosCreatePipe (&In1, &In2, 4096))
+ {
+ DosClose (Out1);
+ DosClose (Out2);
+ return FALSE;
+ }
+
+ /* Save std{in,out,err} */
+ DosDupHandle (STDIN, &Old0);
+ DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
+ DosDupHandle (STDOUT, &Old1);
+ DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
+ DosDupHandle (STDERR, &Old2);
+ DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
+
+ /* Redirect std{in,out,err} */
+ Tmp = STDIN;
+ DosDupHandle (In1, &Tmp);
+ Tmp = STDOUT;
+ DosDupHandle (Out1, &Tmp);
+ Tmp = STDERR;
+ DosDupHandle (Out1, &Tmp);
+
+ /* Close file handles not needed in child */
+
+ DosClose (In1);
+ DosClose (Out1);
+ DosSetFHState (In2, OPEN_FLAGS_NOINHERIT);
+ DosSetFHState (Out2, OPEN_FLAGS_NOINHERIT);
+
+ /* Spawn we now our hoary brood. */
+ pid = spawnvp (P_NOWAIT, argv[0], argv);
+
+ /* Restore std{in,out,err} */
+ Tmp = STDIN;
+ DosDupHandle (Old0, &Tmp);
+ DosClose (Old0);
+ Tmp = STDOUT;
+ DosDupHandle (Old1, &Tmp);
+ DosClose (Old1);
+ Tmp = STDERR;
+ DosDupHandle (Old2, &Tmp);
+ DosClose (Old2);
+
+ if(pid < 0)
+ {
+ DosClose (In2);
+ DosClose (Out2);
+ return -1;
+ }
+
+ pipes[0] = In2;
+ _setmode (pipes[0], O_BINARY);
+ pipes[1] = Out2;
+ _setmode (pipes[1], O_BINARY);
+
+ /* Save ID of write-to-child pipe for pclose() */
+ ll_insert ((LL_KEY) In2, (LL_VAL) pid);
+
+ return pid;
+}
+
+
+/*
+ * Routine: pclose
+ * Returns: TRUE on success
+ * Action : Close a pipe opened with popen();
+ * Params : Pipe - pipe to close
+ */
+int
+pclose (FILE *Pipe)
+{
+ RESULTCODES rc;
+ PID pid, pid1;
+ int Handle = fileno (Pipe);
+
+ fclose (Pipe);
+
+ rc.codeTerminate = -1;
+
+ pid1 = (PID) ll_lookup ((LL_KEY) Handle);
+ /* if pid1 is zero, something's seriously wrong */
+ if (pid1 != 0)
+ {
+ DosWaitChild (DCWA_PROCESSTREE, DCWW_WAIT, &rc, &pid, pid1);
+ ll_delete ((LL_KEY) Handle);
+ }
+ return rc.codeTerminate == 0 ? rc.codeResult : -1;
+}
+
+
+#if DIAGNOSTIC
+void
+main ()
+{
+ FILE *fp1, *fp2, *fp3;
+ int c;
+
+ ll_print ();
+ fp1 = popen ("gcc --version", "r");
+ ll_print ();
+ fp2 = popen ("link386 /?", "r");
+ ll_print ();
+ fp3 = popen ("dir", "r");
+ ll_print ();
+
+ while ((c = getc (fp1)) != EOF)
+ printf ("%c", c);
+
+ while ((c = getc (fp2)) != EOF)
+ printf ("%c", c);
+
+ while ((c = getc (fp3)) != EOF)
+ printf ("%c", c);
+
+ pclose (fp1);
+ ll_print ();
+ pclose (fp2);
+ ll_print ();
+ pclose (fp3);
+ ll_print ();
+
+ return;
+}
+
+#endif /* DIAGNOSTIC */
diff --git a/gnu/usr.bin/cvs/os2/popen.h b/gnu/usr.bin/cvs/os2/popen.h
new file mode 100644
index 00000000000..8daf29eaef0
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/popen.h
@@ -0,0 +1,6 @@
+/* We roll our own popen()/pclose() in OS/2.
+ Thanks, Glenn Gribble! */
+
+FILE *popen (char *cmd, char *mode);
+int popenRW (char **cmd, int *pipes);
+int pclose (FILE *stream);
diff --git a/gnu/usr.bin/cvs/os2/porttcp.c b/gnu/usr.bin/cvs/os2/porttcp.c
new file mode 100644
index 00000000000..a64b511f82d
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/porttcp.c
@@ -0,0 +1,227 @@
+/****************************************************************
+**
+** PORTTCP.C - Support for portable TCP/IP
+**
+****************************************************************/
+
+#define TCPIP_IBM_NOHIDE
+#include <stdio.h>
+#include "tcpip.h"
+
+/*
+ * Common unknown error buffer
+ */
+static char ErrUnknownBuf[36];
+
+#ifndef SockStrError
+
+/****************************************************************
+ * Routine: SockStrError
+ * Returns: Pointer to static buffer
+ * Action : Convert SOCK_ERRNO into error text
+ ****************************************************************/
+
+const char *
+SockStrError(int SockErrno)
+{
+#if defined (TCPIP_IBM) && defined (IBM_CPP)
+ switch (SockErrno)
+ {
+ case SOCEPERM: return "Not owner";
+ case SOCESRCH: return "No such process";
+ case SOCEINTR: return "Interrupted system call";
+ case SOCENXIO: return "No such device or address";
+ case SOCEBADF: return "Bad file number";
+ case SOCEACCES: return "Permission denied";
+ case SOCEFAULT: return "Bad address";
+ case SOCEINVAL: return "Invalid argument";
+ case SOCEMFILE: return "Too many open files";
+ case SOCEPIPE: return "Broken pipe";
+ case SOCEOS2ERR: return "OS/2 Error";
+ case SOCEWOULDBLOCK: return "Operation would block";
+ case SOCEINPROGRESS: return "Operation now in progress";
+ case SOCEALREADY: return "Operation already in progress";
+ case SOCENOTSOCK: return "Socket operation on non-socket";
+ case SOCEDESTADDRREQ: return "Destination address required";
+ case SOCEMSGSIZE: return "Message too long";
+ case SOCEPROTOTYPE: return "Protocol wrong type for socket";
+ case SOCENOPROTOOPT: return "Protocol not available";
+ case SOCEPROTONOSUPPORT: return "Protocol not supported";
+ case SOCESOCKTNOSUPPORT: return "Socket type not supported";
+ case SOCEOPNOTSUPP: return "Operation not supported on socket";
+ case SOCEPFNOSUPPORT: return "Protocol family not supported";
+ case SOCEAFNOSUPPORT:
+ return "Address family not supported by protocol family";
+ case SOCEADDRINUSE: return "Address already in use";
+ case SOCEADDRNOTAVAIL: return "Can't assign requested address";
+ case SOCENETDOWN: return "Network is down";
+ case SOCENETUNREACH: return "Network is unreachable";
+ case SOCENETRESET: return "Network dropped connection on reset";
+ case SOCECONNABORTED: return "Software caused connection abort";
+ case SOCECONNRESET: return "Connection reset by peer";
+ case SOCENOBUFS: return "No buffer space available";
+ case SOCEISCONN: return "Socket is already connected";
+ case SOCENOTCONN: return "Socket is not connected";
+ case SOCESHUTDOWN: return "Can't send after socket shutdown";
+ case SOCETOOMANYREFS: return "Too many references: can't splice";
+ case SOCETIMEDOUT: return "Connection timed out";
+ case SOCECONNREFUSED: return "Connection refused";
+ case SOCELOOP: return "Too many levels of symbolic links";
+ case SOCENAMETOOLONG: return "File name too long";
+ case SOCEHOSTDOWN: return "Host is down";
+ case SOCEHOSTUNREACH: return "No route to host";
+ case SOCENOTEMPTY: return "Directory not empty";
+
+ default:
+ sprintf( ErrUnknownBuf, "SockStrErrno( %d ) unknown", SockErrno );
+ return ErrUnknownBuf;
+ }
+#else
+#error SockStrError not supported for this OS
+#endif
+}
+
+#endif /* SockStrError */
+
+
+/****************************************************************
+ * Routine: HostStrError
+ * Returns: Pointer to static buffer
+ * Action : Convert HOST_ERRNO into error text
+ ****************************************************************/
+
+const char *
+HostStrError(int HostErrno)
+{
+ switch (HostErrno)
+ {
+ case HOST_NOT_FOUND:
+ return "Host not found";
+ case TRY_AGAIN:
+ return "Host not found (suggest try again)";
+ case NO_RECOVERY:
+ return "Non-recoverable error: FORMERR, REFUSED, NOTIMP";
+ case NO_DATA:
+ return "No Data (valid name, but no record of requested type)";
+
+ default:
+ sprintf( ErrUnknownBuf, "HostStrErrno( %d ) unknown", HostErrno );
+ return ErrUnknownBuf;
+ }
+}
+
+
+#if defined( TCPIP_IBM )
+/****************************************************************
+ * Routine: IbmSockSend
+ * Returns: same as send
+ * Action : Do the right thing for IBM TCP/IP which includes
+ * the following two stupidities:
+ * 1) Never try to send more than 32K
+ * 2) Never pass a buffer that crosses a 64K boundary
+ * If Flags is non-zero, this function only attempts
+ * to deal with condition (1) above.
+ ****************************************************************/
+
+int
+IbmSockSend (int Socket, const void *Buffer, int Len, int Flags)
+{
+ int Sent, ToSend, TotalSent = 0;
+
+ const char *Tmp = Buffer;
+
+ /*
+ * If Flags have been passed in, the 64K boundary optimization
+ * can not be performed. For example, MSG_PEEK would not work
+ * correctly.
+ */
+ if (Flags)
+ return send (Socket, (char *) Buffer, min (0x7FFF, Len), Flags);
+
+ do
+ {
+ /* Never send across a 64K boundary */
+ ToSend = min (Len, (int) (0x10000 - (0xFFFF & (long) Tmp)));
+
+ /* Never send more than 32K */
+ if (ToSend > 0x7FFF)
+ ToSend = 0x7FFF;
+
+ Sent = send (Socket, (char *) Tmp, ToSend, 0);
+ if (Sent < 0)
+ {
+ if ((TotalSent > 0) && (SOCK_ERRNO == EWOULDBLOCK))
+ return TotalSent;
+ if (SOCK_ERRNO == EINTR)
+ continue;
+ return Sent;
+ }
+ if (Sent < ToSend)
+ return TotalSent + Sent;
+
+ Tmp += Sent;
+ TotalSent += Sent;
+ Len -= Sent;
+ } while (Len > 0);
+
+ return TotalSent;
+}
+
+
+
+/****************************************************************
+ * Routine: IbmSockRecv
+ * Returns: same as recv
+ * Action : Do the right thing for IBM TCP/IP which includes
+ * the following two stupidities:
+ * 1) Never try to recv more than 32K
+ * 2) Never pass a buffer that crosses a 64K boundary
+ * If Flags is non-zero, this function only attempts
+ * to deal with condition (1) above.
+ ****************************************************************/
+
+int
+IbmSockRecv (int Socket, const void *Buffer, int Len, int Flags)
+{
+ int Recvd, ToRecv, TotalRecvd = 0;
+
+ char *Tmp = Buffer;
+
+ /* If Flags have been passed in, the 64K boundary optimization
+ probably can not be performed. */
+
+ if (Flags)
+ return recv (Socket, Buffer, min (0x7FFF, Len), Flags);
+
+ do
+ {
+ /* Never send across a 64K boundary */
+ ToRecv = min( Len, (int)( 0x10000 - ( 0xFFFF & (long)Tmp )));
+
+ /* Never send more than 32K */
+ if( ToRecv > 0x7FFF )
+ ToRecv = 0x7FFF;
+
+ Recvd = recv (Socket, Tmp, ToRecv, 0);
+ if (Recvd <= 0)
+ {
+ if ((TotalRecvd > 0)
+ && (Recvd == 0 || (SOCK_ERRNO == EWOULDBLOCK )))
+ return TotalRecvd;
+ if (SOCK_ERRNO == EINTR)
+ continue;
+
+ return Recvd;
+ }
+ if (Recvd < ToRecv)
+ return TotalRecvd + Recvd;
+
+ Tmp += Recvd;
+ TotalRecvd += Recvd;
+ Len -= Recvd;
+ } while (Len > 0);
+
+ return TotalRecvd;
+}
+#endif /* defined( TCPIP_IBM ) */
+
diff --git a/gnu/usr.bin/cvs/os2/pwd.c b/gnu/usr.bin/cvs/os2/pwd.c
new file mode 100644
index 00000000000..5fb989b11ff
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/pwd.c
@@ -0,0 +1,205 @@
+/* pwd.c - Try to approximate UN*X's getuser...() functions under MS-DOS.
+ Copyright (C) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
+
+ 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 1, 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Header: /cvs/OpenBSD/src/gnu/usr.bin/cvs/os2/pwd.c,v 1.1.1.1 1996/01/30 00:19:38 tholo Exp $
+*/
+
+/* This 'implementation' is conjectured from the use of this functions in
+ the RCS and BASH distributions. Of course these functions don't do too
+ much useful things under MS-DOS, but using them avoids many "#ifdef
+ MSDOS" in ported UN*X code ... */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+
+static char *lookup_env (char **);
+
+/* where people might scribble their name into the environment ... */
+
+static char *login_strings[] =
+{
+ "LOGIN", "USER", "MAILNAME", (char *) 0
+};
+
+static char *group_strings[] =
+{
+ "GROUP", (char *) 0
+};
+
+
+static char *anonymous = "anonymous"; /* if all else fails ... */
+
+static char *home_dir = "."; /* we feel (no|every)where at home */
+static char *login_shell = "not cmd.exe!";
+
+static char *login = (char *) 0;/* cache the names here */
+static char *group = (char *) 0;
+
+static struct passwd pw; /* should we return a malloc()'d structure */
+static struct group gr; /* instead of pointers to static structures? */
+
+/* return something like a username in a (butchered!) passwd structure. */
+struct passwd *
+getpwuid (int uid)
+{
+ pw.pw_name = getlogin ();
+ pw.pw_dir = home_dir;
+ pw.pw_shell = login_shell;
+ pw.pw_uid = 0;
+
+ return &pw;
+}
+
+struct passwd *
+getpwnam (char *name)
+{
+ return (struct passwd *) 0;
+}
+
+/* return something like a groupname in a (butchered!) group structure. */
+struct group *
+getgrgid (int uid)
+{
+ gr.gr_name = getgr_name ();
+ gr.gr_gid = 0;
+
+ return &gr;
+}
+
+struct group *
+getgrnam (char *name)
+{
+ return (struct group *) 0;
+}
+
+/* return something like a username. */
+char *
+getlogin ()
+{
+ if (!login) /* have we been called before? */
+ login = lookup_env (login_strings);
+
+ if (!login) /* have we been successful? */
+ login = anonymous;
+
+ return login;
+}
+
+/* return something like a group. */
+char *
+getgr_name ()
+{
+ if (!group) /* have we been called before? */
+ group = lookup_env (group_strings);
+
+ if (!group) /* have we been successful? */
+ group = anonymous;
+
+ return group;
+}
+
+/* return something like a uid. */
+int
+getuid ()
+{
+ return 0; /* every user is a super user ... */
+}
+
+int
+getgid ()
+{
+ return 0;
+}
+
+int
+geteuid ()
+{
+ return 0;
+}
+
+int
+getegid ()
+{
+ return 0;
+}
+
+struct passwd *
+getpwent ()
+{
+ return (struct passwd *) 0;
+}
+
+void
+setpwent ()
+{
+}
+
+void
+endpwent ()
+{
+}
+
+void
+endgrent ()
+{
+}
+
+/* return groups. */
+int
+getgroups (int ngroups, int *groups)
+{
+ *groups = 0;
+ return 1;
+}
+
+/* lookup environment. */
+static char *
+lookup_env (char *table[])
+{
+ char *ptr;
+ char *entry;
+ size_t len;
+
+ while (*table && !(ptr = getenv (*table++))) ; /* scan table */
+
+ if (!ptr)
+ return (char *) 0;
+
+ len = strcspn (ptr, " \n\t\n\r"); /* any WS? */
+ if (!(entry = malloc (len + 1)))
+ {
+ fprintf (stderr, "Out of memory.\nStop.");
+ exit (-1);
+ }
+
+ strncpy (entry, ptr, len);
+ entry[len] = '\0';
+
+ return entry;
+
+}
+
+/*
+ * Local Variables:
+ * mode:C
+ * ChangeLog:ChangeLog
+ * compile-command:make
+ * End:
+ */
diff --git a/gnu/usr.bin/cvs/os2/pwd.h b/gnu/usr.bin/cvs/os2/pwd.h
new file mode 100644
index 00000000000..d139d30cc04
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/pwd.h
@@ -0,0 +1,77 @@
+/* pwd.h - Try to approximate UN*X's getuser...() functions under MS-DOS.
+ Copyright (C) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
+
+ 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 1, 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Header: /cvs/OpenBSD/src/gnu/usr.bin/cvs/os2/pwd.h,v 1.1.1.1 1996/01/30 00:19:37 tholo Exp $
+*/
+
+/* This 'implementation' is conjectured from the use of this functions in
+ the RCS and BASH distributions. Of course these functions don't do too
+ much useful things under MS-DOS, but using them avoids many "#ifdef
+ MSDOS" in ported UN*X code ... */
+
+#if 0
+/* This is taken care of in Windows-NT/config.h. */
+typedef int uid_t;
+#endif
+
+struct passwd
+{
+ /* ... */
+ /* missing stuff */
+ /* ... */
+ char *pw_name; /* login user id */
+ char *pw_dir; /* home directory */
+ char *pw_shell; /* login shell */
+ int pw_uid;
+};
+
+struct group
+{
+ /* ... */
+ /* missing stuff */
+ /* ... */
+ char *gr_name; /* login user id */
+ int gr_gid;
+};
+
+extern struct passwd *getpwuid (int);
+extern struct passwd *getpwnam (char *);
+extern struct group *getgrgid (int);
+extern struct group *getgrnam (char *);
+extern char *getlogin (void);
+extern char *getgr_name (void);
+extern int getuid (void);
+extern int getgid (void);
+extern int geteuid (void);
+extern int getegid (void);
+
+extern int *groups;
+extern int ngroups;
+extern int getgroups (int, int *);
+
+extern struct passwd *getpwent (void);
+extern void setpwent (void);
+extern void endpwent (void);
+extern void endgrent (void);
+
+/*
+ * Local Variables:
+ * mode:C
+ * ChangeLog:ChangeLog
+ * compile-command:make
+ * End:
+ */
diff --git a/gnu/usr.bin/cvs/os2/rcmd.c b/gnu/usr.bin/cvs/os2/rcmd.c
new file mode 100644
index 00000000000..36b17516dd5
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/rcmd.c
@@ -0,0 +1,66 @@
+/* rcmd.c --- execute a command on a remote host from OS/2
+ Karl Fogel <kfogel@cyclic.com> --- November 1995 */
+
+#include <io.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <errno.h>
+/* <sys/socket.h> wants `off_t': */
+#include <sys/types.h>
+/* This should get us ibmtcpip\include\sys\socket.h: */
+#include <sys/socket.h>
+#include <assert.h>
+
+#include "rcmd.h"
+
+void
+init_sockets ()
+{
+ int rc;
+
+ rc = sock_init ();
+ if (rc != 0)
+ {
+ fprintf (stderr, "sock_init() failed -- returned %d!\n", rc);
+ exit (1);
+ }
+}
+
+
+static int
+resolve_address (const char **ahost, struct sockaddr_in *sai)
+{
+ fprintf (stderr,
+ "Error: resolve_address() doesn't work.\n");
+ exit (1);
+}
+
+static int
+bind_and_connect (struct sockaddr_in *server_sai)
+{
+ fprintf (stderr,
+ "Error: bind_and_connect() doesn't work.\n");
+ exit (1);
+}
+
+static int
+rcmd_authenticate (int fd, char *locuser, char *remuser, char *command)
+{
+ fprintf (stderr,
+ "Error: rcmd_authenticate() doesn't work.\n");
+ exit (1);
+}
+
+int
+rcmd (const char **ahost,
+ unsigned short inport,
+ char *locuser,
+ char *remuser,
+ char *cmd,
+ int *fd2p)
+{
+ fprintf (stderr,
+ "Error: rcmd() doesn't work.\n");
+ exit (1);
+}
diff --git a/gnu/usr.bin/cvs/os2/rcmd.h b/gnu/usr.bin/cvs/os2/rcmd.h
new file mode 100644
index 00000000000..2bc915a36bd
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/rcmd.h
@@ -0,0 +1,30 @@
+/* rcmd.h --- interface to executing commands on remote hosts
+ Karl Fogel <kfogel@cyclic.com> --- November 1995 */
+
+/* Run the command CMD on the host *AHOST, and return a file descriptor for
+ a bidirectional stream socket connected to the command's standard input
+ and output.
+
+ rcmd looks up *AHOST using gethostbyname, and sets *AHOST to the host's
+ canonical name. If *AHOST is not found, rcmd returns -1.
+
+ rcmd connects to the remote host at TCP port INPORT. This should
+ probably be the "shell" service, port 514.
+
+ LOCUSER is the name of the user on the local machine, and REMUSER is
+ the name of the user on the remote machine; the remote machine uses this,
+ along with the source address of the TCP connection, to authenticate
+ the connection.
+
+ CMD is the command to execute. The remote host will tokenize it any way
+ it damn well pleases. Welcome to Unix.
+
+ FD2P is a feature we don't support, but there's no point in making mindless
+ deviations from the interface. Callers should always pass this argument
+ as zero. */
+extern int rcmd (const char **AHOST,
+ unsigned short INPORT,
+ char *LOCUSER,
+ char *REMUSER,
+ char *CMD,
+ int *fd2p);
diff --git a/gnu/usr.bin/cvs/os2/run.c b/gnu/usr.bin/cvs/os2/run.c
new file mode 100644
index 00000000000..358812b3a1f
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/run.c
@@ -0,0 +1,602 @@
+/* run.c --- routines for executing subprocesses under OS/2.
+
+ 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "cvs.h"
+
+#define INCL_DOSQUEUES
+#define INCL_DOSPROCESS
+#define INCL_DOSSESMGR
+#include <os2.h>
+#include <process.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <io.h>
+
+#define STDIN 0
+#define STDOUT 1
+#define STDERR 2
+
+static void run_add_arg PROTO((const char *s));
+static void run_init_prog PROTO((void));
+
+extern char *strtok ();
+
+/*
+ * To exec a program under CVS, first call run_setup() to setup any initial
+ * arguments. The options to run_setup are essentially like printf(). The
+ * arguments will be parsed into whitespace separated words and added to the
+ * global run_argv list.
+ *
+ * Then, optionally call run_arg() for each additional argument that you'd like
+ * to pass to the executed program.
+ *
+ * Finally, call run_exec() to execute the program with the specified
+ * arguments.
+ * The execvp() syscall will be used, so that the PATH is searched correctly.
+ * File redirections can be performed in the call to run_exec().
+ */
+static char *run_prog;
+static char **run_argv;
+static int run_argc;
+static int run_argc_allocated;
+
+void
+run_setup (const char *fmt,...)
+{
+ va_list args;
+ char *cp;
+ int i;
+
+ run_init_prog ();
+
+ /* clean out any malloc'ed values from run_argv */
+ for (i = 0; i < run_argc; i++)
+ {
+ if (run_argv[i])
+ {
+ free (run_argv[i]);
+ run_argv[i] = (char *) 0;
+ }
+ }
+ run_argc = 0;
+
+ /* process the varargs into run_prog */
+ va_start (args, fmt);
+ (void) vsprintf (run_prog, fmt, args);
+ va_end (args);
+
+ /* put each word into run_argv, allocating it as we go */
+ for (cp = strtok (run_prog, " \t"); cp; cp = strtok ((char *) NULL, " \t"))
+ run_add_arg (cp);
+}
+
+void
+run_arg (s)
+ const char *s;
+{
+ run_add_arg (s);
+}
+
+void
+run_args (const char *fmt,...)
+{
+ va_list args;
+
+ run_init_prog ();
+
+ /* process the varargs into run_prog */
+ va_start (args, fmt);
+ (void) vsprintf (run_prog, fmt, args);
+ va_end (args);
+
+ /* and add the (single) argument to the run_argv list */
+ run_add_arg (run_prog);
+}
+
+/* Return a malloc'd copy of s, with double quotes around it. */
+static char *
+quote (const char *s)
+{
+ size_t s_len = strlen (s);
+ char *copy = xmalloc (s_len + 3);
+ char *scan = copy;
+
+ *scan++ = '"';
+ strcpy (scan, s);
+ scan += s_len;
+ *scan++ = '"';
+ *scan++ = '\0';
+
+ return copy;
+}
+
+static void
+run_add_arg (s)
+ const char *s;
+{
+ /* allocate more argv entries if we've run out */
+ if (run_argc >= run_argc_allocated)
+ {
+ run_argc_allocated += 50;
+ run_argv = (char **) xrealloc ((char *) run_argv,
+ run_argc_allocated * sizeof (char **));
+ }
+
+ if (s)
+ {
+ run_argv[run_argc] = (run_argc ? quote (s) : xstrdup (s));
+ run_argc++;
+ }
+ else
+ /* not post-incremented on purpose! */
+ run_argv[run_argc] = (char *) 0;
+}
+
+static void
+run_init_prog ()
+{
+ /* make sure that run_prog is allocated once */
+ if (run_prog == (char *) 0)
+ run_prog = xmalloc (10 * 1024); /* 10K of args for _setup and _arg */
+}
+
+
+int
+run_exec (stin, stout, sterr, flags)
+ char *stin;
+ char *stout;
+ char *sterr;
+ int flags;
+{
+ int shin, shout, sherr;
+ int sain, saout, saerr; /* saved handles */
+ int mode_out, mode_err;
+ int status = -1;
+ int rerrno = 0;
+ int rval = -1;
+ void (*old_sigint) (int);
+
+ if (trace) /* if in trace mode */
+ {
+ (void) fprintf (stderr, "-> system(");
+ run_print (stderr);
+ (void) fprintf (stderr, ")\n");
+ }
+ if (noexec && (flags & RUN_REALLY) == 0) /* if in noexec mode */
+ return (0);
+
+ /*
+ * start the engine and take off
+ */
+
+ /* make sure that we are null terminated, since we didn't calloc */
+ run_add_arg ((char *) 0);
+
+ /* setup default file descriptor numbers */
+ shin = 0;
+ shout = 1;
+ sherr = 2;
+
+ /* set the file modes for stdout and stderr */
+ mode_out = mode_err = O_WRONLY | O_CREAT;
+ mode_out |= ((flags & RUN_STDOUT_APPEND) ? O_APPEND : O_TRUNC);
+ mode_err |= ((flags & RUN_STDERR_APPEND) ? O_APPEND : O_TRUNC);
+
+ /* open the files as required, shXX are shadows of stdin... */
+ if (stin && (shin = open (stin, O_RDONLY)) == -1)
+ {
+ rerrno = errno;
+ error (0, errno, "cannot open %s for reading (prog %s)",
+ stin, run_argv[0]);
+ goto out0;
+ }
+ if (stout && (shout = open (stout, mode_out, 0666)) == -1)
+ {
+ rerrno = errno;
+ error (0, errno, "cannot open %s for writing (prog %s)",
+ stout, run_argv[0]);
+ goto out1;
+ }
+ if (sterr && (flags & RUN_COMBINED) == 0)
+ {
+ if ((sherr = open (sterr, mode_err, 0666)) == -1)
+ {
+ rerrno = errno;
+ error (0, errno, "cannot open %s for writing (prog %s)",
+ sterr, run_argv[0]);
+ goto out2;
+ }
+ }
+ /* now save the standard handles */
+ sain = saout = saerr = -1;
+ sain = dup( 0); /* dup stdin */
+ saout = dup( 1); /* dup stdout */
+ saerr = dup( 2); /* dup stderr */
+
+ /* the new handles will be dup'd to the standard handles
+ * for the spawn.
+ */
+
+ if (shin != 0)
+ {
+ (void) dup2 (shin, 0);
+ (void) close (shin);
+ }
+ if (shout != 1)
+ {
+ (void) dup2 (shout, 1);
+ (void) close (shout);
+ }
+ if (flags & RUN_COMBINED)
+ (void) dup2 (1, 2);
+ else if (sherr != 2)
+ {
+ (void) dup2 (sherr, 2);
+ (void) close (sherr);
+ }
+
+ /* Ignore signals while we're running this. */
+ old_sigint = signal (SIGINT, SIG_IGN);
+
+ /* dup'ing is done. try to run it now */
+ rval = spawnvp ( P_WAIT, run_argv[0], run_argv);
+
+ /* Restore signal handling. */
+ signal (SIGINT, old_sigint);
+
+ /* restore the original file handles */
+ if (sain != -1) {
+ (void) dup2( sain, 0); /* re-connect stdin */
+ (void) close( sain);
+ }
+ if (saout != -1) {
+ (void) dup2( saout, 1); /* re-connect stdout */
+ (void) close( saout);
+ }
+ if (saerr != -1) {
+ (void) dup2( saerr, 2); /* re-connect stderr */
+ (void) close( saerr);
+ }
+
+ /* Recognize the return code for a failed subprocess. */
+ if (rval == -1)
+ return 2;
+ else
+ return rval; /* return child's exit status */
+
+ /* error cases */
+ /* cleanup the open file descriptors */
+ out2:
+ if (stout)
+ (void) close (shout);
+ out1:
+ if (stin)
+ (void) close (shin);
+
+ out0:
+ if (rerrno)
+ errno = rerrno;
+ return (status);
+}
+
+
+void
+run_print (fp)
+ FILE *fp;
+{
+ int i;
+
+ for (i = 0; i < run_argc; i++)
+ {
+ (void) fprintf (fp, "'%s'", run_argv[i]);
+ if (i != run_argc - 1)
+ (void) fprintf (fp, " ");
+ }
+}
+
+static char *
+requote (const char *cmd)
+{
+ char *requoted = xmalloc (strlen (cmd) + 1);
+ char *p = requoted;
+
+ strcpy (requoted, cmd);
+ while ((p = strchr (p, '\'')) != NULL)
+ {
+ *p++ = '"';
+ }
+
+ return requoted;
+}
+
+FILE *
+Popen (cmd, mode)
+ const char *cmd;
+ const char *mode;
+{
+ if (trace)
+#ifdef SERVER_SUPPORT
+ (void) fprintf (stderr, "%c-> Popen(%s,%s)\n",
+ (server_active) ? 'S' : ' ', cmd, mode);
+#else
+ (void) fprintf (stderr, "-> Popen(%s,%s)\n", cmd, mode);
+#endif
+
+ if (noexec)
+ return (NULL);
+
+ /* If the command string uses single quotes, turn them into
+ double quotes. */
+ {
+ char *requoted = requote (cmd);
+ FILE *result = popen (requoted, mode);
+ free (requoted);
+ return result;
+ }
+}
+
+
+/* Running children with pipes connected to them. */
+
+/* Create a pipe. Set READWRITE[0] to its reading end, and
+ READWRITE[1] to its writing end. */
+
+static int
+my_pipe (int *readwrite)
+{
+ fprintf (stderr,
+ "Error: my_pipe() is unimplemented.\n");
+ exit (1);
+}
+
+
+/* Create a child process running COMMAND with IN as its standard input,
+ and OUT as its standard output. Return a handle to the child, or
+ INVALID_HANDLE_VALUE. */
+static int
+start_child (char *command, int in, int out)
+{
+ fprintf (stderr,
+ "Error: start_child() is unimplemented.\n");
+ exit (1);
+}
+
+
+/* Given an array of arguments that one might pass to spawnv,
+ construct a command line that one might pass to CreateProcess.
+ Try to quote things appropriately. */
+static char *
+build_command (char **argv)
+{
+ int len;
+
+ /* Compute the total length the command will have. */
+ {
+ int i;
+
+ len = 0;
+ for (i = 0; argv[i]; i++)
+ {
+ char *p;
+
+ len += 2; /* for the double quotes */
+
+ for (p = argv[i]; *p; p++)
+ {
+ if (*p == '"')
+ len += 2;
+ else
+ len++;
+ }
+ }
+ len++; /* for the space or the '\0' */
+ }
+
+ {
+ char *command = (char *) malloc (len);
+ int i;
+ char *p;
+
+ if (! command)
+ {
+ errno = ENOMEM;
+ return command;
+ }
+
+ p = command;
+ /* copy each element of argv to command, putting each command
+ in double quotes, and backslashing any quotes that appear
+ within an argument. */
+ for (i = 0; argv[i]; i++)
+ {
+ char *a;
+ *p++ = '"';
+ for (a = argv[i]; *a; a++)
+ {
+ if (*a == '"')
+ *p++ = '\\', *p++ = '"';
+ else
+ *p++ = *a;
+ }
+ *p++ = '"';
+ *p++ = ' ';
+ }
+ p[-1] = '\0';
+
+ return command;
+ }
+}
+
+
+/* Create an asynchronous child process executing ARGV,
+ with its standard input and output connected to the
+ parent with pipes. Set *TO to the file descriptor on
+ which one writes data for the child; set *FROM to
+ the file descriptor from which one reads data from the child.
+ Return the handle of the child process (this is what
+ _cwait and waitpid expect). */
+int
+piped_child (char **argv, int *to, int *from)
+{
+ fprintf (stderr,
+ "Error: piped_child() is unimplemented.\n");
+ exit (1);
+}
+
+/*
+ * dir = 0 : main proc writes to new proc, which writes to oldfd
+ * dir = 1 : main proc reads from new proc, which reads from oldfd
+ *
+ * If this returns at all, then it was successful and the return value
+ * is a file descriptor; else it errors and exits.
+ */
+int
+filter_stream_through_program (int oldfd, int dir,
+ char **prog, int *pidp)
+{
+ int newfd; /* Gets set to one end of the pipe and returned. */
+ HFILE from, to;
+ HFILE Old0 = -1, Old1 = -1, Old2 = -1, Tmp;
+
+ if (DosCreatePipe (&from, &to, 4096))
+ return FALSE;
+
+ /* Save std{in,out,err} */
+ DosDupHandle (STDIN, &Old0);
+ DosSetFHState (Old1, OPEN_FLAGS_NOINHERIT);
+ DosDupHandle (STDOUT, &Old1);
+ DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
+ DosDupHandle (STDERR, &Old2);
+ DosSetFHState (Old2, OPEN_FLAGS_NOINHERIT);
+
+ /* Redirect std{in,out,err} */
+ if (dir) /* Who goes where? */
+ {
+ Tmp = STDIN;
+ DosDupHandle (oldfd, &Tmp);
+ Tmp = STDOUT;
+ DosDupHandle (to, &Tmp);
+ Tmp = STDERR;
+ DosDupHandle (to, &Tmp);
+
+ newfd = from;
+ _setmode (newfd, O_BINARY);
+
+ DosClose (oldfd);
+ DosClose (to);
+ DosSetFHState (from, OPEN_FLAGS_NOINHERIT);
+ }
+ else
+ {
+ Tmp = STDIN;
+ DosDupHandle (from, &Tmp);
+ Tmp = STDOUT;
+ DosDupHandle (oldfd, &Tmp);
+ Tmp = STDERR;
+ DosDupHandle (oldfd, &Tmp);
+
+ newfd = to;
+ _setmode (newfd, O_BINARY);
+
+ DosClose (oldfd);
+ DosClose (from);
+ DosSetFHState (to, OPEN_FLAGS_NOINHERIT);
+ }
+
+ /* Spawn we now our hoary brood. */
+ *pidp = spawnvp (P_NOWAIT, prog[0], prog);
+
+ /* Restore std{in,out,err} */
+ Tmp = STDIN;
+ DosDupHandle (Old0, &Tmp);
+ DosClose (Old0);
+ Tmp = STDOUT;
+ DosDupHandle (Old1, &Tmp);
+ DosClose (Old1);
+ Tmp = STDERR;
+ DosDupHandle (Old2, &Tmp);
+ DosClose (Old2);
+
+ if(*pidp < 0)
+ {
+ DosClose (from);
+ DosClose (to);
+ error (1, 0, "error spawning %s", prog[0]);
+ }
+
+ return newfd;
+}
+
+
+int
+pipe (int *filedesc)
+{
+ /* todo: actually, we can use DosCreatePipe(). Fix this. */
+ fprintf (stderr,
+ "Error: pipe() should not have been called in client.\n");
+ exit (1);
+}
+
+
+void
+close_on_exec (int fd)
+{
+ /* Just does nothing for now... */
+
+ /* Actually, we probably *can* implement this one. Let's see... */
+ /* Nope. OS/2 has <fcntl.h>, but no fcntl() ! Wow. */
+ /* Well, I'll leave this stuff in for future reference. */
+}
+
+
+/* Actually, we #define sleep() in config.h now. */
+#ifndef sleep
+unsigned int
+sleep (unsigned int seconds)
+{
+ /* I don't want to interfere with alarm signals, so I'm going to do
+ this the nasty way. */
+
+ time_t base;
+ time_t tick;
+ int i;
+
+ /* Init. */
+ time (&base);
+ time (&tick);
+
+ /* Loop until time has passed. */
+ while (difftime (tick, base) < seconds)
+ {
+ /* This might be more civilized than calling time over and over
+ again. */
+ for (i = 0; i < 10000; i++)
+ ;
+ time (&tick);
+ }
+
+ return 0;
+}
+#endif /* sleep */
diff --git a/gnu/usr.bin/cvs/os2/strippath.c b/gnu/usr.bin/cvs/os2/strippath.c
new file mode 100644
index 00000000000..8a61a1ed393
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/strippath.c
@@ -0,0 +1,60 @@
+/* strippath.c -- remove unnecessary components from a path specifier
+ Copyright (C) 1992 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <string.h>
+
+static void remove_component(char *beginc, char *endc);
+void strip_trailing_slashes(char *path);
+
+/* Remove unnecessary components from PATH. */
+
+void
+strip_path (path)
+ char *path;
+{
+ int stripped = 0;
+ char *cp, *slash;
+
+ for (cp = path; *(slash = cp + strcspn (cp, "/\\")) != '\0'; cp = slash)
+ {
+ *slash = '\0';
+ if ((!*cp && (cp != path || stripped)) ||
+ strcmp(cp, ".") == 0 || strcmp(cp, "/") == 0)
+ {
+ stripped = 1;
+ remove_component(cp, slash);
+ slash = cp;
+ }
+ else
+ {
+ *slash++ = '/';
+ }
+ }
+ strip_trailing_slashes(path);
+}
+
+/* Remove the component delimited by BEGINC and ENDC from the path */
+
+static void
+remove_component (beginc, endc)
+ char *beginc;
+ char *endc;
+{
+ for (endc++; *endc; endc++)
+ *beginc++ = *endc;
+ *beginc = '\0';
+}
diff --git a/gnu/usr.bin/cvs/os2/stripslash.c b/gnu/usr.bin/cvs/os2/stripslash.c
new file mode 100644
index 00000000000..629dad9393d
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/stripslash.c
@@ -0,0 +1,31 @@
+/* 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.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#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/os2/tcpip.h b/gnu/usr.bin/cvs/os2/tcpip.h
new file mode 100644
index 00000000000..4d19448650a
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/tcpip.h
@@ -0,0 +1,107 @@
+/****************************************************************
+ *
+ * TCPIP.H - Portable TCP/IP header file
+ *
+ * TCP/IP on OS/2 is an add-on and thus is not fully integrated
+ * with the operating system. To ensure portability, follow
+ * these rules:
+ *
+ * * Always call SockInit() at the beginning of your program
+ * and check that it returns TRUE.
+ *
+ * * Use SockSend() & SockRecv() instead of read(), write(),
+ * send(), or recv() when working with sockets.
+ *
+ * * Use SockClose() instead of close() with sockets.
+ *
+ * * Use SOCK_ERRNO when using functions that use or return
+ * sockets, such as SockSend() or accept().
+ *
+ * * Use HOST_ERRNO when using gethostbyname() or gethostbyaddr()
+ * functions.
+ *
+ * * As far as I can tell, getservbyname() and related functions
+ * never set any error variable.
+ *
+ * * Use SockStrError() & HostStrError() to convert SOCK_ERRNO
+ * and HOST_ERRNO to error strings.
+ *
+ * * In .MAK files, include $(TCPIP_MAK) & use $(TCPIPLIB)
+ * when linking applications using TCP/IP.
+ *
+ ****************************************************************/
+
+#if !defined( IN_TCPIP_H )
+#define IN_TCPIP_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+
+#if defined( TCPIP_IBM )
+# include <types.h>
+# if !defined( TCPIP_IBM_NOHIDE )
+# define send IbmSockSend
+# define recv IbmSockRecv
+# endif
+#endif
+
+#if defined( TCPIP_IBM )
+# define BSD_SELECT
+# include <sys/select.h>
+# include <sys/time.h>
+# include <nerrno.h>
+# include <utils.h>
+# if defined( MICROSOFT )
+# define SOCK_ERRNO (tcperrno())
+# else
+# define SOCK_ERRNO (sock_errno())
+# endif
+# define HOST_ERRNO (h_errno)
+# define SockClose(S) soclose(S)
+# define SockInit() (!sock_init())
+# define SockSend IbmSockSend
+# define SockRecv IbmSockRecv
+
+const char *HostStrError(int HostErrno);
+const char *SockStrError(int SockErrno);
+
+int IbmSockSend (int Socket, const void *Buffer, int Len, int Flags);
+int IbmSockRecv (int Socket, const void *Buffer, int Len, int Flags);
+
+#if !defined( h_errno )
+extern int h_errno; /* IBM forgot to declare this in current header files */
+#endif
+
+#elif defined( __unix )
+# if defined( sgi ) /* SGI incorrectly defines FD_ZERO in sys/select.h */
+# include <bstring.h>
+# endif
+# if defined( sunos )
+extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+# else
+# include <sys/select.h>
+# endif
+# include <sys/time.h>
+# include <errno.h>
+# include <arpa/inet.h>
+# define SOCK_ERRNO errno
+# define HOST_ERRNO h_errno
+# define SockClose(S) close(S)
+# define SockInit() TRUE
+# define SockSend send
+# define SockRecv recv
+# define SockStrError(E) strerror(E)
+
+const char *HostStrError( int HostErrno );
+
+#else
+# error Undefined version of TCP/IP specified
+
+#endif
+
+#endif
diff --git a/gnu/usr.bin/cvs/os2/test-makefile b/gnu/usr.bin/cvs/os2/test-makefile
new file mode 100644
index 00000000000..d6179ee386e
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/test-makefile
@@ -0,0 +1,40 @@
+# I use this for single compilation while porting; once the port is
+# done it can be removed.
+
+THIS_BASENAME = ../src/add
+
+CC = icc
+
+LIB = s:\ibmcpp\lib;s:\toolkt21\os2lib;
+CINC = -Is:/ibmcpp/include -Is:/toolkt21/c/os2h
+CFLAGS = -C+
+CFLAGS += -W3 -Wpro+rea+tru+use+ -Ti+ -Ss+ -Gd+ -Gm+ -G4 -Q+ -Sm ${CINC}
+CFLAGS += -DIBM_CPP -DHAVE_CONFIG_H
+
+# translation of most important CFLAGS -- others are trivial
+# ICC sez -C+ -W3 -Ti+ ${CINC}
+# GCC sez -c -Wall -g ${CINC}
+
+# "-I../os2" below ought to be equivalent to "-I."
+CFLAGS += -I../os2 -I../lib -I../src
+
+# Preprocesses to stdout.
+# CFLAGS += -Pd+
+
+# TCP/IP stuff
+TCPIPLIB = s:\ibmtcpip\lib\tcp32dll.lib s:\ibmtcpip\lib\so32dll.lib porttcp.obj
+
+# We probably don't need these.
+# RPCLIB = s:\ibmtcpip\lib\rpc32dll.lib
+# FTPLIB = s:\ibmtcpip\lib\ftpapi.lib
+
+CFLAGS += -DTCPIP_IBM -Is:\ibmtcpip\include
+
+all: ${THIS_BASENAME}.obj
+# all: ${THIS_BASENAME}.exe
+
+${THIS_BASENAME}.obj: ${THIS_BASENAME}.c
+ ${CC} ${CFLAGS} /Fo${THIS_BASENAME}.obj ${THIS_BASENAME}.c
+
+${THIS_BASENAME}.exe: ${THIS_BASENAME}.c
+ ${CC} ${CFLAGS} /Fe${THIS_BASENAME}.exe ${THIS_BASENAME}.c
diff --git a/gnu/usr.bin/cvs/os2/waitpid.c b/gnu/usr.bin/cvs/os2/waitpid.c
new file mode 100644
index 00000000000..2b64f5dcce2
--- /dev/null
+++ b/gnu/usr.bin/cvs/os2/waitpid.c
@@ -0,0 +1,36 @@
+/* waitpid.c --- waiting for process termination, under OS/2
+ Karl Fogel <kfogel@cyclic.com> --- November 1995 */
+
+#include <assert.h>
+#include <stdio.h>
+#include <process.h>
+#include <errno.h>
+
+#include "config.h"
+
+/* Wait for the process PID to exit. Put the return status in *statusp.
+ OPTIONS is not supported yet under OS/2. We hope it's always zero. */
+pid_t waitpid (pid, statusp, options)
+ pid_t pid;
+ int *statusp;
+ int options;
+{
+ pid_t rc;
+
+ /* We don't know how to deal with any options yet. */
+ assert (options == 0);
+
+ rc = _cwait (statusp, pid, WAIT_CHILD);
+
+ if (rc == -1)
+ {
+ if (errno == ECHILD)
+ return pid;
+ else
+ return -1;
+ }
+ else if (rc == pid)
+ return pid;
+ else
+ return -1;
+}