/****************************************************************/ /* */ /* main.c */ /* DOS-C */ /* */ /* Main IPL Functions */ /* */ /* Copyright (c) 1991 */ /* Pasquale J. Villani */ /* All Rights Reserved */ /* */ /* This file is part of DOS-C. */ /* */ /* DOS-C is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version */ /* 2, or (at your option) any later version. */ /* */ /* DOS-C is distributed in the hope that it will be useful, but */ /* WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ /* the GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public */ /* License along with DOS-C; see the file COPYING. If not, */ /* write to the Free Software Foundation, 675 Mass Ave, */ /* Cambridge, MA 02139, USA. */ /****************************************************************/ #define MAIN #include "../../hdr/portab.h" #include "globals.h" /* $Logfile: C:/dos-c/src/ipl/main.c_v $ */ #ifndef IPL static BYTE *mainRcsId = "$Header: C:/dos-c/src/ipl/main.c_v 1.2 01 Sep 1995 17:44:38 patv $"; #endif /* * $Log: C:/dos-c/src/ipl/main.c_v $ * * Rev 1.2 01 Sep 1995 17:44:38 patv * First GPL release. * * Rev 1.1 30 Jul 1995 20:48:10 patv * Eliminated version strings in ipl * * Rev 1.0 02 Jul 1995 8:25:52 patv * Initial revision. * */ COUNT ver(), help(), dir(), type(), prompt(), boot_kernel(), mon86(); COUNT unknown(); VOID init_ipl(), signon(), ipl(); struct table { BYTE *entry; COUNT (*func)(); }; struct table commands[] = { {"?", help}, {"help", help}, {"ver", ver}, {"dir", dir}, {"type", type}, {"prompt", prompt}, {"boot", boot_kernel}, {"", unknown} }; static COUNT BlockIndex = 0; static BYTE *tail; /* an MS-DOS wart emulation */ static BYTE pr_string[LINESIZE]; static BYTE *dflt_pr_string = "\n$n$g "; static BYTE *psignon = "\nDOS-C IPL v%d.%02d\n"; BYTE *id = "wb2gbf"; static BYTE *szDefaultKernel = "kernel.exe"; /* function protypes */ #ifdef PROTO VOID signon(VOID); VOID init_ipl(VOID); VOID init_device(struct dhdr FAR *); struct dhdr FAR *link_dhdr(struct dhdr FAR *, struct dhdr FAR *); COUNT boot_kernel(VOID); VOID ipl(VOID); struct table *lookup(struct table *, BYTE *); COUNT unknown(VOID); COUNT ver(VOID); COUNT help(VOID); COUNT type(COUNT, BYTE *[]); COUNT dir(COUNT, BYTE *[]); #else VOID signon(); VOID init_ipl(); VOID init_device(); struct dhdr FAR *link_dhdr(); COUNT boot_kernel(); VOID ipl(); struct table *lookup(); COUNT unknown(); COUNT ver(); COUNT help(); COUNT type(); COUNT dir(); #endif VOID init_ipl(), signon(), ipl(); VOID main() { BYTE szDrive[2] = { '@', 0 }; #ifdef DEBUG MarkStack(); printf("\n*** IPL started ***\nStack at 0x%04x:%04x\n", MarkSS, MarkSP); #endif init_ipl(); #ifdef DEBUG MarkStack(); printf("\n*** IPL initialized ***\nStack at 0x%04x:%04x\n", MarkSS, MarkSP); #endif signon(); szDrive[0] += BootDrive; printf("\nIPL Booting %s from drive %s\n", szDefaultKernel, szDrive); boot_kernel(); ipl(); } static VOID signon() { printf(psignon, MAJOR_RELEASE, MINOR_RELEASE); } static VOID init_ipl() { REG struct dhdr FAR *dhp = (struct dhdr FAR *)&nul_dev; REG COUNT i; struct dhdr FAR *link_dhdr(); /* Initialize driver chain */ #ifdef DEBUG MarkStack(); printf("Initialize driver chain\nStack at 0x%04x:%04x\n", MarkSS, MarkSP); printf("Device driver chain starts at 0x%04x:%04x\n", FP_SEG(dhp), FP_OFF(dhp)); #endif dhp = link_dhdr(dhp, (struct dhdr FAR *)&con_dev); dhp = link_dhdr(dhp, (struct dhdr FAR *)&blk_dev); syscon = (struct dhdr FAR *)&con_dev; /* Initialize the screen handler for backspaces */ #ifdef DEBUG MarkStack(); printf("Initialize the screen handler for backspaces\n"); #endif scr_pos = 0; /* Initialize the file tables */ #ifdef DEBUG printf("Initialize the file tables\n"); #endif for(i = 0; i < NFILES; i++) f_nodes[i].f_count = 0; /* Log-in the default drive. */ default_drive = 0; /* Initialzie the current directory structures */ for(i = 0; i < NDEVS; i++) scopy("\\", blk_devices[i].dpb_path); /* Initialze the disk buffer management functions */ init_buffers(); /* Now to initialize all special flags, etc. */ mem_access_mode = FIRST_FIT; break_ena = TRUE; verify_ena = FALSE; InDOS = 0; version_flags = 0; /* Figure out 'A' or 'C' drive */ if(BootDrive != 0) BootDrive = 3; else BootDrive = 1; } VOID init_device(dhp) struct dhdr FAR *dhp; { request rq; rq.r_unit = 0; rq.r_status = 0; rq.r_command = C_INIT; rq.r_length = sizeof(request); #ifdef DEBUG printf("init_device: Initializing device with packet at 0x%04x:%04x\n", FP_SEG(&rq), FP_OFF(&rq)); #endif execrh((request FAR *)&rq, dhp); #ifdef DEBUG printf("init_device: execrh returned with status = 0x%04x\n", rq.r_status); #endif /* check for a block device and update device control block */ if(!(dhp -> dh_attr & ATTR_CHAR) && (rq.r_nunits != 0)) { REG COUNT Index; for(Index = 0; Index < rq.r_nunits; Index++, BlockIndex++) { #ifdef DEBUG printf("init_device: building blk_devices[%d]\n", lastdrive); #endif blk_devices[lastdrive].dpb_unit = lastdrive; blk_devices[lastdrive].dpb_subunit = Index; blk_devices[lastdrive].dpb_device = dhp; blk_devices[lastdrive].dpb_flags = M_CHANGED; ++lastdrive; } } #ifdef DEBUG printf("init_device: complete.\n"); #endif } struct dhdr FAR *link_dhdr(lp, dhp) struct dhdr FAR *dhp, FAR *lp; { lp -> dh_next = dhp; #ifdef DEBUG printf("link_dhdr: initializing device at 0x%04x:%04x\n", FP_SEG(dhp), FP_OFF(dhp)); #endif init_device(dhp); #ifdef DEBUG printf("link_dhdr: init_device complete\n"); #endif return dhp; } static COUNT boot_kernel() { COUNT rc; exec_blk exb; /* Test for user break */ if(con_break()) return TRUE; printf("\nBooting DOS-C "); #ifndef IPLDBG /* If not - initialize the exec block */ /* and go for it! */ exb.exec.env_seg = 0; exb.exec.cmd_line = ""; exb.exec.fcb_1 = exb.exec.fcb_2 = (fcb far *)0; rc = DosExec(P_WAIT, (exec_blk far *)&exb, (BYTE far *)szDefaultKernel); /* if we're here, unable to load the kernel, so */ /* give the user the reason and exit */ printf("IPL cannot load kernel\n\n"); switch(rc) { case DE_FILENOTFND: printf("File %s not found\n", szDefaultKernel); break; case DE_INVLDDATA: printf("Inavlid data\n"); break; default: printf("Unknown reason (rc = %d)\n", rc); break; } #endif return FALSE; } static VOID ipl() { register struct table *p; register BYTE *lp; struct table *lookup(); BYTE *scan(), *skipwh(); static COUNT argc; static BYTE *argv[16]; static BYTE args[16][LINESIZE]; scopy(dflt_pr_string, pr_string); for(;;) { put_prompt(pr_string); kb_buf.kb_size = LINESIZE - 1; kb_buf.kb_count = 0; sti((keyboard far *)&kb_buf); kb_buf.kb_buf[kb_buf.kb_count] = '\0'; for(argc = 0; argc < 16; argc++) { argv[argc] = (BYTE *)0; args[argc][0] = '\0'; } lp = scan(kb_buf.kb_buf, args[0]); argv[0] = args[0]; /* this kludge is for an MS-DOS wart emulation */ tail = skipwh(lp); for(argc = 1; ; argc++) { lp = scan(lp, args[argc]); if(*args[argc] == '\0') break; else argv[argc] = args[argc]; } if(*argv[0] != '\0') { p = lookup(commands, argv[0]); (*(p -> func))(argc, argv); } } } COUNT prompt(argc, argv) COUNT argc; BYTE *argv[]; { if(argc == 1) scopy(dflt_pr_string, pr_string); else { pr_string[0] = '\n'; /* should be */ /* scopy(argv[1], &pr_string[1]); */ /* but to emulate an MS-DOS wart, is */ scopy(tail, &pr_string[1]); } return TRUE; } /* put_prompt - print prompt obeying $x commands */ COUNT put_prompt(fmt) register BYTE *fmt; { register BYTE c; BYTE *s; while ((c = *fmt++) != '\0') { if (c != '$') { put_console(c); continue; } switch (c = *fmt++) { case 'p': put_console('A' + default_drive); put_console(':'); for(s = blk_devices[default_drive].dpb_path; *s != '\0'; s++) put_console(*s); continue; case 'n': put_console('A' + default_drive); continue; case 'g': put_console('>'); continue; case 'l': put_console('<'); continue; case 'b': put_console('|'); continue; case 'e': put_console('='); continue; default: put_console(c); continue; } } return TRUE; } struct table *lookup(p, token) struct table *p; BYTE *token; { while(*(p -> entry) != '\0') { if(strcmp(p -> entry, token) == 0) break; else ++p; } return p; } COUNT unknown() { printf("\nBad command or file name"); return FALSE; } COUNT ver() { printf(psignon, MAJOR_RELEASE, MINOR_RELEASE); return TRUE; } COUNT help() { printf("\nSorry, help is not available"); return TRUE; } COUNT type(argc, argv) COUNT argc; BYTE *argv[]; { COUNT fd; BYTE c; if(argc != 2) { printf("\nInvalid number of parameters\n"); return FALSE; } if((fd = dos_open((BYTE far *)argv[1], 0)) < 0) { printf("\nFile not found"); return FALSE; } else printf("\n"); while(dos_read(fd, (BYTE far *)&c, 1) == 1) printf("%c", c); dos_close(fd); return TRUE; } COUNT dir(argc, argv) COUNT argc; BYTE *argv[]; { REG struct f_node *fnp; BYTE buf[13]; COUNT count = 0; if(argc == 1) { if((fnp = dir_open((BYTE FAR *)".")) == (struct f_node *)0) goto quit; } else { if((fnp = dir_open((BYTE FAR *)argv[1])) == (struct f_node *)0) goto quit; } while(dir_read(fnp) == sizeof(struct dirent)) { if(fnp -> f_dir.dir_name[0] != '\0' && fnp -> f_dir.dir_name[0] != DELETED) { WORD hour = TM_HOUR(fnp -> f_dir.dir_time); bcopy(fnp -> f_dir.dir_name, &buf[0], 8); buf[8] = ' '; bcopy(fnp -> f_dir.dir_ext, &buf[9], 3); buf[12] = '\0'; printf("\n %s %-10ld %-2d-%-02d-%-02d %-2d:%-02d%c", buf, fnp -> f_dir.dir_size, DT_MONTH(fnp -> f_dir.dir_date), DT_DAY(fnp -> f_dir.dir_date), (DT_YEAR(fnp -> f_dir.dir_date) + 1980) % 100, hour > 12 ? hour - 12 : (hour == 0) ? 12 : hour, TM_MIN(fnp -> f_dir.dir_time), hour >= 12 ? 'p' : 'a'); ++count; } } printf("\n%-10d file(s)\n", count); quit: dir_close(fnp); return TRUE; }