diff options
-rw-r--r-- | Makefile.wcc | 3 | ||||
-rw-r--r-- | teccmd.c | 126 | ||||
-rw-r--r-- | teco.h | 16 |
3 files changed, 128 insertions, 17 deletions
diff --git a/Makefile.wcc b/Makefile.wcc index 57684f2..13ab749 100644 --- a/Makefile.wcc +++ b/Makefile.wcc @@ -37,7 +37,8 @@ LDFLAGS += format dos option eliminate option map option stack=16k & set WCC_DEFS=-dSTDC_HEADERS=1 -dHAVE_STDIO_H -dHAVE_CTYPE_H -dHAVE_ERRNO_H & -dHAVE_STRING_H -dHAVE_STRINGS_H -dHAVE_FCNTL_H -dHAVE_IO_H & -dHAVE_SYS_STAT_H -dHAVE_SIGNAL_H -dHAVE_STDLIB_H -dHAVE_UNISTD_H & - -dHAVE_STDINT_H -dHAVE_DIRECT_H -dHAVE_I86_H & + -dHAVE_STDINT_H -dHAVE_DIRECT_H -dHAVE_I86_H -dHAVE_PROCESS_H -dHAVE_CONIO_H & + -dHAVE_MALLOC_H & -dHAVE_SBRK -dHAVE_STRCHR -dTERMCAP -d__WATCOM_LFN__ all : teco.exe .SYMBOLIC @@ -1716,7 +1716,6 @@ register int length; -#ifdef UNIX /** * \brief Issue a command to the operating system * @@ -1743,6 +1742,8 @@ register int length; * \retval SUCCESS Command succeeded * \retval FAIL Command failed. Error message has been displayed. */ +#ifdef UNIX + int cmd_oscmd(struct cmd_token *uct, int arg_count, unsigned long arg1, unsigned long arg2, char *cp) { @@ -1953,27 +1954,128 @@ failreap: #else /* UNIX */ -/** - * \brief Issue a command to the operating system +/* + * This version will work on any/most systems with a standard C library + * as it relies on temporary files. * - * This routine is called in response to the EC command which allows the - * user to execute operating system commands from within the editor. + * FIXME: We cannot redirect stderr in MS-DOS. */ int cmd_oscmd(struct cmd_token *uct, int arg_count, unsigned long arg1, unsigned long arg2, char *cp) { +char tmpbuf[LINE_BUFFER_SIZE]; +char pipebuff[IO_BUFFER_SIZE]; +struct undo_token *ut; +int bidir_flag = arg_count > 0; +int status,w; +char cmdline[TECO_FILENAME_TOTAL_LENGTH]; +int input_fd = -1, output_fd = -1; +char input_filename[L_tmpnam] = "", output_filename[L_tmpnam] = ""; +int rc = FAIL; + PREAMBLE(); - /* - * FIXME: We could at least implement a subset with system(), - * that would work on DOS as well. - */ - error_message("?OS Does not currently support EC"); - return(FAIL); + snprintf(cmdline,sizeof(cmdline),"%s >%s <", + cp,tmpnam(output_filename)); -}/* End Routine */ + if(bidir_flag){ + strcat(cmdline,tmpnam(input_filename)); + input_fd = open(input_filename,O_WRONLY|O_CREAT|O_TRUNC); + if(input_fd < 0){ + sprintf(tmpbuf,"?Error opening input temporary file %s: %s", + input_filename,error_text(errno)); + error_message(tmpbuf); + goto cleanup; + }/* End IF */ + +/* + * In bidirectional mode, write buffer range to input_pipe, delete buffer range + * and care about the Undo structures + */ + status = buff_write(curbuf,input_fd,arg1,arg2); + if(status == FAIL) goto cleanup; + + ut = allocate_undo_token(uct); + if(ut == NULL) goto cleanup; + ut->opcode = UNDO_C_CHANGEDOT; + ut->iarg1 = curbuf->dot; + + status = buff_delete_with_undo(uct,curbuf,arg1,arg2-arg1); + if(status == FAIL) goto cleanup; + + close(input_fd); + input_fd = -1; + }/* End IF */ +#ifdef MSDOS + else{ + strcat(cmdline,"NUL"); + }/*End IF*/ + _heapshrink(); #endif + errno = 0; + status = system(cmdline); + if(errno){ + sprintf(tmpbuf,"?Error spawning external process: %s", + error_text(errno)); + error_message(tmpbuf); + goto cleanup; + }/* End If */ + if(status){ + sprintf(tmpbuf,"?External process failed: %d",status); + error_message(tmpbuf); + goto cleanup; + }/* End If */ + + output_fd = open(output_filename,O_RDONLY); + if(output_fd < 0){ + sprintf(tmpbuf,"?Error opening output temporary file %s: %s", + output_filename,error_text(errno)); + error_message(tmpbuf); + goto cleanup; + }/* End IF */ + +/* + * Loop reading stuff coming back from the pipe until we get an + * EOF which means the process has finished. Update the screen + * on newlines so the user can see what is going on. + * + * In unidirectional mode, process output is written to DOT, otherwise to + * the selected buffer range (it effectively gets replaced by the process output). + */ + ut = allocate_undo_token(uct); + if(ut == NULL) goto cleanup; + ut->opcode = UNDO_C_DELETE; + ut->carg1 = (char *)curbuf; + ut->iarg1 = bidir_flag ? arg1 : curbuf->dot; + ut->iarg2 = 0; + + while((w = read(output_fd,pipebuff,sizeof(pipebuff))) > 0){ + status = buff_insert(curbuf,ut->iarg1 + ut->iarg2,pipebuff,w); + if(status == FAIL) goto cleanup; + + ut->iarg2 += w; + }/* End While */ + if(w < 0){ + sprintf(tmpbuf,"?Error reading from output file %s: %s", + output_filename,error_text(errno)); + error_message(tmpbuf); + goto cleanup; + }/* End If */ + + rc = SUCCESS; + +cleanup: + if(input_fd < 0) close(input_fd); + if(*input_filename) unlink(input_filename); + if(output_fd < 0) close(output_fd); + if(*output_filename) unlink(output_filename); + return(rc); +}/* End Routine */ + +#endif /* !UNIX */ + +/* END OF UNIX CONDITIONAL CODE */ @@ -76,6 +76,10 @@ #include <sys/ioctl.h> #endif +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif + /* * sys/filio.h has the FIONREAD definition */ @@ -173,6 +177,14 @@ #include <i86.h> #endif +#if HAVE_PROCESS_H +#include <process.h> +#endif + +#ifdef HAVE_CONIO_H +#include <conio.h> +#endif + #if HAVE_SYS_WAIT_H # include <sys/wait.h> #endif @@ -287,10 +299,6 @@ } #endif -#ifdef MSDOS -#include <conio.h> -#endif - #define TECO_FILENAME_TOTAL_LENGTH FILENAME_MAX #define TECO_FILENAME_COMPONENT_LENGTH 256 #define TECO_READONLY_NAME "visit" |