commit dc349050d70345b448ae4d359cb20f634919a2a4 from: Benjamin Stürz date: Fri Jul 19 13:15:13 2024 UTC remove pinentry-dmenu commit - 6f0a03b88dab13c5b9dbb264ad6087abda50c90a commit + dc349050d70345b448ae4d359cb20f634919a2a4 blob - 186e69be0ae503732e3a9db3d3456a3041bd5276 blob + 343ef4bad293ee4c2924bd3d989327cfe3bc6cf2 --- Makefile +++ Makefile @@ -22,30 +22,11 @@ HDR_STEST = dmenu/arg.h SRC_SLOCK = slock/slock.c HDR_SLOCK = slock/arg.h slock/config.h slock/util.h -SRC_PD = pinentry-dmenu/pinentry-dmenu.c \ - pinentry-dmenu/drw.c \ - pinentry-dmenu/util.c \ - pinentry-dmenu/pinentry/pinentry.c \ - pinentry-dmenu/pinentry/util.c \ - pinentry-dmenu/pinentry/password-cache.c \ - pinentry-dmenu/pinentry/argparse.c \ - pinentry-dmenu/pinentry/secmem.c -HDR_PD = master.h \ - pinentry-dmenu/config.h \ - pinentry-dmenu/drw.h \ - pinentry-dmenu/util.h \ - pinentry-dmenu/pinentry/argparse.h \ - pinentry-dmenu/pinentry/memory.h \ - pinentry-dmenu/pinentry/util.h \ - pinentry-dmenu/pinentry/password-cache.h \ - pinentry-dmenu/pinentry/secmem-util.h \ - pinentry-dmenu/pinentry/pinentry.h - SRC_PD2 = pinentry-dmenu2.sh -MAN = dwm/dwm.1 st/st.1 dmenu/dmenu.1 dmenu/stest.1 slock/slock.1 pinentry-dmenu/pinentry-dmenu.1 +MAN = dwm/dwm.1 st/st.1 dmenu/dmenu.1 dmenu/stest.1 slock/slock.1 -all: bin/dwm bin/st bin/bedstatus bin/dmenu bin/stest bin/xbgcd bin/slock bin/pinentry-dmenu bin/pinentry-dmenu2 +all: bin/dwm bin/st bin/bedstatus bin/dmenu bin/stest bin/xbgcd bin/slock bin/pinentry-dmenu2 check: find etc/common etc/$$(uname) -not -type d | awk '{a=$$0; sub(/etc\/[^\/]+/, "/etc", a); system("diff -u " $$0 " " a)}' @@ -107,10 +88,6 @@ bin/slock: ${SRC_SLOCK} ${HDR_SLOCK} @mkdir -p bin ${CC} -o $@ ${SRC_SLOCK} ${CFLAGS} `pkg-config --cflags --libs x11 xext xrandr` -lpthread -bin/pinentry-dmenu: ${SRC_PD} ${HDR_PD} - @mkdir -p bin - ${CC} -o $@ ${SRC_PD} ${CFLAGS} `pkg-config --cflags --libs libassuan gpg-error fontconfig freetype2 x11 xft xinerama` - bin/pinentry-dmenu2: ${SRC_PD2} @mkdir -p bin cp -f ${SRC_PD2} $@ blob - c7aea1896f776a9dea105ff388d6058a612d4961 (mode 644) blob + /dev/null --- pinentry-dmenu/LICENSE +++ /dev/null @@ -1,280 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS blob - f9e400ea366d163a64889d0807e1c0dd0f4d7c47 (mode 644) blob + /dev/null --- pinentry-dmenu/config.h +++ /dev/null @@ -1,23 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -/* Default settings; can be overriden by command line. */ - -#include "../master.h" - -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 *fonts[] = { - TOPBAR_FONT -}; -static const char *prompt = NULL; -static const char *colors[SchemeLast][4] = { - [SchemePrompt] = { "#bbbbbb", "#222222" }, - [SchemeNormal] = { "#bbbbbb", "#222222" }, - [SchemeSelect] = { "#eeeeee", "#005577" }, - [SchemeDesc] = { "#bbbbbb", "#222222" } -}; blob - c1582e746cc57b7a475c1de3fcc53507cdb50b37 (mode 644) blob + /dev/null --- pinentry-dmenu/drw.c +++ /dev/null @@ -1,421 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include - -#include "drw.h" -#include "util.h" - -#define UTF_INVALID 0xFFFD -#define UTF_SIZ 4 - -static const unsigned char utfbyte[UTF_SIZ + 1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static const unsigned char utfmask[UTF_SIZ + 1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static const long utfmin[UTF_SIZ + 1] = { 0, 0, 0x80, 0x800, 0x10000}; -static const long utfmax[UTF_SIZ + 1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -static long -utf8decodebyte(const char c, size_t *i) -{ - for (*i = 0; *i < (UTF_SIZ + 1); ++(*i)) - if (((unsigned char)c & utfmask[*i]) == utfbyte[*i]) - return (unsigned char)c & ~utfmask[*i]; - return 0; -} - -static size_t -utf8validate(long *u, size_t i) -{ - if (!BETWEEN(*u, utfmin[i], utfmax[i]) || BETWEEN(*u, 0xD800, 0xDFFF)) - *u = UTF_INVALID; - for (i = 1; *u > utfmax[i]; ++i) - ; - return i; -} - -static size_t -utf8decode(const char *c, long *u, size_t clen) -{ - size_t i, j, len, type; - long udecoded; - - *u = UTF_INVALID; - if (!clen) - return 0; - udecoded = utf8decodebyte(c[0], &len); - if (!BETWEEN(len, 1, UTF_SIZ)) - return 1; - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | utf8decodebyte(c[i], &type); - if (type) - return j; - } - if (j < len) - return 0; - *u = udecoded; - utf8validate(u, len); - - return len; -} - -Drw * -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) -{ - Drw *drw = ecalloc(1, sizeof(Drw)); - - drw->dpy = dpy; - drw->screen = screen; - drw->root = root; - drw->w = w; - drw->h = h; - drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); - drw->gc = XCreateGC(dpy, root, 0, NULL); - XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); - - return drw; -} - -void -drw_resize(Drw *drw, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - drw->w = w; - drw->h = h; - if (drw->drawable) - XFreePixmap(drw->dpy, drw->drawable); - drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); -} - -void -drw_free(Drw *drw) -{ - XFreePixmap(drw->dpy, drw->drawable); - XFreeGC(drw->dpy, drw->gc); - free(drw); -} - -/* This function is an implementation detail. Library users should use - * drw_fontset_create instead. - */ -static Fnt * -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) -{ - Fnt *font; - XftFont *xfont = NULL; - FcPattern *pattern = NULL; - - if (fontname) { - /* Using the pattern found at font->xfont->pattern does not yield the - * same substitution results as using the pattern returned by - * FcNameParse; using the latter results in the desired fallback - * behaviour whereas the former just results in missing-character - * rectangles being drawn, at least with some fonts. */ - if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { - fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); - return NULL; - } - if (!(pattern = FcNameParse((FcChar8 *) fontname))) { - fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); - XftFontClose(drw->dpy, xfont); - return NULL; - } - } else if (fontpattern) { - if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { - fprintf(stderr, "error, cannot load font from pattern.\n"); - return NULL; - } - } else { - die("no font specified."); - } - - font = ecalloc(1, sizeof(Fnt)); - font->xfont = xfont; - font->pattern = pattern; - font->h = xfont->ascent + xfont->descent; - font->dpy = drw->dpy; - - return font; -} - -static void -xfont_free(Fnt *font) -{ - if (!font) - return; - if (font->pattern) - FcPatternDestroy(font->pattern); - XftFontClose(font->dpy, font->xfont); - free(font); -} - -Fnt* -drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) -{ - Fnt *cur, *ret = NULL; - size_t i; - - if (!drw || !fonts) - return NULL; - - for (i = 1; i <= fontcount; i++) { - if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { - cur->next = ret; - ret = cur; - } - } - return (drw->fonts = ret); -} - -void -drw_fontset_free(Fnt *font) -{ - if (font) { - drw_fontset_free(font->next); - xfont_free(font); - } -} - -void -drw_clr_create(Drw *drw, Clr *dest, const char *clrname) -{ - if (!drw || !dest || !clrname) - return; - - if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen), - clrname, dest)) - die("error, cannot allocate color '%s'", clrname); -} - -/* Wrapper to create color schemes. The caller has to call free(3) on the - * returned color scheme when done using it. */ -Clr * -drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) -{ - size_t i; - Clr *ret; - - /* need at least two colors for a scheme */ - if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) - return NULL; - - for (i = 0; i < clrcount; i++) - drw_clr_create(drw, &ret[i], clrnames[i]); - return ret; -} - -void -drw_setfontset(Drw *drw, Fnt *set) -{ - if (drw) - drw->fonts = set; -} - -void -drw_setscheme(Drw *drw, Clr *scm) -{ - if (drw) - drw->scheme = scm; -} - -void -drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert) -{ - if (!drw || !drw->scheme) - return; - XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); - if (filled) - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - else - XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); -} - -int -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; - unsigned int ew; - XftDraw *d = NULL; - Fnt *usedfont, *curfont, *nextfont; - size_t i, len; - int utf8strlen, utf8charlen, render = x || y || w || h; - long utf8codepoint = 0; - const char *utf8str; - FcCharSet *fccharset; - FcPattern *fcpattern; - FcPattern *match; - XftResult result; - int charexists = 0; - - if (!drw || (render && !drw->scheme) || !text || !drw->fonts) - return 0; - - if (!render) { - w = ~w; - } else { - XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); - XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); - d = XftDrawCreate(drw->dpy, drw->drawable, - DefaultVisual(drw->dpy, drw->screen), - DefaultColormap(drw->dpy, drw->screen)); - x += lpad; - w -= lpad; - } - - usedfont = drw->fonts; - while (1) { - utf8strlen = 0; - utf8str = text; - nextfont = NULL; - while (*text) { - utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); - for (curfont = drw->fonts; curfont; curfont = curfont->next) { - charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); - if (charexists) { - if (curfont == usedfont) { - utf8strlen += utf8charlen; - text += utf8charlen; - } else { - nextfont = curfont; - } - break; - } - } - - if (!charexists || nextfont) - break; - else - charexists = 0; - } - - if (utf8strlen) { - drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL); - /* shorten text if necessary */ - for (len = MIN(utf8strlen, sizeof(buf) - 1); len && ew > w; len--) - drw_font_getexts(usedfont, utf8str, len, &ew, NULL); - - 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; - } - } - - if (!*text) { - break; - } else if (nextfont) { - charexists = 0; - usedfont = nextfont; - } else { - /* Regardless of whether or not a fallback font is found, the - * character must be drawn. */ - charexists = 1; - - fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, utf8codepoint); - - if (!drw->fonts->pattern) { - /* Refer to the comment in xfont_create for more information. */ - die("the first font in the cache must be loaded from a font string."); - } - - fcpattern = FcPatternDuplicate(drw->fonts->pattern); - FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); - FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); - - FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); - FcDefaultSubstitute(fcpattern); - match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); - - FcCharSetDestroy(fccharset); - FcPatternDestroy(fcpattern); - - if (match) { - usedfont = xfont_create(drw, NULL, match); - if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { - for (curfont = drw->fonts; curfont->next; curfont = curfont->next) - ; /* NOP */ - curfont->next = usedfont; - } else { - xfont_free(usedfont); - usedfont = drw->fonts; - } - } - } - } - if (d) - XftDrawDestroy(d); - - return x + (render ? w : 0); -} - -void -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) -{ - if (!drw) - return; - - XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); - XSync(drw->dpy, False); -} - -unsigned int -drw_fontset_getwidth(Drw *drw, const char *text) -{ - if (!drw || !drw->fonts || !text) - return 0; - return drw_text(drw, 0, 0, 0, 0, 0, text, 0); -} - -void -drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) -{ - XGlyphInfo ext; - - if (!font || !text) - return; - - XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); - if (w) - *w = ext.xOff; - if (h) - *h = font->h; -} - -Cur * -drw_cur_create(Drw *drw, int shape) -{ - Cur *cur; - - if (!drw || !(cur = ecalloc(1, sizeof(Cur)))) - return NULL; - - cur->cursor = XCreateFontCursor(drw->dpy, shape); - - return cur; -} - -void -drw_cur_free(Drw *drw, Cur *cursor) -{ - if (!cursor) - return; - - XFreeCursor(drw->dpy, cursor->cursor); - free(cursor); -} blob - 4c67419a98dd6d87e0b15e6f14094f24aa44c143 (mode 644) blob + /dev/null --- pinentry-dmenu/drw.h +++ /dev/null @@ -1,57 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -typedef struct { - Cursor cursor; -} Cur; - -typedef struct Fnt { - Display *dpy; - unsigned int h; - XftFont *xfont; - FcPattern *pattern; - struct Fnt *next; -} Fnt; - -enum { ColFg, ColBg }; /* Clr scheme index */ -typedef XftColor Clr; - -typedef struct { - unsigned int w, h; - Display *dpy; - int screen; - Window root; - Drawable drawable; - GC gc; - Clr *scheme; - Fnt *fonts; -} Drw; - -/* Drawable abstraction */ -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); -void drw_resize(Drw *drw, unsigned int w, unsigned int h); -void drw_free(Drw *drw); - -/* Fnt abstraction */ -Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount); -void drw_fontset_free(Fnt* set); -unsigned int drw_fontset_getwidth(Drw *drw, const char *text); -void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h); - -/* Colorscheme abstraction */ -void drw_clr_create(Drw *drw, Clr *dest, const char *clrname); -Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount); - -/* Cursor abstraction */ -Cur *drw_cur_create(Drw *drw, int shape); -void drw_cur_free(Drw *drw, Cur *cursor); - -/* Drawing context manipulation */ -void drw_setfontset(Drw *drw, Fnt *set); -void drw_setscheme(Drw *drw, Clr *scm); - -/* Drawing functions */ -void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert); -int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); - -/* Map functions */ -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); blob - 695d0bae2fc394836118e15ec86ca097bdbe9ceb (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/AUTHORS +++ /dev/null @@ -1,11 +0,0 @@ -Program: Pinentry -Bug reports: -Security related bug reports: -License: GPLv2+ - -Robert Bihlmeyer -Werner Koch, g10 Code GmbH -Steffen Hansen, Klarälvdalens Datakonsult AB -Marcus Brinkmann, g10 Code GmbH -Timo Schulz, g10 Code GmbH -Neal Walfied, g10 Code GmbH blob - c7aea1896f776a9dea105ff388d6058a612d4961 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/COPYING +++ /dev/null @@ -1,280 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS blob - 4de24703f540b239f128d04550337e58d769936b (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/Makefile +++ /dev/null @@ -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 blob - ba9d3b1a2b268af3d20bb9faf725277c19d87a85 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/argparse.c +++ /dev/null @@ -1,1609 +0,0 @@ -/* [argparse.c wk 17.06.97] Argument Parser for option handling - * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc. - * Copyright (C) 1997-2001, 2006-2008, 2013-2015 Werner Koch - * - * This file is part of JNLIB, which is a subsystem of GnuPG. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of either - * - * - the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at - * your option) any later version. - * - * or - * - * - 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. - * - * or both in parallel, as here. - * - * JNLIB 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 copies of the GNU General Public License - * and the GNU Lesser General Public License along with this program; - * if not, see . - */ - -/* This file may be used as part of GnuPG or standalone. A GnuPG - build is detected by the presence of the macro GNUPG_MAJOR_VERSION. - Some feature are only availalbe in the GnuPG build mode. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef GNUPG_MAJOR_VERSION -# include "libjnlib-config.h" -# include "mischelp.h" -# include "stringhelp.h" -# include "logging.h" -# ifdef JNLIB_NEED_UTF8CONV -# include "utf8conv.h" -# endif -#endif /*GNUPG_MAJOR_VERSION*/ - -#include "argparse.h" - -/* GnuPG uses GPLv3+ but a standalone version of this defaults to - GPLv2+ because that is the license of this file. Change this if - you include it in a program which uses GPLv3. If you don't want to - set a a copyright string for your usage() you may also hardcode it - here. */ -#ifndef GNUPG_MAJOR_VERSION - -# define ARGPARSE_GPL_VERSION 2 -# define ARGPARSE_CRIGHT_STR "Copyright (C) YEAR NAME" - -#else /* Used by GnuPG */ - -# define ARGPARSE_GPL_VERSION 3 -# define ARGPARSE_CRIGHT_STR "Copyright (C) 2015 Free Software Foundation, Inc." - -#endif /*GNUPG_MAJOR_VERSION*/ - -/* Replacements for standalone builds. */ -#ifndef GNUPG_MAJOR_VERSION -# ifndef _ -# define _(a) (a) -# endif -# ifndef DIM -# define DIM(v) (sizeof(v)/sizeof((v)[0])) -# endif -# define jnlib_malloc(a) malloc ((a)) -# define jnlib_realloc(a,b) realloc ((a), (b)) -# define jnlib_strdup(a) strdup ((a)) -# define jnlib_free(a) free ((a)) -# define jnlib_log_error my_log_error -# define jnlib_log_bug my_log_bug -# define trim_spaces(a) my_trim_spaces ((a)) -# define map_static_macro_string(a) (a) -#endif /*!GNUPG_MAJOR_VERSION*/ - - -#define ARGPARSE_STR(v) #v -#define ARGPARSE_STR2(v) ARGPARSE_STR(v) - - -/* Replacements for standalone builds. */ -#ifndef GNUPG_MAJOR_VERSION -static void -my_log_error (const char *fmt, ...) -{ - va_list arg_ptr ; - - va_start (arg_ptr, fmt); - fprintf (stderr, "%s: ", strusage (11)); - vfprintf (stderr, fmt, arg_ptr); - va_end (arg_ptr); -} - -static void -my_log_bug (const char *fmt, ...) -{ - va_list arg_ptr ; - - va_start (arg_ptr, fmt); - fprintf (stderr, "%s: Ohhhh jeeee: ", strusage (11)); - vfprintf (stderr, fmt, arg_ptr); - va_end (arg_ptr); - abort (); -} - -static char * -my_trim_spaces (char *str) -{ - char *string, *p, *mark; - - string = str; - /* Find first non space character. */ - for (p=string; *p && isspace (*(unsigned char*)p) ; p++) - ; - /* Move characters. */ - for ((mark = NULL); (*string = *p); string++, p++) - if (isspace (*(unsigned char*)p)) - { - if (!mark) - mark = string; - } - else - mark = NULL; - if (mark) - *mark = '\0' ; /* Remove trailing spaces. */ - - return str ; -} - -#endif /*!GNUPG_MAJOR_VERSION*/ - - - -/********************************* - * @Summary arg_parse - * #include "argparse.h" - * - * typedef struct { - * char *argc; pointer to argc (value subject to change) - * char ***argv; pointer to argv (value subject to change) - * unsigned flags; Global flags (DO NOT CHANGE) - * int err; print error about last option - * 1 = warning, 2 = abort - * int r_opt; return option - * int r_type; type of return value (0 = no argument found) - * union { - * int ret_int; - * long ret_long - * ulong ret_ulong; - * char *ret_str; - * } r; Return values - * struct { - * int idx; - * const char *last; - * void *aliases; - * } internal; DO NOT CHANGE - * } ARGPARSE_ARGS; - * - * typedef struct { - * int short_opt; - * const char *long_opt; - * unsigned flags; - * } ARGPARSE_OPTS; - * - * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts ); - * - * @Description - * This is my replacement for getopt(). See the example for a typical usage. - * Global flags are: - * Bit 0 : Do not remove options form argv - * Bit 1 : Do not stop at last option but return other args - * with r_opt set to -1. - * Bit 2 : Assume options and real args are mixed. - * Bit 3 : Do not use -- to stop option processing. - * Bit 4 : Do not skip the first arg. - * Bit 5 : allow usage of long option with only one dash - * Bit 6 : ignore --version - * all other bits must be set to zero, this value is modified by the - * function, so assume this is write only. - * Local flags (for each option): - * Bit 2-0 : 0 = does not take an argument - * 1 = takes int argument - * 2 = takes string argument - * 3 = takes long argument - * 4 = takes ulong argument - * Bit 3 : argument is optional (r_type will the be set to 0) - * Bit 4 : allow 0x etc. prefixed values. - * Bit 6 : Ignore this option - * Bit 7 : This is a command and not an option - * You stop the option processing by setting opts to NULL, the function will - * then return 0. - * @Return Value - * Returns the args.r_opt or 0 if ready - * r_opt may be -2/-7 to indicate an unknown option/command. - * @See Also - * ArgExpand - * @Notes - * You do not need to process the options 'h', '--help' or '--version' - * because this function includes standard help processing; but if you - * specify '-h', '--help' or '--version' you have to do it yourself. - * The option '--' stops argument processing; if bit 1 is set the function - * continues to return normal arguments. - * To process float args or unsigned args you must use a string args and do - * the conversion yourself. - * @Example - * - * ARGPARSE_OPTS opts[] = { - * { 'v', "verbose", 0 }, - * { 'd', "debug", 0 }, - * { 'o', "output", 2 }, - * { 'c', "cross-ref", 2|8 }, - * { 'm', "my-option", 1|8 }, - * { 300, "ignored-long-option, ARGPARSE_OP_IGNORE}, - * { 500, "have-no-short-option-for-this-long-option", 0 }, - * {0} }; - * ARGPARSE_ARGS pargs = { &argc, &argv, 0 } - * - * while( ArgParse( &pargs, &opts) ) { - * switch( pargs.r_opt ) { - * case 'v': opt.verbose++; break; - * case 'd': opt.debug++; break; - * case 'o': opt.outfile = pargs.r.ret_str; break; - * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - * case 500: opt.a_long_one++; break - * default : pargs.err = 1; break; -- force warning output -- - * } - * } - * if( argc > 1 ) - * log_fatal( "Too many args"); - * - */ - -typedef struct alias_def_s *ALIAS_DEF; -struct alias_def_s { - ALIAS_DEF next; - char *name; /* malloced buffer with name, \0, value */ - const char *value; /* ptr into name */ -}; - - -/* Object to store the names for the --ignore-invalid-option option. - This is a simple linked list. */ -typedef struct iio_item_def_s *IIO_ITEM_DEF; -struct iio_item_def_s -{ - IIO_ITEM_DEF next; - char name[]; /* String with the long option name. */ -}; - -static const char *(*strusage_handler)( int ) = NULL; -static int (*custom_outfnc) (int, const char *); - -static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s); -static void show_help(ARGPARSE_OPTS *opts, unsigned flags); -static void show_version(void); -static int writestrings (int is_error, const char *string, ...) -#if __GNUC__ >= 4 - __attribute__ ((sentinel(0))) -#endif - ; - - -void -argparse_register_outfnc (int (*fnc)(int, const char *)) -{ - custom_outfnc = fnc; -} - - -/* Write STRING and all following const char * arguments either to - stdout or, if IS_ERROR is set, to stderr. The list of strings must - be terminated by a NULL. */ -static int -writestrings (int is_error, const char *string, ...) -{ - va_list arg_ptr; - const char *s; - int count = 0; - - if (string) - { - s = string; - va_start (arg_ptr, string); - do - { - if (custom_outfnc) - custom_outfnc (is_error? 2:1, s); - else - fputs (s, is_error? stderr : stdout); - count += strlen (s); - } - while ((s = va_arg (arg_ptr, const char *))); - va_end (arg_ptr); - } - return count; -} - - -static void -flushstrings (int is_error) -{ - if (custom_outfnc) - custom_outfnc (is_error? 2:1, NULL); - else - fflush (is_error? stderr : stdout); -} - - -static void -initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno ) -{ - if( !(arg->flags & (1<<15)) ) - { - /* Initialize this instance. */ - arg->internal.idx = 0; - arg->internal.last = NULL; - arg->internal.inarg = 0; - arg->internal.stopped = 0; - arg->internal.aliases = NULL; - arg->internal.cur_alias = NULL; - arg->internal.iio_list = NULL; - arg->err = 0; - arg->flags |= 1<<15; /* Mark as initialized. */ - if ( *arg->argc < 0 ) - jnlib_log_bug ("invalid argument for arg_parse\n"); - } - - - if (arg->err) - { - /* Last option was erroneous. */ - const char *s; - - if (filename) - { - if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - s = _("argument not expected"); - else if ( arg->r_opt == ARGPARSE_READ_ERROR ) - s = _("read error"); - else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG ) - s = _("keyword too long"); - else if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - s = _("missing argument"); - else if ( arg->r_opt == ARGPARSE_INVALID_ARG ) - s = _("invalid argument"); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - s = _("invalid command"); - else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS ) - s = _("invalid alias definition"); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - s = _("out of core"); - else - s = _("invalid option"); - jnlib_log_error ("%s:%u: %s\n", filename, *lineno, s); - } - else - { - s = arg->internal.last? arg->internal.last:"[??]"; - - if ( arg->r_opt == ARGPARSE_MISSING_ARG ) - jnlib_log_error (_("missing argument for option \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_INVALID_ARG ) - jnlib_log_error (_("invalid argument for option \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG ) - jnlib_log_error (_("option \"%.50s\" does not expect an " - "argument\n"), s ); - else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND ) - jnlib_log_error (_("invalid command \"%.50s\"\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION ) - jnlib_log_error (_("option \"%.50s\" is ambiguous\n"), s); - else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND ) - jnlib_log_error (_("command \"%.50s\" is ambiguous\n"),s ); - else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE ) - jnlib_log_error ("%s\n", _("out of core\n")); - else - jnlib_log_error (_("invalid option \"%.50s\"\n"), s); - } - if (arg->err != ARGPARSE_PRINT_WARNING) - exit (2); - arg->err = 0; - } - - /* Zero out the return value union. */ - arg->r.ret_str = NULL; - arg->r.ret_long = 0; -} - - -static void -store_alias( ARGPARSE_ARGS *arg, char *name, char *value ) -{ - /* TODO: replace this dummy function with a rea one - * and fix the probelms IRIX has with (ALIAS_DEV)arg.. - * used as lvalue - */ - (void)arg; - (void)name; - (void)value; -#if 0 - ALIAS_DEF a = jnlib_xmalloc( sizeof *a ); - a->name = name; - a->value = value; - a->next = (ALIAS_DEF)arg->internal.aliases; - (ALIAS_DEF)arg->internal.aliases = a; -#endif -} - - -/* Return true if KEYWORD is in the ignore-invalid-option list. */ -static int -ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword) -{ - IIO_ITEM_DEF item = arg->internal.iio_list; - - for (; item; item = item->next) - if (!strcmp (item->name, keyword)) - return 1; - return 0; -} - - -/* Add the keywords up to the next LF to the list of to be ignored - options. After returning FP will either be at EOF or the next - character read wll be the first of a new line. The function - returns 0 on success or true on malloc failure. */ -static int -ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp) -{ - IIO_ITEM_DEF item; - int c; - char name[100]; - int namelen = 0; - int ready = 0; - enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS; - - while (!ready) - { - c = getc (fp); - if (c == '\n') - ready = 1; - else if (c == EOF) - { - c = '\n'; - ready = 1; - } - again: - switch (state) - { - case skipWS: - if (!isascii (c) || !isspace(c)) - { - namelen = 0; - state = collectNAME; - goto again; - } - break; - - case collectNAME: - if (isspace (c)) - { - state = addNAME; - goto again; - } - else if (namelen < DIM(name)-1) { - assert(namelen < (sizeof(name) - 1)); - name[namelen++] = c; - } else /* Too long. */ - state = skipNAME; - break; - - case skipNAME: - if (isspace (c)) - { - state = skipWS; - goto again; - } - break; - - case addNAME: - name[namelen] = 0; - if (!ignore_invalid_option_p (arg, name)) - { - item = jnlib_malloc (sizeof *item + namelen + 1); - if (!item) - return 1; - strlcpy (item->name, name, namelen + 1); - item->next = (IIO_ITEM_DEF)arg->internal.iio_list; - arg->internal.iio_list = item; - } - state = skipWS; - goto again; - } - } - return 0; -} - - -/* Clear the entire ignore-invalid-option list. */ -static void -ignore_invalid_option_clear (ARGPARSE_ARGS *arg) -{ - IIO_ITEM_DEF item, tmpitem; - - for (item = arg->internal.iio_list; item; item = tmpitem) - { - tmpitem = item->next; - jnlib_free (item); - } - arg->internal.iio_list = NULL; -} - - - -/**************** - * Get options from a file. - * Lines starting with '#' are comment lines. - * Syntax is simply a keyword and the argument. - * Valid keywords are all keywords from the long_opt list without - * the leading dashes. The special keywords "help", "warranty" and "version" - * are not valid here. - * The special keyword "alias" may be used to store alias definitions, - * which are later expanded like long options. - * The option - * ignore-invalid-option OPTIONNAMEs - * is recognized and updates a list of option which should be ignored if they - * are not defined. - * Caller must free returned strings. - * If called with FP set to NULL command line args are parse instead. - * - * Q: Should we allow the syntax - * keyword = value - * and accept for boolean options a value of 1/0, yes/no or true/false? - * Note: Abbreviation of options is here not allowed. - */ -int -optfile_parse (FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int state, i, c; - int idx=0; - char keyword[100]; - char *buffer = NULL; - size_t buflen = 0; - int in_alias=0; - - if (!fp) /* Divert to to arg_parse() in this case. */ - return arg_parse (arg, opts); - - initialize (arg, filename, lineno); - - /* Find the next keyword. */ - state = i = 0; - for (;;) - { - c = getc (fp); - if (c == '\n' || c== EOF ) - { - if ( c != EOF ) - ++*lineno; - if (state == -1) - break; - else if (state == 2) - { - keyword[i] = 0; - for (i=0; opts[i].short_opt; i++ ) - { - if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) - break; - } - idx = i; - arg->r_opt = opts[idx].short_opt; - if ((opts[idx].flags & ARGPARSE_OPT_IGNORE)) - { - state = i = 0; - continue; - } - else if (!opts[idx].short_opt ) - { - if (!strcmp (keyword, "ignore-invalid-option")) - { - /* No argument - ignore this meta option. */ - state = i = 0; - continue; - } - else if (ignore_invalid_option_p (arg, keyword)) - { - /* This invalid option is in the iio list. */ - state = i = 0; - continue; - } - arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - } - else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) ) - arg->r_type = 0; /* Arg is optional. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 3) - { - /* No argument found. */ - if (in_alias) - arg->r_opt = ARGPARSE_MISSING_ARG; - else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) - arg->r_type = 0; /* Does not take an arg. */ - else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL)) - arg->r_type = 0; /* No optional argument. */ - else - arg->r_opt = ARGPARSE_MISSING_ARG; - - break; - } - else if (state == 4) - { - /* Has an argument. */ - if (in_alias) - { - if (!buffer) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - buffer[i] = 0; - p = strpbrk (buffer, " \t"); - if (p) - { - *p++ = 0; - trim_spaces (p); - } - if (!p || !*p) - { - jnlib_free (buffer); - arg->r_opt = ARGPARSE_INVALID_ALIAS; - } - else - { - store_alias (arg, buffer, p); - } - } - } - else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK)) - arg->r_opt = ARGPARSE_UNEXPECTED_ARG; - else - { - char *p; - - if (!buffer) - { - keyword[i] = 0; - buffer = jnlib_strdup (keyword); - if (!buffer) - arg->r_opt = ARGPARSE_OUT_OF_CORE; - } - else - buffer[i] = 0; - - if (buffer) - { - trim_spaces (buffer); - p = buffer; - if (*p == '"') - { - /* Remove quotes. */ - p++; - if (*p && p[strlen(p)-1] == '\"' ) - p[strlen(p)-1] = 0; - } - if (!set_opt_arg (arg, opts[idx].flags, p)) - jnlib_free(buffer); - } - } - break; - } - else if (c == EOF) - { - ignore_invalid_option_clear (arg); - if (ferror (fp)) - arg->r_opt = ARGPARSE_READ_ERROR; - else - arg->r_opt = 0; /* EOF. */ - break; - } - state = 0; - i = 0; - } - else if (state == -1) - ; /* Skip. */ - else if (state == 0 && isascii (c) && isspace(c)) - ; /* Skip leading white space. */ - else if (state == 0 && c == '#' ) - state = 1; /* Start of a comment. */ - else if (state == 1) - ; /* Skip comments. */ - else if (state == 2 && isascii (c) && isspace(c)) - { - /* Check keyword. */ - keyword[i] = 0; - for (i=0; opts[i].short_opt; i++ ) - if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword)) - break; - idx = i; - arg->r_opt = opts[idx].short_opt; - if ((opts[idx].flags & ARGPARSE_OPT_IGNORE)) - { - state = 1; /* Process like a comment. */ - } - else if (!opts[idx].short_opt) - { - if (!strcmp (keyword, "alias")) - { - in_alias = 1; - state = 3; - } - else if (!strcmp (keyword, "ignore-invalid-option")) - { - if (ignore_invalid_option_add (arg, fp)) - { - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - state = i = 0; - ++*lineno; - } - else if (ignore_invalid_option_p (arg, keyword)) - state = 1; /* Process like a comment. */ - else - { - arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND) - ? ARGPARSE_INVALID_COMMAND - : ARGPARSE_INVALID_OPTION); - state = -1; /* Skip rest of line and leave. */ - } - } - else - state = 3; - } - else if (state == 3) - { - /* Skip leading spaces of the argument. */ - if (!isascii (c) || !isspace(c)) - { - i = 0; - keyword[i++] = c; - state = 4; - } - } - else if (state == 4) - { - /* Collect the argument. */ - if (buffer) - { - if (i < buflen-1) - buffer[i++] = c; - else - { - char *tmp; - size_t tmplen = buflen + 50; - - tmp = jnlib_realloc (buffer, tmplen); - if (tmp) - { - buflen = tmplen; - buffer = tmp; - buffer[i++] = c; - } - else - { - jnlib_free (buffer); - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i < DIM(keyword)-1) - keyword[i++] = c; - else - { - size_t tmplen = DIM(keyword) + 50; - buffer = jnlib_malloc (tmplen); - if (buffer) - { - buflen = tmplen; - memcpy(buffer, keyword, i); - buffer[i++] = c; - } - else - { - arg->r_opt = ARGPARSE_OUT_OF_CORE; - break; - } - } - } - else if (i >= DIM(keyword)-1) - { - arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG; - state = -1; /* Skip rest of line and leave. */ - } - else - { - keyword[i++] = c; - state = 2; - } - } - - return arg->r_opt; -} - - - -static int -find_long_option( ARGPARSE_ARGS *arg, - ARGPARSE_OPTS *opts, const char *keyword ) -{ - int i; - size_t n; - - (void)arg; - - /* Would be better if we can do a binary search, but it is not - possible to reorder our option table because we would mess - up our help strings - What we can do is: Build a nice option - lookup table wehn this function is first invoked */ - if( !*keyword ) - return -1; - for(i=0; opts[i].short_opt; i++ ) - if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) ) - return i; -#if 0 - { - ALIAS_DEF a; - /* see whether it is an alias */ - for( a = args->internal.aliases; a; a = a->next ) { - if( !strcmp( a->name, keyword) ) { - /* todo: must parse the alias here */ - args->internal.cur_alias = a; - return -3; /* alias available */ - } - } - } -#endif - /* not found, see whether it is an abbreviation */ - /* aliases may not be abbreviated */ - n = strlen( keyword ); - for(i=0; opts[i].short_opt; i++ ) { - if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) { - int j; - for(j=i+1; opts[j].short_opt; j++ ) { - if( opts[j].long_opt - && !strncmp( opts[j].long_opt, keyword, n ) ) - return -2; /* abbreviation is ambiguous */ - } - return i; - } - } - return -1; /* Not found. */ -} - -int -arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts) -{ - int idx; - int argc; - char **argv; - char *s, *s2; - int i; - - initialize( arg, NULL, NULL ); - argc = *arg->argc; - argv = *arg->argv; - idx = arg->internal.idx; - - if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0)) - { - /* Skip the first argument. */ - argc--; argv++; idx++; - } - - next_one: - if (!argc) - { - /* No more args. */ - arg->r_opt = 0; - goto leave; /* Ready. */ - } - - s = *argv; - arg->internal.last = s; - - if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL)) - { - arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */ - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* set to next one */ - } - else if( arg->internal.stopped ) - { - arg->r_opt = 0; - goto leave; /* Ready. */ - } - else if ( *s == '-' && s[1] == '-' ) - { - /* Long option. */ - char *argpos; - - arg->internal.inarg = 0; - if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP)) - { - /* Stop option processing. */ - arg->internal.stopped = 1; - arg->flags |= ARGPARSE_FLAG_STOP_SEEN; - argc--; argv++; idx++; - goto next_one; - } - - argpos = strchr( s+2, '=' ); - if ( argpos ) - *argpos = 0; - i = find_long_option ( arg, opts, s+2 ); - if ( argpos ) - *argpos = '='; - - if ( i < 0 && !strcmp ( "help", s+2) ) - show_help (opts, arg->flags); - else if ( i < 0 && !strcmp ( "version", s+2) ) - { - if (!(arg->flags & ARGPARSE_FLAG_NOVERSION)) - { - show_version (); - exit(0); - } - } - else if ( i < 0 && !strcmp( "warranty", s+2)) - { - writestrings (0, strusage (16), "\n", NULL); - exit (0); - } - else if ( i < 0 && !strcmp( "dump-options", s+2) ) - { - for (i=0; opts[i].short_opt; i++ ) - { - if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE)) - writestrings (0, "--", opts[i].long_opt, "\n", NULL); - } - writestrings (0, "--dump-options\n--help\n--version\n--warranty\n", - NULL); - exit (0); - } - - if ( i == -2 ) - arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION; - else if ( i == -1 ) - { - arg->r_opt = ARGPARSE_INVALID_OPTION; - arg->r.ret_str = s+2; - } - else - arg->r_opt = opts[i].short_opt; - if ( i < 0 ) - ; - else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) ) - { - if ( argpos ) - { - s2 = argpos+1; - if ( !*s2 ) - s2 = NULL; - } - else - s2 = argv[1]; - if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */ - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( !argpos && *s2 == '-' - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* The argument is optional and the next seems to be an - option. We do not check this possible option but - assume no argument */ - arg->r_type = ARGPARSE_TYPE_NONE; - } - else - { - set_opt_arg (arg, opts[i].flags, s2); - if ( !argpos ) - { - argc--; argv++; idx++; /* Skip one. */ - } - } - } - else - { - /* Does not take an argument. */ - if ( argpos ) - arg->r_type = ARGPARSE_UNEXPECTED_ARG; - else - arg->r_type = 0; - } - argc--; argv++; idx++; /* Set to next one. */ - } - else if ( (*s == '-' && s[1]) || arg->internal.inarg ) - { - /* Short option. */ - int dash_kludge = 0; - - i = 0; - if ( !arg->internal.inarg ) - { - arg->internal.inarg++; - if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) ) - { - for (i=0; opts[i].short_opt; i++ ) - if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1)) - { - dash_kludge = 1; - break; - } - } - } - s += arg->internal.inarg; - - if (!dash_kludge ) - { - for (i=0; opts[i].short_opt; i++ ) - if ( opts[i].short_opt == *s ) - break; - } - - if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) ) - show_help (opts, arg->flags); - - arg->r_opt = opts[i].short_opt; - if (!opts[i].short_opt ) - { - arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)? - ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION; - arg->internal.inarg++; /* Point to the next arg. */ - arg->r.ret_str = s; - } - else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) ) - { - if ( s[1] && !dash_kludge ) - { - s2 = s+1; - set_opt_arg (arg, opts[i].flags, s2); - } - else - { - s2 = argv[1]; - if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - arg->r_type = ARGPARSE_TYPE_NONE; - } - else if ( !s2 ) - { - arg->r_opt = ARGPARSE_MISSING_ARG; - } - else if ( *s2 == '-' && s2[1] - && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) ) - { - /* The argument is optional and the next seems to - be an option. We do not check this possible - option but assume no argument. */ - arg->r_type = ARGPARSE_TYPE_NONE; - } - else - { - set_opt_arg (arg, opts[i].flags, s2); - argc--; argv++; idx++; /* Skip one. */ - } - } - s = "x"; /* This is so that !s[1] yields false. */ - } - else - { - /* Does not take an argument. */ - arg->r_type = ARGPARSE_TYPE_NONE; - arg->internal.inarg++; /* Point to the next arg. */ - } - if ( !s[1] || dash_kludge ) - { - /* No more concatenated short options. */ - arg->internal.inarg = 0; - argc--; argv++; idx++; - } - } - else if ( arg->flags & ARGPARSE_FLAG_MIXED ) - { - arg->r_opt = ARGPARSE_IS_ARG; - arg->r_type = 2; - arg->r.ret_str = s; - argc--; argv++; idx++; /* Set to next one. */ - } - else - { - arg->internal.stopped = 1; /* Stop option processing. */ - goto next_one; - } - - leave: - *arg->argc = argc; - *arg->argv = argv; - arg->internal.idx = idx; - return arg->r_opt; -} - - -/* Returns: -1 on error, 0 for an integer type and 1 for a non integer - type argument. */ -static int -set_opt_arg (ARGPARSE_ARGS *arg, unsigned flags, char *s) -{ - int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10; - long l; - - switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) ) - { - case ARGPARSE_TYPE_LONG: - case ARGPARSE_TYPE_INT: - errno = 0; - l = strtol (s, NULL, base); - if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) - { - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - if (arg->r_type == ARGPARSE_TYPE_LONG) - arg->r.ret_long = l; - else if ( (l < 0 && l < INT_MIN) || l > INT_MAX ) - { - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - else - arg->r.ret_int = (int)l; - return 0; - - case ARGPARSE_TYPE_ULONG: - while (isascii (*s) && isspace(*s)) - s++; - if (*s == '-') - { - arg->r.ret_ulong = 0; - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - errno = 0; - arg->r.ret_ulong = strtoul (s, NULL, base); - if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE) - { - arg->r_opt = ARGPARSE_INVALID_ARG; - return -1; - } - return 0; - - case ARGPARSE_TYPE_STRING: - default: - arg->r.ret_str = s; - return 1; - } -} - - -static size_t -long_opt_strlen( ARGPARSE_OPTS *o ) -{ - size_t n = strlen (o->long_opt); - - if ( o->description && *o->description == '|' ) - { - const char *s; -#ifdef JNLIB_NEED_UTF8CONV - int is_utf8 = is_native_utf8 (); -#endif - - s=o->description+1; - if ( *s != '=' ) - n++; - /* For a (mostly) correct length calculation we exclude - continuation bytes (10xxxxxx) if we are on a native utf8 - terminal. */ - for (; *s && *s != '|'; s++ ) -#ifdef JNLIB_NEED_UTF8CONV - if ( is_utf8 && (*s&0xc0) != 0x80 ) -#endif - n++; - } - return n; -} - - -/**************** - * Print formatted help. The description string has some special - * meanings: - * - A description string which is "@" suppresses help output for - * this option - * - a description,ine which starts with a '@' and is followed by - * any other characters is printed as is; this may be used for examples - * ans such. - * - A description which starts with a '|' outputs the string between this - * bar and the next one as arguments of the long option. - */ -static void -show_help (ARGPARSE_OPTS *opts, unsigned int flags) -{ - const char *s; - char tmp[2]; - - show_version (); - writestrings (0, "\n", NULL); - s = strusage (42); - if (s && *s == '1') - { - s = strusage (40); - writestrings (1, s, NULL); - if (*s && s[strlen(s)] != '\n') - writestrings (1, "\n", NULL); - } - s = strusage(41); - writestrings (0, s, "\n", NULL); - if ( opts[0].description ) - { - /* Auto format the option description. */ - int i,j, indent; - - /* Get max. length of long options. */ - for (i=indent=0; opts[i].short_opt; i++ ) - { - if ( opts[i].long_opt ) - if ( !opts[i].description || *opts[i].description != '@' ) - if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 ) - indent = j; - } - - /* Example: " -v, --verbose Viele Sachen ausgeben" */ - indent += 10; - if ( *opts[0].description != '@' ) - writestrings (0, "Options:", "\n", NULL); - for (i=0; opts[i].short_opt; i++ ) - { - s = map_static_macro_string (_( opts[i].description )); - if ( s && *s== '@' && !s[1] ) /* Hide this line. */ - continue; - if ( s && *s == '@' ) /* Unindented comment only line. */ - { - for (s++; *s; s++ ) - { - if ( *s == '\n' ) - { - if( s[1] ) - writestrings (0, "\n", NULL); - } - else - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - } - writestrings (0, "\n", NULL); - continue; - } - - j = 3; - if ( opts[i].short_opt < 256 ) - { - tmp[0] = opts[i].short_opt; - tmp[1] = 0; - writestrings (0, " -", tmp, NULL ); - if ( !opts[i].long_opt ) - { - if (s && *s == '|' ) - { - writestrings (0, " ", NULL); j++; - for (s++ ; *s && *s != '|'; s++, j++ ) - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - if ( *s ) - s++; - } - } - } - else - writestrings (0, " ", NULL); - if ( opts[i].long_opt ) - { - tmp[0] = opts[i].short_opt < 256?',':' '; - tmp[1] = 0; - j += writestrings (0, tmp, " --", opts[i].long_opt, NULL); - if (s && *s == '|' ) - { - if ( *++s != '=' ) - { - writestrings (0, " ", NULL); - j++; - } - for ( ; *s && *s != '|'; s++, j++ ) - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - if ( *s ) - s++; - } - writestrings (0, " ", NULL); - j += 3; - } - for (;j < indent; j++ ) - writestrings (0, " ", NULL); - if ( s ) - { - if ( *s && j > indent ) - { - writestrings (0, "\n", NULL); - for (j=0;j < indent; j++ ) - writestrings (0, " ", NULL); - } - for (; *s; s++ ) - { - if ( *s == '\n' ) - { - if ( s[1] ) - { - writestrings (0, "\n", NULL); - for (j=0; j < indent; j++ ) - writestrings (0, " ", NULL); - } - } - else - { - tmp[0] = *s; - tmp[1] = 0; - writestrings (0, tmp, NULL); - } - } - } - writestrings (0, "\n", NULL); - } - if ( (flags & ARGPARSE_FLAG_ONEDASH) ) - writestrings (0, "\n(A single dash may be used " - "instead of the double ones)\n", NULL); - } - if ( (s=strusage(19)) ) - { - writestrings (0, "\n", NULL); - writestrings (0, s, NULL); - } - flushstrings (0); - exit(0); -} - -static void -show_version (void) -{ - const char *s; - int i; - - /* Version line. */ - writestrings (0, strusage (11), NULL); - if ((s=strusage (12))) - writestrings (0, " (", s, ")", NULL); - writestrings (0, " ", strusage (13), "\n", NULL); - /* Additional version lines. */ - for (i=20; i < 30; i++) - if ((s=strusage (i))) - writestrings (0, s, "\n", NULL); - /* Copyright string. */ - if ((s=strusage (14))) - writestrings (0, s, "\n", NULL); - /* Licence string. */ - if( (s=strusage (10)) ) - writestrings (0, s, "\n", NULL); - /* Copying conditions. */ - if ( (s=strusage(15)) ) - writestrings (0, s, NULL); - /* Thanks. */ - if ((s=strusage(18))) - writestrings (0, s, NULL); - /* Additional program info. */ - for (i=30; i < 40; i++ ) - if ( (s=strusage (i)) ) - writestrings (0, s, NULL); - flushstrings (0); -} - - -void -usage (int level) -{ - const char *p; - - if (!level) - { - writestrings (1, strusage(11), " ", strusage(13), "; ", - strusage (14), "\n", NULL); - flushstrings (1); - } - else if (level == 1) - { - p = strusage (40); - writestrings (1, p, NULL); - if (*p && p[strlen(p)] != '\n') - writestrings (1, "\n", NULL); - exit (2); - } - else if (level == 2) - { - p = strusage (42); - if (p && *p == '1') - { - p = strusage (40); - writestrings (1, p, NULL); - if (*p && p[strlen(p)] != '\n') - writestrings (1, "\n", NULL); - } - writestrings (0, strusage(41), "\n", NULL); - exit (0); - } -} - -/* Level - * 0: Print copyright string to stderr - * 1: Print a short usage hint to stderr and terminate - * 2: Print a long usage hint to stdout and terminate - * 10: Return license info string - * 11: Return the name of the program - * 12: Return optional name of package which includes this program. - * 13: version string - * 14: copyright string - * 15: Short copying conditions (with LFs) - * 16: Long copying conditions (with LFs) - * 17: Optional printable OS name - * 18: Optional thanks list (with LFs) - * 19: Bug report info - *20..29: Additional lib version strings. - *30..39: Additional program info (with LFs) - * 40: short usage note (with LF) - * 41: long usage note (with LF) - * 42: Flag string: - * First char is '1': - * The short usage notes needs to be printed - * before the long usage note. - */ -const char * -strusage( int level ) -{ - const char *p = strusage_handler? strusage_handler(level) : NULL; - - if ( p ) - return map_static_macro_string (p); - - switch ( level ) - { - - case 10: -#if ARGPARSE_GPL_VERSION == 3 - p = ("License GPLv3+: GNU GPL version 3 or later " - ""); -#else - p = ("License GPLv2+: GNU GPL version 2 or later " - ""); -#endif - break; - case 11: p = "foo"; break; - case 13: p = "0.0"; break; - case 14: p = ARGPARSE_CRIGHT_STR; break; - case 15: p = -"This is free software: you are free to change and redistribute it.\n" -"There is NO WARRANTY, to the extent permitted by law.\n"; - break; - case 16: p = -"This is free software; you can redistribute it and/or modify\n" -"it under the terms of the GNU General Public License as published by\n" -"the Free Software Foundation; either version " -ARGPARSE_STR2(ARGPARSE_GPL_VERSION) -" of the License, or\n" -"(at your option) any later version.\n\n" -"It is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n\n" -"You should have received a copy of the GNU General Public License\n" -"along with this software. If not, see .\n"; - break; - case 40: /* short and long usage */ - case 41: p = ""; break; - } - - return p; -} - - -/* Set the usage handler. This function is basically a constructor. */ -void -set_strusage ( const char *(*f)( int ) ) -{ - strusage_handler = f; -} - - -#ifdef TEST -static struct { - int verbose; - int debug; - char *outfile; - char *crf; - int myopt; - int echo; - int a_long_one; -} opt; - -int -main(int argc, char **argv) -{ - ARGPARSE_OPTS opts[] = { - ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"), - ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, " - "was wir eingegeben haben")), - ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"), - ARGPARSE_s_s('o', "output", 0 ), - ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ), - /* Note that on a non-utf8 terminal the ß might garble the output. */ - ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"), - ARGPARSE_o_i('m', "my-option", 0), - ARGPARSE_s_n(500, "a-long-option", 0 ), - ARGPARSE_end() - }; - ARGPARSE_ARGS pargs = { &argc, &argv, (ARGPARSE_FLAG_ALL - | ARGPARSE_FLAG_MIXED - | ARGPARSE_FLAG_ONEDASH) }; - int i; - - while (arg_parse (&pargs, opts)) - { - switch (pargs.r_opt) - { - case ARGPARSE_IS_ARG : - printf ("arg='%s'\n", pargs.r.ret_str); - break; - case 'v': opt.verbose++; break; - case 'e': opt.echo++; break; - case 'd': opt.debug++; break; - case 'o': opt.outfile = pargs.r.ret_str; break; - case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break; - case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break; - case 500: opt.a_long_one++; break; - default : pargs.err = ARGPARSE_PRINT_WARNING; break; - } - } - for (i=0; i < argc; i++ ) - printf ("%3d -> (%s)\n", i, argv[i] ); - puts ("Options:"); - if (opt.verbose) - printf (" verbose=%d\n", opt.verbose ); - if (opt.debug) - printf (" debug=%d\n", opt.debug ); - if (opt.outfile) - printf (" outfile='%s'\n", opt.outfile ); - if (opt.crf) - printf (" crffile='%s'\n", opt.crf ); - if (opt.myopt) - printf (" myopt=%d\n", opt.myopt ); - if (opt.a_long_one) - printf (" a-long-one=%d\n", opt.a_long_one ); - if (opt.echo) - printf (" echo=%d\n", opt.echo ); - - return 0; -} -#endif /*TEST*/ - -/**** bottom of file ****/ blob - b4dc253730009daf43fa23e2d04231241d888abc (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/argparse.h +++ /dev/null @@ -1,203 +0,0 @@ -/* argparse.h - Argument parser for option handling. - * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc. - * - * This file is part of JNLIB, which is a subsystem of GnuPG. - * - * JNLIB is free software; you can redistribute it and/or modify it - * under the terms of either - * - * - the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 3 of the License, or (at - * your option) any later version. - * - * or - * - * - 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. - * - * or both in parallel, as here. - * - * JNLIB 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 copies of the GNU General Public License - * and the GNU Lesser General Public License along with this program; - * if not, see . - */ - -#ifndef LIBJNLIB_ARGPARSE_H -#define LIBJNLIB_ARGPARSE_H - -#include - -typedef struct -{ - int *argc; /* Pointer to ARGC (value subject to change). */ - char ***argv; /* Pointer to ARGV (value subject to change). */ - unsigned int flags; /* Global flags. May be set prior to calling the - parser. The parser may change the value. */ - int err; /* Print error description for last option. - Either 0, ARGPARSE_PRINT_WARNING or - ARGPARSE_PRINT_ERROR. */ - - int r_opt; /* Returns option code. */ - int r_type; /* Returns type of option value. */ - union { - int ret_int; - long ret_long; - unsigned long ret_ulong; - char *ret_str; - } r; /* Return values */ - - struct { - int idx; - int inarg; - int stopped; - const char *last; - void *aliases; - const void *cur_alias; - void *iio_list; - } internal; /* Private - do not change. */ -} ARGPARSE_ARGS; - -typedef struct -{ - int short_opt; - const char *long_opt; - unsigned int flags; - const char *description; /* Optional option description. */ -} ARGPARSE_OPTS; - - -/* Global flags (ARGPARSE_ARGS). */ -#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */ -#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return - remaining args with R_OPT set to -1. */ -#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */ -#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */ -#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */ -#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */ -#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */ - -#define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */ - -/* Flags for each option (ARGPARSE_OPTS). The type code may be - ORed with the OPT flags. */ -#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */ -#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */ -#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */ -#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */ -#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */ -#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */ -#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */ -#define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */ -#define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */ - -#define ARGPARSE_TYPE_MASK 7 /* Mask for the type values (internal). */ - -/* A set of macros to make option definitions easier to read. */ -#define ARGPARSE_x(s,l,t,f,d) \ - { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) } - -#define ARGPARSE_s(s,l,t,d) \ - { (s), (l), ARGPARSE_TYPE_ ## t, (d) } -#define ARGPARSE_s_n(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_NONE, (d) } -#define ARGPARSE_s_i(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_INT, (d) } -#define ARGPARSE_s_s(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_STRING, (d) } -#define ARGPARSE_s_l(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_LONG, (d) } -#define ARGPARSE_s_u(s,l,d) \ - { (s), (l), ARGPARSE_TYPE_ULONG, (d) } - -#define ARGPARSE_o(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) } -#define ARGPARSE_o_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) } - -#define ARGPARSE_p(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_p_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) } - -#define ARGPARSE_op(s,l,t,d) \ - { (s), (l), (ARGPARSE_TYPE_ ## t \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_n(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_i(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_INT \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_s(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_STRING \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_l(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_LONG \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } -#define ARGPARSE_op_u(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_ULONG \ - | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } - -#define ARGPARSE_c(s,l,d) \ - { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) } - -#define ARGPARSE_ignore(s,l) \ - { (s), (l), (ARGPARSE_OPT_IGNORE), "@" } - -#define ARGPARSE_group(s,d) \ - { (s), NULL, 0, (d) } - -#define ARGPARSE_end() { 0, NULL, 0, NULL } - - -/* Other constants. */ -#define ARGPARSE_PRINT_WARNING 1 -#define ARGPARSE_PRINT_ERROR 2 - - -/* Error values. */ -#define ARGPARSE_IS_ARG (-1) -#define ARGPARSE_INVALID_OPTION (-2) -#define ARGPARSE_MISSING_ARG (-3) -#define ARGPARSE_KEYWORD_TOO_LONG (-4) -#define ARGPARSE_READ_ERROR (-5) -#define ARGPARSE_UNEXPECTED_ARG (-6) -#define ARGPARSE_INVALID_COMMAND (-7) -#define ARGPARSE_AMBIGUOUS_OPTION (-8) -#define ARGPARSE_AMBIGUOUS_COMMAND (-9) -#define ARGPARSE_INVALID_ALIAS (-10) -#define ARGPARSE_OUT_OF_CORE (-11) -#define ARGPARSE_INVALID_ARG (-12) - - -int arg_parse (ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -int optfile_parse (FILE *fp, const char *filename, unsigned *lineno, - ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); -void usage (int level); -const char *strusage (int level); -void set_strusage (const char *(*f)( int )); -void argparse_register_outfnc (int (*fnc)(int, const char *)); - -#endif /*LIBJNLIB_ARGPARSE_H*/ blob - 354c6c96cd8585f1295998368c32087ae336bbf4 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/memory.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Quintuple Agent secure memory allocation - * Copyright (C) 1998,1999 Free Software Foundation, Inc. - * Copyright (C) 1999,2000 Robert Bihlmeyer - * - * 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 _MEMORY_H -#define _MEMORY_H - -#include - -#ifdef __cplusplus -extern "C" { -#if 0 -} -#endif -#endif - - -/* values for flags, hardcoded in secmem.c */ -#define SECMEM_WARN 0 -#define SECMEM_DONT_WARN 1 -#define SECMEM_SUSPEND_WARN 2 - -void secmem_init( size_t npool ); -void secmem_term( void ); -void *secmem_malloc( size_t size ); -void *secmem_realloc( void *a, size_t newsize ); -void secmem_free( void *a ); -int m_is_secure( const void *p ); -void secmem_dump_stats(void); -void secmem_set_flags( unsigned flags ); -unsigned secmem_get_flags(void); -size_t secmem_get_max_size (void); - -#if 0 -{ -#endif -#ifdef __cplusplus -} -#endif -#endif /* _MEMORY_H */ blob - 898f88cebfc93639fb5050f92ab559956f5f1846 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/password-cache.c +++ /dev/null @@ -1,161 +0,0 @@ -/* password-cache.c - Password cache support. - Copyright (C) 2015 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, see . - */ - -#include "../../master.h" - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#ifdef HAVE_LIBSECRET -# include -#endif - -#include "password-cache.h" -#include "memory.h" - -#ifdef HAVE_LIBSECRET -static const SecretSchema * -gpg_schema (void) -{ - static const SecretSchema the_schema = { - "org.gnupg.Passphrase", SECRET_SCHEMA_NONE, - { - { "stored-by", SECRET_SCHEMA_ATTRIBUTE_STRING }, - { "keygrip", SECRET_SCHEMA_ATTRIBUTE_STRING }, - { "NULL", 0 }, - } - }; - return &the_schema; -} - -static char * -keygrip_to_label (const char *keygrip) -{ - char const prefix[] = "GnuPG: "; - char *label = NULL; - asprintf (&label, "%s%s", prefix, keygrip); - return label; -} -#endif - -void -password_cache_save (UNUSED const char *keygrip, UNUSED const char *password) -{ -#ifdef HAVE_LIBSECRET - char *label; - GError *error = NULL; - - if (! *keygrip) - return; - - label = keygrip_to_label (keygrip); - if (! label) - return; - - if (! secret_password_store_sync (gpg_schema (), - SECRET_COLLECTION_DEFAULT, - label, password, NULL, &error, - "stored-by", "GnuPG Pinentry", - "keygrip", keygrip, NULL)) - { - printf("Failed to cache password for key %s with secret service: %s\n", - keygrip, error->message); - - g_error_free (error); - } - - free (label); -#else - return; -#endif -} - -char * -password_cache_lookup (UNUSED const char *keygrip) -{ -#ifdef HAVE_LIBSECRET - GError *error = NULL; - char *password; - char *password2; - size_t plen; - - if (! *keygrip) - return NULL; - - password = secret_password_lookup_nonpageable_sync - (gpg_schema (), NULL, &error, - "keygrip", keygrip, NULL); - - if (error != NULL) - { - printf("Failed to lookup password for key %s with secret service: %s\n", - keygrip, error->message); - g_error_free (error); - return NULL; - } - if (! password) - /* The password for this key is not cached. Just return NULL. */ - return NULL; - - /* The password needs to be returned in secmem allocated memory. */ - plen = strlen (password) + 1; - password2 = secmem_malloc (plen); - if (password2) - strlcpy(password2, password, plen); - else - printf("secmem_malloc failed: can't copy password!\n"); - - secret_password_free (password); - - return password2; -#else - return NULL; -#endif -} - -/* Try and remove the cached password for key grip. Returns -1 on - error, 0 if the key is not found and 1 if the password was - removed. */ -int -password_cache_clear (UNUSED const char *keygrip) -{ -#ifdef HAVE_LIBSECRET - GError *error = NULL; - int removed = secret_password_clear_sync (gpg_schema (), NULL, &error, - "keygrip", keygrip, NULL); - if (error != NULL) - { - printf("Failed to clear password for key %s with secret service: %s\n", - keygrip, error->message); - g_debug("%s", error->message); - g_error_free (error); - return -1; - } - if (removed) - return 1; - return 0; -#else - return -1; -#endif -} blob - 0bc8788f15d28879c4bf63532949397274926b9d (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/password-cache.h +++ /dev/null @@ -1,29 +0,0 @@ -/* password-cache.h - Password cache support interfaces. - Copyright (C) 2015 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, see . - */ - -#ifndef PASSWORD_CACHE_H -#define PASSWORD_CACHE_H - -void password_cache_save (const char *key_grip, const char *password); - -char *password_cache_lookup (const char *key_grip); - -int password_cache_clear (const char *keygrip); - -#endif blob - d10723a94e527940d9188230c4a4feee99a8e97d (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/pinentry.c +++ /dev/null @@ -1,1314 +0,0 @@ -/* pinentry.c - The PIN entry support library - Copyright (C) 2002, 2003, 2007, 2008, 2010, 2015 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, see . - */ - -#include "../../master.h" - -#include -#include -#include -#include - -#include - -#include "memory.h" -#include "secmem-util.h" -#include "argparse.h" -#include "pinentry.h" -#include "password-cache.h" - -/* Keep the name of our program here. */ -static char this_pgmname[50]; - -struct pinentry pinentry; - -static void -pinentry_reset (int use_defaults) -{ - /* GPG Agent sets these options once when it starts the pinentry. - Don't reset them. */ - int grab = pinentry.grab; - char *ttyname = pinentry.ttyname; - char *ttytype = pinentry.ttytype; - char *lc_ctype = pinentry.lc_ctype; - char *lc_messages = pinentry.lc_messages; - int allow_external_password_cache = pinentry.allow_external_password_cache; - char *default_ok = pinentry.default_ok; - char *default_cancel = pinentry.default_cancel; - char *default_prompt = pinentry.default_prompt; - char *default_pwmngr = pinentry.default_pwmngr; - char *touch_file = pinentry.touch_file; - - /* These options are set from the command line. Don't reset - them. */ - int debug = pinentry.debug; - char *display = pinentry.display; - int parent_wid = pinentry.parent_wid; - - pinentry_color_t color_fg = pinentry.color_fg; - int color_fg_bright = pinentry.color_fg_bright; - pinentry_color_t color_bg = pinentry.color_bg; - pinentry_color_t color_so = pinentry.color_so; - int color_so_bright = pinentry.color_so_bright; - - int timout = pinentry.timeout; - - /* Free any allocated memory. */ - if (use_defaults) - { - free (pinentry.ttyname); - free (pinentry.ttytype); - free (pinentry.lc_ctype); - free (pinentry.lc_messages); - free (pinentry.default_ok); - free (pinentry.default_cancel); - free (pinentry.default_prompt); - free (pinentry.default_pwmngr); - free (pinentry.touch_file); - free (pinentry.display); - } - - free (pinentry.title); - free (pinentry.description); - free (pinentry.error); - free (pinentry.prompt); - free (pinentry.ok); - free (pinentry.notok); - free (pinentry.cancel); - secmem_free (pinentry.pin); - free (pinentry.repeat_passphrase); - free (pinentry.repeat_error_string); - free (pinentry.quality_bar); - free (pinentry.quality_bar_tt); - free (pinentry.keyinfo); - - /* Reset the pinentry structure. */ - memset (&pinentry, 0, sizeof (pinentry)); - - if (use_defaults) - { - /* Pinentry timeout in seconds. */ - pinentry.timeout = 60; - - /* Global grab. */ - pinentry.grab = 1; - - pinentry.color_fg = PINENTRY_COLOR_DEFAULT; - pinentry.color_fg_bright = 0; - pinentry.color_bg = PINENTRY_COLOR_DEFAULT; - pinentry.color_so = PINENTRY_COLOR_DEFAULT; - pinentry.color_so_bright = 0; - } - else - /* Restore the options. */ - { - pinentry.grab = grab; - pinentry.ttyname = ttyname; - pinentry.ttytype = ttytype; - pinentry.lc_ctype = lc_ctype; - pinentry.lc_messages = lc_messages; - pinentry.allow_external_password_cache = allow_external_password_cache; - pinentry.default_ok = default_ok; - pinentry.default_cancel = default_cancel; - pinentry.default_prompt = default_prompt; - pinentry.default_pwmngr = default_pwmngr; - pinentry.touch_file = touch_file; - - pinentry.debug = debug; - pinentry.display = display; - pinentry.parent_wid = parent_wid; - - pinentry.color_fg = color_fg; - pinentry.color_fg_bright = color_fg_bright; - pinentry.color_bg = color_bg; - pinentry.color_so = color_so; - pinentry.color_so_bright = color_so_bright; - - pinentry.timeout = timout; - } -} - -static gpg_error_t -pinentry_assuan_reset_handler (assuan_context_t ctx, char *line) -{ - (void)ctx; - (void)line; - - pinentry_reset (0); - - return 0; -} - - -//static int lc_ctype_unknown_warning = 0; - -/* Copy TEXT or TEXTLEN to BUFFER and escape as required. Return a - pointer to the end of the new buffer. Note that BUFFER must be - large enough to keep the entire text; allocataing it 3 times of - TEXTLEN is sufficient. */ -static char * -copy_and_escape (char *buffer, const void *text, size_t textlen) -{ - int i; - const unsigned char *s = (unsigned char *)text; - char *p = buffer; - - for (i=0; i < textlen; i++) - { - if (s[i] < ' ' || s[i] == '+') - { - snprintf (p, 4, "%%%02X", s[i]); - p += 3; - } - else if (s[i] == ' ') - *p++ = '+'; - else - *p++ = s[i]; - } - return p; -} - - - -/* Run a quality inquiry for PASSPHRASE of LENGTH. (We need LENGTH - because not all backends might be able to return a proper - C-string.). Returns: A value between -100 and 100 to give an - estimate of the passphrase's quality. Negative values are use if - the caller won't even accept that passphrase. Note that we expect - just one data line which should not be escaped in any represent a - numeric signed decimal value. Extra data is currently ignored but - should not be send at all. */ -int -pinentry_inq_quality (pinentry_t pin, const char *passphrase, size_t length) -{ - assuan_context_t ctx = pin->ctx_assuan; - const char prefix[] = "INQUIRE QUALITY "; - char *command; - char *line; - size_t linelen, clen; - int gotvalue = 0; - int value = 0; - int rc; - - if (!ctx) - return 0; /* Can't run the callback. */ - - if (length > 300) - length = 300; /* Limit so that it definitely fits into an Assuan - line. */ - - clen = strlen (prefix) + 3*length + 1; - command = secmem_malloc (clen); - if (!command) - return 0; - strlcpy (command, prefix, clen); - copy_and_escape (command + strlen(command), passphrase, length); - rc = assuan_write_line (ctx, command); - secmem_free (command); - if (rc) - { - fprintf (stderr, "ASSUAN WRITE LINE failed: rc=%d\n", rc); - return 0; - } - - for (;;) - { - do - { - rc = assuan_read_line (ctx, &line, &linelen); - if (rc) - { - fprintf (stderr, "ASSUAN READ LINE failed: rc=%d\n", rc); - return 0; - } - } - while (*line == '#' || !linelen); - if (line[0] == 'E' && line[1] == 'N' && line[2] == 'D' - && (!line[3] || line[3] == ' ')) - break; /* END command received*/ - if (line[0] == 'C' && line[1] == 'A' && line[2] == 'N' - && (!line[3] || line[3] == ' ')) - break; /* CAN command received*/ - if (line[0] == 'E' && line[1] == 'R' && line[2] == 'R' - && (!line[3] || line[3] == ' ')) - break; /* ERR command received*/ - if (line[0] != 'D' || line[1] != ' ' || linelen < 3 || gotvalue) - continue; - gotvalue = 1; - value = atoi (line+2); - } - if (value < -100) - value = -100; - else if (value > 100) - value = 100; - - return value; -} - - - -/* Try to make room for at least LEN bytes in the pinentry. Returns - new buffer on success and 0 on failure or when the old buffer is - sufficient. */ -char * -pinentry_setbufferlen (pinentry_t pin, int len) -{ - char *newp; - - if (pin->pin_len) - assert (pin->pin); - else - assert (!pin->pin); - - if (len < 2048) - len = 2048; - - if (len <= pin->pin_len) - return pin->pin; - - newp = secmem_realloc (pin->pin, len); - if (newp) - { - pin->pin = newp; - pin->pin_len = len; - } - else - { - secmem_free (pin->pin); - pin->pin = 0; - pin->pin_len = 0; - } - return newp; -} - -static void -pinentry_setbuffer_clear (pinentry_t pin) -{ - if (! pin->pin) - { - assert (pin->pin_len == 0); - return; - } - - assert (pin->pin_len > 0); - - secmem_free (pin->pin); - pin->pin = NULL; - pin->pin_len = 0; -} - -static void -pinentry_setbuffer_init (pinentry_t pin) -{ - pinentry_setbuffer_clear (pin); - pinentry_setbufferlen (pin, 0); -} - -/* passphrase better be alloced with secmem_alloc. */ -void -pinentry_setbuffer_use (pinentry_t pin, char *passphrase, int len) -{ - if (! passphrase) - { - assert (len == 0); - pinentry_setbuffer_clear (pin); - - return; - } - - if (passphrase && len == 0) - len = strlen (passphrase) + 1; - - if (pin->pin) - secmem_free (pin->pin); - - pin->pin = passphrase; - pin->pin_len = len; -} - -static struct assuan_malloc_hooks assuan_malloc_hooks = { - secmem_malloc, secmem_realloc, secmem_free -}; - -/* Initialize the secure memory subsystem, drop privileges and return. - Must be called early. */ -void -pinentry_init (const char *pgmname) -{ - /* Store away our name. */ - if (strlen (pgmname) > sizeof this_pgmname - 2) - abort (); - strlcpy (this_pgmname, pgmname, sizeof(this_pgmname)); - - gpgrt_check_version (NULL); - - /* Initialize secure memory. 1 is too small, so the default size - will be used. */ - secmem_init (1); - secmem_set_flags (SECMEM_WARN); - drop_privs (); - - if (atexit (secmem_term)) - { - /* FIXME: Could not register at-exit function, bail out. */ - } - - assuan_set_malloc_hooks (&assuan_malloc_hooks); -} - -/* Simple test to check whether DISPLAY is set or the option --display - was given. Used to decide whether the GUI or curses should be - initialized. */ -int -pinentry_have_display (int argc, char **argv) -{ - for (; argc; argc--, argv++) - if (!strcmp (*argv, "--display") || !strncmp (*argv, "--display=", 10)) - return 1; - return 0; -} - - - -/* Print usage information and and provide strings for help. */ -static const char * -my_strusage( int level ) -{ - const char *p; - - switch (level) - { - case 11: p = this_pgmname; break; - case 12: p = "pinentry"; break; - case 13: p = VERSION; break; - case 14: p = "Copyright (C) 2015 g10 Code GmbH"; break; - case 19: p = "Please report bugs to <" BUGREPORT ">.\n"; break; - case 1: - case 40: - { - static char *str; - - if (!str) - { - size_t n = 50 + strlen (this_pgmname); - str = malloc (n); - if (str) - snprintf (str, n, "Usage: %s [options] (-h for help)", - this_pgmname); - } - p = str; - } - break; - case 41: - p = "Ask securely for a secret and print it to stdout."; - break; - - case 42: - p = "1"; /* Flag print 40 as part of 41. */ - break; - - default: p = NULL; break; - } - return p; -} - - -char * -parse_color (char *arg, pinentry_color_t *color_p, int *bright_p) -{ - static struct - { - const char *name; - pinentry_color_t color; - } colors[] = { { "none", PINENTRY_COLOR_NONE }, - { "default", PINENTRY_COLOR_DEFAULT }, - { "black", PINENTRY_COLOR_BLACK }, - { "red", PINENTRY_COLOR_RED }, - { "green", PINENTRY_COLOR_GREEN }, - { "yellow", PINENTRY_COLOR_YELLOW }, - { "blue", PINENTRY_COLOR_BLUE }, - { "magenta", PINENTRY_COLOR_MAGENTA }, - { "cyan", PINENTRY_COLOR_CYAN }, - { "white", PINENTRY_COLOR_WHITE } }; - - int i; - char *new_arg; - pinentry_color_t color = PINENTRY_COLOR_DEFAULT; - - if (!arg) - return NULL; - - new_arg = strchr (arg, ','); - if (new_arg) - new_arg++; - - if (bright_p) - { - const char *bname[] = { "bright-", "bright", "bold-", "bold" }; - - *bright_p = 0; - for (i = 0; i < sizeof (bname) / sizeof (bname[0]); i++) - if (!strncasecmp (arg, bname[i], strlen (bname[i]))) - { - *bright_p = 1; - arg += strlen (bname[i]); - } - } - - for (i = 0; i < sizeof (colors) / sizeof (colors[0]); i++) - if (!strncasecmp (arg, colors[i].name, strlen (colors[i].name))) - color = colors[i].color; - - *color_p = color; - return new_arg; -} - -/* Parse the command line options. May exit the program if only help - or version output is requested. */ -void -pinentry_parse_opts (int argc, char *argv[]) -{ - static ARGPARSE_OPTS opts[] = { - ARGPARSE_s_n('d', "debug", "Turn on debugging output"), - ARGPARSE_s_s('D', "display", "|DISPLAY|Set the X display"), - ARGPARSE_s_s('T', "ttyname", "|FILE|Set the tty terminal node name"), - ARGPARSE_s_s('N', "ttytype", "|NAME|Set the tty terminal type"), - ARGPARSE_s_s('C', "lc-ctype", "|STRING|Set the tty LC_CTYPE value"), - ARGPARSE_s_s('M', "lc-messages", "|STRING|Set the tty LC_MESSAGES value"), - ARGPARSE_s_i('o', "timeout", - "|SECS|Timeout waiting for input after this many seconds"), - ARGPARSE_s_n('g', "no-global-grab", - "Grab keyboard only while window is focused"), - ARGPARSE_s_u('W', "parent-wid", "Parent window ID (for positioning)"), - ARGPARSE_s_s('c', "colors", "|STRING|Set custom colors for ncurses"), - ARGPARSE_end() - }; - ARGPARSE_ARGS pargs; - memset (&pargs, 0, sizeof (pargs)); - pargs.argc = &argc; - pargs.argv = &argv; - pargs.flags = 0; - - set_strusage (my_strusage); - - pinentry_reset (1); - - while (arg_parse (&pargs, opts)) - { - switch (pargs.r_opt) - { - case 'd': - pinentry.debug = 1; - break; - case 'g': - pinentry.grab = 0; - break; - - case 'D': - /* Note, this is currently not used because the GUI engine - has already been initialized when parsing these options. */ - pinentry.display = strdup (pargs.r.ret_str); - if (!pinentry.display) - { - exit (EXIT_FAILURE); - } - break; - case 'T': - pinentry.ttyname = strdup (pargs.r.ret_str); - if (!pinentry.ttyname) - { - exit (EXIT_FAILURE); - } - break; - case 'N': - pinentry.ttytype = strdup (pargs.r.ret_str); - if (!pinentry.ttytype) - { - exit (EXIT_FAILURE); - } - break; - case 'C': - pinentry.lc_ctype = strdup (pargs.r.ret_str); - if (!pinentry.lc_ctype) - { - exit (EXIT_FAILURE); - } - break; - case 'M': - pinentry.lc_messages = strdup (pargs.r.ret_str); - if (!pinentry.lc_messages) - { - exit (EXIT_FAILURE); - } - break; - case 'W': - pinentry.parent_wid = pargs.r.ret_ulong; - break; - - case 'c': - { - char *tmpstr = pargs.r.ret_str; - - tmpstr = parse_color (tmpstr, &pinentry.color_fg, - &pinentry.color_fg_bright); - tmpstr = parse_color (tmpstr, &pinentry.color_bg, NULL); - tmpstr = parse_color (tmpstr, &pinentry.color_so, - &pinentry.color_so_bright); - } - break; - - case 'o': - pinentry.timeout = pargs.r.ret_int; - break; - - default: - pargs.err = ARGPARSE_PRINT_WARNING; - break; - } - } -} - - -static gpg_error_t -option_handler (assuan_context_t ctx, const char *key, const char *value) -{ - (void)ctx; - - if (!strcmp (key, "no-grab") && !*value) - pinentry.grab = 0; - else if (!strcmp (key, "grab") && !*value) - pinentry.grab = 1; - else if (!strcmp (key, "debug-wait")) - { - } - else if (!strcmp (key, "display")) - { - if (pinentry.display) - free (pinentry.display); - pinentry.display = strdup (value); - if (!pinentry.display) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "ttyname")) - { - if (pinentry.ttyname) - free (pinentry.ttyname); - pinentry.ttyname = strdup (value); - if (!pinentry.ttyname) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "ttytype")) - { - if (pinentry.ttytype) - free (pinentry.ttytype); - pinentry.ttytype = strdup (value); - if (!pinentry.ttytype) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "lc-ctype")) - { - if (pinentry.lc_ctype) - free (pinentry.lc_ctype); - pinentry.lc_ctype = strdup (value); - if (!pinentry.lc_ctype) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "lc-messages")) - { - if (pinentry.lc_messages) - free (pinentry.lc_messages); - pinentry.lc_messages = strdup (value); - if (!pinentry.lc_messages) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "parent-wid")) - { - pinentry.parent_wid = atoi (value); - /* FIXME: Use strtol and add some error handling. */ - } - else if (!strcmp (key, "touch-file")) - { - if (pinentry.touch_file) - free (pinentry.touch_file); - pinentry.touch_file = strdup (value); - if (!pinentry.touch_file) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "default-ok")) - { - pinentry.default_ok = strdup (value); - if (!pinentry.default_ok) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "default-cancel")) - { - pinentry.default_cancel = strdup (value); - if (!pinentry.default_cancel) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "default-prompt")) - { - pinentry.default_prompt = strdup (value); - if (!pinentry.default_prompt) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "default-pwmngr")) - { - pinentry.default_pwmngr = strdup (value); - if (!pinentry.default_pwmngr) - return gpg_error_from_syserror (); - } - else if (!strcmp (key, "allow-external-password-cache") && !*value) - { - pinentry.allow_external_password_cache = 1; - pinentry.tried_password_cache = 0; - } - else if (!strcmp (key, "allow-emacs-prompt") && !*value) - { - return gpg_error (GPG_ERR_NOT_SUPPORTED); - } - else - return gpg_error (GPG_ERR_UNKNOWN_OPTION); - return 0; -} - - -/* Note, that it is sufficient to allocate the target string D as - long as the source string S, i.e.: strlen(s)+1; */ -static void -strcpy_escaped (char *d, const char *s) -{ - while (*s) - { - if (*s == '%' && s[1] && s[2]) - { - s++; - *d++ = xtoi_2 ( s); - s += 2; - } - else - *d++ = *s++; - } - *d = 0; -} - - -static gpg_error_t -cmd_setdesc (assuan_context_t ctx, char *line) -{ - char *newd; - - (void)ctx; - - newd = malloc (strlen (line) + 1); - if (!newd) - return gpg_error_from_syserror (); - - strcpy_escaped (newd, line); - if (pinentry.description) - free (pinentry.description); - pinentry.description = newd; - return 0; -} - - -static gpg_error_t -cmd_setprompt (assuan_context_t ctx, char *line) -{ - char *newp; - - (void)ctx; - - newp = malloc (strlen (line) + 1); - if (!newp) - return gpg_error_from_syserror (); - - strcpy_escaped (newp, line); - if (pinentry.prompt) - free (pinentry.prompt); - pinentry.prompt = newp; - return 0; -} - - -/* The data provided at LINE may be used by pinentry implementations - to identify a key for caching strategies of its own. The empty - string and --clear mean that the key does not have a stable - identifier. */ -static gpg_error_t -cmd_setkeyinfo (assuan_context_t ctx, char *line) -{ - (void)ctx; - - if (pinentry.keyinfo) - free (pinentry.keyinfo); - - if (*line && strcmp(line, "--clear") != 0) - pinentry.keyinfo = strdup (line); - else - pinentry.keyinfo = NULL; - - return 0; -} - - -static gpg_error_t -cmd_setrepeat (assuan_context_t ctx, char *line) -{ - char *p; - - (void)ctx; - - p = malloc (strlen (line) + 1); - if (!p) - return gpg_error_from_syserror (); - - strcpy_escaped (p, line); - free (pinentry.repeat_passphrase); - pinentry.repeat_passphrase = p; - return 0; -} - - -static gpg_error_t -cmd_setrepeaterror (assuan_context_t ctx, char *line) -{ - char *p; - - (void)ctx; - - p = malloc (strlen (line) + 1); - if (!p) - return gpg_error_from_syserror (); - - strcpy_escaped (p, line); - free (pinentry.repeat_error_string); - pinentry.repeat_error_string = p; - return 0; -} - - -static gpg_error_t -cmd_seterror (assuan_context_t ctx, char *line) -{ - char *newe; - - (void)ctx; - - newe = malloc (strlen (line) + 1); - if (!newe) - return gpg_error_from_syserror (); - - strcpy_escaped (newe, line); - if (pinentry.error) - free (pinentry.error); - pinentry.error = newe; - return 0; -} - - -static gpg_error_t -cmd_setok (assuan_context_t ctx, char *line) -{ - char *newo; - - (void)ctx; - - newo = malloc (strlen (line) + 1); - if (!newo) - return gpg_error_from_syserror (); - - strcpy_escaped (newo, line); - if (pinentry.ok) - free (pinentry.ok); - pinentry.ok = newo; - return 0; -} - - -static gpg_error_t -cmd_setnotok (assuan_context_t ctx, char *line) -{ - char *newo; - - (void)ctx; - - newo = malloc (strlen (line) + 1); - if (!newo) - return gpg_error_from_syserror (); - - strcpy_escaped (newo, line); - if (pinentry.notok) - free (pinentry.notok); - pinentry.notok = newo; - return 0; -} - - -static gpg_error_t -cmd_setcancel (assuan_context_t ctx, char *line) -{ - char *newc; - - (void)ctx; - - newc = malloc (strlen (line) + 1); - if (!newc) - return gpg_error_from_syserror (); - - strcpy_escaped (newc, line); - if (pinentry.cancel) - free (pinentry.cancel); - pinentry.cancel = newc; - return 0; -} - - -static gpg_error_t -cmd_settimeout (assuan_context_t ctx, char *line) -{ - (void)ctx; - - if (line && *line) - pinentry.timeout = atoi (line); - - return 0; -} - -static gpg_error_t -cmd_settitle (assuan_context_t ctx, char *line) -{ - char *newt; - - (void)ctx; - - newt = malloc (strlen (line) + 1); - if (!newt) - return gpg_error_from_syserror (); - - strcpy_escaped (newt, line); - if (pinentry.title) - free (pinentry.title); - pinentry.title = newt; - return 0; -} - -static gpg_error_t -cmd_setqualitybar (assuan_context_t ctx, char *line) -{ - char *newval; - - (void)ctx; - - if (!*line) - line = "Quality:"; - - newval = malloc (strlen (line) + 1); - if (!newval) - return gpg_error_from_syserror (); - - strcpy_escaped (newval, line); - if (pinentry.quality_bar) - free (pinentry.quality_bar); - pinentry.quality_bar = newval; - return 0; -} - -/* Set the tooltip to be used for a quality bar. */ -static gpg_error_t -cmd_setqualitybar_tt (assuan_context_t ctx, char *line) -{ - char *newval; - - (void)ctx; - - if (*line) - { - newval = malloc (strlen (line) + 1); - if (!newval) - return gpg_error_from_syserror (); - - strcpy_escaped (newval, line); - } - else - newval = NULL; - if (pinentry.quality_bar_tt) - free (pinentry.quality_bar_tt); - pinentry.quality_bar_tt = newval; - return 0; -} - - -static gpg_error_t -cmd_getpin (assuan_context_t ctx, char *line) -{ - int result; - int set_prompt = 0; - int just_read_password_from_cache = 0; - - (void)line; - - pinentry_setbuffer_init (&pinentry); - if (!pinentry.pin) - return gpg_error (GPG_ERR_ENOMEM); - - /* Try reading from the password cache. */ - if (/* If repeat passphrase is set, then we don't want to read from - the cache. */ - ! pinentry.repeat_passphrase - /* Are we allowed to read from the cache? */ - && pinentry.allow_external_password_cache - && pinentry.keyinfo - /* Only read from the cache if we haven't already tried it. */ - && ! pinentry.tried_password_cache - /* If the last read resulted in an error, then don't read from - the cache. */ - && ! pinentry.error) - { - char *password; - - pinentry.tried_password_cache = 1; - - password = password_cache_lookup (pinentry.keyinfo); - if (password) - /* There is a cached password. Try it. */ - { - int len = strlen(password) + 1; - if (len > pinentry.pin_len) - len = pinentry.pin_len; - - memcpy (pinentry.pin, password, len); - pinentry.pin[len] = '\0'; - - secmem_free (password); - - pinentry.pin_from_cache = 1; - - assuan_write_status (ctx, "PASSWORD_FROM_CACHE", ""); - - /* Result is the length of the password not including the - NUL terminator. */ - result = len - 1; - - just_read_password_from_cache = 1; - - goto out; - } - } - - /* The password was not cached (or we are not allowed to / cannot - use the cache). Prompt the user. */ - pinentry.pin_from_cache = 0; - - if (!pinentry.prompt) - { - pinentry.prompt = pinentry.default_prompt?pinentry.default_prompt:"PIN:"; - set_prompt = 1; - } - pinentry.locale_err = 0; - pinentry.specific_err = 0; - pinentry.close_button = 0; - pinentry.repeat_okay = 0; - pinentry.one_button = 0; - pinentry.ctx_assuan = ctx; - result = (*pinentry_cmd_handler) (&pinentry); - pinentry.ctx_assuan = NULL; - if (pinentry.error) - { - free (pinentry.error); - pinentry.error = NULL; - } - if (pinentry.repeat_passphrase) - { - free (pinentry.repeat_passphrase); - pinentry.repeat_passphrase = NULL; - } - if (set_prompt) - pinentry.prompt = NULL; - - pinentry.quality_bar = 0; /* Reset it after the command. */ - - if (pinentry.close_button) - assuan_write_status (ctx, "BUTTON_INFO", "close"); - - if (result < 0) - { - pinentry_setbuffer_clear (&pinentry); - if (pinentry.specific_err) - return pinentry.specific_err; - return (pinentry.locale_err - ? gpg_error (GPG_ERR_LOCALE_PROBLEM) - : gpg_error (GPG_ERR_CANCELED)); - } - - out: - if (result) - { - if (pinentry.repeat_okay) - assuan_write_status (ctx, "PIN_REPEATED", ""); - result = assuan_send_data (ctx, pinentry.pin, strlen(pinentry.pin)); - if (!result) - result = assuan_send_data (ctx, NULL, 0); - - if (/* GPG Agent says it's okay. */ - pinentry.allow_external_password_cache && pinentry.keyinfo - /* We didn't just read it from the cache. */ - && ! just_read_password_from_cache - /* And the user said it's okay. */ - && pinentry.may_cache_password) - /* Cache the password. */ - password_cache_save (pinentry.keyinfo, pinentry.pin); - } - - pinentry_setbuffer_clear (&pinentry); - - return result; -} - - -/* Note that the option --one-button is a hack to allow the use of old - pinentries while the caller is ignoring the result. Given that - options have never been used or flagged as an error the new option - is an easy way to enable the messsage mode while not requiring to - update pinentry or to have the caller test for the message - command. New applications which are free to require an updated - pinentry should use MESSAGE instead. */ -static gpg_error_t -cmd_confirm (assuan_context_t ctx, char *line) -{ - int result; - - pinentry.one_button = !!strstr (line, "--one-button"); - pinentry.quality_bar = 0; - pinentry.close_button = 0; - pinentry.locale_err = 0; - pinentry.specific_err = 0; - pinentry.canceled = 0; - pinentry_setbuffer_clear (&pinentry); - result = (*pinentry_cmd_handler) (&pinentry); - if (pinentry.error) - { - free (pinentry.error); - pinentry.error = NULL; - } - - if (pinentry.close_button) - assuan_write_status (ctx, "BUTTON_INFO", "close"); - - if (result) - return 0; - - if (pinentry.specific_err) - return pinentry.specific_err; - - if (pinentry.locale_err) - return gpg_error (GPG_ERR_LOCALE_PROBLEM); - - if (pinentry.one_button) - return 0; - - if (pinentry.canceled) - return gpg_error (GPG_ERR_CANCELED); - return gpg_error (GPG_ERR_NOT_CONFIRMED); -} - - -static gpg_error_t -cmd_message (assuan_context_t ctx, char *line) -{ - (void)line; - - return cmd_confirm (ctx, "--one-button"); -} - -/* GETINFO - - Multipurpose function to return a variety of information. - Supported values for WHAT are: - - version - Return the version of the program. - pid - Return the process id of the server. - */ -static gpg_error_t -cmd_getinfo (assuan_context_t ctx, char *line) -{ - int rc; - - if (!strcmp (line, "version")) - { - const char *s = VERSION; - rc = assuan_send_data (ctx, s, strlen (s)); - } - else if (!strcmp (line, "pid")) - { - char numbuf[50]; - - snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ()); - rc = assuan_send_data (ctx, numbuf, strlen (numbuf)); - } - else - rc = gpg_error (GPG_ERR_ASS_PARAMETER); - return rc; -} - -/* CLEARPASSPHRASE - - Clear the cache passphrase associated with the key identified by - cacheid. - */ -static gpg_error_t -cmd_clear_passphrase (assuan_context_t ctx, char *line) -{ - (void)ctx; - - if (! line) - return gpg_error (GPG_ERR_ASS_INV_VALUE); - - /* Remove leading and trailing white space. */ - while (*line == ' ') - line ++; - while (line[strlen (line) - 1] == ' ') - line[strlen (line) - 1] = 0; - - switch (password_cache_clear (line)) - { - case 1: return 0; - case 0: return gpg_error (GPG_ERR_ASS_INV_VALUE); - default: return gpg_error (GPG_ERR_ASS_GENERAL); - } -} - -/* Tell the assuan library about our commands. */ -static gpg_error_t -register_commands (assuan_context_t ctx) -{ - static struct - { - const char *name; - gpg_error_t (*handler) (assuan_context_t, char *line); - } table[] = - { - { "SETDESC", cmd_setdesc }, - { "SETPROMPT", cmd_setprompt }, - { "SETKEYINFO", cmd_setkeyinfo }, - { "SETREPEAT", cmd_setrepeat }, - { "SETREPEATERROR", cmd_setrepeaterror }, - { "SETERROR", cmd_seterror }, - { "SETOK", cmd_setok }, - { "SETNOTOK", cmd_setnotok }, - { "SETCANCEL", cmd_setcancel }, - { "GETPIN", cmd_getpin }, - { "CONFIRM", cmd_confirm }, - { "MESSAGE", cmd_message }, - { "SETQUALITYBAR", cmd_setqualitybar }, - { "SETQUALITYBAR_TT", cmd_setqualitybar_tt }, - { "GETINFO", cmd_getinfo }, - { "SETTITLE", cmd_settitle }, - { "SETTIMEOUT", cmd_settimeout }, - { "CLEARPASSPHRASE", cmd_clear_passphrase }, - { NULL, NULL } - }; - int i, j; - gpg_error_t rc; - - for (i = j = 0; table[i].name; i++) - { - rc = assuan_register_command (ctx, table[i].name, table[i].handler, NULL); - if (rc) - return rc; - } - return 0; -} - - -int -pinentry_loop2 (int infd, int outfd) -{ - gpg_error_t rc; - assuan_fd_t filedes[2]; - assuan_context_t ctx; - - /* Extra check to make sure we have dropped privs. */ - if (getuid() != geteuid()) - abort (); - - rc = assuan_new (&ctx); - if (rc) - { - fprintf (stderr, "server context creation failed: %s\n", - gpg_strerror (rc)); - return -1; - } - - /* For now we use a simple pipe based server so that we can work - from scripts. We will later add options to run as a daemon and - wait for requests on a Unix domain socket. */ - filedes[0] = assuan_fdopen (infd); - filedes[1] = assuan_fdopen (outfd); - rc = assuan_init_pipe_server (ctx, filedes); - if (rc) - { - fprintf (stderr, "%s: failed to initialize the server: %s\n", - this_pgmname, gpg_strerror (rc)); - return -1; - } - rc = register_commands (ctx); - if (rc) - { - fprintf (stderr, "%s: failed to the register commands with Assuan: %s\n", - this_pgmname, gpg_strerror (rc)); - return -1; - } - - assuan_register_option_handler (ctx, option_handler); - assuan_register_reset_notify (ctx, pinentry_assuan_reset_handler); - - for (;;) - { - rc = assuan_accept (ctx); - if (rc == -1) - break; - else if (rc) - { - fprintf (stderr, "%s: Assuan accept problem: %s\n", - this_pgmname, gpg_strerror (rc)); - break; - } - - rc = assuan_process (ctx); - if (rc) - { - fprintf (stderr, "%s: Assuan processing failed: %s\n", - this_pgmname, gpg_strerror (rc)); - continue; - } - } - - assuan_release (ctx); - return 0; -} - - -/* Start the pinentry event loop. The program will start to process - Assuan commands until it is finished or an error occurs. If an - error occurs, -1 is returned. Otherwise, 0 is returned. */ -int -pinentry_loop (void) -{ - return pinentry_loop2 (STDIN_FILENO, STDOUT_FILENO); -} blob - e154ac5cec9da26363e72be00caa1175a2724a2e (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/pinentry.h +++ /dev/null @@ -1,280 +0,0 @@ -/* pinentry.h - The interface for the PIN entry support library. - Copyright (C) 2002, 2003, 2010, 2015 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, see . - */ - -#ifndef PINENTRY_H -#define PINENTRY_H - -#ifdef __cplusplus -extern "C" { -#if 0 -} -#endif -#endif - -typedef enum { - PINENTRY_COLOR_NONE, PINENTRY_COLOR_DEFAULT, - PINENTRY_COLOR_BLACK, PINENTRY_COLOR_RED, - PINENTRY_COLOR_GREEN, PINENTRY_COLOR_YELLOW, - PINENTRY_COLOR_BLUE, PINENTRY_COLOR_MAGENTA, - PINENTRY_COLOR_CYAN, PINENTRY_COLOR_WHITE -} pinentry_color_t; - -struct pinentry -{ - /* The window title, or NULL. (Assuan: "SETTITLE TITLE".) */ - char *title; - /* The description to display, or NULL. (Assuan: "SETDESC - DESC".) */ - char *description; - /* The error message to display, or NULL. (Assuan: "SETERROR - MESSAGE".) */ - char *error; - /* The prompt to display, or NULL. (Assuan: "SETPROMPT - prompt".) */ - char *prompt; - /* The OK button text to display, or NULL. (Assuan: "SETOK - OK".) */ - char *ok; - /* The Not-OK button text to display, or NULL. This is the text for - the alternative option shown by the third button. (Assuan: - "SETNOTOK NOTOK".) */ - char *notok; - /* The Cancel button text to display, or NULL. (Assuan: "SETCANCEL - CANCEL".) */ - char *cancel; - - /* The buffer to store the secret into. */ - char *pin; - /* The length of the buffer. */ - int pin_len; - /* Whether the pin was read from an external cache (1) or entered by - the user (0). */ - int pin_from_cache; - - /* The name of the X display to use if X is available and supported. - (Assuan: "OPTION display DISPLAY".) */ - char *display; - /* The name of the terminal node to open if X not available or - supported. (Assuan: "OPTION ttyname TTYNAME".) */ - char *ttyname; - /* The type of the terminal. (Assuan: "OPTION ttytype TTYTYPE".) */ - char *ttytype; - /* The LC_CTYPE value for the terminal. (Assuan: "OPTION lc-ctype - LC_CTYPE".) */ - char *lc_ctype; - /* The LC_MESSAGES value for the terminal. (Assuan: "OPTION - lc-messages LC_MESSAGES".) */ - char *lc_messages; - - /* True if debug mode is requested. */ - int debug; - - /* The number of seconds before giving up while waiting for user input. */ - int timeout; - - /* True if caller should grab the keyboard. (Assuan: "OPTION grab" - or "OPTION no-grab".) */ - int grab; - /* The window ID of the parent window over which the pinentry window - should be displayed. (Assuan: "OPTION parent-wid WID".) */ - int parent_wid; - - /* The name of an optional file which will be touched after a curses - entry has been displayed. (Assuan: "OPTION touch-file - FILENAME".) */ - char *touch_file; - - /* The frontend should set this to -1 if the user canceled the - request, and to the length of the PIN stored in pin - otherwise. */ - int result; - - /* The frontend should set this if the NOTOK button was pressed. */ - int canceled; - - /* The frontend should set this to true if an error with the local - conversion occured. */ - int locale_err; - - /* The frontend should set this to a gpg-error so that commands are - able to return specific error codes. This is an ugly hack due to - the fact that pinentry_cmd_handler_t returns the length of the - passphrase or a negative error code. */ - int specific_err; - - /* The frontend should set this to true if the window close button - has been used. This flag is used in addition to a regular return - value. */ - int close_button; - - /* The caller should set this to true if only one button is - required. This is useful for notification dialogs where only a - dismiss button is required. */ - int one_button; - - /* If true a second prompt for the passphrase is shown and the user - is expected to enter the same passphrase again. Pinentry checks - that both match. (Assuan: "SETREPEAT".) */ - char *repeat_passphrase; - - /* The string to show if a repeated passphrase does not match. - (Assuan: "SETREPEATERROR ERROR".) */ - char *repeat_error_string; - - /* Set to true if the passphrase has been entered a second time and - matches the first passphrase. */ - int repeat_okay; - - /* If this is not NULL, a passphrase quality indicator is shown. - There will also be an inquiry back to the caller to get an - indication of the quality for the passphrase entered so far. The - string is used as a label for the quality bar. (Assuan: - "SETQUALITYBAR LABEL".) */ - char *quality_bar; - - /* The tooltip to be show for the qualitybar. Malloced or NULL. - (Assuan: "SETQUALITYBAR_TT TOOLTIP".) */ - char *quality_bar_tt; - - /* For the curses pinentry, the color of error messages. */ - pinentry_color_t color_fg; - int color_fg_bright; - pinentry_color_t color_bg; - pinentry_color_t color_so; - int color_so_bright; - - /* Malloced and i18ned default strings or NULL. These strings may - include an underscore character to indicate an accelerator key. - A double underscore represents a plain one. */ - /* (Assuan: "OPTION default-ok OK"). */ - char *default_ok; - /* (Assuan: "OPTION default-cancel CANCEL"). */ - char *default_cancel; - /* (Assuan: "OPTION default-prompt PROMPT"). */ - char *default_prompt; - /* (Assuan: "OPTION default-pwmngr - SAVE_PASSWORD_WITH_PASSWORD_MANAGER?"). */ - char *default_pwmngr; - - /* Whether we are allowed to read the password from an external - cache. (Assuan: "OPTION allow-external-password-cache") */ - int allow_external_password_cache; - - /* We only try the cache once. */ - int tried_password_cache; - - /* A stable identifier for the key. (Assuan: "SETKEYINFO - KEYINFO".) */ - char *keyinfo; - - /* Whether we may cache the password (according to the user). */ - int may_cache_password; - - /* NOTE: If you add any additional fields to this structure, be sure - to update the initializer in pinentry/pinentry.c!!! */ - - /* For the quality indicator we need to do an inquiry. Thus we need - to save the assuan ctx. */ - void *ctx_assuan; - -}; -typedef struct pinentry *pinentry_t; - - -/* The pinentry command handler type processes the pinentry request - PIN. If PIN->pin is zero, request a confirmation, otherwise a PIN - entry. On confirmation, the function should return TRUE if - confirmed, and FALSE otherwise. On PIN entry, the function should - return -1 if an error occured or the user cancelled the operation - and 1 otherwise. */ -typedef int (*pinentry_cmd_handler_t) (pinentry_t pin); - -/* Start the pinentry event loop. The program will start to process - Assuan commands until it is finished or an error occurs. If an - error occurs, -1 is returned and errno indicates the type of an - error. Otherwise, 0 is returned. */ -int pinentry_loop (void); - -/* The same as above but allows to specify the i/o descriptors. - * infd and outfd will be duplicated in this function so the caller - * still has to close them if necessary. - */ -int pinentry_loop2 (int infd, int outfd); - - -/* Convert the UTF-8 encoded string TEXT to the encoding given in - LC_CTYPE. Return NULL on error. */ -char *pinentry_utf8_to_local (const char *lc_ctype, const char *text); - -/* Convert TEXT which is encoded according to LC_CTYPE to UTF-8. With - SECURE set to true, use secure memory for the returned buffer. - Return NULL on error. */ -char *pinentry_local_to_utf8 (char *lc_ctype, char *text, int secure); - - -/* Run a quality inquiry for PASSPHRASE of LENGTH. */ -int pinentry_inq_quality (pinentry_t pin, - const char *passphrase, size_t length); - -/* Try to make room for at least LEN bytes for the pin in the pinentry - PIN. Returns new buffer on success and 0 on failure. */ -char *pinentry_setbufferlen (pinentry_t pin, int len); - -/* Use the buffer at BUFFER for PIN->PIN. BUFFER must be NULL or - allocated using secmem_alloc. LEN is the size of the buffer. If - it is unknown, but BUFFER is a NUL terminated string, you pass 0 to - just use strlen(buffer)+1. */ -void pinentry_setbuffer_use (pinentry_t pin, char *buffer, int len); - -/* Initialize the secure memory subsystem, drop privileges and - return. Must be called early. */ -void pinentry_init (const char *pgmname); - -/* Return true if either DISPLAY is set or ARGV contains the string - "--display". */ -int pinentry_have_display (int argc, char **argv); - -/* Parse the command line options. May exit the program if only help - or version output is requested. */ -void pinentry_parse_opts (int argc, char *argv[]); - - -/* The caller must define this variable to process assuan commands. */ -extern pinentry_cmd_handler_t pinentry_cmd_handler; - - - - - -#ifdef HAVE_W32_SYSTEM -/* Windows declares sleep as obsolete, but provides a definition for - _sleep but non for the still existing sleep. */ -#define sleep(a) _sleep ((a)) -#endif /*HAVE_W32_SYSTEM*/ - - - -#if 0 -{ -#endif -#ifdef __cplusplus -} -#endif - -#endif /* PINENTRY_H */ blob - 88a5d45b954d447cc049094dcb1a54f8a405b8ad (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/secmem++.h +++ /dev/null @@ -1,91 +0,0 @@ -/* STL allocator for secmem - * Copyright (C) 2008 Marc Mutz - * - * 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 - -namespace secmem { - - template - 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 - struct rebind { - typedef alloc 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 alloc( const alloc & ) {} - // 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( 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 - bool operator==( const alloc &, const alloc & ) { return true; } - template - bool operator!=( const alloc &, const alloc & ) { return false; } - -} - -#endif /* __SECMEM_SECMEMPP_H__ */ blob - b422182b499b577adbf844227b48750ae62d3930 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/secmem-util.h +++ /dev/null @@ -1,3 +0,0 @@ -/* This file exists because "util.h" is such a generic name that it is - likely to clash with other such files. */ -#include "util.h" blob - afe89eee03e79224e5e016f8f5ac59fdfb685c34 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/secmem.c +++ /dev/null @@ -1,462 +0,0 @@ -/* secmem.c - memory allocation from a secure heap - * Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. - * Copyright (C) 2015 g10 Code GmbH - * - * This file is part of GnuPG. - * - * GnuPG 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. - * - * GnuPG 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 - */ - -#include "../../master.h" - -#include -#include -#include -#include -#include -#if defined(HAVE_MLOCK) || defined(HAVE_MMAP) -# include -# include -# include -# ifdef USE_CAPABILITIES -# include -# endif -#endif -#include - -#include "memory.h" - -#ifdef ORIGINAL_GPG_VERSION -#include "types.h" -#include "util.h" -#else /* ORIGINAL_GPG_VERSION */ - -#include "util.h" - -typedef union { - int a; - short b; - char c[1]; - long d; -#ifdef HAVE_U64_TYPEDEF - u64 e; -#endif - float f; - double g; -} PROPERLY_ALIGNED_TYPE; - -#define log_error log_info -#define log_bug log_fatal - -void -log_info(char *template, ...) -{ - va_list args; - - va_start(args, template); - vfprintf(stderr, template, args); - va_end(args); -} - -void -log_fatal(char *template, ...) -{ - va_list args; - - va_start(args, template); - vfprintf(stderr, template, args); - va_end(args); - exit(EXIT_FAILURE); -} - -#endif /* ORIGINAL_GPG_VERSION */ - -#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) -# define MAP_ANONYMOUS MAP_ANON -#endif - -#define DEFAULT_POOLSIZE 16384 - -typedef struct memblock_struct MEMBLOCK; -struct memblock_struct { - unsigned size; - union { - MEMBLOCK *next; - PROPERLY_ALIGNED_TYPE aligned; - } u; -}; - - - -static void *pool; -static volatile int pool_okay; /* may be checked in an atexit function */ -__attribute__((unused)) static int pool_is_mmapped; -static size_t poolsize; /* allocated length */ -static size_t poollen; /* used length */ -static MEMBLOCK *unused_blocks; -static unsigned max_alloced; -static unsigned cur_alloced; -static unsigned max_blocks; -static unsigned cur_blocks; -static int disable_secmem; -static int show_warning; -static int no_warning; -static int suspend_warning; - - -static void -print_warn(void) -{ - if( !no_warning ) - log_info("Warning: using insecure memory!\n"); -} - - -static void -lock_pool( UNUSED void *p, UNUSED size_t n ) -{ -#if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK) - int err; - - cap_set_proc( cap_from_text("cap_ipc_lock+ep") ); - err = mlock( p, n ); - if( err && errno ) - err = errno; - cap_set_proc( cap_from_text("cap_ipc_lock+p") ); - - if( err ) { - if( errno != EPERM - #ifdef EAGAIN /* OpenBSD returns this */ - && errno != EAGAIN - #endif - ) - log_error("can't lock memory: %s\n", strerror(err)); - show_warning = 1; - } - -#elif defined(HAVE_MLOCK) - uid_t uid; - int err; - - uid = getuid(); - -#ifdef HAVE_BROKEN_MLOCK - if( uid ) { - errno = EPERM; - err = errno; - } - else { - err = mlock( p, n ); - if( err && errno ) - err = errno; - } -#else - err = mlock( p, n ); - if( err && errno ) - err = errno; -#endif - - if( uid && !geteuid() ) { - if( setuid( uid ) || getuid() != geteuid() ) - log_fatal("failed to reset uid: %s\n", strerror(errno)); - } - - if( err ) { - if( errno != EPERM -#ifdef EAGAIN /* OpenBSD returns this */ - && errno != EAGAIN -#endif - ) - log_error("can't lock memory: %s\n", strerror(err)); - show_warning = 1; - } - -#else - log_info("Please note that you don't have secure memory on this system\n"); -#endif -} - - -static void -init_pool( size_t n) -{ - __attribute__((unused)) size_t pgsize; - - poolsize = n; - - if( disable_secmem ) - log_bug("secure memory is disabled"); - -#ifdef HAVE_GETPAGESIZE - pgsize = getpagesize(); -#else - pgsize = 4096; -#endif - -#if HAVE_MMAP - poolsize = (poolsize + pgsize -1 ) & ~(pgsize-1); -# ifdef MAP_ANONYMOUS - pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); -# else /* map /dev/zero instead */ - { int fd; - - fd = open("/dev/zero", O_RDWR); - if( fd == -1 ) { - log_error("can't open /dev/zero: %s\n", strerror(errno) ); - pool = (void*)-1; - } - else { - pool = mmap( 0, poolsize, PROT_READ|PROT_WRITE, - MAP_PRIVATE, fd, 0); - close (fd); - } - } -# endif - if( pool == (void*)-1 ) - log_info("can't mmap pool of %u bytes: %s - using malloc\n", - (unsigned)poolsize, strerror(errno)); - else { - pool_is_mmapped = 1; - pool_okay = 1; - } - -#endif - if( !pool_okay ) { - pool = malloc( poolsize ); - if( !pool ) - log_fatal("can't allocate memory pool of %u bytes\n", - (unsigned)poolsize); - else - pool_okay = 1; - } - lock_pool( pool, poolsize ); - poollen = 0; -} - - -/* concatenate unused blocks */ -static void -compress_pool(void) -{ - /* fixme: we really should do this */ -} - -void -secmem_set_flags( unsigned flags ) -{ - int was_susp = suspend_warning; - - no_warning = flags & 1; - suspend_warning = flags & 2; - - /* and now issue the warning if it is not longer suspended */ - if( was_susp && !suspend_warning && show_warning ) { - show_warning = 0; - print_warn(); - } -} - -unsigned -secmem_get_flags(void) -{ - unsigned flags; - - flags = no_warning ? 1:0; - flags |= suspend_warning ? 2:0; - return flags; -} - -void -secmem_init( size_t n ) -{ - if( !n ) { -#ifdef USE_CAPABILITIES - /* drop all capabilities */ - cap_set_proc( cap_from_text("all-eip") ); - -#elif !defined(HAVE_DOSISH_SYSTEM) - uid_t uid; - - disable_secmem=1; - uid = getuid(); - if( uid != geteuid() ) { - if( setuid( uid ) || getuid() != geteuid() ) - log_fatal("failed to drop setuid\n" ); - } -#endif - } - else { - if( n < DEFAULT_POOLSIZE ) - n = DEFAULT_POOLSIZE; - if( !pool_okay ) - init_pool(n); - else - log_error("Oops, secure memory pool already initialized\n"); - } -} - - -void * -secmem_malloc( size_t size ) -{ - MEMBLOCK *mb, *mb2; - int compressed=0; - - if( !pool_okay ) { - log_info( - "operation is not possible without initialized secure memory\n"); - log_info("(you may have used the wrong program for this task)\n"); - exit(2); - } - if( show_warning && !suspend_warning ) { - show_warning = 0; - print_warn(); - } - - /* blocks are always a multiple of 32 */ - size += sizeof(MEMBLOCK); - size = ((size + 31) / 32) * 32; - - retry: - /* try to get it from the used blocks */ - for(mb = unused_blocks,mb2=NULL; mb; mb2=mb, mb = mb->u.next ) - if( mb->size >= size ) { - if( mb2 ) - mb2->u.next = mb->u.next; - else - unused_blocks = mb->u.next; - goto leave; - } - /* allocate a new block */ - if( (poollen + size <= poolsize) ) { - mb = (void*)((char*)pool + poollen); - poollen += size; - mb->size = size; - } - else if( !compressed ) { - compressed=1; - compress_pool(); - goto retry; - } - else - return NULL; - - leave: - cur_alloced += mb->size; - cur_blocks++; - if( cur_alloced > max_alloced ) - max_alloced = cur_alloced; - if( cur_blocks > max_blocks ) - max_blocks = cur_blocks; - - memset (&mb->u.aligned.c, 0, - size - (size_t) &((struct memblock_struct *) 0)->u.aligned.c); - - return &mb->u.aligned.c; -} - - -void * -secmem_realloc( void *p, size_t newsize ) -{ - MEMBLOCK *mb; - size_t size; - void *a; - - if (! p) - return secmem_malloc(newsize); - - mb = (MEMBLOCK*)((char*)p - ((size_t) &((MEMBLOCK*)0)->u.aligned.c)); - size = mb->size; - if( newsize < size ) - return p; /* it is easier not to shrink the memory */ - a = secmem_malloc( newsize ); - memcpy(a, p, size); - memset((char*)a+size, 0, newsize-size); - secmem_free(p); - return a; -} - - -void -secmem_free( void *a ) -{ - MEMBLOCK *mb; - size_t size; - - if( !a ) - return; - - mb = (MEMBLOCK*)((char*)a - ((size_t) &((MEMBLOCK*)0)->u.aligned.c)); - size = mb->size; - /* This does not make much sense: probably this memory is held in the - * cache. We do it anyway: */ - wipememory2(mb, 0xff, size ); - wipememory2(mb, 0xaa, size ); - wipememory2(mb, 0x55, size ); - wipememory2(mb, 0x00, size ); - mb->size = size; - mb->u.next = unused_blocks; - unused_blocks = mb; - cur_blocks--; - cur_alloced -= size; -} - -int -m_is_secure( const void *p ) -{ - return p >= pool && p < (void*)((char*)pool+poolsize); -} - -void -secmem_term(void) -{ - if( !pool_okay ) - return; - - wipememory2( pool, 0xff, poolsize); - wipememory2( pool, 0xaa, poolsize); - wipememory2( pool, 0x55, poolsize); - wipememory2( pool, 0x00, poolsize); -#if HAVE_MMAP - if( pool_is_mmapped ) - munmap( pool, poolsize ); -#endif - pool = NULL; - pool_okay = 0; - poolsize=0; - poollen=0; - unused_blocks=NULL; -} - - -void -secmem_dump_stats(void) -{ - if( disable_secmem ) - return; - fprintf(stderr, - "secmem usage: %u/%u bytes in %u/%u blocks of pool %lu/%lu\n", - cur_alloced, max_alloced, cur_blocks, max_blocks, - (ulong)poollen, (ulong)poolsize ); -} - - -size_t -secmem_get_max_size (void) -{ - return poolsize; -} blob - feddaf73b09360c488fa7cceec91a62481da3ee3 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/util.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Quintuple Agent - * Copyright (C) 1999 Robert Bihlmeyer - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#define _GNU_SOURCE 1 - -#include -#ifndef HAVE_W32CE_SYSTEM -# include -#endif -#include -#include -#include -#include -#include - -#include "util.h" - -#ifndef HAVE_DOSISH_SYSTEM -static int uid_set = 0; -static uid_t real_uid, file_uid; -#endif /*!HAVE_DOSISH_SYSTEM*/ - -/* Write DATA of size BYTES to FD, until all is written or an error - occurs. */ -ssize_t -xwrite(int fd, const void *data, size_t bytes) -{ - char *ptr; - size_t todo; - ssize_t written = 0; - - for (ptr = (char *)data, todo = bytes; todo; ptr += written, todo -= written) - { - do - written = write (fd, ptr, todo); - while ( -#ifdef HAVE_W32CE_SYSTEM - 0 -#else - written == -1 && errno == EINTR -#endif - ); - if (written < 0) - break; - } - return written; -} - -#if 0 -extern int debug; - -int -debugmsg(const char *fmt, ...) -{ - va_list va; - int ret; - - if (debug) { - va_start(va, fmt); - fprintf(stderr, "\e[4m"); - ret = vfprintf(stderr, fmt, va); - fprintf(stderr, "\e[24m"); - va_end(va); - return ret; - } else - return 0; -} -#endif - -/* initialize uid variables */ -#ifndef HAVE_DOSISH_SYSTEM -static void -init_uids(void) -{ - real_uid = getuid(); - file_uid = geteuid(); - uid_set = 1; -} -#endif - - -#if 0 /* Not used. */ -/* lower privileges to the real user's */ -void -lower_privs() -{ - if (!uid_set) - init_uids(); - if (real_uid != file_uid) { -#ifdef HAVE_SETEUID - if (seteuid(real_uid) < 0) { - perror("lowering privileges failed"); - exit(EXIT_FAILURE); - } -#else - fprintf(stderr, _("Warning: running q-agent setuid on this system is dangerous\n")); -#endif /* HAVE_SETEUID */ - } -} -#endif /* if 0 */ - -#if 0 /* Not used. */ -/* raise privileges to the effective user's */ -void -raise_privs() -{ - assert(real_uid >= 0); /* lower_privs() must be called before this */ -#ifdef HAVE_SETEUID - if (real_uid != file_uid && seteuid(file_uid) < 0) { - perror("Warning: raising privileges failed"); - } -#endif /* HAVE_SETEUID */ -} -#endif /* if 0 */ - -/* drop all additional privileges */ -void -drop_privs(void) -{ -#ifndef HAVE_DOSISH_SYSTEM - if (!uid_set) - init_uids(); - if (real_uid != file_uid) { - if (setuid(real_uid) < 0) { - perror("dropping privileges failed"); - exit(EXIT_FAILURE); - } - file_uid = real_uid; - } -#endif -} blob - 7986c996c6afd3141c99e14c7d6ef123e7563e3f (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry/util.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Quintuple Agent utilities - * Copyright (C) 1999 Robert Bihlmeyer - * Copyright (C) 2003 g10 Code GmbH - * - * 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 _UTIL_H -#define _UTIL_H - -#include - -#ifndef HAVE_BYTE_TYPEDEF -# undef byte -# ifdef __riscos__ - /* Norcroft treats char == unsigned char but char* != unsigned char* */ - typedef char byte; -# else - typedef unsigned char byte; -# endif -# define HAVE_BYTE_TYPEDEF -#endif - -#ifndef HAVE_ULONG_TYPEDEF -# undef ulong - typedef unsigned long ulong; -# define HAVE_ULONG_TYPEDEF -#endif - - -ssize_t xwrite(int, const void *, size_t); /* write until finished */ -int debugmsg(const char *, ...); /* output a debug message if debugging==on */ -void drop_privs(void); /* finally drop privileges */ - - -/* To avoid that a compiler optimizes certain memset calls away, these - macros may be used instead. */ -#define wipememory2(_ptr,_set,_len) do { \ - volatile char *_vptr=(volatile char *)(_ptr); \ - size_t _vlen=(_len); \ - while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ - } while(0) -#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) -#define wipe(_ptr,_len) wipememory2(_ptr,0,_len) - - - - -#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ - *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) -#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) - - -#endif blob - 8021258ab6391ad9a7bc6394ffbe8cef57401f23 (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry-dmenu.1 +++ /dev/null @@ -1,229 +0,0 @@ -.TH PINENTRY-DMENU 1 "DATE" pinentry-dmenu\-VERSION "pinentry-dmenu Manual" - - -.SH NAME -pinentry-dmenu - a pinentry program with the charm of dmenu -.SH DESCRIPTION -.B pinentry-dmenu -is a dmenu- and pinentry-based passphrase dialog called from the -.BR gpg-agent (1) -daemon. It is not intended to be invoked directly. - - -.SH SYNOPSIS -Set the -.B pinentry-program -in -.IR ~/.gnupg/gpg-agent.conf -to -.B pinentry-dmenu -to use the program as the regular dialog for -.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 "height =" " 8" -Height of pinentry-dmenu in pixels (no less than 8) -.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 -pinentry-dmenu is completely controlled by the keyboard. -.TP -.B Return -Confirm input -.TP -.B Ctrl-Return -Confirm input -.TP -.B Shift\-Return -Confirm input -.TP -.B Escape -Cancel input -.TP -.B C\-c -Escape - -.SS Confirm Mode -.TP -.B Down -Right -.TP -.B End -Right -.TP -.B Home -Left -.TP -.B Next -Right -.TP -.B Prior -Left -.TP -.B Up -Left -.TP -.B g -Cancel input -.TP -.B G -Cancel input -.TP -.B h -Left -.TP -.B j -Left -.TP -.B k -Right -.TP -.B l -Right -.TP -.B n -Confirm with no -.TP -.B N -Confirm with no -.TP -.B y -Confirm with yes -.TP -.B Y -Confirm with yes - -.SS Pin Mode -.TP -.B End -Move cursor to the line end -.TP -.B Home -Move cursor to the line begin -.TP -.B C\-a -Home -.TP -.B C\-b -Left -.TP -.B C\-d -Delete -.TP -.B C\-e -End -.TP -.B C\-f -Right -.TP -.B C\-g -Escape -.TP -.B C\-h -Backspace -.TP -.B C\-k -Delete line right -.TP -.B C\-u -Delete line left -.TP -.B C\-v -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 -.B pinentry-dmenu -is a fork of -.B dmenu - -and uses the api of -.B pinentry -, a GnuPG tool. -.B pinentry-dmenu -itself was written by Moritz Lüdecke . -This version of pinentry-dmenu is a part of Benjamin Stürz' custom desktop. - - -.SH REPORTING BUGS -Report pinentry-dmenu bugs to Benjamin Stürz . - - -.SH SEE ALSO -.BR dmenu (1), -.BR dwm (1), -.BR gpg-agent (1) blob - 0c57ceed3e49bb04802d54b7741a2252d85a1b3f (mode 644) blob + /dev/null --- pinentry-dmenu/pinentry-dmenu.c +++ /dev/null @@ -1,705 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef XINERAMA -#include -#endif -#include - -#include "drw.h" -#include "util.h" - -#include "pinentry/pinentry.h" -#include "pinentry/memory.h" - -#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 MINDESCLEN 8 - - -enum { SchemePrompt, SchemeNormal, SchemeSelect, SchemeDesc, SchemeLast }; -enum { WinPin, WinConfirm }; -enum { Ok, NotOk, Cancel }; -enum { Nothing, Yes, No }; - -static int bh, mw, mh; -static int sel; -static int promptw, pdescw; -/* Sum of left and right padding */ -static int lrpad; -static size_t cursor; -static int screen; - -static char* pin; -static int pin_len; -static char* pin_repeat; -static int pin_repeat_len; -static int repeat; - -static Atom clip, utf8; -static Display *dpy; -static Window root, parentwin, win; -static XIC xic; - -static Drw *drw; -static Clr *scheme[SchemeLast]; - -static int timed_out; -static int winmode; -pinentry_t pinentry_info; - -#include "config.h" - -static int -drawitem(const char* text, Bool sel, int x, int y, int w) { - unsigned int i = (sel) ? SchemeSelect : SchemeNormal; - - drw_setscheme(drw, scheme[i]); - - return drw_text(drw, x, y, w, bh, lrpad / 2, text, 0); -} - -static void -grabfocus(void) { - Window focuswin; - int i, revertwin; - - for (i = 0; i < 100; ++i) { - XGetInputFocus(dpy, &focuswin, &revertwin); - if (focuswin == win) { - return; - } - XSetInputFocus(dpy, win, RevertToParent, CurrentTime); - usleep(1000); - } - - die("cannot grab focus"); -} - -static void -grabkeyboard(void) { - int i; - - if (embedded) { - return; - } - - /* Try to grab keyboard, - * we may have to wait for another process to ungrab */ - for (i = 0; i < 1000; i++) { - if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, - GrabModeAsync, CurrentTime) == GrabSuccess) { - return; - } - usleep(1000); - } - - die("cannot grab keyboard"); -} - -static size_t -nextrune(int cursor, int inc) { - ssize_t n; - - /* Return location of next utf8 rune in the given direction (+1 or -1) */ - for (n = cursor + inc; - n + inc >= 0 && (pin[n] & 0xc0) == 0x80; - n += inc); - - return n; -} - -static void -setup_pin(char* pin_ptr, int len, int reset) { - pin = pin_ptr; - pin_len = len; - - if (reset) { - promptw = (prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - cursor = 0; - - if (pin) { - pin[0] = '\0'; - } - } -} - -static void -insert(const char *str, ssize_t n) { - size_t len = strlen(pin); - - // FIXME: Pinentry crashes when increasing the pin buffer the second time. - // Other pinentry programs has a limited passwort field length. - if (len + n > pin_len - 1) { - if (repeat) { - pin_repeat_len = 2 * pin_repeat_len; - pin_repeat = secmem_realloc(pin_repeat, pin_repeat_len); - setup_pin(pin_repeat, pin_repeat_len, 0); - if (!pin_repeat) { - pin_len = 0; - } - } else { - if (!pinentry_setbufferlen(pinentry_info, 2 * pinentry_info->pin_len)) { - pin_len = 0; - } else { - setup_pin(pinentry_info->pin, pinentry_info->pin_len, 0); - } - } - if (pin_len == 0) { - printf("Error: Couldn't allocate secure memory\n"); - return; - } - } - - /* 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)); - - if (n > 0) { - memcpy(&pin[cursor], str, n); - } - - cursor += n; - pin[len + n] = '\0'; -} - -static void -drawwin(void) { - unsigned int curpos; - int x = 0, fh = drw->fonts->h, pb, pbw = 0, i; - size_t asterlen = strlen(asterisk); - size_t pdesclen; - int leftinput; - char* censort; - - char* pprompt = (repeat) ? pinentry_info->repeat_passphrase : pinentry_info->prompt; - int ppromptw = (pprompt) ? TEXTW(pprompt) : 0; - - unsigned int censortl = minpwlen * TEXTW(asterisk) / strlen(asterisk); - unsigned int confirml = TEXTW(" YesNo ") + 3 * lrpad; - - drw_setscheme(drw, scheme[SchemeNormal]); - drw_rect(drw, 0, 0, mw, mh, 1, 1); - - if (prompt) { - drw_setscheme(drw, scheme[SchemePrompt]); - x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0); - } - - if (pprompt) { - drw_setscheme(drw, scheme[SchemePrompt]); - drw_text(drw, x, 0, ppromptw, bh, lrpad / 2, pprompt, 0); - x += ppromptw; - } - - if (pinentry_info->description) { - pb = mw - x; - pdesclen = strlen(pinentry_info->description); - - if (pb > 0) { - pb -= (winmode == WinPin) ? censortl : confirml; - pbw = MINDESCLEN * pdescw / pdesclen; - pbw = MIN(pbw, pdescw); - - if (pb >= pbw) { - pbw = MAX(pbw, pdescw); - pbw = MIN(pbw, pb); - pb = mw - pbw; - - for (i = 0; i < pdesclen; i++) { - if (pinentry_info->description[i] == '\n') { - pinentry_info->description[i] = ' '; - } - } - - drw_setscheme(drw, scheme[SchemeDesc]); - drw_text(drw, pb, 0, pbw, bh, lrpad / 2, pinentry_info->description, - 0); - } else { - pbw = 0; - } - } - } - - /* Draw input field */ - drw_setscheme(drw, scheme[SchemeNormal]); - - if (winmode == WinPin) { - censort = ecalloc(1, asterlen * pin_len); - - for (i = 0; i < asterlen * strlen(pin); i += asterlen) { - memcpy(&censort[i], asterisk, asterlen); - } - - censort[i+1] = '\n'; - leftinput = mw - x - pbw; - drw_text(drw, x, 0, leftinput, bh, lrpad / 2, censort, 0); - drw_font_getexts(drw->fonts, censort, cursor * asterlen, &curpos, NULL); - - if ((curpos += lrpad / 2 - 1) < leftinput) { - drw_setscheme(drw, scheme[SchemeNormal]); - drw_rect(drw, x + curpos, 2 + (bh - fh) / 2, 2, fh - 4, 1, 0); - } - - free(censort); - } else { - x += TEXTW(" "); - x = drawitem("No", (sel == No), x, 0, TEXTW("No")); - x = drawitem("Yes", (sel == Yes), x, 0, TEXTW("Yes")); - } - - drw_map(drw, win, 0, 0, mw, mh); -} - -static void -setup(void) { - int x, y, i = 0; - unsigned int du; - XSetWindowAttributes swa; - XIM xim; - Window w, dw, *dws; - XWindowAttributes wa; -#ifdef XINERAMA - XineramaScreenInfo *info; - Window pw; - int a, j, di, n, area = 0; -#endif - - /* Init appearance */ - scheme[SchemePrompt] = drw_scm_create(drw, colors[SchemePrompt], 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); - utf8 = XInternAtom(dpy, "UTF8_STRING", False); - - /* Calculate menu geometry */ - bh = drw->fonts->h + 2; - bh = MAX(bh, lineheight); - mh = bh; -#ifdef XINERAMA - info = XineramaQueryScreens(dpy, &n); - - if (parentwin == root && info) { - XGetInputFocus(dpy, &w, &di); - if (mon >= 0 && mon < n) { - i = mon; - } else if (w != root && w != PointerRoot && w != None) { - /* Find top-level window containing current input focus */ - do { - if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) { - XFree(dws); - } - } while (w != root && w != pw); - /* Find xinerama screen with which the window intersects most */ - if (XGetWindowAttributes(dpy, pw, &wa)) { - for (j = 0; j < n; j++) { - a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j]); - if (a > area) { - area = a; - i = j; - } - } - } - } - /* No focused window is on screen, so use pointer location instead */ - if (mon < 0 && !area - && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) { - for (i = 0; i < n; i++) { - if (INTERSECT(x, y, 1, 1, info[i])) { - break; - } - } - } - - x = info[i].x_org; - y = info[i].y_org + (bottom ? info[i].height - mh : 0); - mw = info[i].width; - XFree(info); - } else -#endif - { - if (!XGetWindowAttributes(dpy, parentwin, &wa)) { - die("could not get embedding window attributes: 0x%lx", parentwin); - } - x = 0; - y = bottom ? wa.height - mh : 0; - mw = wa.width; - } - - pdescw = (pinentry_info->description) ? TEXTW(pinentry_info->description) : 0; - - /* Create menu window */ - swa.override_redirect = True; - swa.background_pixel = scheme[SchemePrompt][ColBg].pixel; - swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; - win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); - - /* Open input methods */ - xim = XOpenIM(dpy, NULL, NULL, NULL); - xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, - XNClientWindow, win, XNFocusWindow, win, NULL); - XMapRaised(dpy, win); - - if (embedded) { - XSelectInput(dpy, parentwin, FocusChangeMask); - - if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { - for (i = 0; i < du && dws[i] != win; ++i) { - XSelectInput(dpy, dws[i], FocusChangeMask); - } - - XFree(dws); - } - grabfocus(); - } - - drw_resize(drw, mw, mh); -} - -static void -cleanup(void) { - XUngrabKey(dpy, AnyKey, AnyModifier, root); - free(scheme[SchemeDesc]); - free(scheme[SchemeSelect]); - free(scheme[SchemeNormal]); - free(scheme[SchemePrompt]); - drw_free(drw); - XSync(dpy, False); - XCloseDisplay(dpy); -} - -static int -keypress_confirm(XKeyEvent *ev, KeySym ksym) { - if (ev->state & ControlMask) { - switch(ksym) { - case XK_c: - pinentry_info->canceled = 1; - sel = No; - return 1; - default: - return 1; - } - } - - switch(ksym) { - case XK_KP_Enter: - case XK_Return: - if (sel != Nothing) { - return 1; - } - break; - case XK_y: - case XK_Y: - sel = Yes; - return 1; - case XK_n: - case XK_N: - sel = No; - return 1; - case XK_g: - case XK_G: - case XK_Escape: - pinentry_info->canceled = 1; - sel = No; - return 1; - case XK_h: - case XK_j: - case XK_Home: - case XK_Left: - case XK_Prior: - case XK_Up: - sel = No; - break; - case XK_k: - case XK_l: - case XK_Down: - case XK_End: - case XK_Next: - case XK_Right: - sel = Yes; - break; - } - - return 0; -} - -static int -keypress_pin(XKeyEvent *ev, KeySym ksym, char* buf, int len) { - int old; - - if (ev->state & ControlMask) { - switch(ksym) { - case XK_a: ksym = XK_Home; break; - case XK_b: ksym = XK_Left; break; - case XK_c: ksym = XK_Escape; break; - case XK_d: ksym = XK_Delete; break; - case XK_e: ksym = XK_End; break; - case XK_f: ksym = XK_Right; break; - case XK_g: ksym = XK_Escape; break; - case XK_h: ksym = XK_BackSpace; break; - case XK_k: - old = cursor; - cursor = strlen(pin); - insert(NULL, old - cursor); - break; - case XK_u: - insert(NULL, -cursor); - break; - case XK_v: - XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, - utf8, utf8, win, CurrentTime); - return 0; - case XK_Return: - case XK_KP_Enter: - break; - case XK_bracketleft: - pinentry_info->canceled = 1; - return 1; - default: - return 1; - } - } - - switch(ksym) { - case XK_Delete: - if (pin[cursor] == '\0') { - return 0; - } - cursor = nextrune(cursor, +1); - /* Fallthrough */ - case XK_BackSpace: - if (cursor == 0) { - return 0; - } - insert(NULL, nextrune(cursor, -1) - cursor); - break; - case XK_Escape: - pinentry_info->canceled = 1; - return 1; - case XK_Left: - if (cursor > 0) { - cursor = nextrune(cursor, -1); - } - break; - case XK_Right: - if (pin[cursor] != '\0') { - cursor = nextrune(cursor, +1); - } - break; - case XK_Home: - cursor = 0; - break; - case XK_End: - cursor = strlen(pin); - break; - case XK_Return: - case XK_KP_Enter: - return 1; - break; - default: - if (!iscntrl(*buf)) { - insert(buf, len); - } - } - - return 0; -} - -static int -keypress(XKeyEvent *ev) { - char buf[32]; - int len; - int ret = 1; - - KeySym ksym = NoSymbol; - Status status; - len = XmbLookupString(xic, ev, buf, sizeof(buf), &ksym, &status); - - if (status != XBufferOverflow) { - if (winmode == WinConfirm) { - ret = keypress_confirm(ev, ksym); - } else { - ret = keypress_pin(ev, ksym, buf, len); - } - - if (ret == 0) { - drawwin(); - } - } - - return ret; -} - -static void -paste(void) { - char *p, *q; - int di; - unsigned long dl; - Atom da; - - /* We have been given the current selection, now insert it into input */ - XGetWindowProperty(dpy, win, utf8, 0, pin_len / 4, False, utf8, &da, &di, - &dl, &dl, (unsigned char **)&p); - insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t) strlen(p)); - XFree(p); - drawwin(); -} - -void -run(void) { - XEvent ev; - - drawwin(); - - while (!XNextEvent(dpy, &ev)) { - if (XFilterEvent(&ev, win)) { - continue; - } - switch(ev.type) { - case Expose: - if (ev.xexpose.count == 0) { - drw_map(drw, win, 0, 0, mw, mh); - } - break; - case KeyPress: - if (keypress(&ev.xkey)) { - return; - } - break; - case SelectionNotify: - if (ev.xselection.property == utf8) { - paste(); - } - break; - case VisibilityNotify: - if (ev.xvisibility.state != VisibilityUnobscured) { - XRaiseWindow(dpy, win); - } - break; - } - } -} - -static void -catchsig(int sig) { - if (sig == SIGALRM) { - timed_out = 1; - } -} - -static void -password(void) { - winmode = WinPin; - repeat = 0; - setup_pin(pinentry_info->pin, pinentry_info->pin_len, 1); - run(); - - if (!pinentry_info->canceled && pinentry_info->repeat_passphrase) { - repeat = 1; - pin_repeat_len = pinentry_info->pin_len; - pin_repeat = secmem_malloc(pinentry_info->pin_len); - setup_pin(pin_repeat, pin_repeat_len, 1); - run(); - - pinentry_info->repeat_okay = (strcmp(pinentry_info->pin, pin_repeat) == 0)? 1 : 0; - secmem_free(pin_repeat); - - if (!pinentry_info->repeat_okay) { - pinentry_info->result = -1; - return; - } - } - - if (pinentry_info->canceled) { - pinentry_info->result = -1; - return; - } - - pinentry_info->result = strlen(pinentry_info->pin); -} - -static void -confirm(void) { - winmode = WinConfirm; - sel = Nothing; - run(); - pinentry_info->result = sel != No; -} - -static int -cmdhandler(pinentry_t received_pinentry) { - struct sigaction sa; - XWindowAttributes wa; - - pinentry_info = received_pinentry; - - if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) { - fputs("warning: no locale support\n", stderr); - } - if (!(dpy = XOpenDisplay(pinentry_info->display))) { - die("cannot open display"); - } - screen = DefaultScreen(dpy); - root = RootWindow(dpy, screen); - embedded = (pinentry_info->parent_wid) ? embedded : 0; - parentwin = (embedded) ? pinentry_info->parent_wid : root; - if (!XGetWindowAttributes(dpy, parentwin, &wa)) { - die("could not get embedding window attributes: 0x%lx", parentwin); - } - drw = drw_create(dpy, screen, root, wa.width, wa.height); - if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) { - die("no fonts could be loaded."); - } - lrpad = drw->fonts->h; - drw_setscheme(drw, scheme[SchemePrompt]); - - if (pinentry_info->timeout) { - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = catchsig; - sigaction(SIGALRM, &sa, NULL); - alarm(pinentry_info->timeout); - } - - grabkeyboard(); - setup(); - - if (pinentry_info->pin) { - do { - password(); - } while (!pinentry_info->canceled && pinentry_info->repeat_passphrase - && !pinentry_info->repeat_okay); - } else { - confirm(); - } - - cleanup(); - - return pinentry_info->result; -} - -pinentry_cmd_handler_t pinentry_cmd_handler = cmdhandler; - -int -main(int argc, char *argv[]) { - pinentry_init("pinentry-dmenu"); - pinentry_parse_opts(argc, argv); - return pinentry_loop(); -} blob - fe044fc7b7978d1f3c23768e315aae415d90b11a (mode 644) blob + /dev/null --- pinentry-dmenu/util.c +++ /dev/null @@ -1,35 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include -#include -#include -#include - -#include "util.h" - -void * -ecalloc(size_t nmemb, size_t size) -{ - void *p; - - if (!(p = calloc(nmemb, size))) - die("calloc:"); - return p; -} - -void -die(const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - if (fmt[0] && fmt[strlen(fmt)-1] == ':') { - fputc(' ', stderr); - perror(NULL); - } else { - fputc('\n', stderr); - } - - exit(1); -} blob - f633b5173ad2b5058d48574d5a18fe3f135c4193 (mode 644) blob + /dev/null --- pinentry-dmenu/util.h +++ /dev/null @@ -1,8 +0,0 @@ -/* See LICENSE file for copyright and license details. */ - -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define BETWEEN(X, A, B) ((A) <= (X) && (X) <= (B)) - -void die(const char *fmt, ...); -void *ecalloc(size_t nmemb, size_t size);