home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / vim-2.0.lha / Vim-2.0 / src / amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-15  |  29.7 KB  |  1,441 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved
  4.  *
  5.  * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  6.  *                            Tim Thompson            twitch!tjt
  7.  *                            Tony Andrews            onecom!wldrdg!tony 
  8.  *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  9.  */
  10.  
  11. /*
  12.  * amiga.c
  13.  *
  14.  * Amiga system-dependent routines.
  15.  */
  16.  
  17. #include "vim.h"
  18. #include "globals.h"
  19. #include "proto.h"
  20. #include "param.h"
  21.  
  22. #include <fcntl.h>
  23.  
  24. #undef TRUE             /* will be redefined by exec/types.h */
  25. #undef FALSE
  26.  
  27. #ifndef LATTICE
  28. #  include <exec/types.h>
  29. #  include <exec/exec.h>
  30. #  include <libraries/dos.h>
  31. #  include <libraries/dosextens.h>
  32. #  include <intuition/intuition.h>
  33. #else
  34. #  include <proto/dos.h>
  35. #  include <libraries/dosextens.h>
  36. #  include <proto/intuition.h>
  37. #  include <proto/exec.h>
  38. #endif
  39.  
  40. #ifndef NO_ARP
  41. #include <libraries/arpbase.h>        /* for arp.library */
  42. #endif
  43. #include <dos/dostags.h>            /* for 2.0 functions */
  44. #include <dos/dosasl.h>
  45.  
  46. #if defined(LATTICE) && !defined(SASC) && !defined(NO_ARP)
  47. # include <libraries/arp_pragmas.h>
  48. #endif
  49.  
  50. /*
  51.  * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
  52.  */
  53. #undef TRUE
  54. #define TRUE (1)
  55. #undef FALSE
  56. #define FALSE (0)
  57.  
  58. #ifndef AZTEC_C
  59. static long dos_packet __ARGS((struct MsgPort *, long, long));
  60. #endif
  61. static int lock2name __ARGS((BPTR lock, char *buf, long    len));
  62. static struct FileInfoBlock *get_fib __ARGS((char *));
  63. static int sortcmp __ARGS((char **a, char **b));
  64.  
  65. static BPTR                raw_in = (BPTR)NULL;
  66. static BPTR                raw_out = (BPTR)NULL;
  67. static int                close_win = FALSE;    /* set if Vim opened the window */
  68.  
  69. struct IntuitionBase    *IntuitionBase = NULL;
  70. #ifndef NO_ARP
  71. struct ArpBase            *ArpBase = NULL;
  72. #endif
  73.  
  74. static struct Window    *wb_window;
  75. static char                *oldwindowtitle = NULL;
  76.  
  77. #ifndef NO_ARP
  78. int                        dos2 = FALSE;        /* Amiga DOS 2.0x or higher */
  79. #endif
  80. int                        size_set = FALSE;    /* set to TRUE if window size was set */
  81.  
  82.     void
  83. win_resize_on()
  84. {
  85.     outstrn("\033[12{");
  86. }
  87.  
  88.     void
  89. win_resize_off()
  90. {
  91.     outstrn("\033[12}");
  92. }
  93.  
  94.     void
  95. mch_write(p, len)
  96.     char    *p;
  97.     int        len;
  98. {
  99.     Write(raw_out, p, (long)len);
  100. }
  101.  
  102. /*
  103.  * GetChars(): low level input funcion.
  104.  * Get a characters from the keyboard.
  105.  * If time == 0 do not wait for characters.
  106.  * If time == n wait a short time for characters.
  107.  * If time == -1 wait forever for characters.
  108.  */
  109.     int
  110. GetChars(buf, maxlen, time)
  111.     char    *buf;
  112.     int        maxlen;
  113.     int        time;                /* milli seconds */
  114. {
  115.     int        len;
  116.     long    utime;
  117.     
  118.     if (time >= 0)
  119.     {
  120.         if (time == 0)
  121.             utime = 100L;            /* time = 0 causes problems in DOS 1.2 */
  122.         else
  123.             utime = time * 1000L;    /* convert from milli to micro secs */
  124.         if (WaitForChar(raw_in, utime) == 0)    /* no character available */
  125.             return 0;
  126.     }
  127.     else    /* time == -1 */
  128.     {
  129.     /*
  130.      * If there is no character available within 2 seconds (default)
  131.      * write the autoscript file to disk
  132.      */
  133.         if (WaitForChar(raw_in, p_ut * 1000L) == 0)
  134.             updatescript(0);
  135.     }
  136.  
  137.     for (;;)        /* repeat until we got a character */
  138.     {
  139.         len = Read(raw_in, buf, (long)maxlen);
  140.         if (len > 0)
  141.             return len;
  142.     }
  143. }
  144.  
  145.     void
  146. sleep(n)
  147.     int             n;
  148. {
  149. #ifndef LATTICE            /* SAS declares void Delay(UNLONG) */
  150.     void            Delay __ARGS((long));
  151. #endif
  152.  
  153.     if (n > 0)
  154.         Delay((long)(50L * n));
  155. }
  156.  
  157.     void
  158. vim_delay()
  159. {
  160.     Delay(25L);
  161. }
  162.  
  163. /*
  164.  * We have no job control, fake it by starting a new shell.
  165.  */
  166. void
  167. mch_suspend()
  168. {
  169.     outstr("new shell started\n");
  170.     call_shell(NULL, 0, TRUE);
  171. }
  172.  
  173. #define DOS_LIBRARY     ((UBYTE *) "dos.library")
  174.  
  175.     void
  176. mch_windinit()
  177. {
  178.     static char        intlibname[] = "intuition.library";
  179.  
  180. #ifdef AZTEC_C
  181.     Enable_Abort = 0;            /* disallow vim to be aborted */
  182. #endif
  183.     Columns = 80;
  184.     Rows = 24;
  185.  
  186.     /*
  187.      * Set input and output channels, unless we have opened our own window
  188.      */
  189.     if (raw_in == (BPTR)NULL)
  190.     {
  191.         raw_in = Input();
  192.         raw_out = Output();
  193.     }
  194.  
  195.     flushbuf();
  196.  
  197.     wb_window = NULL;
  198.     if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
  199.     {
  200.         fprintf(stderr, "cannot open %s!?\n", intlibname);
  201.         mch_windexit(3);
  202.     }
  203.     mch_get_winsize();
  204. }
  205.  
  206. #include <workbench/startup.h>
  207.  
  208. /*
  209.  * Check_win checks whether we have an interactive window.
  210.  * If not, a new window is opened with the newcli command.
  211.  * If we would open a window ourselves, the :sh and :! commands would not
  212.  * work properly (Why? probably because we are then running in a background CLI).
  213.  * This also is the best way to assure proper working in a next Workbench release.
  214.  *
  215.  * For the -e option (quickfix mode) and -x we open our own window and disable :sh.
  216.  * Otherwise the compiler would never know when editing is finished.
  217.  */
  218. #define BUF2SIZE 320        /* lenght of buffer for argument with complete path */
  219.  
  220.     void
  221. check_win(argc, argv)
  222.     int argc;
  223.     char **argv;
  224. {
  225.     int                i;
  226.     BPTR            nilfh, fh;
  227.     char            buf1[20];
  228.     char            buf2[BUF2SIZE];
  229.     static char        *(constrings[3]) = {"con:0/0/662/210/",
  230.                                       "con:0/0/640/200/",
  231.                                       "con:0/0/320/200/"};
  232.     static char        winerr[] = "VIM: Can't open window!\n";
  233.     struct WBArg    *argp;
  234.     int                ac;
  235.     char            *av;
  236.     char            *device = NULL;
  237.     int                exitval = 4;
  238.     struct Library    *DosBase;
  239.     int                usewin = FALSE;
  240.  
  241. /*
  242.  * check if we are running under DOS 2.0x or higher
  243.  */
  244.     if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
  245.     {
  246.         CloseLibrary(DosBase);
  247. #ifndef NO_ARP
  248.         dos2 = TRUE;
  249. #endif
  250.     }
  251.     else            /* without arp functions we NEED 2.0 */
  252.     {
  253. #ifdef NO_ARP
  254.         fprintf(stderr, "Need Amigados version 2.04 or later\n");
  255.         exit(3);
  256. #else
  257.                     /* need arp functions for dos 1.x */
  258.         if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
  259.         {
  260.             fprintf(stderr, "Need %s version %ld\n", ArpName, ArpVersion);
  261.             exit(3);
  262.         }
  263. #endif
  264.     }
  265.  
  266. /*
  267.  * scan argv[] for the '-e', '-x' and '-d' arguments
  268.  */
  269.     for (i = 1; i < argc; ++i)
  270.         if (argv[i][0] == '-')
  271.         {
  272.             switch (argv[i][1])
  273.             {
  274.             case 'e':
  275.             case 'x':
  276.                 usewin = TRUE;
  277.                 break;
  278.  
  279.             case 'd':
  280.                 if (i < argc - 1)
  281.                     device = argv[i + 1];
  282.                 break;
  283.             }
  284.         }
  285.  
  286. /*
  287.  * If we were not started from workbench, do not have a '-d' argument and
  288.  * we have been started with an interactive window, use that window.
  289.  */
  290.     if (argc != 0 && device == NULL &&
  291.                 IsInteractive(Input()) && IsInteractive(Output()))
  292.         return;
  293.  
  294. /*
  295.  * If we are in quickfix mode, we open our own window. We can't use the
  296.  * newcli trick below, because the compiler would not know when we are finished.
  297.  * We do the same with the '-x' option, for mail, rn, etc.
  298.  */
  299.     if (usewin)
  300.     {
  301.         /*
  302.          * Try to open a window. First try the specified device.
  303.          * Then try a 24 line 80 column window.
  304.          * If that fails, try two smaller ones.
  305.          */
  306.         for (i = -1; i < 3; ++i)
  307.         {
  308.             if (i >= 0)
  309.                 device = constrings[i];
  310.             if (device && (raw_in = Open((UBYTE *)device, (long)MODE_NEWFILE)) != (BPTR)NULL)
  311.                 break;
  312.         }
  313.         if (raw_in == (BPTR)NULL)        /* all three failed */
  314.         {
  315.             fprintf(stderr, winerr);
  316.             goto exit;
  317.         }
  318.         raw_out = raw_in;
  319.         close_win = TRUE;
  320.         return;
  321.     }
  322.  
  323.     if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
  324.     {
  325.         fprintf(stderr, "Cannot open NIL:\n");
  326.         goto exit;
  327.     }
  328.  
  329.     /*
  330.      * make a unique name for the temp file (which we will not delete!)
  331.      */
  332.     sprintf(buf1, "t:nc%ld", buf1);    /* nobody else is using our stack */
  333.     if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
  334.     {
  335.         fprintf(stderr, "Cannot create %s\n", buf1);
  336.         goto exit;
  337.     }
  338.     /*
  339.      * Write the command into the file, put quotes around the arguments that
  340.      * have a space in them.
  341.      */
  342.     if (argc == 0)        /* run from workbench */
  343.         ac = ((struct WBStartup *)argv)->sm_NumArgs;
  344.     else
  345.         ac = argc;
  346.     for (i = 0; i < ac; ++i)
  347.     {
  348.         if (argc == 0)
  349.         {
  350.             *buf2 = NUL;
  351.             argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
  352.             if (argp->wa_Lock)
  353.                 lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
  354. #ifndef NO_ARP
  355.             if (dos2)        /* use 2.0 function */
  356. #endif
  357.                 AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
  358. #ifndef NO_ARP
  359.             else            /* use arp function */
  360.                 TackOn(buf2, argp->wa_Name);
  361. #endif
  362.             av = buf2;
  363.         }
  364.         else
  365.             av = argv[i];
  366.  
  367.         if (av[0] == '-' && av[1] == 'd')        /* skip '-d' option */
  368.         {
  369.             ++i;
  370.             continue;
  371.         }
  372.         if (strchr(av, ' '))
  373.             Write(fh, "\"", 1L);
  374.         Write(fh, av, (long)strlen(av));
  375.         if (strchr(av, ' '))
  376.             Write(fh, "\"", 1L);
  377.         Write(fh, " ", 1L);
  378.     }
  379.     Write(fh, "\nendcli\n", 8L);
  380.     Close(fh);
  381.  
  382. /*
  383.  * Try to open a new cli in a window. If '-d' argument was given try to open
  384.  * the specified device. Then try a 24 line 80 column window.
  385.  * If that fails, try two smaller ones.
  386.  */
  387.     for (i = -1; i < 3; ++i)
  388.     {
  389.         if (i >= 0)
  390.             device = constrings[i];
  391.         else if (device == NULL)
  392.             continue;
  393.         sprintf(buf2, "newcli <nil: >nil: %s from %s", device, buf1);
  394. #ifndef NO_ARP
  395.         if (dos2)
  396.         {
  397. #endif
  398.             if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
  399.                 break;
  400. #ifndef NO_ARP
  401.         }
  402.         else
  403.         {
  404.             if (Execute((UBYTE *)buf2, nilfh, nilfh))
  405.                 break;
  406.         }
  407. #endif
  408.     }
  409.     if (i == 3)        /* all three failed */
  410.     {
  411.         DeleteFile((UBYTE *)buf1);
  412.         fprintf(stderr, winerr);
  413.         goto exit;
  414.     }
  415.     exitval = 0;    /* The Execute succeeded: exit this program */
  416.  
  417. exit:
  418. #ifndef NO_ARP
  419.     if (ArpBase)
  420.         CloseLibrary((struct Library *) ArpBase);
  421. #endif
  422.     exit(exitval);
  423. }
  424.  
  425. /*
  426.  * fname_case(): Set the case of the filename, if it already exists.
  427.  *                 This will cause the filename to remain exactly the same.
  428.  */
  429.     void
  430. fname_case(name)
  431.     char *name;
  432. {
  433.     register struct FileInfoBlock    *fib;
  434.     register size_t                    len;
  435.  
  436.     fib = get_fib(name);
  437.     if (fib != NULL)
  438.     {
  439.         len = strlen(name);
  440.         if (len == strlen(fib->fib_FileName))    /* safety check */
  441.             memmove(name, fib->fib_FileName, len);
  442.         free(fib);
  443.     }
  444. }
  445.  
  446. /*
  447.  * Get the FileInfoBlock for file "fname"
  448.  * The returned structure has to be free()d.
  449.  * Returns NULL on error.
  450.  */
  451.     static struct FileInfoBlock *
  452. get_fib(fname)
  453.     char *fname;
  454. {
  455.     register BPTR                    flock;
  456.     register struct FileInfoBlock    *fib;
  457.  
  458.     if (fname == NULL)        /* safety check */
  459.         return NULL;
  460.     fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
  461.     if (fib != NULL)
  462.     {
  463.         flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
  464.         if (flock == (BPTR)NULL || !Examine(flock, fib))
  465.         {
  466.             free(fib);    /* in case of an error the memory is freed here */
  467.             fib = NULL;
  468.         }
  469.         if (flock)
  470.             UnLock(flock);
  471.     }
  472.     return fib;
  473. }
  474.  
  475. /*
  476.  * settitle(): set titlebar of our window
  477.  */
  478. static char *lasttitle = NULL;
  479.  
  480.     void
  481. settitle(str)
  482.     char *str;
  483. {
  484.  
  485.     if (wb_window != NULL)
  486.     {
  487.         free(lasttitle);
  488.         lasttitle = alloc((unsigned)(strlen(str) + 7));
  489.         if (lasttitle != NULL)
  490.         {
  491.             sprintf(lasttitle, "VIM - %s", str);
  492.             SetWindowTitles(wb_window, (UBYTE *)lasttitle, (UBYTE *)-1L);
  493.         }
  494.     }
  495. }
  496.  
  497.     void
  498. resettitle()
  499. {
  500.         if (wb_window != NULL && lasttitle != NULL)
  501.                 SetWindowTitles(wb_window, (UBYTE *)lasttitle, (UBYTE *)-1L);
  502. }
  503.  
  504. /*
  505.  * Get name of current directory into buffer 'buf' of length 'len' bytes.
  506.  * Return non-zero for success.
  507.  */
  508. dirname(buf, len)
  509.     char        *buf;
  510.     int            len;
  511. {
  512.     return FullName("", buf, len);
  513. }
  514.  
  515. /*
  516.  * get absolute filename into buffer 'buf' of length 'len' bytes
  517.  */
  518. FullName(fname, buf, len)
  519.     char        *fname, *buf;
  520.     int            len;
  521. {
  522.     BPTR        l;
  523.     int            retval = 0;
  524.  
  525.     if (fname == NULL)    /* always fail */
  526.         return 0;
  527.  
  528.     if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)))/* lock the file */
  529.     {
  530.         retval = lock2name(l, buf, (long)len);
  531.         UnLock(l);
  532.     }
  533.     if (retval == 0 || *buf == 0 || *buf == ':')
  534.         strcpy(buf, fname);            /* something failed; use the filename */
  535.     return retval;
  536. }
  537.  
  538. /*
  539.  * Get the full filename from a lock. Use 2.0 function if possible, because
  540.  * the arp function has more restrictions on the path length.
  541.  */
  542.     static int
  543. lock2name(lock, buf, len)
  544.     BPTR    lock;
  545.     char    *buf;
  546.     long    len;
  547. {
  548. #ifndef NO_ARP
  549.     if (dos2)                /* use 2.0 function */
  550. #endif
  551.         return (int)NameFromLock(lock, (UBYTE *)buf, len);
  552. #ifndef NO_ARP
  553.     else                /* use arp function */
  554.         return (int)PathName(lock, buf, (long)(len/32));
  555. #endif
  556. }
  557.  
  558. /*
  559.  * get file permissions for 'name'
  560.  */
  561.     long
  562. getperm(name)
  563.     char        *name;
  564. {
  565.     struct FileInfoBlock    *fib;
  566.     long                     retval = -1;
  567.  
  568.     fib = get_fib(name);
  569.     if (fib != NULL)
  570.     {
  571.         retval = fib->fib_Protection;
  572.         free(fib);
  573.     }
  574.     return retval;
  575. }
  576.  
  577. /*
  578.  * set file permission for 'name' to 'perm'
  579.  */
  580. setperm(name, perm)
  581.     char        *name;
  582.     long        perm;
  583. {
  584.     perm &= ~FIBF_ARCHIVE;                /* reset archived bit */
  585.     return (int)SetProtection((UBYTE *)name, (long)perm);
  586. }
  587.  
  588. /*
  589.  * check if "name" is a directory
  590.  */
  591. isdir(name)
  592.     char        *name;
  593. {
  594.     struct FileInfoBlock    *fib;
  595.     int                     retval = -1;
  596.  
  597.     fib = get_fib(name);
  598.     if (fib != NULL)
  599.     {
  600.         retval = (fib->fib_DirEntryType >= 0);
  601.         free(fib);
  602.     }
  603.     return retval;
  604. }
  605.  
  606. /*
  607.  * Careful: mch_windexit() may be called before mch_windinit()!
  608.  */
  609.     void
  610. mch_windexit(r)
  611.     int             r;
  612. {
  613.     if (raw_in)                        /* put terminal in 'normal' mode */
  614.     {
  615.         settmode(0);
  616.         stoptermcap();
  617.     }
  618.     if (raw_out)
  619.     {
  620.         if (term_console)
  621.         {
  622.             win_resize_off();        /* window resize events de-activated */
  623.             if (size_set)
  624.                 outstr("\233t\233u");        /* reset window size (CSI t CSI u) */
  625.         }
  626.         flushbuf();
  627.     }
  628.  
  629.     if (wb_window != NULL)            /* disable window title */
  630.         SetWindowTitles(wb_window, (UBYTE *)oldwindowtitle, (UBYTE *)-1L);
  631.     stopscript();                    /* remove autoscript file */
  632. #ifndef NO_ARP
  633.     if (ArpBase)
  634.         CloseLibrary((struct Library *) ArpBase);
  635. #endif
  636.     if (close_win)
  637.         Close(raw_in);
  638.     if (r)
  639.         printf("Vim exiting with %d\n", r);    /* somehow this makes :cq work!? */
  640.     exit(r);
  641. }
  642.  
  643. /*
  644.  * This is a routine for setting a given stream to raw or cooked mode on the
  645.  * Amiga . This is useful when you are using Lattice C to produce programs
  646.  * that want to read single characters with the "getch()" or "fgetc" call.
  647.  *
  648.  * Written : 18-Jun-87 By Chuck McManis.
  649.  */
  650.  
  651. #define MP(xx)    ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
  652.  
  653. /*
  654.  * Function mch_settmode() - Convert the specified file pointer to 'raw' or 'cooked'
  655.  * mode. This only works on TTY's.
  656.  *
  657.  * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
  658.  *        getch() will return immediately rather than wait for a return. You
  659.  *        lose editing features though.
  660.  *
  661.  * Cooked: This function returns the designate file pointer to it's normal,
  662.  *        wait for a <CR> mode. This is exactly like raw() except that
  663.  *        it sends a 0 to the console to make it back into a CON: from a RAW:
  664.  */
  665.     void
  666. mch_settmode(raw)
  667.     int            raw;
  668. {
  669.     if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE, raw ? -1L : 0L) == 0)
  670.         fprintf(stderr, "cannot change console mode ?!\n");
  671. }
  672.  
  673. /*
  674.  * Code for this routine came from the following :
  675.  *
  676.  * ConPackets.c -  C. Scheppner, A. Finkel, P. Lindsay    CBM
  677.  *     DOS packet example
  678.  *     Requires 1.2
  679.  *
  680.  * Found on Fish Disk 56.
  681.  *
  682.  * Heavely modified by mool.
  683.  */
  684.  
  685. #include <devices/conunit.h>
  686.  
  687. /*
  688.  * try to get the real window size
  689.  * return non-zero for failure
  690.  */
  691.     int
  692. mch_get_winsize()
  693. {
  694.     struct ConUnit    *conUnit;
  695.      char            id_a[sizeof(struct InfoData) + 3];
  696.     struct InfoData *id;
  697.  
  698.     if (!term_console)    /* not an amiga window */
  699.         return 1;
  700.  
  701.     /* insure longword alignment */
  702.      id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  703.  
  704.     /*
  705.      * Should make console aware of real window size, not the one we set.
  706.      * Unfortunately, under DOS 2.0x this redraws the window and it
  707.      * is rarely needed, so we skip it now, unless we changed the size.
  708.      */
  709.     if (size_set)
  710.         outstr("\233t\233u");    /* CSI t CSI u */
  711.     flushbuf();
  712.  
  713.     if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0 ||
  714.                 (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
  715.     {
  716.         /* it's not an amiga window, maybe aux device */
  717.         /* terminal type should be set */
  718.         term_console = FALSE;
  719.         return 1;
  720.     }
  721.     if (oldwindowtitle == NULL)
  722.         oldwindowtitle = (char *)wb_window->Title;
  723.     if (id->id_InUse == (BPTR)NULL)
  724.     {
  725.         fprintf(stderr, "mch_get_winsize: not a console??\n");
  726.         return (2);
  727.     }
  728.     conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
  729.  
  730.     /* get window size */
  731.     Rows = conUnit->cu_YMax + 1;
  732.     Columns = conUnit->cu_XMax + 1;
  733.     if (Rows < 0 || Rows > 200)     /* cannot be an amiga window */
  734.     {
  735.         Columns = 80;
  736.         Rows = 24;
  737.         term_console = FALSE;
  738.         return 1;
  739.     }
  740.     Rows_max = Rows;                /* remember physical max height */
  741.  
  742.     check_winsize();
  743.     script_winsize();
  744.  
  745.     return 0;
  746. }
  747.  
  748. /*
  749.  * try to set the real window size
  750.  */
  751.     void
  752. mch_set_winsize()
  753. {
  754.     if (term_console)
  755.     {
  756.         size_set = TRUE;
  757.         outchar(CSI);
  758.         outnum((long)Rows);
  759.         outchar('t');
  760.         outchar(CSI);
  761.         outnum((long)Columns);
  762.         outchar('u');
  763.         flushbuf();
  764.     }
  765. }
  766.  
  767. #ifdef SETKEYMAP
  768. /*
  769.  * load and activate a new keymap for our CLI - DOES NOT WORK -
  770.  * The problem is that after the setting of the keymap the input blocks
  771.  * But the new keymap works allright in another window.
  772.  * Tried but no improvement:
  773.  * - remembering the length, data and command fields in request->io_xxx
  774.  * - settmode(0) first, settmode(1) afterwards
  775.  * - putting the keymap directly in conunit structure
  776.  */
  777.  
  778. #include <devices/keymap.h>
  779.  
  780.     void
  781. set_keymap(name)
  782.     char *name;
  783. {
  784.      char                    id_a[sizeof(struct InfoData) + 3];
  785.     struct InfoData            *id;
  786.     static struct KeyMap    *old;
  787.     static BPTR                segment = (BPTR)NULL;
  788.     struct IOStdReq            *request;
  789.     int                        c;
  790.  
  791.     if (!term_console)
  792.         return;
  793.  
  794.     /* insure longword alignment */
  795.      id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
  796.  
  797.     if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0)
  798.     {
  799.         emsg("dos_packet failed");
  800.         return;
  801.     }
  802.     if (id->id_InUse == (BPTR)NULL)
  803.     {
  804.         emsg("not a console??");
  805.         return;
  806.     }
  807.     request = (struct IOStdReq *) id->id_InUse;
  808.  
  809.     if (segment != (BPTR)NULL)    /* restore old keymap */
  810.     {
  811.         request->io_Command = CD_SETKEYMAP;
  812.         request->io_Length = sizeof(struct KeyMap);
  813.         request->io_Data = (APTR)old;
  814.         DoIO((struct IORequest *)request);
  815.         if (request->io_Error)
  816.             emsg("Cannot reset keymap");
  817.         else                /* no error, free the allocated memory */
  818.         {
  819.             UnLoadSeg(segment);
  820.             FreeMem(old, sizeof(struct KeyMap));
  821.             segment = (BPTR)NULL;
  822.         }
  823.     }
  824.     if (name != NULL)
  825.     {
  826.         segment = LoadSeg(name);
  827.         if (segment == (BPTR)NULL)
  828.         {
  829.             emsg("Cannot open keymap file");
  830.             return;
  831.         }
  832.         old = (struct KeyMap *)AllocMem(sizeof(struct KeyMap), MEMF_PUBLIC);
  833.         if (old == NULL)
  834.         {
  835.             emsg(e_outofmem);
  836.             UnLoadSeg(segment);
  837.             segment = (BPTR)NULL;
  838.         }
  839.         else
  840.         {
  841.             request->io_Command = CD_ASKKEYMAP;
  842.             request->io_Length = sizeof(struct KeyMap);
  843.             request->io_Data = (APTR)old;
  844.             DoIO((struct IORequest *)request);
  845.             if (request->io_Error)
  846.             {
  847.                 emsg("Cannot get old keymap");
  848.                 UnLoadSeg(segment);
  849.                 segment = (BPTR)NULL;
  850.                 FreeMem(old, sizeof(struct KeyMap));
  851.             }
  852.             else
  853.             {
  854.                 request->io_Command = CD_SETKEYMAP;
  855.                 request->io_Length = sizeof(struct KeyMap);
  856.                 request->io_Data = (APTR)((segment << 2) + 18);
  857.                 DoIO((struct IORequest *)request);
  858.                 if (request->io_Error)
  859.                     emsg("Cannot set keymap");
  860.  
  861.                 /* test for blocking */
  862.                 request->io_Command = CMD_READ;
  863.                 request->io_Length = 1;
  864.                 request->io_Data = (APTR)&c;
  865.                 DoIO((struct IORequest *)request);    /* BLOCK HERE! */
  866.                 if (request->io_Error)
  867.                     emsg("Cannot set keymap");
  868.             }
  869.         }
  870.     }
  871. }
  872. #endif
  873.  
  874. #ifndef AZTEC_C
  875. /*
  876.  * Sendpacket.c
  877.  *
  878.  * An invaluable addition to your Amiga.lib file. This code sends a packet to
  879.  * the given message port. This makes working around DOS lots easier.
  880.  *
  881.  * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
  882.  * however that you may wish to add it to Amiga.Lib, to do so, compile it and
  883.  * say 'oml lib:amiga.lib -r sendpacket.o'
  884.  */
  885.  
  886. /* #include <proto/exec.h> */
  887. /* #include <proto/dos.h> */
  888. #include <exec/memory.h>
  889.  
  890. /*
  891.  * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
  892.  * Finkel. This function will send a packet of the given type to the Message
  893.  * Port supplied.
  894.  */
  895.  
  896.     static long
  897. dos_packet(pid, action, arg)
  898.     struct MsgPort *pid;    /* process indentifier ... (handlers message port) */
  899.     long            action, /* packet type ... (what you want handler to do)   */
  900.                     arg;    /* single argument */
  901. {
  902. # ifndef NO_ARP
  903.     struct MsgPort            *replyport;
  904.     struct StandardPacket    *packet;
  905.     long                    res1;
  906.  
  907.     if (dos2)
  908. # endif
  909.         return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L);    /* use 2.0 function */
  910. # ifndef NO_ARP
  911.  
  912.     replyport = (struct MsgPort *) CreatePort(NULL, 0);    /* use arp function */
  913.     if (!replyport)
  914.         return (0);
  915.  
  916.     /* Allocate space for a packet, make it public and clear it */
  917.     packet = (struct StandardPacket *)
  918.         AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
  919.     if (!packet) {
  920.         DeletePort(replyport);
  921.         return (0);
  922.     }
  923.     packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
  924.     packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  925.     packet->sp_Pkt.dp_Port = replyport;
  926.     packet->sp_Pkt.dp_Type = action;
  927.     packet->sp_Pkt.dp_Arg1 = arg;
  928.  
  929.     PutMsg(pid, (struct Message *)packet);        /* send packet */
  930.  
  931.     WaitPort(replyport);
  932.     GetMsg(replyport);
  933.  
  934.     res1 = packet->sp_Pkt.dp_Res1;
  935.  
  936.     FreeMem(packet, (long) sizeof(struct StandardPacket));
  937.     DeletePort(replyport);
  938.  
  939.     return (res1);
  940. # endif
  941. }
  942. #endif
  943.  
  944. /*
  945.  * call shell, return non-zero for failure
  946.  */
  947.     int
  948. call_shell(cmd, filter, cooked)
  949.         char    *cmd;
  950.         int        filter;        /* if != 0: called by dofilter() */
  951.         int        cooked;
  952. {
  953.     BPTR mydir;
  954.     int x;
  955. #ifndef LATTICE
  956.     int    use_execute;
  957.     char *shellcmd = NULL;
  958.     char *shellarg;
  959. #endif
  960.     int    retval = 0;
  961.  
  962.     if (close_win)
  963.     {
  964.         /* if Vim opened a window: Executing a shell may cause crashes */
  965.         emsg("Cannot execute shell with -e or -x option");
  966.         return 1;
  967.     }
  968.  
  969.     if (term_console)
  970.         win_resize_off();             /* window resize events de-activated */
  971.     flushbuf();
  972.  
  973.     if (cooked)
  974.         settmode(0);                 /* set to cooked mode */
  975.     mydir = Lock((UBYTE *)"", (long)ACCESS_READ);    /* remember current directory */
  976.  
  977. #ifdef LATTICE                        /* not tested very much */
  978.     if (cmd == NULL)
  979.     {
  980. # ifndef NO_ARP
  981.         if (dos2)
  982. # endif
  983.             x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
  984. # ifndef NO_ARP
  985.         else
  986.             x = Execute(p_sh, raw_in, raw_out);
  987. # endif
  988.     }
  989.     else
  990.     {
  991. # ifndef NO_ARP
  992.         if (dos2)
  993. # endif
  994.             x = SystemTags(cmd, SYS_UserShell, TRUE, TAG_DONE);
  995. # ifndef NO_ARP
  996.         else
  997.             x = Execute(cmd, 0L, raw_out);
  998. # endif
  999.     }
  1000. # ifdef NO_ARP
  1001.     if (x < 0)
  1002. # else
  1003.     if ((dos2 && x < 0) || (!dos2 && !x))
  1004. # endif
  1005.     {
  1006.         if (cmd == NULL)
  1007.             emsg2("Cannot execute shell %s", p_sh);
  1008.         else
  1009.             emsg2("Cannot execute %s", cmd);
  1010.         outchar('\n');
  1011.         retval = 1;
  1012.     }
  1013. # ifdef NO_ARP
  1014.     else if (x)
  1015. # else
  1016.     else if (!dos2 || x)
  1017. # endif
  1018.     {
  1019.         if (x = IoErr())
  1020.         {
  1021.             smsg("%d returned", x);
  1022.             outchar('\n');
  1023.             retval = 1;
  1024.         }
  1025.     }
  1026. #else    /* LATTICE */
  1027.     if (p_st >= 4 || (p_st >= 2 && !filter))
  1028.         use_execute = 1;
  1029.     else
  1030.         use_execute = 0;
  1031.     if (!use_execute)
  1032.     {
  1033.         /*
  1034.          * separate shell name from argument
  1035.          */
  1036.         shellcmd = strsave(p_sh);
  1037.         if (shellcmd == NULL)        /* out of memory, use Execute */
  1038.             use_execute = 1;
  1039.         else
  1040.         {
  1041.             shellarg = shellcmd;
  1042.             skiptospace(&shellarg);    /* find start of arguments */
  1043.             if (*shellarg != NUL)
  1044.             {
  1045.                 *shellarg++ = NUL;
  1046.                 skipspace(&shellarg);
  1047.             }
  1048.         }
  1049.     }
  1050.     if (cmd == NULL)
  1051.     {
  1052.         if (use_execute)
  1053.         {
  1054. #ifndef NO_ARP
  1055.             if (dos2)
  1056. #endif
  1057.                 x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
  1058. #ifndef NO_ARP
  1059.             else
  1060.                 x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
  1061. #endif
  1062.         }
  1063.         else
  1064.             x = fexecl(shellcmd, shellcmd, shellarg, NULL);
  1065.     }
  1066.     else if (use_execute)
  1067.     {
  1068. #ifndef NO_ARP
  1069.         if (dos2)
  1070. #endif
  1071.             x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
  1072. #ifndef NO_ARP
  1073.         else
  1074.             x = !Execute((UBYTE *)cmd, 0L, raw_out);
  1075. #endif
  1076.     }
  1077.     else if (p_st & 1)
  1078.         x = fexecl(shellcmd, shellcmd, shellarg, cmd, NULL);
  1079.     else
  1080.         x = fexecl(shellcmd, shellcmd, shellarg, "-c", cmd, NULL);
  1081. #ifdef NO_ARP
  1082.     if (x < 0)
  1083. #else
  1084.     if ((dos2 && x < 0) || (!dos2 && x))
  1085. #endif
  1086.     {
  1087.         if (use_execute)
  1088.             emsg2("Cannot execute %s", cmd == NULL ? p_sh : cmd);
  1089.         else
  1090.             emsg2("Cannot execute shell %s", shellcmd);
  1091.         outchar('\n');
  1092.         retval = 1;
  1093.     }
  1094.     else
  1095.     {
  1096.         if (use_execute)
  1097.         {
  1098. #ifdef NO_ARP
  1099.             if (x)
  1100. #else
  1101.             if (!dos2 || x)
  1102. #endif
  1103.                 x = IoErr();
  1104.         }
  1105.         else
  1106.             x = wait();
  1107.         if (x)
  1108.         {
  1109.             smsg("%d returned", x);
  1110.             outchar('\n');
  1111.             retval = 1;
  1112.         }
  1113.     }
  1114.     free(shellcmd);
  1115. #endif
  1116.  
  1117.     if (mydir = CurrentDir(mydir))        /* make sure we stay in the same directory */
  1118.         UnLock(mydir);
  1119.     if (cooked)
  1120.         settmode(1);                     /* set to raw mode */
  1121.     resettitle();
  1122.     if (term_console)
  1123.         win_resize_on();                 /* window resize events activated */
  1124.     return retval;
  1125. }
  1126.  
  1127. /*
  1128.  * check for an "interrupt signal"
  1129.  * We only react to a CTRL-C, but also clear the other break signals to avoid trouble
  1130.  * with lattice-c programs.
  1131.  */
  1132.     void
  1133. breakcheck()
  1134. {
  1135.    if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
  1136.         got_int = TRUE;
  1137. }
  1138.  
  1139. /* this routine causes manx to use this Chk_Abort() rather than it's own */
  1140. /* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
  1141. /* is zero).  Since we want to check for our own ^C's                    */
  1142.  
  1143. #ifdef _DCC
  1144. #define Chk_Abort chkabort
  1145. #endif
  1146.  
  1147.     long
  1148. Chk_Abort()
  1149. {
  1150.     return(0L);
  1151. }
  1152.  
  1153. /*
  1154.  * ExpandWildCard() - this code does wild-card pattern matching using the arp
  1155.  *                      routines. This is based on WildDemo2.c (found in arp1.1
  1156.  *                      distribution). That code's copyright follows :
  1157.  *-------------------------------------------------------------------------
  1158.  * WildDemo2.c - Search filesystem for patterns, and separate into directories
  1159.  *         and files, sorting each separately using DA lists.
  1160.  *
  1161.  * -+=SDB=+-
  1162.  *
  1163.  * Copyright (c) 1987, Scott Ballantyne
  1164.  * Use and abuse as you please.
  1165.  *
  1166.  * num_pat is number of input patterns
  1167.  * pat is array of pointers to input patterns
  1168.  * num_file is pointer to number of matched file names
  1169.  * file is pointer to array of pointers to matched file names
  1170.  * if file_only is TRUE we match only files, no dirs
  1171.  * if list_notfound is TRUE we include not-found entries (probably locked)
  1172.  * return 0 for success, 1 for error (you may loose some memory)
  1173.  *-------------------------------------------------------------------------
  1174.  */
  1175.  
  1176. /* #include <arpfunctions.h> */
  1177. extern void *malloc __ARGS((size_t)), *calloc __ARGS((size_t, size_t));
  1178. static int insfile __ARGS((char *, int));
  1179. static void freefiles __ARGS((void));
  1180.  
  1181. #define ANCHOR_BUF_SIZE (512)
  1182. #define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
  1183.  
  1184. /*
  1185.  * we use this structure to built a list of file names
  1186.  */
  1187. struct onefile
  1188. {
  1189.     struct onefile    *next;
  1190.     char            name[1];    /* really longer */
  1191. } *namelist = NULL;
  1192.  
  1193. /*
  1194.  * insert one file into the list of file names
  1195.  * return -1 for failure
  1196.  * return 0 for success
  1197.  */
  1198.     static int
  1199. insfile(name, isdir)
  1200.     char    *name;
  1201.     int        isdir;
  1202. {
  1203.     struct onefile *new;
  1204.  
  1205.     new = (struct onefile *)alloc((unsigned)(sizeof(struct onefile) + strlen(name) + isdir));
  1206.     if (new == NULL)
  1207.         return -1;
  1208.     strcpy(&(new->name[0]), name);
  1209.     if (isdir)
  1210.         strcat(&(new->name[0]), "/");
  1211.     new->next = namelist;
  1212.     namelist = new;
  1213.     return 0;
  1214. }
  1215.  
  1216. /*
  1217.  * free a whole list of file names
  1218.  */
  1219.     static void
  1220. freefiles()
  1221. {
  1222.     struct onefile *p;
  1223.  
  1224.     while (namelist)
  1225.     {
  1226.         p = namelist->next;
  1227.         free(namelist);
  1228.         namelist = p;
  1229.     }
  1230. }
  1231.  
  1232.     static int
  1233. sortcmp(a, b)
  1234.     char **a, **b;
  1235. {
  1236.     return strcmp(*a, *b);
  1237. }
  1238.  
  1239. ExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
  1240.     int             num_pat;
  1241.     char          **pat;
  1242.     int            *num_file;
  1243.     char         ***file;
  1244.     int            files_only;
  1245.     int            list_notfound;
  1246. {
  1247.     int                     i;
  1248.     struct AnchorPath        *Anchor;
  1249.     int                        domatchend = FALSE;
  1250.     LONG                    Result;
  1251.     struct onefile            *p;
  1252.     char                    *errmsg = NULL;
  1253.     char                    *starbuf, *sp, *dp;
  1254.     int                        foundone;
  1255.  
  1256.     *num_file = 0;
  1257.     *file = (char **)"";
  1258.  
  1259.     /* Get our AnchorBase */
  1260.     Anchor = (struct AnchorPath *) calloc((size_t)1, (size_t)ANCHOR_SIZE);
  1261.     if (!Anchor)
  1262.         goto OUT_OF_MEMORY;
  1263.     Anchor->ap_StrLen = ANCHOR_BUF_SIZE;    /* ap_Length not supported anymore */
  1264. #ifdef APF_DODOT
  1265.     Anchor->ap_Flags = APF_DODOT | APF_DOWILD;        /* allow '.' for current dir */
  1266. #else
  1267.     Anchor->ap_Flags = APF_DoDot | APF_DoWild;        /* allow '.' for current dir */
  1268. #endif
  1269.  
  1270.     for (i = 0; i < num_pat; i++)
  1271.     {
  1272. #ifndef NO_ARP
  1273.         if (dos2)
  1274.         {
  1275. #endif
  1276.                 /* hack to replace '*' by '#?' */
  1277.             starbuf = alloc((unsigned)(2 * strlen(pat[i]) + 1));    /* maximum required */
  1278.             if (starbuf == NULL)
  1279.                 goto OUT_OF_MEMORY;
  1280.             for (sp = pat[i], dp = starbuf; *sp; ++sp)
  1281.             {
  1282.                 if (*sp == '*')
  1283.                 {
  1284.                     *dp++ = '#';
  1285.                     *dp++ = '?';
  1286.                 }
  1287.                 else
  1288.                     *dp++ = *sp;
  1289.             }
  1290.             *dp = NUL;
  1291.             Result = MatchFirst((UBYTE *)starbuf, Anchor);
  1292.             free(starbuf);
  1293. #ifndef NO_ARP
  1294.         }
  1295.         else
  1296.             Result = FindFirst(pat[i], Anchor);
  1297. #endif
  1298.         domatchend = TRUE;
  1299.         foundone = FALSE;
  1300.         while (Result == 0)
  1301.         {
  1302.             if (!files_only || Anchor->ap_Info.fib_DirEntryType < 0)
  1303.             {
  1304.                 (*num_file)++;
  1305.                 if (insfile(Anchor->ap_Buf, Anchor->ap_Info.fib_DirEntryType >= 0))
  1306.                 {
  1307. OUT_OF_MEMORY:
  1308.                     errmsg = "Out of memory";
  1309.                     goto Return;
  1310.                 }
  1311.                 foundone = TRUE;
  1312.             }
  1313. #ifndef NO_ARP
  1314.             if (dos2)
  1315. #endif
  1316.                 Result = MatchNext(Anchor);
  1317. #ifndef NO_ARP
  1318.             else
  1319.                 Result = FindNext(Anchor);
  1320. #endif
  1321.         }
  1322.         if (Result == ERROR_BUFFER_OVERFLOW)
  1323.         {
  1324.             errmsg = "ANCHOR_BUF_SIZE too small.";
  1325.             goto Return;
  1326.         }
  1327.         if (!foundone)
  1328.         {
  1329.             if (list_notfound)    /* put object with error in list */
  1330.             {
  1331.                 (*num_file)++;
  1332.                 if (insfile(pat[i], FALSE))
  1333.                     goto OUT_OF_MEMORY;
  1334.             }
  1335.             else if (Result != ERROR_OBJECT_NOT_FOUND && Result != ERROR_NO_MORE_ENTRIES)
  1336.             {
  1337.                 errmsg = "I/O ERROR";
  1338.                 goto Return;
  1339.             }
  1340.         }
  1341. #ifndef NO_ARP
  1342.         if (dos2)
  1343. #endif
  1344.             MatchEnd(Anchor);
  1345. #ifndef NO_ARP
  1346.         else
  1347.         {
  1348.             FreeAnchorChain(Anchor);
  1349.             Anchor = NULL;            /* is this right or wrong? */
  1350.         }
  1351. #endif
  1352.         domatchend = FALSE;
  1353.     }
  1354.  
  1355.     p = namelist;
  1356.     if (p)
  1357.     {
  1358.         *file = (char **) malloc(sizeof(char *) * (*num_file));
  1359.         if (*file == NULL)
  1360.             goto OUT_OF_MEMORY;
  1361.         for (i = *num_file - 1; p; p = p->next, --i)
  1362.         {
  1363.             (*file)[i] = (char *) malloc(strlen(p->name) + 1);
  1364.             if ((*file)[i] == NULL)
  1365.                 goto OUT_OF_MEMORY;
  1366.             strcpy((*file)[i], p->name);
  1367.         }
  1368.         qsort((void *)*file, (size_t)*num_file, sizeof(char *), sortcmp);
  1369.     }
  1370. Return:
  1371.     if (domatchend)
  1372.     {
  1373. #ifndef NO_ARP
  1374.         if (dos2)
  1375. #endif
  1376.             MatchEnd(Anchor);
  1377. #ifndef NO_ARP
  1378.         else
  1379.         {
  1380.             FreeAnchorChain(Anchor);
  1381.             Anchor = NULL;            /* is this right or wrong? */
  1382.         }
  1383. #endif
  1384.     }
  1385.     if (Anchor)
  1386.         free(Anchor);
  1387.     freefiles();
  1388.     if (errmsg)
  1389.     {
  1390.         emsg(errmsg);
  1391.         *num_file = 0;
  1392.         return 1;
  1393.     }
  1394.     return 0;
  1395. }
  1396.  
  1397.     void
  1398. FreeWild(num, file)
  1399.     int        num;
  1400.     char    **file;
  1401. {
  1402.     if (file == NULL || num == 0)
  1403.         return;
  1404.     while (num--)
  1405.         free(file[num]);
  1406.     free(file);
  1407. }
  1408.  
  1409.     int
  1410. has_wildcard(p)
  1411.     char *p;
  1412. {
  1413.     for ( ; *p; ++p)
  1414.         if (strchr("*?[(~#", *p) != NULL)
  1415.             return 1;
  1416.     return 0;
  1417. }
  1418.  
  1419. /*
  1420.  * With 2.0 support for reading local environment variables
  1421.  */
  1422.  
  1423.     char *
  1424. vimgetenv(var)
  1425.     char *var;
  1426. {
  1427.   int len;
  1428.  
  1429. #ifndef NO_ARP
  1430.   if (!dos2)
  1431.         return getenv(var);
  1432. #endif
  1433.  
  1434.   len = GetVar((UBYTE *)var, (UBYTE *)IObuff, (long)(IOSIZE - 1), (long)0);
  1435.  
  1436.   if (len == -1)
  1437.       return NULL;
  1438.   else
  1439.       return IObuff;
  1440. }
  1441.