diff -Nru comcom32-0.1~alpha2-155/command.c comcom32-0.1~alpha2-161/command.c --- comcom32-0.1~alpha2-155/command.c 2021-06-21 10:47:51.000000000 +0000 +++ comcom32-0.1~alpha2-161/command.c 2021-08-15 23:48:46.000000000 +0000 @@ -2,7 +2,9 @@ * COMMAND.COM-compatible command processor for DOS. * * Copyright (C) 1997, CENTROID CORPORATION, HOWARD, PA 16841 - * Copyright (C) Allen S. Cheung (allencheung@fastmail.ca) + * Copyright (C) Allen S. Cheung (RIP) + * Copyright (C) 2005-2006 FreeDOS-32 project + * Copyright (C) 2018-2021 stsp, dosemu2 project * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -160,6 +162,7 @@ static char for_var; static const char *for_val; static int exiting; +static int break_on; /* * File attribute constants @@ -176,6 +179,8 @@ static void perform_set(const char *arg); static void list_cmds(void); //static void perform_unimplemented_cmd(void); +static void set_env_seg(void); +static void set_env_sel(void); static int installable_command_check(const char *cmd, const char *tail) { @@ -2255,6 +2260,21 @@ puts(cmd_args); } +static void perform_break(const char *arg) + { + if (stricmp(arg, "off") == 0) + break_on = false; + else if (stricmp(arg, "on") == 0) + break_on = true; + else if (arg[0] == '\0') + printf("BREAK is %s\n", break_on ? "on" : "off"); + else + { + cprintf("Syntax error\r\n"); + reset_batfile_call_stack(); + } + } + static void perform_echo_dot(const char *arg) { if (arg[0] == '\0') @@ -2666,6 +2686,7 @@ #ifdef __DJGPP__ __djgpp_exception_toggle(); #endif + set_env_seg(); /* prepend command tail with space */ alen = strlen(cmd_args) + 1; if (alen >= MAX_CMD_BUFLEN) @@ -2680,6 +2701,7 @@ cprintf("Error: unable to execute %s\r\n", full_cmd); else error_level = rc & 0xff; + set_env_sel(); #ifdef __DJGPP__ __djgpp_exception_toggle(); #endif @@ -3146,6 +3168,12 @@ else { char *s; + int is_p = 0; + if (strnicmp(cmd_switch,"/p", 1) == 0) + { + is_p++; + advance_cmd_arg(); + } var_name = cmd_args; if (strlen(var_name) == 0) { @@ -3161,10 +3189,29 @@ s++; } strupr(vname); - if (!s || !*s) - err = unsetenv(vname); + if (is_p) + { + char buf[128]; + char *p; + cputs(s); + p = fgets(buf, sizeof(buf), stdin); + if (p) + { + p = strpbrk(buf, "\r\n"); + if (p) + *p = '\0'; + err = setenv(vname, buf, 1); + } + else + err = -1; + } else - err = setenv(vname, s, 1); + { + if (!s || !*s) + err = unsetenv(vname); + else + err = setenv(vname, s, 1); + } free(vname); if (err != 0) { @@ -3387,6 +3434,7 @@ static struct built_in_cmd cmd_table[] = { {"attrib", perform_attrib, "", "set file attributes"}, + {"break", perform_break, "", "set ^Break handling"}, {"call", perform_call, "", "call batch file"}, {"cd", perform_cd, "", "change directory"}, {"chdir", perform_cd, "", "change directory"}, @@ -3810,6 +3858,21 @@ char name[8]; /* 8 */ } __attribute__((packed)); +static unsigned short env_selector; +static unsigned short env_segment; + +static void set_env_seg(void) +{ + unsigned short psp = _stubinfo->psp_selector; + movedata(_my_ds(), (unsigned)&env_segment, psp, 0x2c, 2); +} + +static void set_env_sel(void) +{ + unsigned short psp = _stubinfo->psp_selector; + movedata(_my_ds(), (unsigned)&env_selector, psp, 0x2c, 2); +} + static unsigned get_env_size(void) { unsigned short psp = _stubinfo->psp_selector; @@ -3835,6 +3898,9 @@ dosmemget(env_addr - sizeof(mcb), sizeof(mcb), &mcb); __dpmi_set_segment_limit(env_sel, mcb.size * 16 - 1); } + + env_selector = env_sel; + env_segment = env_addr >> 4; } static unsigned long psp_addr; @@ -3859,16 +3925,90 @@ dosmemput(&orig_psp_seg, 2, psp_addr + 0x16); } -static void unlink_umb(void) +static void link_umb(int on) { __dpmi_regs r = {}; r.x.ax = 0x5803; - r.x.bx = 0; /* set UMB link off */ + r.x.bx = on; __dpmi_int(0x21, &r); + if (on) { + r.x.ax = 0x5801; + r.x.bx = 0x80; + __dpmi_int(0x21, &r); + } } -int main(int argc, char *argv[], char *envp[]) +unsigned short ss; +unsigned short ds; +char cstack[0x10000]; +int on_cstack; + +int do_int23(void); +int do_int23(void) +{ + return break_on; +} + +asm( + ".global _my_int23_handler\n" + "_my_int23_handler:\n" + "pusha\n" + "push %ds\n" + "mov %cs:_ds, %eax\n" + "mov %eax, %ds\n" + "xorl %eax, %eax\n" + "cmpl _on_cstack, %eax\n" + "jnz 2f\n" + "incl _on_cstack\n" + "mov %ss, %esi\n" + "mov %esp, %edi\n" + "pushl _ss\n" + "lea _cstack+0x10000, %edx\n" + "push %edx\n" + "lss (%esp), %esp\n" + "push %esi\n" + "push %edi\n" + "call _do_int23\n" + "lss (%esp), %esp\n" + "decl _on_cstack\n" + "5:\n" + "pop %ds\n" + "or %eax, %eax\n" + "jnz 1f\n" + "popa\n" + "iret\n" + "1:\n" + "popa\n" + "stc\n" + "lret\n" + "2:\n" + "call _do_int23\n" + "jmp 5b\n" +); +extern void my_int23_handler(void); + +static void setup_break_handling(void) +{ + __dpmi_regs r = {}; + __dpmi_paddr pa; + __djgpp_set_ctrl_c(0); // disable SIGINT on ^C + _go32_want_ctrl_break(1); // disable SIGINT on ^Break + + r.x.ax = 0x3301; // set break handling + r.x.dx = 1; // to "on" + __dpmi_int(0x21, &r); + + ss = _my_ss(); + ds = _my_ds(); + pa.selector = _my_cs(); + pa.offset32 = (uintptr_t)my_int23_handler; + __dpmi_set_protected_mode_interrupt_vector(0x23, &pa); + + break_on = true; +} + +int main(int argc, char *argv[], char *envp[]) { int a; char *cmd_path; @@ -3882,14 +4022,13 @@ // reset fpu _clear87(); _fpreset(); - unlink_umb(); // in case we loaded with shellhigh or lh + link_umb(0); // in case we loaded with shellhigh or lh set_env_size(); #ifdef __spawn_leak_workaround __spawn_flags &= ~__spawn_leak_workaround; #endif - __djgpp_set_ctrl_c(0); // disable SIGINT on ^C - _go32_want_ctrl_break(1); // disable SIGINT on ^Break + setup_break_handling(); // unbuffer stdin and stdout setbuf(stdin, NULL); @@ -3915,7 +4054,7 @@ if (strnicmp(argv[a], "/E:", 3) == 0) { unsigned int env_size; - int seg, sel, old_sel; + int seg, sel; unsigned int old_size = get_env_size(); if (argv[a][3] == '+') @@ -3925,15 +4064,23 @@ env_size &= ~0xf; if (env_size > old_size) { + link_umb(1); seg = __dpmi_allocate_dos_memory(env_size >> 4, &sel); + link_umb(0); if (seg != -1) { unsigned short psp = _stubinfo->psp_selector; - movedata(psp, 0x2c, _my_ds(), (unsigned)&old_sel, 2); movedata(_my_ds(), (unsigned)&sel, psp, 0x2c, 2); /* copy old content to preserve tail (and maybe COMSPEC) */ - movedata(old_sel, 0, sel, 0, old_size); - __dpmi_free_dos_memory(old_sel); + movedata(env_selector, 0, sel, 0, old_size); + __dpmi_free_dos_memory(env_selector); + env_selector = sel; + env_segment = seg; + } + else + { + printf("ERROR: env allocation of %i bytes failed!\n", env_size); + return EXIT_FAILURE; } } } @@ -4008,7 +4155,10 @@ perform_exit(NULL); continue; } + /* TODO: don't forget to set sel in int23 handler */ + set_env_seg(); prompt_for_and_get_cmd(); + set_env_sel(); } else get_cmd_from_bat_file(); diff -Nru comcom32-0.1~alpha2-155/debian/changelog comcom32-0.1~alpha2-161/debian/changelog --- comcom32-0.1~alpha2-155/debian/changelog 2021-06-21 10:47:51.000000000 +0000 +++ comcom32-0.1~alpha2-161/debian/changelog 2021-08-15 23:48:46.000000000 +0000 @@ -1,8 +1,8 @@ -comcom32 (0.1~alpha2-155-f68d179+202106211047~ubuntu20.04.1) focal; urgency=low +comcom32 (0.1~alpha2-161-54b0b2d+202108152348~ubuntu20.04.1) focal; urgency=low * Auto build. - -- stsp Mon, 21 Jun 2021 10:47:51 +0000 + -- stsp Sun, 15 Aug 2021 23:48:46 +0000 comcom32 (0.1~alpha2-1) focal; urgency=low diff -Nru comcom32-0.1~alpha2-155/debian/git-build-recipe.manifest comcom32-0.1~alpha2-161/debian/git-build-recipe.manifest --- comcom32-0.1~alpha2-155/debian/git-build-recipe.manifest 2021-06-21 10:47:51.000000000 +0000 +++ comcom32-0.1~alpha2-161/debian/git-build-recipe.manifest 2021-08-15 23:48:46.000000000 +0000 @@ -1,2 +1,2 @@ -# git-build-recipe format 0.4 deb-version {debupstream}-155-f68d179+202106211047 -lp:comcom32 git-commit:f68d1791970d82b125bd1aefd819ce7fd4e61a29 +# git-build-recipe format 0.4 deb-version {debupstream}-161-54b0b2d+202108152348 +lp:comcom32 git-commit:54b0b2df01a8e5df6eb987085042b77ffef23c24