home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / OS2.C < prev    next >
C/C++ Source or Header  |  1991-09-05  |  14KB  |  568 lines

  1. /*    OS2.C:        Operating specific I/O and Spawning functions
  2.             for the OS/2 operating system
  3.             for MicroEMACS 3.9
  4.             (C)Copyright 1988 by Daniel M. Lawrence
  5.  
  6. Note:  don't try to compile this on non OS/2 systems.... the OS/2
  7.     includes MUST come before ours.....
  8.  
  9. Modifications needed: check that we don't construct command lines and
  10. temporary filenames which are too large for their buffers.
  11.  
  12. */
  13.  
  14. #define INCL_DOS
  15. #include "os2.h"
  16.  
  17. #include        <stdio.h>
  18.  
  19. #undef    PASCAL
  20. #undef    NEAR
  21. #undef    HIBYTE
  22.  
  23. #include    "estruct.h"
  24. #include    "eproto.h"
  25.  
  26. #if    OS2
  27. #define INCL_BASE
  28.  
  29. #include "elang.h"
  30. #include "edef.h"
  31.  
  32.  
  33. /*
  34.  * Create a subjob with a copy of the command intrepreter in it. When the
  35.  * command interpreter exits, mark the screen as garbage so that you do a full
  36.  * repaint. Bound to "^X C". The message at the start in VMS puts out a newline.
  37.  * Under some (unknown) condition, you don't get one free when DCL starts up.
  38.  */
  39. spawncli(f, n)
  40. {
  41.     /* don't allow this command if restricted */
  42.     if (restflag)
  43.         return(resterr());
  44.  
  45.         movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  46.         TTflush();
  47.     TTkclose();
  48.     shell();
  49.     TTkopen();
  50.         sgarbf = TRUE;
  51.         return(TRUE);
  52. }
  53.  
  54.  
  55. /*
  56.  * Run a one-liner in a subjob. When the command returns, wait for a single
  57.  * character to be typed, then mark the screen as garbage so a full repaint is
  58.  * done. Bound to "C-X !".
  59.  */
  60. spawn(f, n)
  61. {
  62.         register int s;
  63.         char line[NLINE];
  64.  
  65.     /* don't allow this command if restricted */
  66.     if (restflag)
  67.         return(resterr());
  68.  
  69.         if ((s=mlreply("!", line, NLINE)) != TRUE)
  70.                 return(s);
  71.     movecursor(term.t_nrow - 1, 0);
  72.     TTkclose();
  73.     system(line);
  74.     TTkopen();
  75.     /* if we are interactive, pause here */
  76.     if (clexec == FALSE) {
  77.             puts(TEXT6);
  78. /*                     "\r\n\n[End]" */
  79.             tgetc();
  80.         }
  81.         sgarbf = TRUE;
  82.         return (TRUE);
  83. }
  84.  
  85.  
  86. /*
  87.  * Run an external program with arguments. When it returns, wait for a single
  88.  * character to be typed, then mark the screen as garbage so a full repaint is
  89.  * done. Bound to "C-X $".
  90.  */
  91.  
  92. execprg(f, n)
  93. {
  94.         register int s;
  95.         char line[NLINE];
  96.  
  97.     /* don't allow this command if restricted */
  98.     if (restflag)
  99.         return(resterr());
  100.  
  101.         if ((s=mlreply("$", line, NLINE)) != TRUE)
  102.                 return(s);
  103.     movecursor(term.t_nrow - 1, 0);
  104.     TTkclose();
  105.         execprog(line);
  106.     TTkopen();
  107.     /* if we are interactive, pause here */
  108.     if (clexec == FALSE) {
  109.             puts(TEXT6);
  110. /*                     "\r\n\n[End]" */
  111.             tgetc();
  112.         }
  113.         sgarbf = TRUE;
  114.         return (TRUE);
  115. }
  116.  
  117. /*
  118.  * Pipe a one line command into a window
  119.  * Bound to ^X @
  120.  * We use a unique temporary file name so that multiple instances of
  121.  * MicroEMACS don't try to use the same file.
  122.  */
  123. pipecmd(f, n)
  124. {
  125.     register WINDOW *wp;    /* pointer to new window */
  126.     register BUFFER *bp;    /* pointer to buffer to zot */
  127.     register char *tmp;    /* ptr to TMP DOS environment variable */
  128.     char line[NLINE];    /* command line send to shell */
  129.     static char bname[] = "command";
  130.     static char filnam[NSTRING];
  131.     char *getenv();
  132.  
  133.     /* don't allow this command if restricted */
  134.     if (restflag)
  135.         return(resterr());
  136.  
  137.     /* get rid of the command output buffer if it exists */
  138.         if ((bp=bfind(bname, FALSE, 0)) != FALSE) {
  139.         /* try to make sure we are off screen */
  140.         wp = wheadp;
  141.         while (wp != NULL) {
  142.             if (wp->w_bufp == bp) {
  143.                 onlywind(FALSE, 1);
  144.                 break;
  145.             }
  146.             wp = wp->w_wndp;
  147.         }
  148.         /* get rid of the existing command buffer */
  149.         if (zotbuf(bp) != TRUE)
  150.             return(FALSE);
  151.     }
  152.  
  153.     /* get the command to pipe in */
  154.         if (mlreply("@", line, NLINE) != TRUE)
  155.                 return(FALSE);
  156.  
  157.     /* Call mktemp() to get a unique filename in the tmp directory. */
  158.     if ((tmp = getenv("TMP")) == NULL)
  159.         filnam[0] = 0;
  160.     else {
  161.         strcpy(filnam, tmp);
  162.         if (filnam[strlen(filnam) - 1] != '\\')
  163.             strcat(filnam, "\\");
  164.         }
  165.     strcat(filnam,"eXXXXXX");
  166.     mktemp(filnam);
  167.  
  168.     /* redirect the command output to the output file */
  169.     strcat(line, " >>");
  170.     strcat(line, filnam);
  171.     movecursor(term.t_nrow - 1, 0);
  172.  
  173.     /* execute the command */
  174.     TTkclose();
  175.     system(line);
  176.     TTkopen();
  177.         sgarbf = TRUE;
  178.  
  179.     /* did the output file get generated? */
  180.     if (access( filnam, 0) != 0)
  181.         return(FALSE);
  182.         
  183.     /* split the current window to make room for the command output */
  184.     if (splitwind(FALSE, 1) == FALSE)
  185.             return(FALSE);
  186.  
  187.     /* and read the stuff in */
  188.     if (getfile(filnam, FALSE) == FALSE)
  189.         return(FALSE);
  190.  
  191.     /* rename the buffer */
  192.     strcpy( curwp->w_bufp->b_bname, "command");
  193.     /* make this window in VIEW mode, update all mode lines */
  194.     curwp->w_bufp->b_mode |= MDVIEW;
  195.     wp = wheadp;
  196.     while (wp != NULL) {
  197.         wp->w_flag |= WFMODE;
  198.         wp = wp->w_wndp;
  199.     }
  200.  
  201.     /* and get rid of the temporary file */
  202.     unlink(filnam);
  203.     return(TRUE);
  204. }
  205.  
  206.  
  207. /*
  208.  * filter a buffer through an external DOS program
  209.  * Bound to ^X #
  210.  * We use unique temporary file names so that multiple instances of
  211.  * MicroEMACS don't try to use the same file.
  212.  */
  213. filter(f, n)
  214.  
  215. {
  216.     register int    s;    /* return status from CLI */
  217.     register BUFFER *bp;    /* pointer to buffer to zot */
  218.     char line[NLINE];    /* command line send to shell */
  219.     char tmpnam[NFILEN];    /* place to store real file name */
  220.     char *tmp;        /* ptr to TMP DOS environment variable */
  221.  
  222.     static char filnam1[NSTRING];
  223.     static char filnam2[NSTRING];
  224.  
  225.     /* don't allow this command if restricted */
  226.     if (restflag)
  227.         return(resterr());
  228.  
  229.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  230.         return(rdonly());    /* we are in read only mode    */
  231.  
  232.     /* get the filter name and its args */
  233.         if ((s=mlreply("#", line, NLINE)) != TRUE)
  234.                 return(s);
  235.  
  236.     /* Call mktemp() to get unique filenames in the tmp directory. */
  237.     if ((tmp = getenv("TMP")) == NULL)
  238.         filnam1[0] = filnam2[0] = 0;
  239.     else {
  240.         strcpy(filnam1, tmp);
  241.         strcpy(filnam2, tmp);
  242.         if (filnam1[strlen(filnam1) - 1] != '\\') {
  243.             strcat(filnam1, "\\");
  244.             strcat(filnam2, "\\");
  245.         }
  246.         }
  247.     strcat(filnam1,"eXXXXXX");
  248.     strcat(filnam2,"eXXXXXX");
  249.     mktemp(filnam1);
  250.                 
  251.     /* setup the proper file names */
  252.     bp = curbp;
  253.     strcpy(tmpnam, bp->b_fname);    /* save the original name */
  254.     strcpy(bp->b_fname, filnam1);    /* set it to our new one */
  255.  
  256.     /* write it out, checking for errors */
  257.     if (writeout(filnam1, "w") != TRUE) {
  258.         mlwrite(TEXT2);
  259. /*                      "[Cannot write filter file]" */
  260.         strcpy(bp->b_fname, tmpnam);
  261.         return(FALSE);
  262.     }
  263.  
  264.     mktemp(filnam2);
  265.     strcat(line, " <");        /* construct the command line */
  266.     strcat(line, filnam1);
  267.     strcat(line, " >");
  268.     strcat(line, filnam2);
  269.     
  270.     movecursor(term.t_nrow - 1, 0);
  271.     TTkclose();
  272.         system(line);
  273.     TTkopen();
  274.         sgarbf = TRUE;
  275.     s = TRUE;
  276.  
  277.     /* on failure, escape gracefully */
  278.     if (s != TRUE || (readin(filnam2,FALSE) == FALSE)) {
  279.         mlwrite(TEXT3);
  280. /*                      "[Execution failed]" */
  281.         strcpy(bp->b_fname, tmpnam);
  282.         unlink(filnam1);
  283.         unlink(filnam2);
  284.         return(s);
  285.     }
  286.  
  287.     /* reset file name */
  288.     strcpy(bp->b_fname, tmpnam);    /* restore name */
  289.     bp->b_flag |= BFCHG;        /* flag it as changed */
  290.  
  291.     /* and get rid of the temporary file */
  292.     unlink(filnam1);
  293.     unlink(filnam2);
  294.     return(TRUE);
  295. }
  296.  
  297.  
  298.  
  299. /*    SHELL: Bring up a shell. */
  300.  
  301. shell(void)
  302. {
  303.     char *shell;        /* Name of system command processor */
  304.  
  305.  
  306.     /*  get name of system shell  */
  307.     if ((shell = getenv("COMSPEC")) == NULL) {
  308.         return(FALSE);        /*  No shell located  */
  309.     }
  310.  
  311.     /*
  312.      * We are actually setting up a shell inside a shell here.
  313.      * Is there a better way?
  314.      */
  315.     return(system(shell));
  316. }
  317.  
  318.  
  319.  
  320. execprog( char *cmd)
  321. {
  322.     char         args[NSTRING];        /* args passed to program */
  323.     char        *sp;
  324.     char         failName[NFILEN];
  325.     char         prog[NSTRING];        /* name of program */
  326.     USHORT         i;
  327.     PRESULTCODES     results;
  328.     
  329.  
  330.     /*
  331.      * Parse the command name from the command line and copy it
  332.      * into the prog and args arrays.
  333.      */
  334.     i = 0;
  335.     while (cmd[i]  &&  (cmd[i] != ' ')  &&  (cmd[i] != '\t')) {
  336.         prog[i] = args[i] = cmd[i];
  337.         i++;
  338.     }
  339.     prog[i] = args[i] = 0;        /* terminate with a null */
  340.  
  341.     /* skip whitespace and copy the args */
  342.     while (cmd[i]  &&  ((cmd[i] == ' ')  ||  (cmd[i] == '\t')))
  343.         i++;
  344.     while (cmd[i]) {
  345.         args[i] = cmd[i];
  346.         i++;
  347.     }
  348.     args[i] = args[i + 1] = 0;    /* terminate with 2 nulls */
  349.     
  350.     
  351.     /* look up the program on the path, trying various extentions */
  352.     if ((sp = flook(prog, TRUE)) == NULL)
  353.         if ((sp = flook(strcat(prog, ".exe"), TRUE)) == NULL) {
  354.             strcpy(&prog[strlen(prog)-4], ".com");
  355.             if ((sp = flook(prog, TRUE)) == NULL)
  356.                 return(FALSE);
  357.         }
  358.     strcpy(prog, sp);
  359.  
  360.     /*
  361.      * Execute the program synchronously.  We wait for child
  362.      * to return.
  363.      */
  364.     return (0 == DosExecPgm( failName, NFILEN, EXEC_SYNC,
  365.                      args, 0, results, prog));
  366. }
  367.  
  368.     
  369. /*    FILE Directory routines        */
  370.  
  371. FILEFINDBUF pBuf;    /* buffer to hold file information */
  372. HDIR hDir;        /* directory handle */
  373. int num_found;        /* number of directory entries found/to find */
  374.  
  375. char path[NFILEN];    /* path of file to find */
  376. char rbuf[NFILEN];    /* return file buffer */
  377.  
  378. /*    do a wild card directory search (for file name completion) */
  379.  
  380. char *PASCAL NEAR getffile(fspec)
  381.  
  382. char *fspec;    /* pattern to match */
  383.  
  384. {
  385.     register int index;        /* index into various strings */
  386.     register int point;        /* index into other strings */
  387.     register int extflag;        /* does the file have an extention? */
  388.     char fname[NFILEN];        /* file/path for DOS call */
  389.  
  390.     /* first parse the file path off the file spec */
  391.     strcpy(path, fspec);
  392.     index = strlen(path) - 1;
  393.     while (index >= 0 && (path[index] != '/' &&
  394.                 path[index] != '\\' && path[index] != ':'))
  395.         --index;
  396.     path[index+1] = 0;
  397.  
  398.     /* check for an extension */
  399.     point = strlen(fspec) - 1;
  400.     extflag = FALSE;
  401.     while (point > index) {
  402.         if (fspec[point] == '.') {
  403.             extflag = TRUE;
  404.             break;
  405.         }
  406.         point--;
  407.     }
  408.  
  409.     /* construct the composite wild card spec */
  410.     strcpy(fname, path);
  411.     strcat(fname, &fspec[index+1]);
  412.     strcat(fname, "*");
  413.     if (extflag == FALSE)
  414.         strcat(fname, ".*");
  415.  
  416.     /* and call for the first file */
  417.     num_found = 1;
  418.     hDir = HDIR_CREATE;
  419.     if (DosFindFirst(fname, &hDir, FILE_NORMAL|FILE_DIRECTORY,
  420.               &pBuf, sizeof(pBuf), &num_found, 0L) != 0)
  421.         return(NULL);
  422.  
  423.     /* return the first file name! */
  424.     strcpy(rbuf, path);
  425.     strcat(rbuf, pBuf.achName);
  426.     mklower(rbuf);
  427.     if (pBuf.attrFile == FILE_DIRECTORY)
  428.         strcat(rbuf, DIRSEPSTR);
  429.     return(rbuf);
  430. }
  431.  
  432. char *PASCAL NEAR getnfile()
  433.  
  434. {
  435.     register int index;        /* index into various strings */
  436.     register int point;        /* index into other strings */
  437.     register int extflag;        /* does the file have an extention? */
  438.     char fname[NFILEN];        /* file/path for DOS call */
  439.  
  440.     /* and call for the next file */
  441.     if (DosFindNext(hDir, (void *)&pBuf, sizeof(pBuf), &num_found) != 0)
  442.         return(NULL);
  443.  
  444.     /* return the first file name! */
  445.     strcpy(rbuf, path);
  446.     strcat(rbuf, pBuf.achName);
  447.     mklower(rbuf);
  448.     if (pBuf.attrFile == FILE_DIRECTORY)
  449.         strcat(rbuf, DIRSEPSTR);
  450.     return(rbuf);
  451. }
  452.  
  453. /* return a system dependant string with the current time */
  454.  
  455. char *timeset()
  456.  
  457. {
  458.     register char *sp;    /* temp string pointer */
  459.     char buf[16];        /* time data buffer */
  460.     extern char *ctime();
  461.  
  462.     time(buf);
  463.     sp = ctime(buf);
  464.     sp[strlen(sp)-1] = 0;
  465.     return(sp);
  466. }
  467.  
  468. #if    OBSOLETE
  469. /*    extcode:    resolve MSDOS extended character codes
  470.             encoding the proper sequences into emacs
  471.             printable character specifications
  472. */
  473.  
  474. int extcode(
  475.     unsigned c    /* byte following a zero extended char byte */
  476. )
  477.  
  478. {
  479.     /* function keys 1 through 9 */
  480.     if (c >= 59 && c < 68)
  481.         return(SPEC | c - 58 + '0');
  482.  
  483.     /* function key 10 */
  484.     if (c == 68)
  485.         return(SPEC | '0');
  486.  
  487.     /* shifted function keys */
  488.     if (c >= 84 && c < 93)
  489.         return(SPEC | SHFT | c - 83 + '0');
  490.     if (c == 93)
  491.         return(SPEC | SHFT | '0');
  492.  
  493.     /* control function keys */
  494.     if (c >= 94 && c < 103)
  495.         return(SPEC | CTRL | c - 93 + '0');
  496.     if (c == 103)
  497.         return(SPEC | CTRL | '0');
  498.  
  499.     /* ALTed function keys */
  500.     if (c >= 104 && c < 113)
  501.         return(SPEC | ALTD | c - 103 + '0');
  502.     if (c == 113)
  503.         return(SPEC | ALTD | '0');
  504.  
  505.     /* ALTed number keys */
  506.     if (c >= 120 && c < 129)
  507.         return(ALTD | c - 119 + '0');
  508.     if (c == 130)
  509.         return(ALTD | '0');
  510.  
  511.     /* some others as well */
  512.     switch (c) {
  513.         case 3:        return(0);        /* null */
  514.         case 15:    return(SHFT | CTRL | 'I');    /* backtab */
  515.  
  516.         case 16:    return(ALTD | 'Q');
  517.         case 17:    return(ALTD | 'W');
  518.         case 18:    return(ALTD | 'E');
  519.         case 19:    return(ALTD | 'R');
  520.         case 20:    return(ALTD | 'T');
  521.         case 21:    return(ALTD | 'Y');
  522.         case 22:    return(ALTD | 'U');
  523.         case 23:    return(ALTD | 'I');
  524.         case 24:    return(ALTD | 'O');
  525.         case 25:    return(ALTD | 'P');
  526.  
  527.         case 30:    return(ALTD | 'A');
  528.         case 31:    return(ALTD | 'S');
  529.         case 32:    return(ALTD | 'D');
  530.         case 33:    return(ALTD | 'F');
  531.         case 34:    return(ALTD | 'G');
  532.         case 35:    return(ALTD | 'H');
  533.         case 36:    return(ALTD | 'J');
  534.         case 37:    return(ALTD | 'K');
  535.         case 38:    return(ALTD | 'L');
  536.  
  537.         case 44:    return(ALTD | 'Z');
  538.         case 45:    return(ALTD | 'X');
  539.         case 46:    return(ALTD | 'C');
  540.         case 47:    return(ALTD | 'V');
  541.         case 48:    return(ALTD | 'B');
  542.         case 49:    return(ALTD | 'N');
  543.         case 50:    return(ALTD | 'M');
  544.  
  545.         case 71:    return(SPEC | '<');    /* HOME */
  546.         case 72:    return(SPEC | 'P');    /* cursor up */
  547.         case 73:    return(SPEC | 'Z');    /* page up */
  548.         case 75:    return(SPEC | 'B');    /* cursor left */
  549.         case 77:    return(SPEC | 'F');    /* cursor right */
  550.         case 79:    return(SPEC | '>');    /* end */
  551.         case 80:    return(SPEC | 'N');    /* cursor down */
  552.         case 81:    return(SPEC | 'V');    /* page down */
  553.         case 82:    return(SPEC | 'C');    /* insert */
  554.         case 83:    return(SPEC | 'D');    /* delete */
  555.         case 115:    return(SPEC | CTRL | 'B');    /* control left */
  556.         case 116:    return(SPEC | CTRL | 'F');    /* control right */
  557.         case 117:    return(SPEC | CTRL | '>');    /* control END */
  558.         case 118:    return(SPEC | CTRL | 'V');    /* control page down */
  559.         case 119:    return(SPEC | CTRL | '<');    /* control HOME */
  560.         case 132:    return(SPEC | CTRL | 'Z');    /* control page up */
  561.     }
  562.  
  563.     return(ALTD | c);
  564. }
  565. #endif    /* obsolete */
  566. #endif
  567.  
  568.