home *** CD-ROM | disk | FTP | other *** search
- /* OS2.C: Operating specific I/O and Spawning functions
- for the OS/2 operating system
- for MicroEMACS 3.9
- (C)Copyright 1988 by Daniel M. Lawrence
-
- Note: don't try to compile this on non OS/2 systems.... the OS/2
- includes MUST come before ours.....
-
- Modifications needed: check that we don't construct command lines and
- temporary filenames which are too large for their buffers.
-
- */
-
- #define INCL_DOS
- #include "os2.h"
-
- #include <stdio.h>
-
- #undef PASCAL
- #undef NEAR
- #undef HIBYTE
-
- #include "estruct.h"
- #include "eproto.h"
-
- #if OS2
- #define INCL_BASE
-
- #include "elang.h"
- #include "edef.h"
-
-
- /*
- * Create a subjob with a copy of the command intrepreter in it. When the
- * command interpreter exits, mark the screen as garbage so that you do a full
- * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
- * Under some (unknown) condition, you don't get one free when DCL starts up.
- */
- spawncli(f, n)
- {
- /* don't allow this command if restricted */
- if (restflag)
- return(resterr());
-
- movecursor(term.t_nrow, 0); /* Seek to last line. */
- TTflush();
- TTkclose();
- shell();
- TTkopen();
- sgarbf = TRUE;
- return(TRUE);
- }
-
-
- /*
- * Run a one-liner in a subjob. When the command returns, wait for a single
- * character to be typed, then mark the screen as garbage so a full repaint is
- * done. Bound to "C-X !".
- */
- spawn(f, n)
- {
- register int s;
- char line[NLINE];
-
- /* don't allow this command if restricted */
- if (restflag)
- return(resterr());
-
- if ((s=mlreply("!", line, NLINE)) != TRUE)
- return(s);
- movecursor(term.t_nrow - 1, 0);
- TTkclose();
- system(line);
- TTkopen();
- /* if we are interactive, pause here */
- if (clexec == FALSE) {
- puts(TEXT6);
- /* "\r\n\n[End]" */
- tgetc();
- }
- sgarbf = TRUE;
- return (TRUE);
- }
-
-
- /*
- * Run an external program with arguments. When it returns, wait for a single
- * character to be typed, then mark the screen as garbage so a full repaint is
- * done. Bound to "C-X $".
- */
-
- execprg(f, n)
- {
- register int s;
- char line[NLINE];
-
- /* don't allow this command if restricted */
- if (restflag)
- return(resterr());
-
- if ((s=mlreply("$", line, NLINE)) != TRUE)
- return(s);
- movecursor(term.t_nrow - 1, 0);
- TTkclose();
- execprog(line);
- TTkopen();
- /* if we are interactive, pause here */
- if (clexec == FALSE) {
- puts(TEXT6);
- /* "\r\n\n[End]" */
- tgetc();
- }
- sgarbf = TRUE;
- return (TRUE);
- }
-
- /*
- * Pipe a one line command into a window
- * Bound to ^X @
- * We use a unique temporary file name so that multiple instances of
- * MicroEMACS don't try to use the same file.
- */
- pipecmd(f, n)
- {
- register WINDOW *wp; /* pointer to new window */
- register BUFFER *bp; /* pointer to buffer to zot */
- register char *tmp; /* ptr to TMP DOS environment variable */
- char line[NLINE]; /* command line send to shell */
- static char bname[] = "command";
- static char filnam[NSTRING];
- char *getenv();
-
- /* don't allow this command if restricted */
- if (restflag)
- return(resterr());
-
- /* get rid of the command output buffer if it exists */
- if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
- /* try to make sure we are off screen */
- wp = wheadp;
- while (wp != NULL) {
- if (wp->w_bufp == bp) {
- onlywind(FALSE, 1);
- break;
- }
- wp = wp->w_wndp;
- }
- /* get rid of the existing command buffer */
- if (zotbuf(bp) != TRUE)
- return(FALSE);
- }
-
- /* get the command to pipe in */
- if (mlreply("@", line, NLINE) != TRUE)
- return(FALSE);
-
- /* Call mktemp() to get a unique filename in the tmp directory. */
- if ((tmp = getenv("TMP")) == NULL)
- filnam[0] = 0;
- else {
- strcpy(filnam, tmp);
- if (filnam[strlen(filnam) - 1] != '\\')
- strcat(filnam, "\\");
- }
- strcat(filnam,"eXXXXXX");
- mktemp(filnam);
-
- /* redirect the command output to the output file */
- strcat(line, " >>");
- strcat(line, filnam);
- movecursor(term.t_nrow - 1, 0);
-
- /* execute the command */
- TTkclose();
- system(line);
- TTkopen();
- sgarbf = TRUE;
-
- /* did the output file get generated? */
- if (access( filnam, 0) != 0)
- return(FALSE);
-
- /* split the current window to make room for the command output */
- if (splitwind(FALSE, 1) == FALSE)
- return(FALSE);
-
- /* and read the stuff in */
- if (getfile(filnam, FALSE) == FALSE)
- return(FALSE);
-
- /* rename the buffer */
- strcpy( curwp->w_bufp->b_bname, "command");
- /* make this window in VIEW mode, update all mode lines */
- curwp->w_bufp->b_mode |= MDVIEW;
- wp = wheadp;
- while (wp != NULL) {
- wp->w_flag |= WFMODE;
- wp = wp->w_wndp;
- }
-
- /* and get rid of the temporary file */
- unlink(filnam);
- return(TRUE);
- }
-
-
- /*
- * filter a buffer through an external DOS program
- * Bound to ^X #
- * We use unique temporary file names so that multiple instances of
- * MicroEMACS don't try to use the same file.
- */
- filter(f, n)
-
- {
- register int s; /* return status from CLI */
- register BUFFER *bp; /* pointer to buffer to zot */
- char line[NLINE]; /* command line send to shell */
- char tmpnam[NFILEN]; /* place to store real file name */
- char *tmp; /* ptr to TMP DOS environment variable */
-
- static char filnam1[NSTRING];
- static char filnam2[NSTRING];
-
- /* don't allow this command if restricted */
- if (restflag)
- return(resterr());
-
- if (curbp->b_mode&MDVIEW) /* don't allow this command if */
- return(rdonly()); /* we are in read only mode */
-
- /* get the filter name and its args */
- if ((s=mlreply("#", line, NLINE)) != TRUE)
- return(s);
-
- /* Call mktemp() to get unique filenames in the tmp directory. */
- if ((tmp = getenv("TMP")) == NULL)
- filnam1[0] = filnam2[0] = 0;
- else {
- strcpy(filnam1, tmp);
- strcpy(filnam2, tmp);
- if (filnam1[strlen(filnam1) - 1] != '\\') {
- strcat(filnam1, "\\");
- strcat(filnam2, "\\");
- }
- }
- strcat(filnam1,"eXXXXXX");
- strcat(filnam2,"eXXXXXX");
- mktemp(filnam1);
-
- /* setup the proper file names */
- bp = curbp;
- strcpy(tmpnam, bp->b_fname); /* save the original name */
- strcpy(bp->b_fname, filnam1); /* set it to our new one */
-
- /* write it out, checking for errors */
- if (writeout(filnam1, "w") != TRUE) {
- mlwrite(TEXT2);
- /* "[Cannot write filter file]" */
- strcpy(bp->b_fname, tmpnam);
- return(FALSE);
- }
-
- mktemp(filnam2);
- strcat(line, " <"); /* construct the command line */
- strcat(line, filnam1);
- strcat(line, " >");
- strcat(line, filnam2);
-
- movecursor(term.t_nrow - 1, 0);
- TTkclose();
- system(line);
- TTkopen();
- sgarbf = TRUE;
- s = TRUE;
-
- /* on failure, escape gracefully */
- if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
- mlwrite(TEXT3);
- /* "[Execution failed]" */
- strcpy(bp->b_fname, tmpnam);
- unlink(filnam1);
- unlink(filnam2);
- return(s);
- }
-
- /* reset file name */
- strcpy(bp->b_fname, tmpnam); /* restore name */
- bp->b_flag |= BFCHG; /* flag it as changed */
-
- /* and get rid of the temporary file */
- unlink(filnam1);
- unlink(filnam2);
- return(TRUE);
- }
-
-
-
- /* SHELL: Bring up a shell. */
-
- shell(void)
- {
- char *shell; /* Name of system command processor */
-
-
- /* get name of system shell */
- if ((shell = getenv("COMSPEC")) == NULL) {
- return(FALSE); /* No shell located */
- }
-
- /*
- * We are actually setting up a shell inside a shell here.
- * Is there a better way?
- */
- return(system(shell));
- }
-
-
-
- execprog( char *cmd)
- {
- char args[NSTRING]; /* args passed to program */
- char *sp;
- char failName[NFILEN];
- char prog[NSTRING]; /* name of program */
- USHORT i;
- PRESULTCODES results;
-
-
- /*
- * Parse the command name from the command line and copy it
- * into the prog and args arrays.
- */
- i = 0;
- while (cmd[i] && (cmd[i] != ' ') && (cmd[i] != '\t')) {
- prog[i] = args[i] = cmd[i];
- i++;
- }
- prog[i] = args[i] = 0; /* terminate with a null */
-
- /* skip whitespace and copy the args */
- while (cmd[i] && ((cmd[i] == ' ') || (cmd[i] == '\t')))
- i++;
- while (cmd[i]) {
- args[i] = cmd[i];
- i++;
- }
- args[i] = args[i + 1] = 0; /* terminate with 2 nulls */
-
-
- /* look up the program on the path, trying various extentions */
- if ((sp = flook(prog, TRUE)) == NULL)
- if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) {
- strcpy(&prog[strlen(prog)-4], ".com");
- if ((sp = flook(prog, TRUE)) == NULL)
- return(FALSE);
- }
- strcpy(prog, sp);
-
- /*
- * Execute the program synchronously. We wait for child
- * to return.
- */
- return (0 == DosExecPgm( failName, NFILEN, EXEC_SYNC,
- args, 0, results, prog));
- }
-
-
- /* FILE Directory routines */
-
- FILEFINDBUF pBuf; /* buffer to hold file information */
- HDIR hDir; /* directory handle */
- int num_found; /* number of directory entries found/to find */
-
- char path[NFILEN]; /* path of file to find */
- char rbuf[NFILEN]; /* return file buffer */
-
- /* do a wild card directory search (for file name completion) */
-
- char *PASCAL NEAR getffile(fspec)
-
- char *fspec; /* pattern to match */
-
- {
- register int index; /* index into various strings */
- register int point; /* index into other strings */
- register int extflag; /* does the file have an extention? */
- char fname[NFILEN]; /* file/path for DOS call */
-
- /* first parse the file path off the file spec */
- strcpy(path, fspec);
- index = strlen(path) - 1;
- while (index >= 0 && (path[index] != '/' &&
- path[index] != '\\' && path[index] != ':'))
- --index;
- path[index+1] = 0;
-
- /* check for an extension */
- point = strlen(fspec) - 1;
- extflag = FALSE;
- while (point > index) {
- if (fspec[point] == '.') {
- extflag = TRUE;
- break;
- }
- point--;
- }
-
- /* construct the composite wild card spec */
- strcpy(fname, path);
- strcat(fname, &fspec[index+1]);
- strcat(fname, "*");
- if (extflag == FALSE)
- strcat(fname, ".*");
-
- /* and call for the first file */
- num_found = 1;
- hDir = HDIR_CREATE;
- if (DosFindFirst(fname, &hDir, FILE_NORMAL|FILE_DIRECTORY,
- &pBuf, sizeof(pBuf), &num_found, 0L) != 0)
- return(NULL);
-
- /* return the first file name! */
- strcpy(rbuf, path);
- strcat(rbuf, pBuf.achName);
- mklower(rbuf);
- if (pBuf.attrFile == FILE_DIRECTORY)
- strcat(rbuf, DIRSEPSTR);
- return(rbuf);
- }
-
- char *PASCAL NEAR getnfile()
-
- {
- register int index; /* index into various strings */
- register int point; /* index into other strings */
- register int extflag; /* does the file have an extention? */
- char fname[NFILEN]; /* file/path for DOS call */
-
- /* and call for the next file */
- if (DosFindNext(hDir, (void *)&pBuf, sizeof(pBuf), &num_found) != 0)
- return(NULL);
-
- /* return the first file name! */
- strcpy(rbuf, path);
- strcat(rbuf, pBuf.achName);
- mklower(rbuf);
- if (pBuf.attrFile == FILE_DIRECTORY)
- strcat(rbuf, DIRSEPSTR);
- return(rbuf);
- }
-
- /* return a system dependant string with the current time */
-
- char *timeset()
-
- {
- register char *sp; /* temp string pointer */
- char buf[16]; /* time data buffer */
- extern char *ctime();
-
- time(buf);
- sp = ctime(buf);
- sp[strlen(sp)-1] = 0;
- return(sp);
- }
-
- #if OBSOLETE
- /* extcode: resolve MSDOS extended character codes
- encoding the proper sequences into emacs
- printable character specifications
- */
-
- int extcode(
- unsigned c /* byte following a zero extended char byte */
- )
-
- {
- /* function keys 1 through 9 */
- if (c >= 59 && c < 68)
- return(SPEC | c - 58 + '0');
-
- /* function key 10 */
- if (c == 68)
- return(SPEC | '0');
-
- /* shifted function keys */
- if (c >= 84 && c < 93)
- return(SPEC | SHFT | c - 83 + '0');
- if (c == 93)
- return(SPEC | SHFT | '0');
-
- /* control function keys */
- if (c >= 94 && c < 103)
- return(SPEC | CTRL | c - 93 + '0');
- if (c == 103)
- return(SPEC | CTRL | '0');
-
- /* ALTed function keys */
- if (c >= 104 && c < 113)
- return(SPEC | ALTD | c - 103 + '0');
- if (c == 113)
- return(SPEC | ALTD | '0');
-
- /* ALTed number keys */
- if (c >= 120 && c < 129)
- return(ALTD | c - 119 + '0');
- if (c == 130)
- return(ALTD | '0');
-
- /* some others as well */
- switch (c) {
- case 3: return(0); /* null */
- case 15: return(SHFT | CTRL | 'I'); /* backtab */
-
- case 16: return(ALTD | 'Q');
- case 17: return(ALTD | 'W');
- case 18: return(ALTD | 'E');
- case 19: return(ALTD | 'R');
- case 20: return(ALTD | 'T');
- case 21: return(ALTD | 'Y');
- case 22: return(ALTD | 'U');
- case 23: return(ALTD | 'I');
- case 24: return(ALTD | 'O');
- case 25: return(ALTD | 'P');
-
- case 30: return(ALTD | 'A');
- case 31: return(ALTD | 'S');
- case 32: return(ALTD | 'D');
- case 33: return(ALTD | 'F');
- case 34: return(ALTD | 'G');
- case 35: return(ALTD | 'H');
- case 36: return(ALTD | 'J');
- case 37: return(ALTD | 'K');
- case 38: return(ALTD | 'L');
-
- case 44: return(ALTD | 'Z');
- case 45: return(ALTD | 'X');
- case 46: return(ALTD | 'C');
- case 47: return(ALTD | 'V');
- case 48: return(ALTD | 'B');
- case 49: return(ALTD | 'N');
- case 50: return(ALTD | 'M');
-
- case 71: return(SPEC | '<'); /* HOME */
- case 72: return(SPEC | 'P'); /* cursor up */
- case 73: return(SPEC | 'Z'); /* page up */
- case 75: return(SPEC | 'B'); /* cursor left */
- case 77: return(SPEC | 'F'); /* cursor right */
- case 79: return(SPEC | '>'); /* end */
- case 80: return(SPEC | 'N'); /* cursor down */
- case 81: return(SPEC | 'V'); /* page down */
- case 82: return(SPEC | 'C'); /* insert */
- case 83: return(SPEC | 'D'); /* delete */
- case 115: return(SPEC | CTRL | 'B'); /* control left */
- case 116: return(SPEC | CTRL | 'F'); /* control right */
- case 117: return(SPEC | CTRL | '>'); /* control END */
- case 118: return(SPEC | CTRL | 'V'); /* control page down */
- case 119: return(SPEC | CTRL | '<'); /* control HOME */
- case 132: return(SPEC | CTRL | 'Z'); /* control page up */
- }
-
- return(ALTD | c);
- }
- #endif /* obsolete */
- #endif
-
-