|
|
1.1 ! root 1: /* ! 2: ! 3: Copyright 1990,1991,1992 Eric R. Smith. All rights reserved. ! 4: ! 5: */ ! 6: ! 7: ! 8: ! 9: #include "mint.h" ! 10: ! 11: #include "version.h" ! 12: ! 13: #include "cookie.h" ! 14: ! 15: #include "xbra.h" ! 16: ! 17: ! 18: ! 19: /* the kernel's stack size */ ! 20: ! 21: #define STACK 8*1024L ! 22: ! 23: ! 24: ! 25: /* if the user is holding down the magic shift key, we ask before booting */ ! 26: ! 27: #define MAGIC_SHIFT 0x1 /* right shift */ ! 28: ! 29: ! 30: ! 31: static void xbra_install P_((xbra_vec *, long, void (*)())); ! 32: ! 33: static void init_intr P_((void)); ! 34: ! 35: static void getmch P_((void)); ! 36: ! 37: static void do_line P_((char *)); ! 38: ! 39: static void shutmedown P_((PROC *)); ! 40: ! 41: void shutdown P_((void)); ! 42: ! 43: static void doset P_((char *,char *)); ! 44: ! 45: static long mint_criticerr P_((long)); ! 46: ! 47: ! 48: ! 49: static int gem_active; /* 0 if AES has started, 1 otherwise */ ! 50: ! 51: ! 52: ! 53: static int check_for_gem P_((void)); ! 54: ! 55: static void run_auto_prgs P_((void)); ! 56: ! 57: ! 58: ! 59: #ifdef LATTICE ! 60: ! 61: /* ! 62: ! 63: * AGK: this is witchcraft to completely replace the startup code for ! 64: ! 65: * Lattice; doing so saves around 10K on the final binary and pulls only ! 66: ! 67: * long division & multitplication from the library (and not even those ! 68: ! 69: * if you compile for native '030). The drawback of this code is it ! 70: ! 71: * passes no environment or command line whatsoever. Since I always ! 72: ! 73: * set MiNT options & environment in 'mint.cnf' this is not a personal ! 74: ! 75: * downer, however at some point in the future we ought to have a kernel ! 76: ! 77: * parseargs() like call which sets these things up. ! 78: ! 79: */ ! 80: ! 81: BASEPAGE *_base; ! 82: ! 83: ! 84: ! 85: static void ! 86: ! 87: start(BASEPAGE *bp) ! 88: ! 89: { ! 90: ! 91: long shrinklen; ! 92: ! 93: ! 94: ! 95: _base = bp; ! 96: ! 97: shrinklen = bp->p_tlen + bp->p_dlen + bp->p_blen + STACK + 0x100; ! 98: ! 99: if (bp->p_lowtpa + shrinklen <= bp->p_hitpa) { ! 100: ! 101: static char null[1] = {""}; ! 102: ! 103: static char *argv[2] = {null, NULL}; ! 104: ! 105: extern __builtin_putreg P_((int, long)); /* totally bogus */ ! 106: ! 107: ! 108: ! 109: __builtin_putreg(15, bp->p_lowtpa + shrinklen); ! 110: ! 111: Mshrink((void *)bp->p_lowtpa, shrinklen); ! 112: ! 113: main(1, argv, argv); ! 114: ! 115: } ! 116: ! 117: Pterm(ENSMEM); ! 118: ! 119: } ! 120: ! 121: #endif ! 122: ! 123: ! 124: ! 125: #ifdef __GNUC__ ! 126: ! 127: long _stksize = STACK; ! 128: ! 129: #include <minimal.h> ! 130: ! 131: #endif ! 132: ! 133: ! 134: ! 135: int curs_off = 0; /* set if we should turn the cursor off when exiting */ ! 136: ! 137: int mint_errno = 0; /* error return from open and creat filesystem calls */ ! 138: ! 139: ! 140: ! 141: /* ! 142: ! 143: * AGK: for proper co-processors we must consider saving their context. ! 144: ! 145: * This variable when non-zero indicates that the BIOS considers a true ! 146: ! 147: * coprocessor to be present. We use this variable in the context switch ! 148: ! 149: * code to decide whether to attempt an FPU context save. ! 150: ! 151: */ ! 152: ! 153: short fpu = 0; ! 154: ! 155: ! 156: ! 157: /* ! 158: ! 159: * "mch" holds what kind of machine we are running on ! 160: ! 161: */ ! 162: ! 163: long mch = 0; ! 164: ! 165: ! 166: ! 167: /* ! 168: ! 169: * variable holds processor type ! 170: ! 171: */ ! 172: ! 173: long mcpu = 0; ! 174: ! 175: ! 176: ! 177: /* ! 178: ! 179: * variable set to 1 iff on a 68010 (used by the context switch code) ! 180: ! 181: * this is redundant with mcpu, but is kept for reasons of speed ! 182: ! 183: */ ! 184: ! 185: short m68010 = 0; ! 186: ! 187: ! 188: ! 189: /* ! 190: ! 191: * variable set if someone has already installed an flk cookie ! 192: ! 193: */ ! 194: ! 195: int flk = 0; ! 196: ! 197: ! 198: ! 199: /* program to run at startup */ ! 200: ! 201: char orig_init[] = "init.prg"; ! 202: ! 203: char *init_prg = orig_init; ! 204: ! 205: char init_tail[128]; ! 206: ! 207: ! 208: ! 209: /* initial environment for that program */ ! 210: ! 211: char *init_env = 0; ! 212: ! 213: /* temporary pointer into that environment for setenv */ ! 214: ! 215: char *env_ptr; ! 216: ! 217: /* length of the environment */ ! 218: ! 219: long env_len; ! 220: ! 221: ! 222: ! 223: /* flag that's set if we want pseudo-drives to have BIOS entries: ! 224: ! 225: * 0 means no BIOS interaction with pseudo-drives at all ! 226: ! 227: * 1 means the drives show up in _drvbits and Drvmap() ! 228: ! 229: * 2 means the above + fake handlers for Rwabs, Mediach, etc. ! 230: ! 231: */ ! 232: ! 233: ! 234: ! 235: int pseudodrives = 2; ! 236: ! 237: ! 238: ! 239: /* GEMDOS pointer to current basepage */ ! 240: ! 241: BASEPAGE **tosbp; ! 242: ! 243: ! 244: ! 245: /* pointer to the BIOS keyboard shift variable */ ! 246: ! 247: extern char *kbshft; /* see bios.c */ ! 248: ! 249: ! 250: ! 251: /* version of TOS we're running over */ ! 252: ! 253: int tosvers; ! 254: ! 255: ! 256: ! 257: /* structures for keyboard/MIDI interrupt vectors */ ! 258: ! 259: KBDVEC *syskey, oldkey; ! 260: ! 261: xbra_vec old_ikbd; /* old ikbd vector */ ! 262: ! 263: ! 264: ! 265: /* values the user sees for the DOS, BIOS, and XBIOS vectors */ ! 266: ! 267: long save_dos, save_bios, save_xbios; ! 268: ! 269: ! 270: ! 271: /* values for original system vectors */ ! 272: ! 273: xbra_vec old_dos, old_bios, old_xbios, old_timer, old_vbl, old_5ms; ! 274: ! 275: xbra_vec old_criticerr; ! 276: ! 277: ! 278: ! 279: long old_term; ! 280: ! 281: ! 282: ! 283: xbra_vec old_resvec; /* old reset vector */ ! 284: ! 285: long old_resval; /* old reset validation */ ! 286: ! 287: ! 288: ! 289: #ifdef EXCEPTION_SIGS ! 290: ! 291: /* bus error, address error, illegal instruction, etc. vectors */ ! 292: ! 293: xbra_vec old_bus, old_addr, old_ill, old_divzero, old_trace, old_priv; ! 294: ! 295: #endif ! 296: ! 297: ! 298: ! 299: /* BIOS disk vectors */ ! 300: ! 301: xbra_vec old_mediach, old_getbpb, old_rwabs; ! 302: ! 303: ! 304: ! 305: /* BIOS drive map */ ! 306: ! 307: long olddrvs; ! 308: ! 309: ! 310: ! 311: extern Func bios_tab[], dos_tab[]; ! 312: ! 313: ! 314: ! 315: /* kernel info that is passed to loaded file systems and device drivers */ ! 316: ! 317: ! 318: ! 319: struct kerinfo kernelinfo = { ! 320: ! 321: MAJ_VERSION, MIN_VERSION, ! 322: ! 323: DEFAULT_MODE, 0, ! 324: ! 325: bios_tab, dos_tab, ! 326: ! 327: changedrv, ! 328: ! 329: TRACE, DEBUG, ALERT, FATAL, ! 330: ! 331: kmalloc, kfree, umalloc, ufree, ! 332: ! 333: strnicmp, stricmp, strlwr, strupr, ksprintf, ! 334: ! 335: ms_time, unixtim, dostim, ! 336: ! 337: nap, sleep, wake, wakeselect, ! 338: ! 339: denyshare, denylock ! 340: ! 341: }; ! 342: ! 343: ! 344: ! 345: /* temporary stack for resets -- see intr.s */ ! 346: ! 347: char tmpstack[256]; ! 348: ! 349: ! 350: ! 351: /* TOS and MiNT cookie jars, respectively. See the comments and code ! 352: ! 353: * after main() for further details ! 354: ! 355: */ ! 356: ! 357: ! 358: ! 359: COOKIE *oldcookie, *newcookie; ! 360: ! 361: ! 362: ! 363: /* ! 364: ! 365: * install a new vector for address "addr", using the XBRA protocol. ! 366: ! 367: * must run in supervisor mode! ! 368: ! 369: */ ! 370: ! 371: ! 372: ! 373: static void ! 374: ! 375: xbra_install(xv, addr, func) ! 376: ! 377: xbra_vec *xv; ! 378: ! 379: long addr; ! 380: ! 381: void (*func)(); ! 382: ! 383: { ! 384: ! 385: xv->xbra_magic = XBRA_MAGIC; ! 386: ! 387: xv->xbra_id = MINT_MAGIC; ! 388: ! 389: xv->jump = JMP_OPCODE; ! 390: ! 391: xv->this = func; ! 392: ! 393: xv->next = *((struct xbra **)addr); ! 394: ! 395: *((short **)addr) = &xv->jump; ! 396: ! 397: } ! 398: ! 399: ! 400: ! 401: /* ! 402: ! 403: * MiNT critical error handler; all it does is to jump through ! 404: ! 405: * the vector for the current process ! 406: ! 407: */ ! 408: ! 409: ! 410: ! 411: static long ! 412: ! 413: mint_criticerr(error) ! 414: ! 415: long error; /* high word is error, low is drive */ ! 416: ! 417: { ! 418: ! 419: return (*curproc->criticerr)(error); ! 420: ! 421: } ! 422: ! 423: ! 424: ! 425: /* initialize all interrupt vectors and new trap routines ! 426: ! 427: * we also get here any TOS variables that we're going to change ! 428: ! 429: * (e.g. the pointer to the cookie jar) so that rest_intr can ! 430: ! 431: * restore them. ! 432: ! 433: */ ! 434: ! 435: ! 436: ! 437: static void ! 438: ! 439: init_intr() ! 440: ! 441: { ! 442: ! 443: extern void mint_bios(), mint_dos(), mint_timer(), mint_vbl(); ! 444: ! 445: extern void mint_5ms(); /* AKP */ ! 446: ! 447: extern void mint_xbios(), reset(); ! 448: ! 449: extern void new_ikbd(); ! 450: ! 451: extern void new_bus(), new_addr(), new_ill(), new_divzero(), ! 452: ! 453: new_trace(), new_priv(); ! 454: ! 455: short savesr; ! 456: ! 457: ! 458: ! 459: syskey = (KBDVEC *)Kbdvbase(); ! 460: ! 461: oldkey = *syskey; ! 462: ! 463: ! 464: ! 465: xbra_install(&old_ikbd, (long)(&syskey->ikbdsys), new_ikbd); ! 466: ! 467: ! 468: ! 469: /* gratuitous (void *) for Lattice */ ! 470: ! 471: old_term = (long)Setexc(0x102, (void *)-1L); ! 472: ! 473: ! 474: ! 475: savesr = spl7(); ! 476: ! 477: ! 478: ! 479: xbra_install(&old_dos, 0x84L, mint_dos); ! 480: ! 481: save_dos = (long)old_dos.next; ! 482: ! 483: ! 484: ! 485: xbra_install(&old_bios, 0xb4L, mint_bios); ! 486: ! 487: save_bios = (long)old_bios.next; ! 488: ! 489: ! 490: ! 491: xbra_install(&old_xbios, 0xb8L, mint_xbios); ! 492: ! 493: save_xbios = (long)old_xbios.next; ! 494: ! 495: ! 496: ! 497: xbra_install(&old_timer, 0x400L, mint_timer); ! 498: ! 499: xbra_install(&old_criticerr, 0x404L, (void (*)())mint_criticerr); ! 500: ! 501: xbra_install(&old_5ms, 0x114L, mint_5ms); ! 502: ! 503: xbra_install(&old_vbl, 4*0x1cL, mint_vbl); ! 504: ! 505: xbra_install(&old_resvec, 0x42aL, reset); ! 506: ! 507: old_resval = *((long *)0x426L); ! 508: ! 509: ! 510: ! 511: spl(savesr); ! 512: ! 513: ! 514: ! 515: #ifdef EXCEPTION_SIGS ! 516: ! 517: /* set up signal handlers */ ! 518: ! 519: xbra_install(&old_bus, 8L, new_bus); ! 520: ! 521: xbra_install(&old_addr, 12L, new_addr); ! 522: ! 523: xbra_install(&old_ill, 16L, new_ill); ! 524: ! 525: xbra_install(&old_divzero, 20L, new_divzero); ! 526: ! 527: xbra_install(&old_trace, 36L, new_trace); ! 528: ! 529: # ifdef STRICT_PRIV ! 530: ! 531: /* don't do this */ ! 532: ! 533: xbra_install(&old_priv, 32L, new_priv); ! 534: ! 535: # endif ! 536: ! 537: #endif ! 538: ! 539: ! 540: ! 541: /* set up disk vectors */ ! 542: ! 543: xbra_install(&old_mediach, 0x47eL, new_mediach); ! 544: ! 545: xbra_install(&old_rwabs, 0x476L, new_rwabs); ! 546: ! 547: xbra_install(&old_getbpb, 0x472L, new_getbpb); ! 548: ! 549: olddrvs = *((long *)0x4c2L); ! 550: ! 551: ! 552: ! 553: /* set up cookie jar */ ! 554: ! 555: oldcookie = *CJAR; /* CJAR defined in cookie.h */ ! 556: ! 557: install_cookies(); ! 558: ! 559: } ! 560: ! 561: ! 562: ! 563: /* restore all interrupt vectors and trap routines */ ! 564: ! 565: /* ! 566: ! 567: * NOTE: This is *not* the approved way of unlinking XBRA trap handlers. ! 568: ! 569: * Normally, one should trace through the XBRA chain. However, this is ! 570: ! 571: * a very unusual situation: when MiNT exits, any TSRs or programs running ! 572: ! 573: * under MiNT will no longer exist, and so any vectors that they have ! 574: ! 575: * caught will be pointing to never-never land! So we do something that ! 576: ! 577: * would normally be considered rude, and restore the vectors to ! 578: ! 579: * what they were before we ran. ! 580: ! 581: * BUG: we should restore *all* vectors, not just the ones that MiNT caught. ! 582: ! 583: */ ! 584: ! 585: ! 586: ! 587: void ! 588: ! 589: restr_intr() ! 590: ! 591: { ! 592: ! 593: short savesr; ! 594: ! 595: ! 596: ! 597: savesr = spl7(); ! 598: ! 599: *syskey = oldkey; /* restore keyboard vectors */ ! 600: ! 601: *tosbp = _base; /* restore GEMDOS basepage pointer */ ! 602: ! 603: *CJAR = oldcookie; /* restore old cookie jar */ ! 604: ! 605: ! 606: ! 607: #ifdef EXCEPTION_SIGS ! 608: ! 609: *((long *)0x08L) = (long) old_bus.next; ! 610: ! 611: *((long *)0x0cL) = (long) old_addr.next; ! 612: ! 613: *((long *)0x10L) = (long) old_ill.next; ! 614: ! 615: *((long *)0x14L) = (long) old_divzero.next; ! 616: ! 617: # ifdef STRICT_PRIV ! 618: ! 619: *((long *)0x20L) = (long) old_priv.next; ! 620: ! 621: # endif ! 622: ! 623: *((long *)0x24L) = (long) old_trace.next; ! 624: ! 625: #endif ! 626: ! 627: *((long *)0x84L) = (long) old_dos.next; ! 628: ! 629: *((long *)0xb4L) = (long) old_bios.next; ! 630: ! 631: *((long *)0xb8L) = (long) old_xbios.next; ! 632: ! 633: *((long *)0x408L) = old_term; ! 634: ! 635: *((long *)0x404L) = (long) old_criticerr.next; ! 636: ! 637: *((long *)0x114L) = (long) old_5ms.next; ! 638: ! 639: *((long *)0x400L) = (long) old_timer.next; ! 640: ! 641: *((long *)0x70L) = (long) old_vbl.next; ! 642: ! 643: *((long *)0x426L) = old_resval; ! 644: ! 645: *((long *)0x42aL) = (long) old_resvec.next; ! 646: ! 647: *((long *)0x476L) = (long) old_rwabs.next; ! 648: ! 649: *((long *)0x47eL) = (long) old_mediach.next; ! 650: ! 651: *((long *)0x472L) = (long) old_getbpb.next; ! 652: ! 653: *((long *)0x4c2L) = olddrvs; ! 654: ! 655: ! 656: ! 657: spl(savesr); ! 658: ! 659: } ! 660: ! 661: ! 662: ! 663: ! 664: ! 665: /* we save the TOS supervisor stack pointer so that we can reset it when ! 666: ! 667: calling Pterm() (not that anyone will ever want to leave MiNT :-)). ! 668: ! 669: */ ! 670: ! 671: ! 672: ! 673: long tosssp; /* TOS supervisor stack pointer */ ! 674: ! 675: ! 676: ! 677: ! 678: ! 679: /* ! 680: ! 681: * enter_kernel: called every time we enter the MiNT kernel via a trap ! 682: ! 683: * call. Sets up the GEMDOS and BIOS vectors to point to TOS, and ! 684: ! 685: * sets up other vectors and system variables appropriately. Note that ! 686: ! 687: * calling enter_kernel multiple times should not be harmful! ! 688: ! 689: */ ! 690: ! 691: ! 692: ! 693: short in_kernel = 0; ! 694: ! 695: ! 696: ! 697: void ! 698: ! 699: enter_kernel() ! 700: ! 701: { ! 702: ! 703: short save_sr; ! 704: ! 705: ! 706: ! 707: if (in_kernel) return; ! 708: ! 709: ! 710: ! 711: save_sr = spl7(); ! 712: ! 713: save_dos = *((long *) 0x84L); ! 714: ! 715: save_bios = *((long *) 0xb4L); ! 716: ! 717: save_xbios = *((long *) 0xb8L); ! 718: ! 719: *((long *) 0x84L) = (long)old_dos.next; ! 720: ! 721: *((long *) 0xb4L) = (long)old_bios.next; ! 722: ! 723: *((long *) 0xb8L) = (long)old_xbios.next; ! 724: ! 725: *tosbp = rootproc->base; ! 726: ! 727: ! 728: ! 729: in_kernel = 1; ! 730: ! 731: spl(save_sr); ! 732: ! 733: } ! 734: ! 735: ! 736: ! 737: /* ! 738: ! 739: * leave_kernel: called before leaving the kernel, either back to ! 740: ! 741: * user mode or when calling a signal handler or the GEMDOS ! 742: ! 743: * terminate vector. Note that interrupts should be disabled before ! 744: ! 745: * this routine is called. ! 746: ! 747: */ ! 748: ! 749: ! 750: ! 751: void ! 752: ! 753: leave_kernel() ! 754: ! 755: { ! 756: ! 757: if (!in_kernel) { ! 758: ! 759: ALERT("leave_kernel: not in kernel??"); ! 760: ! 761: } ! 762: ! 763: *((long *) 0x84L) = save_dos; ! 764: ! 765: *((long *) 0xb4L) = save_bios; ! 766: ! 767: *((long *) 0xb8L) = save_xbios; ! 768: ! 769: *tosbp = curproc->base; ! 770: ! 771: in_kernel = 0; ! 772: ! 773: } ! 774: ! 775: ! 776: ! 777: /* ! 778: ! 779: * shut down processes; this involves waking them all up, and sending ! 780: ! 781: * them SIGTERM to give them a chance to clean up after themselves ! 782: ! 783: */ ! 784: ! 785: ! 786: ! 787: static void ! 788: ! 789: shutmedown(p) ! 790: ! 791: PROC *p; ! 792: ! 793: { ! 794: ! 795: curproc->wait_cond = 0; ! 796: ! 797: } ! 798: ! 799: ! 800: ! 801: void ! 802: ! 803: shutdown() ! 804: ! 805: { ! 806: ! 807: PROC *p; ! 808: ! 809: int proc_left = 0; ! 810: ! 811: ! 812: ! 813: curproc->sighandle[SIGCHLD] = SIG_IGN; ! 814: ! 815: ! 816: ! 817: for (p = proclist; p; p = p->gl_next) { ! 818: ! 819: if (p->pid == 0) continue; ! 820: ! 821: if (p->wait_q != ZOMBIE_Q && p->wait_q != TSR_Q) { ! 822: ! 823: if (p->wait_q != READY_Q) { ! 824: ! 825: rm_q(p->wait_q, p); ! 826: ! 827: add_q(READY_Q, p); ! 828: ! 829: } ! 830: ! 831: post_sig(p, SIGTERM); ! 832: ! 833: proc_left++; ! 834: ! 835: } ! 836: ! 837: } ! 838: ! 839: ! 840: ! 841: if (proc_left) { ! 842: ! 843: /* sleep a little while, to give the other processes a chance to ! 844: ! 845: shut down ! 846: ! 847: */ ! 848: ! 849: ! 850: ! 851: addtimeout(1000, shutmedown); ! 852: ! 853: do { ! 854: ! 855: sleep(WAIT_Q, (long)&shutdown); ! 856: ! 857: } while (curproc->wait_cond == (long)&shutdown); ! 858: ! 859: } ! 860: ! 861: } ! 862: ! 863: ! 864: ! 865: #ifdef ZEROEXIT ! 866: ! 867: /* ! 868: ! 869: * a horrible kludge: TOS 1.4 has a bug that causes GEM to get upset ! 870: ! 871: * if a large AUTO folder program runs and leaves non-zero memory ! 872: ! 873: * behind. So, before we leave, we zero as much of ourselves as ! 874: ! 875: * possible. To do this, we copy a short, position independent ! 876: ! 877: * assembly language function into the basepage, and then execute ! 878: ! 879: * it; the function will take care of exiting. ! 880: ! 881: * Note: the GEM bug doesn't usually bite because most AUTO folder ! 882: ! 883: * programs are TSRs and hence GEM doesn't reuse their memory. ! 884: ! 885: */ ! 886: ! 887: ! 888: ! 889: static short exitfunc[] = { ! 890: ! 891: 0x41fa, 0x0012, /* lea end(pc), a0 */ ! 892: ! 893: 0x226f, 0x0004, /* move.l 4(sp), a1 */ ! 894: ! 895: 0x4240, /* clr.w d0 */ ! 896: ! 897: 0x30c0, /* L1: move.w d0, a0@+ */ ! 898: ! 899: 0xb3c8, /* cmp.l a0, a1 */ ! 900: ! 901: 0x66fa, /* bne L1 */ ! 902: ! 903: 0x3f00, /* move.w d0, sp@- */ ! 904: ! 905: 0x4e41 /* trap #1 */ ! 906: ! 907: }; /* end: */ ! 908: ! 909: ! 910: ! 911: void zeroexit() ! 912: ! 913: { ! 914: ! 915: int i; ! 916: ! 917: short *to, *from; ! 918: ! 919: void (*func)(); ! 920: ! 921: ! 922: ! 923: if (mcpu > 10) { /* on 68020+, we could run into cache problems */ ! 924: ! 925: Pterm0(); /* let's hope we're running a fixed version of TOS */ ! 926: ! 927: } ! 928: ! 929: ! 930: ! 931: to = (short *)_base->p_cmdlin; ! 932: ! 933: func = (void (*)()) to; ! 934: ! 935: from = exitfunc; ! 936: ! 937: for (i = 0; i < sizeof(exitfunc); i++) { ! 938: ! 939: *to++ = *from++; ! 940: ! 941: } ! 942: ! 943: (*P_((void (*)(long)))func)(_base->p_hitpa); ! 944: ! 945: } ! 946: ! 947: #else /* zerofunc */ ! 948: ! 949: void zeroexit() { Pterm0(); } ! 950: ! 951: #endif ! 952: ! 953: ! 954: ! 955: int ! 956: ! 957: main(argc, argv, envp) ! 958: ! 959: int argc; ! 960: ! 961: char **argv; ! 962: ! 963: char **envp; ! 964: ! 965: { ! 966: ! 967: long *sysbase; ! 968: ! 969: long r; ! 970: ! 971: extern int debug_level; /* in debug.c */ ! 972: ! 973: static char buf[SPRINTF_MAX]; ! 974: ! 975: static char curpath[128]; ! 976: ! 977: int yn; ! 978: ! 979: FILEPTR *f; ! 980: ! 981: ! 982: ! 983: /* Allow the user to abort the boot if the magic combination of shift keys ! 984: ! 985: * is held down (see MAGIC_SHIFT above) ! 986: ! 987: */ ! 988: ! 989: if ((Kbshift(-1) & MAGIC_SHIFT) == MAGIC_SHIFT) { ! 990: ! 991: Cconws("Boot MiNT? (y/n) "); ! 992: ! 993: yn = Cconin() & 0x7f; ! 994: ! 995: if (yn != 'y' && yn != 'Y') { ! 996: ! 997: Cconws("\r\n\r\nMiNT not booted, at user's request.\r\n"); ! 998: ! 999: Pterm0(); ! 1000: ! 1001: } ! 1002: ! 1003: } ! 1004: ! 1005: ! 1006: ! 1007: if (argv[0][0] == 0) { /* maybe started from the desktop */ ! 1008: ! 1009: curs_off = 1; ! 1010: ! 1011: } ! 1012: ! 1013: ! 1014: ! 1015: if (argc > 1) { ! 1016: ! 1017: debug_level++; ! 1018: ! 1019: } ! 1020: ! 1021: if (argc > 2) { ! 1022: ! 1023: debug_level++; ! 1024: ! 1025: } ! 1026: ! 1027: ! 1028: ! 1029: /* greetings */ ! 1030: ! 1031: Cconws("\r\n\033eMiNT is Not TOS: MiNT version "); ! 1032: ! 1033: #ifdef PATCHLEVEL ! 1034: ! 1035: ksprintf(buf, VERS_STRING, MAJ_VERSION, MIN_VERSION, PATCHLEVEL); ! 1036: ! 1037: #else ! 1038: ! 1039: ksprintf(buf, VERS_STRING, MAJ_VERSION, MIN_VERSION); ! 1040: ! 1041: #endif ! 1042: ! 1043: Cconws(buf); ! 1044: ! 1045: Cconws("\r\nCopyright 1990,1991,1992 Eric R. Smith\r\n"); ! 1046: ! 1047: Cconws("Use this program at your own risk!\r\n"); ! 1048: ! 1049: Cconws("See the file \"copying\" for distribution conditions\r\n"); ! 1050: ! 1051: ! 1052: ! 1053: gem_active = check_for_gem(); /* this must be done from user mode */ ! 1054: ! 1055: ! 1056: ! 1057: /* ! 1058: ! 1059: * get the current directory, so that we can switch back to it after ! 1060: ! 1061: * the file systems are properly initialized ! 1062: ! 1063: */ ! 1064: ! 1065: /* set the current directory for the current process */ ! 1066: ! 1067: (void)Dgetpath(curpath, 0); ! 1068: ! 1069: ! 1070: ! 1071: tosssp = (long)Super(0L); /* enter supervisor mode */ ! 1072: ! 1073: ! 1074: ! 1075: /* figure out what kind of machine we're running on */ ! 1076: ! 1077: /* biosfs wants to know this, so we have to do it very ! 1078: ! 1079: * early in our initialization ! 1080: ! 1081: */ ! 1082: ! 1083: getmch(); ! 1084: ! 1085: ! 1086: ! 1087: /* get GEMDOS pointer to current basepage */ ! 1088: ! 1089: /* 0x4f2 points to the base of the OS; here we can find the OS compilation ! 1090: ! 1091: date, and (in newer versions of TOS) where the current basepage pointer ! 1092: ! 1093: is kept; in older versions of TOS, it's at 0x602c ! 1094: ! 1095: */ ! 1096: ! 1097: sysbase = *((long **)(0x4f2L)); /* gets the RAM OS header */ ! 1098: ! 1099: sysbase = (long *)sysbase[2]; /* gets the ROM one */ ! 1100: ! 1101: ! 1102: ! 1103: tosvers = (sysbase[0] & 0x0000ffff); ! 1104: ! 1105: if (tosvers == 0x100) { ! 1106: ! 1107: if ((sysbase[7] & 0xfffe0000) == 0x00080000) ! 1108: ! 1109: tosbp = (BASEPAGE **)0x873cL; /* SPANISH ROM */ ! 1110: ! 1111: else ! 1112: ! 1113: tosbp = (BASEPAGE **) 0x602cL; ! 1114: ! 1115: kbshft = (char *) 0x0e1bL; ! 1116: ! 1117: } else { ! 1118: ! 1119: tosbp = (BASEPAGE **) sysbase[10]; ! 1120: ! 1121: kbshft = (char *) sysbase[9]; ! 1122: ! 1123: } ! 1124: ! 1125: ! 1126: ! 1127: /* The TT TOS release notes are wrong... this is the real way to test ! 1128: ! 1129: * for Bconmap ability ! 1130: ! 1131: */ ! 1132: ! 1133: has_bconmap = (Bconmap(0) == 0); ! 1134: ! 1135: ! 1136: ! 1137: /* initialize memory */ ! 1138: ! 1139: init_mem(); ! 1140: ! 1141: TRACE("back from init_mem"); ! 1142: ! 1143: ! 1144: ! 1145: /* initialize the basic file systems */ ! 1146: ! 1147: init_filesys(); ! 1148: ! 1149: TRACE("back from init_filesys"); ! 1150: ! 1151: ! 1152: ! 1153: /* initialize processes */ ! 1154: ! 1155: init_proc(); ! 1156: ! 1157: TRACE("back from init_proc"); ! 1158: ! 1159: ! 1160: ! 1161: /* initialize system calls */ ! 1162: ! 1163: init_dos(); ! 1164: ! 1165: init_bios(); ! 1166: ! 1167: init_xbios(); ! 1168: ! 1169: ! 1170: ! 1171: /* NOTE: there's a call to kmalloc embedded in install_cookies, which ! 1172: ! 1173: * is called by init_intr; so make sure this is the last of the ! 1174: ! 1175: * init_* things called! ! 1176: ! 1177: */ ! 1178: ! 1179: init_intr(); ! 1180: ! 1181: enter_kernel(); ! 1182: ! 1183: ! 1184: ! 1185: /* set up standard file handles for the current process ! 1186: ! 1187: * do this here, *after* init_intr has set the Rwabs vector, ! 1188: ! 1189: * so that AHDI doesn't get upset by references to drive U: ! 1190: ! 1191: */ ! 1192: ! 1193: f = do_open("U:\\DEV\\CONSOLE", O_RDWR, 0, (XATTR *)0); ! 1194: ! 1195: if (!f) { ! 1196: ! 1197: FATAL("unable to open CONSOLE device"); ! 1198: ! 1199: } ! 1200: ! 1201: curproc->control = f; ! 1202: ! 1203: curproc->handle[0] = f; ! 1204: ! 1205: curproc->handle[1] = f; ! 1206: ! 1207: f->links = 3; ! 1208: ! 1209: ! 1210: ! 1211: f = do_open("U:\\DEV\\MODEM1", O_RDWR, 0, (XATTR *)0); ! 1212: ! 1213: curproc->aux = f; ! 1214: ! 1215: if (has_bconmap) { ! 1216: ! 1217: /* If someone has already done a Bconmap call, then ! 1218: ! 1219: * MODEM1 may no longer be the default ! 1220: ! 1221: */ ! 1222: ! 1223: bconmap(curbconmap); ! 1224: ! 1225: f = curproc->aux; /* bconmap can change curproc->aux */ ! 1226: ! 1227: } ! 1228: ! 1229: if (f) { ! 1230: ! 1231: curproc->handle[2] = f; ! 1232: ! 1233: f->links++; ! 1234: ! 1235: } ! 1236: ! 1237: f = do_open("U:\\DEV\\CENTR", O_RDWR, 0, (XATTR *)0); ! 1238: ! 1239: if (f) { ! 1240: ! 1241: curproc->handle[3] = curproc->prn = f; ! 1242: ! 1243: f->links = 2; ! 1244: ! 1245: } ! 1246: ! 1247: if (f) { ! 1248: ! 1249: f = do_open("U:\\DEV\\MIDI", O_RDWR, 0, (XATTR *)0); ! 1250: ! 1251: curproc->midiin = curproc->midiout = f; ! 1252: ! 1253: f->links = 2; ! 1254: ! 1255: } ! 1256: ! 1257: ! 1258: ! 1259: /* load external file systems */ ! 1260: ! 1261: if (*curpath) { ! 1262: ! 1263: (void)d_setpath(curpath); ! 1264: ! 1265: } ! 1266: ! 1267: ! 1268: ! 1269: load_filesys(); ! 1270: ! 1271: ! 1272: ! 1273: /* note that load_filesys changed the ! 1274: ! 1275: * directory on us!! ! 1276: ! 1277: */ ! 1278: ! 1279: if (*curpath) { ! 1280: ! 1281: (void)d_setpath(curpath); ! 1282: ! 1283: } ! 1284: ! 1285: ! 1286: ! 1287: /* load the configuration file */ ! 1288: ! 1289: load_config(); ! 1290: ! 1291: ! 1292: ! 1293: /* if we want pseudo-drives, set the drive map accordingly */ ! 1294: ! 1295: if (pseudodrives > 0) { ! 1296: ! 1297: *((long *)0x4c2L) |= PSEUDODRVS; ! 1298: ! 1299: }; ! 1300: ! 1301: if (pseudodrives < 2) { /* restore old Rwabs, etc. */ ! 1302: ! 1303: *((long *)0x476L) = (long) old_rwabs.next; ! 1304: ! 1305: *((long *)0x47eL) = (long) old_mediach.next; ! 1306: ! 1307: *((long *)0x472L) = (long) old_getbpb.next; ! 1308: ! 1309: } ! 1310: ! 1311: ! 1312: ! 1313: if (init_env == 0) ! 1314: ! 1315: init_env = (char *)_base->p_env; ! 1316: ! 1317: ! 1318: ! 1319: /* empty environment? Set the PATH variable to the root of the current drive */ ! 1320: ! 1321: if (init_env[0] == 0) { ! 1322: ! 1323: static char path_env[] = "PATH=\0C:\0"; ! 1324: ! 1325: path_env[6] = curproc->curdrv + 'A'; ! 1326: ! 1327: init_env = path_env; ! 1328: ! 1329: } ! 1330: ! 1331: ! 1332: ! 1333: /* run any programs appearing after us in the AUTO folder */ ! 1334: ! 1335: run_auto_prgs(); ! 1336: ! 1337: ! 1338: ! 1339: /* run the initial program */ ! 1340: ! 1341: ! 1342: ! 1343: r = p_exec(0, init_prg, init_tail, init_env); ! 1344: ! 1345: ! 1346: ! 1347: /* if it isn't found, and the user didn't say otherwise, try GEM */ ! 1348: ! 1349: if (r == EFILNF && init_prg == orig_init) { ! 1350: ! 1351: if (!gem_active) { ! 1352: ! 1353: BASEPAGE *bp; int pid; ! 1354: ! 1355: bp = (BASEPAGE *)p_exec(7, (char *)7L, (char *)"\0", init_env); ! 1356: ! 1357: bp->p_tbase = *((long *) 0x4feL ); ! 1358: ! 1359: pid = p_exec(106, (char *)"GEM", bp, 0L); ! 1360: ! 1361: if (pid > 0) { ! 1362: ! 1363: do { ! 1364: ! 1365: r = p_wait3(0, (long *)0); ! 1366: ! 1367: } while(pid != ((r & 0xffff0000) >> 16)); ! 1368: ! 1369: r &= 0x0000ffff; ! 1370: ! 1371: } ! 1372: ! 1373: } else { ! 1374: ! 1375: Cconws("If MiNT is run after GEM starts, you must specify a program\r\n"); ! 1376: ! 1377: Cconws("to run initially in MINT.CNF, with an INIT= line\r\n"); ! 1378: ! 1379: r = 0; ! 1380: ! 1381: } ! 1382: ! 1383: } ! 1384: ! 1385: ! 1386: ! 1387: if (r < 0) { ! 1388: ! 1389: ksprintf(buf, "FATAL: couldn't run %s\r\n", init_prg); ! 1390: ! 1391: Cconws(buf); ! 1392: ! 1393: } ! 1394: ! 1395: ! 1396: ! 1397: if (r) { ! 1398: ! 1399: ksprintf(buf, "exit code: %ld\r\n", r); ! 1400: ! 1401: Cconws(buf); ! 1402: ! 1403: } ! 1404: ! 1405: ! 1406: ! 1407: /* shut down all processes gracefully */ ! 1408: ! 1409: shutdown(); ! 1410: ! 1411: ! 1412: ! 1413: /* put everything back and exit */ ! 1414: ! 1415: restr_intr(); ! 1416: ! 1417: close_filesys(); ! 1418: ! 1419: ! 1420: ! 1421: (void)Super((void *)tosssp); /* gratuitous (void *) for Lattice */ ! 1422: ! 1423: Cconws("leaving MiNT\r\n"); ! 1424: ! 1425: ! 1426: ! 1427: if (curs_off) ! 1428: ! 1429: Cconws("\033f"); /* disable cursor */ ! 1430: ! 1431: ! 1432: ! 1433: zeroexit(); ! 1434: ! 1435: return 0; /* dummy -- this should never be reached */ ! 1436: ! 1437: } ! 1438: ! 1439: ! 1440: ! 1441: ! 1442: ! 1443: /* ! 1444: ! 1445: * cookie jar handling routines. The "cookie jar" is an area of memory ! 1446: ! 1447: * reserved by TOS for TSR's and utility programs; the idea is that ! 1448: ! 1449: * you put a cookie in the jar to notify people of available services. ! 1450: ! 1451: * The BIOS uses the cookie jar in TOS 1.6 and higher; for earlier versions ! 1452: ! 1453: * of TOS, the jar is always empty (unless someone added a cookie before ! 1454: ! 1455: * us; POOLFIX does, for example). ! 1456: ! 1457: * MiNT establishes an entirely new cookie jar (with the old cookies copied ! 1458: ! 1459: * over) and frees it on exit. That's because TSR's run under MiNT ! 1460: ! 1461: * will no longer be accessible after MiNT exits. ! 1462: ! 1463: * MiNT also puts a cookie in the jar, with tag field 'MiNT' (of course) ! 1464: ! 1465: * and with the major version of MiNT in the high byte of the low word, ! 1466: ! 1467: * and the minor version in the low byte. ! 1468: ! 1469: */ ! 1470: ! 1471: ! 1472: ! 1473: void ! 1474: ! 1475: install_cookies() ! 1476: ! 1477: { ! 1478: ! 1479: COOKIE *cookie; ! 1480: ! 1481: int i, ncookies; ! 1482: ! 1483: ! 1484: ! 1485: /* note that init_intr sets oldcookie to the old cookie jar */ ! 1486: ! 1487: ! 1488: ! 1489: ncookies = 0; ! 1490: ! 1491: cookie = oldcookie; ! 1492: ! 1493: if (cookie) { ! 1494: ! 1495: while (cookie->tag.aslong != 0) { ! 1496: ! 1497: /* check for true FPU co-processor */ ! 1498: ! 1499: if (!strncmp(cookie->tag.aschar, "_FPU",4) && ! 1500: ! 1501: (cookie->value >> 16) >= 2) ! 1502: ! 1503: fpu = 1; ! 1504: ! 1505: /* check for _FLK cookie */ ! 1506: ! 1507: else if (!strncmp(cookie->tag.aschar, "_FLK",4)) ! 1508: ! 1509: flk = 1; ! 1510: ! 1511: cookie++; ncookies++; ! 1512: ! 1513: } ! 1514: ! 1515: } ! 1516: ! 1517: ! 1518: ! 1519: /* NOTE: obviously, we can do this only if init_intr is called ! 1520: ! 1521: * _after_ memory, processes, etc. have been initialized ! 1522: ! 1523: */ ! 1524: ! 1525: newcookie = (COOKIE *)kmalloc((ncookies + 16)*sizeof(COOKIE)); ! 1526: ! 1527: assert(newcookie); ! 1528: ! 1529: ! 1530: ! 1531: /* copy the old cookies to the new jar */ ! 1532: ! 1533: ! 1534: ! 1535: for (i = 0; i < ncookies; i++) { ! 1536: ! 1537: newcookie[i] = oldcookie[i]; ! 1538: ! 1539: } ! 1540: ! 1541: ! 1542: ! 1543: /* install MiNT cookie */ ! 1544: ! 1545: strncpy(newcookie[i].tag.aschar, "MiNT", 4); ! 1546: ! 1547: newcookie[i].value = (MAJ_VERSION << 8) | MIN_VERSION; ! 1548: ! 1549: i++; ! 1550: ! 1551: ! 1552: ! 1553: /* install _FLK cookie to indicate that file locking works */ ! 1554: ! 1555: if (!flk) { ! 1556: ! 1557: strncpy(newcookie[i].tag.aschar, "_FLK", 4); ! 1558: ! 1559: newcookie[i].value = 0; ! 1560: ! 1561: i++; ! 1562: ! 1563: } ! 1564: ! 1565: ! 1566: ! 1567: /* the last cookie should have a 0 tag, and a value indicating the number ! 1568: ! 1569: * of slots, total ! 1570: ! 1571: */ ! 1572: ! 1573: ! 1574: ! 1575: newcookie[i].tag.aslong = 0; ! 1576: ! 1577: newcookie[i].value = ncookies+16; ! 1578: ! 1579: ! 1580: ! 1581: *CJAR = newcookie; ! 1582: ! 1583: ! 1584: ! 1585: } ! 1586: ! 1587: ! 1588: ! 1589: /* ! 1590: ! 1591: * get the value of the _MCH cookie, if one exists ! 1592: ! 1593: * this must be done in a separate routine because the machine type ! 1594: ! 1595: * is needed when initializing the bios file system, whereas ! 1596: ! 1597: * install_cookies is not called until everything is installed ! 1598: ! 1599: * In fact, getmch() should be called before *anything* else is ! 1600: ! 1601: * initialized, so that if we find a MiNT cookie already in the ! 1602: ! 1603: * jar we can bail out early. ! 1604: ! 1605: */ ! 1606: ! 1607: ! 1608: ! 1609: static void ! 1610: ! 1611: getmch() ! 1612: ! 1613: { ! 1614: ! 1615: COOKIE *jar; ! 1616: ! 1617: ! 1618: ! 1619: jar = *CJAR; /* CJAR defined in cookie.h */ ! 1620: ! 1621: if (jar) { ! 1622: ! 1623: while (jar->tag.aslong != 0) { ! 1624: ! 1625: /* check for machine type */ ! 1626: ! 1627: if (!strncmp(jar->tag.aschar, "_MCH",4)) { ! 1628: ! 1629: mch = jar->value; ! 1630: ! 1631: } else if (!strncmp(jar->tag.aschar, "_CPU", 4)) { ! 1632: ! 1633: mcpu = jar->value; ! 1634: ! 1635: if (mcpu == 10) ! 1636: ! 1637: m68010 = 1; ! 1638: ! 1639: } else if (!strncmp(jar->tag.aschar, "MiNT",4)) { ! 1640: ! 1641: Cconws("MiNT is already installed!!\r\n"); ! 1642: ! 1643: (void)Super((void *)tosssp); ! 1644: ! 1645: Pterm(2); ! 1646: ! 1647: } ! 1648: ! 1649: jar++; ! 1650: ! 1651: } ! 1652: ! 1653: } ! 1654: ! 1655: } ! 1656: ! 1657: ! 1658: ! 1659: /* ! 1660: ! 1661: * routines for reading the configuration file ! 1662: ! 1663: * we allow the following commands in the file: ! 1664: ! 1665: * # anything -- comment ! 1666: ! 1667: * INIT=file -- specify boot program ! 1668: ! 1669: * cd dir -- change directory/drive ! 1670: ! 1671: * ren file1 file2 -- rename a file ! 1672: ! 1673: * sln file1 file2 -- create a symbolic link ! 1674: ! 1675: * echo message -- print a message on the screen ! 1676: ! 1677: * setenv var value -- set an environment variable ! 1678: ! 1679: * ! 1680: ! 1681: * BUG: if you use setenv in mint.cnf, *none* of the original environment ! 1682: ! 1683: * gets passed to children. This is rarely a problem if mint.prg is ! 1684: ! 1685: * in the auto folder. ! 1686: ! 1687: */ ! 1688: ! 1689: ! 1690: ! 1691: extern short bconbdev, bconbsiz; /* from bios.c */ ! 1692: ! 1693: ! 1694: ! 1695: static void ! 1696: ! 1697: doset(name, val) ! 1698: ! 1699: char *name, *val; ! 1700: ! 1701: { ! 1702: ! 1703: char *t; ! 1704: ! 1705: ! 1706: ! 1707: if (!strcmp(name, "INIT")) { ! 1708: ! 1709: t = kmalloc(strlen(val)+1); ! 1710: ! 1711: if (!t) return; ! 1712: ! 1713: strcpy(t, val); ! 1714: ! 1715: init_prg = t; ! 1716: ! 1717: while (*t && !isspace(*t)) t++; ! 1718: ! 1719: /* get the command tail, too */ ! 1720: ! 1721: if (*t) { ! 1722: ! 1723: *t++ = 0; ! 1724: ! 1725: strncpy(init_tail+1, t, 125); ! 1726: ! 1727: init_tail[0] = strlen(init_tail+1); ! 1728: ! 1729: } ! 1730: ! 1731: return; ! 1732: ! 1733: } ! 1734: ! 1735: if (!strcmp(name, "CON")) { ! 1736: ! 1737: FILEPTR *f; ! 1738: ! 1739: int i; ! 1740: ! 1741: ! 1742: ! 1743: f = do_open(val, O_RDWR, 0, (XATTR *)0); ! 1744: ! 1745: if (f) { ! 1746: ! 1747: for (i = -1; i < 2; i++) { ! 1748: ! 1749: do_close(curproc->handle[i]); ! 1750: ! 1751: curproc->handle[i] = f; ! 1752: ! 1753: f->links++; ! 1754: ! 1755: } ! 1756: ! 1757: f->links--; /* correct for overdoing it */ ! 1758: ! 1759: } ! 1760: ! 1761: return; ! 1762: ! 1763: } ! 1764: ! 1765: if (!strcmp(name, "PRN")) { ! 1766: ! 1767: FILEPTR *f; ! 1768: ! 1769: ! 1770: ! 1771: f = do_open(val, O_RDWR|O_CREAT|O_TRUNC, 0, (XATTR *)0); ! 1772: ! 1773: if (f) { ! 1774: ! 1775: do_close(curproc->handle[2]); ! 1776: ! 1777: do_close(curproc->prn); ! 1778: ! 1779: curproc->prn = curproc->handle[2] = f; ! 1780: ! 1781: f->links = 2; ! 1782: ! 1783: } ! 1784: ! 1785: return; ! 1786: ! 1787: } ! 1788: ! 1789: if (!strcmp(name, "BIOSBUF")) { ! 1790: ! 1791: if (*val == 'n' || *val == 'N') { ! 1792: ! 1793: if (bconbsiz) bflush(); ! 1794: ! 1795: bconbdev = -1; ! 1796: ! 1797: } ! 1798: ! 1799: return; ! 1800: ! 1801: } ! 1802: ! 1803: if (!strcmp(name, "PSEUDODRIVES")) { ! 1804: ! 1805: if (*val == 'n' || *val == 'N') { ! 1806: ! 1807: pseudodrives = 0; ! 1808: ! 1809: } else if (*val == 'm' || *val == 'M') { ! 1810: ! 1811: pseudodrives = 1; ! 1812: ! 1813: } ! 1814: ! 1815: return; ! 1816: ! 1817: } ! 1818: ! 1819: if (!strcmp(name, "DEBUG_LEVEL")) { ! 1820: ! 1821: extern int debug_level; ! 1822: ! 1823: if (*val >= '0' && *val <= '9') debug_level = atoi(val); ! 1824: ! 1825: else ALERT("Bad arg to \"DEBUG_LEVEL\" in cnf file"); ! 1826: ! 1827: return; ! 1828: ! 1829: } ! 1830: ! 1831: if (!strcmp(name, "DEBUG_DEVNO")) { ! 1832: ! 1833: extern int out_device; ! 1834: ! 1835: if (*val >= '0' && *val <= '9') out_device= atoi(val); ! 1836: ! 1837: else ALERT("Bad arg to \"DEBUG_DEVNO\" in cnf file"); ! 1838: ! 1839: return; ! 1840: ! 1841: } ! 1842: ! 1843: ! 1844: ! 1845: #ifdef FASTTEXT ! 1846: ! 1847: if (!strcmp(name, "HARDSCROLL")) { ! 1848: ! 1849: int i = 0; ! 1850: ! 1851: extern int hardscroll; ! 1852: ! 1853: ! 1854: ! 1855: i = *val++; ! 1856: ! 1857: if (i < '0' || i > '9') return; ! 1858: ! 1859: hardscroll = i-'0'; ! 1860: ! 1861: i = *val; ! 1862: ! 1863: if (i < '0' || i > '9') return; ! 1864: ! 1865: hardscroll = 10*hardscroll + i - '0'; ! 1866: ! 1867: return; ! 1868: ! 1869: } ! 1870: ! 1871: #endif ! 1872: ! 1873: ALERT("Unknown variable `%s'", name); ! 1874: ! 1875: } ! 1876: ! 1877: ! 1878: ! 1879: /* Execute a line from the config file */ ! 1880: ! 1881: static void ! 1882: ! 1883: do_line(line) ! 1884: ! 1885: char *line; ! 1886: ! 1887: { ! 1888: ! 1889: char *cmd, *arg1, *arg2; ! 1890: ! 1891: char *newenv; ! 1892: ! 1893: char *t; ! 1894: ! 1895: int i; ! 1896: ! 1897: ! 1898: ! 1899: while (*line == ' ') line++; ! 1900: ! 1901: if (*line == '#') return; /* ignore comments */ ! 1902: ! 1903: if (!*line) return; /* and also blank lines */ ! 1904: ! 1905: ! 1906: ! 1907: cmd = line; ! 1908: ! 1909: /* check for variable assignments (e.g. INIT=, etc.) */ ! 1910: ! 1911: /* ! 1912: ! 1913: * AGK: note we check for spaces whilst scanning so that an environment ! 1914: ! 1915: * variable may include an =, this has the unfortunate side effect that ! 1916: ! 1917: * the '=' _has_ to be concatenated to the variable name (INIT etc.) ! 1918: ! 1919: */ ! 1920: ! 1921: for (t = cmd; *t && *t != ' '; t++) { ! 1922: ! 1923: if (*t == '=') { ! 1924: ! 1925: *t++ = 0; ! 1926: ! 1927: doset(cmd, t); ! 1928: ! 1929: return; ! 1930: ! 1931: } ! 1932: ! 1933: } ! 1934: ! 1935: ! 1936: ! 1937: /* OK, assume a regular command; break it up into 'cmd', 'arg1', arg2' */ ! 1938: ! 1939: ! 1940: ! 1941: while (*line && *line != ' ') line++; ! 1942: ! 1943: if (*line == ' ') { ! 1944: ! 1945: *line++ = 0; ! 1946: ! 1947: while (*line == ' ') line++; ! 1948: ! 1949: } ! 1950: ! 1951: ! 1952: ! 1953: if (!strcmp(cmd, "echo")) { ! 1954: ! 1955: c_conws(line); c_conws("\r\n"); ! 1956: ! 1957: return; ! 1958: ! 1959: } ! 1960: ! 1961: arg1 = line; ! 1962: ! 1963: while (*line && *line != ' ') line++; ! 1964: ! 1965: if (*line) { ! 1966: ! 1967: *line++ = 0; ! 1968: ! 1969: while (*line == ' ') line++; ! 1970: ! 1971: } ! 1972: ! 1973: if (!strcmp(cmd, "cd")) { ! 1974: ! 1975: int drv; ! 1976: ! 1977: (void)d_setpath(arg1); ! 1978: ! 1979: drv = toupper(*arg1) - 'A'; ! 1980: ! 1981: if (arg1[1] == ':') (void)d_setdrv(drv); ! 1982: ! 1983: return; ! 1984: ! 1985: } ! 1986: ! 1987: if (!strcmp(cmd, "exec")) { ! 1988: ! 1989: static char cmdline[128]; ! 1990: ! 1991: int i; ! 1992: ! 1993: ! 1994: ! 1995: i = strlen(line); ! 1996: ! 1997: if (i > 126) i = 126; ! 1998: ! 1999: cmdline[0] = i; ! 2000: ! 2001: strncpy(cmdline+1, line, i); ! 2002: ! 2003: cmdline[i+1] = 0; ! 2004: ! 2005: i = p_exec(0, arg1, cmdline, init_env); ! 2006: ! 2007: if (i == -33) { ! 2008: ! 2009: ALERT("%s: file not found", arg1); ! 2010: ! 2011: } else if (i < 0) { ! 2012: ! 2013: ALERT("%s: error while attempting to execute", arg1); ! 2014: ! 2015: } ! 2016: ! 2017: return; ! 2018: ! 2019: } ! 2020: ! 2021: if (!strcmp(cmd, "setenv")) { ! 2022: ! 2023: if (strlen(arg1) + strlen(line) + 4 + (env_ptr - init_env) > ! 2024: ! 2025: env_len) { ! 2026: ! 2027: newenv = umalloc(env_len + 1024L); ! 2028: ! 2029: t = init_env; ! 2030: ! 2031: env_ptr = newenv; ! 2032: ! 2033: for (i = 0; i < env_len; i++) ! 2034: ! 2035: *env_ptr++ = *t++; ! 2036: ! 2037: env_len += 1024; ! 2038: ! 2039: if (init_env) ! 2040: ! 2041: ufree(init_env); ! 2042: ! 2043: init_env = newenv; ! 2044: ! 2045: } ! 2046: ! 2047: while (*arg1) { ! 2048: ! 2049: *env_ptr++ = *arg1++; env_len++; ! 2050: ! 2051: } ! 2052: ! 2053: *env_ptr++ = '='; ! 2054: ! 2055: while (*line) { ! 2056: ! 2057: *env_ptr++ = *line++; env_len++; ! 2058: ! 2059: } ! 2060: ! 2061: *env_ptr++ = 0; ! 2062: ! 2063: *env_ptr = 0; ! 2064: ! 2065: return; ! 2066: ! 2067: } ! 2068: ! 2069: ! 2070: ! 2071: arg2 = line; ! 2072: ! 2073: while (*line && *line != ' ') line++; ! 2074: ! 2075: if (*line) { ! 2076: ! 2077: *line++ = 0; ! 2078: ! 2079: } ! 2080: ! 2081: if (!strcmp(cmd, "sln")) { ! 2082: ! 2083: (void)f_symlink(arg1, arg2); ! 2084: ! 2085: return; ! 2086: ! 2087: } ! 2088: ! 2089: if (!strcmp(cmd, "ren")) { ! 2090: ! 2091: (void)f_rename(0, arg1, arg2); ! 2092: ! 2093: return; ! 2094: ! 2095: } ! 2096: ! 2097: ALERT("syntax error in mint.cnf"); ! 2098: ! 2099: } ! 2100: ! 2101: ! 2102: ! 2103: #define BUF 512 ! 2104: ! 2105: #define LINE 256 ! 2106: ! 2107: ! 2108: ! 2109: void ! 2110: ! 2111: load_config() ! 2112: ! 2113: { ! 2114: ! 2115: int fd; ! 2116: ! 2117: long r; ! 2118: ! 2119: char buf[BUF+1], c; ! 2120: ! 2121: char line[LINE+1]; ! 2122: ! 2123: char *from; ! 2124: ! 2125: int count = 0; ! 2126: ! 2127: ! 2128: ! 2129: TRACE("reading configuration file"); ! 2130: ! 2131: fd = f_open("mint.cnf", 0); ! 2132: ! 2133: if (fd < 0) ! 2134: ! 2135: fd = f_open("\\mint\\mint.cnf", 0); ! 2136: ! 2137: if (fd < 0) return; ! 2138: ! 2139: buf[BUF] = 0; ! 2140: ! 2141: from = &buf[BUF]; ! 2142: ! 2143: line[LINE] = 0; ! 2144: ! 2145: ! 2146: ! 2147: for(;;) { ! 2148: ! 2149: c = *from++; ! 2150: ! 2151: if (!c) { ! 2152: ! 2153: r = f_read(fd, (long)BUF, buf); ! 2154: ! 2155: if (r <= 0) break; ! 2156: ! 2157: buf[r] = 0; ! 2158: ! 2159: from = buf; ! 2160: ! 2161: } else if (c == '\r') { ! 2162: ! 2163: continue; ! 2164: ! 2165: } else if (c == '\n') { ! 2166: ! 2167: line[count] = 0; ! 2168: ! 2169: do_line(line); ! 2170: ! 2171: count = 0; ! 2172: ! 2173: } else { ! 2174: ! 2175: if (count < LINE) { ! 2176: ! 2177: line[count++] = c; ! 2178: ! 2179: } ! 2180: ! 2181: } ! 2182: ! 2183: } ! 2184: ! 2185: f_close(fd); ! 2186: ! 2187: } ! 2188: ! 2189: ! 2190: ! 2191: /* ! 2192: ! 2193: * run programs in the AUTO folder that appear after MINT.PRG ! 2194: ! 2195: * some things to watch out for: ! 2196: ! 2197: * (1) make sure GEM isn't active ! 2198: ! 2199: * (2) make sure there really is a MINT.PRG in the auto folder ! 2200: ! 2201: */ ! 2202: ! 2203: ! 2204: ! 2205: /* ! 2206: ! 2207: * some global variables used to see if GEM is active ! 2208: ! 2209: */ ! 2210: ! 2211: static short aes_intout[64]; ! 2212: ! 2213: static short aes_dummy[64]; ! 2214: ! 2215: static short aes_globl[15]; ! 2216: ! 2217: static short aes_cntrl[6] = { 10, 0, 1, 0, 0 }; ! 2218: ! 2219: ! 2220: ! 2221: short *aes_pb[6] = { aes_cntrl, aes_globl, aes_dummy, aes_intout, ! 2222: ! 2223: aes_dummy, aes_dummy }; ! 2224: ! 2225: ! 2226: ! 2227: /* check for whether GEM is active; remember, this *must* be done in ! 2228: ! 2229: * user mode ! 2230: ! 2231: */ ! 2232: ! 2233: ! 2234: ! 2235: static int ! 2236: ! 2237: check_for_gem() ! 2238: ! 2239: { ! 2240: ! 2241: call_aes(aes_pb); /* does an appl_init */ ! 2242: ! 2243: return aes_globl[0]; ! 2244: ! 2245: } ! 2246: ! 2247: ! 2248: ! 2249: static void ! 2250: ! 2251: run_auto_prgs() ! 2252: ! 2253: { ! 2254: ! 2255: DTABUF *dta; ! 2256: ! 2257: long r; ! 2258: ! 2259: static char pathspec[32] = "\\AUTO\\"; ! 2260: ! 2261: short runthem = 0; /* set to 1 after we find MINT.PRG */ ! 2262: ! 2263: ! 2264: ! 2265: /* if the AES is running, don't check AUTO */ ! 2266: ! 2267: ! 2268: ! 2269: if (gem_active) { ! 2270: ! 2271: return; ! 2272: ! 2273: } ! 2274: ! 2275: ! 2276: ! 2277: /* OK, now let's run through \\AUTO looking for ! 2278: ! 2279: * programs... ! 2280: ! 2281: */ ! 2282: ! 2283: dta = (DTABUF *)f_getdta(); ! 2284: ! 2285: r = f_sfirst("\\AUTO\\*.PRG", 0); ! 2286: ! 2287: while (r >= 0) { ! 2288: ! 2289: if (!strcmp(dta->dta_name, "MINT.PRG")) ! 2290: ! 2291: runthem = 1; ! 2292: ! 2293: else if (runthem) { ! 2294: ! 2295: strcpy(pathspec+6, dta->dta_name); ! 2296: ! 2297: (void)p_exec(0, pathspec, (char *)"", init_env); ! 2298: ! 2299: } ! 2300: ! 2301: r = f_snext(); ! 2302: ! 2303: } ! 2304: ! 2305: } ! 2306:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.