$! ------------------ CUT HERE ----------------------- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))' $! $! This archive created by VMS_SHARE Version 7.2-007 22-FEB-1990 $! On 24-AUG-1990 08:53:34.18 By user TP $! $! This VMS_SHARE Written by: $! Andy Harper, Kings College London UK $! $! Acknowledgements to: $! James Gray - Original VMS_SHARE $! Michael Bednarek - Original Concept and implementation $! $!+ THIS PACKAGE DISTRIBUTED IN 4 PARTS, TO KEEP EACH PART $! BELOW 98 BLOCKS $! $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER $! AND EXECUTE AS A COMMAND PROCEDURE ( @name ) $! $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING: $! 1. [.DOC]AAAREADME.TXT;1 $! 2. [.DOC]DIFF.DOC;1 $! 3. [.DOC]HOW-TO-DIFF.DOC;1 $! 4. [.DOC]PATCH.DOC;1 $! 5. [.SRC]ARGPROC.C;1 $! 6. [.SRC]BUILD_DIFF.COM;2 $! 7. [.SRC]BUILD_PATCH.COM;3 $! 8. [.SRC]COMMON.H;1 $! 9. [.SRC]CONFIG.H;1 $! 10. [.SRC]DIFF.C;1 $! 11. [.SRC]EXTERN.H;1 $! 12. [.SRC]INCLUDES.H;1 $! 13. [.SRC]INP.C;1 $! 14. [.SRC]INP.H;1 $! 15. [.SRC]INTERN.H;1 $! 16. [.SRC]PATCH.C;1 $! 17. [.SRC]PATCHLEVEL.H;1 $! 18. [.SRC]PCH.C;1 $! 19. [.SRC]PCH.H;1 $! 20. [.SRC]UTIL.C;1 $! 21. [.SRC]UTIL.H;1 $! 22. [.SRC]VERSION.C;1 $! 23. [.SRC]VERSION.H;1 $! $set="set" $set symbol/scope=(nolocal,noglobal) $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID")) $e="write sys$error ""%UNPACK"", " $w="write sys$output ""%UNPACK"", " $ if f$trnlnm("SHARE_LOG") then $ w = "!" $ ve=f$getsyi("version") $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START $ e "-E-OLDVER, Must run at least VMS 4.4" $ v=f$verify(v) $ exit 44 $UNPACK: SUBROUTINE ! P1=filename, P2=checksum $ if f$search(P1) .eqs. "" then $ goto file_absent $ e "-W-EXISTS, File ''P1' exists. Skipped." $ delete 'f'* $ exit $file_absent: $ if f$parse(P1) .nes. "" then $ goto dirok $ dn=f$parse(P1,,,"DIRECTORY") $ w "-I-CREDIR, Creating directory ''dn'." $ create/dir 'dn' $ if $status then $ goto dirok $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped." $ delete 'f'* $ exit $dirok: $ w "-I-PROCESS, Processing file ''P1'." $ if .not. f$verify() then $ define/user sys$output nl: $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1' PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET( SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:= CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b)); LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION( BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1); IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE; MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1; ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")= 1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF"; POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r); ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1; COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE, "output_file"));ENDPROCEDURE;Unpacker;QUIT; $ delete/nolog 'f'* $ CHECKSUM 'P1' $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT $ e "-E-CHKSMFAIL, Checksum of ''P1' failed." $ ENDSUBROUTINE $START: $ create 'f' X`09`09`09Patch Kit, Version 2.0 X X`09`09 Copyright (c) 1986, Larry Wall X XYou may copy the patch kit in whole or in part as long as you don't try to Xmake money off it, or pretend that you wrote it. X XNEW FEATURES IN THIS RELEASE X X(Correct) support for 4.3bsd-style context diffs. XFiles can be created from scratch. XYou can specify a fuzz-factor for context matching. XYou can force patch to ask no questions. XYou can specify how much of the leading pathname to strip off filenames. XUses a Configure script for greater portability. XYou are now asked if you want to apply a reversed patch. XNo limit (apart from memory) on the size of hunks. X XFeatures added by Tim Russell (russell@zeus.unl.edu) X XAdded support for VMS from earlier version to patchlevel 9. XAdded parsing support for "patch XArchive-Name: cdiff-v2 X XAfter receiving Bob Larson's sources for the PD context diff program, XI decided to accept his challenge to rewrite the documentation. In Xthe process, I also ported it to TURBOC version 1.5. It probably will Xalso compile in TURBOC 1.0, but since getting the update I dispensed Xwith the previous version and did not try it. `20 X XThe code has been reorganized to strip it of the documentation that Xwas built into it; that has been moved to the file cdiff.mem. Thus, Xthe following shar file includes cdiff.c, cdiff.1 (man source), cdiff.mem X(the previously built-in documentation), cdiff.doc (cdiff.1 passed Xthrough nroff -man for those who do not have nroff available), the Xoriginal README, and a new TC-READ.ME. Follow the notes in TC-READ.ME Xor it will run even slower! `20 X XOf course, no warranties whatsoever go with this. I merely hacked the Xcode minimally. I didn't write it. X--- X XComp.sources.misc: Volume 2, Issue 59 XSubmitted-By: XArchive-Name: pd-cdiff-patch X XNeil Dixon uncovered a flaw in the logic of the cdiff program that Xwas distributed early in January, and which was redistributed with Xchanges to make it compilable in Turbo C. I've tested his patch Xboth on the Unix SysVr2 version and on the PC, and have not found Xany errors. Conversely, the earlier version when compiled in MSC X4.0 (but, for some reason, not when compiled in TC 1.5) would Xsporadically come up with "read" errors. Since it now works in MSC as Xwell as TC, I've included the appropriate ifdefs for both compilers, Xand have incorporated Neil's patch. (This was for clarity. The line Xnumbers in his patch did not correspond precisely to the line numbers Xin the distributed code.) Both the patch as sent to me and the Xrevised code are contained below. X XAs before, I did not write this code. I merely ported it, and of Xcourse make no warranties whatsoever. X X--- X XOk, I guess that I will add my two cents worth. Here is yet another Xrepost of the public domain diff program. `20 X XI have integrated some changes into the i/o portion of the code, providing`2 V0 Xsome significant speedups. These changes were made after spending two`20 Xevenings playging around with the profiler, attempting various fixes to Xmake this beast a little faster. I completed this prior to the latest relea Vse`20 Xof the code (the version listed immediately above). `20 X XI have attempted to merge the changes provided by Mike above, but, since I d Vo`20 Xnot have any other machines close by, I could not test them. X XThe changes which I made are in the following areas: X X`09* modified the fgetss() and fputss() routines. These were the primary X`09 areas of intense activity on the system. From the source that I X`09 could see, these changes should be portable. After timing this`20 X`09 on my 3b1, the changes make this diff run at about the same speed X`09 as the system diff for the files that I was using (amazing isn't it?). X X`09* Moved the defines from within the source code to within the Makefile. X X`09* Ran the code through indent. Sorry about that, but it was the only X`09 way that I could make sure that I got all the other patches integrated` V20 X`09 properly. X X`09* Cleaned up some of the comments and added a few of my own. X X`09* Made a few tweaks to make lint happier. X X`09* Modified the Makefile to allow use of shared libraries. Included X`09 instructions for all the defines in the system as well. X XMark H. Colburn (mark@jhereg.mn.org) X XFixed to support VMS C 3.0 by Tim Russell (russell@zeus.unl.edu). X X12/10/89 mark@infopiz.uucp (uunet!lupine!infopiz!mark) X XFor he VMS environment, the command line interface for diff has been augment Ved Xto be more similar to the native DIFFERENCE utility. Default parts of file Xspecs are taken from the other file name, and allowance is made for diffing Xfile versions by simply specifying a single file/version implying comparison Xwith the previous version. `20 X XExamples: X`20 X `09`09$ diff uucico.c `5B-.v11`5D X`09`09$ diff uucico.c dua0: X`09`09$ diff uucico.c X XNote, the last case properly uses ;-1 as the old file and ;0 as the new. X XFor the VMS environment, Patch has been modified to behave more like a VMS Xutility; it now creates a new version of the patched file leaving the`20 Xoriginal version unmodified. `20 X XOn VMS, if you were patching a file on another device than your default Xlogin device, the patch would seemingly be applied (from the messages),`20 Xbut there would be no changes made and no errors reported. This has Xbeen fixed. X Xdiff has been fixed so that the 'new file name' need not be shorter than`20 Xthe 'old file name'. `20 X XAll patches are now done "in memory" (i.e. Plan A) where before this would`2 V0 Xhave only been the case if the files being patched were STREAM_LF files. XPlan B patches pass through the file several times reading and rereading Xfrom disk. X XAlso, both diff and patch have been given some significant performance`20 Ximprovements by using larger I/O buffers, and both have also been augmented` V20 Xwith argproc, to allow simple command line redirection which these utilities V`20 Xwork quite well with. X X-- Mark Pizzolato $ CALL UNPACK [.DOC]AAAREADME.TXT;1 594373067 $ create 'f' X X X X XDIFF(1) UNIX Programmer's Manual DIFF(1) X X X XNAME X diff - Public Domain diff (context diff) program X XSYNOPSIS X diff `5B -b -c -i -e `5D file1 file2 X XDESCRIPTION X Diff compares two files, showing what must be changed to X make them identical. Either file1 or file2 (but not both) X may refer to directories. If that is the case, a file in the X directory whose name is the same as the other file argument X will be used. The standard input may be used for one of the X files by replacing the argument by "-". Except for the stan- X dard input, both files must be on disk devices. X XOPTIONS X -b Remove trailing whitespace (blanks and tabs) and compress X all other strings of whitespace to a single blank. X X -c Print some context -- matching lines before and after the X non-match section. Mark non-matched sections with "`7C". X X -i Ignore lower/upper case distinctions. X X -e Output is in an "editor script" format which is compati- X ble with the Unix 'ed' editor. X X All information needed to compare the files is maintained in X main memory. This means that very large files (or fairly X large files with many differences) will cause the program to X abort with an "out of space" message. Main memory require- X ments (in words) are approximately: X X 2 * (length of file1 + length of file2) X + 3 * (number of changes) X X (Where "length" is the number of lines of data in each X file.) X X The algorithm reads each file twice, once to build hash X tables and once to check for fortuitous matches (two lines X that are in fact different, but which have the same hash X value). CPU time requirements include sorting the hash X tables and randomly searching memory tables for equivalence X classes. For example, on a time-shared VAX-11/780, comparing X two 1000 line files required about 30 seconds (elapsed clock X time) and about 10,000 bytes of working storage. About 90 X per-cent of the time was taken up by file I/O. X XDIAGNOSTICS X X X X X 4.2 BSD 1 X X X X X X X XDIFF(1) UNIX Programmer's Manual DIFF(1) X X X X Warning, bad option 'x' X The option is ignored. X X Usage ... X Two input files were not specified. X X Can't open input file "filename". X Can't continue. X X Out of space X The program ran out of memory while comparing the two X files. X X Can't read line nnn at xxx in file`5BA/B`5D X This indicates an I/O error when seeking to the X specific line. It should not happen. X X Spurious match, output is not optimal. X Two lines that were different yielded the same hash X value. This is harmless except that the difference X output is not the minimum set of differences between X the two files. For example, instead of the output: X lines 1 to 5 were changed to ... X the program will print X lines 1 to 3 were changed to ... X lines 4 to 5 were changed to ... X X The program uses a CRC16 hash code. X The likelihood of this error is quite small. X XAUTHOR X The diff algorithm was developed by J. W. Hunt and M. D. X McIlroy, using a central algorithm defined by H. S. Stone. X It was published in: X Hunt, J. W., and McIlroy, M. D., X An Algorithm for Differential File Comparison, X Computing Science Technical Report #41, X Bell Laboratories, Murray Hill, NJ 07974 X XBUGS X On RSX and DECUS C on VMS systems, diff may fail if the both X files are not "variable-length, implied carriage control" X format. The scopy program can be used to convert files to X this format if problems arise. X X When compiled under VAX C, diff handles STREAM_LF files X properly (in addition to the canonical variable-length X implied carriage control files). Other variations should X work, but have not been tested. X X X X X X 4.2 BSD 2 X X X X X X X XDIFF(1) UNIX Programmer's Manual DIFF(1) X X X X When compiled under VAX C, diff is quite slow for unknown X reasons which ought to be investigated. On the other hand, X it has access to effectively unlimited memory. X X Output in a form suitable for ed - the -e option - seems X rather pointless; the analogue on DEC systems is SLP (SUMSLP X on VMS). It would be simple to provide SLP-compatible out- X put. The question is, why bother - since the various DEC X file comparison utilities already produce it. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 4.2 BSD 3 X X X $ CALL UNPACK [.DOC]DIFF.DOC;1 404096844 $ create 'f' X How to create a diff X X To create a diff to be sent to Geoff Huston, you use the DIFF program Xwith the "-C" option to create a "context diff" which will have a good chanc Ve Xof working even if someone has made a local change to their source. X X Let's walk through an example. Say I added a nifty change to NEWSPOST.C V. XI want to send it to Geoff to be included in the next patchlevel of NEWS. X X So here's a directory: X X Directory PERM$2:`5BCONSLT32.WORK`5D X X NEWSPOST.C;2 NEWSPOST.C;1 X X Total of 2 files. X X To create the diff, I just use the form "DIFF -C oldfile newfile". One Ximportant thing, though, is to make the newer filename shorter than the olde Vr Xone. I just do this by specifying the version number on the old version, bu Vt Xnot on the new one. X X First, set up a foreign symbol for DIFF if you haven't: X X $ DIFF :== $disk:`5Bdirectory`5DDIFF X X To create the diff: X X $ DEFINE/USER SYS$OUTPUT DIFF.TXT ! Filename of the diff X $ DIFF -C NEWSPOST.C;1 NEWSPOST.C X XHere's what the sample output looks like, in this case: X X--------------------------------------------------------------- X X *** newspost.c;-1 <-- Old filename X --- newspost.c <-- New one, should be shor Vter X ************** <-- Start of first patch X *** 137,142 <-- Section from old file X *msg; X `7B X char mail_cmd`5BIO_SIZE`5D; X `20 X err_line(msg); `20 X if (screen_active) `7B X --- 137,143 ----- <-- Section from new file X *msg; X `7B X char mail_cmd`5BIO_SIZE`5D; X + int added_var; <-- '+' means added line X `20 X err_line(msg); `20 X if (screen_active) `7B X ************** <-- Start of second patch X *** 151,156 X smg$begin_pasteboard_update(&pid); X broad_trap(); X `7D X clear_err_line(); X `7D X #endif X --- 152,158 ----- X smg$begin_pasteboard_update(&pid); X broad_trap(); X `7D X + doit(added_var); <-- Added call to doit() X clear_err_line(); X `7D X #endif X X--------------------------------------------------------------- X XThat's about it. If you have more than one file changed, you can create Xdiffs for each and append them together - patch will do multiple files Xat once. X X Check your patch to make sure it looks right, and it's set to go! X`0C X Applying a patch X X To apply a patch, you must first extract it to a file. You shouldn't Xhave to worry about editing the header from the top, because patch will Xignore it. X X Set up a foreign symbol for patch, i.e. X X $ PATCH :== $disk:`5Bdirectory`5DPATCH X Xthen, set your default directory to wherever the affected files are, Xand invoke PATCH: X X $ PATCH X sets the maximum fuzz factor. This switch only applied X to context diffs, and causes patch to ignore up to that X many lines in looking for places to install a hunk. X Note that a larger fuzz factor increases the odds of a X faulty patch. The default fuzz factor is 2, and it may X not be set to more than the number of lines of context X in the context diff, ordinarily 3. X X -l causes the pattern matching to be done loosely, in case X the tabs and spaces have been munged in your input X file. Any sequence of whitespace in the pattern line X will match any sequence in the input file. Normal X characters must still match exactly. Each line of the X context must still match a line in the input file. X X X X XLOCAL 4.2 BSD 3 X X X X X X X XPATCH(1) UNIX Programmer's Manual PATCH(1) X X X X -n forces patch to interpret the patch file as a normal X diff. X X -N causes patch to ignore patches that it thinks are X reversed or already applied. See also -R . X X -o causes the next argument to be interpreted as the out- X put file name. X X -p X sets the pathname strip count, which controls how path- X names found in the patch file are treated, in case the X you keep your files in a different directory than the X person who sent out the patch. The strip count speci- X fies how many backslashes are to be stripped from the X front of the pathname. (Any intervening directory X names also go away.) For example, supposing the X filename in the patch file was X X /u/howard/src/blurfl/blurfl.c X X setting -p or -p0 gives the entire pathname unmodified, X -p1 gives X X u/howard/src/blurfl/blurfl.c X X without the leading slash, -p4 gives X X blurfl/blurfl.c X X and not specifying -p at all just gives you "blurfl.c". X Whatever you end up with is looked for either in the X current directory, or the directory specified by the -d X switch. X X -r causes the next argument to be interpreted as the X reject file name. X X -R tells patch that this patch was created with the old X and new files swapped. (Yes, I'm afraid that does hap- X pen occasionally, human nature being what it is.) Patch X will attempt to swap each hunk around before applying X it. Rejects will come out in the swapped format. The X -R switch will not work with ed diff scripts because X there is too little information to reconstruct the X reverse operation. X X If the first hunk of a patch fails, patch will reverse X the hunk to see if it can be applied that way. If it X can, you will be asked if you want to have the -R X switch set. If it can't, the patch will continue to be X X X XLOCAL 4.2 BSD 4 X X X X X X X XPATCH(1) UNIX Programmer's Manual PATCH(1) X X X X applied normally. (Note: this method cannot detect a X reversed patch if it is a normal diff and if the first X command is an append (i.e. it should have been a X delete) since appends always succeed, due to the fact X that a null context will match anywhere. Luckily, most X patches add or change lines rather than delete them, so X most reversed normal diffs will begin with a delete, X which will fail, triggering the heuristic.) X X -s makes patch do its work silently, unless an error X occurs. X X -S causes patch to ignore this patch from the patch file, X but continue on looking for the next patch in the file. X Thus X X patch -S + -S + X sets internal debugging flags, and is of interest only X to patch patchers. X XENVIRONMENT X No environment variables are used by patch. X XFILES X /tmp/patch* X XSEE ALSO X diff(1) X XNOTES FOR PATCH SENDERS X There are several things you should bear in mind if you are X going to be sending out patches. First, you can save people X a lot of grief by keeping a patchlevel.h file which is X patched to increment the patch level as the first diff in X the patch file you send out. If you put a Prereq: line in X with the patch, it won't let them apply patches out of order X without some warning. Second, make sure you've specified X the filenames right, either in a context diff header, or X with an Index: line. If you are patching something in a X subdirectory, be sure to tell the patch user to specify a -p X switch as needed. Third, you can create a file by sending X out a diff that compares a null file to the file you want to X create. This will only work if the file you want to create X doesn't exist already in the target directory. Fourth, take X X X XLOCAL 4.2 BSD 5 X X X X X X X XPATCH(1) UNIX Programmer's Manual PATCH(1) X X X X care not to send out reversed patches, since it makes people X wonder whether they already applied the patch. Fifth, while X you may be able to get away with putting 582 diff listings X into one file, it is probably wiser to group related patches X into separate files in case something goes haywire. X XDIAGNOSTICS X Too many to list here, but generally indicative that patch X couldn't parse your patch file. X X The message "Hmm..." indicates that there is unprocessed X text in the patch file and that patch is attempting to X intuit whether there is a patch in that text and, if so, X what kind of patch it is. X XCAVEATS X Patch cannot tell if the line numbers are off in an ed X script, and can only detect bad line numbers in a normal X diff when it finds a "change" or a "delete" command. A con- X text diff using fuzz factor 3 may have the same problem. X Until a suitable interactive interface is added, you should X probably do a context diff in these cases to see if the X changes made sense. Of course, compiling without errors is X a pretty good indication that the patch worked, but not X always. X X Patch usually produces the correct results, even when it has X to do a lot of guessing. However, the results are X guaranteed to be correct only when the patch is applied to X exactly the same version of the file that the patch was gen- X erated from. X XBUGS X Could be smarter about partial matches, excessively deviant X offsets and swapped code, but that would take an extra pass. X X If code has been duplicated (for instance with #ifdef OLD- X CODE ... #else ... #endif), patch is incapable of patching X both versions, and, if it works at all, will likely patch X the wrong one, and tell you that it succeeded to boot. X X If you apply a patch you've already applied, patch will X think it is a reversed patch, and offer to un-apply the X patch. This could be construed as a feature. X X X X X X X X X X XLOCAL 4.2 BSD 6 X X X $ CALL UNPACK [.DOC]PATCH.DOC;1 964225761 $ create 'f' X/* X * @(#)argproc.c 1.0 89/02/01`09`09Mark Pizzolato (mark@infopiz.uucp)`09 X */ X X#ifndef lint Xchar argproc_version`5B`5D = "@(#)argproc.c VMS uucp Version infopiz-1.0"; X#endif X X#include "includes.h"`09`09/* System include files, system dependent */ X X`0C X/* X * getredirection() is intended to aid in porting C programs X * to VMS (Vax-11 C) which does not support '>' and '<' X * I/O redirection, along with a command line pipe mechanism X * using the '`7C' AND background command execution '&'. X * The piping mechanism will probably work with almost any 'filter' type X * of program. With suitable modification, it may useful for other X * portability problems as well. X * X * Author: Mark Pizzolato`09mark@infopiz.UUCP X */ Xstruct list_item X `7B X struct list_item *next; X char *value; X `7D; X Xint Xgetredirection(ac, av) Xint`09`09*ac; Xchar`09`09***av; X/* X * Process vms redirection arg's. Exit if any error is seen. X * If getredirection() processes an argument, it is erased X * from the vector. getredirection() returns a new argc and argv value. X * In the event that a background command is requested (by a trailing "&"), X * this routine creates a background subprocess, and simply exits the progra Vm. X * X * Warning: do not try to simplify the code for vms. The code X * presupposes that getredirection() is called before any data is X * read from stdin or written to stdout. X * X * Normal usage is as follows: X * X *`09main(argc, argv) X *`09int`09`09argc; X * `09char`09`09*argv`5B`5D; X *`09`7B X *`09`09getredirection(&argc, &argv); X *`09`7D X */ X`7B X int`09`09`09argc = *ac;`09/* Argument Count`09 */ X char`09`09**argv = *av;`09/* Argument Vector`09 */ X char`09`09*ap; `09`09/* Argument pointer`09 */ X int`09 `09`09j;`09`09/* argv`5B`5D index`09`09 */ X extern int`09`09errno;`09`09/* Last vms i/o error `09 */ X int`09`09`09item_count = 0;`09/* Count of Items in List */ X struct list_item `09*list_head = 0;`09/* First Item in List`09 */ X struct list_item`09*list_tail;`09/* Last Item in List`09 */ X char `09`09*in = NULL;`09/* Input File Name`09 */ X char `09`09*out = NULL;`09/* Output File Name`09 */ X char `09`09*outmode = "w";`09/* Mode to Open Output File */ X int`09`09`09cmargc = 0; `09/* Piped Command Arg Count */ X char`09`09**cmargv = NULL;/* Piped Command Arg Vector */ X X /* X * First handle the case where the last thing on the line ends with X * a '&'. This indicates the desire for the command to be run in a X * subprocess, so we satisfy that desire. X */ X ap = argv`5Bargc-1`5D; X if (0 == strcmp("&", ap)) X`09exit(background_process(--argc, argv)); X if ('&' == ap`5Bstrlen(ap)-1`5D) X`09`7B X`09ap`5Bstrlen(ap)-1`5D = '\0'; X`09exit(background_process(argc, argv)); X`09`7D X /* X * Now we handle the general redirection cases that involve '>', '>>', X * '<', and pipes '`7C'. X */ X for (j = 0; j < argc; ++j) X`09`7B X`09if (0 == strcmp("<", argv`5Bj`5D)) X`09 `7B X`09 if (j+1 >= argc) X`09`09`7B X`09`09errno = EINVAL; X`09`09perror("No input file"); X`09`09exit(EXIT_ERR); X`09`09`7D X`09 in = argv`5B++j`5D; X`09 continue; X`09 `7D X`09if ('<' == *(ap = argv`5Bj`5D)) X`09 `7B X`09 in = 1 + ap; X`09 continue; X`09 `7D X`09if (0 == strcmp(">", ap)) X`09 `7B X`09 if (j+1 >= argc) X`09`09`7B X`09`09errno = EINVAL; X`09`09perror("No output file"); X`09`09exit(EXIT_ERR); X`09`09`7D X`09 out = argv`5B++j`5D; X`09 continue; X`09 `7D X`09if ('>' == *ap) X`09 `7B X`09 if ('>' == ap`5B1`5D) X`09`09`7B X`09`09outmode = "a"; X`09`09if ('\0' == ap`5B2`5D) X`09`09 out = argv`5B++j`5D; X`09`09else X`09`09 out = 2 + ap; X`09`09`7D X`09 else X`09`09out = 1 + ap; X`09 continue; X`09 `7D X`09if (0 == strcmp("`7C", argv`5Bj`5D)) X`09 `7B X`09 if (j+1 >= argc) X`09`09`7B X`09`09errno = EPIPE; X`09`09perror("No command to Pipe to"); X`09`09exit(EXIT_ERR); X`09`09`7D X`09 cmargc = argc-(j+1); X`09 cmargv = &argv`5Bj+1`5D; X`09 argc = j; X`09 continue; X`09 `7D X`09if ('`7C' == *(ap = argv`5Bj`5D)) X`09 `7B X`09 ++argv`5Bj`5D; X`09 cmargc = argc-j; X`09 cmargv = &argv`5Bj`5D; X`09 argc = j; X`09 continue; X`09 `7D X`09expand_wild_cards(ap, &list_head, &list_tail, &item_count); X`09`7D X /* X * Allocate and fill in the new argument vector, Some Unix's terminate X * the list with an extra null pointer. X */ X argv = *av = calloc(item_count+1, sizeof(char *)); X for (j = 0; j < item_count; ++j, list_head = list_head->next) X`09argv`5Bj`5D = list_head->value; X *ac = item_count; X if (cmargv != NULL) X`09`7B X`09char subcmd`5B1024`5D; X`09static char *pipe_and_fork(); X X`09if (out != NULL) X`09 `7B X`09 errno = EINVAL; X`09 perror("Invalid '`7C' and '>' specified"); X`09 exit(EXIT_ERR); X`09 `7D X`09strcpy(subcmd, cmargv`5B0`5D); X`09for (j = 1; j < cmargc; ++j) X`09 `7B X`09 strcat(subcmd, " \""); X`09 strcat(subcmd, cmargv`5Bj`5D); X`09 strcat(subcmd, "\""); X`09 `7D X`09out = pipe_and_fork(subcmd); X`09`7D X if ((in != NULL) && (NULL == freopen(in, "r", stdin, "mbc=32", "mbf=2")) V) X`09`7B X`09perror(in); `09 `09/* Can't find file`09`09*/ X`09exit(EXIT_ERR);`09`09/* Is a fatal error`09`09*/ X`09`7D X if ((out != NULL) && (NULL == freopen(out, outmode, stdout, "mbc=32", "m Vbf=2"))) X`09`7B`09 X`09perror(ap);`09`09/* Error, can't write or append`09*/ X`09exit(EXIT_ERR);`09`09/* Is a fatal error`09`09*/ X`09`7D X#ifdef DEBUG X fprintf(stderr, "Arglist:\n"); X for (j = 0; j < *ac; ++j) X`09fprintf(stderr, "argv`5B%d`5D = '%s'\n", j, argv`5Bj`5D); X#endif X`7D X Xstatic add_item(head, tail, value, count) Xstruct list_item **head; Xstruct list_item **tail; Xchar *value; Xint *count; X`7B X if (*head == 0) X`09`7B X`09if (NULL == (*head = calloc(1, sizeof(**head)))) X`09 `7B X`09 errno = ENOMEM; X`09 perror(""); X`09 exit(EXIT_ERR); X`09 `7D X`09*tail = *head; X`09`7D X else X`09if (NULL == ((*tail)->next = calloc(1, sizeof(**head)))) X`09 `7B X`09 errno = ENOMEM; X`09 perror(""); X`09 exit(EXIT_ERR); X`09 `7D X`09else X`09 *tail = (*tail)->next; X (*tail)->value = value; X ++(*count); X`7D X Xstatic expand_wild_cards(item, head, tail, count) Xchar *item; Xstruct ltem_list **head; Xstruct ltem_list **tail; Xint *count; X`7B Xint expcount = 0; Xint context = 0; Xint status; Xint status_value; Xint had_version; X$DESCRIPTOR(filespec, item); X$DESCRIPTOR(defaultspec, "SYS$DISK:`5B`5D*.*;"); X$DESCRIPTOR(resultspec, ""); X X if (strcspn(item, "*%") == strlen(item)) X`09`7B X`09add_item(head, tail, item, count); X`09return; X`09`7D X resultspec.dsc$b_dtype = DSC$K_DTYPE_T; X resultspec.dsc$b_class = DSC$K_CLASS_D; X resultspec.dsc$a_pointer = NULL; X filespec.dsc$w_length = strlen(item); X /* X * Only return version specs, if the caller specified a version X */ X had_version = strchr(item, ';'); X while (1 == (1&lib$find_file(&filespec, &resultspec, &context, X `09`09`09`09 &defaultspec, 0, &status_value, &0))) X`09`7B X`09char *string; X`09char *c; X X`09if (NULL == (string = calloc(1, resultspec.dsc$w_length+1))) X`09 `7B X`09 errno = ENOMEM; X`09 perror(""); X`09 exit(EXIT_ERR); X`09 `7D X`09strncpy(string, resultspec.dsc$a_pointer, resultspec.dsc$w_length); X`09string`5Bresultspec.dsc$w_length`5D = '\0'; X`09if (NULL == had_version) X`09 *((char *)strrchr(string, ';')) = '\0'; X`09/* X`09 * Be consistent with what the C RTL has already done to the rest of X`09 * the argv items and lowercase all of these names. X`09 */ X`09for (c = string; *c; ++c) X`09 if (isupper(*c)) X`09`09*c = tolower(*c); X`09add_item(head, tail, string, count); X`09++expcount; X`09`7D X if (expcount == 0) X`09add_item(head, tail, item, count); X lib$sfree1_dd(&resultspec); X lib$find_file_end(&context); X`7D X Xstatic int child_st`5B2`5D;`09/* Event Flag set when child process completes V`09*/ X Xstatic short child_chan;/* I/O Channel for Pipe Mailbox`09`09`09*/ X Xstatic exit_handler(status) Xint *status; X`7B Xshort iosb`5B4`5D; X X if (0 == child_st`5B0`5D) X`09`7B X#ifdef DEBUG X`09fprintf(stderr, "Waiting for Child Process to Finnish . . .\n"); X#endif X`09sys$qiow(0, child_chan, IO$_WRITEOF, iosb, 0, 0, 0, 0, 0, 0, 0, 0); X`09sys$dassgn(child_chan); X`09fclose(stdout); X`09sys$synch(0, child_st); X`09`7D X`7D X X#include syidef`09`09/* System Information Definitions`09*/ X Xstatic sig_child(chan) Xint chan; X`7B X#ifdef DEBUG X fprintf(stderr, "Child Completion AST\n"); X#endif X if (child_st`5B0`5D == 0) X`09child_st`5B0`5D = 1; X`7D X Xstatic struct exit_control_block X `7B X struct exit_control_block *flink; X int`09(*exit_routine)(); X int arg_count; X int *status_address; X int exit_status; X `7D exit_block = X `7B X 0, X exit_handler, X 1, X &exit_block.exit_status, X 0 X `7D; X Xstatic char *pipe_and_fork(cmd) Xchar *cmd; X`7B X $DESCRIPTOR(cmddsc, cmd); X static char mbxname`5B64`5D; X $DESCRIPTOR(mbxdsc, mbxname); X short iosb`5B4`5D; X int status; X int pid; X struct X`09`7B X`09short dna_buflen; X`09short dna_itmcod; X`09char *dna_buffer; X`09short *dna_retlen; X`09int listend; X`09`7D itmlst = X`09`7B X`09sizeof(mbxname), X`09DVI$_DEVNAM, X`09mbxname, X`09&mbxdsc.dsc$w_length, X`090 X`09`7D; X int mbxsize; X struct X`09`7B X`09short mbf_buflen; X`09short mbf_itmcod; X`09int *mbf_maxbuf; X`09short *mbf_retlen; X`09int listend; X`09`7D syiitmlst = X`09`7B X`09sizeof(mbxsize), X`09SYI$_MAXBUF, X`09&mbxsize, X`090, X`090 X`09`7D; X X cmddsc.dsc$w_length = strlen(cmd); X /* X * Get the SYSGEN parameter MAXBUF, and the smaller of it and 2048 as X * the size of the 'pipe' mailbox. X */ X if (1 == (1&(vaxc$errno = sys$getsyiw(0, 0, 0, &syiitmlst, iosb, 0, 0, 0 V)))) X`09vaxc$errno = iosb`5B0`5D; X if (0 == (1&vaxc$errno)) X`09`7B X `09errno = EVMSERR; X`09perror("Can't get SYSGEN parameter value for MAXBUF"); X`09exit(EXIT_ERR); X`09`7D X if (mbxsize > 2048) X`09mbxsize = 2048; X if (0 == (1&(vaxc$errno = sys$crembx(0, &child_chan, mbxsize, mbxsize, 0 V, 0, 0)))) X`09`7B X`09errno = EVMSERR; X`09perror("Can't create pipe mailbox"); X`09exit(EXIT_ERR); X`09`7D X if (1 == (1&(vaxc$errno = sys$getdviw(0, child_chan, 0, &itmlst, iosb, X `09`09`09`09`09 0, 0, 0)))) X`09vaxc$errno = iosb`5B0`5D; X if (0 == (1&vaxc$errno)) X`09`7B X `09errno = EVMSERR; X`09perror("Can't get pipe mailbox device name"); X`09exit(EXIT_ERR); X`09`7D X mbxname`5Bmbxdsc.dsc$w_length`5D = '\0'; X#ifdef DEBUG X fprintf(stderr, "Pipe Mailbox Name = '%s'\n", mbxname); X#endif X if (0 == (1&(vaxc$errno = lib$spawn(&cmddsc, &mbxdsc, 0, &1, X `09`09`09`09`090, &pid, child_st, &0, sig_child, X `09`09`09`09`09&child_chan)))) X`09`7B X`09errno = EVMSERR; X`09perror("Can't spawn subprocess"); X`09exit(EXIT_ERR); X`09`7D X#ifdef DEBUG X fprintf(stderr, "Subprocess's Pid = %08X\n", pid); X#endif X sys$dclexh(&exit_block); X return(mbxname); X`7D X Xbackground_process(argc, argv) Xint argc; Xchar **argv; X`7B Xchar command`5B2048`5D = "$"; X$DESCRIPTOR(value, command); X$DESCRIPTOR(cmd, "BACKGROUND$COMMAND"); X$DESCRIPTOR(null, "NLA0:"); Xint pid; X X strcat(command, argv`5B0`5D); X while (--argc) X`09`7B X`09strcat(command, " \""); X`09strcat(command, *(++argv)); X`09strcat(command, "\""); X`09`7D X value.dsc$w_length = strlen(command); X if (0 == (1&(vaxc$errno = lib$set_symbol(&cmd, &value)))) X`09`7B X`09errno = EVMSERR; +-+-+-+-+-+-+-+- END OF PART 1 +-+-+-+-+-+-+-+-