Exemplo n.º 1
0
void
quit(int status)
{
	(void) resetterm();
	(void) endwin();
	exit(status);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
/* end the game, either normally or due to signal */
static void
uninitgame(void)
{
    clear();
    refresh();
    resetterm();
    echo();
    endwin();
    exit(0);
}
Exemplo n.º 4
0
Arquivo: bs.c Projeto: a565109863/src
/* 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);
}
Exemplo n.º 5
0
Arquivo: bdos.c Projeto: jhallen/cpm
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);
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
void
O_cleanup()
{
	/*
	**	this probably isn't necessary, but in the
	**	name of compeleteness.
	*/
#ifdef M_TERMINFO
	resetterm();
#endif
}
Exemplo n.º 8
0
static void tfini(void)
{
#ifdef TERMINFO
	TPUTS(reset_1string);
	resetterm();
#endif
#ifdef __unix__
	tcsetattr(0, TCSAFLUSH, &save_tty);
#endif
	tflush();
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
0
Arquivo: bdos.c Projeto: jhallen/cpm
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);
}
Exemplo n.º 11
0
Arquivo: bdos.c Projeto: jhallen/cpm
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';
}
Exemplo n.º 12
0
Arquivo: bdos.c Projeto: jhallen/cpm
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;
}
Exemplo n.º 13
0
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);
	}
}