void quit(int status) { (void) resetterm(); (void) endwin(); exit(status); }
void n_shell() { WINDOW *sh_win, *newwin(); SIG_TYPE (*istat)(), (*qstat)(); int sig_status, spid, w; char *shell, *shellpath, *getenv(), *strrchr(); unsigned int sleep(); void _exit(); /* a full window */ sh_win = newwin(LINES, COLS, 0, 0); touchwin(sh_win); waddstr(sh_win, "Pcomm <=> Unix gateway, use ^D or 'exit' to return\n"); wrefresh(sh_win); /* out of curses mode */ resetterm(); shellpath = getenv("SHELL"); if (shellpath == NULL || *shellpath == '\0') shellpath = "/bin/sh"; if (shell = strrchr(shellpath, '/')) shell++; else { shellpath = "/bin/sh"; shell = "sh"; } if (!(spid = fork())) { signal(SIGINT, SIG_DFL); signal(SIGQUIT, SIG_DFL); #ifdef SETUGID setgid(getgid()); setuid(getuid()); #endif /* SETUGID */ execl(shellpath, shell, "-i", (char *) 0); _exit(1); } istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); while ((w = wait(&sig_status)) != spid && w != -1) ; signal(SIGINT, istat); signal(SIGQUIT, qstat); /* back to curses mode */ sleep(1); fixterm(); clearok(curscr, TRUE); werase(sh_win); wrefresh(sh_win); delwin(sh_win); return; }
/* end the game, either normally or due to signal */ static void uninitgame(void) { clear(); refresh(); resetterm(); echo(); endwin(); exit(0); }
/* end the game, either normally or due to signal */ static void uninitgame(int sig) { clear(); (void)refresh(); (void)resetterm(); (void)echo(); (void)endwin(); exit(sig); }
static void delfp(z80info *z80, unsigned where) { int i; for (i = 0; i < storedfps; ++i) if (stfps[i].where == where) { stfps[i].where = 0xffffU; return; } fprintf(stderr, "error: cannot del fp entry for FCB at %04x\n", where); resetterm(); exit(1); }
void iott_close(io_desc *v, mval *pp) { d_tt_struct *ttptr; params ch; int status; int p_offset; boolean_t ch_set; assert(v->type == tt); if (v->state != dev_open) return; ESTABLISH_GTMIO_CH(&v->pair, ch_set); iott_flush(v); if (v->pair.in != v) assert(v->pair.out == v); ttptr = (d_tt_struct *)v->dev_sp; if (v->pair.out != v) assert(v->pair.in == v); v->state = dev_closed; resetterm(v); p_offset = 0; while (*(pp->str.addr + p_offset) != iop_eol) { if ((ch = *(pp->str.addr + p_offset++)) == iop_exception) { v->error_handler.len = *(pp->str.addr + p_offset); v->error_handler.addr = (char *)(pp->str.addr + p_offset + 1); s2pool(&v->error_handler); } p_offset += ((IOP_VAR_SIZE == io_params_size[ch]) ? (unsigned char)*(pp->str.addr + p_offset) + 1 : io_params_size[ch]); } if (v == io_std_device.in || (v == io_std_device.out)) { REVERT_GTMIO_CH(&v->pair, ch_set); return; } CLOSEFILE_RESET(ttptr->fildes, status); /* resets "ttptr->fildes" to FD_INVALID */ if (0 != status) { assert(status == errno); rts_error_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, RTS_ERROR_LITERAL("iott_close(CLOSEFILE)"), CALLFROM, status); } if (ttptr->recall_buff.addr) { free(ttptr->recall_buff.addr); ttptr->recall_buff.addr = NULL; } REVERT_GTMIO_CH(&v->pair, ch_set); return; }
void O_cleanup() { /* ** this probably isn't necessary, but in the ** name of compeleteness. */ #ifdef M_TERMINFO resetterm(); #endif }
static void tfini(void) { #ifdef TERMINFO TPUTS(reset_1string); resetterm(); #endif #ifdef __unix__ tcsetattr(0, TCSAFLUSH, &save_tty); #endif tflush(); }
void suspend(int sig) { int status; send_msg(VARLSTCNT(3) ERR_SUSPENDING, 1, sig); suspend_status = NOW_SUSPEND; /* Dont call flush_pio() if the received signal is SIGTTOU OR if the received signal is SIGTTIN * and the $P.out is terminal. Arrival of SIGTTIN and SIGTTOU indicates that current process is * in the background. Hence it does not make sense to do flush_pio() $P.out is terminal. */ if (!(sig == SIGTTOU || ((tt == io_std_device.out->type) && (sig == SIGTTIN)))) flush_pio(); if (NULL != io_std_device.in && tt == io_std_device.in->type) resetterm(io_std_device.in); sig_count = 0; status = kill(process_id, SIGSTOP); assert(0 == status); return; }
static FILE *getfp(z80info *z80, unsigned where) { int i; for (i = 0; i < storedfps; ++i) if (stfps[i].where == where) { /* check name? */ return stfps[i].fp; } /* fcb not found. maybe it has been moved? */ for (i = 0; i < storedfps; ++i) if (stfps[i].where != 0xffffU && !memcmp(z80->mem+z80->regde+1, stfps[i].name, 11)) { stfps[i].where = where; /* moved FCB */ return stfps[i].fp; } fprintf(stderr, "error: cannot find fp entry for FCB at %04x" " fctn %d, FCB named %s\n", where, z80->regbc & 0xff, z80->mem+where+1); for (i = 0; i < storedfps; ++i) if (stfps[i].where != 0xffffU) printf("%s %04x\n", stfps[i].name, stfps[i].where); resetterm(); exit(1); }
static void storefp(z80info *z80, FILE *fp, unsigned where) { int i; int ind = -1; for (i = 0; i < storedfps; ++i) if (stfps[i].where == 0xffffU) ind = i; else if (stfps[i].where == where) { ind = i; goto putfp; } if (ind < 0) { if (++storedfps > 100) { fprintf(stderr, "out of fp stores!\n"); resetterm(); exit(1); } ind = storedfps - 1; } stfps[ind].where = where; putfp: stfps[ind].fp = fp; memcpy(stfps[ind].name, z80->mem+z80->regde+1, 11); stfps[ind].name[11] = '\0'; }
void check_BDOS_hook(z80info *z80) { int i; char name[32]; char name2[32]; FILE *fp; char *s, *t; const char *mode; if (trace_bdos) { printf("\r\nbdos %d %s (AF=%04x BC=%04x DE=%04x HL =%04x SP=%04x STACK=", C, bdos_decode(C), AF, BC, DE, HL, SP); for (i = 0; i < 8; ++i) printf(" %4x", z80->mem[SP + 2*i] + 256 * z80->mem[SP + 2*i + 1]); printf(")\r\n"); } switch (C) { case 0: /* System Reset */ warmboot(z80); return; #if 0 for (i = 0; i < 0x1600; ++i) z80->mem[i+BIOS-0x1600] = cpmsys[i]; BC = 0; PC = BIOS-0x1600+3; SP = 0x80; #endif break; case 1: /* Console Input */ HL = kget(0); B = H; A = L; if (A < ' ') { switch(A) { case '\r': case '\n': case '\t': vt52(A); break; default: vt52('^'); vt52((A & 0xff)+'@'); if (A == 3) { /* ctrl-C pressed */ /* PC = BIOS+3; check_BIOS_hook(); */ warmboot(z80); return; } } } else { vt52(A); } break; case 2: /* Console Output */ vt52(0x7F & E); HL = 0; B = H; A = L; break; case 6: /* direct I/O */ switch (E) { case 0xff: if (!constat()) { HL = 0; B = H; A = L; F = 0; break; } case 0xfd: HL = kget(0); B = H; A = L; F = 0; break; case 0xfe: HL = constat() ? 0xff : 0; B = H; A = L; F = 0; break; default: vt52(0x7F & E); HL = 0; B = H; A = L; } break; case 9: /* Print String */ s = (char *)(z80->mem + DE); while (*s != '$') vt52(0x7F & *s++); HL = 0; B = H; A = L; break; case 10: /* Read Command Line */ s = rdcmdline(z80, *(unsigned char *)(t = (char *)(z80->mem + DE)), 1); if (PC == BIOS+3) { /* ctrl-C pressed */ /* check_BIOS_hook(); */ /* execute WBOOT */ warmboot(z80); return; } ++t; for (i = 0; i <= *(unsigned char *)s; ++i) t[i] = s[i]; HL = 0; B = H; A = L; break; case 12: /* Return Version Number */ HL = 0x22; /* Emulate CP/M 2.2 */ B = H; A = L; F = 0; break; case 26: /* Set DMA Address */ z80->dma = DE; HL = 0; B = H; A = L; break; case 32: /* Get/Set User Code */ if (E == 0xff) { /* Get Code */ HL = usercode; B = H; A = L; } else { usercode = E; HL = 0; /* Or does it get usercode? */ B = H; A = L; } break; /* dunno if these are correct */ case 11: /* Console Status */ HL = (constat() ? 0xff : 0x00); B = H; A = L; F = 0; break; case 13: /* reset disk system */ /* storedfps = 0; */ /* WS crashes then */ if (dp) closedir(dp); dp = NULL; z80->dma = 0x80; HL = 0; B = H; A = L; /* select only A:, all r/w */ break; case 14: /* select disk */ HL = 0; B = H; A = L; break; case 15: /* open file */ mode = "r+b"; fileio: FCB_to_filename(z80->mem+DE, name); /* Try lowercase */ if (!(fp = fopen(name, mode))) { FCB_to_ufilename(z80->mem+DE, name); /* Try all uppercase instead */ if (!(fp = fopen(name, mode))) { FCB_to_filename(z80->mem+DE, name); if (*mode == 'r') { char ss[50]; sprintf(ss, "%s/%s", CPMLIBDIR, name); fp = fopen(ss, mode); if (!fp) fp = fopen(ss, "rb"); } if (!fp) { /* still no success */ HL = 0xFF; B = H; A = L; F = 0; break; } } } /* success */ /* memset(z80->mem + DE + 12, 0, 33-12); */ /* User has to set EX, S2, and CR: don't change these- some set them to non-zero */ z80->mem[DE + FCB_S1] = 0; /* memset(z80->mem + DE + 16, 0, 16); */ /* Clear D0-Dn */ /* Should we clear R0 - R2? Nope: then we overlap the following area. */ /* memset(z80->mem + DE + 33, 0, 3); */ /* We need to set high bit of S2: means file is open? */ z80->mem[DE + FCB_S2] |= 0x80; z80->mem[DE + FCB_RC] = 0; /* rc field of FCB */ if (fixrc(z80, fp)) { /* Not a real file? */ HL = 0xFF; B = H; A = L; F = 0; fclose(fp); break; } HL = 0; B = H; A = L; F = 0; /* where to store fp? */ storefp(z80, fp, DE); /* printf("opening file %s\n", name); */ break; case 16: /* close file */ z80->mem[DE + FCB_S2] &= 0x7F; /* Clear high bit: indicates closed */ fp = getfp(z80, DE); delfp(z80, DE); fclose(fp); HL = 0; B = H; A = L; /* printf("close file\n"); */ break; case 17: /* search for first */ if (dp) closedir(dp); if (!(dp = opendir("."))) { fprintf(stderr, "opendir fails\n"); resetterm(); exit(1); } sfn = DE; /* fall through */ case 18: /* search for next */ if (!dp) goto retbad; { struct dirent *de; unsigned char *p; const char *sr; nocpmname: if (!(de = readdir(dp))) { closedir(dp); dp = NULL; retbad: HL = 0xff; B = H; A = L; F = 0; break; } /* printf("\r\nlooking at %s\r\n", de->d_name); */ /* compare data */ memset(p = z80->mem+z80->dma, 0, 128); /* dmaaddr instead of DIRBUF!! */ if (*de->d_name == '.') goto nocpmname; if (strchr(sr = de->d_name, '.')) { if (strlen(de->d_name) > 12) /* POSIX: namlen */ goto nocpmname; } else if (strlen(de->d_name) > 8) goto nocpmname; /* seems OK */ for (i = 0; i < 8; ++i) if (*sr != '.' && *sr) { *++p = toupper(*(unsigned char *)sr); sr++; } else *++p = ' '; /* skip dot */ while (*sr && *sr != '.') ++sr; while (*sr == '.') ++sr; for (i = 0; i < 3; ++i) if (*sr != '.' && *sr) { *++p = toupper(*(unsigned char *)sr); sr++; } else *++p = ' '; /* OK, fcb block is filled */ /* match name */ p -= 11; sr = (char *)(z80->mem + sfn); for (i = 1; i <= 12; ++i) if (sr[i] != '?' && sr[i] != p[i]) goto nocpmname; /* yup, it matches */ HL = 0x00; /* always at pos 0 */ B = H; A = L; F = 0; p[32] = p[64] = p[96] = 0xe5; } break; case 19: /* delete file (no wildcards yet) */ FCB_to_filename(z80->mem + DE, name); unlink(name); HL = 0; B = H; A = L; break; case 20: /* read sequential */ fp = getfp(z80, DE); readseq: if (!fseek(fp, SEQ_ADDRESS, SEEK_SET) && ((i = fread(z80->mem+z80->dma, 1, 128, fp)) > 0)) { long ofst = ftell(fp) + 127; if (i != 128) memset(z80->mem+z80->dma+i, 0x1a, 128-i); z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); fixrc(z80, fp); HL = 0x00; B = H; A = L; } else { HL = 0x1; /* ff => pip error */ B = H; A = L; } break; case 21: /* write sequential */ fp = getfp(z80, DE); writeseq: if (!fseek(fp, SEQ_ADDRESS, SEEK_SET) && fwrite(z80->mem+z80->dma, 1, 128, fp) == 128) { long ofst = ftell(fp); z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); fixrc(z80, fp); HL = 0x00; B = H; A = L; } else { HL = 0xff; B = H; A = L; } break; case 22: /* make file */ mode = "w+b"; goto fileio; case 23: /* rename file */ FCB_to_filename(z80->mem + DE, name); FCB_to_filename(z80->mem + DE + 16, name2); /* printf("rename %s %s called\n", name, name2); */ rename(name, name2); HL = 0; B = H; A = L; break; case 24: /* return login vector */ HL = 1; /* only A: online */ B = H; A = L; F = 0; break; case 25: /* return current disk */ HL = 0; /* only A: */ B = H; A = L; F = 0; break; case 29: /* return r/o vector */ HL = 0; /* none r/o */ B = H; A = L; F = 0; break; case 31: /* get disk parameters */ HL = DPB0; /* only A: */ B = H; A = L; break; case 33: /* read random record */ { long ofst; fp = getfp(z80, DE); /* printf("data is %02x %02x %02x\n", z80->mem[z80->regde+33], z80->mem[z80->regde+34], z80->mem[z80->regde+35]); */ ofst = ADDRESS; z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); goto readseq; } case 34: /* write random record */ { long ofst; fp = getfp(z80, DE); /* printf("data is %02x %02x %02x\n", z80->mem[z80->regde+33], z80->mem[z80->regde+34], z80->mem[z80->regde+35]); */ ofst = ADDRESS; z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); goto writeseq; } case 35: /* compute file size */ fp = getfp(z80, DE); fseek(fp, 0L, SEEK_END); /* fall through */ case 36: /* set random record */ fp = getfp(z80, DE); { long ofst = ftell(fp) + 127; long pos = (ofst >> 7); HL = 0x00; /* dunno, if necessary */ B = H; A = L; z80->mem[DE + FCB_R0] = pos & 0xff; z80->mem[DE + FCB_R1] = pos >> 8; z80->mem[DE + FCB_R2] = pos >> 16; z80->mem[DE + FCB_CR] = SEQ_CR(ofst); z80->mem[DE + FCB_EX] = SEQ_EX(ofst); z80->mem[DE + FCB_S2] = (0x80 | SEQ_S2(ofst)); fixrc(z80, fp); } break; case 41: for (s = (char *)(z80->mem + DE); *s; ++s) *s = tolower(*(unsigned char *)s); HL = (restricted_mode || chdir((char *)(z80->mem + DE))) ? 0xff : 0x00; B = H; A = L; break; default: printf("\n\nUnrecognized BDOS-Function:\n"); printf("AF=%04x BC=%04x DE=%04x HL=%04x SP=%04x\nStack =", AF, BC, DE, HL, SP); for (i = 0; i < 8; ++i) printf(" %4x", z80->mem[SP + 2*i] + 256 * z80->mem[SP + 2*i + 1]); printf("\r\n"); resetterm(); exit(1); } z80->mem[PC = DIRBUF-1] = 0xc9; /* Return instruction */ return; }
void op_zedit(mval *v, mval *p) { char *edt; char es[MAX_FBUFF + 1], typ, *ptr; short path_len, tslash; int objcnt; int waitid; unsigned int childid, status; #ifdef _BSD union wait wait_status; #endif bool has_ext, exp_dir; parse_blk pblk; mstr src; zro_ent *sp, *srcdir; struct sigaction act, intr; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (!editor.len) { edt = GETENV("EDITOR"); if (!edt) edt = "editor"; rts_error(VARLSTCNT(4) ERR_FILENOTFND, 2, LEN_AND_STR(edt)); } MV_FORCE_STR(v); MV_FORCE_STR(p); src.len = v->str.len; src.addr = v->str.addr; if (0 == src.len) rts_error(VARLSTCNT(4) ERR_ZEDFILSPEC, 2, src.len, src.addr); memset(&pblk, 0, SIZEOF(pblk)); pblk.buffer = es; pblk.buff_size = MAX_FBUFF; status = parse_file(&src, &pblk); if (!(status & 1)) rts_error(VARLSTCNT(5) ERR_ZEDFILSPEC, 2, src.len, src.addr, status); has_ext = 0 != (pblk.fnb & F_HAS_EXT); exp_dir = 0 != (pblk.fnb & F_HAS_DIR); if (!(pblk.fnb & F_HAS_NAME)) { assert(!has_ext); rts_error(VARLSTCNT(4) ERR_ZEDFILSPEC, 2, pblk.b_esl, pblk.buffer); } if (!exp_dir) { memmove(&es[0], pblk.l_name, pblk.b_name + pblk.b_ext); path_len = pblk.b_name + pblk.b_ext; ptr = es; } else { path_len = pblk.b_esl; ptr = pblk.l_name; } typ = 0; if (!has_ext) { if ('.' != *ptr) { typ = STR_LIT_LEN(DOTM); if (path_len + typ > MAX_FBUFF) rts_error(VARLSTCNT(4) ERR_ZEDFILSPEC, 2, path_len, es); memcpy(&es[path_len], DOTM, STR_LIT_LEN(DOTM)); path_len += typ; } } else { if ((STR_LIT_LEN(DOTOBJ) == pblk.b_ext) && !MEMCMP_LIT(ptr + pblk.b_name, DOTOBJ)) rts_error(VARLSTCNT(4) ERR_ZEDFILSPEC, 2, path_len, es); else if ((STR_LIT_LEN(DOTM) == pblk.b_ext) && !MEMCMP_LIT(ptr + pblk.b_name, DOTM)) typ = STR_LIT_LEN(DOTM); } dollar_zsource.str.addr = es; dollar_zsource.str.len = path_len - typ; s2pool(&dollar_zsource.str); es[path_len] = 0; if (!exp_dir) { src.addr = es; src.len = path_len; srcdir = (zro_ent *)0; zro_search(0, 0, &src, &srcdir, TRUE); if (NULL == srcdir) { /* find the first source directory */ objcnt = (TREF(zro_root))->count; for (sp = TREF(zro_root) + 1; (NULL == srcdir) && (0 < objcnt--); ++sp) { if (ZRO_TYPE_OBJECT == sp->type) { sp++; assert(ZRO_TYPE_COUNT == sp->type); if (0 != sp->count) srcdir = sp + 1; } else { /* shared library entries (ZRO_TYPE_OBJLIB) do not have source directories */ assert(ZRO_TYPE_OBJLIB == sp->type); } } } if (srcdir && srcdir->str.len) { assert(ZRO_TYPE_SOURCE == srcdir->type); tslash = ('/' == srcdir->str.addr[srcdir->str.len - 1]) ? 0 : 1; if (path_len + srcdir->str.len + tslash >= SIZEOF(es)) rts_error(VARLSTCNT(4) ERR_ZEDFILSPEC, 2, src.len, src.addr); memmove(&es[ srcdir->str.len + tslash], &es[0], path_len); if (tslash) es[ srcdir->str.len ] = '/'; memcpy(&es[0], srcdir->str.addr, srcdir->str.len); path_len += srcdir->str.len + tslash; es[ path_len ] = 0; } } flush_pio(); if (tt == io_std_device.in->type) resetterm(io_std_device.in); /* ignore interrupts */ sigemptyset(&act.sa_mask); act.sa_flags = 0; act.sa_handler = SIG_IGN; sigaction(SIGINT, &act, &intr); childid = fork(); /* BYPASSOK: we exec immediately, no FORK_CLEAN needed */ if (childid) { waitid = (int)childid; for (;;) { #ifdef _BSD WAIT(&wait_status, waitid); #else WAIT((int *)&status, waitid); #endif if (waitid == (int)childid) break; if (-1 == waitid) break; } if (-1 != waitid) dollar_zeditor = 0; else dollar_zeditor = errno; /* restore interrupt handler */ sigaction(SIGINT, &intr, 0); if (tt == io_std_device.in->type) setterm(io_std_device.in); } else { EXECL(editor.addr, editor.addr, es, 0); exit(-1); } }