home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / libsrc87 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-30  |  5.3 KB  |  220 lines

  1. #include <stddef.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <osbind.h>
  5. #include <memory.h>
  6. #include <time.h>
  7. #include <fcntl.h>
  8. #include <string.h>
  9. #include "symdir.h"
  10. #include <unistd.h>
  11. #include "lib.h"
  12. #include <ctype.h>
  13.  
  14. int    errno;
  15. int    __mint;        /* 0 for TOS, MiNT version number otherwise */
  16. int    _console_dev;
  17.  
  18. FILE    _iob[_NFILE];    /* stream buffers initialized below */
  19.  
  20. /* functions registered by user for calling at exit */
  21. #ifdef __STDC__
  22. typedef void (*ExitFn)(void);
  23. #else
  24. typedef void (*ExitFn)();
  25. #endif
  26. static ExitFn *_at_exit;
  27. static int num_at_exit;    /* number of functions registered - 1 */
  28. extern clock_t    _start_time;    /* defined in clock.c */
  29. extern clock_t    _child_runtime;    /* defined in spawnve.c */
  30. extern clock_t    _sys_runtime;    /* defined in spawnve.c */
  31.  
  32. /*
  33.  * get MiNT version number
  34.  */
  35. static void
  36. getMiNT(void)
  37. {
  38.     long *cookie;
  39.  
  40.     cookie = *((long **) 0x5a0L);
  41.     if (!cookie)
  42.         __mint = 0;
  43.     else {
  44.         while (*cookie) {
  45.             if (*cookie == 0x4d694e54L) {
  46.                 __mint = cookie[1];
  47.                 return;
  48.             }
  49.             cookie += 2;
  50.         }
  51.     }
  52.     __mint = 0;
  53. }
  54.  
  55. /* supplied by the user */
  56. __EXTERN int main __PROTO((int, char **, char **));
  57.  
  58. /* in getbuf.c */
  59. __EXTERN void _getbuf __PROTO((FILE *));
  60.  
  61. void
  62. _main(_argc, _argv, _envp)
  63.     long _argc;
  64.     char **_argv, **_envp;
  65. {
  66.     char *tty;
  67.     register FILE *f;
  68.     register int i;
  69.      char *s, *t;
  70.     extern int __default_mode__; /* in defmode.c or defined by user */
  71.     int main(int, char **, char **);
  72.  
  73.     _start_time = 0;    /* for dumped prgs */
  74.     _start_time = clock();
  75.     _child_runtime = _sys_runtime = 0;
  76.     num_at_exit = 0;
  77. /*
  78.  * check for MiNT
  79.  */
  80.      (void)Supexec(getMiNT);
  81.  
  82. /*
  83.  * check environment for various things
  84.  */
  85.     _set_unixmode(getenv("UNIXMODE"));
  86.  
  87.     if (tty = getenv("TTY")) {
  88.         if (!strcmp(tty, "AUX:") || !strcmp(tty, "aux:"))
  89.             _console_dev = 1;
  90.         else
  91.             _console_dev = 2;
  92.     }
  93.     else
  94.         _console_dev = 2;
  95.  
  96. /* if stderr is not re-directed to a file, force 2 to console
  97.  * (UNLESS we've been run from a shell we trust, i.e. one that supports
  98.  *  the official ARGV scheme, in which case we leave stderr be).
  99.  */
  100.     if(!*_argv[0] && isatty(2))
  101.         (void)Fforce(2, _console_dev - 3);
  102.  
  103.     stdin->_flag = _IOREAD|_IOFBF|__default_mode__;
  104.     stdout->_flag = _IOWRT|_IOLBF|__default_mode__;
  105.     stderr->_flag = _IORW|_IONBF|__default_mode__;
  106.              /* some brain-dead people read from stderr */
  107.  
  108.     for(i = 0, f = _iob; i < 3; ++i, ++f) {    /* flag device streams */
  109.         if(isatty(f->_file = i))
  110.             f->_flag |= _IODEV;
  111.         else
  112.             if(f == stdout)    { /* stderr is NEVER buffered */
  113.             /* if stdout re-directed, make it full buffered */
  114.                 f->_flag &= ~(_IOLBF | _IONBF);
  115.                 f->_flag |=  _IOFBF;
  116.             }
  117.         _getbuf(f);    /* get a buffer */
  118.     }
  119.  
  120.     for(i = 0; i <= 2; i++) {
  121.         __open_stat[__OPEN_INDEX(i)].filename = isatty(i) ? 
  122.             ((_console_dev == 2) ? "/dev/console" : "/dev/tty1")
  123.                 : (char *)NULL; /* if it was re-dir */
  124.     }
  125.  
  126.      for(i = 3; i < _NFILE; i++, f++) {
  127.       f->_flag = 0;        /* clear flags, if this is a dumped program */
  128.     }
  129.  
  130.     /* Fix up environment, if necessary. At present, the only variable
  131.      * affected is PATH; the "standard" path separators for PATH are
  132.      * ',' and ';' in the Atari world, but POSIX mandates ':'. This
  133.      * conflicts with the use of ':' as a drive separator, so we
  134.      * also convert names like A:\foo to /dev/A/foo
  135.      * NOTE: this conversion must be undone in spawn.c so that
  136.      * old fashioned programs will understand us!
  137.      */
  138.     for (i = 0; s = _envp[i]; i++) {    /* '=', NOT '==' */
  139.         if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' &&
  140.             s[3] == 'H' && s[4] == '=') {
  141.             _envp[i] = (char *)malloc(4 * strlen(s));
  142.             strncpy(_envp[i], s, 5);
  143.             t = _envp[i]+5;
  144.             s += 5;
  145.             while (*s) {
  146.                 if (s[1] == ':' && isalpha(*s)) {    /* drive letter */
  147.                     *t++ = '/';
  148.                     *t++ = 'd'; *t++ = 'e'; *t++ = 'v';
  149.                     *t++ = '/'; *t++ = *s++; s++;
  150.                 } else if (*s == ';' || *s == ',') {
  151.                     *t++ = ':'; s++;
  152.                 } else {
  153.                     *t++ = *s++;
  154.                 }
  155.             }
  156.             *t++ = 0;
  157.             break;
  158.         }
  159.     }
  160.  
  161.     errno = 0;
  162.  
  163.     /* ANSI-Draft: A return from the initial call to the main      */
  164.     /* function is equivalent to calling the exit function with    */
  165.     /* the value returned by the main function as its argument. If */
  166.     /* the main function executes a return that specifies no       */
  167.     /* value, the termination status returned to the host            */
  168.     /* environment is undefined. [section 2.1.2.2]               */
  169.     exit(main((int) _argc, _argv, _envp));    /* if main() returns exit */
  170. }
  171.  
  172. __EXITING _exit(status)
  173.     int status;
  174. {
  175.     __exit((long)status);
  176. }
  177.  
  178. __EXITING exit(status)
  179.     int status;
  180. {
  181.     register int i, f;
  182.  
  183.  
  184.     for(i=0; i<_NFILE; ++i) {
  185.         f = _iob[i]._flag;
  186.         if(f & (_IORW | _IOREAD | _IOWRT))
  187.             if (_iob[i]._file <= 2) /* only flush std. streams */
  188.                 fflush(&_iob[i]);
  189.             else
  190.                 fclose(&_iob[i]);
  191.     }
  192.  
  193.     for(i = num_at_exit - 1; i >= 0; --i)
  194.         (*_at_exit[i])();
  195.  
  196.     _exit(status);
  197. }
  198.  
  199. /* register a function for execution on termination */
  200. /* Ansi requires atleast 32 entries, we make it dynamic and hope
  201.    it meets the ansi requirement */
  202.  
  203. int atexit(func)
  204.     ExitFn func;
  205. {
  206.         ExitFn *new_at_exit = _at_exit;
  207.     
  208.     if (num_at_exit == 0)
  209.         new_at_exit = (ExitFn *)malloc((size_t)sizeof(ExitFn));
  210.     else
  211.         new_at_exit = (ExitFn *)realloc(new_at_exit,
  212.             (size_t)((num_at_exit + 1) * sizeof(ExitFn)));
  213.     if(new_at_exit == (ExitFn *)NULL)
  214.         return -1;    /* failure */
  215.  
  216.         _at_exit = new_at_exit;
  217.     _at_exit[num_at_exit++] = func;
  218.     return 0;        /* success */
  219. }
  220.