home *** CD-ROM | disk | FTP | other *** search
- /* sys/init.c (emx+gcc) -- Copyright (c) 1992-1993 by Eberhard Mattes */
-
- #include <sys/emx.h>
- #include <os2emx.h>
- #include <signal.h>
- #include <string.h>
-
- #define EXTERN
- #define INIT(x) = x
-
- #include "syscalls.h"
- #include "syssig.h"
-
- static int arg_size;
- static int env_size;
- static int argc;
- static int envc;
- static char **vec;
- static char *pool;
-
- extern void volatile __init_ret (void *stack);
- static void parse_args (const char *src);
- static void parse_env (const char *src);
- static ULONG _sys_exception (PEXCEPTIONREPORTRECORD report,
- PEXCEPTIONREGISTRATIONRECORD registration, PCONTEXTRECORD context,
- PVOID whatever);
-
- #define PUTC(c) BEGIN ++arg_size; if (pool != NULL) *pool++ = (c); END
- #define PUTV BEGIN ++argc; if (vec != NULL) *vec++ = pool; END
-
- #define WHITE(c) ((c) == ' ' || (c) == '\t')
-
- static void parse_args (const char *src)
- {
- int bs, quote;
- char *flag_ptr;
-
- argc = 0; arg_size = 0;
- /* argv[0] */
- PUTC (0x80);
- PUTV;
- for (;;)
- {
- PUTC (*src);
- if (*src == 0)
- break;
- ++src;
- }
- ++src;
- for (;;)
- {
- while (WHITE (*src))
- ++src;
- if (*src == 0)
- break;
- flag_ptr = pool;
- PUTC (0x80);
- PUTV;
- bs = 0; quote = 0;
- for (;;)
- {
- if (*src == '"')
- {
- while (bs >= 2)
- {
- PUTC ('\\');
- bs -= 2;
- }
- if (bs & 1)
- PUTC ('"');
- else
- {
- quote = !quote;
- if (flag_ptr != NULL)
- *flag_ptr |= 1;
- }
- bs = 0;
- }
- else if (*src == '\\')
- ++bs;
- else
- {
- while (bs != 0)
- {
- PUTC ('\\');
- --bs;
- }
- if (*src == 0 || (WHITE (*src) && !quote))
- break;
- PUTC (*src);
- }
- ++src;
- }
- PUTC (0);
- }
- }
-
-
- static void parse_env (const char *src)
- {
- envc = 0; env_size = 0;
- while (*src != 0)
- {
- ++envc;
- if (vec != NULL)
- *vec++ = pool;
- for (;;)
- {
- ++env_size;
- if (pool != NULL)
- *pool++ = *src;
- if (*src == 0)
- break;
- ++src;
- }
- ++src;
- }
- }
-
-
-
- void __init (void)
- {
- ULONG rc;
- PTIB ptib;
- PPIB ppib;
- void *stack;
- int n;
- ULONG times;
-
- _sys_get_clock (&_sys_clock0_lo, &_sys_clock0_hi, &_sys_clock0_ms);
- rc = DosGetInfoBlocks (&ptib, &ppib);
- if (rc != 0)
- DosExit (EXIT_PROCESS, 255);
- vec = NULL; pool = NULL;
- parse_env (ppib->pib_pchenv);
- parse_args (ppib->pib_pchcmd);
- n = arg_size + env_size + (argc+1+envc+1) * sizeof (char *);
- if (n & 3)
- n = (n | 3) + 1; /* alignment for EXCEPTIONREGISTRATIONRECORD */
- stack = alloca (n + sizeof (EXCEPTIONREGISTRATIONRECORD));
- _sys_xreg = stack + n;
- vec = stack;
- pool = (char *)(vec + argc+1+envc+1);
- parse_env (ppib->pib_pchenv);
- *vec++ = NULL; /* empty environment */
- parse_args (ppib->pib_pchcmd);
- *vec++ = NULL;
- _sys_heap_size = 0x2000000;
- rc = DosAllocMem (&_sys_heap_base, _sys_heap_size, PAG_READ|PAG_WRITE);
- if (rc != 0)
- DosExit (EXIT_PROCESS, 255);
- _sys_heap_brk = _sys_heap_base;
- for (n = 0; n < NSIG; ++n)
- {
- _sys_sig_handlers[n] = SIG_DFL;
- _sys_sig_ack_req[n] = 0;
- _sys_sig_pending[n] = 0;
- }
- _sys_xreg->prev_structure = (void *)0xffffffff;
- _sys_xreg->ExceptionHandler = _sys_exception;
- rc = DosSetExceptionHandler (_sys_xreg);
- if (rc != 0)
- DosExit (EXIT_PROCESS, 255);
- DosSetSignalExceptionFocus (SIG_SETFOCUS, ×);
- /* Fails for PM programs, error code 303 */
- __init_ret (stack);
- }
-
-
- static const char * const sig_name[NSIG] =
- {
- NULL,
- "SIGHUP",
- "SIGINT",
- "SIGQUIT",
- "SIGILL",
- "SIGTRAP",
- "SIGABRT",
- "SIGEMT",
- "SIGFPE",
- "SIGKILL",
- "SIGBUS",
- "SIGSEGV",
- "SIGSYS",
- "SIGPIPE",
- "SIGALRM",
- "SIGTERM",
- "SIGCLD",
- "SIGBREAK"
- };
-
-
- static void say (const char *msg)
- {
- __write (2, msg, strlen (msg));
- };
-
-
- static ULONG _sys_signal (int sig)
- {
- if (sig < 1 || sig >= NSIG)
- return (XCPT_CONTINUE_SEARCH);
- if (_sys_sig_handlers[sig] == SIG_IGN)
- return (XCPT_CONTINUE_EXECUTION);
- else if (_sys_sig_handlers[sig] == SIG_DFL)
- {
- if (sig == SIGCLD)
- return (XCPT_CONTINUE_EXECUTION);
- if (sig == SIGABRT)
- say ("\r\nAbnormal program termination\r\n");
- else
- {
- say ("\r\nProcess terminated by ");
- say (sig_name[sig]);
- say ("\r\n");
- }
- while (1)
- DosExit (EXIT_PROCESS, 3);
- }
- else
- {
- _sys_sig_handlers[sig] (sig);
- return (XCPT_CONTINUE_EXECUTION);
- }
- }
-
-
- static ULONG _sys_exception (PEXCEPTIONREPORTRECORD report,
- PEXCEPTIONREGISTRATIONRECORD registration,
- PCONTEXTRECORD context,
- PVOID whatever)
- {
- if (report->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
- return (XCPT_CONTINUE_SEARCH);
- switch (report->ExceptionNum)
- {
- case XCPT_SIGNAL:
- if (report->cParameters >= 1)
- {
- if (report->ExceptionInfo[0] == XCPT_SIGNAL_INTR)
- return (_sys_signal (SIGINT));
- else if (report->ExceptionInfo[0] == XCPT_SIGNAL_BREAK)
- return (_sys_signal (SIGBREAK));
- }
- break;
- case SIG2X (SIGHUP):
- return (_sys_signal (SIGHUP));
- case SIG2X (SIGINT):
- return (_sys_signal (SIGINT));
- case SIG2X (SIGQUIT):
- return (_sys_signal (SIGQUIT));
- case SIG2X (SIGILL):
- return (_sys_signal (SIGILL));
- case SIG2X (SIGTRAP):
- return (_sys_signal (SIGTRAP));
- case SIG2X (SIGABRT):
- return (_sys_signal (SIGABRT));
- case SIG2X (SIGEMT):
- return (_sys_signal (SIGEMT));
- case SIG2X (SIGFPE):
- return (_sys_signal (SIGFPE));
- case SIG2X (SIGKILL):
- return (_sys_signal (SIGKILL));
- case SIG2X (SIGBUS):
- return (_sys_signal (SIGBUS));
- case SIG2X (SIGSEGV):
- return (_sys_signal (SIGSEGV));
- case SIG2X (SIGSYS):
- return (_sys_signal (SIGSYS));
- case SIG2X (SIGPIPE):
- return (_sys_signal (SIGPIPE));
- case SIG2X (SIGALRM):
- return (_sys_signal (SIGALRM));
- case SIG2X (SIGTERM):
- return (_sys_signal (SIGTERM));
- case SIG2X (SIGCLD):
- return (_sys_signal (SIGCLD));
- case SIG2X (SIGBREAK):
- return (_sys_signal (SIGBREAK));
- }
- return (XCPT_CONTINUE_SEARCH);
- }
-
-
- void _sys_get_clock (unsigned long *lo, unsigned long *hi, unsigned long *ms)
- {
- ULONG val_lo, val_hi, val_ms, tmp_lo, tmp_hi;
-
- do
- {
- DosQuerySysInfo (QSV_TIME_HIGH, QSV_TIME_HIGH,
- &val_hi, sizeof (val_hi));
- DosQuerySysInfo (QSV_TIME_LOW, QSV_TIME_LOW,
- &val_lo, sizeof (val_lo));
- DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT,
- &val_ms, sizeof (val_ms));
- DosQuerySysInfo (QSV_TIME_LOW, QSV_TIME_LOW,
- &tmp_lo, sizeof (tmp_lo));
- DosQuerySysInfo (QSV_TIME_HIGH, QSV_TIME_HIGH,
- &tmp_hi, sizeof (tmp_hi));
- } while (val_lo != tmp_lo || val_hi != tmp_hi);
- *lo = val_lo;
- *hi = val_hi;
- *ms = val_ms;
- }
-