Beispiel #1
0
static bool
handle_input(DIALOG_CALLBACK * cb)
{
    MY_OBJ *obj = (MY_OBJ *) cb;
    bool result;
    int status;
    char buf[MY_LEN];

    if (dialog_state.pipe_input == 0) {
	status = -1;
    } else if ((status = read_data(buf, dialog_state.pipe_input)) > 0) {

	if (isMarker(buf)) {
	    /*
	     * Historically, next line should be percentage, but one of the
	     * worse-written clones of 'dialog' assumes the number is missing.
	     * (Gresham's Law applied to software).
	     */
	    if ((status = read_data(buf, dialog_state.pipe_input)) > 0) {

		obj->prompt_buf[0] = '\0';
		if (decode_percent(buf))
		    obj->percent = atoi(buf);
		else
		    strcpy(obj->prompt_buf, buf);

		/* Rest is message text */
		while ((status = read_data(buf, dialog_state.pipe_input)) > 0
		       && !isMarker(buf)) {
		    if (strlen(obj->prompt_buf) + strlen(buf) <
			sizeof(obj->prompt_buf) - 1) {
			strcat(obj->prompt_buf, buf);
		    }
		}

		if (obj->prompt != obj->prompt_buf)
		    free(obj->prompt);
		obj->prompt = obj->prompt_buf;
	    }
	} else if (decode_percent(buf)) {
	    obj->percent = atoi(buf);
	}
    } else {
	if (feof(dialog_state.pipe_input) ||
	    (ferror(dialog_state.pipe_input) && errno != EINTR)) {
	    delink(obj);
	    dlg_remove_callback(cb);
	}
    }

    if (status > 0) {
	result = TRUE;
	repaint_text(obj);
    } else {
	result = FALSE;
    }

    return result;
}
Beispiel #2
0
void
dlg_free_gauge(void *objptr)
{
    MY_OBJ *obj = (MY_OBJ *) objptr;

    curs_set(1);
    if (valid(obj)) {
	delink(obj);
	obj->obj.keep_win = FALSE;
	dlg_remove_callback(&(obj->obj));
    }
}
Beispiel #3
0
/*
 * Display a gauge, or progress meter.  Starts at percent% and reads stdin.  If
 * stdin is not XXX, then it is interpreted as a percentage, and the display is
 * updated accordingly.  Otherwise the next line is the percentage, and
 * subsequent lines up to another XXX are used for the new prompt.  Note that
 * the size of the window never changes, so the prompt can not get any larger
 * than the height and width specified.
 */
int
dialog_gauge(const char *title,
	     const char *cprompt,
	     int height,
	     int width,
	     int percent)
{
    int fkey;
    int ch, result;
    void *objptr = dlg_allocate_gauge(title, cprompt, height, width, percent);
    MY_OBJ *obj = (MY_OBJ *) objptr;

    dlg_add_callback_ref((DIALOG_CALLBACK **) & obj, my_cleanup);
    dlg_update_gauge(obj, percent);

    dlg_trace_win(obj->obj.win);
    do {
	ch = dlg_getc(obj->obj.win, &fkey);
#ifdef KEY_RESIZE
	if (fkey && ch == KEY_RESIZE) {
	    MY_OBJ *oldobj = obj;

	    dlg_mouse_free_regions();

	    obj = dlg_allocate_gauge(title,
				     cprompt,
				     height,
				     width,
				     oldobj->percent);

	    /* avoid breaking new window in dlg_remove_callback */
	    oldobj->obj.caller = 0;
	    oldobj->obj.input = 0;
	    oldobj->obj.keep_win = FALSE;

	    /* remove the old version of the gauge */
	    dlg_clear();
	    dlg_remove_callback(&(oldobj->obj));
	    refresh();

	    dlg_add_callback_ref((DIALOG_CALLBACK **) & obj, my_cleanup);
	    dlg_update_gauge(obj, obj->percent);
	}
#endif
    }
    while (valid(obj) && handle_my_getc(&(obj->obj), ch, fkey, &result));

    dlg_free_gauge(obj);

    return (DLG_EXIT_OK);
}
Beispiel #4
0
int
dlg_getc_callbacks(int ch, int fkey, int *result)
{
    int code = FALSE;
    DIALOG_CALLBACK *p, *q;

    if ((p = dialog_state.getc_callbacks) != 0) {
	if (check_inputs() >= 0) {
	    do {
		q = p->next;
		if (p->input_ready) {
		    if (!(p->handle_getc(p, ch, fkey, result))) {
			dlg_remove_callback(p);
		    }
		}
	    } while ((p = q) != 0);
	}
	code = (dialog_state.getc_callbacks != 0);
    }
    return code;
}
Beispiel #5
0
/*
 * If we have callbacks active, purge the list of all that are not marked
 * to keep in the background.  If any remain, run those in a background
 * process.
 */
void
dlg_killall_bg(int *retval)
{
    DIALOG_CALLBACK *cb;
    int pid;
#ifdef HAVE_TYPE_UNIONWAIT
    union wait wstatus;
#else
    int wstatus;
#endif

    if ((cb = dialog_state.getc_callbacks) != 0) {
	while (cb != 0) {
	    if (cb->keep_bg) {
		cb = cb->next;
	    } else {
		dlg_remove_callback(cb);
		cb = dialog_state.getc_callbacks;
	    }
	}
	if (dialog_state.getc_callbacks != 0) {

	    refresh();
	    fflush(stdout);
	    fflush(stderr);
	    reset_shell_mode();
	    if ((pid = fork()) != 0) {
		_exit(pid > 0 ? DLG_EXIT_OK : DLG_EXIT_ERROR);
	    } else if (pid == 0) {	/* child */
		if ((pid = fork()) != 0) {
		    /*
		     * Echo the process-id of the grandchild so a shell script
		     * can read that, and kill that process.  We'll wait around
		     * until then.  Our parent has already left, leaving us
		     * temporarily orphaned.
		     */
		    if (pid > 0) {	/* parent */
			fprintf(stderr, "%d\n", pid);
			fflush(stderr);
		    }
		    /* wait for child */
#ifdef HAVE_WAITPID
		    while (-1 == waitpid(pid, &wstatus, 0)) {
#ifdef EINTR
			if (errno == EINTR)
			    continue;
#endif /* EINTR */
#ifdef ERESTARTSYS
			if (errno == ERESTARTSYS)
			    continue;
#endif /* ERESTARTSYS */
			break;
		    }
#else
		    while (wait(&wstatus) != pid)	/* do nothing */
			;
#endif
		    _exit(WEXITSTATUS(wstatus));
		} else if (pid == 0) {
		    if (!dialog_vars.cant_kill)
			(void) signal(SIGHUP, finish_bg);
		    (void) signal(SIGINT, finish_bg);
		    (void) signal(SIGQUIT, finish_bg);
		    (void) signal(SIGSEGV, finish_bg);
		    while (dialog_state.getc_callbacks != 0) {
			int fkey = 0;
			dlg_getc_callbacks(ERR, fkey, retval);
			napms(1000);
		    }
		}
	    }
	}
    }
}
Beispiel #6
0
/*
 * Read a character from the given window.  Handle repainting here (to simplify
 * things in the calling application).  Also, if input-callback(s) are set up,
 * poll the corresponding files and handle the updates, e.g., for displaying a
 * tailbox.
 */
int
dlg_getc(WINDOW *win, int *fkey)
{
    WINDOW *save_win = win;
    int ch = ERR;
    int before_chr;
    int before_fkey;
    int result;
    bool done = FALSE;
    bool literal = FALSE;
    DIALOG_CALLBACK *p = 0;
    int interval = (dialog_vars.timeout_secs * 1000);
    time_t expired = time((time_t *) 0) + dialog_vars.timeout_secs;
    time_t current;

    if (may_handle_inputs())
	wtimeout(win, WTIMEOUT_VAL);
    else if (interval > 0)
	wtimeout(win, interval);

    while (!done) {
	bool handle_others = FALSE;

	/*
	 * If there was no pending file-input, check the keyboard.
	 */
	ch = really_getch(win, fkey);
	if (literal) {
	    done = TRUE;
	    continue;
	}

	before_chr = ch;
	before_fkey = *fkey;

	ch = dlg_lookup_key(win, ch, fkey);
	dlg_trace_chr(ch, *fkey);

	current = time((time_t *) 0);

	/*
	 * If we acquired a fkey value, then it is one of dialog's builtin
	 * codes such as DLGK_HELPFILE.
	 */
	if (!*fkey || *fkey != before_fkey) {
	    switch (ch) {
	    case CHR_LITERAL:
		literal = TRUE;
		keypad(win, FALSE);
		continue;
	    case CHR_REPAINT:
		(void) touchwin(win);
		(void) wrefresh(curscr);
		break;
	    case ERR:		/* wtimeout() in effect; check for file I/O */
		if (interval > 0
		    && current >= expired) {
		    dlg_exiterr("timeout");
		}
		if (!valid_file(stdin)
		    || !valid_file(dialog_state.screen_output)) {
		    ch = ESC;
		    done = TRUE;
		} else if (check_inputs()) {
		    if (handle_inputs(win))
			dlg_raise_window(win);
		    else
			done = TRUE;
		} else {
		    done = (interval <= 0);
		}
		break;
	    case DLGK_HELPFILE:
		if (dialog_vars.help_file) {
		    int yold, xold;
		    getyx(win, yold, xold);
		    dialog_helpfile("HELP", dialog_vars.help_file, 0, 0);
		    dlg_raise_window(win);
		    wmove(win, yold, xold);
		}
		continue;
	    case DLGK_FIELD_PREV:
		/* FALLTHRU */
	    case KEY_BTAB:
		/* FALLTHRU */
	    case DLGK_FIELD_NEXT:
		/* FALLTHRU */
	    case TAB:
		/* Handle tab/backtab as a special case for traversing between
		 * the nominal "current" window, and other windows having
		 * callbacks.  If the nominal (control) window closes, we'll
		 * close the windows with callbacks.
		 */
		if (dialog_state.getc_callbacks != 0 &&
		    (isBeforeChr(TAB) ||
		     isBeforeFkey(KEY_BTAB))) {
		    p = (isBeforeChr(TAB)
			 ? next_callback(p)
			 : prev_callback(p));
		    if ((dialog_state.getc_redirect = p) != 0) {
			win = p->win;
		    } else {
			win = save_win;
		    }
		    dlg_raise_window(win);
		    break;
		}
		/* FALLTHRU */
	    default:
#ifdef NO_LEAKS
		if (isBeforeChr(DLG_CTRL('P'))) {
		    /* for testing, ^P closes the connection */
		    close(0);
		    close(1);
		    close(2);
		    break;
		}
#endif
		handle_others = TRUE;
		break;
#ifdef HAVE_DLG_TRACE
	    case CHR_TRACE:
		dlg_trace_win(win);
		break;
#endif
	    }
	} else {
	    handle_others = TRUE;
	}

	if (handle_others) {
	    if ((p = dialog_state.getc_redirect) != 0) {
		if (!(p->handle_getc(p, ch, *fkey, &result))) {
		    done = (p->win == save_win) && (!p->keep_win);
		    dlg_remove_callback(p);
		    dialog_state.getc_redirect = 0;
		    win = save_win;
		}
	    } else {
		done = TRUE;
	    }
	}
    }
    if (literal)
	keypad(win, TRUE);
    return ch;
}