Compare commits

...

5 Commits
1.0.1 ... main

Author SHA1 Message Date
Luca Bilke 3caf01a905
fix typo
ci/woodpecker/tag/woodpecker Pipeline was successful Details
2024-02-05 18:06:04 +01:00
Luca Bilke 5f4bcf8f71
update build stage
ci/woodpecker/tag/woodpecker Pipeline failed Details
2024-02-05 18:05:19 +01:00
Luca Bilke 856a9d7094
fix typo
ci/woodpecker/tag/woodpecker Pipeline failed Details
2024-02-05 18:00:40 +01:00
Luca Bilke dbd0c5295c
pull changes from rnpnr fork
ci/woodpecker/tag/woodpecker Pipeline failed Details
2024-02-05 17:56:12 +01:00
Luca Bilke cdbccd7871 woodpecker update 2024-01-28 15:53:50 +01:00
19 changed files with 337 additions and 648 deletions

View File

@ -1,8 +0,0 @@
BasedOnStyle: Google
IndentWidth: 4
InsertBraces: true
ColumnLimit: 79
AlignConsecutiveMacros: Consecutive
AllowShortFunctionsOnASingleLine: None
AllowShortLoopsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: Never

View File

@ -1,30 +0,0 @@
Checks: |
-*,
abseil-*,
bugprone-*,
clang-analyzer-*,
misc-*,
modernize-*,
performance-*,
portability-*,
readability-*,
llvm-*,
-bugprone-easily-swappable-parameters,
-readability-avoid-const-params-in-decls,
-readability-identifier-length
CheckOptions:
- key: readability-inconsistent-declaration-parameter-name.Strict
value: true
- key: readability-identifier-naming.StructCase
value: lower_case
- key: readability-identifier-naming.FunctionCase
value: lower_case
- key: readability-identifier-naming.VariableCase
value: lower_case
- key: readability-identifier-naming.EnumConstantCase
value: UPPER_CASE
- key: readability-identifier-naming.MacroDefinitionCase
value: UPPER_CASE
- key: readability-function-cognitive-complexity.Threshold
value: 15

View File

@ -1,3 +0,0 @@
Diagnostics:
UnusedIncludes: Strict
MissingIncludes: Strict

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
build build
*.o *.o
pinentry-dmenu pinentry-dmenu
compile_commands.json

View File

@ -1,12 +1,15 @@
when: when:
event: tag - event: tag
- event: manual
steps: steps:
build: build:
image: ghcr.io/void-linux/void-glibc image: gcc
environment: environment:
- BUILD_DEPS=base-devel libX11-devel libXinerama-devel libXft-devel libconfig-devel gpgme-devel libassuan-devel - BUILD_DEPS=libx11-dev libxinerama-dev libxft-dev libfreetype6-dev libgpgme-dev libfontconfig1-dev libassuan-dev
commands: | commands: |
xbps-install -Sy $${BUILD_DEPS} >/dev/null 2>&1 apt-get update
apt-get install -y $${BUILD_DEPS}
make install DESTDIR="$${CI_WORKSPACE}/pkg" PREFIX="/usr" make install DESTDIR="$${CI_WORKSPACE}/pkg" PREFIX="/usr"
package-xbps: package-xbps:
@ -47,7 +50,7 @@ steps:
- source: xbps_pem_passphrase - source: xbps_pem_passphrase
target: XBPS_PASSPHRASE target: XBPS_PASSPHRASE
volumes: volumes:
- /srv/xbps:/target - /var/www/xbps:/target
- /etc/woodpecker/:/etc/woodpecker:ro - /etc/woodpecker/:/etc/woodpecker:ro
commands: | commands: |
export XBPS_TARGET_ARCH export XBPS_TARGET_ARCH

View File

@ -1,66 +1,68 @@
# pinentry-dmenu - dmenu-like stupid pin entry # pinentry-dmenu - dmenu-like stupid pin entry
# See LICENSE file for copyright and license details. # See LICENSE file for copyright and license details.
.POSIX:
include config.mk include config.mk
SRC = pinentry-dmenu.c drw.c util.c SRC = pinentry-dmenu.c drw.c util.c
OBJ = ${SRC:.c=.o} OBJ = $(SRC:.c=.o)
OBJ_PIN = pinentry/pinentry.o pinentry/util.o pinentry/password-cache.o pinentry/argparse.o pinentry/secmem.o PIN_SRC = \
pinentry/argparse.c\
pinentry/password-cache.c\
pinentry/pinentry.c\
pinentry/secmem.c\
pinentry/util.c
PIN_OBJ = $(PIN_SRC:.c=.o)
PIN_DEP = \
pinentry/argparse.h\
pinentry/password-cache.h\
pinentry/pinentry.h\
pinentry/memory.h\
pinentry/util.h
all: options pinentry-dmenu all: options pinentry-dmenu
options: options:
@echo pinentry-dmenu build options: @echo pinentry-dmenu build options:
@echo "CFLAGS = ${CFLAGS}" @echo "CFLAGS = $(CFLAGS)"
@echo "LDFLAGS = ${LDFLAGS}" @echo "LDFLAGS = $(LDFLAGS)"
@echo "CC = ${CC}" @echo "CC = $(CC)"
.c.o: .c.o:
@echo CC $< $(CC) -c $(CFLAGS) $(INCS) $(CPPFLAGS) -o $@ -c $<
@${CC} -c ${CFLAGS} $<
config.h: config.h:
@echo creating $@ from config.def.h cp config.def.h $@
@cp config.def.h $@
${OBJ}: config.h config.mk drw.h $(OBJ): config.h config.mk drw.h
pinentry: $(PIN_OBJ): $(PIN_DEP)
$(MAKE) -C pinentry
pinentry-dmenu: pinentry pinentry-dmenu.o drw.o util.o pinentry-dmenu: $(OBJ) $(PIN_OBJ)
@echo CC -o $@ $(CC) -o $@ $(OBJ) $(PIN_OBJ) $(LDFLAGS) $(LIBS)
@${CC} -o $@ ${OBJ} ${OBJ_PIN} ${LDFLAGS} -lassuan -lgpgme -lgpg-error -lconfig
clean: clean:
@echo cleaning rm -f pinentry-dmenu $(OBJ) $(PIN_OBJ)
@rm -f pinentry-dmenu ${OBJ}
$(MAKE) -C pinentry/ clean
dist: clean dist: clean
@echo creating dist tarball mkdir -p pinentry-dmenu-$(VERSION)
@mkdir -p dmenu-${VERSION} cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1 \
@cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1 \ drw.h util.h $(SRC) \
drw.h util.h dmenu_path dmenu_run stest.1 ${SRC} \ pinentry-dmenu-$(VERSION)
dmenu-${VERSION} tar -cf pinentry-dmenu-$(VERSION).tar pinentry-dmenu-$(VERSION)
@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION} gzip pinentry-dmenu-$(VERSION).tar
@gzip dmenu-${VERSION}.tar rm -rf pinentry-dmenu-$(VERSION)
@rm -rf dmenu-${VERSION}
install: all install: all
@echo installing executable to ${DESTDIR}${PREFIX}/bin mkdir -p $(DESTDIR)$(PREFIX)/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin cp -f pinentry-dmenu $(DESTDIR)$(PREFIX)/bin
@cp -f pinentry-dmenu ${DESTDIR}${PREFIX}/bin chmod 755 $(DESTDIR)$(PREFIX)/bin/pinentry-dmenu
@chmod 755 ${DESTDIR}${PREFIX}/bin/pinentry-dmenu mkdir -p $(DESTDIR)$(MANPREFIX)/man1
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/$(VERSION)/g" < pinentry-dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/pinentry-dmenu.1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1 chmod 644 $(DESTDIR)$(MANPREFIX)/man1/pinentry-dmenu.1
@sed "s/VERSION/${VERSION}/g;s/DATE/${DATE}/g;s/BUGREPORT/${BUGREPORT}/g" < pinentry-dmenu.1 > ${DESTDIR}${MANPREFIX}/man1/pinentry-dmenu.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/pinentry-dmenu.1
uninstall: uninstall:
@echo removing executable from ${DESTDIR}${PREFIX}/bin rm -f $(DESTDIR)$(PREFIX)/bin/pinentry-dmenu
@rm -f ${DESTDIR}${PREFIX}/bin/pinentry-dmenu rm -f $(DESTDIR)$(MANPREFIX)/man1/pinentry-dmenu.1
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/pinentry-dmenu.1
.PHONY: all options clean dist install pinentry uninstall .PHONY: all options clean dist install pinentry uninstall

View File

@ -5,6 +5,8 @@ pinentry-dmenu is a pinentry program with the charm of [dmenu](https://tools.suc
This program is a fork from [spine](https://gitgud.io/zavok/spine.git) which is also a fork from [dmenu](https://tools.suckless.org/dmenu). This program is a fork from [spine](https://gitgud.io/zavok/spine.git) which is also a fork from [dmenu](https://tools.suckless.org/dmenu).
This is a further fork of pinentry-dmenu with many of the upstream [dmenu](https://tools.suckless.org/dmenu) changes merged and config file support removed.
Requirements Requirements
------------ ------------
@ -25,41 +27,4 @@ Config
------ ------
To use pinentry-dmenu add in `~/.gnupg/gpg-agent.conf`: To use pinentry-dmenu add in `~/.gnupg/gpg-agent.conf`:
pinentry-program <absolute path to pinentry-dmenu> pinentry-program <absolut path to pinentry-dmenu>
The config is located in `~/.gnupg/pinentry-dmenu.conf`.
Parameter | Default | Description
:------------------ |:----------------- |:-----------
asterisk | * | Defines the symbol which is showed for each typed character
bottom | false | pinentry-dmenu appears at the bottom of the screen
min_password_length | 32 | The minimal space of the password field. This value has affect to the description field after the password field
monitor | -1 | pinentry-dmenu is displayed on the monitor number supplied. Monitor numbers are starting from 0
prompt | "" | Defines the prompt to be displayed to the left of the input field
font | monospace:size=10 | Defines the font or font set used
prompt_bg | #bbbbbb | Defines the prompt background color
prompt_fg | #222222 | Defines the prompt foreground color
normal_bg | #bbbbbb | Defines the normal background color
normal_fg | #222222 | Defines the normal foreground color
select_bg | #eeeeee | Defines the selected background color
select_fg | #005577 | Defines the selected foreground color
desc_bg | #bbbbbb | Defines the description background color
desc_fg | #222222 | Defines the description foreground color
embedded | false | Embed into window
Example
-------
```
asterisk= "# ";
prompt = "$";
font = "Noto Sans UI:size=13";
prompt_fg = "#eeeeee";
prompt_bg = "#d9904a";
normal_fg = "#ffffff";
normal_bg = "#000000";
select_fg = "#eeeeee";
select_bg = "#d9904a";
desc_fg = "#eeeeee";
desc_bg = "#d9904a";
```

24
config.def.h Normal file
View File

@ -0,0 +1,24 @@
/* See LICENSE file for copyright and license details. */
/* minimum length to use for displaying the pw field */
static int minpwflen = 16;
/* character to be used as a replacement for typed characters */
static const char *asterisk = "*";
/* if 0, pinentry-dmenu appears at bottom */
static int topbar = 1;
/* default X11 font or font set */
static const char *fonts[] = {
"monospace:size=10"
};
static const char *prompt = NULL;
static const char *colors[SchemeLast][2] = {
/* fg bg */
[SchemePrompt] = { "#bbbbbb", "#222222" },
[SchemeNorm] = { "#bbbbbb", "#222222" },
[SchemeSel] = { "#eeeeee", "#005577" },
[SchemeDesc] = { "#bbbbbb", "#222222" }
};

View File

@ -1,14 +1,6 @@
/* See LICENSE file for copyright and license details. */ static int minpwlen = 16;
/* Default settings; can be overriden by command line. */
static int bottom = 0;
static int embedded = 0;
static int minpwlen = 32;
static int mon = -1;
static int lineheight = 0;
static int min_lineheight = 8;
static const char *asterisk = ""; static const char *asterisk = "";
static int topbar = 1;
static const char *fonts[] = { static const char *fonts[] = {
"FiraCode Nerd Font Mono:pixelsize=14", "FiraCode Nerd Font Mono:pixelsize=14",
"Noto Color Emoji:pixelsize=14", "Noto Color Emoji:pixelsize=14",
@ -19,4 +11,5 @@ static const char *colors[SchemeLast][4] = {
[SchemePrompt] = {"#7aa2f7", "#15161E"}, [SchemePrompt] = {"#7aa2f7", "#15161E"},
[SchemeNormal] = {"#7aa2f7", "#15161E"}, [SchemeNormal] = {"#7aa2f7", "#15161E"},
[SchemeSelect] = {"#15161E", "#7aa2f7"}, [SchemeSelect] = {"#15161E", "#7aa2f7"},
[SchemeDesc] = {"#7aa2f7", "#15161E"}}; [SchemeDesc] = {"#7aa2f7", "#15161E"}
};

View File

@ -1,11 +1,10 @@
# Pinentry settings # Pinentry settings
DATE = $$(date +'%B %Y')
VERSION = 0.1 VERSION = 0.1
BUGREPORT = https:\/\/github.com\/ritze\/pinentry-dmenu BUGREPORT = https:\/\/github.com\/0x766F6964\/pinentry-dmenu
# Paths # Paths
PREFIX = /usr/local PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man MANPREFIX = $(PREFIX)/share/man
X11INC = /usr/X11R6/include X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib X11LIB = /usr/X11R6/lib
@ -18,16 +17,16 @@ XINERAMAFLAGS = -DXINERAMA
FREETYPELIBS = -lfontconfig -lXft FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2 FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment) # OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2 #FREETYPEINC = $(X11INC)/freetype2
# Includes and libs # Includes and libs
INCS = -I${X11INC} -I${FREETYPEINC} INCS = -I$(X11INC) -I$(FREETYPEINC)
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS} LIBS = -lassuan -lgpg-error -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
# Flags # Flags
CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS} -DPACKAGE_VERSION=\"${VERSION}\" -DPACKAGE_BUGREPORT=\"${BUGREPORT}\" CPPFLAGS = -D_DEFAULT_SOURCE -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) -DPACKAGE_VERSION=\"$(VERSION)\" -DPACKAGE_BUGREPORT=\"$(BUGREPORT)\" -DHAVE_MLOCK
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS} CFLAGS = -std=c99 -pedantic -Wall -Os
LDFLAGS = -s ${LIBS} LDFLAGS = -s
# Compiler and linker # Compiler and linker
CC = cc CC = cc

90
drw.c
View File

@ -95,6 +95,7 @@ drw_free(Drw *drw)
{ {
XFreePixmap(drw->dpy, drw->drawable); XFreePixmap(drw->dpy, drw->drawable);
XFreeGC(drw->dpy, drw->gc); XFreeGC(drw->dpy, drw->gc);
drw_fontset_free(drw->fonts);
free(drw); free(drw);
} }
@ -237,12 +238,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
int int
drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
{ {
char buf[1024]; int ty, ellipsis_x = 0;
int ty; unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, hash, h0, h1;
unsigned int ew;
XftDraw *d = NULL; XftDraw *d = NULL;
Fnt *usedfont, *curfont, *nextfont; Fnt *usedfont, *curfont, *nextfont;
size_t i, len;
int utf8strlen, utf8charlen, render = x || y || w || h; int utf8strlen, utf8charlen, render = x || y || w || h;
long utf8codepoint = 0; long utf8codepoint = 0;
const char *utf8str; const char *utf8str;
@ -250,13 +249,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
FcPattern *fcpattern; FcPattern *fcpattern;
FcPattern *match; FcPattern *match;
XftResult result; XftResult result;
int charexists = 0; int charexists = 0, overflow = 0;
/* keep track of a couple codepoints for which we have no match. */
static unsigned int nomatches[128], ellipsis_width;
if (!drw || (render && !drw->scheme) || !text || !drw->fonts) if (!drw || (render && (!drw->scheme || !w)) || !text || !drw->fonts)
return 0; return 0;
if (!render) { if (!render) {
w = ~w; w = invert ? invert : ~invert;
} else { } else {
XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
@ -268,8 +269,10 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
} }
usedfont = drw->fonts; usedfont = drw->fonts;
if (!ellipsis_width && render)
ellipsis_width = drw_fontset_getwidth(drw, "...");
while (1) { while (1) {
utf8strlen = 0; ew = ellipsis_len = utf8strlen = 0;
utf8str = text; utf8str = text;
nextfont = NULL; nextfont = NULL;
while (*text) { while (*text) {
@ -277,9 +280,27 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
for (curfont = drw->fonts; curfont; curfont = curfont->next) { for (curfont = drw->fonts; curfont; curfont = curfont->next) {
charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
if (charexists) { if (charexists) {
if (curfont == usedfont) { drw_font_getexts(curfont, text, utf8charlen, &tmpw, NULL);
if (ew + ellipsis_width <= w) {
/* keep track where the ellipsis still fits */
ellipsis_x = x + ew;
ellipsis_w = w - ew;
ellipsis_len = utf8strlen;
}
if (ew + tmpw > w) {
overflow = 1;
/* called from drw_fontset_getwidth_clamp():
* it wants the width AFTER the overflow
*/
if (!render)
x += tmpw;
else
utf8strlen = ellipsis_len;
} else if (curfont == usedfont) {
utf8strlen += utf8charlen; utf8strlen += utf8charlen;
text += utf8charlen; text += utf8charlen;
ew += tmpw;
} else { } else {
nextfont = curfont; nextfont = curfont;
} }
@ -287,36 +308,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
} }
} }
if (!charexists || nextfont) if (overflow || !charexists || nextfont)
break; break;
else else
charexists = 0; charexists = 0;
} }
if (utf8strlen) { if (utf8strlen) {
drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); if (render) {
/* shorten text if necessary */ ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
drw_font_getexts(usedfont, utf8str, len, &ew, NULL); usedfont->xfont, x, ty, (XftChar8 *)utf8str, utf8strlen);
if (len) {
memcpy(buf, utf8str, len);
buf[len] = '\0';
if (len < utf8strlen)
for (i = len; i && i > len - 3; buf[--i] = '.')
; /* NOP */
if (render) {
ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
usedfont->xfont, x, ty, (XftChar8 *)buf, len);
}
x += ew;
w -= ew;
} }
x += ew;
w -= ew;
} }
if (render && overflow)
drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0, "...", invert);
if (!*text) { if (!*text || overflow) {
break; break;
} else if (nextfont) { } else if (nextfont) {
charexists = 0; charexists = 0;
@ -326,6 +336,15 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
* character must be drawn. */ * character must be drawn. */
charexists = 1; charexists = 1;
hash = (unsigned int)utf8codepoint;
hash = ((hash >> 16) ^ hash) * 0x21F0AAAD;
hash = ((hash >> 15) ^ hash) * 0xD35A2D97;
h0 = ((hash >> 15) ^ hash) % LENGTH(nomatches);
h1 = (hash >> 17) % LENGTH(nomatches);
/* avoid expensive XftFontMatch call when we know we won't find a match */
if (nomatches[h0] == utf8codepoint || nomatches[h1] == utf8codepoint)
goto no_match;
fccharset = FcCharSetCreate(); fccharset = FcCharSetCreate();
FcCharSetAddChar(fccharset, utf8codepoint); FcCharSetAddChar(fccharset, utf8codepoint);
@ -353,6 +372,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
curfont->next = usedfont; curfont->next = usedfont;
} else { } else {
xfont_free(usedfont); xfont_free(usedfont);
nomatches[nomatches[h0] ? h1 : h0] = utf8codepoint;
no_match:
usedfont = drw->fonts; usedfont = drw->fonts;
} }
} }
@ -382,6 +403,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
return drw_text(drw, 0, 0, 0, 0, 0, text, 0); return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
} }
unsigned int
drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
{
unsigned int tmp = 0;
if (drw && drw->fonts && text && n)
tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
return MIN(n, tmp);
}
void void
drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
{ {

1
drw.h
View File

@ -35,6 +35,7 @@ void drw_free(Drw *drw);
Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
void drw_fontset_free(Fnt* set); void drw_fontset_free(Fnt* set);
unsigned int drw_fontset_getwidth(Drw *drw, const char *text); unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
/* Colorscheme abstraction */ /* Colorscheme abstraction */

View File

@ -1,4 +1,4 @@
.TH PINENTRY-DMENU 1 "DATE" pinentry-dmenu\-VERSION "pinentry-dmenu Manual" .TH PINENTRY-DMENU 1 pinentry-dmenu\-VERSION "pinentry-dmenu Manual"
.SH NAME .SH NAME
@ -19,63 +19,6 @@ to
.B pinentry-dmenu .B pinentry-dmenu
to use the program as the regular dialog for to use the program as the regular dialog for
.BR gpg-agent . .BR gpg-agent .
.PP
The configuration is placed in
.IR ~/.gnupg/pinentry-dmenu.conf .
You can change the path to the config file with the environment variable
.IR GNUPGHOME .
.SH OPTIONS
.TP
.BI "asterisk =" " *"
Defines the symbol which is showed for each typed character.
.TP
.BI "bottom =" " false"
pinentry-dmenu appears at the bottom of the screen.
.TP
.BI "min_password_length =" " 32"
The minimal space of the password field. This value has affect to the description field after the password field.
.TP
.BI "monitor =" " -1"
pinentry-dmenu is displayed on the monitor number supplied. Monitor numbers are starting from 0.
.TP
.BI "prompt =" " """"
Defines the prompt to be displayed to the left of the input field.
.TP
.BI "font =" " monospace:size=10"
Defines the font or font set used.
.TP
.BI "prompt_bg =" " #bbbbbb"
Defines the prompt background color.
.IR #RGB ,
.I #RRGGBB
and X color names are supported.
.TP
.BI "prompt_fg =" " #222222"
Defines the prompt foreground color.
.TP
.BI "normal_bg =" " #bbbbbb"
Defines the normal background color.
.TP
.BI "normal_fg =" " #222222"
Defines the normal foreground color.
.TP
.BI "select_bg =" " #eeeeee"
Defines the selected background color.
.TP
.BI "select_fg =" " #005577"
Defines the selected foreground color.
.TP
.BI "desc_bg =" " #bbbbbb"
Defines the description background color.
.TP
.BI "desc_fg =" " #222222"
Defines the description foreground color.
.TP
.BI "embedded =" " false"
Embed into window.
.SH USAGE .SH USAGE
pinentry-dmenu is completely controlled by the keyboard. pinentry-dmenu is completely controlled by the keyboard.
@ -184,25 +127,6 @@ Delete line left
Paste from primary X selection Paste from primary X selection
.SH EXAMPLES
.sp
.if n \{
.RS 4
.\}
.nf
asterisk= "# ";
prompt = "$";
font = "Noto Sans UI:size=13";
prompt_fg = "#eeeeee";
prompt_bg = "#d9904a";
normal_fg = "#ffffff";
normal_bg = "#000000";
select_fg = "#eeeeee";
select_bg = "#d9904a";
desc_fg = "#eeeeee";
desc_bg = "#d9904a";
.SH AUTHORS .SH AUTHORS
.B pinentry-dmenu .B pinentry-dmenu
is a fork of is a fork of
@ -214,11 +138,6 @@ and uses the api of
.B pinentry-dmenu .B pinentry-dmenu
itself was written by Moritz Lüdecke <ritze@skweez.net>. itself was written by Moritz Lüdecke <ritze@skweez.net>.
.SH REPORTING BUGS
Report pinentry-dmenu bugs to <BUGREPORT>
.SH SEE ALSO .SH SEE ALSO
.BR dmenu (1), .BR dmenu (1),
.BR dwm (1), .BR dwm (1),

View File

@ -1,6 +1,5 @@
/* See LICENSE file for copyright and license details. */ /* See LICENSE file for copyright and license details. */
#include <ctype.h> #include <ctype.h>
#include <libconfig.h>
#include <locale.h> #include <locale.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
@ -25,32 +24,28 @@
#include "pinentry/pinentry.h" #include "pinentry/pinentry.h"
#include "pinentry/memory.h" #include "pinentry/memory.h"
#define CONFIG_DIR "/.gnupg" #define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \
#define CONFIG_FILE "/pinentry-dmenu.conf" * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
#define INTERSECT(x, y, w, h, r) \
(MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \
&& MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
#define LENGTH(X) (sizeof(X) / sizeof(X[0]))
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
#define MINDESCLEN 8 #define MINDESCLEN 8
/* enums */
enum { SchemePrompt, SchemeNormal, SchemeSelect, SchemeDesc, SchemeLast }; enum { SchemePrompt, SchemeNormal, SchemeSelect, SchemeDesc, SchemeLast }; /* color schemes */
enum { WinPin, WinConfirm }; enum { WinPin, WinConfirm };
enum { Ok, NotOk, Cancel };
enum { Nothing, Yes, No }; enum { Nothing, Yes, No };
/* FIXME: this can't currently be set */
static char *embed;
static int bh, mw, mh; static int bh, mw, mh;
static int sel; static int sel;
static int promptw, pdescw; static int promptw, pdescw;
/* Sum of left and right padding */ static int lrpad; /* sum of left and right padding */
static int lrpad;
static size_t cursor; static size_t cursor;
static int screen; static int mon = -1, screen;
static char* pin; static char *pin;
static int pin_len; static int pin_len;
static char* pin_repeat; static char *pin_repeat;
static int pin_repeat_len; static int pin_repeat_len;
static int repeat; static int repeat;
@ -69,7 +64,8 @@ pinentry_t pinentry_info;
#include "config.h" #include "config.h"
static int static int
drawitem(const char* text, Bool sel, int x, int y, int w) { drawitem(const char* text, Bool sel, int x, int y, int w)
{
unsigned int i = (sel) ? SchemeSelect : SchemeNormal; unsigned int i = (sel) ? SchemeSelect : SchemeNormal;
drw_setscheme(drw, scheme[i]); drw_setscheme(drw, scheme[i]);
@ -78,57 +74,54 @@ drawitem(const char* text, Bool sel, int x, int y, int w) {
} }
static void static void
grabfocus(void) { grabfocus(void)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
Window focuswin; Window focuswin;
int i, revertwin; int i, revertwin;
for (i = 0; i < 100; ++i) { for (i = 0; i < 100; ++i) {
XGetInputFocus(dpy, &focuswin, &revertwin); XGetInputFocus(dpy, &focuswin, &revertwin);
if (focuswin == win) { if (focuswin == win)
return; return;
}
XSetInputFocus(dpy, win, RevertToParent, CurrentTime); XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
usleep(1000); nanosleep(&ts, NULL);
} }
die("cannot grab focus"); die("cannot grab focus");
} }
static void static void
grabkeyboard(void) { grabkeyboard(void)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 };
int i; int i;
if (embedded) { if (embed)
return; return;
} /* try to grab keyboard, we may have to wait for another process to ungrab */
/* Try to grab keyboard,
* we may have to wait for another process to ungrab */
for (i = 0; i < 1000; i++) { for (i = 0; i < 1000; i++) {
if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
GrabModeAsync, CurrentTime) == GrabSuccess) { GrabModeAsync, CurrentTime) == GrabSuccess)
return; return;
} nanosleep(&ts, NULL);
usleep(1000);
} }
die("cannot grab keyboard"); die("cannot grab keyboard");
} }
static size_t static size_t
nextrune(int cursor, int inc) { nextrune(int inc)
{
ssize_t n; ssize_t n;
/* Return location of next utf8 rune in the given direction (+1 or -1) */ /* return location of next utf8 rune in the given direction (+1 or -1) */
for (n = cursor + inc; for (n = cursor + inc; n + inc >= 0 && (pin[n] & 0xc0) == 0x80; n += inc)
n + inc >= 0 && (pin[n] & 0xc0) == 0x80; ;
n += inc);
return n; return n;
} }
static void static void
setup_pin(char* pin_ptr, int len, int reset) { setup_pin(char *pin_ptr, int len, int reset)
{
pin = pin_ptr; pin = pin_ptr;
pin_len = len; pin_len = len;
@ -136,14 +129,14 @@ setup_pin(char* pin_ptr, int len, int reset) {
promptw = (prompt) ? TEXTW(prompt) - lrpad / 4 : 0; promptw = (prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
cursor = 0; cursor = 0;
if (pin) { if (pin)
pin[0] = '\0'; pin[0] = '\0';
}
} }
} }
static void static void
insert(const char *str, ssize_t n) { insert(const char *str, ssize_t n)
{
size_t len = strlen(pin); size_t len = strlen(pin);
// FIXME: Pinentry crashes when increasing the pin buffer the second time. // FIXME: Pinentry crashes when increasing the pin buffer the second time.
@ -153,15 +146,13 @@ insert(const char *str, ssize_t n) {
pin_repeat_len = 2 * pin_repeat_len; pin_repeat_len = 2 * pin_repeat_len;
pin_repeat = secmem_realloc(pin_repeat, pin_repeat_len); pin_repeat = secmem_realloc(pin_repeat, pin_repeat_len);
setup_pin(pin_repeat, pin_repeat_len, 0); setup_pin(pin_repeat, pin_repeat_len, 0);
if (!pin_repeat) { if (!pin_repeat)
pin_len = 0; pin_len = 0;
}
} else { } else {
if (!pinentry_setbufferlen(pinentry_info, 2 * pinentry_info->pin_len)) { if (!pinentry_setbufferlen(pinentry_info, 2 * pinentry_info->pin_len))
pin_len = 0; pin_len = 0;
} else { else
setup_pin(pinentry_info->pin, pinentry_info->pin_len, 0); setup_pin(pinentry_info->pin, pinentry_info->pin_len, 0);
}
} }
if (pin_len == 0) { if (pin_len == 0) {
printf("Error: Couldn't allocate secure memory\n"); printf("Error: Couldn't allocate secure memory\n");
@ -169,27 +160,27 @@ insert(const char *str, ssize_t n) {
} }
} }
/* Move existing text out of the way, insert new text, and update cursor */ /* move existing text out of the way, insert new text, and update cursor */
memmove(&pin[cursor + n], &pin[cursor], pin_len - cursor - MAX(n, 0)); memmove(&pin[cursor + n], &pin[cursor], pin_len - cursor - MAX(n, 0));
if (n > 0) { if (n > 0)
memcpy(&pin[cursor], str, n); memcpy(&pin[cursor], str, n);
}
cursor += n; cursor += n;
pin[len + n] = '\0'; pin[len + n] = '\0';
} }
static void static void
drawwin(void) { drawmenu(void)
{
unsigned int curpos; unsigned int curpos;
int x = 0, pb, pbw = 0, i; int x = 0, fh = drw->fonts->h, pb, pbw = 0, i;
size_t asterlen = strlen(asterisk); size_t asterlen = strlen(asterisk);
size_t pdesclen; size_t pdesclen;
int leftinput; int leftinput;
char* censort; char *censort;
char* pprompt = (repeat) ? pinentry_info->repeat_passphrase : pinentry_info->prompt; char *pprompt = (repeat) ? pinentry_info->repeat_passphrase : pinentry_info->prompt;
int ppromptw = (pprompt) ? TEXTW(pprompt) : 0; int ppromptw = (pprompt) ? TEXTW(pprompt) : 0;
unsigned int censortl = minpwlen * TEXTW(asterisk) / strlen(asterisk); unsigned int censortl = minpwlen * TEXTW(asterisk) / strlen(asterisk);
@ -223,11 +214,9 @@ drawwin(void) {
pbw = MIN(pbw, pb); pbw = MIN(pbw, pb);
pb = mw - pbw; pb = mw - pbw;
for (i = 0; i < pdesclen; i++) { for (i = 0; i < pdesclen; i++)
if (pinentry_info->description[i] == '\n') { if (pinentry_info->description[i] == '\n')
pinentry_info->description[i] = ' '; pinentry_info->description[i] = ' ';
}
}
drw_setscheme(drw, scheme[SchemeDesc]); drw_setscheme(drw, scheme[SchemeDesc]);
drw_text(drw, pb, 0, pbw, bh, lrpad / 2, pinentry_info->description, drw_text(drw, pb, 0, pbw, bh, lrpad / 2, pinentry_info->description,
@ -244,18 +233,17 @@ drawwin(void) {
if (winmode == WinPin) { if (winmode == WinPin) {
censort = ecalloc(1, asterlen * pin_len); censort = ecalloc(1, asterlen * pin_len);
for (i = 0; i < asterlen * strlen(pin); i += asterlen) { for (i = 0; i < asterlen * strlen(pin); i += asterlen)
memcpy(&censort[i], asterisk, asterlen); memcpy(&censort[i], asterisk, asterlen);
}
censort[i+1] = '\n'; censort[i+1] = '\n';
leftinput = mw - x - pbw; leftinput = mw - x - pbw;
drw_text(drw, x, 0, leftinput, bh, lrpad / 2, censort, 0); drw_text(drw, x, 0, leftinput, bh, lrpad / 2, censort, 0);
drw_font_getexts(drw->fonts, censort, cursor * asterlen, &curpos, NULL); curpos = TEXTW(censort) - TEXTW(&censort[cursor]);
if ((curpos += lrpad / 2 - 1) < leftinput) { if ((curpos += lrpad / 2 - 1) < leftinput) {
drw_setscheme(drw, scheme[SchemeNormal]); drw_setscheme(drw, scheme[SchemeNormal]);
drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0); drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0);
} }
free(censort); free(censort);
@ -264,29 +252,27 @@ drawwin(void) {
x = drawitem("No", (sel == No), x, 0, TEXTW("No")); x = drawitem("No", (sel == No), x, 0, TEXTW("No"));
x = drawitem("Yes", (sel == Yes), x, 0, TEXTW("Yes")); x = drawitem("Yes", (sel == Yes), x, 0, TEXTW("Yes"));
} }
drw_map(drw, win, 0, 0, mw, mh); drw_map(drw, win, 0, 0, mw, mh);
} }
static void static void
setup(void) { setup(void)
int x, y, i = 0; {
int x, y, i, j;
unsigned int du; unsigned int du;
XSetWindowAttributes swa; XSetWindowAttributes swa;
XIM xim; XIM xim;
Window w, dw, *dws; Window w, dw, *dws;
XWindowAttributes wa; XWindowAttributes wa;
XClassHint ch = {"pinentry-dmenu", "pinentry-dmenu"};
#ifdef XINERAMA #ifdef XINERAMA
XineramaScreenInfo *info; XineramaScreenInfo *info;
Window pw; Window pw;
int a, j, di, n, area = 0; int a, di, n, area = 0;
#endif #endif
/* init appearance */
/* Init appearance */ for (j = 0; j < SchemeLast; j++)
scheme[SchemePrompt] = drw_scm_create(drw, colors[SchemePrompt], 2); scheme[j] = drw_scm_create(drw, colors[j], 2);
scheme[SchemeNormal] = drw_scm_create(drw, colors[SchemeNormal], 2);
scheme[SchemeSelect] = drw_scm_create(drw, colors[SchemeSelect], 2);
scheme[SchemeDesc] = drw_scm_create(drw, colors[SchemeDesc], 2);
clip = XInternAtom(dpy, "CLIPBOARD", False); clip = XInternAtom(dpy, "CLIPBOARD", False);
utf8 = XInternAtom(dpy, "UTF8_STRING", False); utf8 = XInternAtom(dpy, "UTF8_STRING", False);
@ -295,52 +281,43 @@ setup(void) {
bh = drw->fonts->h + 2; bh = drw->fonts->h + 2;
mh = bh; mh = bh;
#ifdef XINERAMA #ifdef XINERAMA
info = XineramaQueryScreens(dpy, &n); i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
if (parentwin == root && info) {
XGetInputFocus(dpy, &w, &di); XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n) { if (mon >= 0 && mon < n)
i = mon; i = mon;
} else if (w != root && w != PointerRoot && w != None) { else if (w != root && w != PointerRoot && w != None) {
/* Find top-level window containing current input focus */ /* find top-level window containing current input focus */
do { do {
if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) { if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
XFree(dws); XFree(dws);
}
} while (w != root && w != pw); } while (w != root && w != pw);
/* Find xinerama screen with which the window intersects most */ /* find xinerama screen with which the window intersects most */
if (XGetWindowAttributes(dpy, pw, &wa)) { if (XGetWindowAttributes(dpy, pw, &wa))
for (j = 0; j < n; j++) { for (j = 0; j < n; j++)
a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j]); if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
if (a > area) {
area = a; area = a;
i = j; i = j;
} }
}
}
} }
/* No focused window is on screen, so use pointer location instead */ /* no focused window is on screen, so use pointer location instead */
if (mon < 0 && !area if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
&& XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) { for (i = 0; i < n; i++)
for (i = 0; i < n; i++) { if (INTERSECT(x, y, 1, 1, info[i]) != 0)
if (INTERSECT(x, y, 1, 1, info[i])) {
break; break;
}
}
}
x = info[i].x_org; x = info[i].x_org;
y = info[i].y_org + (bottom ? info[i].height - mh : 0); y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
mw = info[i].width; mw = info[i].width;
XFree(info); XFree(info);
} else } else
#endif #endif
{ {
if (!XGetWindowAttributes(dpy, parentwin, &wa)) { if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("could not get embedding window attributes: 0x%lx", parentwin); die("could not get embedding window attributes: 0x%lx",
} parentwin);
x = 0; x = 0;
y = bottom ? wa.height - mh : 0; y = topbar ? 0 : wa.height - mh;
mw = wa.width; mw = wa.width;
} }
@ -353,43 +330,44 @@ setup(void) {
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
XSetClassHint(dpy, win, &ch);
/* input methods */
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
die("XOpenIM failed: could not open input device");
/* Open input methods */
xim = XOpenIM(dpy, NULL, NULL, NULL);
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
XNClientWindow, win, XNFocusWindow, win, NULL); XNClientWindow, win, XNFocusWindow, win, NULL);
XMapRaised(dpy, win); XMapRaised(dpy, win);
if (embed) {
if (embedded) { XSelectInput(dpy, parentwin, FocusChangeMask | SubstructureNotifyMask);
XSelectInput(dpy, parentwin, FocusChangeMask);
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
for (i = 0; i < du && dws[i] != win; ++i) { for (i = 0; i < du && dws[i] != win; ++i)
XSelectInput(dpy, dws[i], FocusChangeMask); XSelectInput(dpy, dws[i], FocusChangeMask);
}
XFree(dws); XFree(dws);
} }
grabfocus(); grabfocus();
} }
drw_resize(drw, mw, mh); drw_resize(drw, mw, mh);
} }
static void static void
cleanup(void) { cleanup(void)
{
size_t i;
XUngrabKey(dpy, AnyKey, AnyModifier, root); XUngrabKey(dpy, AnyKey, AnyModifier, root);
free(scheme[SchemeDesc]); for (i = 0; i < SchemeLast; i++)
free(scheme[SchemeSelect]); free(scheme[i]);
free(scheme[SchemeNormal]);
free(scheme[SchemePrompt]);
drw_free(drw); drw_free(drw);
XSync(dpy, False); XSync(dpy, False);
XCloseDisplay(dpy); XCloseDisplay(dpy);
} }
static int static int
keypress_confirm(XKeyEvent *ev, KeySym ksym) { keypress_confirm(XKeyEvent *ev, KeySym ksym)
{
if (ev->state & ControlMask) { if (ev->state & ControlMask) {
switch(ksym) { switch(ksym) {
case XK_c: case XK_c:
@ -404,9 +382,8 @@ keypress_confirm(XKeyEvent *ev, KeySym ksym) {
switch(ksym) { switch(ksym) {
case XK_KP_Enter: case XK_KP_Enter:
case XK_Return: case XK_Return:
if (sel != Nothing) { if (sel != Nothing)
return 1; return 1;
}
break; break;
case XK_y: case XK_y:
case XK_Y: case XK_Y:
@ -425,17 +402,23 @@ keypress_confirm(XKeyEvent *ev, KeySym ksym) {
case XK_h: case XK_h:
case XK_j: case XK_j:
case XK_Home: case XK_Home:
case XK_KP_Home:
case XK_Left: case XK_Left:
case XK_KP_Left:
case XK_Prior: case XK_Prior:
case XK_KP_Prior:
case XK_Up: case XK_Up:
case XK_KP_Up:
sel = No; sel = No;
break; break;
case XK_k: case XK_k:
case XK_l: case XK_l:
case XK_Down: case XK_Down:
case XK_KP_Down:
case XK_End: case XK_End:
case XK_Next: case XK_Next:
case XK_Right: case XK_Right:
case XK_KP_Right:
sel = Yes; sel = Yes;
break; break;
} }
@ -444,7 +427,8 @@ keypress_confirm(XKeyEvent *ev, KeySym ksym) {
} }
static int static int
keypress_pin(XKeyEvent *ev, KeySym ksym, char* buf, int len) { keypress_pin(XKeyEvent *ev, KeySym ksym, char* buf, int len)
{
int old; int old;
if (ev->state & ControlMask) { if (ev->state & ControlMask) {
@ -482,34 +466,35 @@ keypress_pin(XKeyEvent *ev, KeySym ksym, char* buf, int len) {
switch(ksym) { switch(ksym) {
case XK_Delete: case XK_Delete:
if (pin[cursor] == '\0') { case XK_KP_Delete:
if (pin[cursor] == '\0')
return 0; return 0;
} cursor = nextrune(+1);
cursor = nextrune(cursor, +1);
/* Fallthrough */ /* Fallthrough */
case XK_BackSpace: case XK_BackSpace:
if (cursor == 0) { if (cursor == 0)
return 0; return 0;
} insert(NULL, nextrune(-1) - cursor);
insert(NULL, nextrune(cursor, -1) - cursor);
break; break;
case XK_Escape: case XK_Escape:
pinentry_info->canceled = 1; pinentry_info->canceled = 1;
return 1; return 1;
case XK_Left: case XK_Left:
if (cursor > 0) { case XK_KP_Left:
cursor = nextrune(cursor, -1); if (cursor > 0)
} cursor = nextrune(-1);
break; break;
case XK_Right: case XK_Right:
if (pin[cursor] != '\0') { case XK_KP_Right:
cursor = nextrune(cursor, +1); if (pin[cursor] != '\0')
} cursor = nextrune(+1);
break; break;
case XK_Home: case XK_Home:
case XK_KP_Home:
cursor = 0; cursor = 0;
break; break;
case XK_End: case XK_End:
case XK_KP_End:
cursor = strlen(pin); cursor = strlen(pin);
break; break;
case XK_Return: case XK_Return:
@ -517,16 +502,16 @@ keypress_pin(XKeyEvent *ev, KeySym ksym, char* buf, int len) {
return 1; return 1;
break; break;
default: default:
if (!iscntrl(*buf)) { if (!iscntrl((unsigned char)*buf))
insert(buf, len); insert(buf, len);
}
} }
return 0; return 0;
} }
static int static int
keypress(XKeyEvent *ev) { keypress(XKeyEvent *ev)
{
char buf[32]; char buf[32];
int len; int len;
int ret = 1; int ret = 1;
@ -536,79 +521,83 @@ keypress(XKeyEvent *ev) {
len = XmbLookupString(xic, ev, buf, sizeof(buf), &ksym, &status); len = XmbLookupString(xic, ev, buf, sizeof(buf), &ksym, &status);
if (status != XBufferOverflow) { if (status != XBufferOverflow) {
if (winmode == WinConfirm) { if (winmode == WinConfirm)
ret = keypress_confirm(ev, ksym); ret = keypress_confirm(ev, ksym);
} else { else
ret = keypress_pin(ev, ksym, buf, len); ret = keypress_pin(ev, ksym, buf, len);
}
if (ret == 0) { if (ret == 0)
drawwin(); drawmenu();
}
} }
return ret; return ret;
} }
static void static void
paste(void) { paste(void)
{
char *p, *q; char *p, *q;
int di; int di;
unsigned long dl; unsigned long dl;
Atom da; Atom da;
/* We have been given the current selection, now insert it into input */ /* we have been given the current selection, now insert it into input */
XGetWindowProperty(dpy, win, utf8, 0, pin_len / 4, False, utf8, &da, &di, if (XGetWindowProperty(dpy, win, utf8, 0, (pin_len/ 4) + 1, False,
&dl, &dl, (unsigned char **)&p); utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t) strlen(p)); == Success && p) {
XFree(p); insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p));
drawwin(); XFree(p);
}
drawmenu();
} }
void void
run(void) { run(void)
{
XEvent ev; XEvent ev;
drawwin(); drawmenu();
while (!XNextEvent(dpy, &ev)) { while (!XNextEvent(dpy, &ev)) {
if (XFilterEvent(&ev, win)) { if (XFilterEvent(&ev, win))
continue; continue;
}
switch(ev.type) { switch(ev.type) {
case DestroyNotify:
if (ev.xdestroywindow.window != win)
break;
cleanup();
exit(1);
case Expose: case Expose:
if (ev.xexpose.count == 0) { if (ev.xexpose.count == 0)
drw_map(drw, win, 0, 0, mw, mh); drw_map(drw, win, 0, 0, mw, mh);
}
break; break;
case KeyPress: case KeyPress:
if (keypress(&ev.xkey)) { if (keypress(&ev.xkey))
return; return;
}
break; break;
case SelectionNotify: case SelectionNotify:
if (ev.xselection.property == utf8) { if (ev.xselection.property == utf8)
paste(); paste();
}
break; break;
case VisibilityNotify: case VisibilityNotify:
if (ev.xvisibility.state != VisibilityUnobscured) { if (ev.xvisibility.state != VisibilityUnobscured)
XRaiseWindow(dpy, win); XRaiseWindow(dpy, win);
}
break; break;
} }
} }
} }
/* FIXME: this does nothing */
static void static void
catchsig(int sig) { catchsig(int sig)
if (sig == SIGALRM) { {
if (sig == SIGALRM)
timed_out = 1; timed_out = 1;
}
} }
static void static void
password(void) { password(void)
{
winmode = WinPin; winmode = WinPin;
repeat = 0; repeat = 0;
setup_pin(pinentry_info->pin, pinentry_info->pin_len, 1); setup_pin(pinentry_info->pin, pinentry_info->pin_len, 1);
@ -639,7 +628,8 @@ password(void) {
} }
static void static void
confirm(void) { confirm(void)
{
winmode = WinConfirm; winmode = WinConfirm;
sel = Nothing; sel = Nothing;
run(); run();
@ -647,30 +637,33 @@ confirm(void) {
} }
static int static int
cmdhandler(pinentry_t received_pinentry) { cmdhandler(pinentry_t received_pinentry)
{
struct sigaction sa; struct sigaction sa;
XWindowAttributes wa; XWindowAttributes wa;
pinentry_info = received_pinentry; pinentry_info = received_pinentry;
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) { if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr); fputs("warning: no locale support\n", stderr);
} if (!(dpy = XOpenDisplay(pinentry_info->display)))
if (!(dpy = XOpenDisplay(pinentry_info->display))) {
die("cannot open display"); die("cannot open display");
}
screen = DefaultScreen(dpy); screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen); root = RootWindow(dpy, screen);
embedded = (pinentry_info->parent_wid) ? embedded : 0; embed = (pinentry_info->parent_wid) ? embed : 0;
parentwin = (embedded) ? pinentry_info->parent_wid : root; parentwin = (embed) ? pinentry_info->parent_wid : root;
if (!XGetWindowAttributes(dpy, parentwin, &wa)) { if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("could not get embedding window attributes: 0x%lx", parentwin); die("could not get embedding window attributes: 0x%lx", parentwin);
}
drw = drw_create(dpy, screen, root, wa.width, wa.height); drw = drw_create(dpy, screen, root, wa.width, wa.height);
if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) { if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
die("no fonts could be loaded."); die("no fonts could be loaded.");
}
lrpad = drw->fonts->h; lrpad = drw->fonts->h;
#ifdef __OpenBSD__
if (pledge("stdio rpath", NULL) == -1)
die("pledge");
#endif
drw_setscheme(drw, scheme[SchemePrompt]); drw_setscheme(drw, scheme[SchemePrompt]);
if (pinentry_info->timeout) { if (pinentry_info->timeout) {
@ -683,14 +676,13 @@ cmdhandler(pinentry_t received_pinentry) {
grabkeyboard(); grabkeyboard();
setup(); setup();
if (pinentry_info->pin) { if (pinentry_info->pin)
do { do {
password(); password();
} while (!pinentry_info->canceled && pinentry_info->repeat_passphrase } while (!pinentry_info->canceled && pinentry_info->repeat_passphrase
&& !pinentry_info->repeat_okay); && !pinentry_info->repeat_okay);
} else { else
confirm(); confirm();
}
cleanup(); cleanup();
@ -700,100 +692,13 @@ cmdhandler(pinentry_t received_pinentry) {
pinentry_cmd_handler_t pinentry_cmd_handler = cmdhandler; pinentry_cmd_handler_t pinentry_cmd_handler = cmdhandler;
int int
main(int argc, char *argv[]) { main(int argc, char *argv[])
Bool bval; {
int i, val;
const char *str;
struct passwd *pw;
char path[PATH_MAX];
char *sudo_uid = getenv("SUDO_UID");
char *home = getenv("HOME");
char *gnupghome = getenv("GNUPGHOME");
config_t cfg;
if (gnupghome) {
i = strlen(gnupghome);
strcpy(path, gnupghome);
} else {
/* Get the home dir even if the user used sudo or logged in as root */
if (sudo_uid) {
i = atoi(sudo_uid);
pw = getpwuid(i);
home = pw->pw_dir;
}
i = strlen(home);
strcpy(path, home);
strcpy(&path[i], CONFIG_DIR);
i += strlen(CONFIG_DIR);
}
strcpy(&path[i], CONFIG_FILE);
endpwent();
config_init(&cfg);
/* Read the file. If there is an error, report it and exit. */
if (config_read_file(&cfg, path)) {
if (config_lookup_string(&cfg, "asterisk", &str)) {
asterisk = str;
}
if (config_lookup_bool(&cfg, "bottom", &bval)) {
bottom = bval;
}
if (config_lookup_int(&cfg, "min_password_length", &val)) {
minpwlen = val;
}
if (config_lookup_int(&cfg, "monitor", &val)) {
mon = val;
}
if (config_lookup_string(&cfg, "prompt", &str)) {
prompt = str;
}
if (config_lookup_string(&cfg, "font", &str)) {
fonts[0] = str;
}
if (config_lookup_string(&cfg, "prompt_bg", &str)) {
colors[SchemePrompt][ColBg] = str;
}
if (config_lookup_string(&cfg, "prompt_fg", &str)) {
colors[SchemePrompt][ColFg] = str;
}
if (config_lookup_string(&cfg, "normal_bg", &str)) {
colors[SchemeNormal][ColBg] = str;
}
if (config_lookup_string(&cfg, "normal_fg", &str)) {
colors[SchemeNormal][ColFg] = str;
}
if (config_lookup_string(&cfg, "select_bg", &str)) {
colors[SchemeSelect][ColBg] = str;
}
if (config_lookup_string(&cfg, "select_fg", &str)) {
colors[SchemeSelect][ColFg] = str;
}
if (config_lookup_string(&cfg, "desc_bg", &str)) {
colors[SchemeDesc][ColBg] = str;
}
if (config_lookup_string(&cfg, "desc_fg", &str)) {
colors[SchemeDesc][ColFg] = str;
}
if (config_lookup_bool(&cfg, "embedded", &bval)) {
embedded = bval;
}
} else if ((str = config_error_file(&cfg))) {
fprintf(stderr, "%s:%d: %s\n", config_error_file(&cfg),
config_error_line(&cfg), config_error_text(&cfg));
return(EXIT_FAILURE);
}
pinentry_init("pinentry-dmenu"); pinentry_init("pinentry-dmenu");
pinentry_parse_opts(argc, argv); pinentry_parse_opts(argc, argv);
if (pinentry_loop()) { if (pinentry_loop())
return 1; return 1;
}
config_destroy(&cfg);
return 0; return 0;
} }

View File

@ -1,21 +0,0 @@
include ../config.mk
SRC = util.c pinentry.c argparse.c password-cache.c secmem.c
OBJ = ${SRC:.c=.o}
CFLAGS += -DHAVE_MLOCK
all: pinentry
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: pinentry.h argparse.h password-cache.h memory.h util.h
pinentry: pinentry.o argparse.o password-cache.o secmem.o util.o
clean:
@echo cleaning
@rm -f ${OBJ}
.PHONY: all clean pinentry

View File

@ -1,91 +0,0 @@
/* STL allocator for secmem
* Copyright (C) 2008 Marc Mutz <marc@kdab.com>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __SECMEM_SECMEMPP_H__
#define __SECMEM_SECMEMPP_H__
#include "secmem/memory.h"
#include <cstddef>
namespace secmem {
template <typename T>
class alloc {
public:
// type definitions:
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
// rebind
template <typename U>
struct rebind {
typedef alloc<U> other;
};
// address
pointer address( reference value ) const {
return &value;
}
const_pointer address( const_reference value ) const {
return &value;
}
// (trivial) ctors and dtors
alloc() {}
alloc( const alloc & ) {}
template <typename U> alloc( const alloc<U> & ) {}
// copy ctor is ok
~alloc() {}
// de/allocation
size_type max_size() const {
return secmem_get_max_size();
}
pointer allocate( size_type n, void * =0 ) {
return static_cast<pointer>( secmem_malloc( n * sizeof(T) ) );
}
void deallocate( pointer p, size_type ) {
secmem_free( p );
}
// de/construct
void construct( pointer p, const T & value ) {
void * loc = p;
new (loc)T(value);
}
void destruct( pointer p ) {
p->~T();
}
};
// equality comparison
template <typename T1,typename T2>
bool operator==( const alloc<T1> &, const alloc<T2> & ) { return true; }
template <typename T1, typename T2>
bool operator!=( const alloc<T1> &, const alloc<T2> & ) { return false; }
}
#endif /* __SECMEM_SECMEMPP_H__ */

6
test
View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
if [[ $1 -eq 1 ]]; then if [ $1 -eq 1 ]; then
echo "SETTITLE title echo "SETTITLE title
SETPROMPT prompt SETPROMPT prompt
@ -8,7 +8,7 @@ SETDESC PROMPT
GETPIN GETPIN
BYE" | ./pinentry-dmenu BYE" | ./pinentry-dmenu
elif [[ $1 -eq 2 ]]; then elif [ $1 -eq 2 ]; then
echo "SETTITLE title echo "SETTITLE title
SETPROMPT confirm SETPROMPT confirm
@ -16,7 +16,7 @@ SETDESC CONFIRM
confirm confirm
BYE" | ./pinentry-dmenu BYE" | ./pinentry-dmenu
elif [[ $1 -eq 3 ]]; then elif [ $1 -eq 3 ]; then
echo "SETTITLE title echo "SETTITLE title
SETPROMPT prompt SETPROMPT prompt

23
util.c
View File

@ -6,18 +6,9 @@
#include "util.h" #include "util.h"
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}
void void
die(const char *fmt, ...) { die(const char *fmt, ...)
{
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
@ -33,3 +24,13 @@ die(const char *fmt, ...) {
exit(1); exit(1);
} }
void *
ecalloc(size_t nmemb, size_t size)
{
void *p;
if (!(p = calloc(nmemb, size)))
die("calloc:");
return p;
}

1
util.h
View File

@ -3,6 +3,7 @@
#define MAX(A, B) ((A) > (B) ? (A) : (B)) #define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MIN(A, B) ((A) < (B) ? (A) : (B))
#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) #define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B))
#define LENGTH(X) (sizeof (X) / sizeof (X)[0])
void die(const char *fmt, ...); void die(const char *fmt, ...);
void *ecalloc(size_t nmemb, size_t size); void *ecalloc(size_t nmemb, size_t size);