home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright 1990,1991,1992 Eric R. Smith. All rights reserved.
- */
-
- #include "mint.h"
- #include "version.h"
- #include "cookie.h"
- #include "xbra.h"
-
- /* the kernel's stack size */
- #define STACK 8*1024L
-
- /* if the user is holding down the magic shift key, we ask before booting */
- #define MAGIC_SHIFT 0x1 /* right shift */
-
- static void xbra_install P_((xbra_vec *, long, void (*)()));
- static void init_intr P_((void));
- static void getmch P_((void));
- static void do_line P_((char *));
- static void shutmedown P_((PROC *));
- void shutdown P_((void));
- static void doset P_((char *,char *));
- static long mint_criticerr P_((long));
-
- static int gem_active; /* 0 if AES has started, 1 otherwise */
-
- static int check_for_gem P_((void));
- static void run_auto_prgs P_((void));
-
- #ifdef LATTICE
- /*
- * AGK: this is witchcraft to completely replace the startup code for
- * Lattice; doing so saves around 10K on the final binary and pulls only
- * long division & multitplication from the library (and not even those
- * if you compile for native '030). The drawback of this code is it
- * passes no environment or command line whatsoever. Since I always
- * set MiNT options & environment in 'mint.cnf' this is not a personal
- * downer, however at some point in the future we ought to have a kernel
- * parseargs() like call which sets these things up.
- */
- BASEPAGE *_base;
-
- static void
- start(BASEPAGE *bp)
- {
- long shrinklen;
-
- _base = bp;
- shrinklen = bp->p_tlen + bp->p_dlen + bp->p_blen + STACK + 0x100;
- if (bp->p_lowtpa + shrinklen <= bp->p_hitpa) {
- static char null[1] = {""};
- static char *argv[2] = {null, NULL};
- extern __builtin_putreg P_((int, long)); /* totally bogus */
-
- __builtin_putreg(15, bp->p_lowtpa + shrinklen);
- Mshrink((void *)bp->p_lowtpa, shrinklen);
- main(1, argv, argv);
- }
- Pterm(ENSMEM);
- }
- #endif
-
- #ifdef __GNUC__
- long _stksize = STACK;
- #include <minimal.h>
- #endif
-
- int curs_off = 0; /* set if we should turn the cursor off when exiting */
- int mint_errno = 0; /* error return from open and creat filesystem calls */
-
- /*
- * AGK: for proper co-processors we must consider saving their context.
- * This variable when non-zero indicates that the BIOS considers a true
- * coprocessor to be present. We use this variable in the context switch
- * code to decide whether to attempt an FPU context save.
- */
- short fpu = 0;
-
- /*
- * "mch" holds what kind of machine we are running on
- */
- long mch = 0;
-
- /*
- * variable holds processor type
- */
- long mcpu = 0;
-
- /*
- * variable set to 1 iff on a 68010 (used by the context switch code)
- * this is redundant with mcpu, but is kept for reasons of speed
- */
- short m68010 = 0;
-
- /*
- * variable set if someone has already installed an flk cookie
- */
- int flk = 0;
-
- /* program to run at startup */
- char orig_init[] = "init.prg";
- char *init_prg = orig_init;
- char init_tail[128];
-
- /* initial environment for that program */
- char *init_env = 0;
- /* temporary pointer into that environment for setenv */
- char *env_ptr;
- /* length of the environment */
- long env_len;
-
- /* flag that's set if we want pseudo-drives to have BIOS entries:
- * 0 means no BIOS interaction with pseudo-drives at all
- * 1 means the drives show up in _drvbits and Drvmap()
- * 2 means the above + fake handlers for Rwabs, Mediach, etc.
- */
-
- int pseudodrives = 2;
-
- /* GEMDOS pointer to current basepage */
- BASEPAGE **tosbp;
-
- /* pointer to the BIOS keyboard shift variable */
- extern char *kbshft; /* see bios.c */
-
- /* version of TOS we're running over */
- int tosvers;
-
- /* structures for keyboard/MIDI interrupt vectors */
- KBDVEC *syskey, oldkey;
- xbra_vec old_ikbd; /* old ikbd vector */
-
- /* values the user sees for the DOS, BIOS, and XBIOS vectors */
- long save_dos, save_bios, save_xbios;
-
- /* values for original system vectors */
- xbra_vec old_dos, old_bios, old_xbios, old_timer, old_vbl, old_5ms;
- xbra_vec old_criticerr;
-
- long old_term;
-
- xbra_vec old_resvec; /* old reset vector */
- long old_resval; /* old reset validation */
-
- #ifdef EXCEPTION_SIGS
- /* bus error, address error, illegal instruction, etc. vectors */
- xbra_vec old_bus, old_addr, old_ill, old_divzero, old_trace, old_priv;
- #endif
-
- /* BIOS disk vectors */
- xbra_vec old_mediach, old_getbpb, old_rwabs;
-
- /* BIOS drive map */
- long olddrvs;
-
- extern Func bios_tab[], dos_tab[];
-
- /* kernel info that is passed to loaded file systems and device drivers */
-
- struct kerinfo kernelinfo = {
- MAJ_VERSION, MIN_VERSION,
- DEFAULT_MODE, 0,
- bios_tab, dos_tab,
- changedrv,
- TRACE, DEBUG, ALERT, FATAL,
- kmalloc, kfree, umalloc, ufree,
- strnicmp, stricmp, strlwr, strupr, ksprintf,
- ms_time, unixtim, dostim,
- nap, sleep, wake, wakeselect,
- denyshare, denylock
- };
-
- /* temporary stack for resets -- see intr.s */
- char tmpstack[256];
-
- /* TOS and MiNT cookie jars, respectively. See the comments and code
- * after main() for further details
- */
-
- COOKIE *oldcookie, *newcookie;
-
- /*
- * install a new vector for address "addr", using the XBRA protocol.
- * must run in supervisor mode!
- */
-
- static void
- xbra_install(xv, addr, func)
- xbra_vec *xv;
- long addr;
- void (*func)();
- {
- xv->xbra_magic = XBRA_MAGIC;
- xv->xbra_id = MINT_MAGIC;
- xv->jump = JMP_OPCODE;
- xv->this = func;
- xv->next = *((struct xbra **)addr);
- *((short **)addr) = &xv->jump;
- }
-
- /*
- * MiNT critical error handler; all it does is to jump through
- * the vector for the current process
- */
-
- static long
- mint_criticerr(error)
- long error; /* high word is error, low is drive */
- {
- return (*curproc->criticerr)(error);
- }
-
- /* initialize all interrupt vectors and new trap routines
- * we also get here any TOS variables that we're going to change
- * (e.g. the pointer to the cookie jar) so that rest_intr can
- * restore them.
- */
-
- static void
- init_intr()
- {
- extern void mint_bios(), mint_dos(), mint_timer(), mint_vbl();
- extern void mint_5ms(); /* AKP */
- extern void mint_xbios(), reset();
- extern void new_ikbd();
- extern void new_bus(), new_addr(), new_ill(), new_divzero(),
- new_trace(), new_priv();
- short savesr;
-
- syskey = (KBDVEC *)Kbdvbase();
- oldkey = *syskey;
-
- xbra_install(&old_ikbd, (long)(&syskey->ikbdsys), new_ikbd);
-
- /* gratuitous (void *) for Lattice */
- old_term = (long)Setexc(0x102, (void *)-1L);
-
- savesr = spl7();
-
- xbra_install(&old_dos, 0x84L, mint_dos);
- save_dos = (long)old_dos.next;
-
- xbra_install(&old_bios, 0xb4L, mint_bios);
- save_bios = (long)old_bios.next;
-
- xbra_install(&old_xbios, 0xb8L, mint_xbios);
- save_xbios = (long)old_xbios.next;
-
- xbra_install(&old_timer, 0x400L, mint_timer);
- xbra_install(&old_criticerr, 0x404L, (void (*)())mint_criticerr);
- xbra_install(&old_5ms, 0x114L, mint_5ms);
- xbra_install(&old_vbl, 4*0x1cL, mint_vbl);
- xbra_install(&old_resvec, 0x42aL, reset);
- old_resval = *((long *)0x426L);
-
- spl(savesr);
-
- #ifdef EXCEPTION_SIGS
- /* set up signal handlers */
- xbra_install(&old_bus, 8L, new_bus);
- xbra_install(&old_addr, 12L, new_addr);
- xbra_install(&old_ill, 16L, new_ill);
- xbra_install(&old_divzero, 20L, new_divzero);
- xbra_install(&old_trace, 36L, new_trace);
- # ifdef STRICT_PRIV
- /* don't do this */
- xbra_install(&old_priv, 32L, new_priv);
- # endif
- #endif
-
- /* set up disk vectors */
- xbra_install(&old_mediach, 0x47eL, new_mediach);
- xbra_install(&old_rwabs, 0x476L, new_rwabs);
- xbra_install(&old_getbpb, 0x472L, new_getbpb);
- olddrvs = *((long *)0x4c2L);
-
- /* set up cookie jar */
- oldcookie = *CJAR; /* CJAR defined in cookie.h */
- install_cookies();
- }
-
- /* restore all interrupt vectors and trap routines */
- /*
- * NOTE: This is *not* the approved way of unlinking XBRA trap handlers.
- * Normally, one should trace through the XBRA chain. However, this is
- * a very unusual situation: when MiNT exits, any TSRs or programs running
- * under MiNT will no longer exist, and so any vectors that they have
- * caught will be pointing to never-never land! So we do something that
- * would normally be considered rude, and restore the vectors to
- * what they were before we ran.
- * BUG: we should restore *all* vectors, not just the ones that MiNT caught.
- */
-
- void
- restr_intr()
- {
- short savesr;
-
- savesr = spl7();
- *syskey = oldkey; /* restore keyboard vectors */
- *tosbp = _base; /* restore GEMDOS basepage pointer */
- *CJAR = oldcookie; /* restore old cookie jar */
-
- #ifdef EXCEPTION_SIGS
- *((long *)0x08L) = (long) old_bus.next;
- *((long *)0x0cL) = (long) old_addr.next;
- *((long *)0x10L) = (long) old_ill.next;
- *((long *)0x14L) = (long) old_divzero.next;
- # ifdef STRICT_PRIV
- *((long *)0x20L) = (long) old_priv.next;
- # endif
- *((long *)0x24L) = (long) old_trace.next;
- #endif
- *((long *)0x84L) = (long) old_dos.next;
- *((long *)0xb4L) = (long) old_bios.next;
- *((long *)0xb8L) = (long) old_xbios.next;
- *((long *)0x408L) = old_term;
- *((long *)0x404L) = (long) old_criticerr.next;
- *((long *)0x114L) = (long) old_5ms.next;
- *((long *)0x400L) = (long) old_timer.next;
- *((long *)0x70L) = (long) old_vbl.next;
- *((long *)0x426L) = old_resval;
- *((long *)0x42aL) = (long) old_resvec.next;
- *((long *)0x476L) = (long) old_rwabs.next;
- *((long *)0x47eL) = (long) old_mediach.next;
- *((long *)0x472L) = (long) old_getbpb.next;
- *((long *)0x4c2L) = olddrvs;
-
- spl(savesr);
- }
-
-
- /* we save the TOS supervisor stack pointer so that we can reset it when
- calling Pterm() (not that anyone will ever want to leave MiNT :-)).
- */
-
- long tosssp; /* TOS supervisor stack pointer */
-
-
- /*
- * enter_kernel: called every time we enter the MiNT kernel via a trap
- * call. Sets up the GEMDOS and BIOS vectors to point to TOS, and
- * sets up other vectors and system variables appropriately. Note that
- * calling enter_kernel multiple times should not be harmful!
- */
-
- short in_kernel = 0;
-
- void
- enter_kernel()
- {
- short save_sr;
-
- if (in_kernel) return;
-
- save_sr = spl7();
- save_dos = *((long *) 0x84L);
- save_bios = *((long *) 0xb4L);
- save_xbios = *((long *) 0xb8L);
- *((long *) 0x84L) = (long)old_dos.next;
- *((long *) 0xb4L) = (long)old_bios.next;
- *((long *) 0xb8L) = (long)old_xbios.next;
- *tosbp = rootproc->base;
-
- in_kernel = 1;
- spl(save_sr);
- }
-
- /*
- * leave_kernel: called before leaving the kernel, either back to
- * user mode or when calling a signal handler or the GEMDOS
- * terminate vector. Note that interrupts should be disabled before
- * this routine is called.
- */
-
- void
- leave_kernel()
- {
- if (!in_kernel) {
- ALERT("leave_kernel: not in kernel??");
- }
- *((long *) 0x84L) = save_dos;
- *((long *) 0xb4L) = save_bios;
- *((long *) 0xb8L) = save_xbios;
- *tosbp = curproc->base;
- in_kernel = 0;
- }
-
- /*
- * shut down processes; this involves waking them all up, and sending
- * them SIGTERM to give them a chance to clean up after themselves
- */
-
- static void
- shutmedown(p)
- PROC *p;
- {
- curproc->wait_cond = 0;
- }
-
- void
- shutdown()
- {
- PROC *p;
- int proc_left = 0;
-
- curproc->sighandle[SIGCHLD] = SIG_IGN;
-
- for (p = proclist; p; p = p->gl_next) {
- if (p->pid == 0) continue;
- if (p->wait_q != ZOMBIE_Q && p->wait_q != TSR_Q) {
- if (p->wait_q != READY_Q) {
- rm_q(p->wait_q, p);
- add_q(READY_Q, p);
- }
- post_sig(p, SIGTERM);
- proc_left++;
- }
- }
-
- if (proc_left) {
- /* sleep a little while, to give the other processes a chance to
- shut down
- */
-
- addtimeout(1000, shutmedown);
- do {
- sleep(WAIT_Q, (long)&shutdown);
- } while (curproc->wait_cond == (long)&shutdown);
- }
- }
-
- #ifdef ZEROEXIT
- /*
- * a horrible kludge: TOS 1.4 has a bug that causes GEM to get upset
- * if a large AUTO folder program runs and leaves non-zero memory
- * behind. So, before we leave, we zero as much of ourselves as
- * possible. To do this, we copy a short, position independent
- * assembly language function into the basepage, and then execute
- * it; the function will take care of exiting.
- * Note: the GEM bug doesn't usually bite because most AUTO folder
- * programs are TSRs and hence GEM doesn't reuse their memory.
- */
-
- static short exitfunc[] = {
- 0x41fa, 0x0012, /* lea end(pc), a0 */
- 0x226f, 0x0004, /* move.l 4(sp), a1 */
- 0x4240, /* clr.w d0 */
- 0x30c0, /* L1: move.w d0, a0@+ */
- 0xb3c8, /* cmp.l a0, a1 */
- 0x66fa, /* bne L1 */
- 0x3f00, /* move.w d0, sp@- */
- 0x4e41 /* trap #1 */
- }; /* end: */
-
- void zeroexit()
- {
- int i;
- short *to, *from;
- void (*func)();
-
- if (mcpu > 10) { /* on 68020+, we could run into cache problems */
- Pterm0(); /* let's hope we're running a fixed version of TOS */
- }
-
- to = (short *)_base->p_cmdlin;
- func = (void (*)()) to;
- from = exitfunc;
- for (i = 0; i < sizeof(exitfunc); i++) {
- *to++ = *from++;
- }
- (*P_((void (*)(long)))func)(_base->p_hitpa);
- }
- #else /* zerofunc */
- void zeroexit() { Pterm0(); }
- #endif
-
- int
- main(argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
- {
- long *sysbase;
- long r;
- extern int debug_level; /* in debug.c */
- static char buf[SPRINTF_MAX];
- static char curpath[128];
- int yn;
- FILEPTR *f;
-
- /* Allow the user to abort the boot if the magic combination of shift keys
- * is held down (see MAGIC_SHIFT above)
- */
- if ((Kbshift(-1) & MAGIC_SHIFT) == MAGIC_SHIFT) {
- Cconws("Boot MiNT? (y/n) ");
- yn = Cconin() & 0x7f;
- if (yn != 'y' && yn != 'Y') {
- Cconws("\r\n\r\nMiNT not booted, at user's request.\r\n");
- Pterm0();
- }
- }
-
- if (argv[0][0] == 0) { /* maybe started from the desktop */
- curs_off = 1;
- }
-
- if (argc > 1) {
- debug_level++;
- }
- if (argc > 2) {
- debug_level++;
- }
-
- /* greetings */
- Cconws("\r\n\033eMiNT is Not TOS: MiNT version ");
- #ifdef PATCHLEVEL
- ksprintf(buf, VERS_STRING, MAJ_VERSION, MIN_VERSION, PATCHLEVEL);
- #else
- ksprintf(buf, VERS_STRING, MAJ_VERSION, MIN_VERSION);
- #endif
- Cconws(buf);
- Cconws("\r\nCopyright 1990,1991,1992 Eric R. Smith\r\n");
- Cconws("Use this program at your own risk!\r\n");
- Cconws("See the file \"copying\" for distribution conditions\r\n");
-
- gem_active = check_for_gem(); /* this must be done from user mode */
-
- /*
- * get the current directory, so that we can switch back to it after
- * the file systems are properly initialized
- */
- /* set the current directory for the current process */
- (void)Dgetpath(curpath, 0);
-
- tosssp = (long)Super(0L); /* enter supervisor mode */
-
- /* figure out what kind of machine we're running on */
- /* biosfs wants to know this, so we have to do it very
- * early in our initialization
- */
- getmch();
-
- /* get GEMDOS pointer to current basepage */
- /* 0x4f2 points to the base of the OS; here we can find the OS compilation
- date, and (in newer versions of TOS) where the current basepage pointer
- is kept; in older versions of TOS, it's at 0x602c
- */
- sysbase = *((long **)(0x4f2L)); /* gets the RAM OS header */
- sysbase = (long *)sysbase[2]; /* gets the ROM one */
-
- tosvers = (sysbase[0] & 0x0000ffff);
- if (tosvers == 0x100) {
- if ((sysbase[7] & 0xfffe0000) == 0x00080000)
- tosbp = (BASEPAGE **)0x873cL; /* SPANISH ROM */
- else
- tosbp = (BASEPAGE **) 0x602cL;
- kbshft = (char *) 0x0e1bL;
- } else {
- tosbp = (BASEPAGE **) sysbase[10];
- kbshft = (char *) sysbase[9];
- }
-
- /* The TT TOS release notes are wrong... this is the real way to test
- * for Bconmap ability
- */
- has_bconmap = (Bconmap(0) == 0);
-
- /* initialize memory */
- init_mem();
- TRACE("back from init_mem");
-
- /* initialize the basic file systems */
- init_filesys();
- TRACE("back from init_filesys");
-
- /* initialize processes */
- init_proc();
- TRACE("back from init_proc");
-
- /* initialize system calls */
- init_dos();
- init_bios();
- init_xbios();
-
- /* NOTE: there's a call to kmalloc embedded in install_cookies, which
- * is called by init_intr; so make sure this is the last of the
- * init_* things called!
- */
- init_intr();
- enter_kernel();
-
- /* set up standard file handles for the current process
- * do this here, *after* init_intr has set the Rwabs vector,
- * so that AHDI doesn't get upset by references to drive U:
- */
- f = do_open("U:\\DEV\\CONSOLE", O_RDWR, 0, (XATTR *)0);
- if (!f) {
- FATAL("unable to open CONSOLE device");
- }
- curproc->control = f;
- curproc->handle[0] = f;
- curproc->handle[1] = f;
- f->links = 3;
-
- f = do_open("U:\\DEV\\MODEM1", O_RDWR, 0, (XATTR *)0);
- curproc->aux = f;
- if (has_bconmap) {
- /* If someone has already done a Bconmap call, then
- * MODEM1 may no longer be the default
- */
- bconmap(curbconmap);
- f = curproc->aux; /* bconmap can change curproc->aux */
- }
- if (f) {
- curproc->handle[2] = f;
- f->links++;
- }
- f = do_open("U:\\DEV\\CENTR", O_RDWR, 0, (XATTR *)0);
- if (f) {
- curproc->handle[3] = curproc->prn = f;
- f->links = 2;
- }
- if (f) {
- f = do_open("U:\\DEV\\MIDI", O_RDWR, 0, (XATTR *)0);
- curproc->midiin = curproc->midiout = f;
- f->links = 2;
- }
-
- /* load external file systems */
- if (*curpath) {
- (void)d_setpath(curpath);
- }
-
- load_filesys();
-
- /* note that load_filesys changed the
- * directory on us!!
- */
- if (*curpath) {
- (void)d_setpath(curpath);
- }
-
- /* load the configuration file */
- load_config();
-
- /* if we want pseudo-drives, set the drive map accordingly */
- if (pseudodrives > 0) {
- *((long *)0x4c2L) |= PSEUDODRVS;
- };
- if (pseudodrives < 2) { /* restore old Rwabs, etc. */
- *((long *)0x476L) = (long) old_rwabs.next;
- *((long *)0x47eL) = (long) old_mediach.next;
- *((long *)0x472L) = (long) old_getbpb.next;
- }
-
- if (init_env == 0)
- init_env = (char *)_base->p_env;
-
- /* empty environment? Set the PATH variable to the root of the current drive */
- if (init_env[0] == 0) {
- static char path_env[] = "PATH=\0C:\0";
- path_env[6] = curproc->curdrv + 'A';
- init_env = path_env;
- }
-
- /* run any programs appearing after us in the AUTO folder */
- run_auto_prgs();
-
- /* run the initial program */
-
- r = p_exec(0, init_prg, init_tail, init_env);
-
- /* if it isn't found, and the user didn't say otherwise, try GEM */
- if (r == EFILNF && init_prg == orig_init) {
- if (!gem_active) {
- BASEPAGE *bp; int pid;
- bp = (BASEPAGE *)p_exec(7, (char *)7L, (char *)"\0", init_env);
- bp->p_tbase = *((long *) 0x4feL );
- pid = p_exec(106, (char *)"GEM", bp, 0L);
- if (pid > 0) {
- do {
- r = p_wait3(0, (long *)0);
- } while(pid != ((r & 0xffff0000) >> 16));
- r &= 0x0000ffff;
- }
- } else {
- Cconws("If MiNT is run after GEM starts, you must specify a program\r\n");
- Cconws("to run initially in MINT.CNF, with an INIT= line\r\n");
- r = 0;
- }
- }
-
- if (r < 0) {
- ksprintf(buf, "FATAL: couldn't run %s\r\n", init_prg);
- Cconws(buf);
- }
-
- if (r) {
- ksprintf(buf, "exit code: %ld\r\n", r);
- Cconws(buf);
- }
-
- /* shut down all processes gracefully */
- shutdown();
-
- /* put everything back and exit */
- restr_intr();
- close_filesys();
-
- (void)Super((void *)tosssp); /* gratuitous (void *) for Lattice */
- Cconws("leaving MiNT\r\n");
-
- if (curs_off)
- Cconws("\033f"); /* disable cursor */
-
- zeroexit();
- return 0; /* dummy -- this should never be reached */
- }
-
-
- /*
- * cookie jar handling routines. The "cookie jar" is an area of memory
- * reserved by TOS for TSR's and utility programs; the idea is that
- * you put a cookie in the jar to notify people of available services.
- * The BIOS uses the cookie jar in TOS 1.6 and higher; for earlier versions
- * of TOS, the jar is always empty (unless someone added a cookie before
- * us; POOLFIX does, for example).
- * MiNT establishes an entirely new cookie jar (with the old cookies copied
- * over) and frees it on exit. That's because TSR's run under MiNT
- * will no longer be accessible after MiNT exits.
- * MiNT also puts a cookie in the jar, with tag field 'MiNT' (of course)
- * and with the major version of MiNT in the high byte of the low word,
- * and the minor version in the low byte.
- */
-
- void
- install_cookies()
- {
- COOKIE *cookie;
- int i, ncookies;
-
- /* note that init_intr sets oldcookie to the old cookie jar */
-
- ncookies = 0;
- cookie = oldcookie;
- if (cookie) {
- while (cookie->tag.aslong != 0) {
- /* check for true FPU co-processor */
- if (!strncmp(cookie->tag.aschar, "_FPU",4) &&
- (cookie->value >> 16) >= 2)
- fpu = 1;
- /* check for _FLK cookie */
- else if (!strncmp(cookie->tag.aschar, "_FLK",4))
- flk = 1;
- cookie++; ncookies++;
- }
- }
-
- /* NOTE: obviously, we can do this only if init_intr is called
- * _after_ memory, processes, etc. have been initialized
- */
- newcookie = (COOKIE *)kmalloc((ncookies + 16)*sizeof(COOKIE));
- assert(newcookie);
-
- /* copy the old cookies to the new jar */
-
- for (i = 0; i < ncookies; i++) {
- newcookie[i] = oldcookie[i];
- }
-
- /* install MiNT cookie */
- strncpy(newcookie[i].tag.aschar, "MiNT", 4);
- newcookie[i].value = (MAJ_VERSION << 8) | MIN_VERSION;
- i++;
-
- /* install _FLK cookie to indicate that file locking works */
- if (!flk) {
- strncpy(newcookie[i].tag.aschar, "_FLK", 4);
- newcookie[i].value = 0;
- i++;
- }
-
- /* the last cookie should have a 0 tag, and a value indicating the number
- * of slots, total
- */
-
- newcookie[i].tag.aslong = 0;
- newcookie[i].value = ncookies+16;
-
- *CJAR = newcookie;
-
- }
-
- /*
- * get the value of the _MCH cookie, if one exists
- * this must be done in a separate routine because the machine type
- * is needed when initializing the bios file system, whereas
- * install_cookies is not called until everything is installed
- * In fact, getmch() should be called before *anything* else is
- * initialized, so that if we find a MiNT cookie already in the
- * jar we can bail out early.
- */
-
- static void
- getmch()
- {
- COOKIE *jar;
-
- jar = *CJAR; /* CJAR defined in cookie.h */
- if (jar) {
- while (jar->tag.aslong != 0) {
- /* check for machine type */
- if (!strncmp(jar->tag.aschar, "_MCH",4)) {
- mch = jar->value;
- } else if (!strncmp(jar->tag.aschar, "_CPU", 4)) {
- mcpu = jar->value;
- if (mcpu == 10)
- m68010 = 1;
- } else if (!strncmp(jar->tag.aschar, "MiNT",4)) {
- Cconws("MiNT is already installed!!\r\n");
- (void)Super((void *)tosssp);
- Pterm(2);
- }
- jar++;
- }
- }
- }
-
- /*
- * routines for reading the configuration file
- * we allow the following commands in the file:
- * # anything -- comment
- * INIT=file -- specify boot program
- * cd dir -- change directory/drive
- * ren file1 file2 -- rename a file
- * sln file1 file2 -- create a symbolic link
- * echo message -- print a message on the screen
- * setenv var value -- set an environment variable
- *
- * BUG: if you use setenv in mint.cnf, *none* of the original environment
- * gets passed to children. This is rarely a problem if mint.prg is
- * in the auto folder.
- */
-
- extern short bconbdev, bconbsiz; /* from bios.c */
-
- static void
- doset(name, val)
- char *name, *val;
- {
- char *t;
-
- if (!strcmp(name, "INIT")) {
- t = kmalloc(strlen(val)+1);
- if (!t) return;
- strcpy(t, val);
- init_prg = t;
- while (*t && !isspace(*t)) t++;
- /* get the command tail, too */
- if (*t) {
- *t++ = 0;
- strncpy(init_tail+1, t, 125);
- init_tail[0] = strlen(init_tail+1);
- }
- return;
- }
- if (!strcmp(name, "CON")) {
- FILEPTR *f;
- int i;
-
- f = do_open(val, O_RDWR, 0, (XATTR *)0);
- if (f) {
- for (i = -1; i < 2; i++) {
- do_close(curproc->handle[i]);
- curproc->handle[i] = f;
- f->links++;
- }
- f->links--; /* correct for overdoing it */
- }
- return;
- }
- if (!strcmp(name, "PRN")) {
- FILEPTR *f;
-
- f = do_open(val, O_RDWR|O_CREAT|O_TRUNC, 0, (XATTR *)0);
- if (f) {
- do_close(curproc->handle[2]);
- do_close(curproc->prn);
- curproc->prn = curproc->handle[2] = f;
- f->links = 2;
- }
- return;
- }
- if (!strcmp(name, "BIOSBUF")) {
- if (*val == 'n' || *val == 'N') {
- if (bconbsiz) bflush();
- bconbdev = -1;
- }
- return;
- }
- if (!strcmp(name, "PSEUDODRIVES")) {
- if (*val == 'n' || *val == 'N') {
- pseudodrives = 0;
- } else if (*val == 'm' || *val == 'M') {
- pseudodrives = 1;
- }
- return;
- }
- if (!strcmp(name, "DEBUG_LEVEL")) {
- extern int debug_level;
- if (*val >= '0' && *val <= '9') debug_level = atoi(val);
- else ALERT("Bad arg to \"DEBUG_LEVEL\" in cnf file");
- return;
- }
- if (!strcmp(name, "DEBUG_DEVNO")) {
- extern int out_device;
- if (*val >= '0' && *val <= '9') out_device= atoi(val);
- else ALERT("Bad arg to \"DEBUG_DEVNO\" in cnf file");
- return;
- }
-
- #ifdef FASTTEXT
- if (!strcmp(name, "HARDSCROLL")) {
- int i = 0;
- extern int hardscroll;
-
- i = *val++;
- if (i < '0' || i > '9') return;
- hardscroll = i-'0';
- i = *val;
- if (i < '0' || i > '9') return;
- hardscroll = 10*hardscroll + i - '0';
- return;
- }
- #endif
- ALERT("Unknown variable `%s'", name);
- }
-
- /* Execute a line from the config file */
- static void
- do_line(line)
- char *line;
- {
- char *cmd, *arg1, *arg2;
- char *newenv;
- char *t;
- int i;
-
- while (*line == ' ') line++;
- if (*line == '#') return; /* ignore comments */
- if (!*line) return; /* and also blank lines */
-
- cmd = line;
- /* check for variable assignments (e.g. INIT=, etc.) */
- /*
- * AGK: note we check for spaces whilst scanning so that an environment
- * variable may include an =, this has the unfortunate side effect that
- * the '=' _has_ to be concatenated to the variable name (INIT etc.)
- */
- for (t = cmd; *t && *t != ' '; t++) {
- if (*t == '=') {
- *t++ = 0;
- doset(cmd, t);
- return;
- }
- }
-
- /* OK, assume a regular command; break it up into 'cmd', 'arg1', arg2' */
-
- while (*line && *line != ' ') line++;
- if (*line == ' ') {
- *line++ = 0;
- while (*line == ' ') line++;
- }
-
- if (!strcmp(cmd, "echo")) {
- c_conws(line); c_conws("\r\n");
- return;
- }
- arg1 = line;
- while (*line && *line != ' ') line++;
- if (*line) {
- *line++ = 0;
- while (*line == ' ') line++;
- }
- if (!strcmp(cmd, "cd")) {
- int drv;
- (void)d_setpath(arg1);
- drv = toupper(*arg1) - 'A';
- if (arg1[1] == ':') (void)d_setdrv(drv);
- return;
- }
- if (!strcmp(cmd, "exec")) {
- static char cmdline[128];
- int i;
-
- i = strlen(line);
- if (i > 126) i = 126;
- cmdline[0] = i;
- strncpy(cmdline+1, line, i);
- cmdline[i+1] = 0;
- i = p_exec(0, arg1, cmdline, init_env);
- if (i == -33) {
- ALERT("%s: file not found", arg1);
- } else if (i < 0) {
- ALERT("%s: error while attempting to execute", arg1);
- }
- return;
- }
- if (!strcmp(cmd, "setenv")) {
- if (strlen(arg1) + strlen(line) + 4 + (env_ptr - init_env) >
- env_len) {
- newenv = umalloc(env_len + 1024L);
- t = init_env;
- env_ptr = newenv;
- for (i = 0; i < env_len; i++)
- *env_ptr++ = *t++;
- env_len += 1024;
- if (init_env)
- ufree(init_env);
- init_env = newenv;
- }
- while (*arg1) {
- *env_ptr++ = *arg1++; env_len++;
- }
- *env_ptr++ = '=';
- while (*line) {
- *env_ptr++ = *line++; env_len++;
- }
- *env_ptr++ = 0;
- *env_ptr = 0;
- return;
- }
-
- arg2 = line;
- while (*line && *line != ' ') line++;
- if (*line) {
- *line++ = 0;
- }
- if (!strcmp(cmd, "sln")) {
- (void)f_symlink(arg1, arg2);
- return;
- }
- if (!strcmp(cmd, "ren")) {
- (void)f_rename(0, arg1, arg2);
- return;
- }
- ALERT("syntax error in mint.cnf");
- }
-
- #define BUF 512
- #define LINE 256
-
- void
- load_config()
- {
- int fd;
- long r;
- char buf[BUF+1], c;
- char line[LINE+1];
- char *from;
- int count = 0;
-
- TRACE("reading configuration file");
- fd = f_open("mint.cnf", 0);
- if (fd < 0)
- fd = f_open("\\mint\\mint.cnf", 0);
- if (fd < 0) return;
- buf[BUF] = 0;
- from = &buf[BUF];
- line[LINE] = 0;
-
- for(;;) {
- c = *from++;
- if (!c) {
- r = f_read(fd, (long)BUF, buf);
- if (r <= 0) break;
- buf[r] = 0;
- from = buf;
- } else if (c == '\r') {
- continue;
- } else if (c == '\n') {
- line[count] = 0;
- do_line(line);
- count = 0;
- } else {
- if (count < LINE) {
- line[count++] = c;
- }
- }
- }
- f_close(fd);
- }
-
- /*
- * run programs in the AUTO folder that appear after MINT.PRG
- * some things to watch out for:
- * (1) make sure GEM isn't active
- * (2) make sure there really is a MINT.PRG in the auto folder
- */
-
- /*
- * some global variables used to see if GEM is active
- */
- static short aes_intout[64];
- static short aes_dummy[64];
- static short aes_globl[15];
- static short aes_cntrl[6] = { 10, 0, 1, 0, 0 };
-
- short *aes_pb[6] = { aes_cntrl, aes_globl, aes_dummy, aes_intout,
- aes_dummy, aes_dummy };
-
- /* check for whether GEM is active; remember, this *must* be done in
- * user mode
- */
-
- static int
- check_for_gem()
- {
- call_aes(aes_pb); /* does an appl_init */
- return aes_globl[0];
- }
-
- static void
- run_auto_prgs()
- {
- DTABUF *dta;
- long r;
- static char pathspec[32] = "\\AUTO\\";
- short runthem = 0; /* set to 1 after we find MINT.PRG */
-
- /* if the AES is running, don't check AUTO */
-
- if (gem_active) {
- return;
- }
-
- /* OK, now let's run through \\AUTO looking for
- * programs...
- */
- dta = (DTABUF *)f_getdta();
- r = f_sfirst("\\AUTO\\*.PRG", 0);
- while (r >= 0) {
- if (!strcmp(dta->dta_name, "MINT.PRG"))
- runthem = 1;
- else if (runthem) {
- strcpy(pathspec+6, dta->dta_name);
- (void)p_exec(0, pathspec, (char *)"", init_env);
- }
- r = f_snext();
- }
- }
-