home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / AOSVS.C < prev    next >
C/C++ Source or Header  |  1991-10-11  |  56KB  |  1,925 lines

  1. /*
  2.  * aosvs.c  -  AOS/VS & MV/UX version of the termio.c module
  3.  *
  4.  * The functions in this module deal with the O/S in reading/writing
  5.  * characters from/to the screen.  We also deal with various wiedness things
  6.  * in dealing with the AOS/VS file system such as ACL's and elementsizes.
  7.  * This has been written primarily for AOS/VS but should work for MV/UX as
  8.  * well.  No promises though.
  9.  *
  10.  * AOS/VS and MV/UX are products of Data General Corporation, Westboro MA.
  11.  *
  12.  * Authors:
  13.  *          Daniel Lawrence --- doing MicroEmacs... stuff copied into here...
  14.  *          Douglas Rady ------ most of the rest of the stuff here
  15.  * Credits:
  16.  *          Michael Meissner -- beating Doug over the head with advice and info.
  17.  *                              on AOS/VS "C" compiler.     THANK YOU!!!!!!!!!!
  18.  *          Bill Benedetto
  19.  *          & friends      ---- beta victims, bug finders/fixers
  20.  *          GNU --------------- inspiration, software tools, clean readable BSD
  21.  *                              and USG code examples and interesting comments.
  22.  *
  23.  * Definition: uka = Unixly Known As
  24.  *
  25.  * Revision/Hack History
  26.  *  MicroEMACS v3.<9p,10> AOS/VS History
  27.  *  
  28.  *  3.09.16.00 - 3.09.16.09         ??-???-??           dcr
  29.  *      Before written history.  Suffice to say that .00 - .04 was just the
  30.  *      AOS/VS port from 3.8z, 3.9e, 3.9i and 3.9n with major cleaning up and
  31.  *      rewriting of the AOS/VS stuff.  Sub-revisions 3.09.16.05 - 3.09.16.09
  32.  *      being optimizations and various fixes.
  33.  *      Yawn...
  34.  *
  35.  *  3.09.16.10                      25-Aug-88           dcr
  36.  *      Changed  do_system_end()  in  aosvs.c  to check for execution of a 
  37.  *    macro as basis for not executing an  mlreply("Continue")  call.
  38.  *      Also fixed  stime()  in  aosvs.c  so it just plain worked.
  39.  *      #$&^@*&(+$#!!!!
  40.  *      Also added  REPLYNL  in  estruct.h  and made use of CR or NL in the
  41.  *      mlreply()  routine in  input.c  compile time conditional.
  42.  *
  43.  *  3.09.16.11                      13-Sep-88           dcr
  44.  *      Start of written hisory.  This is a momentous event in the course of
  45.  *      AOS/VS MicroEMACS history: doug writes some change doc.!!! Yeah!!!
  46.  *      Changed several functions to force the  $builtin  version as a trade of
  47.  *      more code size for more speed (usually defaulted to $builtin anyway...).
  48.  *
  49.  *  3.09.16.12                      14-Sep-88           dcr
  50.  *      Recompiled with revision 4.00 of AOS/VS C.  A miracle...
  51.  *
  52.  *  3.09.16.13                      12-Oct-88           dcr
  53.  *      Changed to have the temporary file for pipecmd() be created in a system
  54.  *      wide temporary file directory known as :TMP, uka /tmp.  You paranoids
  55.  *      can create :TMP as a CPD with max. size of 2048 blocks and an ACL of
  56.  *      +,WE and you should be able to relax a nibble.
  57.  *      Creates temp. file with ACL of  username,OWAR
  58.  *
  59.  *  3.09.16.14                      13-Oct-88           dcr
  60.  *      Put in MCA's hack to reduce memory consumption when VIEWing a file.
  61.  *      Modified  lalloc()  in line.c  Test case of paru.h saved 27 2Kb pages.
  62.  *
  63.  *  3.10.00.00                      09-Nov-88           dcr
  64.  *      Begin code porting for 3.10 BETA.
  65.  *
  66.  *  3.10.00.01                      20-Dec-88           dcr
  67.  *      Implemented multi-language messages in  aosvs.c  per 3.10 BETA.
  68.  *
  69.  *  3.10.00.02                      26-Dec-88           dcr
  70.  *      Tracked down some un-documented runtime optimizations and got
  71.  *      a working version. Also resolved timeset() references.
  72.  *
  73.  *  3.10.00.03                      17-Jan-89           dcr
  74.  *      Cleaned up for shipping to Dan.  Put in some missing code for input.c
  75.  *
  76.  *  3.10.00.04                      17-Jan-89           dcr
  77.  *      Put in some optimizations regarding TTflush() and ostring() in the
  78.  *      bind.c, input.c and aosvs.c files.  This freed 2Kb... but not for long.
  79.  *
  80.  *  3.10.00.05                      17-Jan-89           dcr
  81.  *      Some memory optimization in  exec.c  and  input.c for small regain.
  82.  *
  83.  *  3.10.00.06 - 3.10.00.27     02-Mar-89 - 10-Mar-89   dcr
  84.  *      Various changes. Cleaned up the AOS/VS changes in other modules so 
  85.  *      we actually work right.  Added conditionals for using either BSD or
  86.  *      USG console i/o (BSD doesn't seem to work).  Reclaimed about 4Kb of 
  87.  *      memory in various places and made some of these optimizations compile
  88.  *      time conditional. We are still using .890+ ms to start up intead of the
  89.  *      .520+ ms that we took with 3.9p. Not much hope there... but...
  90.  *      Various tweaks here and there.  Added the skip of nulls when reading in
  91.  *      a file (most unpleasant results if we don't).  Lost some memory to the
  92.  *      USG console i/o stuff.  Threw out the BSD console i/o stuff, sigh....
  93.  *
  94.  *  3.10.00.28                      10-Mar-89           dcr
  95.  *      Stuck in the  aosvs$unix_to_aosvs_path()  routine to replace the code
  96.  *      in resolve_pathname().  The new routine does a fairly complete job of
  97.  *      converting Unix(tm) pathnames to AOS/VS format. It also handles the 
  98.  *      Ms-Dog '\' path seperator.
  99.  *  
  100.  *  3.10.00.29                      16-Mar-89           dcr
  101.  *      Changed pathname expansion to be invisible to user.  Required changes
  102.  *      to  fileio.c  to #if AOSVS  replace the fopen() calls with our xxfopen()
  103.  *      call which does the pathname expansion.  Allowed removal of all the
  104.  *      related to the EXPPATH define.  Also changed several routines here.
  105.  *      Allows user to reference buffer & file names w/o "unexpanding" the 
  106.  *      orginal pathname.
  107.  *      Diff'd & sent to Dan.
  108.  *
  109.  */
  110.  
  111. #nolist
  112. #include        <stdio.h>           /* get the usual */
  113. #list
  114. #include        "estruct.h"         /* get the MicroEMACS stuff */
  115.  
  116. #ifdef  AOSVS | MV_UX               /* should this be done? */
  117.  
  118. #define dashertermdef   1           /* might not be used any more */
  119.  
  120. #nolist
  121. #include        "edef.h"            /* get the MicroEMACS extern's */
  122. #include        "elang.h"
  123. #list
  124.  
  125. /* There is no kitchen sink in C so we can't include it. Maybe in C++... */
  126. #nolist
  127. #include    <paru.h>                /* AOS/VS system mnemonics */
  128. #include    <sysid.h>               /* AOS/VS system call mnemonics */
  129. #include    <packets/characteristics.h> /* sys call packet for terminal char.*/
  130. #include    <packets/create.h>      /* sys call packet to create files */
  131. #include    <packets/filestatus.h>  /* sys call packet to get file info */
  132. #include    <packets/misc.h>        /* misc. sys call packets (?SYSPRV) */
  133.  
  134. /* And now... the Unix(tm) stuff... */
  135. #include    <fcntl.h>               /* terminal file control stuff */
  136. #include    <signal.h>              /* the signals... */
  137. #include    <termio.h>              /* more terminal control stuff */
  138. #list
  139.  
  140. /*
  141.     Variables!!!   Functions!!!  Externals!!!!
  142. */
  143. struct  termio  old_in_termio;  /* original stdin terminal characteristics */
  144. struct  termio  new_in_termio;  /* stdin characteristics to use inside */
  145.  
  146. int kbdpoll;                    /* type ahead polling flag      */
  147. int kbdflgs;                    /* saved keyboard fd flags      */
  148. int kbdqp;                      /* there is a char in kbdq      */
  149. char kbdq;                      /* char we've already read      */
  150.  
  151. /*
  152.     some D.G. supplied AOS/VS & MV/UX specific functions
  153.  
  154.     _toaos_fid() - changes UNIX(tm)  pathname to AOS/VS pathname (Thank you!)
  155.     traceback() - calls the ?SNAP LANG_RT routine for error traceback
  156. */    
  157. /*extern int  _toaos_fid(char*, char* );*/
  158. extern VOID traceback(int );
  159.  
  160. /*
  161.     This is how we make an MV/Eclipse accumulator in C with almost all options.
  162. */
  163. union accumulator {                 /* dearly beloved, we are gathered here...*/
  164.     unsigned long * ptr;            /* pointer to unsigned long (generic) */
  165.     char *          cptr;           /* pointer to char */
  166.     unsigned int  * pint;           /* pointer to unsigned int */
  167.     unsigned short *psht;           /* pointer to short */
  168.     unsigned long   ulng;           /* unsigned long */
  169.     signed long     lng;            /* signed long */
  170.     unsigned int    uin;            /* unsigned int */
  171.     signed int      in;             /* signed int */
  172.     unsigned short usht;            /* unsigned short */
  173.     unsigned char   chr;            /* a char, unsigned of course!!! */
  174. } ac0, ac1, ac2;                    /* our bountiful accumulators, sigh... */
  175.     
  176.  
  177. P_CREATE    create_pkt;             /* file create system call packet */
  178. P_FSTAT     fstat_pkt;              /* file status system call packet */
  179. char acl_buf[ $MXACL ];             /* ACL buffer, gotta protect things... */
  180. char *crt_eol="\013";               /* Dasher D2xx commands */
  181. char *crt_eop="\014";               /* Dasher D2xx commands */
  182. int dimsts, revsts;
  183. int su_mode;                        /* Superuser mode flag */
  184. #define TLINE_LEN   512
  185. char tline[TLINE_LEN];                /* command line for cli/shell/program calls */
  186.  
  187. extern VOID do_system();        /* calls the cli/shell/program */
  188. extern VOID do_system_end();    /* cleans up after cli/shell/program calls */
  189. extern VOID init_tline();       /* inits the command line for cli/shell... */
  190. extern VOID ttputs();
  191. extern VOID in_init();
  192. extern FILE *ffp;               /* file stream pointer used in fileio.c */
  193. extern int vttidy();            /* MicroEMACS routine to tidy up the screen */
  194.  
  195. extern int              aosvs$expand_pathname();
  196. extern void             aosvs$unix_to_aosvs_path();
  197. #endif
  198.  
  199. FILE *STDIN, *STDOUT;           /* Needed since the array of files went away.*/
  200.                                 /* Of course, if _iob changes, we'll have to */
  201.                 /* bend over since we use  ->_file  in _iob. */
  202.  
  203. static int mexist;    /* is the mouse driver installed? */
  204. static int nbuttons;    /* number of buttons on the mouse */
  205. static int oldbut;    /* Previous state of mouse buttons */
  206.  
  207. /*------------------------------------------------------------------------------
  208.  *  resolve_full_pathname(char*, char*) - resolves a filename or pathname to
  209.  *  full AOS/VS pathname via the ?GRNAME system call.  If the file does not
  210.  *  exsist then the current working directory is assumed by  AOS/VS.
  211.  *
  212.  *  Returns  FIOSUC  if  from_path  is found or  FIOFNF  if it isn't found.
  213.  */
  214. int resolve_full_pathname(from_path, to_path)
  215.  
  216. char *from_path, *to_path;      /* resolve "from" pathname "to" pathname */
  217. {
  218.     if (aosvs$expand_pathname(from_path, to_path))
  219.         return(FIOFNF);
  220.  
  221.     return(FIOSUC);
  222. }
  223.  
  224. /*
  225.  *  ffwopen() - AOS/VS specific version of the ffwopen() routine found in the
  226.  *  fileio.c source.  This version will attempt to recreate the edit file
  227.  *  (if it exists) with the existing edit file ACL, elementsize, filetype and
  228.  *  recordsize parameters as determined via a ?FSTAT filestatus system call.
  229.  *
  230.  *  Returns  FIOSUC  if file is opened or  FIOERR  if not opened.
  231.  *
  232.  *    DOUG, we need to make the mode param work here, or ignore it....
  233.  */
  234. int ffwopen(bfilnam, mode, sfilnam)
  235.  
  236. char *bfilnam;    /* buffer file name */
  237. char *mode;      /* mode for file open (w = write, a = append) */
  238. char *sfilnam;    /* save file name or NULL */
  239. {
  240.     char bfnam[NFILEN], sfnam[NFILEN];
  241.     char *tptr;
  242.  
  243.     /* some initializations */
  244.     zero((char *) &create_pkt, sizeof(create_pkt));
  245.     zero((char *) &fstat_pkt, sizeof(fstat_pkt));
  246.     zero(acl_buf, $MXACL);
  247.  
  248.     strcpy(bfnam, bfilnam);
  249.     if (sfilnam) {
  250.         strcpy(sfnam, sfilnam);
  251.     resolve_full_pathname(sfnam, sfnam);
  252.         tptr = sfnam;
  253.     } else {
  254.         tptr = bfnam;    
  255.     }
  256.     
  257.     create_pkt.ctim = -1L;      /* take default file creation time */
  258.     create_pkt.cacp = -1L;      /* take default file creation acl */
  259.     create_pkt.cdel = -1L;      /* take default file creation elementsize */
  260.     create_pkt.cmil = -1L;      /* take default file creation max. index levels */
  261.     fstat_pkt.stim = -1L;
  262.     fstat_pkt.sacp = -1L;
  263.  
  264.     /* attempt to get full AOS/VS pathname of the file */
  265.     if  ((resolve_full_pathname(bfnam, bfnam)) == FIOFNF) { /* edit file found? */
  266.         /* bfnam not found, create one with default specs. */
  267.         create_pkt.cftyp_format = $ORDS;    /* data sensitive record type */
  268.         create_pkt.cftyp_entry  = $FTXT;    /* text file type */
  269.         ac2.ptr = &create_pkt;
  270.         ac1.lng = 0L;
  271.  
  272.         ac0.cptr = tptr;
  273.  
  274.         /* have AOS/VS attempt to create the file */
  275.         if  (sys($CREATE, &ac0, &ac1, &ac2))
  276.             goto fubar;
  277.  
  278.     } else {    /* bfnam found, get filestatus info. for recreation of bfnam */ 
  279.         ac2.ptr = &fstat_pkt;
  280.         ac1.lng = 0L;
  281.         ac0.cptr = bfnam;
  282.         /* have AOS/VS attempt to get the file information for us */
  283.         if  (sys($FSTAT, &ac0, &ac1, &ac2))
  284.             goto fubar;
  285.  
  286.         /*
  287.             Get ACL of bfnam.  If we can't get that then we get the
  288.             default ACL and use that.
  289.         */
  290.         ac0.cptr = bfnam;
  291.         ac1.cptr = acl_buf;
  292.         ac2.lng = 0L;
  293.         if  (sys($GACL, &ac0, &ac1, &ac2)) {    /* try to get the file ACL */
  294.             /* can't get ACL of file, get default ACL */
  295.             ac0.lng = 0L;
  296.             ac2.lng = 0L;
  297.             ac1.cptr = acl_buf;
  298.             sys($DACL, &ac0, &ac1, &ac2); /* try to get user default ACL */
  299.         }
  300.  
  301.         /*
  302.             Delete  sfnam  file.  We don't care about any errors on this.
  303.         */
  304.         ac0.cptr = tptr;
  305.         ac1.lng = 0L;
  306.         ac2.lng = 0L;
  307.         sys($DELETE, &ac0, &ac1, &ac2);   /* delete it */
  308.     
  309.         /*
  310.             Set up the packet for the file create system call
  311.         */
  312.         create_pkt.cftyp_format = fstat_pkt.styp_format;    /* file format  */
  313.         create_pkt.cftyp_entry  = fstat_pkt.styp_type;      /* file type    */
  314.         create_pkt.ccps = fstat_pkt.scps;   /* recordsize, if any */
  315.         create_pkt.cacp = acl_buf;          /* acl buffer ptr   */
  316.         create_pkt.cdeh = fstat_pkt.sdeh;   /* element size     */
  317.         create_pkt.cmil = fstat_pkt.smil;   /* max. index level */
  318.  
  319.         /*
  320.             Make system call to create a file with supplied specs.
  321.         */
  322.         ac2.ptr  = &create_pkt;
  323.         ac0.cptr = tptr;
  324.  
  325.         ac1.lng = 0L;
  326.         if  (sys($CREATE, &ac0, &ac1, &ac2))    /* attempt file create */
  327.             goto fubar;
  328.     }
  329.  
  330.     if  ((ffp = fopen(tptr, "a")) == NULL)
  331.             goto fubar;
  332.  
  333. #if     ISADIR
  334.     if  (isadirectory(ffp)) {   /* check to see if file is a directory */
  335.         mlwrite(TEXT216);       /* bitch... */
  336.     ffclose(ffp);           /* yes, close it and get out!!! */
  337.         return(FIOERR);         /* actual checking code in O/S modules */
  338.     }
  339. #endif
  340.  
  341.     return(FIOSUC);
  342.  
  343.     /*
  344.         Common error exit for all  ffwopen()  errors
  345.     */
  346. fubar:
  347.     mlwrite(TEXT155);
  348. /*    mlwrite("Cannot open file for writing");*/
  349.     return(FIOERR);
  350. }
  351.  
  352. /*
  353.  *  unlink() - delete a file - called from  writeout()  in  file.c
  354.  *
  355.  *  This routine replaces the DG supplied  unlink()  since we don't use the
  356.  *  link() unlink() combination to rename files.  Saves some memory.
  357.  *
  358.  */
  359. int unlink(del_fnam)
  360.  
  361. char *del_fnam;        /* name of file to delete */
  362. {
  363.     char dtmp[NFILEN];
  364.  
  365.     strcpy(dtmp, del_fnam);
  366.     resolve_full_pathname(dtmp, dtmp);
  367.     ac0.cptr = dtmp;
  368.     ac1.lng = 0L;
  369.     ac2.lng = 0L;
  370.     if (sys($DELETE, &ac0, &ac1, &ac2))    /* attempt to delete it */
  371.         return(-1);                           /* normal error return */
  372.     return(0);                                /* normal okay return */
  373. }
  374.  
  375. /*
  376.  *  rename() - rename a file - called from  writeout()  in  file.c
  377.  */
  378. int rename(from_nam, to_nam)
  379.  
  380. char *from_nam;     /* rename from name */
  381. char *to_nam;       /* rename to name */
  382. {
  383.     char ftmp[NFILEN], ttmp[NFILEN];
  384.  
  385.     /*
  386.         First we convert Unix(tm) or Ms-dog paths to Aos/Vs paths.
  387.         Second we strip the actual filename from the "to" path by going to the
  388.     end of the string and working our way backward until we find a pathname
  389.     seperator which under AOS/VS is a colon (:).
  390.     */
  391.     strcpy(ftmp, from_nam);
  392.     strcpy(ttmp, to_nam);
  393.     resolve_full_pathname(ftmp, ftmp);
  394.     resolve_full_pathname(ttmp, ttmp);
  395.  
  396.     ac1.cptr = ttmp + (sizeof(char) * strlen(ttmp));
  397.     while ((ac1.cptr >= ttmp) && (*ac1.cptr != ':') && (*ac1.cptr != '='))
  398.         --ac1.cptr;
  399.  
  400.     ++ac1.cptr;     /* move pointer from seperator to 1st char in filename */
  401.     ac0.cptr = ftmp;
  402.     ac2.lng = 0L;
  403.     if  (sys($RENAME, &ac0, &ac1, &ac2))    /* attempt the rename */
  404.         return(-1);   /* oops!!! */
  405.     return(0);        /* okay... */
  406. }
  407.  
  408. /*
  409.  * This function gets called just before we go back home to the command
  410.  * interpreter.
  411.  */
  412. VOID ttclose()
  413. {
  414.     fflush(stdout);
  415.     fflush(stdin);
  416.     ioctl(STDIN->_file, TCSETA, &old_in_termio);     /* restore terminal settings */
  417.     fcntl(STDIN->_file, F_SETFL, kbdflgs);
  418. }
  419.  
  420. /*
  421.  * Write a character to the display.
  422.  */
  423. #if TTPUTC == 0
  424. VOID ttputc(c)
  425. {
  426.     putc(c, stdout);
  427. }
  428. #endif
  429.  
  430. /*
  431.  * Flush terminal buffer. Does real work where the terminal output is buffered
  432.  * up. A no-operation on systems where byte at a time terminal I/O is done.
  433.  */
  434. #if TTFLUSH == 0
  435. VOID ttflush()
  436. {
  437.     fflush(stdout);
  438. }
  439. #endif
  440.  
  441. unsigned int extcode(c)
  442.  
  443. unsigned int c;
  444.  
  445. {
  446.     if ((c == 1 || c == 8 || c == 17 || c == 23) || (c >= 24 && c <=26)
  447.         || (c >= 32 && c <= 110) || (c >= 112 && c <= 126))   /* 111 is mouse */
  448.         return((c & 255) | SPEC);
  449.  
  450.     return(c & 255);
  451. }
  452.  
  453. /*    input buffers and pointers    */
  454.  
  455. #define    IBUFSIZE    64    /* this must be a power of 2 */
  456.  
  457. unsigned char in_buf[IBUFSIZE];    /* input character buffer */
  458. int in_next = 0;        /* pos to retrieve next input character */
  459. int in_last = 0;        /* pos to place most recent input character */
  460.  
  461. VOID in_init()  /* initialize the input buffer */
  462.  
  463. {
  464.     in_next = in_last = 0;
  465. }
  466.  
  467. int in_check()    /* is the input buffer non-empty? */
  468.  
  469. {
  470.     if (in_next == in_last)
  471.         return(FALSE);
  472.     else
  473.         return(TRUE);
  474. }
  475.  
  476. VOID in_put(event)
  477.  
  478. int event;    /* event to enter into the input buffer */
  479.  
  480. {
  481.     in_buf[in_last++] = event;
  482.     in_last &= (IBUFSIZE - 1);
  483. }
  484.  
  485. int in_get()    /* get an event from the input buffer */
  486.  
  487. {
  488.     register int event;    /* event to return */
  489.  
  490.     event = in_buf[in_next++];
  491.     in_next &= (IBUFSIZE - 1);
  492.     return(event);
  493. }
  494. #if    MOUSE
  495. int checkmouse()
  496.  
  497. {
  498.     register int k;        /* current bit/button of mouse */
  499.     register int event;    /* encoded mouse event */
  500.     int newbut;        /* new state of the mouse buttons */
  501.     int mousecol;        /* current mouse column */
  502.     int mouserow;        /* current mouse row */
  503.     int sstate;        /* current shift key status */
  504.  
  505.     /* check to see if any mouse buttons are different */
  506. /*    rg.x.ax = 3;*/    /* Get button status and mouse position */
  507. /*    int86(0x33, &rg, &rg);*/
  508. /*    newbut   = rg.x.bx;*/
  509. /*    mousecol = rg.x.cx >> 3;*/
  510.     mouserow = rg.x.dx >> 3;
  511.  
  512.     /* get the shift key status as well */
  513.     sstate = 0;
  514. /*    rg.h.ah = 2;*/    /* return current shift status */
  515. /*    int86(0x16, &rg, &rg);*/
  516. /*    sstate = rg.h.al;*/
  517.  
  518.     for (k=1; k != (1 << nbuttons); k = k<<1) {
  519.         /* For each button on the mouse */
  520.         if ((oldbut&k) != (newbut&k)) {
  521.             /* This button changed, generate an event */
  522.             in_put(0);
  523.             in_put(MOUS >> 8);
  524.             in_put(mousecol);
  525.             in_put(mouserow);
  526.             event = ((newbut&k) ? 0 : 1);    /* up or down? */
  527.             if (k == 2)            /* center button? */
  528.                 event += 4;
  529.             if (k == 4)            /* right button? */
  530.                 event += 2;
  531.             if (sstate & 3)            /* shifted */
  532.                 event += 'A';
  533.             else if (sstate & 4)        /* controled? */
  534.                 event += 1;
  535.             else
  536.                 event += 'a';        /* plain */
  537.             in_put(event);
  538.             oldbut = newbut;
  539.             return(TRUE);
  540.         }
  541.     }
  542.     return(FALSE);
  543. }
  544. #endif
  545.  
  546. int doschar()
  547.  
  548. {
  549. /* USG - SysV console i/o - From  "C Users Journal", April 1989, Vol. 7, # 9 */
  550.     if(kbdqp)               /* any typeahead known? */
  551.         kbdqp = FALSE;      /* yes, clear flag & return typeahead char */
  552.     else {                  /* no typeahead. */
  553.         if (fcntl(STDIN->_file, F_SETFL, kbdflgs) < 0 && kbdpoll)
  554.             return(FALSE);
  555.         kbdpoll = FALSE;
  556.         read(STDIN->_file, &kbdq, 1);   /* wait and get a char */
  557.     }
  558.     if (kbdq == '\036') {   /* D.G. Dasher CRT function key lead-in? */
  559.         in_put(SPEC >> 8);  /* ??? stash in the keyboard buffer stuff ??? */
  560.         return(0);
  561.     }
  562.     return (kbdq & 255);
  563. }
  564.  
  565. /*
  566.  * Read a character from the terminal, performing no editing and doing no echo
  567.  * at all.
  568.  */
  569. int ttgetc()
  570. {
  571.         /* return any keystrokes waiting in the
  572.         type ahead buffer */
  573. ttc:    if (in_check())
  574.         return(in_get());
  575.  
  576.     if (typahead())
  577.         return(doschar());
  578.  
  579.     /* with no mouse, this is a simple get char routine */
  580.     if (mexist == FALSE || mouseflag == FALSE)
  581.             return(doschar());
  582.  
  583. #if    MOUSE
  584.     /* turn the mouse cursor on */
  585. /*    rg.x.ax = 1;*/    /* Show Cursor */
  586. /*    int86(0x33, &rg, &rg);*/
  587.     /* loop waiting for something to happen */
  588.     while (TRUE) {
  589.         if (typahead())
  590.             break;
  591.         if (checkmouse())
  592.             break;
  593.     }
  594.  
  595.     /* turn the mouse cursor back off */
  596. /*    rg.x.ax = 2;*/    /* Hide Cursor */
  597. /*    int86(0x33, &rg, &rg);*/
  598.  
  599.         goto ttc:
  600. #endif  /* MOUSE */
  601. }
  602.  
  603. #if     TYPEAH
  604. /* typahead:    Check to see if any characters are already in the
  605.                 keyboard buffer.  Hurray for kludges!!!
  606. */
  607. int typahead()
  608. {
  609. /* USG - SysV console i/o - From  "C Users Journal", April 1989, Vol. 7, # 9 */
  610.     if (!kbdqp) {
  611.         if (fcntl(STDIN->_file, F_SETFL, (kbdflgs | O_NDELAY)) < 0 && kbdpoll)
  612.             return(FALSE);
  613.         kbdpoll = TRUE;
  614.         kbdqp = (1 == read(STDIN->_file, &kbdq, 1));
  615.     }
  616.     return(kbdqp);
  617. }
  618.  
  619. #endif  /* TYPEAH */
  620.  
  621. /*      Spawn:  various DOS access commands
  622.                 for MicroEMACS ver 3.9e
  623. */
  624.  
  625.  
  626. /*
  627.  * Create a subjob with a copy of the command intrepreter in it. When the
  628.  * command interpreter exits, mark the screen as garbage so that you do a full
  629.  * repaint. Bound to "^X C".
  630.  */
  631. int spawncli(f, n)
  632. {
  633.     register char *cp;
  634.  
  635.     /* don't allow this command if restricted */
  636.     if (restflag)
  637.         return(resterr());
  638.  
  639. #if     MV_UX
  640.     TTflush();
  641.     TTclose();                              /* stty to old settings */
  642.     if ((cp = getenv("SHELL")) != NULL && *cp != '\0')
  643.         system(cp);
  644.     else
  645.         system("exec /bin/sh");
  646. #endif
  647.  
  648. #if     AOSVS
  649.     init_tline();
  650.     strcat(tline,"CHAIN/1=AB/2=AB,:CLI,EMACS_SET_CLI_PREFIX");
  651.     do_system();
  652. #endif
  653.  
  654.     sleep(2);
  655.     return(TRUE);
  656. }
  657.  
  658. /*
  659.  * Run a one-liner in a subjob. When the command returns, wait for a single
  660.  * character to be typed, then mark the screen as garbage so a full repaint is
  661.  * done. Bound to "C-X !".
  662.  */
  663. int spawn(f, n)
  664. {
  665.     register int    s;
  666.     char            line[NLINE];
  667.  
  668.     /* don't allow this command if restricted */
  669.     if (restflag)
  670.         return(resterr());
  671.  
  672.     if ((s=mlreply("!", line, NLINE)) != TRUE)
  673.         return (s);
  674.     init_tline();
  675.     strcat(tline,line);
  676.     do_system();
  677.     do_system_end();
  678.     return (TRUE);
  679. }
  680.  
  681. /*
  682.  * Run an external program with arguments. When it returns, wait for a single
  683.  * character to be typed, then mark the screen as garbage so a full repaint is
  684.  * done. Bound to "C-X $".
  685.  */
  686.  
  687. int execprg(f, n)
  688.  
  689. {
  690.     register int    s;
  691.     char            line[NLINE];
  692.  
  693.     /* don't allow this command if restricted */
  694.     if (restflag)
  695.         return(resterr());
  696.  
  697.     if ((s=mlreply("!", line, NLINE)) != TRUE)
  698.         return (s);
  699.     strcpy(tline, line);
  700.     do_system();
  701.     do_system_end();
  702.     return (TRUE);
  703. }
  704.  
  705. /*
  706.  * Pipe a one line command into a window
  707.  * Bound to ^X @
  708.  *
  709.  * This command REQUIRES a directory named :TMP or a link by that name to 
  710.  * another directory such as :SL_TEMPS.  This diectory should have an
  711.  * ACL of  +,RWE  which will allow all users to access it.  This diectory is
  712.  * where the output file for this command is placed.  This was done because
  713.  * the sons of MircoEMACS do not always have the same privileges.  The file
  714.  * is of the pathname :TMP:pid.MICRO_EMACS_COMMAND where "pid" is the PID
  715.  * of the MicroEMACS process.  Also note that this sort of follows the UNIX(tm)
  716.  * convention for a common temporary file directory.
  717.  * The temp. file is created with an ACL of  username,OWAR
  718.  *
  719.  * See the THINGS_TO_DO.TXT for planned enhancements in this area.
  720.  *
  721.  */
  722. int pipecmd(f, n)
  723. {
  724.     register int    s;      /* return status from CLI */
  725.     register WINDOW *wp;    /* pointer to new window */
  726.     register BUFFER *bp;    /* pointer to buffer to zot */
  727.     char    line[NLINE];    /* command line send to shell */
  728.     const char pipecmd_bname[] = "command";
  729.     char pipecmd_filnam[NFILEN] = ":tmp:";  /* must be AOS/VS format!!!! */
  730.  
  731.  
  732.     /* don't allow this command if restricted */
  733.     if (restflag)
  734.         return(resterr());
  735.  
  736.     /* get the users pid and build a pathname for our scratch file */
  737.     ac0.ulng = 0L;
  738.     ac2.ulng = 0L;
  739.     ac1.ulng = -1L;
  740.     sys($PNAME, &ac0, &ac1, &ac2);    /* get our PID */
  741.     itoa(ac1.in, line);
  742.     strcat(pipecmd_filnam, line);     /* build temp. filename */
  743.     strcat(pipecmd_filnam, ".micro_emacs_command");
  744.  
  745.     zero((char *) &create_pkt, sizeof(create_pkt));
  746.     zero(acl_buf, $MXACL);
  747.     ac2.cptr = &acl_buf;
  748.     ac0.ulng = -1L;
  749.     ac1.ulng = -1L;
  750.     sys($GUNM, &ac0, &ac1, &ac2);     /* get our user name */
  751.     ac0.cptr = &acl_buf[strlen(acl_buf)];
  752.     ac0.cptr++;
  753.     *ac0.cptr = ($FACO | $FACW | $FACA | $FACR);  /* specify the ACL */
  754.     ac0.cptr++;
  755.     *ac0.cptr = '\000';
  756.     create_pkt.cacp = &acl_buf;         /* load addr of temp file ACL */
  757.  
  758.     create_pkt.ctim = -1L;
  759.     create_pkt.cdel = -1L;
  760.     create_pkt.cmil = -1L;
  761.     create_pkt.cftyp_format = $ORDS;    /* data sensitive */
  762.     create_pkt.cftyp_entry  = $FTXT;    /* TEXT file type */
  763.     ac2.ptr = &create_pkt;
  764.     ac1.lng = 0L;
  765.     ac0.cptr = &pipecmd_filnam;
  766.     sys($CREATE, &ac0, &ac1, &ac2);   /* have AOS/VS create the temp file */
  767.  
  768.     /* get the command to pipe in */
  769.     if ((s=mlreply("@", line, NLINE)) != TRUE)
  770.         return(s);
  771.  
  772.     /* get rid of the command output buffer if it exists */
  773.     if ((bp=bfind(pipecmd_bname, FALSE, 0)) != FALSE) {
  774.         /* try to make sure we are off screen */
  775.         wp = wheadp;
  776.         while (wp) {
  777.             if (wp->w_bufp == bp) {
  778.                 onlywind(FALSE, 1);
  779.                 break;
  780.             }
  781.             wp = wp->w_wndp;
  782.         }
  783.         if (zotbuf(bp) != TRUE)
  784.             return(FALSE);
  785.     }
  786.  
  787.     s = 0;                          /* init. index into line        */
  788.     init_tline();
  789.     strcat(tline,"LISTFILE,");      /* give CLI an @LIST to use     */
  790.     strcat(tline,pipecmd_filnam);           /* tack on the filename for @LIST */
  791.     strcat(tline,";");              /* separate the commands        */
  792.     s = strpbrk(line,",; \t");      /* check for cmd line delimiters */
  793.     if (s) {                        /* find any?    */
  794.         strncat(tline,line,(s-(int) &line));/* get whats before the delimeter*/
  795.         strcat(tline,"/L");         /* tack on "use @LIST file" switch */
  796.         strcat(tline,s);            /* get the rest of the cmd line */
  797.     } else {                        /* no delimiers...      */
  798.          strcat(tline,line);        /* get the cmd line     */
  799.         strcat(tline,"/L");         /* tack on "use @LIST file" switch*/
  800.     }
  801.     strcat(tline,";BYE/L=@NULL");   /* tell CLI to die quietly      */
  802.     do_system();
  803.     s = TRUE;
  804.  
  805.     /* split the current window to make room for the command output */
  806.     if (splitwind(FALSE, 1) == FALSE)
  807.         goto fubar;
  808.  
  809.     /* and read the stuff in */
  810.     if (getfile(pipecmd_filnam, FALSE) == FALSE)
  811.         goto fubar;
  812.  
  813.     /* make this window in VIEW mode, update all mode lines */
  814.     curwp->w_bufp->b_mode |= MDVIEW;
  815.     wp = wheadp;
  816.     while (wp) {
  817.         wp->w_flag |= WFMODE;
  818.         wp = wp->w_wndp;
  819.     }
  820.  
  821.     /* and get rid of the temporary file */
  822.     unlink(pipecmd_filnam);
  823.     return(TRUE);
  824.  
  825. fubar:
  826.     unlink(pipecmd_filnam);
  827.     return(FALSE);
  828. }
  829.  
  830. /*
  831.  * filter a buffer through an external DOS program
  832.  * Bound to ^X #
  833.  */
  834. int filter(f, n)
  835.  
  836. {
  837.     mlwrite(TEXT217);
  838. /*    mlwrite("[Not available yet under AOS/VS]");*/
  839.     sleep(1);
  840.     return(FALSE);
  841. }
  842.  
  843.  
  844. /*
  845.     return a system dependant string with the current time
  846.     original version didn't work.  modified idea of bill benedetto by
  847.     doug rady.  note the use of sys($ITIME, ...)  instead of sys_itime() 
  848. */
  849. char *PASCAL NEAR timeset()
  850.  
  851. {
  852.     register char *sp;      /* temp string pointer */
  853.     short int tvec[2];
  854.     extern char *dg_ctime();
  855.  
  856.     ac0.ulng = 0L;
  857.     ac1.ulng = 0L;
  858.     ac2.ulng = 0L;
  859.     sys($ITIME, &ac0, &ac1, &ac2);    /* get system time */
  860.     tvec[0] = ac2.in;
  861.     ac1.lng /= 32768L;
  862.     tvec[1] = (int)(ac1.lng/2L);
  863.     sp = dg_ctime(tvec);
  864.     sp[ strlen(sp)-1 ] = NULL;
  865.     return(sp);
  866. }
  867.  
  868. VOID init_tline()
  869. {
  870.     extern char *curdir();
  871.  
  872.     tline[0] = '\000';
  873.     strcat(tline, "DIR,");
  874.     curdir(&tline[4]);
  875.     strcat(tline, ";");
  876.     return;
  877. }
  878.  
  879. VOID do_system()
  880. {
  881.     movecursor(term.t_nrow, 0);             /* Seek to last line.   */
  882.     mlerase();
  883.     TTclose();                              /* stty to old modes    */
  884.     system(tline);
  885.     TTkopen();
  886.     sgarbf = TRUE;
  887. }
  888.  
  889. VOID do_system_end()
  890. {
  891.     int s;
  892.  
  893.     if  (clexec == TRUE) {
  894.         mlputs(TEXT188);
  895. /*        mlputs("[End]");*/
  896.         TTflush();
  897.         while ((s = tgetc()) != '\r' && s != ' ')
  898.             ;
  899.     }
  900.     return;
  901. }
  902.  
  903. /*
  904.     Data General AOS/VS terminal handling routines
  905.   
  906.     Known types are:
  907.       DASHER D2xx/4xx series - support primarily for D2xx series
  908.       written by Doug Rady (based on ANSI.C and VMSVT.C)
  909.  */
  910. extern  VOID    ttopen();
  911. extern  VOID    ttkopen();
  912. extern  VOID    ttkclose();
  913. extern  VOID    tteeol();
  914. extern  VOID    tteeop();
  915. extern  VOID    ttbeep();
  916. extern  VOID    dashermove();
  917. extern  VOID    ansimove();
  918. extern  VOID    dasherrev();
  919. extern  VOID    ansirev();
  920. extern  int     ttcres();
  921. #if     COLOR
  922. extern  VOID    ttfcol();
  923. extern  VOID    ttbcol();
  924. #endif
  925. extern  VOID    dasherdim();
  926. extern  VOID    ansidim();
  927. extern  VOID    spal();
  928.  
  929. #define NROWS   24              /* normal # of screen rows */
  930. #define MXROWS  24              /* max # of screen rows */
  931. #define NCOLS   80              /* normal mode # of screen columns*/
  932. #define MXCOLS  135             /* wide mode # of screen columns*/
  933. #define MARGIN  4               /* size of minimim margin and   */
  934. #define SCRSIZ  64              /* scroll size for extended lines */
  935. #define NPAUSE  100             /* # times thru update to pause */
  936. #define ESC     0x16
  937. #define BEL     7
  938.  
  939. /*
  940.  * Dispatch table. All the
  941.  * hard fields just point into the
  942.  * terminal I/O code.
  943.  */
  944. noshare TERM    term    = {
  945.         MXROWS -1,
  946.         NROWS -1,
  947.         MXCOLS,
  948.         NCOLS,
  949.     0, 0,
  950.         MARGIN,
  951.         SCRSIZ,
  952.         NPAUSE,
  953.         &ttopen,
  954.         &ttclose,
  955.         &ttkopen,
  956.         &ttkclose,
  957.         &ttgetc,
  958. #if TTPUTC == 0
  959.         &ttputc,
  960. #endif
  961. #if TTFLUSH == 0
  962.         &ttflush,
  963. #endif
  964.         &dashermove,
  965.         &tteeol,
  966.         &tteeop,
  967.         &tteeop,
  968.         &ttbeep,
  969.         &dasherrev,
  970.         &ttcres,
  971.         &dasherdim,
  972. #if     COLOR
  973.         &ttfcol,
  974.         &ttbcol
  975. #endif
  976. };
  977.  
  978. /*
  979.     dashermove - Move the cursor for DG Dasher
  980.  */
  981. VOID dashermove(row, col)
  982. {
  983.     TTputc('\020');
  984.     TTputc(col);
  985.     TTputc(row);
  986. }
  987.  
  988. /*
  989.     ansimove - Move the cursor for ANSI crt
  990.  */
  991. VOID ansimove(row, col)
  992.  
  993. int row, col;
  994. {
  995.     char rc_tmp[ 8 ];
  996.  
  997.     ++row;
  998.     ++col;
  999.     ttputs("\033[");
  1000.     itoa(row, rc_tmp);
  1001.     ttputs(rc_tmp);
  1002.     TTputc(';');
  1003.     itoa(col, rc_tmp);
  1004.     ttputs(rc_tmp);
  1005.     TTputc('H');
  1006. }
  1007.  
  1008. /*
  1009.  *  dasherrev - set the reverse video status for DG Dasher
  1010.  */
  1011. VOID dasherrev(status)
  1012.  
  1013. int status;     /* TRUE = reverse video, FALSE = normal video */
  1014. {
  1015.     if (status)
  1016.         ttputs("\036\104");
  1017.     else
  1018.         ttputs("\036\105");
  1019. }
  1020.  
  1021. /*
  1022.  *  ansirev- set the reverse video status for ANSI crt
  1023.  */
  1024. VOID ansirev(status)
  1025.  
  1026. int status;
  1027. {
  1028.     if  (dimsts) {
  1029.         if (status) {
  1030.             ttputs("\033[0;2;7m");
  1031.         } else {
  1032.             ttputs("\033[0;2m");
  1033.         }
  1034.     } else {
  1035.         if (status) {
  1036.             ttputs("\033[0;7m");
  1037.         } else {
  1038.             ttputs("\033[0m");
  1039.         }
  1040.     }
  1041.     if  (status)
  1042.         revsts = TRUE;
  1043.     else
  1044.         revsts = FALSE;
  1045. }
  1046.  
  1047. /*
  1048.  *  dasherdim - set the dim/bright video status for DG Dasher
  1049.  */
  1050. VOID dasherdim(status)
  1051.  
  1052. int status;     /* TRUE = dim video, FALSE = bright video */
  1053. {
  1054.     if (status)
  1055.        TTputc('\034');
  1056.     else
  1057.        TTputc('\035');
  1058. }
  1059.  
  1060. /*
  1061.  *  ansidim - set the dim/bright video status for ANSI crt
  1062.  */
  1063. VOID ansidim(status)
  1064.  
  1065. int status;
  1066. {
  1067.     if  (revsts) {
  1068.         if (status) {
  1069.             ttputs("\033[0;2;7m");
  1070.         } else {
  1071.             ttputs("\033[0;7m");
  1072.         }
  1073.     } else {
  1074.         if (status) {
  1075.             ttputs("\033[0;2m");
  1076.         }
  1077.         else
  1078.         {
  1079.             ttputs("\033[0m");
  1080.         }
  1081.     }
  1082.     if  (status)
  1083.         dimsts = TRUE;
  1084.     else
  1085.         dimsts = FALSE;
  1086. }
  1087.  
  1088. /*
  1089.     ttcres - Change screen resolution (what resolution?)
  1090. */
  1091. int ttcres()
  1092. {
  1093.         return(TRUE);
  1094. }
  1095.  
  1096. VOID spal()          /* change palette string */
  1097.  
  1098. {
  1099.         /*      Does nothing here       */
  1100. }
  1101.  
  1102. #if     COLOR
  1103. /*
  1104.     ttfcol - Set the forground color (not implimented)
  1105.  */
  1106. VOID ttfcol()
  1107. {
  1108. }
  1109.  
  1110. /*
  1111.     ttbcol - Set the background color (not implimented)
  1112.  */
  1113.  
  1114. VOID ttbcol()
  1115. {
  1116. }
  1117. #endif  /* COLOR */
  1118.  
  1119. /*
  1120.     tteeol - Erase to end of line
  1121.  */
  1122. VOID tteeol()
  1123. {
  1124.     ttputs(crt_eol);
  1125. }
  1126.  
  1127.  
  1128. /*
  1129.     tteeop - Erase to end of page (clear screen)
  1130.  */
  1131. VOID tteeop()
  1132. {
  1133.     ttputs(crt_eop);
  1134. }
  1135.  
  1136.  
  1137. /*
  1138.     ttbeep - Ring the bell
  1139.  */
  1140. VOID ttbeep()
  1141. {
  1142.     TTputc('\007');
  1143. }
  1144.  
  1145. VOID ttputs(str)
  1146. char *str;
  1147. {
  1148.     while(*str) {
  1149.         putc(*str, stdout);
  1150.     str++;
  1151.     }
  1152. }
  1153.  
  1154. /*
  1155.     ttopen() - open the terminal and change characteristics for our use
  1156.  */
  1157.  
  1158. VOID ttopen()
  1159. {
  1160.     int sys_err;
  1161.     P_CHAR_EX   crt_info;               /* for ?GECHR system call */
  1162.     /*
  1163.     set some traps
  1164.     */
  1165.     signal(SIGTRAP, &traceback);
  1166.     signal(SIGIOT,  &traceback);
  1167.     signal(SIGILL,  &traceback);
  1168.     signal(SIGSEGV, &traceback);
  1169.     signal(SIGTERM, &traceback);
  1170. /*    signal(SIGINT,  &traceback);*/
  1171.     signal(SIGQUIT, &traceback);
  1172.     signal(SIGEMT,  &traceback);
  1173.     signal(SIGFPE,  &traceback);
  1174.     signal(SIGKILL, &traceback);
  1175.     signal(SIGBUS,  &traceback);
  1176.     signal(SIGSYS,  &traceback);
  1177.     signal(SIGTERM, &traceback);
  1178.  
  1179.     ac0.in = fchannel(stdout);    /* make sure it is opened */
  1180.     ac0.in = fchannel(stdin);     /* make sure it is opened */
  1181.     ac1.ulng = (BIT0 | (sizeof(crt_info)/2)); /* get characteristics flag */
  1182.     ac2.ptr = (unsigned long*) &crt_info;
  1183.  
  1184.     sys_err = sys($GECHR, &ac0, &ac1, &ac2);    /* ?GECHR system call */
  1185.  
  1186.     /*
  1187.         copy the actual stdio pointer macro values into pointers
  1188.     */
  1189.     STDIN   = stdin;
  1190.     STDOUT  = stdout;
  1191.  
  1192.     /*
  1193.         set LPP & CPL in case they aren't == defaults - idea from bill benedetto
  1194.         resetting the max. row value is condtional because some of us can
  1195.         display more than LPP lines on a screen.
  1196.     */
  1197.     term.t_ncol = (short)crt_info.char_cpl;     /* get CPL */
  1198.     term.t_nrow = ((short)crt_info.char_lpp -1);/* get LPP */
  1199.     if  (term.t_nrow > term.t_mrow)   /* only reset max. row if LPP is > */
  1200.         term.t_mrow = term.t_nrow;      /* default max. row */
  1201.  
  1202. #if XXCRT
  1203.     if  (termcode == 0) { /* CRT type given on command line? */
  1204.         /* nope, we must figure it out */
  1205.     }
  1206.     
  1207.     switch  (termcode) {
  1208.         case 0: /* Generic ANSI compliant */
  1209.             crt_eol     = "\033[K";
  1210.             crt_eop     = "\033[J";
  1211.             term.t_move = &ansimove;
  1212.             term.t_rev  = &ansirev;
  1213.             term.t_dim  = &ansidim;
  1214. /*
  1215.             term.t_getkey = &ansigetkey;
  1216. */
  1217.             break;
  1218.         case 1: /* DEC VT100 */
  1219.         case 2: /* DEC VT100K */
  1220.             crt_eol     = "\033[K";
  1221.             crt_eop     = "\033[J";
  1222.             term.t_move = &ansimove;
  1223.             term.t_rev  = &ansirev;
  1224.             term.t_dim  = &ansidim;
  1225. /*
  1226.             term.t_getkey = &vt100getkey;
  1227. */
  1228.             break;
  1229.         case 4: /* DEC VT102 */
  1230.         case 5: /* DEC VT102K */
  1231.             crt_eol     = "\033[K";
  1232.             crt_eop     = "\033[J";
  1233.             term.t_move = &ansimove;
  1234.             term.t_rev  = &ansirev;
  1235.             term.t_dim  = &ansidim;
  1236.             crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE);
  1237. /*
  1238.             term.t_getkey = &vt100getkey;
  1239. */
  1240.             break;
  1241.         case 7: /* DEC VT220 */
  1242.         case 8: /* DEC VT220K */
  1243.             crt_eol     = "\033[K";
  1244.             crt_eop     = "\033[J";
  1245.             term.t_move = &ansimove;
  1246.             term.t_rev  = &ansirev;
  1247.             term.t_dim  = &ansidim;
  1248. /*
  1249.             term.t_getkey = &vt220getkey;
  1250. */
  1251.             break;
  1252.         case 6: /* D.G. Dasher D4xx */
  1253.             crt_func = (INS_CHAR | INS_LINE | DEL_CHAR | DEL_LINE);
  1254.             break;
  1255.         case 3: /* D.G. Dasher D2xx */
  1256.         default;
  1257.     }
  1258. #else
  1259.     if  ((crt_info.char_cdt != char_d2xx)    /* is not CRT3 or D2xx ?  and */
  1260.     &&  (crt_info.char_cdt != char_d4xx)) {  /* is not CRT6 or D4xx or D5xx ? */
  1261.         crt_eol     = "\033[K";
  1262.         crt_eop     = "\033[J";
  1263.         term.t_move = &ansimove;
  1264.         term.t_rev  = &ansirev;
  1265.         term.t_dim  = &ansidim;
  1266.     }
  1267. #endif  /* XXCRT */
  1268.  
  1269.     /*
  1270.         change terminal charactersitcs to Unix(tm) raw mode
  1271.     */
  1272.     ioctl(STDIN->_file, TCGETA, &old_in_termio);    /* save old settings */
  1273.     new_in_termio.c_iflag = 0;            /* setup new settings */
  1274.     new_in_termio.c_oflag = 0;
  1275.     new_in_termio.c_lflag = 0;
  1276.     new_in_termio.c_cc[VTIME] = 0;
  1277.     new_in_termio.c_cc[VMIN] = 1;
  1278.     new_in_termio.c_line = BELL_LD;       /* emulate unix(tm) line handling */
  1279.     new_in_termio.c_cflag = old_in_termio.c_cflag;
  1280.     ioctl(STDIN->_file, TCSETA, &new_in_termio);
  1281.     kbdflgs = fcntl(STDIN->_file, F_GETFL, 0);
  1282.     dimsts = 0;
  1283.     revsts = 0;
  1284.  
  1285.     /*
  1286.     check for mouse here
  1287.     */
  1288.     mexist = 0;
  1289.     nbuttons = 0;
  1290.     oldbut = 0;
  1291.  
  1292.     /*
  1293.         on all screens we are not sure of the initial position
  1294.         of the cursor
  1295.     */
  1296.     ttrow = 999;
  1297.     ttcol = 999;
  1298.  
  1299.     /* assume terminal has following */
  1300.     eolexist = TRUE;
  1301.     revexist = TRUE;
  1302.     strcpy(sres, "NORMAL");
  1303.  
  1304.     /*
  1305.         here we lower the priority of this task so that the console
  1306.     reader task will always get control when we get a char.
  1307.     */
  1308.     ac0.ulng = 0L;                      /* will get TID of this task */
  1309.     ac1.ulng = 0L;                      /* will get task pri. this task */
  1310.     ac2.ulng = 0L;                      /* who knows... */
  1311.     sys($MYTID, &ac0, &ac1, &ac2);
  1312.     ac1.ulng = 100L;                    /* new task priority */
  1313.     ac2.ulng = 0L;                      /* must be zero... */
  1314.     sys($IDPRI, &ac1, &ac0, &ac2);      /* do it!!! */
  1315.  
  1316. }
  1317.  
  1318. /*
  1319.     open the keyboard
  1320. */  
  1321. VOID ttkopen()
  1322. {
  1323.     /*
  1324.         activate the MircoEmacs console characteristics
  1325.     */
  1326.     ioctl(STDIN->_file, TCSETA, &new_in_termio);
  1327.     fcntl(STDIN->_file, F_SETFL, kbdflgs);
  1328.     kbdqp = 0;
  1329.     kbdpoll = FALSE;
  1330.     kbdq = '\000';
  1331.     in_init();
  1332. }
  1333.  
  1334. VOID ttkclose()
  1335. {
  1336. }
  1337.  
  1338. #if     FLABEL
  1339. fnclabel(f, n)          /* label a function key */
  1340.  
  1341. int f,n;        /* default flag, numeric argument [unused] */
  1342.  
  1343. {
  1344.         /* on machines with no function keys...don't bother */
  1345.         return(TRUE);
  1346. }
  1347. #endif
  1348.  
  1349. /*
  1350.      Change the current working directory
  1351. */
  1352. PASCAL NEAR int chdirectory()
  1353.  
  1354. {
  1355. #if CHDIR                               /* include this code?   */
  1356.  
  1357.     /* don't allow this command if restricted    */
  1358.     if (restflag)
  1359.         return(resterr());
  1360.  
  1361.     if ((ac0.in = mlreply("Directory: ", tline, NLINE)) != TRUE)
  1362.         return(ac0.in);
  1363.     
  1364.     ac0.in = chdir(tline);    /* change the current working directory */
  1365.  
  1366.     /*
  1367.     tell the story... success or failure
  1368.     */
  1369.     if (ac0.in) {
  1370.         mlwrite("Error- directory not changed.");
  1371.         return(ac0.in);
  1372.     }
  1373.     else {
  1374.         mlwrite("Directory changed.");
  1375.     return(TRUE);
  1376.     }
  1377. #endif
  1378. }
  1379.  
  1380.  
  1381. #if ORMDNI
  1382.  
  1383. /*
  1384.     superuser on/off toggle routines to override those annoying ACLs
  1385.  
  1386.     usage:  superuser_on();  or  superuser_off();
  1387.  
  1388. */
  1389. int superuser_on()
  1390.  
  1391. {
  1392.     int err;
  1393.  
  1394.     if  (restflag)
  1395.         return(resterr());
  1396.  
  1397.     ac0.lng = -1L;
  1398.     ac1.ulng = 0L;
  1399.     ac2.ulng = 0L;
  1400.     err = 0;
  1401.  
  1402.     if  ((err = sys($SUSER, &ac0, &ac1, &ac2)))
  1403.         if  (err = ERPRV)
  1404.         mlwrite("Error: you are not allowed use of superuser.");
  1405.         else
  1406.         mlwrite("Error turning superuser ON.");
  1407.  
  1408.     return(err);
  1409. }
  1410.  
  1411.  
  1412. int superuser_off()
  1413.  
  1414. {
  1415.     int err;
  1416.  
  1417.     if  (restflag)
  1418.         return(resterr());
  1419.  
  1420.     ac0.ulng = 1L;
  1421.     ac1.ulng = 0L;
  1422.     ac2.ulng = 0L;
  1423.     err = 0;
  1424.  
  1425.     if  ((err = sys($SUSER, &ac0, &ac1, &ac2)))
  1426.         mlwrite("Error turning superuser OFF.");
  1427.  
  1428.     return(err);
  1429. }
  1430. #endif
  1431.  
  1432. #if     ISADIR
  1433. int isadirectory(fstream)
  1434.  
  1435. FILE *fstream;
  1436.  
  1437. {
  1438.     return(isadir(fstream->_file));
  1439. }
  1440. #endif
  1441.  
  1442.  
  1443. /****************************************************************************/
  1444. /*                                                                          */
  1445. /*                                                                          */
  1446. /*  All aosvs$ library routines Copyright (c) 1989 by Douglas C. Rady       */
  1447. /*                                                                          */
  1448. /*                                                                          */
  1449. /****************************************************************************/
  1450.  
  1451. /*
  1452.     aosvs$bsd_dir.h -- a replacement inlcude file under AOS/VS for:
  1453.     <dir.h> -- definitions for 4.2BSD-compatible directory access
  1454.  
  1455.         Taken from GNU's emacs/etc/ndir.h for porting GNU stuff to AOS/VS.
  1456.  
  1457.         All of the usual fields are defined but dd_buf is defined as a char*
  1458.     so we can pass a poniter to a template under AOS/VS.
  1459. */
  1460.  
  1461. #ifndef DIRSIZ
  1462. struct direct {                /* data from readdir() */
  1463.     long        d_ino;        /* inode number of entry */
  1464.     unsigned short    d_reclen;    /* length of this record */
  1465.     unsigned short    d_namlen;    /* length of string in d_name */
  1466.     char        d_name[$MXFN];    /* name of file */
  1467.     };
  1468. #endif
  1469.  
  1470. typedef struct {
  1471.     int    dd_fd;            /* file desc. - channel# under aos/vs */
  1472.     int    dd_loc;            /* offset in block */
  1473.     int    dd_size;        /* amount of valid data */
  1474.         char   *dd_buf;                 /* pointer to wildcard/template */
  1475.     }    DIR;                    /* stream data from opendir() */
  1476.  
  1477. /*
  1478.     set up the MV/Eclipse accumulators used by the  aosvs$  routines
  1479. */
  1480. $align(1) $low32k union aosvs$accumulator { /* dearly beloved, we are gathered here...*/
  1481.     unsigned long * ptr;            /* pointer to unsigned long */
  1482.     char *          cptr;           /* pointer to char */
  1483.     unsigned int  * pint;           /* pointer to unsigned int */
  1484.     unsigned short *psht;           /* pointer to short */
  1485.     unsigned long   ulng;           /* unsigned long */
  1486.     signed long     lng;            /* signed long */
  1487.     unsigned int    uin;            /* unsigned int */
  1488.     signed int      in;             /* signed int */
  1489.     unsigned short usht;            /* unsigned short */
  1490.     unsigned char   chr;            /* a char, unsigned of course!!! */
  1491. } aosvs$ac0, aosvs$ac1, aosvs$ac2;  /* our bountiful accumulators, sigh... */
  1492.  
  1493.  
  1494. /*
  1495.     aosvs$bsd_dir.c -- fake 4.2BSD directory access routines for AOS/VS
  1496.  
  1497.     System call city...
  1498.  
  1499. */
  1500.  
  1501. P_GNFN aosvs$bsd_gnfn_pkt;
  1502.  
  1503. /*
  1504.     aosvs$bsd_closedir
  1505. */
  1506. void closedir(dir_stream)  /* $name("aosvs$bsd_closedir") */
  1507.  
  1508. DIR *dir_stream;
  1509.  
  1510. {
  1511.     aosvs$ac0.ulng = 0L;
  1512.     aosvs$ac2.ulng = 0L;
  1513.     aosvs$ac1.in = dir_stream->dd_fd;   /* load channel number */
  1514.     sys($GCLOSE, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2);
  1515. }
  1516.  
  1517.  
  1518. /*
  1519.     aosvs$bsd_opendir
  1520. */
  1521.  
  1522. DIR *opendir(dir_name) /* name$("aosvs$bsd_opendir") */
  1523.  
  1524. char *dir_name;
  1525.  
  1526. {
  1527.  
  1528. #include    "packets/block_io.h"
  1529.     
  1530.     P_GOPEN gopen_pkt;
  1531.     DIR *dir_stream;
  1532.     int err;
  1533.     char t_name[$MXPL];
  1534.  
  1535.     err = 0;
  1536.     dir_stream = (DIR *) malloc(sizeof(DIR));
  1537.     zero((char *) dir_stream, sizeof(DIR));
  1538.     zero((char *) &aosvs$bsd_gnfn_pkt, sizeof(aosvs$bsd_gnfn_pkt));
  1539.     zero((char *) &gopen_pkt, sizeof(gopen_pkt));
  1540.  
  1541.     err = aosvs$expand_pathname(dir_name, t_name);
  1542.     aosvs$ac0.cptr = t_name;
  1543.     aosvs$ac1.lng = -1L;
  1544.     aosvs$ac2.ptr = &gopen_pkt;
  1545.  
  1546.     /* Try to ?GOPEN the file. */
  1547.     if (err = sys($GOPEN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2)) {
  1548.         free(dir_stream);       /* Error Will Robinson! Error! Error! */
  1549.         return(NULL);
  1550.     }
  1551.  
  1552.     /* Make sure it is some type of directory! */
  1553.     if ((gopen_pkt.opty_type != $FDIR) && (gopen_pkt.opty_type != $FLDU)
  1554.     && (gopen_pkt.opty_type != $FCPD)) {    /* AOS/VS 7.62 directory types. */
  1555.         dir_stream->dd_fd = (int)gopen_pkt.opch;
  1556.         closedir(dir_stream);
  1557.         free(dir_stream);       /* Error Will Robinson! Error! Error! */
  1558.         return(NULL);
  1559.     }
  1560.  
  1561.     dir_stream->dd_fd = (int)gopen_pkt.opch;    /* stash the channel number */
  1562.     return(dir_stream);
  1563. }
  1564.  
  1565.  
  1566. /*
  1567.     aosvs$bsd_readdir
  1568. */
  1569.  
  1570. struct direct *readdir(dir_stream)   /* name$("aosvs$bsd_readdir") */
  1571.  
  1572. DIR *dir_stream;
  1573.  
  1574. {
  1575.     struct direct *dptr;
  1576.  
  1577.     dptr = NULL;
  1578.     aosvs$ac0.in = 0;
  1579.     aosvs$ac1.in = dir_stream->dd_fd;   /* load channel number */
  1580.  
  1581.     dptr = (struct direct *) malloc(sizeof(struct direct));
  1582.     zero((char *)dptr, sizeof(struct direct));
  1583.  
  1584.     if (dir_stream->dd_loc)
  1585.         aosvs$bsd_gnfn_pkt.nfky     = (short)dir_stream->dd_loc;
  1586.     else
  1587.         aosvs$bsd_gnfn_pkt.nfky     = 0;
  1588.  
  1589.     if (dir_stream->dd_buf)         /* if passed a template */
  1590.         aosvs$bsd_gnfn_pkt.nftp = dir_stream->dd_buf;   /* load it into packet */
  1591.     else
  1592.         aosvs$bsd_gnfn_pkt.nftp   = (char *) -1L;   /* load default flag */
  1593.  
  1594.     aosvs$bsd_gnfn_pkt.nfnm   = dptr->d_name;       /* load buffer ptr */
  1595.     aosvs$ac2.ptr  = &aosvs$bsd_gnfn_pkt;
  1596.     if  (sys($GNFN, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2) == 0)
  1597.     {
  1598.         /* save the AOS/VS internal pointer */
  1599.         dir_stream->dd_loc = (int) aosvs$bsd_gnfn_pkt.nfky;
  1600.  
  1601.         /* load the direct struct values */
  1602.         dptr->d_ino = (long) aosvs$bsd_gnfn_pkt.nfky;   /* fake an inode */
  1603.         dptr->d_reclen = sizeof(struct direct);         /* why? why not? */
  1604.     dptr->d_namlen = strlen(dptr->d_name);          /* handy to have */
  1605.     return(dptr);
  1606.     }
  1607.  
  1608.     free(dptr);
  1609.     return(NULL);    
  1610. }
  1611.  
  1612.  
  1613. /*
  1614.     aosvs$bsd_seekdir
  1615. */
  1616.  
  1617. void seekdir(dir_stream, pos)  /* name$("aosvs$bsd_seekdir") */
  1618.  
  1619. DIR *dir_stream;
  1620. long pos;
  1621.  
  1622. {
  1623.     dir_stream->dd_loc = (short)pos;
  1624. }
  1625.  
  1626.  
  1627. /*
  1628.     aosvs$bsd_telldir
  1629. */
  1630.  
  1631. long telldir(dir_stream)  /* name$("aosvs$bsd_telldir") */
  1632.  
  1633. DIR *dir_stream;
  1634.  
  1635. {
  1636.     return(dir_stream->dd_loc);
  1637. }
  1638.  
  1639.  
  1640. /*
  1641. aosvs$unix_to_aosvs_path.c -- convert a Unix(tm) pathname to a Aos/Vs pathname
  1642.                               We also accept the Ms-Dos '\' seperator and
  1643.                   convert it to the Unix(tm) '/' seperator.  We do
  1644.                   not deal with Ms-Dos device specifiers. The '\'
  1645.                   is handled since most current Ms-Dos C compilers
  1646.                   can deal with either '\' or '/'.
  1647.  
  1648. usage:
  1649.     aosvs$unix_to_aosvs(u_path, a_path);
  1650.  
  1651. where:
  1652. data item name          data type           description
  1653. ----------------------- ------------------  -----------------------------------
  1654. u_path                  char *              char * of Unix(tm) pathname,
  1655.                                             end with null.
  1656. a_path                  char *              char * for Aos/Vs pathname, MUST be
  1657.                                             $MXPL in length.
  1658.  
  1659. -------------------------------------------------------------------------------
  1660. edit history
  1661.  
  1662. who  mm/dd/yy  rev #  what.....................................................
  1663. ---  --------  -----  ---------------------------------------------------------
  1664. dcr  01/27/89  01.00  birth, new life, creation...
  1665. dcr  03/02/89  01.01  cleaned up, added internal temp. storage for path.
  1666. dcr  03/02/89  01.02  added code to deal with Ms-Dog '\' seperator.
  1667. dcr  03/02/89  01.03  added code to skip out if first char is legal Aos/Vs char.
  1668.                       This makes us "just like" _toaos_fid().
  1669. */
  1670. void aosvs$unix_to_aosvs_path(u_path, a_path)
  1671.  
  1672. char *u_path, *a_path;
  1673. {
  1674.  
  1675.     extern int _toaos_fid();        /* Data General library routine */
  1676.  
  1677.     /*
  1678.     local variables
  1679.     */
  1680.     register char *up, *ap;
  1681.     register int dec1;
  1682.     char t_path[$MXPL], octal[4];
  1683.  
  1684.     /*
  1685.     check for null ptrs... no tricks here please...
  1686.     */
  1687.     if ((u_path == NULL) || (a_path == NULL))
  1688.         return;
  1689.  
  1690.     /*
  1691.     copy to register vars.
  1692.     */
  1693.     up = u_path;            /* load ptr to Unix(tm) path */
  1694.     ap = t_path;            /* load ptr to temp. storage area */
  1695.     zero(t_path, $MXPL);    /* zero the temp. storage area */
  1696.             
  1697.     /*
  1698.     to be "just like" DG's _toaos_fid()  we skip out if the first char. is a
  1699.     legal Aos/Vs seperator.  This is from page 2-1 of the "Using Specialized
  1700.     C Functions" manual, DG part number 093-000585-00.
  1701.     */
  1702.     if ((*up == '^') || (*up == '@') || (*up == '=') || (*up == ':')) {
  1703.         strcpy(a_path, u_path);
  1704.     return;
  1705.     }
  1706.  
  1707.     /*
  1708.     step through the unix(tm) pathname and copy or translate bytes into
  1709.     the temp. storage area.
  1710.     */
  1711.     while (*up) {     /* better be NULL terminated!!! */
  1712.         if ((*up == '$') || (*up == '?') || (*up == '\\') || (*up == '_')
  1713.     || ((*up >= '.') && (*up <= ':'))   /* thank you ASCII */
  1714.     || ((*up >= 'A') && (*up <= 'Z'))
  1715.     || ((*up >= 'a') && (*up <= 'z'))) {
  1716.             if (*up == '\\') {   /* convert ms-dos '\' to unix(tm) '/' */
  1717.             *ap++ = '/';
  1718.         up++;
  1719.                 continue;
  1720.             }
  1721.         *ap++ = *up++;
  1722.             continue;
  1723.         }
  1724.  
  1725.         dec1 = 0;
  1726.         zero(octal, 4);
  1727.         *ap++ = '?';            /* marker for octal replacement */
  1728.         dec1 = (int)*up;
  1729.         otoa(dec1, octal);
  1730.         if (dec1 < 64)
  1731.         *ap++ = '0';
  1732.         strcat(ap, octal);
  1733.         if (dec1 >= 64)
  1734.         ap++;
  1735.         ap++;
  1736.     ap++;
  1737.         up++;
  1738.     }
  1739.  
  1740.     *ap = NULL;
  1741.  
  1742.     /*
  1743.     go home...
  1744.     */
  1745.     _toaos_fid(t_path, a_path);
  1746.  
  1747.     return;
  1748. }
  1749.  
  1750. /*
  1751. aosvs$expand_pathname.c
  1752.  
  1753. usage:
  1754.     err = aosvs$expand_pathname(c_path, x_path);
  1755.  
  1756. where:
  1757. data item name          data type           description
  1758. ----------------------- ------------------  -----------------------------------
  1759. err                     int                 Error return, if any.
  1760. c_path                  char *              Current pathname.
  1761. x_path                  char *              Expanded pathname returned here.
  1762.                                             This must be at least $MXPL bytes.
  1763.  
  1764. -------------------------------------------------------------------------------
  1765. edit history
  1766.  
  1767. who  mm/dd/yy  rev #  what.....................................................
  1768. ---  --------  -----  ---------------------------------------------------------
  1769. dcr  03/02/89  01.00  birth, new life, creation...
  1770.  
  1771. */
  1772.  
  1773. /*
  1774. aosvs$expand_pathname.c
  1775.  
  1776. usage:
  1777.     err = aosvs$expand_pathname(c_path, x_path);
  1778.  
  1779. where:
  1780. data item name          data type           description
  1781. ----------------------- ------------------  -----------------------------------
  1782. err                     int                 Error return, if any.
  1783. c_path                  char *              Current pathname.
  1784. x_path                  char *              Expanded pathname returned here.
  1785.                                             This must be at least $MXPL bytes.
  1786.  
  1787. -------------------------------------------------------------------------------
  1788. edit history
  1789.  
  1790. who  mm/dd/yy  rev #  what.....................................................
  1791. ---  --------  -----  ---------------------------------------------------------
  1792. dcr  03/02/89  01.00  birth, new life, creation...
  1793.  
  1794. */
  1795.  
  1796. int aosvs$expand_pathname(c_path, x_path)
  1797.  
  1798. char *c_path, *x_path;
  1799.  
  1800. {
  1801.     /*
  1802.     local variables
  1803.     */
  1804.     char t_path[$MXPL];
  1805.  
  1806.     /*
  1807.     things to do...
  1808.     */
  1809.     zero(t_path, $MXPL);
  1810.     aosvs$unix_to_aosvs_path(c_path, t_path);
  1811.  
  1812.     aosvs$ac2.in = $MXPL;
  1813.     aosvs$ac0.cptr = t_path;
  1814.     aosvs$ac1.cptr = x_path;
  1815.     if (sys($GRNAME, &aosvs$ac0, &aosvs$ac1, &aosvs$ac2))
  1816.         if ((aosvs$ac0.in == ERFDE) || (aosvs$ac0.in == ERFDE))
  1817.             strcpy(x_path, t_path);
  1818.         else
  1819.         return(1);
  1820.  
  1821.     return(0);
  1822. }
  1823.  
  1824. extern DIR        *opendir();
  1825. extern struct direct    *readdir();
  1826. extern long        telldir();
  1827. extern void        seekdir();
  1828. extern void        closedir();
  1829.  
  1830. #define rewinddir( dirp )    seekdir( dirp, 0L )
  1831.  
  1832.  
  1833. /*    FILE Directory routines        */
  1834.  
  1835. char gnfntmp[NFILEN];   /* wildcard template */
  1836. char gnfnpath[NFILEN];    /* path of file to find */
  1837. char gnfnrbuf[NFILEN];    /* return file buffer */
  1838. DIR *gnfndir;
  1839. struct direct *gnfndirect;
  1840.  
  1841. char PASCAL NEAR *getnfile();
  1842.  
  1843. /*  do a template directory search (for file name completion) */
  1844.  
  1845. char *PASCAL NEAR getffile(fspec)
  1846.  
  1847. char *fspec;    /* pattern to match */
  1848.  
  1849. {
  1850.     register int index;        /* index into various strings */
  1851.  
  1852.         /* clean up from our last time in here... */
  1853.         if (gnfndir) {
  1854.         closedir(gnfndir);
  1855.         free(gnfndir);
  1856.         }
  1857.  
  1858.         if (gnfndirect)
  1859.             free(gnfndirect);
  1860.  
  1861.         /* init. some things... */
  1862.         zero(gnfnpath, NFILEN);
  1863.         zero(gnfnrbuf, NFILEN);
  1864.     zero(gnfntmp, NFILEN);
  1865.         gnfndir = NULL;
  1866.         gnfndirect = NULL;
  1867.  
  1868.         /* first parse the file path off the file spec */
  1869.     strcpy(gnfnpath, fspec);
  1870.     index = strlen(gnfnpath) - 1;
  1871.     while (index >= 0 && (gnfnpath[index] != '/' &&
  1872.                 gnfnpath[index] != '\\' && gnfnpath[index] != ':'))
  1873.         --index;
  1874.  
  1875.     gnfnpath[index+1] = 0;
  1876.  
  1877.         if  ((gnfndir = opendir(gnfnpath)) == NULL)
  1878.         return(NULL);
  1879.  
  1880.         /* build the wildcard or template to use in the lookup */
  1881.         strcpy(gnfntmp, &fspec[index+1]);
  1882.         strcat(gnfntmp, "+");
  1883.         gnfndir->dd_buf = gnfntmp;
  1884.  
  1885.         return(getnfile());
  1886. }
  1887.  
  1888. char *PASCAL NEAR getnfile()
  1889.  
  1890. {
  1891.     register int index;        /* index into various strings */
  1892.  
  1893.         zero(gnfnrbuf, NFILEN);         /* init return buffer */
  1894.  
  1895.     /* and call for the next file */
  1896.         if ((gnfndirect = readdir(gnfndir)) == NULL) {
  1897.         closedir(gnfndir);
  1898.             free(gnfndir);
  1899.             gnfndir = NULL;
  1900.             return(NULL);
  1901.         }
  1902.  
  1903.     /* return the next file name! */
  1904.     strcpy(gnfnrbuf, gnfnpath);
  1905.         strcat(gnfnrbuf, gnfndirect->d_name);
  1906.     mklower(gnfnrbuf);
  1907.         free(gnfndirect);
  1908.         gnfndirect = NULL;
  1909.     return(gnfnrbuf);
  1910. }
  1911.  
  1912. FILE *xxfopen(fn, mode)     /* expand a pathname and open it */
  1913.  
  1914. char *fn, *mode;
  1915.  
  1916. {
  1917.     char tmppath[NFILEN];               /* temp. to hold expanded pathname */
  1918.  
  1919.     strcpy(tmppath, fn);                        /* load passed pathname */
  1920.     resolve_full_pathname(tmppath, tmppath);    /* expand it... */
  1921.     return(fopen(tmppath, mode));           /* try to open expanded pathname */
  1922. }
  1923.  
  1924. #endif  /* AOSVS */
  1925.