home *** CD-ROM | disk | FTP | other *** search
- /* from Dale Schumacher's dLibs */
- /* heavily modified by ers and jrb */
-
- #include <stddef.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <osbind.h>
- #include <mintbind.h>
- #include <memory.h>
- #include <time.h>
- #include <fcntl.h>
- #include <unistd.h>
-
- int errno;
- int __mint; /* 0 for TOS, MiNT version number otherwise */
-
- char _rootdir; /* user's preferred root directory */
-
- clock_t _starttime; /* 200 HZ tick when we started the program */
- clock_t _childtime; /* time consumed so far by our children */
- FILE _iob[_NFILE]; /* stream buffers initialized below */
-
- /* functions registered by user for calling at exit */
- #ifdef __STDC__
- typedef void (*ExitFn)(void);
- #else
- typedef void (*ExitFn)();
- #endif
- static ExitFn *_at_exit;
- static int num_at_exit; /* number of functions registered - 1 */
-
- /*
- * get MiNT version number. Since this has to be done in supervisor mode,
- * we might as well set the start-up time of the system here, too.
- */
-
- static void
- getMiNT()
- {
- long *cookie;
-
- /* get the system time in 200HZ ticks from the BIOS _hz_200 variable */
- _starttime = *((unsigned long *) 0x4ba);
- _childtime = 0;
-
- cookie = *((long **) 0x5a0);
- if (!cookie)
- __mint = 0;
- else {
- while (*cookie) {
- if (*cookie == 0x4d694e54L) { /* MiNT */
- __mint = cookie[1];
- return;
- }
- cookie += 2;
- }
- }
- __mint = 0;
- }
-
- /* supplied by the user */
- __EXTERN int main __PROTO((int, char **, char **));
-
- /* in getbuf.c */
- __EXTERN void _getbuf __PROTO((FILE *));
-
- void
- _main(_argc, _argv, _envp)
- long _argc;
- char **_argv, **_envp;
- {
- register FILE *f;
- register int i;
- char *s, *t, *new;
- extern int __default_mode__; /* in binmode.c or defined by user */
- extern short _app; /* tells if we're an application or acc */
-
- num_at_exit = 0;
- errno = 0;
- /*
- * check for MiNT
- */
- (void)Supexec(getMiNT);
- if (__mint && _app)
- (void)Pdomain(1); /* set MiNT domain */
-
- /*
- * initialize UNIXMODE stuff. Note that this library supports only
- * a few of the UNIXMODE variables, namely "b" (binary mode default)
- * and "r<c>" (default root directory).
- */
- if ((s = getenv("UNIXMODE")) != 0) {
- while (*s) {
- if (*s == 'b')
- __default_mode__ = _IOBIN;
- else if (*s == 'r' && s[1])
- _rootdir = *++s;
- s++;
- }
- }
-
- if (_rootdir >= 'A' && _rootdir <= 'Z')
- _rootdir = _rootdir - 'A' + 'a';
-
- /*
- * if we're running under MiNT, and the current drive is U:, then this
- * must be our preferred drive
- */
- if (!_rootdir && __mint >= 9) {
- if (Dgetdrv() == 'U'-'A')
- _rootdir = 'u';
- }
-
- /* if stderr is not re-directed to a file, force 2 to console
- * (UNLESS we've been run from a shell we trust, i.e. one that supports
- * the official ARGV scheme, in which case we leave stderr be).
- */
- if(!*_argv[0] && isatty(2))
- (void)Fforce(2, -1);
-
- stdin->_flag = _IOREAD|_IOFBF|__default_mode__;
- stdout->_flag = _IOWRT|_IOLBF|__default_mode__;
- stderr->_flag = _IORW|_IONBF|__default_mode__;
- /* some brain-dead people read from stderr */
-
- for(i = 0, f = _iob; i < 3; ++i, ++f) { /* flag device streams */
- if(isatty(f->_file = i))
- f->_flag |= _IODEV;
- else
- if(f == stdout) { /* stderr is NEVER buffered */
- /* if stdout re-directed, make it full buffered */
- f->_flag &= ~(_IOLBF | _IONBF);
- f->_flag |= _IOFBF;
- }
- _getbuf(f); /* get a buffer */
- }
- for(i = 3; i < _NFILE; i++, f++) {
- f->_flag = 0; /* clear flags, if this is a dumped program */
- }
-
- /* Fix up environment, if necessary. At present, the only variable
- * affected is PATH; the "standard" path separators for PATH are
- * ',' and ';' in the Atari world, but POSIX mandates ':'. This
- * conflicts with the use of ':' as a drive separator, so we
- * also convert names like A:\foo to /dev/A/foo
- * NOTE: this conversion must be undone in spawn.c so that
- * old fashioned programs will understand us!
- */
- for (i = 0; s = _envp[i]; i++) { /* '=', NOT '==' */
- if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' &&
- s[3] == 'H' && s[4] == '=') {
- new = (char *) alloca(4*strlen(s));
- strncpy(new, s, 5);
- t = new+5;
- s += 5;
- while (*s) {
- if (s[1] == ':') { /* drive letter */
- *t++ = '/';
- *t++ = 'd'; *t++ = 'e'; *t++ = 'v';
- *t++ = '/'; *t++ = *s++; s++;
- } else if (*s == ';' || *s == ',') {
- *t++ = ':'; s++;
- } else if (*s == '\\') {
- *t++ = '/'; s++;
- } else {
- *t++ = *s++;
- }
- }
- *t++ = 0;
- _envp[i] = strdup(new);
- break;
- }
- }
-
- /* ANSI-Draft: A return from the initial call to the main
- * function is equivalent to calling the exit function with
- * the value returned by the main function as its argument. If
- * the main function executes a return that specifies no
- * value, the termination status returned to the host
- * environment is undefined. [section 2.1.2.2]
- */
- exit(main((int) _argc, _argv, _envp));
- }
-
- __EXITING exit(status)
- int status;
- {
- register int i, f;
-
- for(i = num_at_exit - 1; i >= 0; --i)
- (*_at_exit[i])();
-
- for(i=0; i<_NFILE; ++i) {
- f = _iob[i]._flag;
- if(f & (_IORW | _IOREAD | _IOWRT))
- if (_iob[i]._file <= 2) /* only flush std. streams */
- fflush(&_iob[i]);
- else
- fclose(&_iob[i]);
- }
- _exit(status);
- }
-
- /* register a function for execution on termination */
- /* Ansi requires atleast 32 entries, we make it dynamic and hope
- it meets the ansi requirement */
-
- int atexit(func)
- ExitFn func;
- {
- ExitFn *new_at_exit = _at_exit;
-
- if (num_at_exit == 0)
- new_at_exit = (ExitFn *)malloc((size_t)sizeof(ExitFn));
- else
- new_at_exit = (ExitFn *)realloc(new_at_exit,
- (size_t)((num_at_exit + 1) * sizeof(ExitFn)));
- if(new_at_exit == (ExitFn *)NULL)
- return -1; /* failure */
-
- _at_exit = new_at_exit;
- _at_exit[num_at_exit++] = func;
- return 0; /* success */
- }
-