/* File : $Workfile: COM.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$ * COM.C 1.2 97/03/21 14:41:21 * Added /n option to disable critical error handler * COM.C 1.59 94/12/01 10:05:21 * Removed closing handles 5 and 6 in error_code() in order to be able * to continue with a batch file if the user wants to. JBEULICH * Enabled UNC filenames * COM.C 1.58 94/08/10 14:49:22 * After first run through looking for a file to execute, now strips the D: * off the path, if only a drive and not a directory is specified. So, if you * type D:TEST, it will look for TEST on the current directory of drive D:, then * continue to search the path. It will only skip searching the path if a * specific directory is specified. * COM.C 1.57 94/03/29 16:12:11 * docmd_int2f in CSTART.ASM returns 1 if it has been accepted. * In this case, we don't want it, so docmd_offer returns TRUE. * All cases of docmd_offer return if TRUE, so we don't process * the line ourselves. * COM.C 1.56 94/02/08 11:50:17 * Fixed a problem where typing COMMAND DIR A: after giving the correct error * message for DIR being an incorrect loadpath, tries to access A: and crashes * under /MULTI. * Break added after error message to fix crashing problem. * Variable lferror added so that after an incorrect loadpath, it does not use * the next bit (ie. A:) as keyboard input. * COM.C 1.54 93/12/09 18:07:04 * Fixed a bug which screwed the upper memory link if you entered c:lh dir * COM.C 1.53 93/12/01 23:14:02 * Fix parsing bug "outfile command" would fail * COM.C 1.49 93/12/01 11:32:08 * Now do a flush cache call before displaying prompt. * COM.C 1.48 93/12/01 00:17:17 * docmd_offer() will do an int 2F/AE (2 if external) within batch files * SPR: 811218, shouldn't access drive whatever the prompt * COM.C 1.45 93/11/19 21:08:14 * Put code to report "Syntax Error" for "| command" and "command |" back to * it's original state. * COM.C 1.43 93/11/08 23:59:19 * F8 key now only affects autoexec, not 1st batch file * COM.C 1.42 93/11/05 13:03:00 * Fix problem with /P /MH (missing break;....) * COM.C 1.41 93/11/05 00:44:07 * /MU option only valid with /P option. The problem is if you "exit" with upper * memory unlinked the resident portion isn't freed, and you eat upper memory. * COM.C 1.40 93/10/29 17:05:51 * Add PROMPT=$P$G and PATH=d:\NWDOS to default env * COM.C 1.39 93/10/22 11:51:30 * Changed Beta string from 3 to 4 * COM.C 1.36 93/09/15 18:56:39 * FOR command now allows any char in brackets. eg for %%v in (+ -) do... * COM.C 1.34 93/08/26 09:39:05 * Now use PSP for stack during func 4b exec. There's some debug * code in case things screw up. * COM.C 1.30 93/07/05 08:32:57 * Memory allocation strategy now restored if ctrl-c pressed during a hiload. * COM.C 1.25 93/05/24 11:34:43 * psp now points to itself when /P isn't specified. * COM.C 1.24 93/05/17 11:22:28 * Added support for F5 and F8 being pressed during boot-up. * COM.C 1.23 93/04/22 14:51:10 * Now close handles 5-19 after an exec. * echoflg is now correctly preserved when batch files are chained. See * echoflg_save2. * COM.C 1.19 93/01/21 14:29:44 * Now do INT 21 ah=29 when changing default drive. * COM.C 1.16 92/11/25 09:30:15 * Password support enabled/disabled by #if defined(PASSWORD) statements. * HOMEDIR support disabled. * COM.C 1.12 92/09/25 19:48:56 * Removed .cmd from search order if DOSPLUS defined. * Fixed bug when ;; appears in path. * COM.C 1.11 92/09/17 11:30:14 * Piping a batch file through MORE no longer stops with Syntax Error * displayed. * COM.C 1.10 92/09/11 10:43:41 * COMMAND /P: disables time and date prompt and copyright message. * COMMAND ? no longer hangs. * ENDLOG */ #include "defines.h" #if 0 #if defined(DLS) #define MSG_VER 111 /* required message file version No. */ #else #define MSG_VER msg_ver111 /* required message file version No. */ extern char *MSG_VER; #endif #endif #include #include #if defined(MWC) && defined(strlen) #undef strcmp /* These are defined as macros in string.h */ #undef strcpy /* which are expaneded in line under */ #undef strlen /* Metaware C. These undefs avoid this. */ #endif #include #include #if !defined(DOSPLUS) #include #include #endif #include "command.h" /* Command Definitions */ #include "support.h" /* Support routines */ #include "dos.h" /* MSDOS function definitions */ #include "dosif.h" /* DOS interface definitions */ #include "toupper.h" #include "global.h" /* Global Variables */ /* RG-00- */ #define PATH_LEN 65 /* max path length (null terminated) */ #if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) #include #include "security.h" #include "login.h" #endif /* RG-00- end */ MLOCAL BYTE valid_sepchar[] = ":.;,=+"; #if defined(DOSPLUS) /* we now define initial */ MLOCAL BYTE PATH_DIR[] = "A:\\OPENDOS"; MLOCAL BYTE SET_PATH[] = "PATH=%s"; MLOCAL BYTE SET_PROMPT[] = "PROMPT=$P$G"; MLOCAL BYTE SET_OS[] = "OS=OPENDOS"; /* environment in COMMAND */ MLOCAL BYTE SET_VER[] = "VER=7"; /* not in BIOSINIT */ #if !defined(FINAL) MLOCAL BYTE SET_BETA[] = "BETA=Beta 4"; #endif #endif GLOBAL jmp_buf break_env; #if defined(DOSPLUS) EXTERN UWORD _psp; EXTERN VOID *batchptr_off; EXTERN VOID *batchflg_off; EXTERN VOID *echoflg_off; EXTERN UWORD FAR *batch_seg_ptr; #endif /*RG-03*/ EXTERN BOOLEAN if_context; /* BATCH.C */ /*RG-03-end*/ #if defined(DOSPLUS) EXTERN VOID CDECL show_help(WORD); /* CSTART.ASM */ EXTERN VOID CDECL put_resident_high(WORD); /* CSTART.ASM */ EXTERN BYTE FAR * CDECL get_config_env(VOID); /* CTSART.ASM */ EXTERN UWORD CDECL get_original_envsize(VOID); EXTERN VOID CDECL copy_crit_msgs(VOID); /* CSUP.ASM */ EXTERN VOID CDECL copy_rld_msgs(VOID); /* CSUP.ASM */ EXTERN WORD CDECL dos_parse_filename(BYTE *); EXTERN UWORD CDECL docmd_int2f(BYTE *, BYTE *, UWORD); #endif EXTERN void CDECL flush_cache(void); EXTERN BYTE *kbdptr; EXTERN BYTE msg_patheq[]; /* Static Environ String "PATH=" */ EXTERN S_CMD cmd_list[]; /* CMDLIST.C */ #if defined(DOSPLUS) EXTERN VOID inherit_parent_state(); #endif EXTERN WORD echoflg_save2; EXTERN VOID batch_start(BYTE *, BYTE *, BYTE *); EXTERN VOID batch_end(VOID); /* BATCH.C */ EXTERN VOID batch_endall(VOID); /* BATCH.C */ EXTERN VOID batch_close(VOID); /* BATCH.C */ EXTERN VOID for_end(VOID); /* BATCH.C */ EXTERN BOOLEAN getcmd(BYTE *); /* BATCH.C */ #if !defined(CDOSTMP) EXTERN VOID int2e_start(); /* BATCH.C */ EXTERN VOID int2e_finish(); /* BATCH.C */ #endif EXTERN VOID CDECL cmd_cd(BYTE *); /* COMINT.C */ EXTERN VOID CDECL cmd_ver(); /* COMINT.C */ EXTERN VOID CDECL cmd_set(BYTE *); /* COMINT.C */ GLOBAL VOID docmd(BYTE *, BOOLEAN); /* COM.C */ MLOCAL VOID cmd_loop (BYTE *); /* COM.C */ MLOCAL VOID error_code(UWORD); /* COM.C */ MLOCAL VOID cmd_cleantp(VOID); /* COM.C */ GLOBAL BOOLEAN parse(BYTE *); /* COM.C */ MLOCAL VOID init(BYTE *); /* COM.C */ MLOCAL BOOLEAN doexec(BYTE *, BYTE *, UWORD, BYTE *); #if !defined(CDOSTMP) MLOCAL BYTE msg_comspec[] = "COMSPEC="; /*EXTERN BYTE *reload_file; CSTART.ASM */ EXTERN VOID CDECL get_reload_file(VOID); /* CSUP.ASM */ EXTERN VOID CDECL set_reload_file(VOID); /* CSUP.ASM */ EXTERN VOID CDECL get_out_pipe(VOID); /* CSUP.ASM */ EXTERN VOID CDECL install_perm(VOID); /* CSTART.ASM */ EXTERN VOID CDECL master_env(UWORD); /* CSTART.ASM */ GLOBAL WORD CDECL findfile(BYTE *, UWORD *); /* COM.C for MS-DOS */ MLOCAL WORD checkfile(BYTE *, UWORD *, BYTE *, BYTE *, BYTE *, BYTE *); EXTERN BYTE cbreak_ok; /* control break handler initialised */ #else EXTERN WORD CDECL findfile(BYTE *, UWORD *); /* DOSIF.A86 (P_PATH) */ EXTERN VOID network_init(VOID); /* NETWORK.C */ EXTERN PD FAR * CDECL pd; /* Far pointer to Current PD */ MLOCAL BOOLEAN system_init = TRUE; #endif EXTERN BYTE FAR * CDECL farptr(BYTE *); EXTERN BYTE FAR * CDECL cgroupptr(BYTE *); #if defined(CPM) EXTERN UWORD CDECL cpm_init(VOID); /* CP/M Init Routine */ #endif #if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) /* global VC data */ UWORD vc_base; /* first vc number for this station */ UWORD num_of_vcs; /* number of vcs on this station */ #endif #if !defined(CDOSTMP) BYTE autoexec_name[13] = "autoexec.bat"; #endif #if defined(DOSPLUS) UWORD boot_key_scan_code = 0; #endif #if !defined(FINAL) void save_psp(void); void check_psp(void); WORD psp_xsum; #endif VOID FAR CDECL _main(cmd) BYTE *cmd; { BYTE cmd_buf[128]; #if defined(CDOSTMP) /* Insure the NETWORK_INIT */ network_init(); /* function is called before */ #endif /* any disk activity so that */ /* Diskless DRNET systems can*/ /* be generated. */ #if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) /* get the VC data and make global */ vc_data(&vc_base, &num_of_vcs, &station); #endif #if defined(DOSPLUS) && defined(DLS) copy_crit_msgs(); copy_rld_msgs(); #endif init(cmd); /* Initialize COMMAND.??? */ #if defined(CPM) if(cpm_init()) { /* If this is the CP/M Media */ eprintf(MSG_SINGLECPM); /* Access program then call */ ms_x_exit(1); /* the CPM_INIT function */ } #endif ms_drv_set(drive); /* try to set default drive */ FOREVER { error_code(setjmp(break_env)); /* Initialize Error Handler */ #if !defined(CDOSTMP) cbreak_ok = TRUE; /* we can handle break now */ #endif #if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) #if defined(CDOSTMP) ms_drv_set(drive); /* try to set default drive */ /* Ensure we are the foreground process on the Virtual Console */ /* before displaying login prompt. */ if(login_enabled()) { disable_vc_switch(); /* stop user switching to another console */ /* if 1st time through on VC 0 then run system autoexec */ if (system_init) { login_save_initial_state(); if (pd->P_CNS==0) { /* log this event */ logevent("",LOG_POWERON); /* process system Autoexec.bat */ while (*kbdptr || batchflg) cmd_loop (cmd_buf); } system_init = FALSE; } if(waiting_on_login() && !background_proc()) login_station(); /* login station */ login_consoles(); /* initialise all VCs */ enable_vc_switch(); } #endif FOREVER { error_code(setjmp(break_env)); /* Initialize Error Handler */ if (login_enabled()) { if(!logged_in()) /* keep going until logged out */ break; } #endif cmd_loop (cmd_buf); #if !defined(NOSECURITY) && (defined(CDOSTMP) || defined(CDOS)) } if(login_enabled()) { /* kill off any remaining batch processes still running */ while (batchflg) cmd_exit(""); #if defined(CDOSTMP) /* the logout event */ if(!background_proc()) logout(); #else return; /* CDOS.COM just dies when logout happens */ #endif } #endif } } /*MLOCAL*/ VOID cmd_loop (cmd) BYTE *cmd; { WORD echoing; REG BYTE *cmdline; BYTE first_ch; cmd_cleanup(); /* Cleanup after the command */ cmdline = cmd; if (!batchflg) flush_cache(); echoing = getcmd(cmdline); /* do not echo Labels */ first_ch = *deblank(cmdline); if((pipe_out && !batchflg && !*deblank(kbdptr)) || /* if "|" */ (pipe_in && (first_ch == 0 || first_ch == ':'))) { /* or "|" */ eprintf(MSG_SYNTAX); /* report syntax error */ pipe_out = NO; /* forget about pipes */ pipe_in = NO; if (!batchflg) *kbdptr = '\0'; /* discard rest of line */ crlfflg = YES; /* remember to do a LF */ return; /* stop now before echo */ } if(echoing && first_ch != ':') { /* Echo command line if ECHO */ puts(cmdline); /* ON and source not keyboard*/ crlf(); /* and not a label */ } crlfflg = NO; /* NO CR/LF req'd */ cmdline = deblank(cmdline); /* remove leading spaces */ if(*cmdline && *cmdline != ':') /* Check for a command */ { /* not a LABEL */ if (!strnicmp(cmdline,"IF",2)) docmd(cmdline,YES); else { if(!parse(cmdline)) { /* If the Parse succeeds then*/ docmd(cmdline, YES); /* execute the command. */ } } } } /*.pa*/ /* * */ #define COMMAND_P (cflag & 1) /* Permanent Flag */ #define COMMAND_C (cflag & 2) /* One Command Option */ #define COMMAND_T (cflag & 4) /* CDOS TSR option */ MLOCAL VOID init(cmd) BYTE *cmd; { UBYTE console = 1; /* Concurrent Console No. +1 */ SYSDATE date; /* System Date Structure */ WORD ret; /* General Variable */ UWORD cflag; BYTE *s; #if defined(CDOSTMP) UWORD vc_base, vc_num, pc_num; /* Virtual Console Data */ #else BYTE buf[MAX_ENVLEN], c; UWORD envsize = 256; #endif #if defined(DOSPLUS) BOOLEAN no_timedate = FALSE; WORD prh_function = 0; UWORD FAR *p_batch_seg; #endif BYTE lferror = 0; strcpy(kbdptr, ""); /* start with no commands */ #if 0 #if defined(DLS) dls_msg_ver(MSG_VER); /* check message file version*/ #else s = MSG_VER; /* ensure label is referenced */ #endif #endif #if defined(CDOS) ret = ioctl_ver(); if(ret < 0x1450 || ret > 0x1499) { /* Get the CDOS BDOS Version */ eprintf(MSG_BADOS); /* and quit if it is not 5.0 */ ms_x_exit(-1); /* or Above */ } #endif #if defined(DOSPLUS) batchptr_off = (VOID *) &batch; batchflg_off = (VOID *) &batchflg; echoflg_off = (VOID *) &echoflg; envsize = get_original_envsize(); /* BAP - sets envsize to */ /* same as original COMMAND */ if ((envsize < 128) || (envsize > 32752)) envsize = 256; /* shouldn't really need this */ parent_psp = MK_FP(_psp, 0x16); /* our parental PSP is here */ ret = ioctl_ver(); /* Get the BDOS Version No. */ if(ret < 0x1071) { /* Abort if this is not DOS */ eprintf(MSG_BADOS); /* PLUS with a BDOS version */ if ((*parent_psp) && (*parent_psp != _psp)) ms_x_exit(-1); /* abort unless root process */ while(1){}; } #if 0 #if defined(DLS) dls_msg_crit(); /* init crit error messages */ #endif #endif #endif #if defined(CDOSTMP) console = (UBYTE) bdos(C_GET, 0) + 1; /* CDOS Console No. + 1 */ execed = NO; /* COMMAND.RSP not EXECED */ err_ret = 0; /* Initial Error Code 0000 */ #else execed = YES; /* Assume we have been loaded*/ /* from the command line */ break_flag = ms_set_break(NO); /* Get the Current Break Flag*/ err_ret = ms_x_wait(); /* Get the completion code */ /* for process's that cause */ /* COMMAND.COM to be reloaded*/ init_switchar(); /* initialise switchar and */ /* pathchar */ #endif drive = ms_drv_get(); /* get default drive. */ country.code = ms_s_country(&country); /* Initialise the Country data*/ in_handle = psp_poke(STDIN, 0xFF); /* Get the standard input */ psp_poke(STDIN, in_handle); /* and save internally */ out_handle = psp_poke(STDOUT, 0xFF); /* Get the standard Output */ psp_poke(STDOUT, out_handle); /* and save internally */ for(ret=5;ret<20;ms_x_close(ret++)); /* close handles 5-20 */ if(initflg) /* is this a warm boot? */ return; /* Yes then QUIT */ initflg = YES; /* there's only one 1st time */ cflag = 0; /* Clear the switch variable */ #if !defined(CDOSTMP) /* * * COMMAND.COM * The following command line formats must be supported for * applications that exec the command processor. * * COMMAND /CCOPY filex filey FrameWork Install * COMMAND /C DIR *.* /P Procomm directory option * COMMAND /C=DIR *.* * * These varients prevent support for multiple options and * force the option scanning to be halted at the first command * * COMMAND /T - TSR support for CDOS * * We are auto-invoking COMMAND after detecting a TSR, so * try and inherit any open batch files. * */ s = (BYTE *) heap_get(128); /* allocate some heap memory */ FOREVER { cmd = deblank(cmd); /* Deblank the command line */ if((*cmd == '\0') || (*cmd == *switchar)) break; /* stop at option or end */ cmd = get_filename(s, cmd, NO); if(strlen(s)) { /* look for Loadpath/STDIO */ if((ret = ms_x_open(s, OPEN_RW)) >= 0) { if(isdev(ret)) { strcat(kbdptr,"ctty "); /* if its a R/W device put */ strcat(kbdptr, s); /* CTTY into buffer */ strcat(kbdptr,"!"); } else /* otherwise its an error */ eprintf(MSG_LOADPATH); /* an invalid loadpath */ ms_x_close(ret); /* Close the handle */ } else { append_slash(s); /* user specified loadpath */ get_reload_file(); /* get reload_file on heap */ strcat(s, fptr(heap())); if(file_exist(s)) { /* append existing load file */ ms_x_expand(heap(), s); set_reload_file(); /* copy heap to reload_file */ } else { /* Print an error message if */ eprintf(MSG_LOADPATH); /* an invalid path used. */ lferror = 1; break; } } } else { eprintf(MSG_LOADPATH); break; } } heap_set(s); /* free up heap memory */ c_option = FALSE; k_option = FALSE; FOREVER { cmd = deblank(cmd); /* Deblank the command line */ if(*cmd != *switchar) /* Stop the option check if */ break; /* the next character is not */ cmd++; /* a switch character. */ c = toupper(*cmd++); switch(c) { /*RG-05-*/ #if (defined(CDOS)||defined(DOSPLUS)) && !defined(NOHELP) case 'H': /* Support /H Help Option */ case '?': /* Support /? Help Option */ cflag |= 2; cmd_ver(); crlf(); printf(HELP_COM); ms_x_exit(0); break; #endif /*RG-05-end*/ case 'C': /* Support /C Option */ echoflg = ECHO_OFF; /* Don't issue CR LF */ c_option = TRUE; case 'K': k_option = TRUE; cmd = deblank(cmd); if (*cmd == '=') { cmd++; /* Skip optional '=' */ cmd = deblank(cmd); } cflag |= 2; break; case 'N': n_option = TRUE; break; case 'P': /* Support /P Option */ cflag |= 1; if (*cmd == ':') { /* See if a different fname */ cmd++; /* has been specified for */ ret = 0; /* AUTOEXEC.BAT. */ while ((*cmd > 32) && (ret < 12)) autoexec_name[ret++] = *cmd++; autoexec_name[ret] = 0; while (*cmd > 32) cmd++; } break; case 'E': /* Environment Option */ if(*cmd != ':') /* Check for /E:nnn */ break; cmd++; if(getdigit(&ret, &cmd) && ret > 128 && ret < 32752) envsize = ret; break; #if defined(CDOS) case 'T': /* TSR support */ cflag |= 5; inherit_TMP_state(); /* inherit batch files etc */ break; #endif #if defined(DOSPLUS) case 'T': inherit_parent_state(); break; #endif #if defined(DOSPLUS) case 'M': /* relocate resident portion */ c = toupper(*cmd++); if (c == 'H') prh_function = 1; if (c == 'U') prh_function = 2; if (c == 'L') prh_function = -1; break; case 'D': no_timedate = TRUE; break; #endif case '\0': /* Treat the NULL character */ cmd--; /* specially in case some of*/ break; /* the following command "/"*/ default: /* Skip invalid options. */ break; } } #if defined(DOSPLUS) /* We cannot allow COMMAND to go into upper memory unless "/P" has also */ /* been given. If we do the memory won't be freed up on exit */ switch(prh_function) { case 0: /* try high, upper, then low */ if(COMMAND_P) put_resident_high(0); else put_resident_high(1); break; case 1: /* try high, then low */ put_resident_high(1); break; case 2: /* try upper, then low */ if(COMMAND_P) put_resident_high(2); break; default:/* try low */ break; } #endif master_env(envsize); /* Allocate the master */ /* environment of ENVSIZE */ /* bytes in length */ #if 0 /* * If no COMSPEC has been defined or it is different from * the RELOAD_FILE specification then update COMSPEC. */ if(env_scan(msg_comspec, heap()) || stricmp(heap(), reload_file)) { sprintf(buf, "%s%s", msg_comspec, reload_file); cmd_set(buf); } #else /* BAP changed this */ get_reload_file(); if(env_scan(msg_comspec,heap())) { sprintf(buf,"%s%s",msg_comspec,heap()); cmd_set(buf); } #endif #if defined(DOSPLUS) save_parent = *parent_psp; *parent_psp = _psp; /* Always do this */ if(COMMAND_P) { /* Action the /P flag for */ execed = NO; /* DOSPLUS.COM */ PATH_DIR[0] = drive + 'A'; /* if DRDOS directory exists */ ret = ms_x_chmod(PATH_DIR, ATTR_ALL, 0); if ((ret > 0) && (ret & 0x10)) {/* point the path at it */ sprintf(buf, SET_PATH, PATH_DIR); cmd_set(buf); } cmd_set(SET_PROMPT); cmd_set(SET_OS); cmd_set(SET_VER); #if !defined(FINAL) cmd_set(SET_BETA); #endif install_perm(); /* Install Backdoor entry */ } /* process the environment created by config.sys */ process_config_env(); #endif #endif FOREVER { if(execed) { /* If this is a transient */ if (!lferror) strcat(kbdptr, cmd); /* command processor then */ ret = FALSE; /* get the command line and*/ break; /* ignore AUTOEXEC.BAT. */ } /* Check for the presence of STARTnnn.BAT in the root */ /* of the boot disk if not found check for AUTOEXEC */ /* if neither are present then if this is console 0 */ /* and this is < 1987 ask for the date. */ #if defined(CDOSTMP) vc_data(&vc_base, &vc_num, &pc_num); /* Get VC Data */ vc_num = console - vc_base; /* Relative VC Num */ sprintf(heap(), "!start%02d%1d.bat", pc_num, vc_num); if((ret = file_exist(heap()+1)) == 0) { strcpy(heap(), "!autoexec.bat"); ret = file_exist(heap()+1); } if(ret != 0) { strcat(kbdptr, heap()); sprintf(heap(), " %d %d %d", console, pc_num, vc_num); strcat(kbdptr, heap()); break; } #else strcpy(heap(), "!"); strcat(heap(), autoexec_name); if((ret = file_exist(heap()+1)) != 0) { if (boot_key_scan_code != 0x3f00 /*F5*/) strcat(kbdptr,heap()); break; } else { boot_key_scan_code = 0; } #endif #if defined(DOSPLUS) if (!no_timedate && *autoexec_name!=0) strcat(kbdptr, "!date!time"); #else ms_getdate(&date); if(console == 1 && date.year < 1987) strcat(kbdptr, "!date!time"); #endif break; } #if defined(CDOS) && !defined(CPM) if(COMMAND_P) /* Action the /P flag for */ execed = NO; /* CDOS.COM to disable EXIT */ #endif #if 0 if(COMMAND_C) { /* Append EXIT if COMMAND.COM*/ strcat(kbdptr, "!exit 0"); /* is just used to execute a */ } /* a command. */ #endif #if !defined(CDOSTMP) #if 0 else { #else if(!COMMAND_C) { #endif #if defined(DOSPLUS) if (*autoexec_name != 0) { cmd_ver(); /* display the signon */ printf(MSG_OEMCPYRT); crlf(); } #else if(!COMMAND_T) { /* if it's CDOS TSR support */ cmd_ver(); /* don't display signon */ crlf(); } #endif } #endif } /* * The following function is called to clean up COMMAND.COM after * an internal or external command has been executed. The major areas * to be handled by this function are:- * * 1) Control-C termination for Batch file termination * 2) I/O Redirection * 3) Hiloading off */ MLOCAL VOID cmd_cleanup() { BYTE cmdbuf[128]; #if 0 hiload_set(NO); /* HILOADing off now */ #endif if(err_ret == BREAK_EXIT || /* Check for Control-C */ err_ret == ERROR_EXIT) { /* or Critical Error Exit */ if(pipe_out) { /* If a Pipe'ed command is */ pipe_out = NO; /* is aborted then absorb */ getcmd(cmdbuf); /* the second command. */ crlf(); } if(batchflg) { eprintf(MSG_BATTERM); /* Processing a BATCH file */ err_flag = TRUE; /* ask if the uses wishes to */ if(yes(NO, YES)) /* to abort this batch job */ batch_endall(); /* Close ALL batch files */ err_flag = FALSE; } else if(for_flag) /* If processing a FOR */ for_end(); /* command outside a batch */ } /* file then abort it. */ err_ret &= 0x00FF; /* Mask the Termination */ /* condition this should only*/ /* be tested once. */ /* * After the termination of a Batch file or a Program then * the relevant redirection is removed. If the redirection * was instigated because of the PIPE facility then the * correct clean up code is executed. */ while(in_flag & REDIR_ACTIVE) { /* Is Redirection Active */ if((in_flag & REDIR_BATCH) && batchflg) break; if((in_flag & REDIR_FOR) && for_flag) break; ms_x_close(STDIN); /* Close the Redirected File */ psp_poke(STDIN, in_handle); /* Restore original Handle */ if(pipe_in) { pipe_in = NO; ms_x_unlink(old_pipe); heap_set(old_pipe); } in_flag = NULL; } while(out_flag & REDIR_ACTIVE) { /* Is Redirection Active */ if((out_flag & REDIR_BATCH) && batchflg) break; if((out_flag & REDIR_FOR) && for_flag) break; ms_x_close(STDOUT); /* Close the Redirected File */ psp_poke(STDOUT, out_handle); /* Restore original Handle */ if(pipe_out) { pipe_in = YES; pipe_out = NO; old_pipe = heap_get(strlen(out_pipe)+1); strcpy(old_pipe,out_pipe); } out_flag = NULL; } country.code = ms_s_country(&country); /* re-init the Country data */ #if 0 #if defined(DLS) dls_msg_crit(); /* re-init crit error msgs */ #endif #endif } /*.pa*/ /* * ERROR_INIT is the "CRITICAL" error handler which will initialize * the error handling code, displays error messages and clean-up the * environment after an error has occurred. */ /*RG-00*/ /*MLOCAL VOID error_code(error)*/ VOID error_code(error) /*RG-00-end*/ UWORD error; { switch(error) { case 0: /* Setting JMPBUF. Enable */ #if !defined(CDOSTMP) /* break checking in case */ ms_set_break(YES); /* this is the first time */ #endif /* through the command proc. */ return; case IA_BREAK: putc('\r'); /* A CR here makes SideKick+ */ /* look good when it */ /* deinstalls itself */ /* The following two function calls close the batch file during an INT 23 thus disallowing to continue with a batch file if the user chooses to do so after being prompted. However, there migh have been a reason why this has been inserted before which I don't know of. JBM */ /* ms_x_close(5); ##jc## Close Unused Handles*/ /* ms_x_close(6); ##jc## Close Unused Handles*/ mem_free(&bufaddr); /* Free External Copy Buffer */ #if defined(CDOSTMP) /* On Concurrent DOS and */ bdos(DRV_RESET, 0xFFFF); /* DOSPLUS reset the disk */ crlf(); /* when we get a Control-C. */ #endif break; case IA_STACK: /* Stack Overflow Error */ case IA_HEAP: /* Heap Overflow Error */ batch_endall(); /* Out of memory error */ eprintf(MSG_BATNEST); /* probably caused by nesting*/ break; /* batch files TOO deep. */ case IA_FILENAME: /* FileName Error */ eprintf(ERR_FILE); /* display an error message */ break; /* and terminate the command */ default: eprintf(MSG_LONGJMP, error); break; } crlfflg = NO; /* Reset CR/LF Flag */ } /* * This function is invoked after a CONTROL-BREAK or Critical Error * during the execution of an internal function. Any BREAK specific * cleanup is executed here. The break handler then restarts normal * code execution by executing a LONGJMP. */ GLOBAL VOID CDECL int_break() { int i; if (show_file_buf) mem_free(&show_file_buf); if (global_in_hiload) { /* if ctrl-c pressed during a hiload, restore memory */ /* allocation strategy. */ for(i=1;i<10;i++) { /* free up any UMB's we have */ if (hidden_umb[i]) { free_region(hidden_umb[i]); hidden_umb[i] = 0; } } set_upper_memory_link(global_link); set_alloc_strategy(global_strat); global_in_hiload = 0; } err_ret = BREAK_EXIT; /* Update the Global Error Return */ longjmp(break_env, IA_BREAK); /* Either Control-C or Critical */ /* Error Process Termination. */ } /*.pa*/ /* * This function parses the command line and extracts all unquoted * >>, > and < character sequences and their corresponding filenames. * The last redirection specification of the same type is used all * previous references will be removed. Redirection will only be * enabled if no redirection of the same type is already active. * ie. If redirection is enabled on a batch file all redirection * commands of the same type inside the file are ignored. */ GLOBAL BOOLEAN parse(s) /* Parse the command line looking */ BYTE *s; /* for Redirection commands */ { REG BYTE *bps; BYTE *bpi, *bpo; BYTE infile[MAX_FILELEN]; /* Input Redirection FileName */ BYTE outfile[MAX_FILELEN]; /* Output Redirection FileName */ BYTE cmdbuf[128]; /* Command buffer for Aborted Pipe */ WORD h; BOOLEAN quote = NO; /* Check for Quoted Statements */ BOOLEAN append; /* Out Redirection Append */ crlfflg = YES; /* Force a CRLF in case an error */ /* occurs in the command line parsing*/ for(bpi = NULL, bpo = NULL; *s; s++) { if(*s == '"') { /* Maintain the correct */ quote = !quote; /* Status of the QUOTE flag*/ continue; } if(quote) /* If the QUOTE flag is */ continue; /* then skip the following */ if(*s == '>') { /* Found Output redirection */ bpo = outfile; /* Character extract the Path*/ bps = s+1; append = FALSE; /* and save locally */ if(*(bps) == '>') { /* Check for append mode */ append = TRUE; bps++; } bps = get_filename(bpo, deblank(bps), NO); /* Extract the FileName */ bps = deblank(bps); strcpy(s--, bps); /* Then remove data from Line*/ continue; /* S decrement to force new */ } /* next character to be read */ if(*s == '<') { /* Found Input redirection */ bpi = infile; /* Character extract the Path*/ bps = get_filename(bpi, deblank(s+1), NO); /* Extract the FileName */ bps = deblank(bps); strcpy(s--, bps); /* Then remove data from Line*/ } /* S decrement to force new */ } /* next character to be read */ #if defined(DOSPLUS) /* only redirect if not already redirected */ if ((pipe_in || bpi) && (!(in_flag & REDIR_ACTIVE))) { #else if(pipe_in || bpi) { /* Check for any redirection */ if(in_flag & REDIR_ACTIVE) { /* If Standard Input has been*/ eprintf(MSG_INACTIVE); /* redirected then fail */ return FAILURE; } #endif bpi = pipe_in ? out_pipe : infile; /* BPI points to the filename*/ h = ms_x_open(bpi, OPEN_READ); if(h < 0) { /* Attempt to Open the file */ e_check(h); /* || device specified and */ return FAILURE; /* print an error message if */ } /* we fail. */ psp_poke(STDIN, psp_poke(h, 0xFF)); /* Force New input file onto */ /* Standard Input and close */ in_flag = REDIR_ACTIVE; /* the returned handle */ } #if defined(DOSPLUS) /* only redirect if not already redirected */ if ((pipe_out || bpo) && (!(out_flag & REDIR_ACTIVE))) { #else if(pipe_out || bpo) { /* Check for any redirection */ if(out_flag & REDIR_ACTIVE) { /* If Standard Output has been*/ eprintf(MSG_OUTACTIVE); /* redirected then fail */ return FAILURE; } #endif if(pipe_out) { #if defined(CDOSTMP) out_pipe[0] = *SYSDATB(TEMPDISK)+'A'; /* Initialise the DRIVE */ out_pipe[3] = '\0'; /* Terminate String */ #else if (!env_scan("TEMP=",out_pipe)) { /* if TEMP != "d:\" check its a valid directory */ if ((strlen(out_pipe) > 3) || (out_pipe[1] !=':')) { h = ms_x_chmod(out_pipe,ATTR_ALL,0); if ((h<0) || !(h&0x10)) goto assume_root; } append_slash(out_pipe); } else { assume_root: get_out_pipe(); /* get string from low_seg */ out_pipe[0] = drive+'A'; /* Initialise the DRIVE */ out_pipe[3] = '\0'; /* Terminate String */ } #endif bpo = out_pipe; h = ms_x_unique(out_pipe, ATTR_SYS); } else { /* Create the output file if */ bpo = outfile; /* not Appending or the OPEN */ /* on the file fails. */ if(!append || (h = ms_x_open(bpo, OPEN_WRITE)) < 0) h = ms_x_creat(bpo, 0); } if(e_check(h) < 0) { /* Display any error message */ if(pipe_out) { /* Pipe'ed command then */ pipe_out = NO; /* absorb the second command*/ getcmd(cmdbuf); /* return FAILURE on error */ crlfflg = YES; } return FAILURE; } if(append) /* If in APPEND mode then */ ms_x_lseek(h, 0L, 2); /* seek to the end. */ psp_poke(STDOUT, psp_poke(h, 0xFF));/* Force New input file onto */ /* Standard Ouput and close */ out_flag = REDIR_ACTIVE; /* the returned handle */ if(pipe_out) out_flag |= REDIR_PIPE; } crlfflg = NO; return SUCCESS; } MLOCAL BOOLEAN docmd_offer(BYTE *cp, BYTE *command, UWORD internal_flag) { BYTE *lcp; int i; UWORD int2f_gotit = 0; lcp = heap(); lcp[0] = 0x80; /* copy command line to buffer */ lcp[1] = strlen(cp); /* with "readline" format */ for (i=0;i=0) && (loadfile[i+1] == ' '); i--); loadfile[0] = i+1; /* set length of cmd */ for(;strchr(valid_sepchar,*cp);cp++); /* ignore leading separators */ for(;is_filechar(cp);cp++); /* skip the command itself */ /* offer command line to */ /* interested parties */ if(docmd_offer(lcp,loadfile,0xFF00+strlen(cp))) /* If they want it */ return; /* we don't */ cp = lcp; if ((cp[0] != 0) && (cp[1] == ':')) cp+=2; for(;strchr(valid_sepchar,*cp);cp++); for(;is_filechar(cp);cp++); /* skip the command itself */ cp1 = cp; i = 0; while (*cp1 != '\0') { if (*cp1 == '"') i ^= 1; if (is_blank(cp1) == 2 && !i) /* replace each KANJI space */ *cp1 = *(cp1 + 1) = ' '; /* with one ASCII space */ cp1 = skip_char(cp1); } s_cmd_p = (S_CMD FAR *)farptr((BYTE *)&cmd_list[0]); while(internal && s_cmd_p->cmnd) { /* while more builtins */ cpf = cgroupptr(s_cmd_p->cmnd); for(i=0;cpf[i];i++) /* make upper case copy */ argv0[i]=toupper(cpf[i]); for(;i<8;argv0[i++]=' '); /* space fill it to 8 */ if(!strncmp(argv0,loadfile+1,8)) { /* Is this a match ? */ #if !defined(NOHELP) /* Handle /H or /? in command */ strcpy(heap(),deblank(cp)); if(!strnicmp(heap(),"/h",2)||!strnicmp(heap(),"/?",2)) { if (s_cmd_p->help_index != -1) show_help(s_cmd_p->help_index); crlf(); return; } #endif /* check for embedded commands in IF that only have meaning in that context */ if(s_cmd_p->needparm==PARAM_IFCONTEXT) { if(if_context==FALSE) break; } cp1 = deblank(cp); /* Remove Blanks from Options*/ if(s_cmd_p->needparm!=PARAM_NONE /* if a parameter is needed */ && !*cp1) { /* but none is supplied */ switch ((UWORD)s_cmd_p->needparm) /* display an error message */ { case PARAM_NEEDFILE: eprintf(MSG_NEEDFILE); break; case PARAM_NEEDPATH: eprintf(MSG_NEEDPATH); break; case PARAM_NEEDDEV: eprintf(MSG_NEEDDEV); break; default: eprintf(MSG_SYNTAX); break; } eprintf("\n"); return; /* ignore the command */ } page_len = get_lines_page(); /* so /P works in 43 and 50 */ /* line modes */ (*s_cmd_p->func)(cp1, cp); /* Just Invoke builtin */ return; } s_cmd_p ++; /* compare with next command */ } /* it's not an internal command - could it be help ? */ if ((!strnicmp(lcp,"/h",2))||(!strncmp(lcp,"/?",2))) { show_help(0); s_cmd_p = (S_CMD FAR *)farptr((BYTE *)&cmd_list[0]); while(s_cmd_p->cmnd) { cpf = cgroupptr(s_cmd_p->cmnd); printf("%s\t",cpf); s_cmd_p++; } crlf(); return; } /* command is not builtin, must be disk based so determine path ... */ if(docmd_offer(lcp,loadfile,strlen(cp))) /* offer command line to */ return; /* interested parties */ /* If they want it, we don't */ cp = get_filename(loadfile, lcp, NO); strcpy(argv0, loadfile); /* the original command name */ strlwr(loadfile); if((loadfile[strlen(loadfile)-1] == '\\') || ((strlen(loadfile) == 2) && (loadfile[1] == ':'))) { if(!dos_parse_filename(loadfile) && d_check(loadfile)) { if (ddrive != -1) { ms_drv_set(ddrive); /* then check the requested */ drive = ddrive; /* drive and make it the */ crlfflg = NO; /* default if OK. */ } } else { eprintf(ERR15); crlf(); } return; } if (strcmp(loadfile,"________") == 0) { ms_x_first("________.???",ATTR_HID+ATTR_STD,(DTA *) heap()); strcpy(loadfile,"C:\\________.COM"); } else if((i = findfile(loadfile, &loadtype)) < 0) { if(i == ED_FILE || /* Determine the full */ i == ED_ROOM || /* path and type of the */ i == ED_PATH) { /* command and return if*/ eprintf(MSG_BADCMD); /* file or command cannot be located */ } else { e_check(i); } return; } if(!env_scan(msg_comspec, heap())) /* If COMSPEC is defined */ set_reload_file(); /* then update RELOAD_FILE */ doexec(argv0, loadfile, loadtype, cp); /* Load the file */ allow_pexec = TRUE; } /* * FindFile searches the file system copying the actions of the * Concurrent DOS P_PATH function. If this is TMP for Concurrent * DOS then use the system call otherwise use the C function. * * If no extension is specified then check the file types in * the following order .CMD, .COM, .EXE, .BAT * * If a Path is specified then just check that location otherwise * check the current directory and then all entries in the path. */ #if !defined(CDOSTMP) GLOBAL WORD CDECL findfile(loadpath, loadtype) BYTE *loadpath; /* Command Name expanded to full path */ UWORD *loadtype; /* Command file Type */ { REG BYTE *s; BYTE sppath[MAX_PATHLEN]; /* Buffer for the optional */ /* load path. */ BYTE fname[8+1+3+1+8+1]; /* Buffer for the filename */ /* optional extension and */ /* password */ BYTE *path; /* Environment Load path */ BYTE *ftype; /* Optional file type */ BYTE *pwd; /* Optional Password */ BYTE *envpath; /* current PATH= in env */ WORD i, ret; #if !STACK BYTE pathbuf[MAX_ENVLEN]; /* temporary path buffer */ #endif strip_path(loadpath, sppath); /* isolate the optional path*/ ftype = loadpath+strlen(sppath); /* get the Filename Address */ if(strlen(ftype) < sizeof(fname)) /* If the filename is not */ strcpy(fname, ftype); /* too long then copy to an */ else /* internal buffer otherwise*/ longjmp(break_env, IA_FILENAME); /* break with FILENAME error*/ if((ftype = strchr(fname, '.')) != 0) { /* then extract the optional*/ *ftype++ = '\0'; /* file type from the name */ pwd = ftype; } else { /* If no type has been */ ftype = NULLPTR; /* specified then make it */ pwd = fname; /* file type a NULL pointer */ } if ((ret = ms_x_open (fname, 0)) > 0) { /* don't exec a device in */ i = isdev (ret); /* any shape or form */ ms_x_close (ret); if (i) return (ED_FILE); } #if defined(PASSWORD) if((pwd = strchr(pwd, *pwdchar)) != 0) /* Finally extract the */ *pwd++ = '\0'; /* optional password if none*/ else /* exists then default to a */ pwd = NULLPTR; /* NULL pointer. */ #endif if(ftype) { /* If a file type has been */ for(i=0; ftypes[i]; i++) /* specified then check that*/ if(!strcmp(ftype, ftypes[i])) /* is legal and return an */ break; /* error if not. */ if(!ftypes[i]) /* If an illegal filetype */ return ED_FILE; /* has been given then */ } /* return FAILURE */ *loadtype = i; /* Save the Load File Type */ /* * Check if a path is currently defined if YES then get * a copy of the path and save locally on the heap. Protecting * it against being overwritten. */ if(!env_scan(msg_patheq, heap())) { envpath = heap(); while (*envpath) { /* process path in env */ if(dbcs_lead(*envpath)) /* so delimiters are the */ envpath++; /* pathchar we expect */ else if((*envpath == '/') || (*envpath == '\\')) *envpath = *pathchar; envpath++; } #if STACK envpath = stack(strlen(heap()) + 1); #else envpath = &pathbuf[0]; #endif strcpy(envpath, heap()); } else envpath = ""; /* * First attempt to load the file from the default/specified * path and then if no path was specified attempt to load the * file from all the entries in the search path defined in the * environment. */ if(*sppath) path = sppath; else path = ""; do { i = checkfile(loadpath, loadtype, path, fname, ftype, pwd); switch (i) { case SUCCESS: strupr(loadpath); return SUCCESS; case ED_FAIL: case ED_DRIVE: /* if bad drive in search */ if ((!*sppath) && (*path)) /* path, print msg & carry on*/ { eprintf(MSG_PATHDRV); i = ED_FILE; break; } default: break; /* get next search path */ } path = envpath; /* Set PATH to the next */ if((s=strchr(envpath, ';')) != 0) { /* element in the search path*/ while (*s == ';') { /* Skip over extra semicolons*/ *s = 0; s++; } envpath = s; } else envpath = ""; /* path exhausted, -> null */ /* If you type FILENAME.EXE, it will search the current drive then */ /* the path. If you type C:\DIR\FILENAME.EXE, it will search */ /* C:\DIR. Now, if you type C:FILENAME.EXE, it will search the */ /* current directory on C:, then path. This is done by resetting */ /* sppath after the first run through, if it is just D: */ if((strlen(sppath) == 2) && (sppath[1] == ':')) sppath[0] = '\0'; } while(!*sppath && *path); return i; } /* * CHECKFILE generates the full path of the load file and * attempts to open the file. If the file is located and * can successfully be opened return SUCCESS with the full * path in LOADPATH and the LOADTYPE initialised. * * If no file extension has been specified then use the standard * search order. * * ATTR_SEARCH specifies the attributes used to locate the file * to be loaded. */ #define ATTR_SEARCH ATTR_STD + ATTR_HID MLOCAL WORD checkfile(loadpath, loadtype, path, fname, ftype, pwd) BYTE *loadpath; UWORD *loadtype; BYTE *path, *fname, *ftype, *pwd; { UWORD type; WORD ret; DTA search; BYTE curpath[MAX_PATHLEN+1]; if((path = d_check(path)) == NULL) /* Remove the drive specifier*/ return ED_DRIVE; /* and return on Error. */ /* get path starting from root. n.b. don't use ms_x_expand (func 60h) */ /* as it upsets Novell */ if (ddrive != -1) { sprintf(loadpath, "%c:%c", ddrive + 'A', *pathchar); if((*path == '\\') || (*path == '/')) /* If path is absolute then */ strcpy(loadpath+2, path); /* just append to drive */ else { /* Otherwise append the */ ms_x_curdir(ddrive+1, loadpath+3); /* path to the drive and */ if(*fptr(loadpath)) /* current subdirectory. */ append_slash(loadpath); strcat(loadpath, path); } } else ms_x_expand(loadpath,path); if(*fptr(loadpath)) append_slash(loadpath); strcat(loadpath, fname); /* Add the FileName */ strcat(loadpath, "."); path = loadpath + strlen(loadpath); /* Save the Extension Offset */ #if defined(PCDOS) /* * If running under PCDOS the check if any extension has been specified * if not then search first for filename.* and return if no match occurs * This will be quicker than opening each file in turn. */ if(!ftype) { strcat(path, "*"); if((ret = ms_x_first(loadpath, ATTR_SEARCH, &search)) < 0) { if( ret == ED_FILE || /* Abort if an error occurs */ ret == ED_ROOM || /* but ignore File not Found */ ret == ED_PATH) /* and invalid path errors */ return ED_FILE; else return e_check(ret); } } #endif if (ftype == 0) type = COM_FILETYPE; /* Initialize the Type Index */ else /* correctly depending on the */ type = *loadtype; /* initial file type. */ do { strcpy(path, ftypes[type]); /* Add the first file type */ #if defined(PASSWORD) if(pwd) { /* followed by the optional */ strcat(path, pwdchar); /* password and attempt to */ strcat(path, pwd); /* open the file. */ } #endif if((ret = ms_x_first(loadpath, ATTR_SEARCH, &search)) < 0) { if(ret == ED_PATH) /* Stop scanning this */ return ED_FILE; /* element of the path if */ /* it is invalid. */ #if 0 if(ret != ED_FILE && ret != ED_ROOM) return ret; #endif } else { *loadtype = type; /* Set the correct loadtype */ return SUCCESS; /* and return SUCCESS */ } if (++type > BAT_FILETYPE) #if defined(DOSPLUS) || defined(NETWARE) type = COM_FILETYPE; #else type = CMD_FILETYPE; #endif } while(!ftype && (type != COM_FILETYPE)); return ED_FILE; } #endif MLOCAL BOOLEAN doexec(argv0, loadpath, loadtype, tail) BYTE *argv0; /* Invoking Command */ BYTE *loadpath; /* Fully expanded filename */ UWORD loadtype; /* File Type .BAT, .EXE etc. */ BYTE *tail; /* Command line options */ { WORD ret; WORD i; BYTE *s; #if !STACK BYTE tailbuf[128]; #endif #if 0 printf("DOEXEC Load File \"%s\" Command Line \"%s\"\n", loadpath, (tail ? tail : "")); #endif if(loadtype == BAT_FILETYPE) { /* if Batch file then:- */ if (batchflg == 0) echoflg_save2 = echoflg; ret = echoflg; /* Save the Current ECHO State */ batch_end(); /* Close any Existing Batch file */ echoflg = ret; /* restore the ECHO status */ batch_start(argv0, loadpath, tail); /* and initialize the new batch */ return YES; /* use "CALL" to nest batches. */ } /* if CMD, COM or EXE */ if(batchflg) /* close the BATCH file if OPEN cos */ batch_close(); /* some programs update the running */ /* batch file. */ s = deblank(tail); /* No SPACE before options */ if(!*s) /* if this is a blank line */ tail = s; #if defined(CDOSTMP) ret = exec(loadpath, loadtype, tail, back_flag); #else ms_set_break(break_flag); #if STACK s = stack(strlen(tail)+2)+1; #else s = &tailbuf[1]; #endif tail = strcpy(s, tail) - 1; *tail = (UBYTE) strlen(tail+1); strcat(tail+1, "\r"); #if !defined(FINAL) save_psp(); #endif ret = exec(loadpath, loadtype, tail, back_flag); #if !defined(FINAL) check_psp(); #endif init_switchar(); /* switch character may have changed */ break_flag = ms_set_break(YES); #endif /* * Novell use the MS_DRV_GET function to detect abnormal * program termination. They assume this function is only * called by the command processor when a child has terminated. * They close all Remote Handles when the parent command * processor calls this function. */ drive = ms_drv_get(); /* get default drive. */ for (i=5;i<20;i++) ms_x_close(i); /* Close all handles */ if(ret < 0) { /* Get the returned Error Code */ #if defined(CDOS) || defined(CDOSTMP) if(ret == ED_ENVIRON) /* Check for an Environment */ ret = (-255); /* error this is really */ #endif /* a resource unavailable. */ /* Print a message if the exec */ e_check(ret); /* went wrong otherwise get the */ /* completion status and return */ return FAILURE; } err_ret = ms_x_wait(); return YES; } #if !defined(CDOSTMP) VOID FAR CDECL int2e_handler (cmd) BYTE *cmd; { BYTE *p; jmp_buf save_jmpbuf; /* save the normal setjmp environment and reset it to ourselves */ /* so that the int2e caller does not get aborted on criterr or */ /* Control break */ memmove (&save_jmpbuf, &break_env, sizeof (jmp_buf)); if (setjmp (break_env) == 0) { if ((p = strchr (cmd, 0xd)) != NULL) *p = '\0'; int2e_start(); docmd (deblank (cmd), TRUE); /* if int2e is executing a batch file, do not return until all */ /* batch file commands have been processed. Loop round as in main */ /* loop */ while (batchflg > 0) { cmd_loop (cmd); } int2e_finish(); } memmove (&break_env, &save_jmpbuf, sizeof (jmp_buf)); } MLOCAL VOID init_switchar() { *switchar = ms_switchar(); /* get switch character */ if (*switchar == '/') /* if not UNIX path char */ *pathchar = '\\'; /* then be compatible */ else *pathchar = '/'; } #endif #if defined(DOSPLUS) GLOBAL VOID process_config_env() { BYTE FAR *config_env; WORD i; BYTE buff[128]; BYTE *s; config_env = get_config_env(); if (config_env) { FOREVER { i = 0; while ((*config_env) && (*config_env!=0x1A) && (i < 127)) { buff[i++] = *config_env++; } if (i == 0) { while (*config_env != 0x1A) config_env++; config_env++; boot_key_scan_code = * ((UWORD far *) config_env); break; } buff[i] = 0; cmd_set(buff); while (*config_env) config_env++; config_env++; } #if 0 s = heap(); if (!env_scan("HOMEDIR=",s)) { if (s[1] == ':') ms_drv_set(toupper(*s)-'A'); ms_x_chdir(s); } #endif } } #endif #if !defined(FINAL) void save_psp() { BYTE far *fp; WORD i; fp = MK_FP(_psp,0); psp_xsum = 0; for (i=64;i<128;i++) psp_xsum += fp[i]; } void check_psp() { BYTE far *fp; WORD xsum; WORD i; fp = MK_FP(_psp,0); xsum = 0; for (i=64;i<128;i++) xsum += fp[i]; if (xsum != psp_xsum) { printf("BETA DEBUG ERROR: Need more stack!\n"); printf("Press a key to continue.\n"); getch(); } } #endif