diff options
Diffstat (limited to 'src/passphrase_helper.h')
-rw-r--r-- | src/passphrase_helper.h | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/src/passphrase_helper.h b/src/passphrase_helper.h new file mode 100644 index 0000000..7ec57a8 --- /dev/null +++ b/src/passphrase_helper.h @@ -0,0 +1,313 @@ +/** + * libpassphrase – Personalisable library for TTY passphrase reading + * + * Copyright © 2013, 2014, 2015 Mattias Andrée (maandree@member.fsf.org) + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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, see <http://www.gnu.org/licenses/>. + */ +#ifndef PASSPHRASE_HELPER_H +#define PASSPHRASE_HELPER_H + + +/* Fix conflicting configurations */ +#if defined(PASSPHRASE_TEXT) && defined(PASSPHRASE_STAR) +# warning You cannot have both PASSPHRASE_TEXT and PASSPHRASE_STAR +# undef PASSPHRASE_TEXT +#endif + + +/* Default texts */ +#ifndef PASSPHRASE_STAR_CHAR +# define PASSPHRASE_STAR_CHAR "*" /* TODO document */ +#endif +#ifndef PASSPHRASE_TEXT_EMPTY +# define PASSPHRASE_TEXT_EMPTY "(empty)" /* TODO document */ +#endif +#ifndef PASSPHRASE_TEXT_NOT_EMPTY +# define PASSPHRASE_TEXT_NOT_EMPTY "(not empty)" /* TODO document */ +#endif + + + +/* Control keys. */ + +/** + * Home-key. + * Character sequences: \e[1~ \eOH + * Control-key combination: ^A + */ +#define KEY_HOME -1 + +/** + * Insert-key. + * Character sequences: \e[2~ + */ +#define KEY_INSERT -2 + +/** + * Delete-key. + * Character sequences: \e[3~ + * Control-key combination: ^D + */ +#define KEY_DELETE -3 + +/** + * End-key. + * Character sequences: \e[4~ \eOF + * Control-key combination: ^E + */ +#define KEY_END -4 + +/** + * Erase-key, also known as backspace. + * Character sequences: \d8 \d127 + */ +#define KEY_ERASE -5 + +/** + * Right-key. + * Character sequences: \e[C + * Control-key combination: ^F + */ +#define KEY_RIGHT -6 + +/** + * Left-key. + * Character sequences: \e[D + * Control-key combination: ^B + */ +#define KEY_LEFT -7 + + + +/* Custom fflush and fprintf */ +#if defined(PASSPHRASE_STAR) || defined(PASSPHRASE_TEXT) +# define xprintf(...) fprintf(stderr, __VA_ARGS__) +# define xflush() fflush(stderr) +#elif defined(PASSPHRASE_MOVE) && !defined(PASSPHRASE_ECHO) +# define xprintf(...) ({ /* do nothing */ }) +# define xflush() ({ /* do nothing */ }) +#elif defined(PASSPHRASE_MOVE) +# define xprintf(...) fprintf(stderr, __VA_ARGS__) +# define xflush() fflush(stderr) +#else +# define xflush() fflush(stderr) +#endif + + + +/* Custom putchar */ +#if defined(PASSPHRASE_STAR) +# define xputchar(C) (((C & 0xC0) != 0x80) ? fprintf(stderr, "%s", PASSPHRASE_STAR_CHAR) : 0) +#elif defined(PASSPHRASE_ECHO) && defined(PASSPHRASE_MOVE) +# define xputchar(C) fputc(C, stderr) +#else +# define xputchar(C) ({ /* be silent */ }) +#endif + + + +/* Is insert active by default? */ +#if defined(PASSPHRASE_OVERRIDE) && defined(PASSPHRASE_INSERT) +# if defined(DEFAULT_INSERT) +# define DEFAULT_INSERT_VALUE 1 +# else +# define DEFAULT_INSERT_VALUE 0 +# endif +#endif + + + +/* PASSPHRASE_INVALID's affect */ +#if defined(PASSPHRASE_INVALID) +# define null_terminate() (*(rc + len) = 0) +#else +# define null_terminate() ({ /* do nothing*/ }) +#endif + + + +/* Implementation of the right-key's action */ +#define move_right() \ + ({ \ + xprintf("\033[C"); \ + do \ + point++; \ + while ((len != point) && ((*(rc + point) & 0xC0) == 0x80)); \ + }) + + +/* Implementation of the left-key's action */ +#define move_left() \ + ({ \ + xprintf("\033[D"); \ + point--; \ + while (point && ((*(rc + point) & 0xC0) == 0x80)) \ + point--; \ + }) + + +/* Implementation of the home-key's action */ +#define move_home() \ + ({ \ + size_t n = 0; \ + for (i = 0; i < point; i++) \ + if ((*(rc + i) & 0xC0) != 0x80) \ + n++; \ + xprintf("\033[%zuD", n); \ + point = 0; \ + }) + + +/* Implementation of the end-key's action */ +#define move_end() \ + ({ \ + size_t n = 0; \ + for (i = point; i < len; i++) \ + if ((*(rc + i) & 0xC0) != 0x80) \ + n++; \ + xprintf("\033[%zuC", n); \ + point = len; \ + }) + + +/* Implementation of the delete-key's action upon the passphrase buffer */ +#define delete_next() \ + ({ \ + null_terminate(); \ + do \ + { \ + for (i = point; i < len; i++) \ + *(rc + i) = *(rc + i + 1); \ + len--; \ + } \ + while ((len != point) && ((*(rc + point) & 0xC0) == 0x80)); \ + }) + + +/* Implementation of the erase-key's action upon the passphrase buffer */ +#if defined(PASSPHRASE_MOVE) +#define erase_prev() \ + ({ \ + char redo = 1; \ + null_terminate(); \ + while (redo) \ + { \ + redo = (*(rc + point - 1) & 0xC0) == 0x80; \ + for (i = point; i < len; i++) \ + *(rc + i - 1) = *(rc + i); \ + if (point <= len) \ + *(rc + len - 1) = *(rc + len); \ + point--; \ + len--; \ + } \ + }) +#else +# define erase_prev() (*(rc + --len) = 0) +#endif + + +#if defined(PASSPHRASE_MOVE) +# define append_char() (xputchar(c), *(rc + len++) = (char)c, point++) +#elif defined(PASSPHRASE_TEXT) +# define append_char() \ + ({ \ + if (len == 0) \ + { \ + xprintf("\e[K%s%zn", PASSPHRASE_TEXT_NOT_EMPTY, &printed_len); \ + if (printed_len) \ + xprintf("\e[%zuD", printed_len); \ + } \ + *(rc + len++) = (char)c; \ + }) +#else +# define append_char() (xputchar(c), *(rc + len++) = (char)c) +#endif + + +#define insert_char() \ + ({ \ + if ((c & 0xC0) != 0x80) \ + xprintf("\033[@"); \ + xputchar(c); \ + for (i = len; i > point; i--) \ + *(rc + i) = *(rc + i - 1); \ + len++; \ + *(rc + point++) = (char)c; \ + }) + + +#define override_char() \ + ({ \ + size_t n = 1; \ + char cn = (char)c; \ + while ((*(rc + point + n) & 0xC0) == 0x80) \ + n++; \ + for (i = point + n; i < len; i++) \ + *(rc + i - n) = *(rc + i); \ + passphrase_wipe(rc + len - n, n); \ + len -= n; \ + n = 0; \ + while (cn & 0x80) \ + { \ + cn = (char)(cn << 1); \ + n++; \ + } \ + n = n ?: 1; \ + if (len + n > size) \ + { \ + if ((rc = xrealloc(rc, size, size << 1L)) == NULL) \ + return NULL; \ + size <<= 1L; \ + } \ + len += n; \ + for (i = len - 1; i > point + n; i--) \ + *(rc + i) = *(rc + i - n); \ + if (len - 1 >= point + n) \ + *(rc + point + n) = *(rc + point); \ + for (i = 0; i < n; i++) \ + { \ + if (i) \ + c = getchar(); \ + xputchar(c); \ + *(rc + point++) = (char)c; \ + } \ + }) + + +/* Implementation of the delete-key's action upon the display */ +#if defined(PASSPHRASE_TEXT) +# define print_erase() \ + (len == 0 ? 0 : (xprintf("\e[K%s%zn", PASSPHRASE_TEXT_EMPTY, &printed_len), \ + (printed_len ? xprintf("\e[%zuD", printed_len) : 0))) +#else +# define print_delete() xprintf("\033[P") +#endif + + +/* Implementation of the erase-key's action upon the display */ +#if defined(PASSPHRASE_TEXT) +# define print_erase() \ + (len == 0 ? 0 : (xprintf("\e[K%s%zn", PASSPHRASE_TEXT_EMPTY, &printed_len), \ + (printed_len ? xprintf("\e[%zuD", printed_len) : 0))) +#elif defined(PASSPHRASE_MOVE) +# define print_erase() xprintf("\033[D\033[P") +#elif defined(PASSPHRASE_STAR) +# define print_erase() xprintf("\033[D \033[D") +#endif + + + +#endif + |