#include #include #include #include #include #include #include #include #include "symdir.h" #include #include "lib.h" #include int errno; int __mint; /* 0 for TOS, MiNT version number otherwise */ int _console_dev; 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 */ extern clock_t _start_time; /* defined in clock.c */ extern clock_t _child_runtime; /* defined in spawnve.c */ extern clock_t _sys_runtime; /* defined in spawnve.c */ /* * get MiNT version number */ static void getMiNT(void) { long *cookie; cookie = *((long **) 0x5a0L); if (!cookie) __mint = 0; else { while (*cookie) { if (*cookie == 0x4d694e54L) { __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; { char *tty; register FILE *f; register int i; char *s, *t; extern int __default_mode__; /* in defmode.c or defined by user */ int main(int, char **, char **); _start_time = 0; /* for dumped prgs */ _start_time = clock(); _child_runtime = _sys_runtime = 0; num_at_exit = 0; /* * check for MiNT */ (void)Supexec(getMiNT); /* * check environment for various things */ _set_unixmode(getenv("UNIXMODE")); if (tty = getenv("TTY")) { if (!strcmp(tty, "AUX:") || !strcmp(tty, "aux:")) _console_dev = 1; else _console_dev = 2; } else _console_dev = 2; /* 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, _console_dev - 3); 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 = 0; i <= 2; i++) { __open_stat[__OPEN_INDEX(i)].filename = isatty(i) ? ((_console_dev == 2) ? "/dev/console" : "/dev/tty1") : (char *)NULL; /* if it was re-dir */ } 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] == '=') { _envp[i] = (char *)malloc(4 * strlen(s)); strncpy(_envp[i], s, 5); t = _envp[i]+5; s += 5; while (*s) { if (s[1] == ':' && isalpha(*s)) { /* drive letter */ *t++ = '/'; *t++ = 'd'; *t++ = 'e'; *t++ = 'v'; *t++ = '/'; *t++ = *s++; s++; } else if (*s == ';' || *s == ',') { *t++ = ':'; s++; } else { *t++ = *s++; } } *t++ = 0; break; } } errno = 0; /* 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)); /* if main() returns exit */ } __EXITING _exit(status) int status; { __exit((long)status); } __EXITING exit(status) int status; { register int i, f; 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]); } for(i = num_at_exit - 1; i >= 0; --i) (*_at_exit[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 */ }