home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / memacs400_src.lzh / MEMACS400 / SRC / nt.c < prev    next >
Text File  |  1996-04-25  |  18KB  |  564 lines

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