📄 batch.c
字号:
/*
; File : $Workfile: BATCH.C$
;
; Description :
;
; Original Author : DIGITAL RESEARCH
;
; Last Edited By : $CALDERA$
;
;-----------------------------------------------------------------------;
; Copyright Work of Caldera, Inc. All Rights Reserved.
;
; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
; CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
; *** Current Edit History ***
; *** End of Current Edit History ***
;
; $Log$
; ENDLOG
*/
/*
* 27 Oct 87 Improve GOTO command to ignore trailing white space, only
* match on the first 8 characters and only allow valid
* filename characters.
* 28 Oct 87 Correct duplicate prompt display when a batch file label
* is read and the echo flag is ON.
* 9 Nov 87 Change Batch file termination so that Output Redirection is
* correctly handled.
* 13 Jan 88 If prompt display is aborted because of a critical error
* the following prompt will be forced to "$n$g".
* 25 Jan 88 Support redirection on the FOR command correctly
* 24 Feb 88 Generate batch file parameter %0 correctly as WS200 install
* requires that the drive specifier be present. Garry Silvey
* 5 May 88 Batch paramater %0 is now a copied from the invoking command
* line.
* 18 May 88 Support the ESC_CHAR in the command line.
* 20 May 88 Disable MULTI_CHAR support in DOSPLUS when the user enters the
* first command.
* 26 May 88 Added STACK switch and support $q in prompt.
* 27 May 88 Added string undefs.
* 6 Jun 88 Call resident portion to do readline (SideKick+ problem)
* 23 Jun 88 Support CR only delimited batch files and if errorlevel ==
* syntax used in installation files.
* 6 Jul 88 Support the FOR ... CALL syntax correctly. (IMS)
* 17 Aug 88 Jump to labels followed by comments (Ashton Tate By-Line)
* 21 Sep 88 Use KEYIN_FLG to allow the default ECHO state to be ON.
* 16 Nov 88 Disable BACK_CHAR in Concurrent DOS.
* 21 Dec 88 Allow leading whitespace before labels
* 5 Jan 89 Support Quoted strings in Batch files.
* 18 Apr 89 Support Quoted strings in IF command
* 19 Apr 89 Quotes in IF command: "x == "x" parses, "x=x" == "x.. doesn't
* 24 Apr 89 Increase MAX_LINE to 128 for pctools ver 5
* 19 May 89 Take out support for quoted strings in IF command
* 05 Jun 89 Do not echo command or display the prompt during FOR command.
* Restore support for batch files with long lines.
* 02 Nov 89 batch_line bodge which substitutes 0xFF for 0x00 changed - we
* now substitute '\r\n', then throw away rest of the line.
* 01 Dec 89 batch_line - trailing % at end of line is discarded
* 15 Dec 89 "if errorlevel -1" allowed
* 30 Jan 90 Added int2e_start and int2e_finish to save and restore
* important batch file variables to allow novell menu program
* to use int 2e to invoke batch files.
* 30 Jan 90 Forced batch data structures to appear on segment boundaries;
* Added dummy memory descriptor before batch structure;
* Put segment address of batch structure in batch_seg_ptr;
* All so novell can find and patch the drive letter of
* autoexec.bat during a remote boot.
* 6-Mar-90 Watcom C v 7.0
* 7-Mar-90 allow ESC_CHAR through unless followed by MULTI/BACK_CHAR
* 14-Mar-90 Reduce batch_buf to 32 bytes like wot dos is
* 20-Mar-90 Batch structures allocated by mem_alloc (ie. MS_M_ALLOC)
* rather than on heap. Batch file nesting no longer heap limited.
* 27-Mar-90 Allow "=", "==", "===" etc in "if errorlevel==n"
* 10-Apr-90 Make errorlevel 999 same as errorlevel 231 (mod 256)
* 8-May-90 Don't echo getcmd unless batch file (eg. "dir|more" shouldn't
* echo "C:>more")
* 23-May-90 batch_read no longer repeatedly deblanks line (which leads
* to the buffer happily wandering up memory).
* 30-May-90 "if ab de==ef" form doesn't generate syntax error
* 13-Jun-90 batch_line rejects unmatched "|" as syntax error
* 20-Sep-90 is_filechar() and is_pathchar() now take pointer instead of byte
* Changed batch_char() to return pointer instead of byte,
* renamed to batch_ptr().
* Amended make_label(), batch_start() and cmd_for() to check for
* DBCS lead bytes.
* 24-Sep-90 Add $m and $u option to PROMPT to display status of mail
and user name respectively
* 27-Sep-90 Add IF USERID <userid> COMMAND
IF LOGINNAME <loginname> COMMAND
IF GROUPNAME <groupname> COMMAND
IF ASK ["string"] <char> COMMAND
.. AND .. OR .. to IF processing
INPUT ["string"] <environment-variable>
INPUTC ["string"] <environment-variable>
* 10-Oct-90 inherit batch files from TMP when TSR auto-loads CDOS.COM
(a bodge for Stellar)
* 25-Oct-90 inherit echoflg from TMP when TSR auto-loads CDOS.COM
* 31-Oct-90 change IF ASK command to IF KEY command
DRDOS BUXTON
------------
* 25-Apr-91 '!' is now ignored during COMMAND /C processing.
* 28-May-91 leading white space is now ignored before labels.
* 09-Jun-91 Added GOSUB, RETURN and SWITCH commands.
* 24-Jul-91 if batch_seg_ptr is poked to zero all batch processing is
terminated.
* 26-Jul-91 batch files are now read into a far buffer. This avoids
reading directly to seg FFFF if we happen to be there and so
solves some NOVELL problems.
* 18-Jun-92 Support ? in batch files as in config.sys.
* 23-Jun-92 $u in prompt causes LOGINNAME in environment to be displayed.
* 07-Jul-92 IF EXIST now finds hidden files.
*/
#include "defines.h"
#include <string.h>
#if defined(MWC) && defined(strlen)
#undef strcmp /* These are defined as macros in string.h */
#undef strcpy /* which are expanded in line under */
#undef strlen /* Metaware C. These undefs avoid this. */
#endif
#include <portab.h>
#if !defined(DOSPLUS)
#include <ccpm.h>
#endif
#include "command.h"
#include "toupper.h"
#include "support.h"
#include "dosif.h"
#include "global.h"
#include "dos.h"
#include <setjmp.h>
/*RG-01*/
#if defined(CDOSTMP) || defined(CDOS)
#include <pd.h>
#define PATH_LEN 65 /* max path length (null terminated) */
EXTERN PD FAR * CDECL pd; /* Far pointer to Current PD */
EXTERN VOID CDECL cmd_set(BYTE *); /* COMINT.C */
#if !defined (NOSECURITY)
#include "security.h"
#include "login.h"
#endif
#endif
/*RG-01-end*/
EXTERN VOID CDECL cmd_pause();
EXTERN BOOLEAN parse(BYTE *);
EXTERN UWORD boot_key_scan_code; /* in COM.C */
/*RG-03*/
BOOLEAN if_context=FALSE;
BOOLEAN ifcond=FALSE;
/*RG-03-end*/
EXTERN jmp_buf break_env;
#define MAX_LINE 128 /* Maximum No of Chars in input line */
#if defined(CPM)
EXTERN UWORD user; /* USER Number variable for CPM.EXE */
#endif
EXTERN BYTE msg_prmeq[]; /* Static Environ String "PROMPT=" */
#if 0
#define FCONTROL struct fcc
MLOCAL FCONTROL {
BOOLEAN sflg; /* FOR File Search Flag */
DTA search; /* FOR Search structure */
BYTE *files; /* FOR File list */
BYTE *cmd; /* FOR Command Line */
BYTE forvar; /* FOR variable char */
};
#endif
MLOCAL FCONTROL *forptr;
#if 0
#define BCONTROL struct bcc
GLOBAL BCONTROL {
BCONTROL FAR *bcontrol; /* Previous Batch Control Structure */
BOOLEAN eof; /* End of File Flag */
LONG offset; /* Offset in BATCH file */
LONG ret_offset[4]; /* return offset from gosub */
BYTE *batcmd; /* Batch File Input parameters */
UWORD batshift; /* Shift Offset */
BYTE batfile[MAX_PATHLEN]; /* Batch File Name */
UWORD stream; /* Stream for this Batch File */
FCONTROL *fcontrol; /* Pointer to previous FOR command */
BYTE *heap_start; /* Heap pointer before extra bytes */
WORD heap_size; /* are added to shift to segment */
BYTE save_area[1]; /* boundary. - EJH */
} FAR *batch, FAR *batch_save; /* Master Batch Control Stucture */
#endif
/* Handle 255 is closed */
#define CLOSED 0xff
/* Keyboard Variables */
GLOBAL BYTE kbdbuf[MAX_LINE+2]= {0};/* Keyboard Input Buffer */
GLOBAL BYTE *kbdptr = kbdbuf+2; /* Keyboard Buffer Pointer */
MLOCAL BOOLEAN keyin_flg = FALSE; /* This flag is set to TRUE when the */
/* initial command line buffer setup */
/* by INIT() has been exhausted. */
MLOCAL WORD batchflg_save; /* Used during INT 2E handling. */
MLOCAL WORD echoflg_save; /* ditto above */
GLOBAL WORD echoflg_save2; /* saves echo state when batch file */
/* execed. */
/*
* Batch file buffering control structures.
*/
MLOCAL LONG batch_off; /* Offset of buffered data in File */
MLOCAL WORD batch_cnt = 0; /* Number of bytes in buffer */
MLOCAL BYTE batch_buf[32];
MLOCAL BYTE batch_eof[] = "\x1a"; /* End of file string */
MLOCAL BYTE batch_sep[] = "\t ;,="; /* Batch Command line option delimiters */
EXTERN VOID CDECL cmd_ver(BYTE *); /* COMINT.C Display Version */
EXTERN VOID docmd(BYTE *, BOOLEAN); /* COM.C */
EXTERN VOID CDECL int_break(VOID); /* COM.C */
GLOBAL BOOLEAN getcmd(BYTE *);
GLOBAL VOID for_end();
GLOBAL VOID batch_start(BYTE *, BYTE *, BYTE *);
GLOBAL VOID batch_end(VOID);
GLOBAL VOID batch_close(VOID);
MLOCAL VOID for_in(BYTE *);
MLOCAL WORD batch_open(VOID);
MLOCAL VOID batch_read(BYTE *, BOOLEAN);
MLOCAL VOID batch_line(BYTE *, BOOLEAN);
MLOCAL BYTE *batch_ptr(VOID);
MLOCAL VOID prompt(VOID);
MLOCAL BOOLEAN novell_extension(BYTE *, BYTE *);
#if !defined(CDOSTMP)
EXTERN UWORD FAR *batch_seg_ptr; /* For novell remote boot. see CSTART.ASM */
#endif
#if defined(CDOS) || defined(CDOSTMP)
#define TmpPspEchoFlgPtr 0x58 /* Magic location to keep echo flag */
#define TmpPspDataSeg 0x5a /* Magic location to keep Data Seg */
#define TmpPspBatchSeg 0x5c /* Magic location to keep Batch Ptr */
#define TmpPspMpad 0x5e /* Magic location to keep unlinked MPAD */
#endif
#if defined(CDOS)
typedef struct _mpad
{
UWORD link; /* address of next MPAD */
UWORD start; /* seg of allocation unit */
UWORD length; /* length in paras */
UWORD res0x06; /* reserved */
UWORD xios; /* Process id */
} MPAD;
GLOBAL VOID inherit_TMP_state(VOID);
#endif
/*.pa*/
GLOBAL BOOLEAN getcmd(line) /* read command line */
BYTE *line;
{
BYTE *s;
BOOLEAN quote = FALSE;
BOOLEAN cancel_prompt = FALSE;
#if defined(DOSPLUS)
WORD i;
BYTE cmd_name[16];
#endif
back_flag = FALSE; /* Disable BackGround Processing*/
*line = '\0';
FOREVER {
if(for_flag) { /* If Processing a FOR command */
for_in(line); /* then call then use the FOR_IN*/
return NO; /* routine to fill the keyboard */
} /* buffer and then return */
if(!batchflg) /* If no batch processing then */
break; /* skip further tests */
batch_restart:
#if defined(DOSPLUS)
if (!*batch_seg_ptr) { /* if batch_seg_ptr has been set to */
batch_endall(); /* zero terminate all batch files */
return NO;
}
#endif
if(batchflg && batch->eof) { /* Close the batch file if at */
batch_end(); /* the end of the file. */
if(batchflg == 0) /* BREAK if batch processing */
return NO; /* is complete. */
continue;
}
if(!batch_open()) /* Open the file and read a line*/
return YES; /* from the file */
batch_read(line, NO); /* Read Line */
if(batch->eof) /* If the end of the batch file */
batch_close(); /* has been detected then close */
/* the file. */
if (*line == '?' || boot_key_scan_code == 0x4200) {
optional_line(line);
}
if(*line == '@') { /* If first character in the */
strcpy(line, line+1); /* command line is '@' donot */
return NO; /* echo the command and move the*/
} /* string down 1 character. */
if (!cancel_prompt) {
if(crlfflg && echoflg)
crlf();
prompt();
}
return echoflg;
}
if(!*kbdptr) { /* Set the Keyboard Input flag */
keyin_flg = TRUE; /* after a initial command line */
/* buffer has been exhausted */
#if 1
if (c_option) { /* insert an EXIT command if we */
kbdptr = &kbdbuf[2]; /* are processing a /C command */
strcpy(&kbdbuf[2],"exit");
}
#endif
}
if (!*kbdptr) { /* Check for existing line */
/* NEIL */
if(crlfflg && echoflg)
crlf();
/* NEIL end */
prompt(); /* issue command line prompt */
allow_pexec = FALSE;
/* $x in prompt string may cause batchflg to be set. */
/* If so we must jump to batch processing code. */
if (batchflg) {
cancel_prompt = TRUE;
goto batch_restart;
}
kbdptr = ""; /* Force KBDPTR to point to '\0'*/
/* in case we get ABORTED and */
/* drop through here again. */
kbdbuf[0] = MAX_LINE; /* set max. input length */
kbdbuf[kbdbuf[1]+2] = '\r'; /* Terminate current line. */
#if defined(CDOSTMP)
system(C_READSTR, kbdbuf); /* read a line */
#else
readline(kbdbuf);
#endif
crlf();
kbdbuf[kbdbuf[1] + 2]='\0'; /* terminate input */
kbdptr = kbdbuf + 2;
}
s = kbdptr;
while(*s) {
if(*s == '"') /* Check for a " character and */
quote = !quote; /* update the flag correctly */
#if !defined(DOSPLUS)
if(*s == ESC_CHAR && /* If the Escape character has */
!quote && /* been specified then do not */
((*(s+1) == MULTI_CHAR) || (*(s+1) == BACK_CHAR))) {
*line++ = *++s; /* process the following char. */
s++;
continue;
}
#endif
#if defined(DOSPLUS) /* Disable MULTI_CHAR support */
if(!(keyin_flg||c_option||k_option))
/* after the init command line */
#endif /* has been exhausted. */
if(*s == MULTI_CHAR && /* If a Multiple command char */
!quote) { /* and the QUOTE flag is FALSE */
s++; /* then break the command here */
break; /* and save the rest of the line*/
} /* for next time. */
#if FALSE /* defined(CDOSTMP) */
if(*s == BACK_CHAR && /* If a Back Ground processing */
!quote) { /* and the QUOTE flag is FALSE */
s++; /* then treat as for MULTI_CHAR */
back_flag = TRUE; /* except that the current */
break; /* command is executed in the */
} /* background. */
#endif
if(*s == PIPE_CHAR && /* If a Pipe enable character */
!quote) { /* and the QUOTE flag is FALSE */
s++; /* then break the command here */
pipe_out = YES; /* and save the rest of the line*/
break; /* for next time. */
}
copy_char(&line, &s); /* Just save the character */
}
*line = '\0'; /* Terminate the Buffer */
kbdptr = deblank(s); /* Copy the possibly null length*/
return NO; /* string to KBDBUF for next */
/* next invocation and save CCP */
}
MLOCAL VOID for_in(line) /* A FOR command is currently */
BYTE *line; /* executing so build the line */
{ /* from the internal FOR data */
BYTE *s,*t; /* initialized by CMD_FOR */
BYTE *bp1, *fp;
WORD i;
FOREVER {
fp = forptr->files; /* Get the next string and stop */
if(strlen(fp) == 0) { /* if its the zero length string */
*line = '\0'; /* which marks the end of the FOR */
crlfflg = YES; /* search list. */
for_end();
return;
}
if(!iswild(fp)) { /* If not an ambiguous file */
forptr->sflg = NO; /* then update the FOR */
forptr->files += strlen(fp)+1; /* pointer to the next file */
break; /* in the search list. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -