home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib25.zoo / main.c < prev    next >
C/C++ Source or Header  |  1992-09-05  |  6KB  |  217 lines

  1. /* from Dale Schumacher's dLibs */
  2. /* heavily modified by ers and jrb */
  3.  
  4. #include <stddef.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <osbind.h>
  9. #include <mintbind.h>
  10. #include <memory.h>
  11. #include <time.h>
  12. #include <fcntl.h>
  13. #include <unistd.h>
  14. #include <ctype.h>
  15.  
  16. int    errno;
  17. int    __mint;        /* 0 for TOS, MiNT version number otherwise */
  18.  
  19. char    _rootdir;    /* user's preferred root directory */
  20.  
  21. clock_t _starttime;    /* 200 HZ tick when we started the program */
  22. clock_t _childtime;    /* time consumed so far by our children */
  23. FILE    _iob[_NFILE];    /* stream buffers initialized below */
  24.  
  25. /* functions registered by user for calling at exit */
  26. #ifdef __STDC__
  27. typedef void (*ExitFn)(void);
  28. #else
  29. typedef void (*ExitFn)();
  30. #endif
  31. ExitFn *_at_exit;
  32. int _num_at_exit;    /* number of functions registered - 1 */
  33.  
  34. /*
  35.  * get MiNT version number. Since this has to be done in supervisor mode,
  36.  * we might as well set the start-up time of the system here, too.
  37.  */
  38.  
  39. static void
  40. getMiNT()
  41. {
  42.     long *cookie;
  43.  
  44. /* get the system time in 200HZ ticks from the BIOS _hz_200 variable */
  45.     _starttime = *((unsigned long *) 0x4baL);
  46.     _childtime = 0;
  47.  
  48.     cookie = *((long **) 0x5a0L);
  49.     if (!cookie)
  50.         __mint = 0;
  51.     else {
  52.         while (*cookie) {
  53.             if (*cookie == 0x4d694e54L) {    /* MiNT */
  54.                 __mint = (int) cookie[1];
  55.                 return;
  56.             }
  57.             cookie += 2;
  58.         }
  59.     }
  60.     __mint = 0;
  61. }
  62.  
  63. /* supplied by the user */
  64. __EXTERN int main __PROTO((int, char **, char **));
  65.  
  66. /* in getbuf.c */
  67. __EXTERN void _getbuf __PROTO((FILE *));
  68.  
  69. #if defined(__TURBOC__) && !defined(__NO_FLOAT__)
  70. void _fpuinit(void); /* in PCFLTLIB.LIB */
  71.  
  72. long _fpuvect[10];
  73. long _pfumode;
  74. long _fpuctrl;
  75. #endif
  76.  
  77. void
  78. _main(_argc, _argv, _envp)
  79.     long _argc;
  80.     char **_argv, **_envp;
  81. {
  82.     register FILE *f;
  83.     register int i;
  84.     char *s, *t;
  85.     extern int __default_mode__;    /* in defmode.c or defined by user */
  86.     extern short _app;    /* tells if we're an application or acc */
  87.  
  88.     _num_at_exit = 0;
  89.     errno = 0;
  90.  
  91. #if defined(__TURBOC__) && !defined(__NO_FLOAT__)
  92.     _fpuinit();
  93. #endif
  94.  
  95. /*
  96.  * check for MiNT
  97.  */
  98.     (void)Supexec(getMiNT);
  99.     if (__mint && _app)
  100.         (void)Pdomain(1);    /* set MiNT domain */
  101.  
  102. /*
  103.  * initialize UNIXMODE stuff. Note that this library supports only
  104.  * a few of the UNIXMODE variables, namely "b" (binary mode default)
  105.  * and "r<c>" (default root directory).
  106.  */
  107.     if ((s = getenv("UNIXMODE")) != 0) {
  108.         while (*s) {
  109.             if (*s == 'b')
  110.                 __default_mode__ = _IOBIN;
  111.             else if (*s == 'r' && s[1])
  112.                 _rootdir = *++s;
  113.             s++;
  114.         }
  115.     }
  116.  
  117.     if (_rootdir >= 'A' && _rootdir <= 'Z')
  118.         _rootdir = _rootdir - 'A' + 'a';
  119.  
  120. /*
  121.  * if we're running under MiNT, and the current drive is U:, then this
  122.  * must be our preferred drive
  123.  */
  124.     if (!_rootdir && __mint >= 9) {
  125.         if (Dgetdrv() == 'U'-'A')
  126.             _rootdir = 'u';
  127.     }
  128.  
  129. /* if stderr is not re-directed to a file, force 2 to console
  130.  * (UNLESS we've been run from a shell we trust, i.e. one that supports
  131.  *  the official ARGV scheme, in which case we leave stderr be).
  132.  */
  133.     if(!*_argv[0] && isatty(2))
  134.         (void)Fforce(2, -1);
  135.  
  136.     stdin->_flag = _IOREAD|_IOFBF|__default_mode__;
  137.     stdout->_flag = _IOWRT|_IOLBF|__default_mode__;
  138.     stderr->_flag = _IORW|_IONBF|__default_mode__;
  139.              /* some brain-dead people read from stderr */
  140.  
  141.     for(i = 0, f = _iob; i < 3; ++i, ++f) {    /* flag device streams */
  142.         if(isatty(f->_file = i))
  143.             f->_flag |= _IODEV;
  144.         else
  145.             if(f == stdout)    { /* stderr is NEVER buffered */
  146.             /* if stdout re-directed, make it full buffered */
  147.                 f->_flag &= ~(_IOLBF | _IONBF);
  148.                 f->_flag |=  _IOFBF;
  149.             }
  150.         _getbuf(f);    /* get a buffer */
  151.     }
  152.      for(i = 3; i < _NFILE; i++, f++) {
  153.       f->_flag = 0;        /* clear flags, if this is a dumped program */
  154.     }
  155.  
  156.     /* Fix up environment, if necessary. At present, the only variable
  157.      * affected is PATH; the "standard" path separators for PATH are
  158.      * ',' and ';' in the Atari world, but POSIX mandates ':'. This
  159.      * conflicts with the use of ':' as a drive separator, so we
  160.      * also convert names like A:\foo to /dev/A/foo
  161.      * NOTE: this conversion must be undone in spawn.c so that
  162.      * old fashioned programs will understand us!
  163.      */
  164.     for (i = 0; (s = _envp[i]) != 0; i++) {
  165.         if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' &&
  166.             s[3] == 'H' && s[4] == '=') {
  167.             _envp[i] = (char *)malloc(4 * strlen(s));
  168.             strncpy(_envp[i], s, 5);
  169.             t = _envp[i]+5;
  170.             s += 5;
  171.             while (*s) {
  172.                 if (s[1] == ':' && isalpha(*s)) {    /* drive letter */
  173.                     *t++ = '/';
  174.                     *t++ = 'd'; *t++ = 'e'; *t++ = 'v';
  175.                     *t++ = '/'; *t++ = *s++; s++;
  176.                 } else if (*s == ';' || *s == ',') {
  177.                     *t++ = ':'; s++;
  178.                 } else if (*s == '\\') {
  179.                     *t++ = '/'; s++;
  180.                 } else {
  181.                     *t++ = *s++;
  182.                 }
  183.             }
  184.             *t++ = 0;
  185.             break;
  186.         }
  187.     }
  188.  
  189.     /* ANSI-Draft: A return from the initial call to the main 
  190.      * function is equivalent to calling the exit function with
  191.      * the value returned by the main function as its argument. If
  192.      * the main function executes a return that specifies no
  193.      * value, the termination status returned to the host
  194.      * environment is undefined. [section 2.1.2.2]
  195.      */
  196.     exit(main((int) _argc, _argv, _envp));
  197. }
  198.  
  199. __EXITING exit(status)
  200.     int status;
  201. {
  202.     register int i, f;
  203.  
  204.     for(i = _num_at_exit - 1; i >= 0; --i)
  205.         (*_at_exit[i])();
  206.  
  207.     for(i=0; i<_NFILE; ++i) {
  208.         f = _iob[i]._flag;
  209.         if(f & (_IORW | _IOREAD | _IOWRT))
  210.             if (_iob[i]._file <= 2) /* only flush std. streams */
  211.                 fflush(&_iob[i]);
  212.             else
  213.                 fclose(&_iob[i]);
  214.     }
  215.     _exit(status);
  216. }
  217.