Page MenuHome GnuPG

pinentry-curses.c
No OneTemporary

pinentry-curses.c

/* pinentry-curses.c - A secure curses dialog for PIN entry, library version
Copyright (C) 2002 g10 Code GmbH
This file is part of PINENTRY.
PINENTRY 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 of the License, or
(at your option) any later version.
PINENTRY 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <curses.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <locale.h>
#include <iconv.h>
#include <langinfo.h>
#include <limits.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif /*HAVE_UTIME_H*/
#include <memory.h>
#ifdef HAVE_WCHAR_H
#include <wchar.h>
#endif /*HAVE_WCHAR_H*/
#include "pinentry.h"
#include "assuan.h"
/* FIXME: We should allow configuration of these button labels and in
any case use the default_ok, default_cancel values if available.
However, I have no clue about curses and localization. */
#define STRING_OK "<OK>"
#define STRING_NOTOK "<No>"
#define STRING_CANCEL "<Cancel>"
#define USE_COLORS (has_colors () && COLOR_PAIRS >= 2)
static short pinentry_color[] = { -1, -1, COLOR_BLACK, COLOR_RED,
COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
static int init_screen;
#ifndef HAVE_DOSISH_SYSTEM
static int timed_out;
#endif
typedef enum
{
DIALOG_POS_NONE,
DIALOG_POS_PIN,
DIALOG_POS_OK,
DIALOG_POS_NOTOK,
DIALOG_POS_CANCEL
}
dialog_pos_t;
struct dialog
{
dialog_pos_t pos;
int pin_y;
int pin_x;
/* Width of the PIN field. */
int pin_size;
/* Cursor location in PIN field. */
int pin_loc;
char *pin;
int pin_max;
/* Length of PIN. */
int pin_len;
int ok_y;
int ok_x;
char *ok;
int cancel_y;
int cancel_x;
char *cancel;
int notok_y;
int notok_x;
char *notok;
};
typedef struct dialog *dialog_t;
#ifdef HAVE_NCURSESW
typedef wchar_t CH;
#define STRLEN(x) wcslen (x)
#define ADDCH(x) addnwstr (&x, 1);
#define CHWIDTH(x) wcwidth (x)
#define NULLCH L'\0'
#define NLCH L'\n'
#define SPCH L' '
#else
typedef char CH;
#define STRLEN(x) strlen (x)
#define ADDCH(x) addch ((unsigned char) x)
#define CHWIDTH(x) 1
#define NULLCH '\0'
#define NLCH '\n'
#define SPCH ' '
#endif
/* Return the next line up to MAXLEN columns wide in START and LEN.
The first invocation should have 0 as *LEN. If the line ends with
a \n, it is a normal line that will be continued. If it is a '\0'
the end of the text is reached after this line. In all other cases
there is a forced line break. A full line is returned and will be
continued in the next line. */
static void
collect_line (int maxwidth, CH **start_p, int *len_p)
{
int last_space = 0;
int len = *len_p;
int width = 0;
CH *end;
/* Skip to next line. */
*start_p += len;
/* Skip leading space. */
while (**start_p == SPCH)
(*start_p)++;
end = *start_p;
len = 0;
while (width < maxwidth - 1 && *end != NULLCH && *end != NLCH)
{
len++;
end++;
if (*end == SPCH)
last_space = len;
width += CHWIDTH (*end);
}
if (*end != NULLCH && *end != NLCH && last_space != 0)
{
/* We reached the end of the available space, but still have
characters to go in this line. We can break the line into
two parts at a space. */
len = last_space;
(*start_p)[len] = NLCH;
}
*len_p = len + 1;
}
#ifdef HAVE_NCURSESW
static CH *
utf8_to_local (char *lc_ctype, char *string)
{
mbstate_t ps;
size_t len;
char *local;
const char *p;
wchar_t *wcs = NULL;
char *old_ctype = NULL;
local = pinentry_utf8_to_local (lc_ctype, string);
if (!local)
return NULL;
old_ctype = strdup (setlocale (LC_CTYPE, NULL));
setlocale (LC_CTYPE, lc_ctype? lc_ctype : "");
p = local;
memset (&ps, 0, sizeof(mbstate_t));
len = mbsrtowcs (NULL, &p, strlen (string), &ps);
if (len == (size_t)-1)
{
free (local);
goto leave;
}
wcs = calloc (len + 1, sizeof(wchar_t));
if (!wcs)
{
free (local);
goto leave;
}
p = local;
memset (&ps, 0, sizeof(mbstate_t));
mbsrtowcs (wcs, &p, len, &ps);
free (local);
leave:
if (old_ctype)
{
setlocale (LC_CTYPE, old_ctype);
free (old_ctype);
}
return wcs;
}
#else
static CH *
utf8_to_local (const char *lc_ctype, const char *string)
{
return pinentry_utf8_to_local (lc_ctype, string);
}
#endif
static int
dialog_create (pinentry_t pinentry, dialog_t dialog)
{
int err = 0;
int size_y;
int size_x;
int y;
int x;
int ypos;
int xpos;
int description_x = 0;
int error_x = 0;
CH *description = NULL;
CH *error = NULL;
CH *prompt = NULL;
#define COPY_OUT(what) \
do \
if (pinentry->what) \
{ \
what = utf8_to_local (pinentry->lc_ctype, pinentry->what); \
if (!what) \
{ \
err = 1; \
pinentry->specific_err = ASSUAN_Locale_Problem; \
goto out; \
} \
} \
while (0)
COPY_OUT (description);
COPY_OUT (error);
COPY_OUT (prompt);
#define MAKE_BUTTON(which,default) \
do \
{ \
char *new = NULL; \
if (pinentry->which) \
{ \
int len = strlen (pinentry->which); \
new = malloc (len + 3); \
if (!new) \
{ \
err = 1; \
pinentry->specific_err = ASSUAN_Out_Of_Core; \
goto out; \
} \
new[0] = '<'; \
memcpy (&new[1], pinentry->which, len); \
new[len + 1] = '>'; \
new[len + 2] = '\0'; \
} \
dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype, \
new ? new : default); \
if (!dialog->which) \
{ \
err = 1; \
pinentry->specific_err = ASSUAN_Locale_Problem; \
goto out; \
} \
} \
while (0)
MAKE_BUTTON (ok, STRING_OK);
if (!pinentry->one_button)
MAKE_BUTTON (cancel, STRING_CANCEL);
else
dialog->cancel = NULL;
if (!pinentry->one_button && pinentry->notok)
MAKE_BUTTON (notok, STRING_NOTOK);
else
dialog->notok = NULL;
getmaxyx (stdscr, size_y, size_x);
/* Check if all required lines fit on the screen. */
y = 1; /* Top frame. */
if (description)
{
CH *start = description;
int len = 0;
do
{
collect_line (size_x - 4, &start, &len);
if (len > description_x)
description_x = len;
y++;
}
while (start[len - 1]);
y++;
}
if (pinentry->pin)
{
if (error)
{
CH *p = error;
int err_x = 0;
while (*p)
{
if (*(p++) == '\n')
{
if (err_x > error_x)
error_x = err_x;
y++;
err_x = 0;
}
else
err_x++;
}
if (err_x > error_x)
error_x = err_x;
y += 2; /* Error message. */
}
y += 2; /* Pin entry field. */
}
y += 2; /* OK/Cancel and bottom frame. */
if (y > size_y)
{
err = 1;
pinentry->specific_err = ASSUAN_Too_Short;
goto out;
}
/* Check if all required columns fit on the screen. */
x = 0;
if (description)
{
int new_x = description_x;
if (new_x > size_x - 4)
new_x = size_x - 4;
if (new_x > x)
x = new_x;
}
if (pinentry->pin)
{
#define MIN_PINENTRY_LENGTH 40
int new_x;
if (error)
{
new_x = error_x;
if (new_x > size_x - 4)
new_x = size_x - 4;
if (new_x > x)
x = new_x;
}
new_x = MIN_PINENTRY_LENGTH;
if (prompt)
{
new_x += STRLEN (prompt) + 1; /* One space after prompt. */
}
if (new_x > size_x - 4)
new_x = size_x - 4;
if (new_x > x)
x = new_x;
}
/* We position the buttons after the first, second and third fourth
of the width. Account for rounding. */
if (x < 3 * strlen (dialog->ok))
x = 3 * strlen (dialog->ok);
if (dialog->cancel)
if (x < 3 * strlen (dialog->cancel))
x = 3 * strlen (dialog->cancel);
if (dialog->notok)
if (x < 3 * strlen (dialog->notok))
x = 3 * strlen (dialog->notok);
/* Add the frame. */
x += 4;
if (x > size_x)
{
err = 1;
pinentry->specific_err = ASSUAN_Too_Short;
goto out;
}
dialog->pos = DIALOG_POS_NONE;
dialog->pin = pinentry->pin;
dialog->pin_max = pinentry->pin_len;
dialog->pin_loc = 0;
dialog->pin_len = 0;
ypos = (size_y - y) / 2;
xpos = (size_x - x) / 2;
move (ypos, xpos);
addch (ACS_ULCORNER);
hline (0, x - 2);
move (ypos, xpos + x - 1);
addch (ACS_URCORNER);
move (ypos + 1, xpos + x - 1);
vline (0, y - 2);
move (ypos + y - 1, xpos);
addch (ACS_LLCORNER);
hline (0, x - 2);
move (ypos + y - 1, xpos + x - 1);
addch (ACS_LRCORNER);
ypos++;
if (description)
{
CH *start = description;
int len = 0;
do
{
int i;
move (ypos, xpos);
addch (ACS_VLINE);
addch (' ');
collect_line (size_x - 4, &start, &len);
for (i = 0; i < len - 1; i++)
{
ADDCH (start[i]);
}
if (start[len - 1] != NULLCH && start[len - 1] != NLCH)
ADDCH (start[len - 1]);
ypos++;
}
while (start[len - 1]);
move (ypos, xpos);
addch (ACS_VLINE);
ypos++;
}
if (pinentry->pin)
{
int i;
if (error)
{
CH *p = error;
i = 0;
while (*p)
{
move (ypos, xpos);
addch (ACS_VLINE);
addch (' ');
if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
{
attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
}
else
standout ();
for (;*p && *p != NLCH; p++)
if (i < x - 4)
{
i++;
ADDCH (*p);
}
if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE)
{
attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0));
attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
}
else
standend ();
if (*p == '\n')
p++;
i = 0;
ypos++;
}
move (ypos, xpos);
addch (ACS_VLINE);
ypos++;
}
move (ypos, xpos);
addch (ACS_VLINE);
addch (' ');
dialog->pin_y = ypos;
dialog->pin_x = xpos + 2;
dialog->pin_size = x - 4;
if (prompt)
{
CH *p = prompt;
i = STRLEN (prompt);
if (i > x - 4 - MIN_PINENTRY_LENGTH)
i = x - 4 - MIN_PINENTRY_LENGTH;
dialog->pin_x += i + 1;
dialog->pin_size -= i + 1;
while (i-- > 0)
{
ADDCH (*(p++));
}
addch (' ');
}
for (i = 0; i < dialog->pin_size; i++)
addch ('_');
ypos++;
move (ypos, xpos);
addch (ACS_VLINE);
ypos++;
}
move (ypos, xpos);
addch (ACS_VLINE);
if (dialog->cancel || dialog->notok)
{
dialog->ok_y = ypos;
/* Calculating the left edge of the left button, rounding down. */
dialog->ok_x = xpos + 2 + ((x - 4) / 3 - strlen (dialog->ok)) / 2;
move (dialog->ok_y, dialog->ok_x);
addstr (dialog->ok);
if (dialog->notok)
{
dialog->notok_y = ypos;
/* Calculating the left edge of the middle button, rounding up. */
dialog->notok_x = xpos + x / 2 - strlen (dialog->notok) / 2;
move (dialog->notok_y, dialog->notok_x);
addstr (dialog->notok);
}
if (dialog->cancel)
{
dialog->cancel_y = ypos;
/* Calculating the left edge of the right button, rounding up. */
dialog->cancel_x = xpos + x - 2 - ((x - 4) / 3 + strlen (dialog->cancel)) / 2;
move (dialog->cancel_y, dialog->cancel_x);
addstr (dialog->cancel);
}
}
else
{
dialog->ok_y = ypos;
/* Calculating the left edge of the OK button, rounding down. */
dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2;
move (dialog->ok_y, dialog->ok_x);
addstr (dialog->ok);
}
out:
if (description)
free (description);
if (error)
free (error);
if (prompt)
free (prompt);
return err;
}
static void
set_cursor_state (int on)
{
static int normal_state = -1;
static int on_last;
if (normal_state < 0 && !on)
{
normal_state = curs_set (0);
on_last = on;
}
else if (on != on_last)
{
curs_set (on ? normal_state : 0);
on_last = on;
}
}
static int
dialog_switch_pos (dialog_t diag, dialog_pos_t new_pos)
{
if (new_pos != diag->pos)
{
switch (diag->pos)
{
case DIALOG_POS_OK:
move (diag->ok_y, diag->ok_x);
addstr (diag->ok);
break;
case DIALOG_POS_NOTOK:
if (diag->notok)
{
move (diag->notok_y, diag->notok_x);
addstr (diag->notok);
}
break;
case DIALOG_POS_CANCEL:
if (diag->cancel)
{
move (diag->cancel_y, diag->cancel_x);
addstr (diag->cancel);
}
break;
default:
break;
}
diag->pos = new_pos;
switch (diag->pos)
{
case DIALOG_POS_PIN:
move (diag->pin_y, diag->pin_x + diag->pin_loc);
set_cursor_state (1);
break;
case DIALOG_POS_OK:
set_cursor_state (0);
move (diag->ok_y, diag->ok_x);
standout ();
addstr (diag->ok);
standend ();
move (diag->ok_y, diag->ok_x);
break;
case DIALOG_POS_NOTOK:
if (diag->notok)
{
set_cursor_state (0);
move (diag->notok_y, diag->notok_x);
standout ();
addstr (diag->notok);
standend ();
move (diag->notok_y, diag->notok_x);
}
break;
case DIALOG_POS_CANCEL:
if (diag->cancel)
{
set_cursor_state (0);
move (diag->cancel_y, diag->cancel_x);
standout ();
addstr (diag->cancel);
standend ();
move (diag->cancel_y, diag->cancel_x);
}
break;
case DIALOG_POS_NONE:
set_cursor_state (0);
break;
}
refresh ();
}
return 0;
}
/* XXX Assume that field width is at least > 5. */
static void
dialog_input (dialog_t diag, int chr)
{
int old_loc = diag->pin_loc;
assert (diag->pin);
assert (diag->pos == DIALOG_POS_PIN);
switch (chr)
{
case KEY_BACKSPACE:
if (diag->pin_len > 0)
{
diag->pin_len--;
diag->pin_loc--;
if (diag->pin_loc == 0 && diag->pin_len > 0)
{
diag->pin_loc = diag->pin_size - 5;
if (diag->pin_loc > diag->pin_len)
diag->pin_loc = diag->pin_len;
}
}
break;
default:
if (chr > 0 && chr < 256 && diag->pin_len < diag->pin_max)
{
diag->pin[diag->pin_len] = (char) chr;
diag->pin_len++;
diag->pin_loc++;
if (diag->pin_loc == diag->pin_size && diag->pin_len < diag->pin_max)
{
diag->pin_loc = 5;
if (diag->pin_loc < diag->pin_size - (diag->pin_max + 1 - diag->pin_len))
diag->pin_loc = diag->pin_size - (diag->pin_max + 1 - diag->pin_len);
}
}
break;
}
if (old_loc < diag->pin_loc)
{
move (diag->pin_y, diag->pin_x + old_loc);
while (old_loc++ < diag->pin_loc)
addch ('*');
}
else if (old_loc > diag->pin_loc)
{
move (diag->pin_y, diag->pin_x + diag->pin_loc);
while (old_loc-- > diag->pin_loc)
addch ('_');
}
move (diag->pin_y, diag->pin_x + diag->pin_loc);
}
static int
dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
{
struct dialog diag;
FILE *ttyfi = NULL;
FILE *ttyfo = NULL;
SCREEN *screen = 0;
int done = 0;
char *pin_utf8;
#ifndef HAVE_DOSISH_SYSTEM
int no_input = 1;
#endif
#ifdef HAVE_NCURSESW
char *old_ctype = NULL;
if (pinentry->lc_ctype)
{
old_ctype = strdup (setlocale (LC_CTYPE, NULL));
setlocale (LC_CTYPE, pinentry->lc_ctype);
}
else
setlocale (LC_CTYPE, "");
#endif
/* Open the desired terminal if necessary. */
if (tty_name)
{
ttyfi = fopen (tty_name, "r");
if (!ttyfi)
{
pinentry->specific_err = ASSUAN_ENOENT;
return -1;
}
ttyfo = fopen (tty_name, "w");
if (!ttyfo)
{
int err = errno;
fclose (ttyfi);
errno = err;
pinentry->specific_err = ASSUAN_ENOENT;
return -1;
}
screen = newterm (tty_type, ttyfo, ttyfi);
set_term (screen);
}
else
{
if (!init_screen)
{
if (!(isatty(fileno(stdin)) && isatty(fileno(stdout))))
{
errno = ENOTTY;
pinentry->specific_err = ASSUAN_ENOTTY;
return -1;
}
init_screen = 1;
initscr ();
}
else
clear ();
}
keypad (stdscr, TRUE); /* Enable keyboard mapping. */
nonl (); /* Tell curses not to do NL->CR/NL on output. */
cbreak (); /* Take input chars one at a time, no wait for \n. */
noecho (); /* Don't echo input - in color. */
if (has_colors ())
{
start_color ();
#ifdef NCURSES_VERSION
use_default_colors ();
#endif
if (pinentry->color_so == PINENTRY_COLOR_DEFAULT)
{
pinentry->color_so = PINENTRY_COLOR_RED;
pinentry->color_so_bright = 1;
}
if (COLOR_PAIRS >= 2)
{
init_pair (1, pinentry_color[pinentry->color_fg],
pinentry_color[pinentry->color_bg]);
init_pair (2, pinentry_color[pinentry->color_so],
pinentry_color[pinentry->color_bg]);
bkgd (COLOR_PAIR (1));
attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
}
}
refresh ();
/* Create the dialog. */
if (dialog_create (pinentry, &diag))
{
/* Note: pinentry->specific_err has already been set. */
endwin ();
if (screen)
delscreen (screen);
#ifdef HAVE_NCURSESW
if (old_ctype)
{
setlocale (LC_CTYPE, old_ctype);
free (old_ctype);
}
#endif
if (ttyfi)
fclose (ttyfi);
if (ttyfo)
fclose (ttyfo);
return -2;
}
dialog_switch_pos (&diag, diag.pin ? DIALOG_POS_PIN : DIALOG_POS_OK);
#ifndef HAVE_DOSISH_SYSTEM
wtimeout (stdscr, 70);
#endif
do
{
int c;
c = wgetch (stdscr); /* Refresh, accept single keystroke of input. */
#ifndef HAVE_DOSISH_SYSTEM
if (timed_out && no_input)
{
done = -2;
break;
}
#endif
switch (c)
{
#ifndef HAVE_DOSISH_SYSTEM
case ERR:
continue;
#endif
case KEY_LEFT:
case KEY_UP:
switch (diag.pos)
{
case DIALOG_POS_OK:
if (diag.pin)
dialog_switch_pos (&diag, DIALOG_POS_PIN);
break;
case DIALOG_POS_NOTOK:
dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
case DIALOG_POS_CANCEL:
if (diag.notok)
dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
else
dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
default:
break;
}
break;
case KEY_RIGHT:
case KEY_DOWN:
switch (diag.pos)
{
case DIALOG_POS_PIN:
dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
case DIALOG_POS_OK:
if (diag.notok)
dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
else
dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
break;
case DIALOG_POS_NOTOK:
dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
break;
default:
break;
}
break;
case '\t':
switch (diag.pos)
{
case DIALOG_POS_PIN:
dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
case DIALOG_POS_OK:
if (diag.notok)
dialog_switch_pos (&diag, DIALOG_POS_NOTOK);
else
dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
break;
case DIALOG_POS_NOTOK:
dialog_switch_pos (&diag, DIALOG_POS_CANCEL);
break;
case DIALOG_POS_CANCEL:
if (diag.pin)
dialog_switch_pos (&diag, DIALOG_POS_PIN);
else
dialog_switch_pos (&diag, DIALOG_POS_OK);
break;
default:
break;
}
break;
case '\005':
done = -2;
break;
case '\r':
switch (diag.pos)
{
case DIALOG_POS_PIN:
case DIALOG_POS_OK:
done = 1;
break;
case DIALOG_POS_NOTOK:
done = -1;
break;
case DIALOG_POS_CANCEL:
done = -2;
break;
case DIALOG_POS_NONE:
break;
}
break;
default:
if (diag.pos == DIALOG_POS_PIN)
dialog_input (&diag, c);
}
#ifndef HAVE_DOSISH_SYSTEM
no_input = 0;
#endif
}
while (!done);
set_cursor_state (1);
endwin ();
if (screen)
delscreen (screen);
#ifdef HAVE_NCURSESW
if (old_ctype)
{
setlocale (LC_CTYPE, old_ctype);
free (old_ctype);
}
#endif
if (ttyfi)
fclose (ttyfi);
if (ttyfo)
fclose (ttyfo);
/* XXX Factor out into dialog_release or something. */
free (diag.ok);
if (diag.cancel)
free (diag.cancel);
if (diag.notok)
free (diag.notok);
if (pinentry->pin)
{
pinentry->locale_err = 1;
pin_utf8 = pinentry_local_to_utf8 (pinentry->lc_ctype, pinentry->pin, 1);
if (pin_utf8)
{
pinentry_setbufferlen (pinentry, strlen (pin_utf8) + 1);
if (pinentry->pin)
strcpy (pinentry->pin, pin_utf8);
secmem_free (pin_utf8);
pinentry->locale_err = 0;
}
}
if (done == -2)
pinentry->canceled = 1;
return diag.pin ? (done < 0 ? -1 : diag.pin_len) : (done < 0 ? 0 : 1);
}
/* If a touch has been registered, touch that file. */
static void
do_touch_file (pinentry_t pinentry)
{
#ifdef HAVE_UTIME_H
struct stat st;
time_t tim;
if (!pinentry->touch_file || !*pinentry->touch_file)
return;
if (stat (pinentry->touch_file, &st))
return; /* Oops. */
/* Make sure that we actually update the mtime. */
while ( (tim = time (NULL)) == st.st_mtime )
sleep (1);
/* Update but ignore errors as we can't do anything in that case.
Printing error messages may even clubber the display further. */
utime (pinentry->touch_file, NULL);
#endif /*HAVE_UTIME_H*/
}
#ifndef HAVE_DOSISH_SYSTEM
static void
catchsig (int sig)
{
if (sig == SIGALRM)
timed_out = 1;
}
#endif
int
curses_cmd_handler (pinentry_t pinentry)
{
int rc;
#ifndef HAVE_DOSISH_SYSTEM
timed_out = 0;
if (pinentry->timeout)
{
struct sigaction sa;
memset (&sa, 0, sizeof(sa));
sa.sa_handler = catchsig;
sigaction (SIGALRM, &sa, NULL);
alarm (pinentry->timeout);
}
#endif
rc = dialog_run (pinentry, pinentry->ttyname, pinentry->ttytype);
do_touch_file (pinentry);
return rc;
}

File Metadata

Mime Type
text/x-c
Expires
Mon, Dec 23, 3:25 PM (1 d, 6 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
53/bc/d6183c771a6dbb21ba61ffd2b445

Event Timeline