MS-DOS patches to perl.
Apply this patch to the standard perl source, version 4, patch level 19,
using "patch -p."  Do this in the root directory of the perl source
distribution.

You can cat all these patches together and pipe the output to patch -p.

Len Reed
Holos Software, Inc.
..!gatech!holos0!lbr
holos0!lbr@gatech.edu
--------------------------------------
*** perl.man.old	Thu Nov 14 07:29:32 1991
--- perl.man	Sun Feb 23 08:41:49 1992
***************
*** 68,73 ****
--- 68,80 ----
  .ds L' `
  .ds R' '
  'br\}
+ '''
+ ''' Define string Ms for MS-DOS support:
+ '''   unix = no MS-DOSisms in manual
+ '''   both = Unix and MS-DOS
+ '''   msdos = MS-DOS only
+ .ds Ms both
+ '''
  .TH PERL 1 "\*(RP"
  .UC
  .SH NAME
***************
*** 123,129 ****
--- 130,154 ----
  .I perl
  scripts.
  OK, enough hype.
+ .if '\*(Ms'msdos' \{\
  .PP
+ This manual applies only to the MS-DOS version.  Unix-only features
+ are mentioned but are not fully documented here.
+ \}
+ .if '\*(Ms'both' \{\
+ .PP
+ Note to MS-DOS users.
+ \}
+ .if !'\*(Ms'unix' \{\
+ The MS-DOS version of
+ .I perl
+ attempts to duplicate the Unix version's functionality but is crippled
+ by MS-DOS and by the severe memory limitations MS-DOS imposes.  The MS-DOS
+ version is nevertheless useful for text processing and for limited
+ applications involving subprocess management.  Refer to the section on
+ MS-DOS CONSIDERATIONS.
+ \}
+ .PP
  Upon startup,
  .I perl
  looks for your script in one of the following places:
***************
*** 229,234 ****
--- 254,266 ----
  is given,
  .I perl
  will not look for a script filename in the argument list.
+ .if !'\*(Ms'unix' \{\
+ On MS-DOS, the
+ .B \-e
+ switch will not work well unless perl is run from an MKS tool,
+ such as the Korn shell.  This is due to limitations in the standard
+ method of MS-DOS argument passing.
+ \}
  .TP 5
  .BI \-i extension
  specifies that files processed by the <> construct are to be edited
***************
*** 276,281 ****
--- 308,328 ----
  .Sp
  You can use eof to locate the end of each input file, in case you want
  to append to each file, or reset line numbering (see example under eof).
+ .if !'\*(Ms'unix' \{\
+ .Sp
+ On MS-DOS, and on OS/2 with the FAT filesystem, simple renaming will
+ rarely work and so
+ .I perl
+ uses a multiple-try scheme.  The renaming described above is tried, and
+ if it works, fine.  If not, the following schemes are tried in order.
+ If the suffix begins with '.', the extension is replaced.  If the
+ suffix is a single character, attempts are made to append that character
+ to the extension, to append that character to the filename, to replace
+ the last character
+ of the extension, and to replace the last character of the filename.
+ If all of these fail, attempts are made to change the extension to
+ \*(L"$$$\*(R", then \*(L"\~\~\~\*(R".
+ \}
  .TP 5
  .BI \-I directory
  may be used in conjunction with
***************
*** 372,377 ****
--- 419,436 ----
  (Since both comments and cpp directives begin with the # character,
  you should avoid starting comments with any words recognized
  by the C preprocessor such as \*(L"if\*(R", \*(L"else\*(R" or \*(L"define\*(R".)
+ .if !'\*(Ms'unix' \{\
+ On MS-DOS, the
+ .B -P
+ option is implemented using the perl script
+ .IR doscpp.pl .
+ This script must be found in the first directory listed in @INC.
+ (see the @INC array in Predefined Names).  Currently the
+ .B -P
+ switch only works in conjuction with Microsoft C 6.0, but editing the
+ .I doscpp.pl
+ script may allow its use with other compilers.
+ \}
  .TP 5
  .B \-s
  enables some rudimentary switch parsing for switches on the command line
***************
*** 394,399 ****
--- 453,459 ----
  .I perl
  use the PATH environment variable to search for the script
  (unless the name of the script starts with a slash).
+ .if !'\*(Ms'msdos' \{\
  Typically this is used to emulate #! startup on machines that don't
  support #!, in the following manner:
  .nf
***************
*** 437,449 ****
  		if 0;
  
  .fi
  .TP 5
  .B \-u
  causes
  .I perl
  to dump core after compiling your script.
! You can then take this core dump and turn it into an executable file
! by using the undump program (not supplied).
  This speeds startup at the expense of some disk space (which you can
  minimize by stripping the executable).
  (Still, a "hello world" executable comes out to about 200K on my machine.)
--- 497,549 ----
  		if 0;
  
  .fi
+ \}
+ .if '\*(Ms'msdos' \{\
+ On MS-DOS, this can be used to create an executable batch or shell-script.
+ \}
+ .if '\*(Ms'both' \{\
+ On MS-DOS, similar techniques can be used to create an executable
+ batch file or shell-script.
+ \}
+ .if !'\*(Ms'unix' \{\
+ To create an executable batch file, the following technique can be used.
+ .nf
+ 
+ .ne 8
+ 
+ 	@REM=(qq!
+ 	@perl -S %0.bat %1 %2 %3 %4 %5 %6 %7 %8 %9
+ 	@goto end !) if 0 ;
+ 
+ 	    # The perl script goes here.
+ 
+ 	@REM=(qq!
+ 	:end !) if 0 ;
+ 
+ .fi
+ Note that only nine arguments to perl can be passed in this manner.
+ The four '!' characters can be replaced with some untypeable character,
+ such as Ctrl-A.  This will allow you to pass any characters, including
+ ".." strings as arguments.
+ .Sp
+ An MKS Korn shell script can be handled almost as on Unix.  Put the
+ script into a file with the extension \*(L".ksh\*(R" and prepend
+ the following.
+ .nf
+ 
+ .ne 3
+ 	eval "exec /usr/bin/perl \-S $0.ksh $*"
+ 		if $running_under_some_shell;
+ .fi
+ \}
  .TP 5
  .B \-u
  causes
  .I perl
  to dump core after compiling your script.
! .if !'\*(Ms'msdos' \{\
! You can then take this core dump and turn it into an executable
! file by using the undump program (not supplied).
  This speeds startup at the expense of some disk space (which you can
  minimize by stripping the executable).
  (Still, a "hello world" executable comes out to about 200K on my machine.)
***************
*** 453,458 ****
--- 553,560 ----
  dump operator instead.
  Note: availability of undump is platform specific and may not be available
  for a specific port of perl.
+ \}
+ .if !'\*(Ms'unix' This switch is not supported on MS-DOS.
  .TP 5
  .B \-U
  allows
***************
*** 461,466 ****
--- 563,569 ----
  Currently the only \*(L"unsafe\*(R" operations are the unlinking of directories while
  running as superuser, and running setuid programs with fatal taint checks
  turned into warnings.
+ .if !'\*(Ms'unix' (Thse aren't applicable to MS-DOS.)
  .TP 5
  .B \-v
  prints the version and patchlevel of your
***************
*** 1504,1513 ****
--- 1607,1621 ----
  The interpretation of the file permission operators \-r, \-R, \-w, \-W, \-x and \-X
  is based solely on the mode of the file and the uids and gids of the user.
  There may be other reasons you can't actually read, write or execute the file.
+ .if !'\*(Ms'msdos' \{\
  Also note that, for the superuser, \-r, \-R, \-w and \-W always return 1, and 
  \-x and \-X return 1 if any execute bit is set in the mode.
  Scripts run by the superuser may thus need to do a stat() in order to determine
  the actual mode of the file, or temporarily set the uid to something else.
+ \}
+ .if !'\*(Ms'unix' \{\
+ (Note that several of the above operators don't mean much under MS-DOS.)
+ \}
  .Sp
  Example:
  .nf
***************
*** 1667,1677 ****
  Only ?? patterns local to the current package are reset.
  .Ip "accept(NEWSOCKET,GENERICSOCKET)" 8 2
  Does the same thing that the accept system call does.
  Returns true if it succeeded, false otherwise.
  See example in section on Interprocess Communication.
  .Ip "alarm(SECONDS)" 8 4
  .Ip "alarm SECONDS" 8
! Arranges to have a SIGALRM delivered to this process after the specified number
  of seconds (minus 1, actually) have elapsed.  Thus, alarm(15) will cause
  a SIGALRM at some point more than 14 seconds in the future.
  Only one timer may be counting at once.  Each call disables the previous
--- 1775,1790 ----
  Only ?? patterns local to the current package are reset.
  .Ip "accept(NEWSOCKET,GENERICSOCKET)" 8 2
  Does the same thing that the accept system call does.
+ .if !'\*(Ms'msdos' \{\
  Returns true if it succeeded, false otherwise.
  See example in section on Interprocess Communication.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "alarm(SECONDS)" 8 4
  .Ip "alarm SECONDS" 8
! .if !'\*(Ms'msdos' \{\
! Arranges to have a SIGALRM delivered to this process after
! the specified number
  of seconds (minus 1, actually) have elapsed.  Thus, alarm(15) will cause
  a SIGALRM at some point more than 14 seconds in the future.
  Only one timer may be counting at once.  Each call disables the previous
***************
*** 1678,1683 ****
--- 1791,1798 ----
  timer, and an argument of 0 may be supplied to cancel the previous timer
  without starting a new one.
  The returned value is the amount of time remaining on the previous timer.
+ \}
+ .if !'\*(Ms'unix'  Not supported on MS-DOS.
  .Ip "atan2(Y,X)" 8 2
  Returns the arctangent of Y/X in the range
  .if t \-\(*p to \(*p.
***************
*** 1684,1699 ****
  .if n \-PI to PI.
  .Ip "bind(SOCKET,NAME)" 8 2
  Does the same thing that the bind system call does.
  Returns true if it succeeded, false otherwise.
  NAME should be a packed address of the proper type for the socket.
  See example in section on Interprocess Communication.
  .Ip "binmode(FILEHANDLE)" 8 4
  .Ip "binmode FILEHANDLE" 8 4
! Arranges for the file to be read in \*(L"binary\*(R" mode in operating systems
  that distinguish between binary and text files.
  Files that are not read in binary mode have CR LF sequences translated
  to LF on input and LF translated to CR LF on output.
! Binmode has no effect under Unix.
  If FILEHANDLE is an expression, the value is taken as the name of
  the filehandle.
  .Ip "caller(EXPR)"
--- 1799,1823 ----
  .if n \-PI to PI.
  .Ip "bind(SOCKET,NAME)" 8 2
  Does the same thing that the bind system call does.
+ .if !'\*(Ms'msdos'\{\
  Returns true if it succeeded, false otherwise.
  NAME should be a packed address of the proper type for the socket.
  See example in section on Interprocess Communication.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "binmode(FILEHANDLE)" 8 4
  .Ip "binmode FILEHANDLE" 8 4
! Arranges for the file to be read in \*(L"binary\*(R" mode in operating
! .if !'\*(Ms'unix' systems, such as MS-DOS,
! .if '\*(Ms'unix' systems
  that distinguish between binary and text files.
  Files that are not read in binary mode have CR LF sequences translated
  to LF on input and LF translated to CR LF on output.
! .if !'\*(Ms'unix' \{\
! In addition, MS-DOS will consider ^Z to indicate end of file
! for files being read in text mode.\}
! The is no way to return a file handle to text mode.
! .if !'\*(Ms'msdos' Binmode has no effect under Unix.
  If FILEHANDLE is an expression, the value is taken as the name of
  the filehandle.
  .Ip "caller(EXPR)"
***************
*** 1714,1719 ****
--- 1838,1861 ----
  Returns 1 upon success, 0 otherwise.
  See example under
  .IR die .
+ .if !'\*(Ms'unix' \{\
+ .Sp
+ On MS-DOS, the path and/or the directory can be specified.
+ .nf
+ 
+ .ne 6
+ chdir "c:/junk/subdir";
+ chdir "e:";
+ chdir "abc/xyz";
+ 
+ .fi
+ The first of these changes the default drive and directory.  The
+ second changes to the default directory on drive E:.  The third changes
+ the directory on the current drive.
+ As with all filenames, forward slashes are recommended inside
+ .IR perl .
+ (See the section on MS-DOS considerations.)
+ \}
  .Ip "chmod(LIST)" 8 2
  .Ip "chmod LIST" 8 2
  Changes the permissions of a list of files.
***************
*** 1761,1766 ****
--- 1903,1909 ----
  The first two elements of the list must be the NUMERICAL uid and gid,
  in that order.
  Returns the number of files successfully changed.
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .nf
  
  .ne 2
***************
*** 1801,1809 ****
--- 1944,1955 ----
  .fi
  .Ip "chroot(FILENAME)" 8 5
  .Ip "chroot FILENAME" 8
+ .if !'\*(Ms'msdos' \{\
  Does the same as the system call of that name.
  If you don't know what it does, don't worry about it.
  If FILENAME is omitted, does chroot to $_.
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "close(FILEHANDLE)" 8 5
  .Ip "close FILEHANDLE" 8
  Closes the file or pipe associated with the file handle.
***************
*** 1834,1842 ****
--- 1980,1991 ----
  Closes a directory opened by opendir().
  .Ip "connect(SOCKET,NAME)" 8 2
  Does the same thing that the connect system call does.
+ .if !'\*(Ms'msdos' \{\
  Returns true if it succeeded, false otherwise.
  NAME should be a package address of the proper type for the socket.
  See example in section on Interprocess Communication.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "cos(EXPR)" 8 6
  .Ip "cos EXPR" 8 6
  Returns the cosine of EXPR (expressed in radians).
***************
*** 1843,1850 ****
--- 1992,2002 ----
  If EXPR is omitted takes cosine of $_.
  .Ip "crypt(PLAINTEXT,SALT)" 8 6
  Encrypts a string exactly like the crypt() function in the C library.
+ .if !'\*(Ms'msdos' \{\
  Useful for checking the password file for lousy passwords.
  Only the guys wearing white hats should do this.
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "dbmclose(ASSOC_ARRAY)" 8 6
  .Ip "dbmclose ASSOC_ARRAY" 8
  Breaks the binding between a dbm file and an associative array.
***************
*** 1863,1868 ****
--- 2015,2024 ----
  dbmopen in your program.
  If your system has neither dbm nor ndbm, calling dbmopen produces a fatal
  error.
+ .if !'\*(Ms'unix' \{\
+ (MS-DOS users: the MS-DOS port uses Gnu-dbm, which supports
+ multiple files.)
+ \}
  .Sp
  Values assigned to the associative array prior to the dbmopen are lost.
  A certain number of values from the dbm file are cached in memory.
***************
*** 2056,2063 ****
  the \*(L"require\*(R" operator.
  .Ip "dump LABEL" 8 6
  This causes an immediate core dump.
! Primarily this is so that you can use the undump program to turn your
! core dump into an executable binary after having initialized all your
  variables at the beginning of the program.
  When the new binary is executed it will begin by executing a "goto LABEL"
  (with all the restrictions that goto suffers).
--- 2212,2220 ----
  the \*(L"require\*(R" operator.
  .Ip "dump LABEL" 8 6
  This causes an immediate core dump.
! .if !'\*(Ms'msdos' \{\
! Primarily this is so that you can use the undump program to
! turn your core dump into an executable binary after having initialized all your
  variables at the beginning of the program.
  When the new binary is executed it will begin by executing a "goto LABEL"
  (with all the restrictions that goto suffers).
***************
*** 2067,2072 ****
--- 2224,2231 ----
  when the program is reincarnated, with possible resulting confusion on the part
  of perl.
  See also \-u.
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Sp
  Example:
  .nf
***************
*** 2232,2237 ****
--- 2391,2406 ----
  	exec $shell '-sh';		# pretend it's a login shell
  
  .fi
+ .if !'\*(Ms'unix'\{\
+ The MS-DOS implementation of
+ .IR exec
+ has problems.  Unlike
+ .IR system
+ and pipes it is not MKS toolkit compatible.  As of this writing (September
+ 1991) it will not even allow for temporary file cleanup.  The use of
+ .IR exec
+ on MS-DOS is strongly discouraged.
+ \}
  .Ip "exit(EXPR)" 8 6
  .Ip "exit EXPR" 8
  Evaluates EXPR and exits immediately with that value.
***************
*** 2254,2259 ****
--- 2423,2429 ----
  If EXPR is omitted, gives exp($_).
  .Ip "fcntl(FILEHANDLE,FUNCTION,SCALAR)" 8 4
  Implements the fcntl(2) function.
+ .if !'\*(Ms'msdos'\{\
  You'll probably have to say
  .nf
  
***************
*** 2269,2274 ****
--- 2439,2446 ----
  Argument processing and value return works just like ioctl below.
  Note that fcntl will produce a fatal error if used on a machine that doesn't implement
  fcntl(2).
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "fileno(FILEHANDLE)" 8 4
  .Ip "fileno FILEHANDLE" 8 4
  Returns the file descriptor for a filehandle.
***************
*** 2277,2282 ****
--- 2449,2456 ----
  the filehandle.
  .Ip "flock(FILEHANDLE,OPERATION)" 8 4
  Calls flock(2) on FILEHANDLE.
+ \}
+ .if !'\*(Ms'msdos' \{\
  See manual page for flock(2) for definition of OPERATION.
  Returns true for success, false on failure.
  Will produce a fatal error if used on a machine that doesn't implement
***************
*** 2309,2319 ****
--- 2483,2502 ----
  	do unlock();
  
  .fi
+ \}
+ .if !'\*(Ms'unix' \{\
+ .br
+ File locking is not supported on MS-DOS, though perhaps it could be
+ constructed using MS-DOS file constructions.)
+ \}
  .Ip "fork" 8 4
  Does a fork() call.
+ .if !'\*(Ms'msdos' \{\
  Returns the child pid to the parent process and 0 to the child process.
  Note: unflushed buffers remain unflushed in both processes, which means
  you may need to set $| to avoid duplicate output.
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "getc(FILEHANDLE)" 8 4
  .Ip "getc FILEHANDLE" 8
  .Ip "getc" 8
***************
*** 2322,2333 ****
  If FILEHANDLE is omitted, reads from STDIN.
  .Ip "getlogin" 8 3
  Returns the current login from /etc/utmp, if any.
! If null, use getpwuid.
! 
  	$login = getlogin || (getpwuid($<))[0] || "Somebody";
! 
  .Ip "getpeername(SOCKET)" 8 3
  Returns the packed sockaddr address of other end of the SOCKET connection.
  .nf
  
  .ne 4
--- 2505,2519 ----
  If FILEHANDLE is omitted, reads from STDIN.
  .Ip "getlogin" 8 3
  Returns the current login from /etc/utmp, if any.
! .if !'\*(Ms'msdos' If null, use getpwuid.
! .if !'\*(Ms'unix' (Not supported on MS-DOS.)
! .if !'\*(Ms'msdos' \{\
  	$login = getlogin || (getpwuid($<))[0] || "Somebody";
! \}
  .Ip "getpeername(SOCKET)" 8 3
  Returns the packed sockaddr address of other end of the SOCKET connection.
+ .if !'\*(Ms'unix' (Sockets are not yet supported on MS-DOS.)
+ .if !'\*(Ms'msdos' \{\
  .nf
  
  .ne 4
***************
*** 2341,2362 ****
  	($family, $port, $heraddr) =
  			unpack($sockaddr,$hersockaddr);
  'br\}
! 
  .fi
  .Ip "getpgrp(PID)" 8 4
  .Ip "getpgrp PID" 8
  Returns the current process group for the specified PID, 0 for the current
  process.
! Will produce a fatal error if used on a machine that doesn't implement
! getpgrp(2).
  If EXPR is omitted, returns process group of current process.
  .Ip "getppid" 8 4
! Returns the process id of the parent process.
  .Ip "getpriority(WHICH,WHO)" 8 4
  Returns the current priority for a process, a process group, or a user.
  (See getpriority(2).)
  Will produce a fatal error if used on a machine that doesn't implement
  getpriority(2).
  .Ip "getpwnam(NAME)" 8
  .Ip "getgrnam(NAME)" 8
  .Ip "gethostbyname(NAME)" 8
--- 2527,2555 ----
  	($family, $port, $heraddr) =
  			unpack($sockaddr,$hersockaddr);
  'br\}
! \}
  .fi
  .Ip "getpgrp(PID)" 8 4
  .Ip "getpgrp PID" 8
  Returns the current process group for the specified PID, 0 for the current
  process.
! .if !'\*(Ms'msdos' \{\
! Will produce a fatal error if used on a machine
! that doesn't implement getpgrp(2).
  If EXPR is omitted, returns process group of current process.
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "getppid" 8 4
! On Unix, returns the process id of the parent process.
! .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "getpriority(WHICH,WHO)" 8 4
  Returns the current priority for a process, a process group, or a user.
+ .if !'\*(Ms'msdos' \{\
  (See getpriority(2).)
  Will produce a fatal error if used on a machine that doesn't implement
  getpriority(2).
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "getpwnam(NAME)" 8
  .Ip "getgrnam(NAME)" 8
  .Ip "gethostbyname(NAME)" 8
***************
*** 2389,2394 ****
--- 2582,2590 ----
  .Ip "endservent" 8
  These routines perform the same functions as their counterparts in the
  system library.
+ .if '\*(Ms'msdos' None are supported on MS-DOS.
+ .if '\*(Ms'both' (None are supported on MS-DOS.)
+ .if !'\*(Ms'msdos' \{\
  The return values from the various get routines are as follows:
  .nf
  
***************
*** 2413,2420 ****
--- 2609,2618 ----
  	($a,$b,$c,$d) = unpack('C4',$addr[0]);
  
  .fi
+ \}
  .Ip "getsockname(SOCKET)" 8 3
  Returns the packed sockaddr address of this end of the SOCKET connection.
+ .if !'\*(Ms'msdos' \{\
  .nf
  
  .ne 4
***************
*** 2428,2437 ****
  	($family, $port, $myaddr) =
  			unpack($sockaddr,$mysockaddr);
  'br\}
! 
  .fi
  .Ip "getsockopt(SOCKET,LEVEL,OPTNAME)" 8 3
  Returns the socket option requested, or undefined if there is an error.
  .Ip "gmtime(EXPR)" 8 4
  .Ip "gmtime EXPR" 8
  Converts a time as returned by the time function to a 9-element array with
--- 2626,2637 ----
  	($family, $port, $myaddr) =
  			unpack($sockaddr,$mysockaddr);
  'br\}
! \}
  .fi
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "getsockopt(SOCKET,LEVEL,OPTNAME)" 8 3
  Returns the socket option requested, or undefined if there is an error.
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "gmtime(EXPR)" 8 4
  .Ip "gmtime EXPR" 8
  Converts a time as returned by the time function to a 9-element array with
***************
*** 2498,2504 ****
  Returns the integer portion of EXPR.
  If EXPR is omitted, uses $_.
  .Ip "ioctl(FILEHANDLE,FUNCTION,SCALAR)" 8 4
! Implements the ioctl(2) function.
  You'll probably have to say
  .nf
  
--- 2698,2705 ----
  Returns the integer portion of EXPR.
  If EXPR is omitted, uses $_.
  .Ip "ioctl(FILEHANDLE,FUNCTION,SCALAR)" 8 4
! Implements the Unix ioctl(2) function.
! .if !'\*(Ms'msdos' \{\
  You'll probably have to say
  .nf
  
***************
*** 2509,2515 ****
  If ioctl.ph doesn't exist or doesn't have the correct definitions
  you'll have to roll
  your own, based on your C header files such as <sys/ioctl.h>.
! (There is a perl script called h2ph that comes with the perl kit
  which may help you in this.)
  SCALAR will be read and/or written depending on the FUNCTION\*(--a pointer
  to the string value of SCALAR will be passed as the third argument of
--- 2710,2716 ----
  If ioctl.ph doesn't exist or doesn't have the correct definitions
  you'll have to roll
  your own, based on your C header files such as <sys/ioctl.h>.
! (There is a perl script called h2ph that comes with the Unix perl kit
  which may help you in this.)
  SCALAR will be read and/or written depending on the FUNCTION\*(--a pointer
  to the string value of SCALAR will be passed as the third argument of
***************
*** 2551,2556 ****
--- 2752,2818 ----
  	($retval = ioctl(...)) || ($retval = -1);
  	printf "System returned %d\en", $retval;
  .fi
+ \}
+ .if !'\*(Ms'unix' \{\
+ .Sp
+ On MS-DOS, the function code of the ioctl function (the second
+ argument) is encoded as follows:
+ .nf
+ 
+ .ne 3
+ 	The lowest nibble of the function code goes to AL.
+ 	The two middle nibbles go to CL.
+ 	The high nibble goes to CH.
+ .fi
+ .Sp
+ The return code is -1 in the case of an error and if successful:
+ .nf
+ 
+ .ne 3
+ 	for functions AL = 00, 09, 0a the value of the register DX
+ 	for functions AL = 02 - 08, 0e the value of the register AX
+ 	for functions AL = 01, 0b - 0f the number 0.
+ .fi
+ 
+ .if !'\*(Ms'msdos' \{\
+ .Sp
+ The program can distiguish between the return value and the success
+ of ioctl as described for Unix above.\}
+ 
+ Some MS-DOS ioctl functions need a number as the first argument.
+ Provided that no other files have been opened the
+ number can be obtained if ioctl is called with \@fdnum\[number\]
+ as the first argument after executing the following code:
+ 
+ .nf
+ .ne 6
+ 	@fdnum = ("STDIN", "STDOUT", "STDERR");
+ 	$maxdrives = 15;
+ 	for ($i = 3; $i < $maxdrives; $i++) {
+ 		open("FD$i", "nul");
+ 		@fdnum[$i - 1] = "FD$i";
+ 	}
+ .fi
+ .if '\*(Ms'msdos' \{\
+ The return value of ioctl (and fcntl) is as follows:
+ .nf
+ 
+ .ne 4
+ 	if OS returns:\h'|3i'perl returns:
+ 	  -1\h'|3i'  undefined value
+ 	  0\h'|3i'  string "0 but true"
+ 	  anything else\h'|3i'  that number
+ 
+ .fi
+ Thus perl returns true on success and false on failure, yet you can still
+ easily determine the actual value returned by the operating system:
+ .nf
+ 
+ 	($retval = ioctl(...)) || ($retval = -1);
+ 	printf "System returned %d\en", $retval;
+ .fi
+ \}
+ \}
  .Ip "join(EXPR,LIST)" 8 8
  .Ip "join(EXPR,ARRAY)" 8
  Joins the separate strings of LIST or ARRAY into a single string with fields
***************
*** 2597,2602 ****
--- 2859,2865 ----
  .Ip "kill(LIST)" 8 8
  .Ip "kill LIST" 8 2
  Sends a signal to a list of processes.
+ .if !'\*(Ms'msdos' \{\
  The first element of the list must be the signal to send.
  Returns the number of processes successfully signaled.
  .nf
***************
*** 2609,2614 ****
--- 2872,2881 ----
  (On System V, a negative \fIprocess\fR number will also kill process groups,
  but that's not portable.)
  You may use a signal name in quotes.
+ \}
+ .if !'\(*Ms'unix' \{\
+ Not supported on MS-DOS.
+ \}
  .Ip "last LABEL" 8 8
  .Ip "last" 8
  The
***************
*** 2636,2645 ****
--- 2903,2916 ----
  .Ip "link(OLDFILE,NEWFILE)" 8 2
  Creates a new filename linked to the old filename.
  Returns 1 for success, 0 otherwise.
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "listen(SOCKET,QUEUESIZE)" 8 2
  Does the same thing that the listen system call does.
+ .if !'\*(Ms'msdos' \{\
  Returns true if it succeeded, false otherwise.
  See example in section on Interprocess Communication.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "local(LIST)" 8 4
  Declares the listed variables to be local to the enclosing block,
  subroutine, eval or \*(L"do\*(R".
***************
*** 2723,2731 ****
--- 2994,3008 ----
  .Ip "lstat FILEHANDLE" 8
  .Ip "lstat(EXPR)" 8
  .Ip "lstat SCALARVARIABLE" 8
+ .if !'\*(Ms'msdos' \{\
  Does the same thing as the stat() function, but stats a symbolic link
  instead of the file the symbolic link points to.
  If symbolic links are unimplemented on your system, a normal stat is done.
+ \}
+ .if '\*(Ms'msdos' \{\
+ Used to stat symbolic links on Unix.  On MS-DOS, same as
+ .IR stat.
+ \}
  .Ip "m/PATTERN/gio" 8 4
  .Ip "/PATTERN/gio" 8
  Searches a string for a pattern match, and returns true (1) or false (\'\').
***************
*** 2820,2830 ****
--- 3097,3111 ----
  Creates the directory specified by FILENAME, with permissions specified by
  MODE (as modified by umask).
  If it succeeds it returns 1, otherwise it returns 0 and sets $! (errno).
+ .if !'\*(Ms'msdos' \{\
  .Ip "msgctl(ID,CMD,ARG)" 8 4
  Calls the System V IPC function msgctl.  If CMD is &IPC_STAT, then ARG
  must be a variable which will hold the returned msqid_ds structure.
  Returns like ioctl: the undefined value for error, "0 but true" for
  zero, or the actual return value otherwise.
+ .if !'\*(Ms'unix' \{\
+ (The message family is not available under MS-DOS.)
+ \}
  .Ip "msgget(KEY,FLAGS)" 8 4
  Calls the System V IPC function msgget.  Returns the message queue id,
  or the undefined value if there is an error.
***************
*** 2840,2845 ****
--- 3121,3135 ----
  the first thing in VAR, and the maximum length of VAR is SIZE plus the
  size of the message type.  Returns true if successful, or false if
  there is an error.
+ \}
+ .if '\*(Ms'msdos' \{\
+ .Ip "msgctl(ID,CMD,ARG)" 8 4
+ .Ip "msgget(KEY,FLAGS)" 8 4
+ .Ip "msgsnd(ID,MSG,FLAGS)" 8 4
+ .Ip "msgrcv(ID,VAR,SIZE,TYPE,FLAGS)" 8 4
+ These System V inter-process communications functions are not available
+ on MS-DOS.
+ \}
  .Ip "next LABEL" 8 8
  .Ip "next" 8
  The
***************
*** 2995,3004 ****
--- 3285,3296 ----
  	print STDERR "stderr 2\en";
  
  .fi
+ .if !'\*(Ms'msdos' \{\
  If you open a pipe on the command \*(L"\-\*(R", i.e. either \*(L"|\-\*(R" or \*(L"\-|\*(R",
  then there is an implicit fork done, and the return value of open
  is the pid of the child within the parent process, and 0 within the child
  process.
+ .if !'\*(Ms'unix' (This is not supported under MS-DOS.)
  (Use defined($pid) to determine if the open was successful.)
  The filehandle behaves normally for the parent, but i/o to that
  filehandle is piped from/to the
***************
*** 3024,3036 ****
  	open(FOO, "\-|") || exec \'cat\', \'\-n\', $file;
  
  .fi
! Explicitly closing any piped filehandle causes the parent process to wait for the
! child to finish, and returns the status value in $?.
  Note: on any operation which may do a fork,
  unflushed buffers remain unflushed in both
  processes, which means you may need to set $| to
  avoid duplicate output.
  .Sp
  The filename that is passed to open will have leading and trailing
  whitespace deleted.
  In order to open a file with arbitrary weird characters in it, it's necessary
--- 3316,3341 ----
  	open(FOO, "\-|") || exec \'cat\', \'\-n\', $file;
  
  .fi
! \}
! .br
! Explicitly closing any piped filehandle causes the parent process to wait
! for the child to finish, and returns the status value in $?.
  Note: on any operation which may do a fork,
  unflushed buffers remain unflushed in both
  processes, which means you may need to set $| to
  avoid duplicate output.
+ .if !'\*(Ms'unix' \{\
  .Sp
+ On MS-DOS, \*(L"pipes\*(R" are actually files, and the subprocess is
+ run to completion.  For output pipes, the subprocess is run when
+ .IR perl
+ exits or when the pipe is explicitly closed.  For input pipes, the
+ subprogram is run to completion when the
+ .IR open
+ is done.
+ \}
+ .if !'\*(Ms'msdos' \{\
+ .SP
  The filename that is passed to open will have leading and trailing
  whitespace deleted.
  In order to open a file with arbitrary weird characters in it, it's necessary
***************
*** 3040,3047 ****
  .ne 2
          $file =~ s#^(\es)#./$1#;
          open(FOO, "< $file\e0");
- 
  .fi
  .Ip "opendir(DIRHANDLE,EXPR)" 8 3
  Opens a directory named EXPR for processing by readdir(), telldir(), seekdir(),
  rewinddir() and closedir().
--- 3345,3359 ----
  .ne 2
          $file =~ s#^(\es)#./$1#;
          open(FOO, "< $file\e0");
  .fi
+ \}
+ .if !'\*(Ms'unix' \{\
+ .br
+ On MS-DOS,
+ it is recommended that forward slashes be used to delimit path components
+ in file names.
+ (See the section on MS-DOS considerations.)
+ \}
  .Ip "opendir(DIRHANDLE,EXPR)" 8 3
  Opens a directory named EXPR for processing by readdir(), telldir(), seekdir(),
  rewinddir() and closedir().
***************
*** 3145,3150 ****
--- 3457,3463 ----
  The same template may generally also be used in the unpack function.
  .Ip "pipe(READHANDLE,WRITEHANDLE)" 8 3
  Opens a pair of connected pipes like the corresponding system call.
+ .if !'\*(Ms'msdos' \{\
  Note that if you set up a loop of piped processes, deadlock can occur
  unless you are very careful.
  In addition, note that perl's pipes use stdio buffering, so you may need
***************
*** 3151,3156 ****
--- 3464,3471 ----
  to set $| to flush your WRITEHANDLE after each command, depending on
  the application.
  [Requires version 3.0 patchlevel 9.]
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "pop(ARRAY)" 8
  .Ip "pop ARRAY" 8 6
  Pops and returns the last value of the array, shortening the array by 1.
***************
*** 3254,3270 ****
  or a null list in an array context.
  .Ip "readlink(EXPR)" 8 6
  .Ip "readlink EXPR" 8
! Returns the value of a symbolic link, if symbolic links are implemented.
  If not, gives a fatal error.
  If there is some system error, returns the undefined value and sets $! (errno).
  If EXPR is omitted, uses $_.
  .Ip "recv(SOCKET,SCALAR,LEN,FLAGS)" 8 4
  Receives a message on a socket.
  Attempts to receive LENGTH bytes of data into variable SCALAR from the specified
  SOCKET filehandle.
  Returns the address of the sender, or the undefined value if there's an error.
  SCALAR will be grown or shrunk to the length actually read.
  Takes the same flags as the system call of the same name.
  .Ip "redo LABEL" 8 8
  .Ip "redo" 8
  The
--- 3569,3593 ----
  or a null list in an array context.
  .Ip "readlink(EXPR)" 8 6
  .Ip "readlink EXPR" 8
! Returns the value of a symbolic
! .if !'\*(Ms'msdos' \{\
! link, if symbolic links are implemented.
  If not, gives a fatal error.
  If there is some system error, returns the undefined value and sets $! (errno).
  If EXPR is omitted, uses $_.
+ \}
+ .if '\*(Ms'msdos' link.
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "recv(SOCKET,SCALAR,LEN,FLAGS)" 8 4
  Receives a message on a socket.
+ .if !!'\*(Ms'unix' \{\
  Attempts to receive LENGTH bytes of data into variable SCALAR from the specified
  SOCKET filehandle.
  Returns the address of the sender, or the undefined value if there's an error.
  SCALAR will be grown or shrunk to the length actually read.
  Takes the same flags as the system call of the same name.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "redo LABEL" 8 8
  .Ip "redo" 8
  The
***************
*** 3470,3476 ****
  	$^ = \'report1_top\';
  	select(REPORT2);
  	$^ = \'report2_top\';
- 
  .fi
  FILEHANDLE may be an expression whose value gives the name of the actual filehandle.
  Thus:
--- 3793,3798 ----
***************
*** 3480,3485 ****
--- 3802,3811 ----
  
  .fi
  .Ip "select(RBITS,WBITS,EBITS,TIMEOUT)" 8 3
+ .if '\*(Ms'msdos' \{\
+ This calls the Unix select system call, which is not implemented on MS-DOS.
+ \}
+ .if !'\*(Ms'msdos' \{\
  This calls the select system call with the bitmasks specified, which can
  be constructed using fileno() and vec(), along these lines:
  .nf
***************
*** 3525,3530 ****
--- 3851,3867 ----
  The timeout, if specified, is in seconds, which may be fractional.
  NOTE: not all implementations are capable of returning the $timeleft.
  If not, they always return $timeleft equal to the supplied $timeout.
+ \}
+ .if '\*(Ms'both' \{\
+ .Sp
+ (The
+ .I select
+ system call is not implemented on MS-DOS.
+ \}
+ .if !'\*(Ms'unix' \{\
+ (The Systerm V semaphore family is not available under MS-DOS.)
+ \}
+ .if !'\*(Ms'msdos' \{\
  .Ip "semctl(ID,SEMNUM,CMD,ARG)" 8 4
  Calls the System V IPC function semctl.  If CMD is &IPC_STAT or
  &GETALL, then ARG must be a variable which will hold the returned
***************
*** 3531,3536 ****
--- 3868,3877 ----
  semid_ds structure or semaphore value array.  Returns like ioctl: the
  undefined value for error, "0 but true" for zero, or the actual return
  value otherwise.
+ .if !'\*(Ms'unix' \{\
+ .Sp
+ (Note: the Systerm V semaphore family is not available under MS-DOS.)
+ \}
  .Ip "semget(KEY,NSEMS,SIZE,FLAGS)" 8 4
  Calls the System V IPC function semget.  Returns the semaphore id, or
  the undefined value if there is an error.
***************
*** 3549,3575 ****
  
  .fi
  To signal the semaphore, replace "-1" with "1".
! .Ip "send(SOCKET,MSG,FLAGS,TO)" 8 4
  .Ip "send(SOCKET,MSG,FLAGS)" 8
  Sends a message on a socket.
  Takes the same flags as the system call of the same name.
  On unconnected sockets you must specify a destination to send TO.
  Returns the number of characters sent, or the undefined value if
  there is an error.
  .Ip "setpgrp(PID,PGRP)" 8 4
  Sets the current process group for the specified PID, 0 for the current
  process.
  Will produce a fatal error if used on a machine that doesn't implement
  setpgrp(2).
  .Ip "setpriority(WHICH,WHO,PRIORITY)" 8 4
  Sets the current priority for a process, a process group, or a user.
  (See setpriority(2).)
  Will produce a fatal error if used on a machine that doesn't implement
  setpriority(2).
  .Ip "setsockopt(SOCKET,LEVEL,OPTNAME,OPTVAL)" 8 3
  Sets the socket option requested.
  Returns undefined if there is an error.
  OPTVAL may be specified as undef if you don't want to pass an argument.
  .Ip "shift(ARRAY)" 8 6
  .Ip "shift ARRAY" 8
  .Ip "shift" 8
--- 3890,3940 ----
  
  .fi
  To signal the semaphore, replace "-1" with "1".
! \}
! .if '\*(Ms'msdos' \{\
! .Ip "semctl(ID,SEMNUM,CMD,ARG)" 8 4
! .Ip "semget(KEY,NSEMS,SIZE,FLAGS)" 8 4
! .Ip "semop(KEY,OPSTRING)" 8 4
! \}
  .Ip "send(SOCKET,MSG,FLAGS)" 8
  Sends a message on a socket.
+ .if !'(*Ms'msdos' \{\
  Takes the same flags as the system call of the same name.
  On unconnected sockets you must specify a destination to send TO.
  Returns the number of characters sent, or the undefined value if
  there is an error.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
+ .if '\*(Ms'msdos' \{\
+ .Ip "semctl(ID,SEMNUM,CMD,ARG)" 8 4
+ .Ip "semget(KEY,NSEMS,SIZE,FLAGS)" 8 4
+ .Ip "semop(KEY,OPSTRING)" 8 4
+ These System V inter-process communications functions are not available
+ on MS-DOS.
+ \}
  .Ip "setpgrp(PID,PGRP)" 8 4
  Sets the current process group for the specified PID, 0 for the current
  process.
+ .if !'\*(Ms'msdos' \{\
  Will produce a fatal error if used on a machine that doesn't implement
  setpgrp(2).
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "setpriority(WHICH,WHO,PRIORITY)" 8 4
  Sets the current priority for a process, a process group, or a user.
+ .if !'\*(Ms'msdos' \{\
  (See setpriority(2).)
  Will produce a fatal error if used on a machine that doesn't implement
  setpriority(2).
+ \}
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "setsockopt(SOCKET,LEVEL,OPTNAME,OPTVAL)" 8 3
  Sets the socket option requested.
+ .if !'\*(Ms'msdos' \{\
  Returns undefined if there is an error.
  OPTVAL may be specified as undef if you don't want to pass an argument.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "shift(ARRAY)" 8 6
  .Ip "shift ARRAY" 8
  .Ip "shift" 8
***************
*** 3582,3592 ****
--- 3947,3961 ----
  See also unshift(), push() and pop().
  Shift() and unshift() do the same thing to the left end of an array that push()
  and pop() do to the right end.
+ .if !'\*(Ms'msdos' \{\
  .Ip "shmctl(ID,CMD,ARG)" 8 4
  Calls the System V IPC function shmctl.  If CMD is &IPC_STAT, then ARG
  must be a variable which will hold the returned shmid_ds structure.
  Returns like ioctl: the undefined value for error, "0 but true" for
  zero, or the actual return value otherwise.
+ .if !'\*(Ms'unix' \{\
+ (The shared memory family is not available under MS-DOS.)
+ \}
  .Ip "shmget(KEY,SIZE,FLAGS)" 8 4
  Calls the System V IPC function shmget.  Returns the shared memory
  segment id, or the undefined value if there is an error.
***************
*** 3602,3607 ****
--- 3971,3986 ----
  .Ip "shutdown(SOCKET,HOW)" 8 3
  Shuts down a socket connection in the manner indicated by HOW, which has
  the same interpretation as in the system call of the same name.
+ .if !'\*(Ms'unix' (Sockets are not yet supported on MS-DOS.)
+ \}
+ .if '\*(Ms'msdos' \{\
+ .Ip "shmctl(ID,CMD,ARG)" 8 4
+ .Ip "shmget(KEY,SIZE,FLAGS)" 8 4
+ .Ip "shmread(ID,VAR,POS,SIZE)" 8 4
+ .Ip "shmwrite(ID,STRING,POS,SIZE)" 8
+ These System V inter-process communications functions are not available
+ on MS-DOS.
+ \}
  .Ip "sin(EXPR)" 8 4
  .Ip "sin EXPR" 8
  Returns the sine of EXPR (expressed in radians).
***************
*** 3614,3619 ****
--- 3993,4002 ----
  Returns the number of seconds actually slept.
  You probably cannot mix alarm() and sleep() calls, since sleep() is
  often implemented using alarm().
+ ! .if !'\*(Ms'unix' \{\
+ ! Pretty worthless on MS-DOS, as it just wastes the number of seconds
+ ! requested.
+ ! \}
  .Ip "socket(SOCKET,DOMAIN,TYPE,PROTOCOL)" 8 3
  Opens a socket of the specified kind and attaches it to filehandle SOCKET.
  DOMAIN, TYPE and PROTOCOL are specified the same as for the system call
***************
*** 3622,3634 ****
--- 4005,4022 ----
  in a perl library file.
  Return true if successful.
  See the example in the section on Interprocess Communication.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "socketpair(SOCKET1,SOCKET2,DOMAIN,TYPE,PROTOCOL)" 8 3
  Creates an unnamed pair of sockets in the specified domain, of the specified
  type.
+ .if !'\*(Ms'msdos' \{\
  DOMAIN, TYPE and PROTOCOL are specified the same as for the system call
  of the same name.
  If unimplemented, yields a fatal error.
  Return true if successful.
+ \}
+ .if !'\*(Ms'unix' Sockets are not yet supported on MS-DOS.
  .Ip "sort(SUBROUTINE LIST)" 8 9
  .Ip "sort(LIST)" 8
  .Ip "sort SUBROUTINE LIST" 8
***************
*** 3838,3843 ****
--- 4226,4234 ----
  If stat is passed the special filehandle consisting of an underline,
  no stat is done, but the current contents of the stat structure from
  the last stat or filetest are returned.
+ .if !'\*(Ms'unix' \{\
+ (Note that on MS-DOS several of these values are spurious.)
+ \}
  Example:
  .nf
  
***************
*** 3928,3933 ****
--- 4319,4326 ----
  sprintf().
  .Ip "symlink(OLDFILE,NEWFILE)" 8 2
  Creates a new filename symbolically linked to the old filename.
+ .if !'\*(Ms'unix' (Note that MS-DOS does not support symbolic links.)
+ .if !'\*(Ms'msdos' \{\
  Returns 1 for success, 0 otherwise.
  On systems that don't support symbolic links, produces a fatal error at
  run time.
***************
*** 3937,3947 ****
  	$symlink_exists = (eval \'symlink("","");\', $@ eq \'\');
  
  .fi
  .Ip "syscall(LIST)" 8 6
  .Ip "syscall LIST" 8
  Calls the system call specified as the first element of the list, passing
  the remaining elements as arguments to the system call.
! If unimplemented, produces a fatal error.
  The arguments are interpreted as follows: if a given argument is numeric,
  the argument is passed as an int.
  If not, the pointer to the string value is passed.
--- 4330,4344 ----
  	$symlink_exists = (eval \'symlink("","");\', $@ eq \'\');
  
  .fi
+ \}
  .Ip "syscall(LIST)" 8 6
  .Ip "syscall LIST" 8
  Calls the system call specified as the first element of the list, passing
  the remaining elements as arguments to the system call.
! .if '\*(Ms'unix' If unimplemented, produces a fatal error.
! .if '\*(Ms'both' If unimplemented, and on MS-DOS, produces a fatal error.
! .if '\*(Ms'msdos' Not supported on MS-DOS.
! .if !'\*(Ms'msdos' \{\
  The arguments are interpreted as follows: if a given argument is numeric,
  the argument is passed as an int.
  If not, the pointer to the string value is passed.
***************
*** 3956,3961 ****
--- 4353,4359 ----
  	syscall(&SYS_write, fileno(STDOUT), "hi there\en", 9);
  
  .fi
+ \}
  .Ip "sysread(FILEHANDLE,SCALAR,LENGTH,OFFSET)" 8 5
  .Ip "sysread(FILEHANDLE,SCALAR,LENGTH)" 8 5
  Attempts to read LENGTH bytes of data into variable SCALAR from the specified
***************
*** 3976,3981 ****
--- 4374,4385 ----
  To get the actual exit value divide by 256.
  See also
  .IR exec .
+ .if !'\*(Ms'unix' \{\
+ .Sp
+ On MS-DOS, this is implemented using the
+ .I spawn
+ system call.
+ \}
  .Ip "syswrite(FILEHANDLE,SCALAR,LENGTH,OFFSET)" 8 5
  .Ip "syswrite(FILEHANDLE,SCALAR,LENGTH)" 8 5
  Attempts to write LENGTH bytes of data from variable SCALAR to the specified
***************
*** 4005,4013 ****
  .Ip "times" 8 4
  Returns a four-element array giving the user and system times, in seconds, for this
  process and the children of this process.
  .Sp
      ($user,$system,$cuser,$csystem) = times;
! .Sp
  .Ip "tr/SEARCHLIST/REPLACEMENTLIST/cds" 8 5
  .Ip "y/SEARCHLIST/REPLACEMENTLIST/cds" 8
  Translates all occurrences of the characters found in the search list with
--- 4409,4420 ----
  .Ip "times" 8 4
  Returns a four-element array giving the user and system times, in seconds, for this
  process and the children of this process.
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
+ .if !'\*(Ms'msdos' \{\
  .Sp
      ($user,$system,$cuser,$csystem) = times;
! 
! \}
  .Ip "tr/SEARCHLIST/REPLACEMENTLIST/cds" 8 5
  .Ip "y/SEARCHLIST/REPLACEMENTLIST/cds" 8
  Translates all occurrences of the characters found in the search list with
***************
*** 4068,4074 ****
  .Ip "umask EXPR" 8
  .Ip "umask" 8
  Sets the umask for the process and returns the old one.
! If EXPR is omitted, merely returns current umask.
  .Ip "undef(EXPR)" 8 6
  .Ip "undef EXPR" 8
  .Ip "undef" 8
--- 4475,4482 ----
  .Ip "umask EXPR" 8
  .Ip "umask" 8
  Sets the umask for the process and returns the old one.
! .if !'\*(Ms'msdos' If EXPR is omitted, merely returns current umask.
! .if !'\*(Ms'unix' Not supported on MS-DOS.
  .Ip "undef(EXPR)" 8 6
  .Ip "undef EXPR" 8
  .Ip "undef" 8
***************
*** 4095,4100 ****
--- 4503,4509 ----
  .Ip "unlink LIST" 8
  Deletes a list of files.
  Returns the number of files successfully deleted.
+ .if !'\*(Ms'unix' (MS-DOS users should note that open files cannot be deleted.)
  .nf
  
  .ne 2
***************
*** 4102,4107 ****
--- 4511,4517 ----
  	unlink @goners;
  	unlink <*.bak>;
  
+ .if !'\*(Ms'msods' \{\
  .fi
  Note: unlink will not delete directories unless you are superuser and the
  .B \-U
***************
*** 4110,4115 ****
--- 4520,4527 ----
  Even if these conditions are met, be warned that unlinking a directory
  can inflict damage on your filesystem.
  Use rmdir instead.
+ .if !'\*(Ms'unix' (MS-DOS does not support directory unlinking: use rmdir.)
+ \}
  .Ip "unpack(TEMPLATE,EXPR)" 8 4
  Unpack does the reverse of pack: it takes a string representing
  a structure and expands it out into an array value, returning the array
***************
*** 4162,4167 ****
--- 4574,4580 ----
  Changes the access and modification times on each file of a list of files.
  The first two elements of the list must be the NUMERICAL access and
  modification times, in that order.
+ .if !'\*(Ms'unix' (On MS-DOS, the access time field is ignored.)
  Returns the number of files successfully changed.
  The inode modification time of each file is set to the current time.
  Example of a \*(L"touch\*(R" command:
***************
*** 4205,4213 ****
--- 4618,4637 ----
  Waits for a child process to terminate and returns the pid of the deceased
  process, or -1 if there are no child processes.
  The status is returned in $?.
+ .if !'\*(Ms'unix' \{\
+ .Sp
+ Not supported on MS-DOS: subprocesses are run to completion and their status
+ is returned by
+ .IR close ,
+ .IR system ,
+ or
+ .IR \`\` .
+ \}
  .Ip "waitpid(PID,FLAGS)" 8 6
  Waits for a particular child process to terminate and returns the pid of the deceased
  process, or -1 if there is no such child process.
+ .if !'\*(Ms'unix' Not supported on MS-DOS.
+ .if !'\*(Ms'msdos' \{\
  The status is returned in $?.
  If you say
  .nf
***************
*** 4227,4232 ****
--- 4651,4657 ----
  everywhere.  (Perl emulates the system call by remembering the status
  values of processes that have exited but have not been harvested by the
  Perl script yet.)
+ \}
  .Ip "wantarray" 8 4
  Returns true if the context of the currently executing subroutine
  is looking for an array value.
***************
*** 4739,4744 ****
--- 5164,5171 ----
  .Sh "Interprocess Communication"
  The IPC facilities of perl are built on the Berkeley socket mechanism.
  If you don't have sockets, you can ignore this section.
+ .if !'\*(Ms'unix' (Sockets are not yet supported on MS-DOS.)
+ .if !'\*(Ms'msdos' \{\
  The calls have the same names as the corresponding system calls,
  but the arguments tend to differ, for two reasons.
  First, perl file handles work differently than C file descriptors.
***************
*** 4834,4839 ****
--- 5261,5267 ----
  	}
  
  .fi
+ \}
  .Sh "Predefined Names"
  The following names have special meaning to
  .IR perl .
***************
*** 4964,4969 ****
--- 5392,5402 ----
  .I perl
  running this script.
  (Mnemonic: same as shells.)
+ .if !'\*(Ms'unix' \{\
+ On MS-DOS, this is
+ .IR perl 's
+ PSP (program segment prefix) segment.
+ \}
  .Ip $? 8
  The status returned by the last pipe close, backtick (\`\`) command or
  .I system
***************
*** 4972,4977 ****
--- 5405,5413 ----
  call, so the exit value of the subprocess is actually ($? >> 8).
  $? & 255 gives which signal, if any, the process died from, and whether
  there was a core dump.
+ .if !'\(*Ms'unix' \{\
+ MS-DOS users should note that the MS-DOS return values are fudged internally
+ so that $? gives Unix-like results.\}
  (Mnemonic: similar to sh and ksh.)
  .Ip $& 8 4
  The string matched by the last pattern match (not counting any matches hidden
***************
*** 5192,5198 ****
  It initially consists of the arguments to any
  .B \-I
  command line switches, followed
! by the default
  .I perl
  library, probably \*(L"/usr/local/lib/perl\*(R",
  followed by \*(L".\*(R", to represent the current directory.
--- 5628,5636 ----
  It initially consists of the arguments to any
  .B \-I
  command line switches, followed
! by any directories in the PERLLIB environment variable (omitted for
! .IR taintperl ),
! followed by the default
  .I perl
  library, probably \*(L"/usr/local/lib/perl\*(R",
  followed by \*(L".\*(R", to represent the current directory.
***************
*** 5525,5530 ****
--- 5963,5970 ----
  
  .fi
  .Sh "Setuid Scripts"
+ .if '\*(Ms'msdos' Setuid processes are not supported on MS-DOS.
+ .if !'\*(Ms'msdos' \{\
  .I Perl
  is designed to make it easy to write secure setuid and setgid scripts.
  Unlike shells, which are based on multiple substitution passes on each line
***************
*** 5547,5553 ****
  You'll need to either disable the kernel setuid script feature, or put
  a C wrapper around the script.
  .PP
! When perl is executing a setuid script, it takes special precautions to
  prevent you from falling into any obvious traps.
  (In some ways, a perl script is more secure than the corresponding
  C program.)
--- 5987,5995 ----
  You'll need to either disable the kernel setuid script feature, or put
  a C wrapper around the script.
  .PP
! When
! .I perl
! is executing a setuid script, it takes special precautions to
  prevent you from falling into any obvious traps.
  (In some ways, a perl script is more secure than the corresponding
  C program.)
***************
*** 5634,5650 ****
  careful what you print out.
  The tainting mechanism is intended to prevent stupid mistakes, not to remove
  the need for thought.
  .SH ENVIRONMENT
  .I Perl
  uses PATH in executing subprocesses, and in finding the script if \-S
  is used.
  HOME or LOGDIR are used if chdir has no argument.
  .PP
! Apart from these,
  .I perl
  uses no environment variables, except to make them available
  to the script being executed, and to child processes.
! However, scripts running setuid would do well to execute the following lines
  before doing anything else, just to keep people honest:
  .nf
  
--- 6076,6406 ----
  careful what you print out.
  The tainting mechanism is intended to prevent stupid mistakes, not to remove
  the need for thought.
+ \}
+ .if !'\*(Ms'unix' \{\
+ .SH MS-DOS CONSIDERATIONS
+ This section describes the MS-DOS version of
+ .IR perl.
+ MS-DOS
+ .I perl
+ has been tested with MS-DOS versions 3.2, 3.3, 4.01, and 5.0, and
+ should work with 2.0 or higher.  640 K-bytes are needed to get
+ anything done.  MS-DOS 5.0 running in high memory is
+ recommended.
+ .Sh "Command-Line Arguments in MS-DOS"
+ MS-DOS
+ .I perl
+ recognizes the calling conventions of the MKS toolkit, accepting
+ MKS-style arguments and passing MKS-style arguments to subprocesses.
+ (The MKS toolkit is a set of Unix-like tools for MS-DOS, sold by
+ Mortice Kern Systems of Waterloo, Ontario.)
+ The MKS tools support an expanded, upwardly compatible argument-passing
+ convention by which
+ several kilobytes of pre-globbed arguments can be passed to a process,
+ resulting in Unix-like invocation.
+ Arbitrary arguments, for example
+ .B -e
+ commands, can be enclosed in single quotes just as in Unix.  This works
+ even if MKSARGS (see the section on the environment below) is not set.
+ .PP
+ When invoked from a non-MKS tool with MKS tooling present,
+ .I perl
+ will use the MKS glob program (see GLOB in the section on
+ the MS-DOS environment, below) to expand the wildcards.
+ .PP
+ When run on a system that doesn't have MKS tools,
+ .I perl
+ will attempt to expand wildcards it sees in the argument list by using
+ Microsoft's globbing code.  This code is not smart enough to handle
+ single quote marks, making the
+ .B -e
+ switch almost useless.
+ .PP
+ Unix does globbing differently than MS-DOS.  Under Unix and MKS,
+ \*(L"abc*\*(R" matches abc.c,  Under DOS, though, the * won't match \*(L".\*(R"
+ The MKS tools use the former interpretation; the perlglob.exe program
+ distributed with perl and the globbing built in to perl.exe use the latter.
+ (Don't install the distributed perlglob.exe if you are using the MKS tools.)
+ .Sh "File names in MS-DOS"
+ .I Perl
+ scripts should use forward slashes to delimit path name components. (C
+ programmers should note that most MS-DOS compilers support this, too.)
+ MS-DOS
+ .I perl
+ will work with backslashes, but they make code unnecessarily messy since
+ they must be doubled any time they might be interpreted as an
+ escape sequence.
+ Subprograms may or may not like forward slashes: most programs compiled
+ from C source like them fine, but command.com won't take them as
+ command names or as file names in \*(L"internal\*(R" commands.
+ Slashes can be reversed before invoking a subprocess using the perl
+ substution features.
+ Inside
+ .IR perl ,
+ the following name the same file:
+ .nf
+ 
+ .ne 6
+ 	"c:/new/report"
+ 	"c:\\\\new\\\\report"
+ 	\'c:/new/report\'
+ 	\'c:\\new\\report\'
+ 
+ .fi
+ Drive prefixes are optional.  If omitted, the file is sought on the current
+ drive.
+ .Sh "The MS-DOS Environment"
+ MS-DOS
+ .I perl
+ uses a number of environment variables not used by Unix
+ .IR perl .
+ This allows customizing the MS-DOS version, which can be widely distributed
+ in executable form.  (Not everyone who wishes to use
+ .I perl
+ on MS-DOS has the tools to build it from the source code.)
+ Directory and file names in the environment can be delimited with forward
+ or back slashes.
+ Environment variables are interpreted when they are needed.
+ (Exception: creation of TMP from TMPDIR is done at startup.)  Thus the
+ perl script can change them.  For example, if a huge \*(L"pipe\*(R" file is
+ to be created, and there's room on the hard disk (c:) but not the
+ usual TMP, which is a RAM disk, you can write:
+ .nf
+ 
+ .ne 6
+ 	ENV{'TMP'} = "c:/tmp";
+ 	open (HANDLE, "program|");
+ .fi
+ .IP PATH 12
+ This is the semicolon-separated path list.  The current directory is
+ searched first unless MKSARGS is defined and MKS support is
+ compiled in, in which case the current directory is searched
+ only in response to an explicit "." or null path component.
+ (This applies to the
+ .B -S
+ switch as well.)
+ .IP MKSARGS 12
+ Set to 1 enable all MKSisms.  The MKS tools can assume that the
+ other pieces of the toolkit are lying around, but
+ .I perl
+ can't.  (It may be the only MKS-compatible program on a
+ system.)  If have have the MKS tools, you should set this
+ variable.  Perl will recognize and generate MKS compatible
+ arguments in any case, but without the switch will default
+ SLASHC to "-c" instead of "-ce", will fail to run MKS
+ glob, and will run perl's glob instead of the Korn shell
+ to expand expressions like <*.c>.
+ .IP ROOTDIR 12
+ Full drive and path where MKS toolkit is installed.  Example,
+ "c:/mks" or "d:/".  Typically is already set in MKS environment.
+ Used only if MKSARGS is set and GLOB is not.  See GLOB.
+ .IP TMP 12
+ First choice for temporary files, e.g., 'h:\\tmp'.  If not set,
+ uses TMPDIR (see below), if that's not set, the current directory
+ is used.  Swapping also goes here unless EXESWAP is defined.
+ Temporary files are pseudo-pipes, the swap file, and the
+ .B -e
+ file.
+ .IP TMPDIR 12
+ If TMPDIR is set and TMP is not, the following is done internally:
+ .nf
+ 
+ 	( $ENV{'TMP'} = $ENV{'TMPDIR'} ) =~ s,/,\\\\,g;
+ 
+ .fi
+ (Backslashes are reversed as a gesture to intolerant decendents of
+ the perl process.)  Creation of $ENV{'TMP'} from $ENV{'TMPDIR'} is
+ done at perl.exe startup.  Note that the MKS tools use TMPDIR as
+ a first choice; as a gesture of compatibility for non-MKS users,
+ here, it is a second choice.
+ .IP EXESWAP 12
+ First choice for swap out file location.  A RAM disk is
+ a nice choice.  TMP is used if this isn't set.  (See also
+ TMPDIR).  The swap file created the first time swapping is
+ invoked and is left open until perl exits or does an exec.
+ Set to ".off" (note illegal DOS name) to inhibit
+ swapping\*(-- useful for speedy running of small subprocesses.
+ This feature
+ (inhibition) can be turned on and off.  The following example
+ runs \*(L"ls\*(R" using "e:/tmp" as the directory for the swap file.
+ It then runs \*(L"who,\*(R" with swapping disabled.  Finally, it
+ runs \*(L"ps\*(R" with swapping re-enabled.  Note that $ENV{'EXESWAP'}
+ is set to 'yes' but anything other than '.off' would have sufficed.
+ .nf
+ .ne 7
+ 
+ 	$ENV{'EXESWAP'} = 'e:/tmp';
+ 	system "ls";
+ 	$ENV{'EXESWAP'} = '.off';
+ 	system "who";
+ 	$ENV{'EXESWAP'} = 'yes';
+ 	system "ps"; 
+ .fi
+ .IP GLOB 12
+ First choice for MKS globbing program: full path, name,
+ and extension.  Example: "d:/mks/etc/glob.exe".  The perl
+ globbing program (used for <*.c> expansion) is found, as
+ before, via the PATH.  Used only in an MKS environment, and
+ then only when perl is run from a non-MKS program.  Ignored
+ if MKS support compiled out.
+ .IP SHELL 12
+ Full path name and extension of the shell used used for
+ subprocesses when wildcard expansion is required, e.g.,
+ "c:/mks/bin/sh.exe".  If undefined, COMSPEC is used.
+ Presumably this could be the MKS korn shell, but it can
+ be another shell (e.g., 4DOS) and thus SHELL is inspected
+ even if MKS support is compiled out.
+ .IP COMSPEC 12
+ Full path name of DOS command interpreter, e.g.,
+ 'c:\\command.com'  Used only if SHELL is not defined.
+ If not found, '\\command.com' is used.
+ (It is bad practice to allow COMSPEC to default or to
+ have it have anything other than a full drive and path name.  You
+ don't want your programs looking for command.com on alternate
+ drives.)
+ .IP METACHAR 12
+ List of characters that are metacharacters to the SHELL or
+ COMPSPEC.  Used to determine if command can be run directly or
+ if a subshell must be invoked.  If undefined, \\|\<\> is used
+ for COMSPEC and *"\?\<\>\|\(\)\&\]\[\$\#\`\'\\ for SHELL.
+ .IP SLASHC 12
+ The shell option for invoking a command.  Defaults:
+ /c for COMSPEC, MS-DOS version 4.x or better [sic]
+ where
+ .I s
+ is the switch character, for COMSPEC, DOS < 4.0;
+ -ce for SHELL if MKSARGS is set.
+ (The -e needed to get the MKS Korn shell to return the status properly).
+ The default is -c for other SHELLs.  (This is a guess.)
+ .IP PERLLIB 12
+ Directory(ies) containing perl library.  Defaults to
+ /usr/local/lib/perl.  Directories are separated as in PATH:
+ semicolons in MS-DOS, colons in Unix.  For the -P switch,
+ only the first PERLLIB directory (or the default, if there's
+ no PERLLIB) is tried.
+ .Sh "Typical MKS setup (profile.ksh)"
+ .nf
+ # If you're using the MKS stuff, you probably don't have
+ # to do anything other than set MKSARGS and PERLLIB.
+ 
+ export MKSARGS=1
+ # ROOTDIR set by init process or etc.rc or here.
+ export TMPDIR=e:/tmp
+ # EXESWAP left to default to $TMPDIR
+ # GLOB left to default to $ROOTDIR/etc/glob.exe
+ # SHELL set by init process or here.
+ # COMSPEC not used by perl.exe but probably defined for other uses.
+ # METACHAR not defined, left to default.
+ export PERLLIB='c:/lib/perl;d:/usr/me/myperlib'
+ .fi
+ .Sh "Typical non-MKS setup (AUTOEXEC.BAT)"
+ .nf
+ Rem You probably don't need to do anything except set TMP,
+ Rem which you may be doing anyway.
+ 
+ Rem MKSARGS not set
+ Rem ROOTDIR not used
+ set TMP=d:\\tmp
+ Rem EXESWAP left to default to TMP
+ Rem GLOB not used
+ Rem SHELL not set
+ Rem COMPEC set by config.sys SHELL command or by MS-DOS startup.
+ Rem METACHAR not defined, left to default.
+ set PERLLIB=c:/lib/perl;d:/usr/me/myperlib'
+ .fi
+ .Sh "Globbing <> Expressions on MS-DOS"
+ Expressions like <*.c> are expanded by a subshell in Unix.  On MS-DOS
+ there are two cases.  If MKSARGS is defined in the environment and
+ MKS support is compiled in, the SHELL is used,
+ running
+ .I echo
+ piped to
+ .I tr
+ as with the Bourne shell on Unix
+ .IR perl .
+ Otherwise, the supplied perlglob.exe program is run.  This program simply
+ takes the supplied command line, DOS-globs it, and writes the result, to the
+ .I perl
+ process via a \*(L"pipe.\*(R"
+ .Sh "Running Subprocesses on MS-DOS"
+ .I Perl
+ will by default swap itself out almost entirely when it runs a
+ subprocess other than MKS GLOB.  (See the EXESWAP environment variable).
+ The swap file is opened when the first subprocess is run and is left
+ open until
+ .I perl
+ exits or does an
+ IR exec .
+ The command line to be run is scanned for METACHARacters as described
+ above.  If none are found, the subcommand is invoked directly.  If
+ metacharacter(s) are found, a SHELL or COMSPEC is invoked to run the command.
+ 
+ Use of a single
+ .B |
+ in a open() command does not constitute a metacharcter:
+ this is a directive to perl to open a pipe.  The following, too, has
+ no SHELL metacharacters since the subprocess is simply pwd:
+ .nf
+ 
+ chop($direct = \`pwd\`);
+ 
+ .fi
+ Beware of MS-DOS "internal" commands; i.e., those that are built into
+ command.com.  Examples are DIR and COPY.  COMMAND.COM users can use
+ these directly if the command has METACHARacters; if not, you must
+ invoke an explicit command.com.  In the first example below, '>' is
+ a metacharacter.  In the second example, there are no metacharacters and
+ so the internal \*(L"ver\*(R" command must be run with an expliclit
+ COMSPEC.
+ .ne 5
+ .nf
+ 
+ 	system "dir >my.fil";
+ 	system "$ENV{'COMSPEC'} /c ver";
+ 
+ .fi
+ Users of SHELLs other than COMMAND.COM must use
+ the second format to access \*(L"internal\*(R" commands.
+ 
+ Be aware that no wild card expansion is going to be done by command.com
+ usless you're using one of the built-in commands that does it (e.g., COPY).
+ You can use <> expansion to get around this.  Even those who have fancy
+ SHELLs should take note of this, since having
+ .I perl
+ run the SHELL and
+ then the command may use less memory than if perl runs the $SHELL which runs
+ the command:
+ .ne 3
+ .nf
+ 
+ 	$files = <*.c>;
+ 	\`the_com $files\`;
+ .fi
+ \}
  .SH ENVIRONMENT
  .I Perl
  uses PATH in executing subprocesses, and in finding the script if \-S
  is used.
  HOME or LOGDIR are used if chdir has no argument.
+ .IR Perl ,
+ but not 
+ .IR taintperl ,
+ will add PERLLIB to @INC.  PERLLIB is syntactically similar to PATH:
+ it contains a list of directories.
  .PP
! Apart from these, Unix
  .I perl
  uses no environment variables, except to make them available
  to the script being executed, and to child processes.
! .if !'\*(Ms'unix' \{\
! (MS-DOS
! .I perl
! makes heavy use of the environment; refer to the section on MS-DOS
! consdirations.)
! \}
! .if !'\*(Ms'msdos' \{\
! .br
! Scripts running setuid would do well to execute the following lines
  before doing anything else, just to keep people honest:
  .nf
  
***************
*** 5658,5667 ****
--- 6414,6431 ----
  Larry Wall <lwall@netlabs.com>
  .br
  MS-DOS port by Diomidis Spinellis <dds@cc.ic.ac.uk>
+ and Len Reed <holos0!lbr@gatech.edu>
  .SH FILES
  /tmp/perl\-eXXXXXX	temporary file for
  .B \-e
  commands.
+ .if !'\*(Ms'unix' \{\
+ $TMP/plXXXXXX		temporary file for
+ .B \-e
+ commands (MS-DOS).
+ $TMP/swpXXXXX		swap file (MS-DOS)
+ $TMP/ppXXXXXX		\*(L"pipe\*(R" files (MS-DOS)
+ \}
  .SH SEE ALSO
  a2p	awk to perl translator
  .br
***************
*** 5676,5685 ****
--- 6440,6451 ----
  switches, each
  .B \-e
  is counted as one line.)
+ .if !'\*(Ms'msdos' \{\
  .PP
  Setuid scripts have additional constraints that can produce error messages
  such as \*(L"Insecure dependency\*(R".
  See the section on setuid scripts.
+ \}
  .SH TRAPS
  Accustomed
  .IR awk
