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