/* x11-ssh-askpass.c: A generic X11-based password dialog for OpenSSH.
* created 1999-Nov-17 03:40 Jim Knoble <jmknoble@pobox.com>
* autodate: 2001-Sep-16 18:08
*
* by Jim Knoble <jmknoble@pobox.com>
* Copyright (C) 1999,2000,2001 Jim Knoble
*
* Disclaimer:
*
* The software is provided "as is", without warranty of any kind,
* express or implied, including but not limited to the warranties of
* merchantability, fitness for a particular purpose and
* noninfringement. In no event shall the author(s) be liable for any
* claim, damages or other liability, whether in an action of
* contract, tort or otherwise, arising from, out of or in connection
* with the software or the use or other dealings in the software.
*
* Portions of this code are distantly derived from code in xscreensaver
* by Jamie Zawinski <jwz@jwz.org>. That code says:
*
* --------8<------------------------------------------------8<--------
* xscreensaver, Copyright (c) 1991-1999 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
* --------8<------------------------------------------------8<--------
*
* The remainder of this code falls under the same permissions and
* provisions as those of the xscreensaver code.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* For (get|set)rlimit() ... */
#include <sys/time.h>
#include <sys/resource.h>
/* ... end */
/* For (get|set)rlimit(), sleep(), and getpid() ... */
#include <unistd.h>
/* ... end */
/* For errno ... */
#include <errno.h>
/* ... end */
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/Xos.h>
#include "dynlist.h"
#include "drawing.h"
#include "resources.h"
#include "x11-ssh-askpass.h"
#undef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
char *progname = NULL;
char *progclass = NULL;
XrmDatabase db = 0;
static char *defaults[] = {
#include "SshAskpass_ad.h"
0
};
void outOfMemory(AppInfo *app, int line)
{
fprintf(stderr, "%s[%ld]: Aaahhh! I ran out of memory at line %d.\n",
app->appName, (long) app->pid, line);
exit(EXIT_STATUS_NO_MEMORY);
}
void freeIf(void *p)
{
if (p) {
free(p);
}
}
void freeFontIf(AppInfo *app, XFontStruct *f)
{
if (f) {
XFreeFont(app->dpy, f);
}
}
XFontStruct *getFontResource(AppInfo *app, char *instanceName, char *className)
{
char *fallbackFont = "fixed";
XFontStruct *f = NULL;
char *s = get_string_resource(instanceName, className);
f = XLoadQueryFont(app->dpy, (s ? s : fallbackFont));
if (!f) {
f = XLoadQueryFont(app->dpy, fallbackFont);
}
if (s) {
free(s);
}
return(f);
}
char *getStringResourceWithDefault(char *instanceName, char *className,
char *defaultText)
{
char *s = get_string_resource(instanceName, className);
if (!s) {
if (!defaultText) {
s = strdup("");
} else {
s = strdup(defaultText);
}
}
return(s);
}
unsigned int getUnsignedIntegerResource(AppInfo *app, char *instanceName,
char *className,
unsigned int defaultValue)
{
int n;
unsigned int value;
char c;
char *s = get_string_resource(instanceName, className);
char *cp = s;
if (NULL == s) {
return(defaultValue);
}
while ((*cp) && isspace(*cp)) {
/* Skip whitespace. */
cp++;
}
if (*cp) {
if (('0' == cp[0]) && cp[1]) {
if (('x' == cp[1]) || ('X' == cp[1])) {
/* Hex */
n = sscanf(cp + 2, "%x %c", &value, &c);
} else {
/* Octal */
n = sscanf(cp + 1, "%o %c", &value, &c);
}
if (1 == n) {
free(s);
return(value);
}
} else {
/* Unsigned Decimal */
n = sscanf(cp, "%u %c", &value, &c);
if (1 == n) {
free(s);
return(value);
}
}
}
/* If we get here, no conversion succeeded. */
fprintf(stderr, "%s[%ld]: invalid value '%s' for %s.\n",
app->appName, (long) app->pid, s, instanceName);
free(s);
return(defaultValue);
}
/* Default resolution is 75 dots/inch. 1 in = 2.54 cm. */
#define DefaultResolution ((75 * 10000) / 254)
long getResolutionResource(AppInfo *app, char *instanceName, char *className,
char *defaultResolutionSpec)
{
char units[3];
char *s;
int n;
long resolution;
unsigned int i;
memset(units, 0, sizeof(units));
s = getStringResourceWithDefault(instanceName, className,
defaultResolutionSpec);
/* NOTE: The width of the %s format must be one less than
* the length of the units[] array above!
*/
n = sscanf(s, "%ld / %2s", &resolution, units);
if (n != 2) {
fprintf(stderr, "%s[%ld]: invalid value '%s' for %s.\n",
app->appName, (long) app->pid, s, instanceName);
resolution = DefaultResolution;
} else {
if (resolution < 0) {
/* Resolution specifications should not be negative. */
resolution = -(resolution);
}
for (i = 0; i < (sizeof(units) - 1); i++) {
units[i] = tolower(units[i]);
}
if ((0 == strcmp(units, "in")) ||
(0 == strcmp(units, "i")) ||
(0 == strcmp(units, "\""))) {
/* dots/inch */
resolution = resolution * 10000 / 254;
} else if ((0 == strcmp(units, "m")) ||
(0 == strcmp(units, "me"))) {
/* dots/meter; no conversion necessary */
;
} else {
/* some unit we don't recognize; cringe and stare at the floor */
resolution = DefaultResolution;
}
}
return(resolution);
}
#undef DefaultResolution
void calcTextObjectExtents(TextObject *t, XFontStruct *font) {
if ((!t) || (!(t->text))) {
return;
}
t->textLength = strlen(t->text);
XTextExtents(font, t->text, t->textLength, &(t->direction),
&(t->ascent), &(t->descent), &(t->overall));
}
void calcLabelTextExtents(LabelInfo *label)
{
TextObject *t;
if ((!label) || (!(label->fullText)) || (!(label->font))) {
return;
}
t = label->multiText;
while (NULL != t) {
calcTextObjectExtents(t, label->font);
label->w.height += (t->ascent + t->descent);
if (label->w.width < t->overall.width) {
label->w.width = t->overall.width;
}
t = t->next;
}
}
void calcTotalButtonExtents(ButtonInfo *button)
{
if (!button) {
return;
}
button->w3.w.width = (button->w3.interiorWidth +
(2 * button->w3.shadowThickness));
button->w3.w.width += (2 * button->w3.borderWidth);
button->w3.w.height = (button->w3.interiorHeight +
(2 * button->w3.shadowThickness));
button->w3.w.height += (2 * button->w3.borderWidth);
}
void calcButtonExtents(ButtonInfo *button)
{
if (!button) {
return;
}
calcLabelTextExtents(&(button->label));
button->w3.interiorWidth = (button->label.w.width +
(2 * button->w3.horizontalSpacing));
button->w3.interiorHeight = (button->label.w.height +
(2 * button->w3.verticalSpacing));
calcTotalButtonExtents(button);
}
void balanceButtonExtents(ButtonInfo *button1, ButtonInfo *button2)
{
if ((!button1) || (!button2)) {
return;
}
button1->w3.interiorWidth = button2->w3.interiorWidth =
MAX(button1->w3.interiorWidth, button2->w3.interiorWidth);
button1->w3.interiorHeight = button2->w3.interiorHeight =
MAX(button1->w3.interiorHeight, button2->w3.interiorHeight);
calcTotalButtonExtents(button1);
calcTotalButtonExtents(button2);
}
void calcButtonLabelPosition(ButtonInfo *button)
{
if (!button) {
return;
}
button->label.w.x = button->w3.w.x +
((button->w3.w.width - button->label.w.width) / 2);
button->label.w.y = button->w3.w.y +
((button->w3.w.he