Just like on rtapelib, the vms vfork() does not really fork, it sets up
a longjump, and the exec* command starts up the child.
VMS C library maps pipes to a device known as a mailbox, and unlike
pipes, mailboxes are small, limited to 65535 bytes. So for the output
pipe, in external module, a special routine that buffers the mailbox
into virtual memory was added. It is in a separate module.
The file descriptor for that pipe is also stored in an external routine
because special action to signal EOF is needed when it is closed. The
routines that I implemented to allow open() and close() to work also
signal that EOF.
Tar 1.19 is now working on VMS as well as I can test it.
In addition to the supplied files, I needed to add the following files.
The gnv$*.c_first and gnv$first_include.h files are pre-pended to the
files of the same name before the compile is done. This allows me to
make vms specific modifications, and also to manipulate compiler options.
Along with other things, these implement the fdopen() and dirfd()
routine that gnulib wants to see.
The gnv$*.opt files specify additional modules and options to be linked in.
The setup_tar_build.com sets up VMS symbols for the subsequent build.
The vms_configure.sh is the parameters needed to get the configure
script to run, and the gnv$conftest.c_first is modifications to the
conftest.c files to get the configure tests to either pretend that VMS
supports a required feature, or corrects the test to actually produce
the correct results on VMS.
The make*.sh files set some VMS specific environment variables to make
the GNV port of bash and CC/LD emulation work more like the UNIX build
environment expects.
The [vms_common] modules are common to multiple projects, two modules
are used for gnu tar, one is a pre-init module that runs before main()
to put the VMS CRTL into a more UNIX like mode, and the other is a
routine to make VMS mailboxes contain more data like a UNIX pipe. The
vms_common.mms is makefile that is VMS specific.
So do you want to look over the gnv$* and such to integrate into the gnu
tar source, or do you prefer to leave them separate?
I still have to write the script that puts the VMS gnu tar kit into a
installable kit.
Directory LCL_ROOT:[tar-1^.19]
setup_tar_build.com;2
EAGLE> dir [...]gnv$*.*;
Directory LCL_ROOT:[tar-1^.19]
gnv$conftest.c_first;19
Total of 1 file.
Directory LCL_ROOT:[tar-1^.19.lib]
gnv$argmatch.c_first;3 gnv$argp-fmtstream.c_first;4
gnv$argp-help.c_first;3 gnv$error.c_first;3
gnv$fchdir.c_first;69
gnv$getcwd.c_first;8 gnv$getdate.c_first;3
gnv$rtapelib.c_first;6 gnv$savedir.c_first;1
gnv$strtoimax.c_first;2 gnv$strtoumax.c_first;1
gnv$xstrtoumax.c_first;3
Total of 12 files.
Directory LCL_ROOT:[tar-1^.19.lib.uniwidth]
gnv$first_include.h;1
Total of 1 file.
Directory LCL_ROOT:[tar-1^.19.src]
gnv$buffer.c_first;5 gnv$compare.c_first;2
gnv$create.c_first;9 gnv$extract.c_first;32
gnv$incremen.c_first;6 gnv$list.c_first;3
gnv$misc.c_first;7
gnv$names.c_first;9 gnv$sparse.c_first;3
gnv$system.c_first;9
gnv$tar.c_first;6 gnv$tar.opt;3 gnv$update.c_first;2
gnv$xheader.c_first;3
Total of 14 files.
Directory LCL_ROOT:[tar-1^.19.tests]
gnv$genfile.c_first;5 gnv$genfile.opt;1
Total of 2 files.
EAGLE> dir [...]make_tar*.sh;,vms_configure.sh;
Directory LCL_ROOT:[tar-1^.19]
make_tar.sh;13 make_tar_debug.sh;6 make_tar_install.sh;1
vms_configure.sh;11
Directory LCL_ROOT:[vms_common]
vms_crtl_init.c;13 vms_vm_pipe.c;2 vms_common.mms;15
-John
[EMAIL PROTECTED]
Personal Opinion Only
--- /src_root/tar-1.19/src/system.c Sun Aug 26 03:56:55 2007
+++ /lcl_root/tar-1.19/src/system.c Mon Mar 31 23:06:53 2008
@@ -202,6 +202,10 @@
}
}
+#ifdef __VMS
+#define xfork vfork
+#endif
+
void
sys_spawn_shell (void)
{
@@ -313,6 +317,7 @@
pid_t child_pid;
int wait_status;
+#ifndef __VMS
xpipe (parent_pipe);
child_pid = xfork ();
@@ -331,6 +336,7 @@
xdup2 (parent_pipe[PREAD], STDIN_FILENO);
xclose (parent_pipe[PWRITE]);
+#endif
/* Check if we need a grandchild tar. This happens only if either:
a) the file is to be accessed by rmt: compressor doesn't know how;
@@ -356,12 +362,47 @@
errno = saved_errno;
open_fatal (archive_name_array[0]);
}
+#ifdef __VMS
+ {
+ int save_stdout;
+
+ /* VMS is always in the Parent process on both returns on vfork() */
+ /* So need to save what ever the STDOUT fileno is using and restore */
+ save_stdout = dup(STDOUT_FILENO);
+
+ /* VMS pipes too small, so create a better one */
+ vms_fifo_write_pipe(parent_pipe);
+
+ child_pid = vfork ();
+ if (child_pid > 0)
+ {
+ /* The parent tar is still here! Just clean up. */
+
+ archive = parent_pipe[PWRITE];
+
+ /* Need to handle the close special */
+ vms_save_fd_info(archive, NULL, NULL, 1, 0);
+
+ xclose (parent_pipe[PREAD]);
+ xdup2(save_stdout, STDOUT_FILENO);
+ return child_pid;
+ }
+ decc$set_child_standard_streams(parent_pipe[PREAD], -1, -1);
+ }
+#endif
xdup2 (archive, STDOUT_FILENO);
}
execlp (use_compress_program_option, use_compress_program_option, NULL);
exec_fatal (use_compress_program_option);
}
+#ifdef __VMS
+ /* VMS does not have a true fork, so no possiblity of grandchildren */
+ /* Getting here means we did not fork or open the archive */
+ archive = -1;
+ return -1;
+#else
+
/* We do need a grandchild tar. */
xpipe (child_pipe);
@@ -462,6 +503,7 @@
exit_status = WEXITSTATUS (wait_status);
exit (exit_status);
+#endif
}
/* Set ARCHIVE for uncompressing, then reading an archive. */
@@ -474,6 +516,7 @@
pid_t child_pid;
int wait_status;
+#ifndef __VMS
xpipe (parent_pipe);
child_pid = xfork ();
@@ -492,6 +535,7 @@
xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
xclose (parent_pipe[PREAD]);
+#endif
/* Check if we need a grandchild tar. This happens only if either:
a) we're reading stdin: to force unblocking;
@@ -508,6 +552,27 @@
archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW);
if (archive < 0)
open_fatal (archive_name_array[0]);
+
+#ifdef __VMS
+ {
+ int save_stdin;
+
+ save_stdin = dup(STDIN_FILENO);
+ xpipe (parent_pipe);
+ decc$set_child_standard_streams(-1, parent_pipe[PWRITE], -1);
+ child_pid = vfork();
+ /* VMS is aways the parent on return */
+
+ if (child_pid > 0)
+ {
+ /* The parent tar is still here! Just clean up. */
+ archive = parent_pipe[PREAD];
+ xclose (parent_pipe[PWRITE]);
+ xdup2(save_stdin, STDIN_FILENO);
+ return child_pid;
+ }
+ }
+#endif
xdup2 (archive, STDIN_FILENO);
execlp (use_compress_program_option, use_compress_program_option,
"-d", (char *) 0);
@@ -516,6 +581,13 @@
/* We do need a grandchild tar. */
+#ifdef __VMS
+ /* VMS does not have a real fork() so no possibility of a grandchild */
+ /* Getting here means we did not vfork(). or open the archive */
+ archive = -1;
+ return -1;
+#else
+
xpipe (child_pipe);
grandchild_pid = xfork ();
@@ -600,6 +672,7 @@
exit_status = WEXITSTATUS (wait_status);
exit (exit_status);
+#endif
}