зеркало из https://github.com/github/putty.git
Whitespace rationalisation of entire code base.
The number of people has been steadily increasing who read our source code with an editor that thinks tab stops are 4 spaces apart, as opposed to the traditional tty-derived 8 that the PuTTY code expects. So I've been wondering for ages about just fixing it, and switching to a spaces-only policy throughout the code. And I recently found out about 'git blame -w', which should make this change not too disruptive for the purposes of source-control archaeology; so perhaps now is the time. While I'm at it, I've also taken the opportunity to remove all the trailing spaces from source lines (on the basis that git dislikes them, and is the only thing that seems to have a strong opinion one way or the other). Apologies to anyone downstream of this code who has complicated patch sets to rebase past this change. I don't intend it to be needed again.
This commit is contained in:
Родитель
b60230dbb8
Коммит
5d718ef64b
2
Recipe
2
Recipe
|
@ -1,5 +1,5 @@
|
|||
# -*- makefile -*-
|
||||
#
|
||||
#
|
||||
# This file describes which PuTTY programs are made up from which
|
||||
# object and resource files. It is processed into the various
|
||||
# Makefiles by means of a Perl script. Makefile changes should
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
* character sets known to this library.
|
||||
*/
|
||||
typedef enum {
|
||||
CS_NONE, /* used for reporting errors, etc */
|
||||
CS_NONE, /* used for reporting errors, etc */
|
||||
CS_ISO8859_1,
|
||||
CS_ISO8859_1_X11, /* X font encoding with VT100 glyphs */
|
||||
CS_ISO8859_1_X11, /* X font encoding with VT100 glyphs */
|
||||
CS_ISO8859_2,
|
||||
CS_ISO8859_3,
|
||||
CS_ISO8859_4,
|
||||
|
@ -77,7 +77,7 @@ typedef struct {
|
|||
|
||||
/*
|
||||
* Routine to convert a MB/SB character set to Unicode.
|
||||
*
|
||||
*
|
||||
* This routine accepts some number of bytes, updates a state
|
||||
* variable, and outputs some number of Unicode characters. There
|
||||
* are no guarantees. You can't even guarantee that at most one
|
||||
|
@ -86,12 +86,12 @@ typedef struct {
|
|||
* then you suddenly see FE. Now you need to output _two_ error
|
||||
* characters - one for the incomplete sequence E1 80, and one for
|
||||
* the completely invalid UTF-8 byte FE.
|
||||
*
|
||||
*
|
||||
* Returns the number of wide characters output; will never output
|
||||
* more than the size of the buffer (as specified on input).
|
||||
* Advances the `input' pointer and decrements `inlen', to indicate
|
||||
* how far along the input string it got.
|
||||
*
|
||||
*
|
||||
* The sequence of `errlen' wide characters pointed to by `errstr'
|
||||
* will be used to indicate a conversion error. If `errstr' is
|
||||
* NULL, `errlen' will be ignored, and the library will choose
|
||||
|
@ -101,21 +101,21 @@ typedef struct {
|
|||
|
||||
int charset_to_unicode(const char **input, int *inlen,
|
||||
wchar_t *output, int outlen,
|
||||
int charset, charset_state *state,
|
||||
const wchar_t *errstr, int errlen);
|
||||
int charset, charset_state *state,
|
||||
const wchar_t *errstr, int errlen);
|
||||
|
||||
/*
|
||||
* Routine to convert Unicode to an MB/SB character set.
|
||||
*
|
||||
*
|
||||
* This routine accepts some number of Unicode characters, updates
|
||||
* a state variable, and outputs some number of bytes.
|
||||
*
|
||||
*
|
||||
* Returns the number of bytes characters output; will never output
|
||||
* more than the size of the buffer (as specified on input), and
|
||||
* will never output a partial MB character. Advances the `input'
|
||||
* pointer and decrements `inlen', to indicate how far along the
|
||||
* input string it got.
|
||||
*
|
||||
*
|
||||
* The sequence of `errlen' characters pointed to by `errstr' will
|
||||
* be used to indicate a conversion error. If `errstr' is NULL,
|
||||
* `errlen' will be ignored, and the library will choose something
|
||||
|
@ -125,8 +125,8 @@ int charset_to_unicode(const char **input, int *inlen,
|
|||
|
||||
int charset_from_unicode(const wchar_t **input, int *inlen,
|
||||
char *output, int outlen,
|
||||
int charset, charset_state *state,
|
||||
const char *errstr, int errlen);
|
||||
int charset, charset_state *state,
|
||||
const char *errstr, int errlen);
|
||||
|
||||
/*
|
||||
* Convert X11 encoding names to and from our charset identifiers.
|
||||
|
@ -152,6 +152,6 @@ int charset_localenc_nth(int n);
|
|||
* Convert Mac OS script/region/font to our charset identifiers.
|
||||
*/
|
||||
int charset_from_macenc(int script, int region, int sysvers,
|
||||
const char *fontname);
|
||||
const char *fontname);
|
||||
|
||||
#endif /* charset_charset_h */
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* enum.c - enumerate all charsets defined by the library.
|
||||
*
|
||||
*
|
||||
* This file maintains a list of every other source file which
|
||||
* contains ENUM_CHARSET definitions. It #includes each one with
|
||||
* ENUM_CHARSETS defined, which causes those source files to do
|
||||
* nothing at all except call the ENUM_CHARSET macro on each
|
||||
* charset they define.
|
||||
*
|
||||
*
|
||||
* This file in turn is included from various other places, with
|
||||
* the ENUM_CHARSET macro defined to various different things. This
|
||||
* allows us to have multiple implementations of the master charset
|
||||
|
|
|
@ -21,29 +21,29 @@ static void charset_emit(void *ctx, long int output)
|
|||
int outlen;
|
||||
|
||||
if (output == ERROR) {
|
||||
p = param->errstr;
|
||||
outlen = param->errlen;
|
||||
p = param->errstr;
|
||||
outlen = param->errlen;
|
||||
} else {
|
||||
outval = output;
|
||||
p = &outval;
|
||||
outlen = 1;
|
||||
outval = output;
|
||||
p = &outval;
|
||||
outlen = 1;
|
||||
}
|
||||
|
||||
if (param->outlen >= outlen) {
|
||||
while (outlen > 0) {
|
||||
*param->output++ = *p++;
|
||||
param->outlen--;
|
||||
outlen--;
|
||||
}
|
||||
while (outlen > 0) {
|
||||
*param->output++ = *p++;
|
||||
param->outlen--;
|
||||
outlen--;
|
||||
}
|
||||
} else {
|
||||
param->stopped = 1;
|
||||
param->stopped = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int charset_from_unicode(const wchar_t **input, int *inlen,
|
||||
char *output, int outlen,
|
||||
int charset, charset_state *state,
|
||||
const char *errstr, int errlen)
|
||||
int charset, charset_state *state,
|
||||
const char *errstr, int errlen)
|
||||
{
|
||||
charset_spec const *spec = charset_find_spec(charset);
|
||||
charset_state localstate;
|
||||
|
@ -57,36 +57,36 @@ int charset_from_unicode(const wchar_t **input, int *inlen,
|
|||
* charset_emit will expect a valid errstr.
|
||||
*/
|
||||
if (!errstr) {
|
||||
/* *shrug* this is good enough, and consistent across all SBCS... */
|
||||
param.errstr = ".";
|
||||
param.errlen = 1;
|
||||
/* *shrug* this is good enough, and consistent across all SBCS... */
|
||||
param.errstr = ".";
|
||||
param.errlen = 1;
|
||||
}
|
||||
param.errstr = errstr;
|
||||
param.errlen = errlen;
|
||||
|
||||
if (!state) {
|
||||
localstate.s0 = 0;
|
||||
localstate.s0 = 0;
|
||||
} else {
|
||||
localstate = *state; /* structure copy */
|
||||
localstate = *state; /* structure copy */
|
||||
}
|
||||
state = &localstate;
|
||||
|
||||
while (*inlen > 0) {
|
||||
int lenbefore = param.output - output;
|
||||
spec->write(spec, **input, &localstate, charset_emit, ¶m);
|
||||
if (param.stopped) {
|
||||
/*
|
||||
* The emit function has _tried_ to output some
|
||||
* characters, but ran up against the end of the
|
||||
* buffer. Leave immediately, and return what happened
|
||||
* _before_ attempting to process this character.
|
||||
*/
|
||||
return lenbefore;
|
||||
}
|
||||
if (state)
|
||||
*state = localstate; /* structure copy */
|
||||
(*input)++;
|
||||
(*inlen)--;
|
||||
int lenbefore = param.output - output;
|
||||
spec->write(spec, **input, &localstate, charset_emit, ¶m);
|
||||
if (param.stopped) {
|
||||
/*
|
||||
* The emit function has _tried_ to output some
|
||||
* characters, but ran up against the end of the
|
||||
* buffer. Leave immediately, and return what happened
|
||||
* _before_ attempting to process this character.
|
||||
*/
|
||||
return lenbefore;
|
||||
}
|
||||
if (state)
|
||||
*state = localstate; /* structure copy */
|
||||
(*input)++;
|
||||
(*inlen)--;
|
||||
}
|
||||
return param.output - output;
|
||||
}
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
#define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
|
||||
|
||||
/* This is an invalid Unicode value used to indicate an error. */
|
||||
#define ERROR 0xFFFFL /* Unicode value representing error */
|
||||
#define ERROR 0xFFFFL /* Unicode value representing error */
|
||||
|
||||
typedef struct charset_spec charset_spec;
|
||||
typedef struct sbcs_data sbcs_data;
|
||||
|
||||
struct charset_spec {
|
||||
int charset; /* numeric identifier */
|
||||
int charset; /* numeric identifier */
|
||||
|
||||
/*
|
||||
* A function to read the character set and output Unicode
|
||||
|
@ -24,8 +24,8 @@ struct charset_spec {
|
|||
* on the input.
|
||||
*/
|
||||
void (*read)(charset_spec const *charset, long int input_chr,
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
/*
|
||||
* A function to read Unicode characters and output in this
|
||||
* character set. The `emit' function expects to get byte
|
||||
|
@ -33,8 +33,8 @@ struct charset_spec {
|
|||
* non-representable characters on the input.
|
||||
*/
|
||||
void (*write)(charset_spec const *charset, long int input_chr,
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
void const *data;
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,7 @@ struct sbcs_data {
|
|||
* position in this table, you branch according to whether
|
||||
* sbcs2ucs[ucs2sbcs[X]] is less than, greater than, or equal
|
||||
* to U.
|
||||
*
|
||||
*
|
||||
* Note that since there may be fewer than 256 valid byte
|
||||
* values in a particular SBCS, we must supply the length of
|
||||
* this table as well as the contents.
|
||||
|
@ -74,11 +74,11 @@ struct sbcs_data {
|
|||
*/
|
||||
charset_spec const *charset_find_spec(int charset);
|
||||
void read_sbcs(charset_spec const *charset, long int input_chr,
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
void write_sbcs(charset_spec const *charset, long int input_chr,
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx);
|
||||
|
||||
/*
|
||||
* Placate compiler warning about unused parameters, of which we
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* announcing what character set it will be using), and a set of
|
||||
* enumeration functions which return a list of supported
|
||||
* encodings one by one.
|
||||
*
|
||||
*
|
||||
* charset_from_localenc will attempt all other text translations
|
||||
* as well as this table, to maximise the number of different ways
|
||||
* you can select a supported charset.
|
||||
|
@ -83,10 +83,10 @@ const char *charset_to_localenc(int charset)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(localencs); i++)
|
||||
if (charset == localencs[i].charset)
|
||||
return localencs[i].name;
|
||||
if (charset == localencs[i].charset)
|
||||
return localencs[i].name;
|
||||
|
||||
return NULL; /* not found */
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
int charset_from_localenc(const char *name)
|
||||
|
@ -94,24 +94,24 @@ int charset_from_localenc(const char *name)
|
|||
int i;
|
||||
|
||||
if ( (i = charset_from_mimeenc(name)) != CS_NONE)
|
||||
return i;
|
||||
return i;
|
||||
if ( (i = charset_from_xenc(name)) != CS_NONE)
|
||||
return i;
|
||||
return i;
|
||||
|
||||
for (i = 0; i < (int)lenof(localencs); i++) {
|
||||
const char *p, *q;
|
||||
p = name;
|
||||
q = localencs[i].name;
|
||||
while (*p || *q) {
|
||||
if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
|
||||
break;
|
||||
p++; q++;
|
||||
}
|
||||
if (!*p && !*q)
|
||||
return localencs[i].charset;
|
||||
const char *p, *q;
|
||||
p = name;
|
||||
q = localencs[i].name;
|
||||
while (*p || *q) {
|
||||
if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
|
||||
break;
|
||||
p++; q++;
|
||||
}
|
||||
if (!*p && !*q)
|
||||
return localencs[i].charset;
|
||||
}
|
||||
|
||||
return CS_NONE; /* not found */
|
||||
return CS_NONE; /* not found */
|
||||
}
|
||||
|
||||
int charset_localenc_nth(int n)
|
||||
|
@ -119,8 +119,8 @@ int charset_localenc_nth(int n)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(localencs); i++)
|
||||
if (localencs[i].return_in_enum && !n--)
|
||||
return localencs[i].charset;
|
||||
if (localencs[i].return_in_enum && !n--)
|
||||
return localencs[i].charset;
|
||||
|
||||
return CS_NONE; /* end of list */
|
||||
return CS_NONE; /* end of list */
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* 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
|
||||
|
@ -38,39 +38,39 @@
|
|||
* independent of that.
|
||||
*/
|
||||
|
||||
#define smRoman 0
|
||||
#define smJapanese 1
|
||||
#define smTradChinese 2
|
||||
#define smKorean 3
|
||||
#define smArabic 4
|
||||
#define smHebrew 5
|
||||
#define smCyrillic 7
|
||||
#define smDevenagari 9
|
||||
#define smGurmukhi 10
|
||||
#define smGujurati 11
|
||||
#define smThai 21
|
||||
#define smSimpChinese 25
|
||||
#define smTibetan 26
|
||||
#define smEthiopic 28
|
||||
#define smCentralEuroRoman 29
|
||||
#define smRoman 0
|
||||
#define smJapanese 1
|
||||
#define smTradChinese 2
|
||||
#define smKorean 3
|
||||
#define smArabic 4
|
||||
#define smHebrew 5
|
||||
#define smCyrillic 7
|
||||
#define smDevenagari 9
|
||||
#define smGurmukhi 10
|
||||
#define smGujurati 11
|
||||
#define smThai 21
|
||||
#define smSimpChinese 25
|
||||
#define smTibetan 26
|
||||
#define smEthiopic 28
|
||||
#define smCentralEuroRoman 29
|
||||
|
||||
#define verGreece 20
|
||||
#define verIceland 21
|
||||
#define verTurkey 24
|
||||
#define verYugoCroatian 25
|
||||
#define verRomania 39
|
||||
#define verFaroeIsl 47
|
||||
#define verIran 48
|
||||
#define verRussia 49
|
||||
#define verSlovenian 66
|
||||
#define verCroatia 68
|
||||
#define verBulgaria 72
|
||||
#define verScottishGaelic 75
|
||||
#define verManxGaelic 76
|
||||
#define verBreton 77
|
||||
#define verNunavut 78
|
||||
#define verWelsh 79
|
||||
#define verIrishGaelicScript 81
|
||||
#define verGreece 20
|
||||
#define verIceland 21
|
||||
#define verTurkey 24
|
||||
#define verYugoCroatian 25
|
||||
#define verRomania 39
|
||||
#define verFaroeIsl 47
|
||||
#define verIran 48
|
||||
#define verRussia 49
|
||||
#define verSlovenian 66
|
||||
#define verCroatia 68
|
||||
#define verBulgaria 72
|
||||
#define verScottishGaelic 75
|
||||
#define verManxGaelic 76
|
||||
#define verBreton 77
|
||||
#define verNunavut 78
|
||||
#define verWelsh 79
|
||||
#define verIrishGaelicScript 81
|
||||
|
||||
static const struct {
|
||||
int script;
|
||||
|
@ -152,17 +152,17 @@ static const struct {
|
|||
};
|
||||
|
||||
int charset_from_macenc(int script, int region, int sysvers,
|
||||
char const *fontname)
|
||||
char const *fontname)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(macencs); i++)
|
||||
if ((macencs[i].script == script) &&
|
||||
(macencs[i].region < 0 || macencs[i].region == region) &&
|
||||
(macencs[i].sysvermin <= sysvers) &&
|
||||
(macencs[i].fontname == NULL ||
|
||||
(fontname != NULL && strcmp(macencs[i].fontname, fontname) == 0)))
|
||||
return macencs[i].charset;
|
||||
if ((macencs[i].script == script) &&
|
||||
(macencs[i].region < 0 || macencs[i].region == region) &&
|
||||
(macencs[i].sysvermin <= sysvers) &&
|
||||
(macencs[i].fontname == NULL ||
|
||||
(fontname != NULL && strcmp(macencs[i].fontname, fontname) == 0)))
|
||||
return macencs[i].charset;
|
||||
|
||||
return CS_NONE;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* mimeenc.c - translate our internal character set codes to and
|
||||
* from MIME standard character-set names.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -14,9 +14,9 @@ static const struct {
|
|||
} mimeencs[] = {
|
||||
/*
|
||||
* These names are taken from
|
||||
*
|
||||
*
|
||||
* http://www.iana.org/assignments/character-sets
|
||||
*
|
||||
*
|
||||
* Where multiple encoding names map to the same encoding id
|
||||
* (such as the variety of aliases for ISO-8859-1), the first
|
||||
* is considered canonical and will be returned when
|
||||
|
@ -192,10 +192,10 @@ const char *charset_to_mimeenc(int charset)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(mimeencs); i++)
|
||||
if (charset == mimeencs[i].charset)
|
||||
return mimeencs[i].name;
|
||||
if (charset == mimeencs[i].charset)
|
||||
return mimeencs[i].name;
|
||||
|
||||
return NULL; /* not found */
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
int charset_from_mimeenc(const char *name)
|
||||
|
@ -203,17 +203,17 @@ int charset_from_mimeenc(const char *name)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(mimeencs); i++) {
|
||||
const char *p, *q;
|
||||
p = name;
|
||||
q = mimeencs[i].name;
|
||||
while (*p || *q) {
|
||||
if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
|
||||
break;
|
||||
p++; q++;
|
||||
}
|
||||
if (!*p && !*q)
|
||||
return mimeencs[i].charset;
|
||||
const char *p, *q;
|
||||
p = name;
|
||||
q = mimeencs[i].name;
|
||||
while (*p || *q) {
|
||||
if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
|
||||
break;
|
||||
p++; q++;
|
||||
}
|
||||
if (!*p && !*q)
|
||||
return mimeencs[i].charset;
|
||||
}
|
||||
|
||||
return CS_NONE; /* not found */
|
||||
return CS_NONE; /* not found */
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
*/
|
||||
|
||||
void read_sbcs(charset_spec const *charset, long int input_chr,
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx)
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx)
|
||||
{
|
||||
const struct sbcs_data *sd = charset->data;
|
||||
|
||||
|
@ -24,8 +24,8 @@ void read_sbcs(charset_spec const *charset, long int input_chr,
|
|||
}
|
||||
|
||||
void write_sbcs(charset_spec const *charset, long int input_chr,
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx)
|
||||
charset_state *state,
|
||||
void (*emit)(void *ctx, long int output), void *emitctx)
|
||||
{
|
||||
const struct sbcs_data *sd = charset->data;
|
||||
int i, j, k, c;
|
||||
|
@ -38,16 +38,16 @@ void write_sbcs(charset_spec const *charset, long int input_chr,
|
|||
i = -1;
|
||||
j = sd->nvalid;
|
||||
while (i+1 < j) {
|
||||
k = (i+j)/2;
|
||||
c = sd->ucs2sbcs[k];
|
||||
if (input_chr < sd->sbcs2ucs[c])
|
||||
j = k;
|
||||
else if (input_chr > sd->sbcs2ucs[c])
|
||||
i = k;
|
||||
else {
|
||||
emit(emitctx, c);
|
||||
return;
|
||||
}
|
||||
k = (i+j)/2;
|
||||
c = sd->ucs2sbcs[k];
|
||||
if (input_chr < sd->sbcs2ucs[c])
|
||||
j = k;
|
||||
else if (input_chr > sd->sbcs2ucs[c])
|
||||
i = k;
|
||||
else {
|
||||
emit(emitctx, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit(emitctx, ERROR);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Data file defining single-byte character sets.
|
||||
|
||||
|
||||
All lines which begin with whitespace are considered comments.
|
||||
|
||||
To generate an SBCS table from a unicode.org mapping table:
|
||||
|
@ -588,7 +588,7 @@ XXXX 2018 2019 201c 201d 2022 2013 2014 02dc 2122 XXXX 203a 0153 XXXX XXXX 0178
|
|||
0111 00f1 0323 00f3 00f4 01a1 00f6 00f7 00f8 00f9 00fa 00fb 00fc 01b0 20ab 00ff
|
||||
|
||||
KOI8-R, generated by this code:
|
||||
|
||||
|
||||
{ echo charset CS_KOI8_R;
|
||||
gensbcs http://www.unicode.org/Public/MAPPINGS/VENDORS/MISC/KOI8-R.TXT; }
|
||||
|
||||
|
|
|
@ -32,24 +32,24 @@ my @sortpriority = ();
|
|||
while (<FOO>) {
|
||||
chomp;
|
||||
if (/^charset (.*)$/) {
|
||||
$charsetname = $1;
|
||||
@vals = ();
|
||||
@sortpriority = map { 0 } 0..255;
|
||||
$charsetname = $1;
|
||||
@vals = ();
|
||||
@sortpriority = map { 0 } 0..255;
|
||||
} elsif (/^sortpriority ([^-]*)-([^-]*) (.*)$/) {
|
||||
for ($i = hex $1; $i <= hex $2; $i++) {
|
||||
$sortpriority[$i] += $3;
|
||||
}
|
||||
for ($i = hex $1; $i <= hex $2; $i++) {
|
||||
$sortpriority[$i] += $3;
|
||||
}
|
||||
} elsif (/^[0-9a-fA-FX]/) {
|
||||
push @vals, map { $_ eq "XXXX" ? -1 : hex $_ } split / +/, $_;
|
||||
if (scalar @vals > 256) {
|
||||
die "$infile:$.: charset $charsetname has more than 256 values\n";
|
||||
} elsif (scalar @vals == 256) {
|
||||
&outcharset($charsetname, \@vals, \@sortpriority);
|
||||
push @charsetnames, $charsetname;
|
||||
$charsetname = undef;
|
||||
@vals = ();
|
||||
@sortpriority = map { 0 } 0..255;
|
||||
}
|
||||
push @vals, map { $_ eq "XXXX" ? -1 : hex $_ } split / +/, $_;
|
||||
if (scalar @vals > 256) {
|
||||
die "$infile:$.: charset $charsetname has more than 256 values\n";
|
||||
} elsif (scalar @vals == 256) {
|
||||
&outcharset($charsetname, \@vals, \@sortpriority);
|
||||
push @charsetnames, $charsetname;
|
||||
$charsetname = undef;
|
||||
@vals = ();
|
||||
@sortpriority = map { 0 } 0..255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,36 +72,36 @@ sub outcharset($$$) {
|
|||
$prefix = " ";
|
||||
@sorted = ();
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
if ($vals->[$i] < 0) {
|
||||
printf "%sERROR ", $prefix;
|
||||
} else {
|
||||
printf "%s0x%04x", $prefix, $vals->[$i];
|
||||
die "ooh? $i\n" unless defined $sortpriority->[$i];
|
||||
push @sorted, [$i, $vals->[$i], 0+$sortpriority->[$i]];
|
||||
}
|
||||
if ($i % 8 == 7) {
|
||||
$prefix = ",\n ";
|
||||
} else {
|
||||
$prefix = ", ";
|
||||
}
|
||||
if ($vals->[$i] < 0) {
|
||||
printf "%sERROR ", $prefix;
|
||||
} else {
|
||||
printf "%s0x%04x", $prefix, $vals->[$i];
|
||||
die "ooh? $i\n" unless defined $sortpriority->[$i];
|
||||
push @sorted, [$i, $vals->[$i], 0+$sortpriority->[$i]];
|
||||
}
|
||||
if ($i % 8 == 7) {
|
||||
$prefix = ",\n ";
|
||||
} else {
|
||||
$prefix = ", ";
|
||||
}
|
||||
}
|
||||
print "\n },\n {\n";
|
||||
@sorted = sort { ($a->[1] == $b->[1] ?
|
||||
$b->[2] <=> $a->[2] :
|
||||
$a->[1] <=> $b->[1]) ||
|
||||
$b->[2] <=> $a->[2] :
|
||||
$a->[1] <=> $b->[1]) ||
|
||||
$a->[0] <=> $b->[0] } @sorted;
|
||||
$prefix = " ";
|
||||
$uval = -1;
|
||||
for ($i = $j = 0; $i < scalar @sorted; $i++) {
|
||||
next if ($uval == $sorted[$i]->[1]); # low-priority alternative
|
||||
$uval = $sorted[$i]->[1];
|
||||
printf "%s0x%02x", $prefix, $sorted[$i]->[0];
|
||||
if ($j % 8 == 7) {
|
||||
$prefix = ",\n ";
|
||||
} else {
|
||||
$prefix = ", ";
|
||||
}
|
||||
$j++;
|
||||
next if ($uval == $sorted[$i]->[1]); # low-priority alternative
|
||||
$uval = $sorted[$i]->[1];
|
||||
printf "%s0x%02x", $prefix, $sorted[$i]->[0];
|
||||
if ($j % 8 == 7) {
|
||||
$prefix = ",\n ";
|
||||
} else {
|
||||
$prefix = ", ";
|
||||
}
|
||||
$j++;
|
||||
}
|
||||
printf "\n },\n %d\n", $j;
|
||||
print "};\n";
|
||||
|
|
|
@ -22,8 +22,8 @@ charset_spec const *charset_find_spec(int charset)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(cs_table); i++)
|
||||
if (cs_table[i]->charset == charset)
|
||||
return cs_table[i];
|
||||
if (cs_table[i]->charset == charset)
|
||||
return cs_table[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -21,35 +21,35 @@ static void unicode_emit(void *ctx, long int output)
|
|||
int outlen;
|
||||
|
||||
if (output == ERROR) {
|
||||
if (param->errstr) {
|
||||
p = param->errstr;
|
||||
outlen = param->errlen;
|
||||
} else {
|
||||
outval = 0xFFFD; /* U+FFFD REPLACEMENT CHARACTER */
|
||||
p = &outval;
|
||||
outlen = 1;
|
||||
}
|
||||
if (param->errstr) {
|
||||
p = param->errstr;
|
||||
outlen = param->errlen;
|
||||
} else {
|
||||
outval = 0xFFFD; /* U+FFFD REPLACEMENT CHARACTER */
|
||||
p = &outval;
|
||||
outlen = 1;
|
||||
}
|
||||
} else {
|
||||
outval = output;
|
||||
p = &outval;
|
||||
outlen = 1;
|
||||
outval = output;
|
||||
p = &outval;
|
||||
outlen = 1;
|
||||
}
|
||||
|
||||
if (param->outlen >= outlen) {
|
||||
while (outlen > 0) {
|
||||
*param->output++ = *p++;
|
||||
param->outlen--;
|
||||
outlen--;
|
||||
}
|
||||
while (outlen > 0) {
|
||||
*param->output++ = *p++;
|
||||
param->outlen--;
|
||||
outlen--;
|
||||
}
|
||||
} else {
|
||||
param->stopped = 1;
|
||||
param->stopped = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int charset_to_unicode(const char **input, int *inlen,
|
||||
wchar_t *output, int outlen,
|
||||
int charset, charset_state *state,
|
||||
const wchar_t *errstr, int errlen)
|
||||
int charset, charset_state *state,
|
||||
const wchar_t *errstr, int errlen)
|
||||
{
|
||||
charset_spec const *spec = charset_find_spec(charset);
|
||||
charset_state localstate;
|
||||
|
@ -62,28 +62,28 @@ int charset_to_unicode(const char **input, int *inlen,
|
|||
param.stopped = 0;
|
||||
|
||||
if (!state) {
|
||||
localstate.s0 = 0;
|
||||
localstate.s0 = 0;
|
||||
} else {
|
||||
localstate = *state; /* structure copy */
|
||||
localstate = *state; /* structure copy */
|
||||
}
|
||||
|
||||
while (*inlen > 0) {
|
||||
int lenbefore = param.output - output;
|
||||
spec->read(spec, (unsigned char)**input, &localstate,
|
||||
unicode_emit, ¶m);
|
||||
if (param.stopped) {
|
||||
/*
|
||||
* The emit function has _tried_ to output some
|
||||
* characters, but ran up against the end of the
|
||||
* buffer. Leave immediately, and return what happened
|
||||
* _before_ attempting to process this character.
|
||||
*/
|
||||
return lenbefore;
|
||||
}
|
||||
if (state)
|
||||
*state = localstate; /* structure copy */
|
||||
(*input)++;
|
||||
(*inlen)--;
|
||||
int lenbefore = param.output - output;
|
||||
spec->read(spec, (unsigned char)**input, &localstate,
|
||||
unicode_emit, ¶m);
|
||||
if (param.stopped) {
|
||||
/*
|
||||
* The emit function has _tried_ to output some
|
||||
* characters, but ran up against the end of the
|
||||
* buffer. Leave immediately, and return what happened
|
||||
* _before_ attempting to process this character.
|
||||
*/
|
||||
return lenbefore;
|
||||
}
|
||||
if (state)
|
||||
*state = localstate; /* structure copy */
|
||||
(*input)++;
|
||||
(*inlen)--;
|
||||
}
|
||||
|
||||
return param.output - output;
|
||||
|
|
1180
charset/utf8.c
1180
charset/utf8.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* xenc.c - translate our internal character set codes to and from
|
||||
* X11 character encoding names.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -15,9 +15,9 @@ static const struct {
|
|||
/*
|
||||
* Officially registered encoding names. This list is derived
|
||||
* from the font encodings section of
|
||||
*
|
||||
*
|
||||
* http://ftp.x.org/pub/DOCS/registry
|
||||
*
|
||||
*
|
||||
* Where multiple encoding names map to the same encoding id
|
||||
* (such as iso8859-15 and fcd8859-15), the first is considered
|
||||
* canonical and will be returned when translating the id to a
|
||||
|
@ -67,10 +67,10 @@ const char *charset_to_xenc(int charset)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(xencs); i++)
|
||||
if (charset == xencs[i].charset)
|
||||
return xencs[i].name;
|
||||
if (charset == xencs[i].charset)
|
||||
return xencs[i].name;
|
||||
|
||||
return NULL; /* not found */
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
int charset_from_xenc(const char *name)
|
||||
|
@ -78,17 +78,17 @@ int charset_from_xenc(const char *name)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < (int)lenof(xencs); i++) {
|
||||
const char *p, *q;
|
||||
p = name;
|
||||
q = xencs[i].name;
|
||||
while (*p || *q) {
|
||||
if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
|
||||
break;
|
||||
p++; q++;
|
||||
}
|
||||
if (!*p && !*q)
|
||||
return xencs[i].charset;
|
||||
const char *p, *q;
|
||||
p = name;
|
||||
q = xencs[i].name;
|
||||
while (*p || *q) {
|
||||
if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
|
||||
break;
|
||||
p++; q++;
|
||||
}
|
||||
if (!*p && !*q)
|
||||
return xencs[i].charset;
|
||||
}
|
||||
|
||||
return CS_NONE; /* not found */
|
||||
return CS_NONE; /* not found */
|
||||
}
|
||||
|
|
1860
cmdgen.c
1860
cmdgen.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
680
cmdline.c
680
cmdline.c
|
@ -14,14 +14,14 @@
|
|||
* eventual running configuration. For this we use the macro
|
||||
* SAVEABLE, which notices if the `need_save' parameter is set and
|
||||
* saves the parameter and value on a list.
|
||||
*
|
||||
*
|
||||
* We also assign priorities to saved parameters, just to slightly
|
||||
* ameliorate silly ordering problems. For example, if you specify
|
||||
* a saved session to load, it will be loaded _before_ all your
|
||||
* local modifications such as -L are evaluated; and if you specify
|
||||
* a protocol and a port, the protocol is set up first so that the
|
||||
* port can override its choice of port number.
|
||||
*
|
||||
*
|
||||
* (In fact -load is not saved at all, since in at least Plink the
|
||||
* processing of further command-line options depends on whether or
|
||||
* not the loaded session contained a hostname. So it must be
|
||||
|
@ -59,16 +59,16 @@ void cmdline_cleanup(void)
|
|||
int pri;
|
||||
|
||||
if (cmdline_password) {
|
||||
smemclr(cmdline_password, strlen(cmdline_password));
|
||||
sfree(cmdline_password);
|
||||
cmdline_password = NULL;
|
||||
smemclr(cmdline_password, strlen(cmdline_password));
|
||||
sfree(cmdline_password);
|
||||
cmdline_password = NULL;
|
||||
}
|
||||
|
||||
|
||||
for (pri = 0; pri < NPRIORITIES; pri++) {
|
||||
sfree(saves[pri].params);
|
||||
saves[pri].params = NULL;
|
||||
saves[pri].savesize = 0;
|
||||
saves[pri].nsaved = 0;
|
||||
sfree(saves[pri].params);
|
||||
saves[pri].params = NULL;
|
||||
saves[pri].savesize = 0;
|
||||
saves[pri].nsaved = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ int cmdline_get_passwd_input(prompts_t *p)
|
|||
* that comes in a prompt-set on its own.
|
||||
*/
|
||||
if (!cmdline_password || p->n_prompts != 1 || p->prompts[0]->echo) {
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -99,7 +99,7 @@ int cmdline_get_passwd_input(prompts_t *p)
|
|||
* to try).
|
||||
*/
|
||||
if (tried_once)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
prompt_set_result(p->prompts[0], cmdline_password);
|
||||
smemclr(cmdline_password, strlen(cmdline_password));
|
||||
|
@ -124,8 +124,8 @@ int cmdline_tooltype = 0;
|
|||
static bool cmdline_check_unavailable(int flag, const char *p)
|
||||
{
|
||||
if (cmdline_tooltype & flag) {
|
||||
cmdline_error("option \"%s\" not available in this tool", p);
|
||||
return true;
|
||||
cmdline_error("option \"%s\" not available in this tool", p);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -325,11 +325,11 @@ int cmdline_process_param(const char *p, char *value,
|
|||
!loaded_session) {
|
||||
/*
|
||||
* For some tools, we equivocate between a
|
||||
* hostname argument and an argument naming a
|
||||
* saved session. Here we attempt to load a
|
||||
* session with the specified name, and if that
|
||||
* session exists and is launchable, we overwrite
|
||||
* the entire Conf with it.
|
||||
* hostname argument and an argument naming a
|
||||
* saved session. Here we attempt to load a
|
||||
* session with the specified name, and if that
|
||||
* session exists and is launchable, we overwrite
|
||||
* the entire Conf with it.
|
||||
*
|
||||
* We skip this check if a -load option has
|
||||
* already happened, so that
|
||||
|
@ -345,7 +345,7 @@ int cmdline_process_param(const char *p, char *value,
|
|||
* So if that was the behaviour someone wanted,
|
||||
* then they could get it by leaving off the
|
||||
* -load completely.)
|
||||
*/
|
||||
*/
|
||||
Conf *conf2 = conf_new();
|
||||
if (do_defaults(hostname_after_user, conf2) &&
|
||||
conf_launchable(conf2)) {
|
||||
|
@ -394,83 +394,83 @@ int cmdline_process_param(const char *p, char *value,
|
|||
}
|
||||
|
||||
if (!strcmp(p, "-load")) {
|
||||
RETURN(2);
|
||||
/* This parameter must be processed immediately rather than being
|
||||
* saved. */
|
||||
do_defaults(value, conf);
|
||||
loaded_session = true;
|
||||
cmdline_session_name = dupstr(value);
|
||||
return 2;
|
||||
RETURN(2);
|
||||
/* This parameter must be processed immediately rather than being
|
||||
* saved. */
|
||||
do_defaults(value, conf);
|
||||
loaded_session = true;
|
||||
cmdline_session_name = dupstr(value);
|
||||
return 2;
|
||||
}
|
||||
if (!strcmp(p, "-ssh")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_SSH;
|
||||
default_port = 22;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
return 1;
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_SSH;
|
||||
default_port = 22;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(p, "-telnet")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_TELNET;
|
||||
default_port = 23;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
return 1;
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_TELNET;
|
||||
default_port = 23;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(p, "-rlogin")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_RLOGIN;
|
||||
default_port = 513;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
return 1;
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_RLOGIN;
|
||||
default_port = 513;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
conf_set_int(conf, CONF_port, default_port);
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(p, "-raw")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_RAW;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_RAW;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
}
|
||||
if (!strcmp(p, "-serial")) {
|
||||
RETURN(1);
|
||||
/* Serial is not NONNETWORK in an odd sense of the word */
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_SERIAL;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
/* The host parameter will already be loaded into CONF_host,
|
||||
* so copy it across */
|
||||
conf_set_str(conf, CONF_serline, conf_get_str(conf, CONF_host));
|
||||
RETURN(1);
|
||||
/* Serial is not NONNETWORK in an odd sense of the word */
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = PROT_SERIAL;
|
||||
conf_set_int(conf, CONF_protocol, default_protocol);
|
||||
/* The host parameter will already be loaded into CONF_host,
|
||||
* so copy it across */
|
||||
conf_set_str(conf, CONF_serline, conf_get_str(conf, CONF_host));
|
||||
}
|
||||
if (!strcmp(p, "-v")) {
|
||||
RETURN(1);
|
||||
flags |= FLAG_VERBOSE;
|
||||
RETURN(1);
|
||||
flags |= FLAG_VERBOSE;
|
||||
}
|
||||
if (!strcmp(p, "-l")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_str(conf, CONF_username, value);
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_str(conf, CONF_username, value);
|
||||
}
|
||||
if (!strcmp(p, "-loghost")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_str(conf, CONF_loghost, value);
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_str(conf, CONF_loghost, value);
|
||||
}
|
||||
if (!strcmp(p, "-hostkey")) {
|
||||
char *dup;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
dup = dupstr(value);
|
||||
if (!validate_manual_hostkey(dup)) {
|
||||
cmdline_error("'%s' is not a valid format for a manual host "
|
||||
|
@ -478,51 +478,51 @@ int cmdline_process_param(const char *p, char *value,
|
|||
sfree(dup);
|
||||
return ret;
|
||||
}
|
||||
conf_set_str_str(conf, CONF_ssh_manual_hostkeys, dup, "");
|
||||
conf_set_str_str(conf, CONF_ssh_manual_hostkeys, dup, "");
|
||||
sfree(dup);
|
||||
}
|
||||
if ((!strcmp(p, "-L") || !strcmp(p, "-R") || !strcmp(p, "-D"))) {
|
||||
char type, *q, *qq, *key, *val;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
if (strcmp(p, "-D")) {
|
||||
/*
|
||||
char type, *q, *qq, *key, *val;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
if (strcmp(p, "-D")) {
|
||||
/*
|
||||
* For -L or -R forwarding types:
|
||||
*
|
||||
* We expect _at least_ two colons in this string. The
|
||||
* possible formats are `sourceport:desthost:destport',
|
||||
* or `sourceip:sourceport:desthost:destport' if you're
|
||||
* specifying a particular loopback address. We need to
|
||||
* replace the one between source and dest with a \t;
|
||||
* this means we must find the second-to-last colon in
|
||||
* the string.
|
||||
*
|
||||
* (This looks like a foolish way of doing it given the
|
||||
* existence of strrchr, but it's more efficient than
|
||||
* two strrchrs - not to mention that the second strrchr
|
||||
* would require us to modify the input string!)
|
||||
*/
|
||||
* We expect _at least_ two colons in this string. The
|
||||
* possible formats are `sourceport:desthost:destport',
|
||||
* or `sourceip:sourceport:desthost:destport' if you're
|
||||
* specifying a particular loopback address. We need to
|
||||
* replace the one between source and dest with a \t;
|
||||
* this means we must find the second-to-last colon in
|
||||
* the string.
|
||||
*
|
||||
* (This looks like a foolish way of doing it given the
|
||||
* existence of strrchr, but it's more efficient than
|
||||
* two strrchrs - not to mention that the second strrchr
|
||||
* would require us to modify the input string!)
|
||||
*/
|
||||
|
||||
type = p[1]; /* 'L' or 'R' */
|
||||
|
||||
q = qq = host_strchr(value, ':');
|
||||
while (qq) {
|
||||
char *qqq = host_strchr(qq+1, ':');
|
||||
if (qqq)
|
||||
q = qq;
|
||||
qq = qqq;
|
||||
}
|
||||
q = qq = host_strchr(value, ':');
|
||||
while (qq) {
|
||||
char *qqq = host_strchr(qq+1, ':');
|
||||
if (qqq)
|
||||
q = qq;
|
||||
qq = qqq;
|
||||
}
|
||||
|
||||
if (!q) {
|
||||
cmdline_error("-%c expects at least two colons in its"
|
||||
" argument", type);
|
||||
return ret;
|
||||
}
|
||||
if (!q) {
|
||||
cmdline_error("-%c expects at least two colons in its"
|
||||
" argument", type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
key = dupprintf("%c%.*s", type, (int)(q - value), value);
|
||||
val = dupstr(q+1);
|
||||
} else {
|
||||
key = dupprintf("%c%.*s", type, (int)(q - value), value);
|
||||
val = dupstr(q+1);
|
||||
} else {
|
||||
/*
|
||||
* Dynamic port forwardings are entered under the same key
|
||||
* as if they were local (because they occupy the same
|
||||
|
@ -532,313 +532,313 @@ int cmdline_process_param(const char *p, char *value,
|
|||
* anything in the ordinary -L case by containing no
|
||||
* colon).
|
||||
*/
|
||||
key = dupprintf("L%s", value);
|
||||
val = dupstr("D");
|
||||
}
|
||||
conf_set_str_str(conf, CONF_portfwd, key, val);
|
||||
sfree(key);
|
||||
sfree(val);
|
||||
key = dupprintf("L%s", value);
|
||||
val = dupstr("D");
|
||||
}
|
||||
conf_set_str_str(conf, CONF_portfwd, key, val);
|
||||
sfree(key);
|
||||
sfree(val);
|
||||
}
|
||||
if ((!strcmp(p, "-nc"))) {
|
||||
char *host, *portp;
|
||||
char *host, *portp;
|
||||
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
|
||||
portp = host_strchr(value, ':');
|
||||
if (!portp) {
|
||||
cmdline_error("-nc expects argument of form 'host:port'");
|
||||
return ret;
|
||||
}
|
||||
portp = host_strchr(value, ':');
|
||||
if (!portp) {
|
||||
cmdline_error("-nc expects argument of form 'host:port'");
|
||||
return ret;
|
||||
}
|
||||
|
||||
host = dupprintf("%.*s", (int)(portp - value), value);
|
||||
conf_set_str(conf, CONF_ssh_nc_host, host);
|
||||
conf_set_int(conf, CONF_ssh_nc_port, atoi(portp + 1));
|
||||
host = dupprintf("%.*s", (int)(portp - value), value);
|
||||
conf_set_str(conf, CONF_ssh_nc_host, host);
|
||||
conf_set_int(conf, CONF_ssh_nc_port, atoi(portp + 1));
|
||||
sfree(host);
|
||||
}
|
||||
if (!strcmp(p, "-m")) {
|
||||
const char *filename;
|
||||
FILE *fp;
|
||||
const char *filename;
|
||||
FILE *fp;
|
||||
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
|
||||
filename = value;
|
||||
filename = value;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
cmdline_error("unable to open command file \"%s\"", filename);
|
||||
return ret;
|
||||
}
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
cmdline_error("unable to open command file \"%s\"", filename);
|
||||
return ret;
|
||||
}
|
||||
strbuf *command = strbuf_new();
|
||||
char readbuf[4096];
|
||||
while (1) {
|
||||
while (1) {
|
||||
size_t nread = fread(readbuf, 1, sizeof(readbuf), fp);
|
||||
if (nread == 0)
|
||||
break;
|
||||
put_data(command, readbuf, nread);
|
||||
}
|
||||
fclose(fp);
|
||||
conf_set_str(conf, CONF_remote_cmd, command->s);
|
||||
conf_set_str(conf, CONF_remote_cmd2, "");
|
||||
conf_set_bool(conf, CONF_nopty, true); /* command => no terminal */
|
||||
strbuf_free(command);
|
||||
}
|
||||
fclose(fp);
|
||||
conf_set_str(conf, CONF_remote_cmd, command->s);
|
||||
conf_set_str(conf, CONF_remote_cmd2, "");
|
||||
conf_set_bool(conf, CONF_nopty, true); /* command => no terminal */
|
||||
strbuf_free(command);
|
||||
}
|
||||
if (!strcmp(p, "-P")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1); /* lower priority than -ssh,-telnet */
|
||||
conf_set_int(conf, CONF_port, atoi(value));
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1); /* lower priority than -ssh,-telnet */
|
||||
conf_set_int(conf, CONF_port, atoi(value));
|
||||
}
|
||||
if (!strcmp(p, "-pw")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
/* We delay evaluating this until after the protocol is decided,
|
||||
* so that we can warn if it's of no use with the selected protocol */
|
||||
if (conf_get_int(conf, CONF_protocol) != PROT_SSH)
|
||||
cmdline_error("the -pw option can only be used with the "
|
||||
"SSH protocol");
|
||||
else {
|
||||
cmdline_password = dupstr(value);
|
||||
/* Assuming that `value' is directly from argv, make a good faith
|
||||
* attempt to trample it, to stop it showing up in `ps' output
|
||||
* on Unix-like systems. Not guaranteed, of course. */
|
||||
smemclr(value, strlen(value));
|
||||
}
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
/* We delay evaluating this until after the protocol is decided,
|
||||
* so that we can warn if it's of no use with the selected protocol */
|
||||
if (conf_get_int(conf, CONF_protocol) != PROT_SSH)
|
||||
cmdline_error("the -pw option can only be used with the "
|
||||
"SSH protocol");
|
||||
else {
|
||||
cmdline_password = dupstr(value);
|
||||
/* Assuming that `value' is directly from argv, make a good faith
|
||||
* attempt to trample it, to stop it showing up in `ps' output
|
||||
* on Unix-like systems. Not guaranteed, of course. */
|
||||
smemclr(value, strlen(value));
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-agent") || !strcmp(p, "-pagent") ||
|
||||
!strcmp(p, "-pageant")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_tryagent, true);
|
||||
!strcmp(p, "-pageant")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_tryagent, true);
|
||||
}
|
||||
if (!strcmp(p, "-noagent") || !strcmp(p, "-nopagent") ||
|
||||
!strcmp(p, "-nopageant")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_tryagent, false);
|
||||
!strcmp(p, "-nopageant")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_tryagent, false);
|
||||
}
|
||||
if (!strcmp(p, "-share")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_ssh_connection_sharing, true);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_ssh_connection_sharing, true);
|
||||
}
|
||||
if (!strcmp(p, "-noshare")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_ssh_connection_sharing, false);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_ssh_connection_sharing, false);
|
||||
}
|
||||
if (!strcmp(p, "-A")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_agentfwd, true);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_agentfwd, true);
|
||||
}
|
||||
if (!strcmp(p, "-a")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_agentfwd, false);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_agentfwd, false);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-X")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_x11_forward, true);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_x11_forward, true);
|
||||
}
|
||||
if (!strcmp(p, "-x")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_x11_forward, false);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_x11_forward, false);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-t")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1); /* lower priority than -m */
|
||||
conf_set_bool(conf, CONF_nopty, false);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1); /* lower priority than -m */
|
||||
conf_set_bool(conf, CONF_nopty, false);
|
||||
}
|
||||
if (!strcmp(p, "-T")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
conf_set_bool(conf, CONF_nopty, true);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
conf_set_bool(conf, CONF_nopty, true);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-N")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_ssh_no_shell, true);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_ssh_no_shell, true);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-C")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_compression, true);
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_bool(conf, CONF_compression, true);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-1")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_int(conf, CONF_sshprot, 0); /* ssh protocol 1 only */
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_int(conf, CONF_sshprot, 0); /* ssh protocol 1 only */
|
||||
}
|
||||
if (!strcmp(p, "-2")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_int(conf, CONF_sshprot, 3); /* ssh protocol 2 only */
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_int(conf, CONF_sshprot, 3); /* ssh protocol 2 only */
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-i")) {
|
||||
Filename *fn;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
fn = filename_from_str(value);
|
||||
conf_set_filename(conf, CONF_keyfile, fn);
|
||||
Filename *fn;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
fn = filename_from_str(value);
|
||||
conf_set_filename(conf, CONF_keyfile, fn);
|
||||
filename_free(fn);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-4") || !strcmp(p, "-ipv4")) {
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV4);
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV4);
|
||||
}
|
||||
if (!strcmp(p, "-6") || !strcmp(p, "-ipv6")) {
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV6);
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
conf_set_int(conf, CONF_addressfamily, ADDRTYPE_IPV6);
|
||||
}
|
||||
if (!strcmp(p, "-sercfg")) {
|
||||
char* nextitem;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
if (conf_get_int(conf, CONF_protocol) != PROT_SERIAL)
|
||||
cmdline_error("the -sercfg option can only be used with the "
|
||||
"serial protocol");
|
||||
/* Value[0] contains one or more , separated values, like 19200,8,n,1,X */
|
||||
nextitem = value;
|
||||
while (nextitem[0] != '\0') {
|
||||
int length, skip;
|
||||
char *end = strchr(nextitem, ',');
|
||||
if (!end) {
|
||||
length = strlen(nextitem);
|
||||
skip = 0;
|
||||
} else {
|
||||
length = end - nextitem;
|
||||
nextitem[length] = '\0';
|
||||
skip = 1;
|
||||
}
|
||||
if (length == 1) {
|
||||
switch (*nextitem) {
|
||||
case '1':
|
||||
case '2':
|
||||
conf_set_int(conf, CONF_serstopbits, 2 * (*nextitem-'0'));
|
||||
break;
|
||||
char* nextitem;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
if (conf_get_int(conf, CONF_protocol) != PROT_SERIAL)
|
||||
cmdline_error("the -sercfg option can only be used with the "
|
||||
"serial protocol");
|
||||
/* Value[0] contains one or more , separated values, like 19200,8,n,1,X */
|
||||
nextitem = value;
|
||||
while (nextitem[0] != '\0') {
|
||||
int length, skip;
|
||||
char *end = strchr(nextitem, ',');
|
||||
if (!end) {
|
||||
length = strlen(nextitem);
|
||||
skip = 0;
|
||||
} else {
|
||||
length = end - nextitem;
|
||||
nextitem[length] = '\0';
|
||||
skip = 1;
|
||||
}
|
||||
if (length == 1) {
|
||||
switch (*nextitem) {
|
||||
case '1':
|
||||
case '2':
|
||||
conf_set_int(conf, CONF_serstopbits, 2 * (*nextitem-'0'));
|
||||
break;
|
||||
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
conf_set_int(conf, CONF_serdatabits, *nextitem-'0');
|
||||
break;
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
conf_set_int(conf, CONF_serdatabits, *nextitem-'0');
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_NONE);
|
||||
break;
|
||||
case 'o':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_ODD);
|
||||
break;
|
||||
case 'e':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_EVEN);
|
||||
break;
|
||||
case 'm':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_MARK);
|
||||
break;
|
||||
case 's':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_SPACE);
|
||||
break;
|
||||
case 'n':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_NONE);
|
||||
break;
|
||||
case 'o':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_ODD);
|
||||
break;
|
||||
case 'e':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_EVEN);
|
||||
break;
|
||||
case 'm':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_MARK);
|
||||
break;
|
||||
case 's':
|
||||
conf_set_int(conf, CONF_serparity, SER_PAR_SPACE);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_NONE);
|
||||
break;
|
||||
case 'X':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_XONXOFF);
|
||||
break;
|
||||
case 'R':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_RTSCTS);
|
||||
break;
|
||||
case 'D':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_DSRDTR);
|
||||
break;
|
||||
case 'N':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_NONE);
|
||||
break;
|
||||
case 'X':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_XONXOFF);
|
||||
break;
|
||||
case 'R':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_RTSCTS);
|
||||
break;
|
||||
case 'D':
|
||||
conf_set_int(conf, CONF_serflow, SER_FLOW_DSRDTR);
|
||||
break;
|
||||
|
||||
default:
|
||||
cmdline_error("Unrecognised suboption \"-sercfg %c\"",
|
||||
*nextitem);
|
||||
}
|
||||
} else if (length == 3 && !strncmp(nextitem,"1.5",3)) {
|
||||
/* Messy special case */
|
||||
conf_set_int(conf, CONF_serstopbits, 3);
|
||||
} else {
|
||||
int serspeed = atoi(nextitem);
|
||||
if (serspeed != 0) {
|
||||
conf_set_int(conf, CONF_serspeed, serspeed);
|
||||
} else {
|
||||
cmdline_error("Unrecognised suboption \"-sercfg %s\"",
|
||||
nextitem);
|
||||
}
|
||||
}
|
||||
nextitem += length + skip;
|
||||
}
|
||||
default:
|
||||
cmdline_error("Unrecognised suboption \"-sercfg %c\"",
|
||||
*nextitem);
|
||||
}
|
||||
} else if (length == 3 && !strncmp(nextitem,"1.5",3)) {
|
||||
/* Messy special case */
|
||||
conf_set_int(conf, CONF_serstopbits, 3);
|
||||
} else {
|
||||
int serspeed = atoi(nextitem);
|
||||
if (serspeed != 0) {
|
||||
conf_set_int(conf, CONF_serspeed, serspeed);
|
||||
} else {
|
||||
cmdline_error("Unrecognised suboption \"-sercfg %s\"",
|
||||
nextitem);
|
||||
}
|
||||
}
|
||||
nextitem += length + skip;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-sessionlog")) {
|
||||
Filename *fn;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER);
|
||||
/* but available even in TOOLTYPE_NONNETWORK, cf pterm "-log" */
|
||||
SAVEABLE(0);
|
||||
fn = filename_from_str(value);
|
||||
conf_set_filename(conf, CONF_logfilename, fn);
|
||||
conf_set_int(conf, CONF_logtype, LGTYP_DEBUG);
|
||||
Filename *fn;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER);
|
||||
/* but available even in TOOLTYPE_NONNETWORK, cf pterm "-log" */
|
||||
SAVEABLE(0);
|
||||
fn = filename_from_str(value);
|
||||
conf_set_filename(conf, CONF_logfilename, fn);
|
||||
conf_set_int(conf, CONF_logtype, LGTYP_DEBUG);
|
||||
filename_free(fn);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-sshlog") ||
|
||||
!strcmp(p, "-sshrawlog")) {
|
||||
Filename *fn;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
fn = filename_from_str(value);
|
||||
conf_set_filename(conf, CONF_logfilename, fn);
|
||||
conf_set_int(conf, CONF_logtype,
|
||||
Filename *fn;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
fn = filename_from_str(value);
|
||||
conf_set_filename(conf, CONF_logfilename, fn);
|
||||
conf_set_int(conf, CONF_logtype,
|
||||
!strcmp(p, "-sshlog") ? LGTYP_PACKETS :
|
||||
/* !strcmp(p, "-sshrawlog") ? */ LGTYP_SSHRAW);
|
||||
filename_free(fn);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-proxycmd")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
conf_set_int(conf, CONF_proxy_type, PROXY_CMD);
|
||||
conf_set_str(conf, CONF_proxy_telnet_command, value);
|
||||
conf_set_str(conf, CONF_proxy_telnet_command, value);
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
@ -847,22 +847,22 @@ int cmdline_process_param(const char *p, char *value,
|
|||
*/
|
||||
if (!strcmp(p, "-restrict-acl") || !strcmp(p, "-restrict_acl") ||
|
||||
!strcmp(p, "-restrictacl")) {
|
||||
RETURN(1);
|
||||
RETURN(1);
|
||||
restrict_process_acl();
|
||||
restricted_acl = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret; /* unrecognised */
|
||||
return ret; /* unrecognised */
|
||||
}
|
||||
|
||||
void cmdline_run_saved(Conf *conf)
|
||||
{
|
||||
int pri, i;
|
||||
for (pri = 0; pri < NPRIORITIES; pri++) {
|
||||
for (i = 0; i < saves[pri].nsaved; i++) {
|
||||
cmdline_process_param(saves[pri].params[i].p,
|
||||
saves[pri].params[i].value, 0, conf);
|
||||
for (i = 0; i < saves[pri].nsaved; i++) {
|
||||
cmdline_process_param(saves[pri].params[i].p,
|
||||
saves[pri].params[i].value, 0, conf);
|
||||
sfree(saves[pri].params[i].p);
|
||||
sfree(saves[pri].params[i].value);
|
||||
}
|
||||
|
|
234
conf.c
234
conf.c
|
@ -36,8 +36,8 @@ static int valuetypes[] = { CONFIG_OPTIONS(CONF_VALUETYPE_DEF) };
|
|||
struct key {
|
||||
int primary;
|
||||
union {
|
||||
int i;
|
||||
char *s;
|
||||
int i;
|
||||
char *s;
|
||||
} secondary;
|
||||
};
|
||||
|
||||
|
@ -46,18 +46,18 @@ struct key {
|
|||
struct constkey {
|
||||
int primary;
|
||||
union {
|
||||
int i;
|
||||
const char *s;
|
||||
int i;
|
||||
const char *s;
|
||||
} secondary;
|
||||
};
|
||||
|
||||
struct value {
|
||||
union {
|
||||
bool boolval;
|
||||
int intval;
|
||||
char *stringval;
|
||||
Filename *fileval;
|
||||
FontSpec *fontval;
|
||||
bool boolval;
|
||||
int intval;
|
||||
char *stringval;
|
||||
Filename *fileval;
|
||||
FontSpec *fontval;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
@ -84,20 +84,20 @@ static int conf_cmp(void *av, void *bv)
|
|||
struct key *b = (struct key *)bv;
|
||||
|
||||
if (a->primary < b->primary)
|
||||
return -1;
|
||||
return -1;
|
||||
else if (a->primary > b->primary)
|
||||
return +1;
|
||||
return +1;
|
||||
switch (subkeytypes[a->primary]) {
|
||||
case TYPE_INT:
|
||||
if (a->secondary.i < b->secondary.i)
|
||||
return -1;
|
||||
else if (a->secondary.i > b->secondary.i)
|
||||
return +1;
|
||||
return 0;
|
||||
if (a->secondary.i < b->secondary.i)
|
||||
return -1;
|
||||
else if (a->secondary.i > b->secondary.i)
|
||||
return +1;
|
||||
return 0;
|
||||
case TYPE_STR:
|
||||
return strcmp(a->secondary.s, b->secondary.s);
|
||||
return strcmp(a->secondary.s, b->secondary.s);
|
||||
default:
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,20 +107,20 @@ static int conf_cmp_constkey(void *av, void *bv)
|
|||
struct constkey *b = (struct constkey *)bv;
|
||||
|
||||
if (a->primary < b->primary)
|
||||
return -1;
|
||||
return -1;
|
||||
else if (a->primary > b->primary)
|
||||
return +1;
|
||||
return +1;
|
||||
switch (subkeytypes[a->primary]) {
|
||||
case TYPE_INT:
|
||||
if (a->secondary.i < b->secondary.i)
|
||||
return -1;
|
||||
else if (a->secondary.i > b->secondary.i)
|
||||
return +1;
|
||||
return 0;
|
||||
if (a->secondary.i < b->secondary.i)
|
||||
return -1;
|
||||
else if (a->secondary.i > b->secondary.i)
|
||||
return +1;
|
||||
return 0;
|
||||
case TYPE_STR:
|
||||
return strcmp(a->secondary.s, b->secondary.s);
|
||||
return strcmp(a->secondary.s, b->secondary.s);
|
||||
default:
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ static int conf_cmp_constkey(void *av, void *bv)
|
|||
static void free_key(struct key *key)
|
||||
{
|
||||
if (subkeytypes[key->primary] == TYPE_STR)
|
||||
sfree(key->secondary.s);
|
||||
sfree(key->secondary.s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -144,11 +144,11 @@ static void copy_key(struct key *to, struct key *from)
|
|||
to->primary = from->primary;
|
||||
switch (subkeytypes[to->primary]) {
|
||||
case TYPE_INT:
|
||||
to->secondary.i = from->secondary.i;
|
||||
break;
|
||||
to->secondary.i = from->secondary.i;
|
||||
break;
|
||||
case TYPE_STR:
|
||||
to->secondary.s = dupstr(from->secondary.s);
|
||||
break;
|
||||
to->secondary.s = dupstr(from->secondary.s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,11 +160,11 @@ static void copy_key(struct key *to, struct key *from)
|
|||
static void free_value(struct value *val, int type)
|
||||
{
|
||||
if (type == TYPE_STR)
|
||||
sfree(val->u.stringval);
|
||||
sfree(val->u.stringval);
|
||||
else if (type == TYPE_FILENAME)
|
||||
filename_free(val->u.fileval);
|
||||
filename_free(val->u.fileval);
|
||||
else if (type == TYPE_FONT)
|
||||
fontspec_free(val->u.fontval);
|
||||
fontspec_free(val->u.fontval);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -175,20 +175,20 @@ static void copy_value(struct value *to, struct value *from, int type)
|
|||
{
|
||||
switch (type) {
|
||||
case TYPE_BOOL:
|
||||
to->u.boolval = from->u.boolval;
|
||||
break;
|
||||
to->u.boolval = from->u.boolval;
|
||||
break;
|
||||
case TYPE_INT:
|
||||
to->u.intval = from->u.intval;
|
||||
break;
|
||||
to->u.intval = from->u.intval;
|
||||
break;
|
||||
case TYPE_STR:
|
||||
to->u.stringval = dupstr(from->u.stringval);
|
||||
break;
|
||||
to->u.stringval = dupstr(from->u.stringval);
|
||||
break;
|
||||
case TYPE_FILENAME:
|
||||
to->u.fileval = filename_copy(from->u.fileval);
|
||||
break;
|
||||
to->u.fileval = filename_copy(from->u.fileval);
|
||||
break;
|
||||
case TYPE_FONT:
|
||||
to->u.fontval = fontspec_copy(from->u.fontval);
|
||||
break;
|
||||
to->u.fontval = fontspec_copy(from->u.fontval);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +216,7 @@ static void conf_clear(Conf *conf)
|
|||
struct conf_entry *entry;
|
||||
|
||||
while ((entry = delpos234(conf->tree, 0)) != NULL)
|
||||
free_entry(entry);
|
||||
free_entry(entry);
|
||||
}
|
||||
|
||||
void conf_free(Conf *conf)
|
||||
|
@ -230,10 +230,10 @@ static void conf_insert(Conf *conf, struct conf_entry *entry)
|
|||
{
|
||||
struct conf_entry *oldentry = add234(conf->tree, entry);
|
||||
if (oldentry && oldentry != entry) {
|
||||
del234(conf->tree, oldentry);
|
||||
free_entry(oldentry);
|
||||
oldentry = add234(conf->tree, entry);
|
||||
assert(oldentry == entry);
|
||||
del234(conf->tree, oldentry);
|
||||
free_entry(oldentry);
|
||||
oldentry = add234(conf->tree, entry);
|
||||
assert(oldentry == entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,11 +245,11 @@ void conf_copy_into(Conf *newconf, Conf *oldconf)
|
|||
conf_clear(newconf);
|
||||
|
||||
for (i = 0; (entry = index234(oldconf->tree, i)) != NULL; i++) {
|
||||
entry2 = snew(struct conf_entry);
|
||||
copy_key(&entry2->key, &entry->key);
|
||||
copy_value(&entry2->value, &entry->value,
|
||||
valuetypes[entry->key.primary]);
|
||||
add234(newconf->tree, entry2);
|
||||
entry2 = snew(struct conf_entry);
|
||||
copy_key(&entry2->key, &entry->key);
|
||||
copy_value(&entry2->value, &entry->value,
|
||||
valuetypes[entry->key.primary]);
|
||||
add234(newconf->tree, entry2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,7 @@ char *conf_get_str_str(Conf *conf, int primary, const char *secondary)
|
|||
}
|
||||
|
||||
char *conf_get_str_strs(Conf *conf, int primary,
|
||||
char *subkeyin, char **subkeyout)
|
||||
char *subkeyin, char **subkeyout)
|
||||
{
|
||||
struct constkey key;
|
||||
struct conf_entry *entry;
|
||||
|
@ -345,14 +345,14 @@ char *conf_get_str_strs(Conf *conf, int primary,
|
|||
assert(valuetypes[primary] == TYPE_STR);
|
||||
key.primary = primary;
|
||||
if (subkeyin) {
|
||||
key.secondary.s = subkeyin;
|
||||
entry = findrel234(conf->tree, &key, NULL, REL234_GT);
|
||||
key.secondary.s = subkeyin;
|
||||
entry = findrel234(conf->tree, &key, NULL, REL234_GT);
|
||||
} else {
|
||||
key.secondary.s = "";
|
||||
entry = findrel234(conf->tree, &key, conf_cmp_constkey, REL234_GE);
|
||||
key.secondary.s = "";
|
||||
entry = findrel234(conf->tree, &key, conf_cmp_constkey, REL234_GE);
|
||||
}
|
||||
if (!entry || entry->key.primary != primary)
|
||||
return NULL;
|
||||
return NULL;
|
||||
*subkeyout = entry->key.secondary.s;
|
||||
return entry->value.u.stringval;
|
||||
}
|
||||
|
@ -370,10 +370,10 @@ char *conf_get_str_nthstrkey(Conf *conf, int primary, int n)
|
|||
entry = findrelpos234(conf->tree, &key, conf_cmp_constkey,
|
||||
REL234_GE, &index);
|
||||
if (!entry || entry->key.primary != primary)
|
||||
return NULL;
|
||||
return NULL;
|
||||
entry = index234(conf->tree, index + n);
|
||||
if (!entry || entry->key.primary != primary)
|
||||
return NULL;
|
||||
return NULL;
|
||||
return entry->key.secondary.s;
|
||||
}
|
||||
|
||||
|
@ -450,7 +450,7 @@ void conf_set_str(Conf *conf, int primary, const char *value)
|
|||
}
|
||||
|
||||
void conf_set_str_str(Conf *conf, int primary, const char *secondary,
|
||||
const char *value)
|
||||
const char *value)
|
||||
{
|
||||
struct conf_entry *entry = snew(struct conf_entry);
|
||||
|
||||
|
@ -473,8 +473,8 @@ void conf_del_str_str(Conf *conf, int primary, const char *secondary)
|
|||
key.secondary.s = (char *)secondary;
|
||||
entry = find234(conf->tree, &key, NULL);
|
||||
if (entry) {
|
||||
del234(conf->tree, entry);
|
||||
free_entry(entry);
|
||||
del234(conf->tree, entry);
|
||||
free_entry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -506,33 +506,33 @@ void conf_serialise(BinarySink *bs, Conf *conf)
|
|||
struct conf_entry *entry;
|
||||
|
||||
for (i = 0; (entry = index234(conf->tree, i)) != NULL; i++) {
|
||||
put_uint32(bs, entry->key.primary);
|
||||
put_uint32(bs, entry->key.primary);
|
||||
|
||||
switch (subkeytypes[entry->key.primary]) {
|
||||
case TYPE_INT:
|
||||
put_uint32(bs, entry->key.secondary.i);
|
||||
break;
|
||||
case TYPE_STR:
|
||||
switch (subkeytypes[entry->key.primary]) {
|
||||
case TYPE_INT:
|
||||
put_uint32(bs, entry->key.secondary.i);
|
||||
break;
|
||||
case TYPE_STR:
|
||||
put_asciz(bs, entry->key.secondary.s);
|
||||
break;
|
||||
}
|
||||
switch (valuetypes[entry->key.primary]) {
|
||||
case TYPE_BOOL:
|
||||
put_bool(bs, entry->value.u.boolval);
|
||||
break;
|
||||
case TYPE_INT:
|
||||
put_uint32(bs, entry->value.u.intval);
|
||||
break;
|
||||
case TYPE_STR:
|
||||
put_asciz(bs, entry->value.u.stringval);
|
||||
break;
|
||||
case TYPE_FILENAME:
|
||||
break;
|
||||
}
|
||||
switch (valuetypes[entry->key.primary]) {
|
||||
case TYPE_BOOL:
|
||||
put_bool(bs, entry->value.u.boolval);
|
||||
break;
|
||||
case TYPE_INT:
|
||||
put_uint32(bs, entry->value.u.intval);
|
||||
break;
|
||||
case TYPE_STR:
|
||||
put_asciz(bs, entry->value.u.stringval);
|
||||
break;
|
||||
case TYPE_FILENAME:
|
||||
filename_serialise(bs, entry->value.u.fileval);
|
||||
break;
|
||||
case TYPE_FONT:
|
||||
break;
|
||||
case TYPE_FONT:
|
||||
fontspec_serialise(bs, entry->value.u.fontval);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
put_uint32(bs, 0xFFFFFFFFU);
|
||||
|
@ -550,44 +550,44 @@ bool conf_deserialise(Conf *conf, BinarySource *src)
|
|||
return false;
|
||||
if (primary == 0xFFFFFFFFU)
|
||||
return true;
|
||||
if (primary >= N_CONFIG_OPTIONS)
|
||||
return false;
|
||||
if (primary >= N_CONFIG_OPTIONS)
|
||||
return false;
|
||||
|
||||
entry = snew(struct conf_entry);
|
||||
entry->key.primary = primary;
|
||||
entry = snew(struct conf_entry);
|
||||
entry->key.primary = primary;
|
||||
|
||||
switch (subkeytypes[entry->key.primary]) {
|
||||
case TYPE_INT:
|
||||
entry->key.secondary.i = toint(get_uint32(src));
|
||||
break;
|
||||
case TYPE_STR:
|
||||
entry->key.secondary.s = dupstr(get_asciz(src));
|
||||
break;
|
||||
}
|
||||
switch (subkeytypes[entry->key.primary]) {
|
||||
case TYPE_INT:
|
||||
entry->key.secondary.i = toint(get_uint32(src));
|
||||
break;
|
||||
case TYPE_STR:
|
||||
entry->key.secondary.s = dupstr(get_asciz(src));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (valuetypes[entry->key.primary]) {
|
||||
case TYPE_BOOL:
|
||||
entry->value.u.boolval = get_bool(src);
|
||||
break;
|
||||
case TYPE_INT:
|
||||
entry->value.u.intval = toint(get_uint32(src));
|
||||
break;
|
||||
case TYPE_STR:
|
||||
entry->value.u.stringval = dupstr(get_asciz(src));
|
||||
break;
|
||||
case TYPE_FILENAME:
|
||||
switch (valuetypes[entry->key.primary]) {
|
||||
case TYPE_BOOL:
|
||||
entry->value.u.boolval = get_bool(src);
|
||||
break;
|
||||
case TYPE_INT:
|
||||
entry->value.u.intval = toint(get_uint32(src));
|
||||
break;
|
||||
case TYPE_STR:
|
||||
entry->value.u.stringval = dupstr(get_asciz(src));
|
||||
break;
|
||||
case TYPE_FILENAME:
|
||||
entry->value.u.fileval = filename_deserialise(src);
|
||||
break;
|
||||
case TYPE_FONT:
|
||||
break;
|
||||
case TYPE_FONT:
|
||||
entry->value.u.fontval = fontspec_deserialise(src);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (get_err(src)) {
|
||||
free_entry(entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
conf_insert(conf, entry);
|
||||
conf_insert(conf, entry);
|
||||
}
|
||||
}
|
||||
|
|
3386
config.c
3386
config.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -47,12 +47,12 @@ void fatal(const char *fmt, ...)
|
|||
void net_readdata(sel_rfd *rfd, void *data, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
exit(0); /* EOF on network - client went away */
|
||||
exit(0); /* EOF on network - client went away */
|
||||
telnet_from_net(telnet, data, len);
|
||||
if (sel_write(netw, NULL, 0) > BUF)
|
||||
sel_rfd_freeze(ptyr);
|
||||
sel_rfd_freeze(ptyr);
|
||||
if (sel_write(ptyw, NULL, 0) > BUF)
|
||||
sel_rfd_freeze(netr);
|
||||
sel_rfd_freeze(netr);
|
||||
}
|
||||
|
||||
void net_readerr(sel_rfd *rfd, int error)
|
||||
|
@ -64,7 +64,7 @@ void net_readerr(sel_rfd *rfd, int error)
|
|||
void net_written(sel_wfd *wfd, size_t bufsize)
|
||||
{
|
||||
if (bufsize < BUF)
|
||||
sel_rfd_unfreeze(ptyr);
|
||||
sel_rfd_unfreeze(ptyr);
|
||||
}
|
||||
|
||||
void net_writeerr(sel_wfd *wfd, int error)
|
||||
|
@ -76,18 +76,18 @@ void net_writeerr(sel_wfd *wfd, int error)
|
|||
void pty_readdata(sel_rfd *rfd, void *data, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
exit(0); /* EOF on pty */
|
||||
exit(0); /* EOF on pty */
|
||||
telnet_from_pty(telnet, data, len);
|
||||
if (sel_write(netw, NULL, 0) > BUF)
|
||||
sel_rfd_freeze(ptyr);
|
||||
sel_rfd_freeze(ptyr);
|
||||
if (sel_write(ptyw, NULL, 0) > BUF)
|
||||
sel_rfd_freeze(netr);
|
||||
sel_rfd_freeze(netr);
|
||||
}
|
||||
|
||||
void pty_readerr(sel_rfd *rfd, int error)
|
||||
{
|
||||
if (error == EIO) /* means EOF, on a pty */
|
||||
exit(0);
|
||||
if (error == EIO) /* means EOF, on a pty */
|
||||
exit(0);
|
||||
fprintf(stderr, "pty: read: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ void pty_readerr(sel_rfd *rfd, int error)
|
|||
void pty_written(sel_wfd *wfd, size_t bufsize)
|
||||
{
|
||||
if (bufsize < BUF)
|
||||
sel_rfd_unfreeze(netr);
|
||||
sel_rfd_unfreeze(netr);
|
||||
}
|
||||
|
||||
void pty_writeerr(sel_wfd *wfd, int error)
|
||||
|
@ -109,12 +109,12 @@ void sig_readdata(sel_rfd *rfd, void *data, size_t len)
|
|||
char *p = data;
|
||||
|
||||
while (len > 0) {
|
||||
if (*p == 'C') {
|
||||
int status;
|
||||
waitpid(-1, &status, WNOHANG);
|
||||
if (WIFEXITED(status) || WIFSIGNALED(status))
|
||||
exit(0); /* child process vanished */
|
||||
}
|
||||
if (*p == 'C') {
|
||||
int status;
|
||||
waitpid(-1, &status, WNOHANG);
|
||||
if (WIFEXITED(status) || WIFSIGNALED(status))
|
||||
exit(0); /* child process vanished */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,24 +150,24 @@ int main(int argc, char **argv)
|
|||
telnet = telnet_new(netw, ptyw);
|
||||
|
||||
if (pipe(signalpipe) < 0) {
|
||||
perror("pipe");
|
||||
return 1;
|
||||
perror("pipe");
|
||||
return 1;
|
||||
}
|
||||
sigr = sel_rfd_add(asel, signalpipe[0], sig_readdata,
|
||||
sig_readerr, NULL);
|
||||
sig_readerr, NULL);
|
||||
|
||||
signal(SIGCHLD, sigchld);
|
||||
|
||||
do {
|
||||
struct shell_data shdata;
|
||||
struct shell_data shdata;
|
||||
|
||||
ret = sel_iterate(asel, -1);
|
||||
if (!shell_started && telnet_shell_ok(telnet, &shdata)) {
|
||||
ptyfd = run_program_in_pty(&shdata, directory, program_args);
|
||||
sel_rfd_setfd(ptyr, ptyfd);
|
||||
sel_wfd_setfd(ptyw, ptyfd);
|
||||
shell_started = 1;
|
||||
}
|
||||
ret = sel_iterate(asel, -1);
|
||||
if (!shell_started && telnet_shell_ok(telnet, &shdata)) {
|
||||
ptyfd = run_program_in_pty(&shdata, directory, program_args);
|
||||
sel_rfd_setfd(ptyr, ptyfd);
|
||||
sel_wfd_setfd(ptyw, ptyfd);
|
||||
shell_started = 1;
|
||||
}
|
||||
} while (ret == 0);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -13,26 +13,26 @@ void *smalloc(size_t size) {
|
|||
void *p;
|
||||
p = malloc(size);
|
||||
if (!p) {
|
||||
fatal("out of memory");
|
||||
fatal("out of memory");
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void sfree(void *p) {
|
||||
if (p) {
|
||||
free(p);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
void *srealloc(void *p, size_t size) {
|
||||
void *q;
|
||||
if (p) {
|
||||
q = realloc(p, size);
|
||||
q = realloc(p, size);
|
||||
} else {
|
||||
q = malloc(size);
|
||||
q = malloc(size);
|
||||
}
|
||||
if (!q)
|
||||
fatal("out of memory");
|
||||
fatal("out of memory");
|
||||
return q;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,18 +30,18 @@ void pty_preinit(void)
|
|||
*/
|
||||
master = open("/dev/ptmx", O_RDWR);
|
||||
if (master < 0) {
|
||||
perror("/dev/ptmx: open");
|
||||
exit(1);
|
||||
perror("/dev/ptmx: open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (grantpt(master) < 0) {
|
||||
perror("grantpt");
|
||||
exit(1);
|
||||
perror("grantpt");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (unlockpt(master) < 0) {
|
||||
perror("unlockpt");
|
||||
exit(1);
|
||||
perror("unlockpt");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,24 +70,24 @@ int run_program_in_pty(const struct shell_data *shdata,
|
|||
|
||||
#if 0
|
||||
{
|
||||
struct winsize ws;
|
||||
struct termios ts;
|
||||
struct winsize ws;
|
||||
struct termios ts;
|
||||
|
||||
/*
|
||||
* FIXME: think up some good defaults here
|
||||
*/
|
||||
/*
|
||||
* FIXME: think up some good defaults here
|
||||
*/
|
||||
|
||||
if (!ioctl(0, TIOCGWINSZ, &ws))
|
||||
ioctl(master, TIOCSWINSZ, &ws);
|
||||
if (!tcgetattr(0, &ts))
|
||||
tcsetattr(master, TCSANOW, &ts);
|
||||
if (!ioctl(0, TIOCGWINSZ, &ws))
|
||||
ioctl(master, TIOCSWINSZ, &ws);
|
||||
if (!tcgetattr(0, &ts))
|
||||
tcsetattr(master, TCSANOW, &ts);
|
||||
}
|
||||
#endif
|
||||
|
||||
slave = open(ptyname, O_RDWR | O_NOCTTY);
|
||||
if (slave < 0) {
|
||||
perror("slave pty: open");
|
||||
return 1;
|
||||
perror("slave pty: open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -95,26 +95,26 @@ int run_program_in_pty(const struct shell_data *shdata,
|
|||
*/
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fork");
|
||||
return 1;
|
||||
perror("fork");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
int i, fd;
|
||||
int i, fd;
|
||||
|
||||
/*
|
||||
* We are the child.
|
||||
*/
|
||||
close(master);
|
||||
/*
|
||||
* We are the child.
|
||||
*/
|
||||
close(master);
|
||||
|
||||
fcntl(slave, F_SETFD, 0); /* don't close on exec */
|
||||
dup2(slave, 0);
|
||||
dup2(slave, 1);
|
||||
if (slave != 0 && slave != 1)
|
||||
close(slave);
|
||||
dup2(1, 2);
|
||||
setsid();
|
||||
setpgrp();
|
||||
fcntl(slave, F_SETFD, 0); /* don't close on exec */
|
||||
dup2(slave, 0);
|
||||
dup2(slave, 1);
|
||||
if (slave != 0 && slave != 1)
|
||||
close(slave);
|
||||
dup2(1, 2);
|
||||
setsid();
|
||||
setpgrp();
|
||||
i = 0;
|
||||
#ifdef TIOCNOTTY
|
||||
if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
|
||||
|
@ -139,26 +139,26 @@ int run_program_in_pty(const struct shell_data *shdata,
|
|||
perror("slave pty: open");
|
||||
exit(127);
|
||||
}
|
||||
tcsetpgrp(0, getpgrp());
|
||||
tcsetpgrp(0, getpgrp());
|
||||
|
||||
for (i = 0; i < shdata->nenvvars; i++)
|
||||
for (i = 0; i < shdata->nenvvars; i++)
|
||||
putenv(shdata->envvars[i]);
|
||||
if (shdata->termtype)
|
||||
if (shdata->termtype)
|
||||
putenv(shdata->termtype);
|
||||
|
||||
if (directory)
|
||||
chdir(directory);
|
||||
|
||||
/*
|
||||
* Use the provided shell program name, if the user gave
|
||||
* one. Failing that, use $SHELL; failing that, look up
|
||||
* the user's default shell in the password file; failing
|
||||
* _that_, revert to the bog-standard /bin/sh.
|
||||
*/
|
||||
if (!program_args) {
|
||||
/*
|
||||
* Use the provided shell program name, if the user gave
|
||||
* one. Failing that, use $SHELL; failing that, look up
|
||||
* the user's default shell in the password file; failing
|
||||
* _that_, revert to the bog-standard /bin/sh.
|
||||
*/
|
||||
if (!program_args) {
|
||||
char *shell;
|
||||
|
||||
shell = getenv("SHELL");
|
||||
|
||||
shell = getenv("SHELL");
|
||||
if (!shell) {
|
||||
const char *login;
|
||||
uid_t uid;
|
||||
|
@ -189,11 +189,11 @@ int run_program_in_pty(const struct shell_data *shdata,
|
|||
|
||||
execv(program_args[0], program_args);
|
||||
|
||||
/*
|
||||
* If we're here, exec has gone badly foom.
|
||||
*/
|
||||
perror("exec");
|
||||
exit(127);
|
||||
/*
|
||||
* If we're here, exec has gone badly foom.
|
||||
*/
|
||||
perror("exec");
|
||||
exit(127);
|
||||
}
|
||||
|
||||
close(slave);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef CYGTERMD_PTY_H
|
||||
#define CYGTERMD_PTY_H
|
||||
|
||||
#include "telnet.h" /* for struct shdata */
|
||||
#include "telnet.h" /* for struct shdata */
|
||||
|
||||
/*
|
||||
* Called at program startup to actually allocate a pty, so that
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
typedef struct bufchain_tag {
|
||||
struct bufchain_granule *head, *tail;
|
||||
size_t buffersize; /* current amount of buffered data */
|
||||
size_t buffersize; /* current amount of buffered data */
|
||||
} bufchain;
|
||||
struct bufchain_granule {
|
||||
struct bufchain_granule *next;
|
||||
|
@ -43,9 +43,9 @@ static void bufchain_clear(bufchain *ch)
|
|||
{
|
||||
struct bufchain_granule *b;
|
||||
while (ch->head) {
|
||||
b = ch->head;
|
||||
ch->head = ch->head->next;
|
||||
sfree(b);
|
||||
b = ch->head;
|
||||
ch->head = ch->head->next;
|
||||
sfree(b);
|
||||
}
|
||||
ch->tail = NULL;
|
||||
ch->buffersize = 0;
|
||||
|
@ -65,31 +65,31 @@ static void bufchain_add(bufchain *ch, const void *data, size_t len)
|
|||
ch->buffersize += len;
|
||||
|
||||
if (ch->tail && ch->tail->buflen < BUFFER_GRANULE) {
|
||||
size_t copylen = BUFFER_GRANULE - ch->tail->buflen;
|
||||
if (copylen > len)
|
||||
copylen = len;
|
||||
memcpy(ch->tail->buf + ch->tail->buflen, buf, copylen);
|
||||
buf += copylen;
|
||||
len -= copylen;
|
||||
ch->tail->buflen += copylen;
|
||||
size_t copylen = BUFFER_GRANULE - ch->tail->buflen;
|
||||
if (copylen > len)
|
||||
copylen = len;
|
||||
memcpy(ch->tail->buf + ch->tail->buflen, buf, copylen);
|
||||
buf += copylen;
|
||||
len -= copylen;
|
||||
ch->tail->buflen += copylen;
|
||||
}
|
||||
while (len > 0) {
|
||||
struct bufchain_granule *newbuf;
|
||||
size_t grainlen = BUFFER_GRANULE;
|
||||
if (grainlen > len)
|
||||
grainlen = len;
|
||||
newbuf = snew(struct bufchain_granule);
|
||||
newbuf->bufpos = 0;
|
||||
newbuf->buflen = grainlen;
|
||||
memcpy(newbuf->buf, buf, grainlen);
|
||||
buf += grainlen;
|
||||
len -= grainlen;
|
||||
if (ch->tail)
|
||||
ch->tail->next = newbuf;
|
||||
else
|
||||
ch->head = ch->tail = newbuf;
|
||||
newbuf->next = NULL;
|
||||
ch->tail = newbuf;
|
||||
struct bufchain_granule *newbuf;
|
||||
size_t grainlen = BUFFER_GRANULE;
|
||||
if (grainlen > len)
|
||||
grainlen = len;
|
||||
newbuf = snew(struct bufchain_granule);
|
||||
newbuf->bufpos = 0;
|
||||
newbuf->buflen = grainlen;
|
||||
memcpy(newbuf->buf, buf, grainlen);
|
||||
buf += grainlen;
|
||||
len -= grainlen;
|
||||
if (ch->tail)
|
||||
ch->tail->next = newbuf;
|
||||
else
|
||||
ch->head = ch->tail = newbuf;
|
||||
newbuf->next = NULL;
|
||||
ch->tail = newbuf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,19 +99,19 @@ static void bufchain_consume(bufchain *ch, size_t len)
|
|||
|
||||
assert(ch->buffersize >= len);
|
||||
while (len > 0) {
|
||||
size_t remlen = len;
|
||||
assert(ch->head != NULL);
|
||||
if (remlen >= ch->head->buflen - ch->head->bufpos) {
|
||||
remlen = ch->head->buflen - ch->head->bufpos;
|
||||
tmp = ch->head;
|
||||
ch->head = tmp->next;
|
||||
sfree(tmp);
|
||||
if (!ch->head)
|
||||
ch->tail = NULL;
|
||||
} else
|
||||
ch->head->bufpos += remlen;
|
||||
ch->buffersize -= remlen;
|
||||
len -= remlen;
|
||||
size_t remlen = len;
|
||||
assert(ch->head != NULL);
|
||||
if (remlen >= ch->head->buflen - ch->head->bufpos) {
|
||||
remlen = ch->head->buflen - ch->head->bufpos;
|
||||
tmp = ch->head;
|
||||
ch->head = tmp->next;
|
||||
sfree(tmp);
|
||||
if (!ch->head)
|
||||
ch->tail = NULL;
|
||||
} else
|
||||
ch->head->bufpos += remlen;
|
||||
ch->buffersize -= remlen;
|
||||
len -= remlen;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,8 +163,8 @@ sel *sel_new(void *ctx)
|
|||
}
|
||||
|
||||
sel_wfd *sel_wfd_add(sel *sel, int fd,
|
||||
sel_written_fn_t written, sel_writeerr_fn_t writeerr,
|
||||
void *ctx)
|
||||
sel_written_fn_t written, sel_writeerr_fn_t writeerr,
|
||||
void *ctx)
|
||||
{
|
||||
sel_wfd *wfd = snew(sel_wfd);
|
||||
|
||||
|
@ -177,9 +177,9 @@ sel_wfd *sel_wfd_add(sel *sel, int fd,
|
|||
wfd->next = NULL;
|
||||
wfd->prev = sel->wtail;
|
||||
if (sel->wtail)
|
||||
sel->wtail->next = wfd;
|
||||
sel->wtail->next = wfd;
|
||||
else
|
||||
sel->whead = wfd;
|
||||
sel->whead = wfd;
|
||||
sel->wtail = wfd;
|
||||
wfd->parent = sel;
|
||||
|
||||
|
@ -187,8 +187,8 @@ sel_wfd *sel_wfd_add(sel *sel, int fd,
|
|||
}
|
||||
|
||||
sel_rfd *sel_rfd_add(sel *sel, int fd,
|
||||
sel_readdata_fn_t readdata, sel_readerr_fn_t readerr,
|
||||
void *ctx)
|
||||
sel_readdata_fn_t readdata, sel_readerr_fn_t readerr,
|
||||
void *ctx)
|
||||
{
|
||||
sel_rfd *rfd = snew(sel_rfd);
|
||||
|
||||
|
@ -201,9 +201,9 @@ sel_rfd *sel_rfd_add(sel *sel, int fd,
|
|||
rfd->next = NULL;
|
||||
rfd->prev = sel->rtail;
|
||||
if (sel->rtail)
|
||||
sel->rtail->next = rfd;
|
||||
sel->rtail->next = rfd;
|
||||
else
|
||||
sel->rhead = rfd;
|
||||
sel->rhead = rfd;
|
||||
sel->rtail = rfd;
|
||||
rfd->parent = sel;
|
||||
|
||||
|
@ -242,13 +242,13 @@ int sel_wfd_delete(sel_wfd *wfd)
|
|||
int ret;
|
||||
|
||||
if (wfd->prev)
|
||||
wfd->prev->next = wfd->next;
|
||||
wfd->prev->next = wfd->next;
|
||||
else
|
||||
sel->whead = wfd->next;
|
||||
sel->whead = wfd->next;
|
||||
if (wfd->next)
|
||||
wfd->next->prev = wfd->prev;
|
||||
wfd->next->prev = wfd->prev;
|
||||
else
|
||||
sel->wtail = wfd->prev;
|
||||
sel->wtail = wfd->prev;
|
||||
|
||||
bufchain_clear(&wfd->buf);
|
||||
|
||||
|
@ -263,13 +263,13 @@ int sel_rfd_delete(sel_rfd *rfd)
|
|||
int ret;
|
||||
|
||||
if (rfd->prev)
|
||||
rfd->prev->next = rfd->next;
|
||||
rfd->prev->next = rfd->next;
|
||||
else
|
||||
sel->rhead = rfd->next;
|
||||
sel->rhead = rfd->next;
|
||||
if (rfd->next)
|
||||
rfd->next->prev = rfd->prev;
|
||||
rfd->next->prev = rfd->prev;
|
||||
else
|
||||
sel->rtail = rfd->prev;
|
||||
sel->rtail = rfd->prev;
|
||||
|
||||
ret = rfd->fd;
|
||||
sfree(rfd);
|
||||
|
@ -279,9 +279,9 @@ int sel_rfd_delete(sel_rfd *rfd)
|
|||
void sel_free(sel *sel)
|
||||
{
|
||||
while (sel->whead)
|
||||
sel_wfd_delete(sel->whead);
|
||||
sel_wfd_delete(sel->whead);
|
||||
while (sel->rhead)
|
||||
sel_rfd_delete(sel->rhead);
|
||||
sel_rfd_delete(sel->rhead);
|
||||
sfree(sel);
|
||||
}
|
||||
|
||||
|
@ -306,35 +306,35 @@ int sel_iterate(sel *sel, long timeout)
|
|||
FD_ZERO(&wset);
|
||||
|
||||
for (rfd = sel->rhead; rfd; rfd = rfd->next) {
|
||||
if (rfd->fd >= 0 && !rfd->frozen) {
|
||||
FD_SET(rfd->fd, &rset);
|
||||
if (maxfd < rfd->fd + 1)
|
||||
maxfd = rfd->fd + 1;
|
||||
}
|
||||
if (rfd->fd >= 0 && !rfd->frozen) {
|
||||
FD_SET(rfd->fd, &rset);
|
||||
if (maxfd < rfd->fd + 1)
|
||||
maxfd = rfd->fd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (wfd = sel->whead; wfd; wfd = wfd->next) {
|
||||
if (wfd->fd >= 0 && bufchain_size(&wfd->buf)) {
|
||||
FD_SET(wfd->fd, &wset);
|
||||
if (maxfd < wfd->fd + 1)
|
||||
maxfd = wfd->fd + 1;
|
||||
}
|
||||
if (wfd->fd >= 0 && bufchain_size(&wfd->buf)) {
|
||||
FD_SET(wfd->fd, &wset);
|
||||
if (maxfd < wfd->fd + 1)
|
||||
maxfd = wfd->fd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeout < 0) {
|
||||
ptv = NULL;
|
||||
ptv = NULL;
|
||||
} else {
|
||||
ptv = &tv;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = 1000 * (timeout % 1000);
|
||||
ptv = &tv;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = 1000 * (timeout % 1000);
|
||||
}
|
||||
|
||||
do {
|
||||
ret = select(maxfd, &rset, &wset, NULL, ptv);
|
||||
ret = select(maxfd, &rset, &wset, NULL, ptv);
|
||||
} while (ret < 0 && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
if (ret < 0)
|
||||
return errno;
|
||||
return errno;
|
||||
|
||||
/*
|
||||
* Just in case one of the callbacks destroys an rfd or wfd we
|
||||
|
@ -346,40 +346,40 @@ int sel_iterate(sel *sel, long timeout)
|
|||
* using select in the first place.
|
||||
*/
|
||||
do {
|
||||
for (wfd = sel->whead; wfd; wfd = wfd->next)
|
||||
if (wfd->fd >= 0 && FD_ISSET(wfd->fd, &wset)) {
|
||||
void *data;
|
||||
size_t len;
|
||||
for (wfd = sel->whead; wfd; wfd = wfd->next)
|
||||
if (wfd->fd >= 0 && FD_ISSET(wfd->fd, &wset)) {
|
||||
void *data;
|
||||
size_t len;
|
||||
|
||||
FD_CLR(wfd->fd, &wset);
|
||||
bufchain_prefix(&wfd->buf, &data, &len);
|
||||
ret = write(wfd->fd, data, len);
|
||||
assert(ret != 0);
|
||||
if (ret < 0) {
|
||||
if (wfd->writeerr)
|
||||
wfd->writeerr(wfd, errno);
|
||||
} else {
|
||||
bufchain_consume(&wfd->buf, len);
|
||||
if (wfd->written)
|
||||
wfd->written(wfd, bufchain_size(&wfd->buf));
|
||||
}
|
||||
break;
|
||||
}
|
||||
FD_CLR(wfd->fd, &wset);
|
||||
bufchain_prefix(&wfd->buf, &data, &len);
|
||||
ret = write(wfd->fd, data, len);
|
||||
assert(ret != 0);
|
||||
if (ret < 0) {
|
||||
if (wfd->writeerr)
|
||||
wfd->writeerr(wfd, errno);
|
||||
} else {
|
||||
bufchain_consume(&wfd->buf, len);
|
||||
if (wfd->written)
|
||||
wfd->written(wfd, bufchain_size(&wfd->buf));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (wfd);
|
||||
do {
|
||||
for (rfd = sel->rhead; rfd; rfd = rfd->next)
|
||||
if (rfd->fd >= 0 && !rfd->frozen && FD_ISSET(rfd->fd, &rset)) {
|
||||
FD_CLR(rfd->fd, &rset);
|
||||
ret = read(rfd->fd, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
if (rfd->readerr)
|
||||
rfd->readerr(rfd, errno);
|
||||
} else {
|
||||
if (rfd->readdata)
|
||||
rfd->readdata(rfd, buf, ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (rfd = sel->rhead; rfd; rfd = rfd->next)
|
||||
if (rfd->fd >= 0 && !rfd->frozen && FD_ISSET(rfd->fd, &rset)) {
|
||||
FD_CLR(rfd->fd, &rset);
|
||||
ret = read(rfd->fd, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
if (rfd->readerr)
|
||||
rfd->readerr(rfd, errno);
|
||||
} else {
|
||||
if (rfd->readdata)
|
||||
rfd->readdata(rfd, buf, ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (rfd);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -37,7 +37,7 @@ typedef void (*sel_readerr_fn_t)(sel_rfd *rfd, int error);
|
|||
|
||||
/*
|
||||
* Create a sel structure, which will oversee a select loop.
|
||||
*
|
||||
*
|
||||
* "ctx" is user-supplied data stored in the sel structure; it can
|
||||
* be read and written with sel_get_ctx() and sel_set_ctx().
|
||||
*/
|
||||
|
@ -47,10 +47,10 @@ sel *sel_new(void *ctx);
|
|||
* Add a new fd for writing. Returns a sel_wfd which identifies
|
||||
* that fd in the sel structure, e.g. for putting data into its
|
||||
* output buffer.
|
||||
*
|
||||
*
|
||||
* "ctx" is user-supplied data stored in the sel structure; it can
|
||||
* be read and written with sel_wfd_get_ctx() and sel_wfd_set_ctx().
|
||||
*
|
||||
*
|
||||
* "written" and "writeerr" are called from the event loop when
|
||||
* things happen.
|
||||
*
|
||||
|
@ -59,22 +59,22 @@ sel *sel_new(void *ctx);
|
|||
* using sel_wfd_setfd.
|
||||
*/
|
||||
sel_wfd *sel_wfd_add(sel *sel, int fd,
|
||||
sel_written_fn_t written, sel_writeerr_fn_t writeerr,
|
||||
void *ctx);
|
||||
sel_written_fn_t written, sel_writeerr_fn_t writeerr,
|
||||
void *ctx);
|
||||
|
||||
/*
|
||||
* Add a new fd for reading. Returns a sel_rfd which identifies
|
||||
* that fd in the sel structure.
|
||||
*
|
||||
*
|
||||
* "ctx" is user-supplied data stored in the sel structure; it can
|
||||
* be read and written with sel_rfd_get_ctx() and sel_rfd_set_ctx().
|
||||
*
|
||||
*
|
||||
* "readdata" and "readerr" are called from the event loop when
|
||||
* things happen. "ctx" is passed to both of them.
|
||||
*/
|
||||
sel_rfd *sel_rfd_add(sel *sel, int fd,
|
||||
sel_readdata_fn_t readdata, sel_readerr_fn_t readerr,
|
||||
void *ctx);
|
||||
sel_readdata_fn_t readdata, sel_readerr_fn_t readerr,
|
||||
void *ctx);
|
||||
|
||||
/*
|
||||
* Write data into the output buffer of a wfd. Returns the new
|
||||
|
@ -137,7 +137,7 @@ void sel_rfd_set_ctx(sel_rfd *rfd, void *ctx);
|
|||
* Run one iteration of the sel event loop, calling callbacks as
|
||||
* necessary. Returns zero on success; in the event of a fatal
|
||||
* error, returns the errno value.
|
||||
*
|
||||
*
|
||||
* "timeout" is a value in microseconds to limit the length of the
|
||||
* select call. Less than zero means to wait indefinitely.
|
||||
*/
|
||||
|
|
|
@ -13,27 +13,27 @@
|
|||
#include "malloc.h"
|
||||
#include "pty.h"
|
||||
|
||||
#define IAC 255 /* interpret as command: */
|
||||
#define DONT 254 /* you are not to use option */
|
||||
#define DO 253 /* please, you use option */
|
||||
#define WONT 252 /* I won't use option */
|
||||
#define WILL 251 /* I will use option */
|
||||
#define SB 250 /* interpret as subnegotiation */
|
||||
#define SE 240 /* end sub negotiation */
|
||||
#define IAC 255 /* interpret as command: */
|
||||
#define DONT 254 /* you are not to use option */
|
||||
#define DO 253 /* please, you use option */
|
||||
#define WONT 252 /* I won't use option */
|
||||
#define WILL 251 /* I will use option */
|
||||
#define SB 250 /* interpret as subnegotiation */
|
||||
#define SE 240 /* end sub negotiation */
|
||||
|
||||
#define GA 249 /* you may reverse the line */
|
||||
#define EL 248 /* erase the current line */
|
||||
#define EC 247 /* erase the current character */
|
||||
#define AYT 246 /* are you there */
|
||||
#define AO 245 /* abort output--but let prog finish */
|
||||
#define IP 244 /* interrupt process--permanently */
|
||||
#define BREAK 243 /* break */
|
||||
#define DM 242 /* data mark--for connect. cleaning */
|
||||
#define NOP 241 /* nop */
|
||||
#define EOR 239 /* end of record (transparent mode) */
|
||||
#define ABORT 238 /* Abort process */
|
||||
#define SUSP 237 /* Suspend process */
|
||||
#define xEOF 236 /* End of file: EOF is already used... */
|
||||
#define GA 249 /* you may reverse the line */
|
||||
#define EL 248 /* erase the current line */
|
||||
#define EC 247 /* erase the current character */
|
||||
#define AYT 246 /* are you there */
|
||||
#define AO 245 /* abort output--but let prog finish */
|
||||
#define IP 244 /* interrupt process--permanently */
|
||||
#define BREAK 243 /* break */
|
||||
#define DM 242 /* data mark--for connect. cleaning */
|
||||
#define NOP 241 /* nop */
|
||||
#define EOR 239 /* end of record (transparent mode) */
|
||||
#define ABORT 238 /* Abort process */
|
||||
#define SUSP 237 /* Suspend process */
|
||||
#define xEOF 236 /* End of file: EOF is already used... */
|
||||
|
||||
#define TELOPTS(X) \
|
||||
X(BINARY, 0) /* 8-bit data path */ \
|
||||
|
@ -95,9 +95,9 @@
|
|||
enum { TELOPTS(telnet_enum) dummy=0 };
|
||||
#undef telnet_enum
|
||||
|
||||
#define TELQUAL_IS 0 /* option is... */
|
||||
#define TELQUAL_SEND 1 /* send option */
|
||||
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
|
||||
#define TELQUAL_IS 0 /* option is... */
|
||||
#define TELQUAL_SEND 1 /* send option */
|
||||
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
|
||||
#define BSD_VAR 1
|
||||
#define BSD_VALUE 0
|
||||
#define RFC_VAR 0
|
||||
|
@ -113,9 +113,9 @@ static char *telopt(int opt)
|
|||
{
|
||||
#define telnet_str(x,y) case TELOPT_##x: return #x;
|
||||
switch (opt) {
|
||||
TELOPTS(telnet_str)
|
||||
TELOPTS(telnet_str)
|
||||
default:
|
||||
return "<unknown>";
|
||||
return "<unknown>";
|
||||
}
|
||||
#undef telnet_str
|
||||
}
|
||||
|
@ -123,13 +123,13 @@ static char *telopt(int opt)
|
|||
static void telnet_size(void *handle, int width, int height);
|
||||
|
||||
struct Opt {
|
||||
int send; /* what we initially send */
|
||||
int nsend; /* -ve send if requested to stop it */
|
||||
int ack, nak; /* +ve and -ve acknowledgements */
|
||||
int option; /* the option code */
|
||||
int index; /* index into telnet->opt_states[] */
|
||||
int send; /* what we initially send */
|
||||
int nsend; /* -ve send if requested to stop it */
|
||||
int ack, nak; /* +ve and -ve acknowledgements */
|
||||
int option; /* the option code */
|
||||
int index; /* index into telnet->opt_states[] */
|
||||
enum {
|
||||
REQUESTED, ACTIVE, INACTIVE, REALLY_INACTIVE
|
||||
REQUESTED, ACTIVE, INACTIVE, REALLY_INACTIVE
|
||||
} initial_state;
|
||||
};
|
||||
|
||||
|
@ -174,8 +174,8 @@ struct Telnet {
|
|||
int sb_size;
|
||||
|
||||
enum {
|
||||
TOP_LEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT,
|
||||
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
|
||||
TOP_LEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT,
|
||||
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
|
||||
} state;
|
||||
|
||||
sel_wfd *net, *pty;
|
||||
|
@ -210,8 +210,8 @@ static void send_opt(Telnet *telnet, int cmd, int option)
|
|||
static void deactivate_option(Telnet *telnet, const struct Opt *o)
|
||||
{
|
||||
if (telnet->opt_states[o->index] == REQUESTED ||
|
||||
telnet->opt_states[o->index] == ACTIVE)
|
||||
send_opt(telnet, o->nsend, o->option);
|
||||
telnet->opt_states[o->index] == ACTIVE)
|
||||
send_opt(telnet, o->nsend, o->option);
|
||||
telnet->opt_states[o->index] = REALLY_INACTIVE;
|
||||
}
|
||||
|
||||
|
@ -225,16 +225,16 @@ static void option_side_effects(Telnet *telnet, const struct Opt *o, int enabled
|
|||
static void activate_option(Telnet *telnet, const struct Opt *o)
|
||||
{
|
||||
if (o->option == TELOPT_NEW_ENVIRON ||
|
||||
o->option == TELOPT_OLD_ENVIRON ||
|
||||
o->option == TELOPT_TTYPE) {
|
||||
char buf[6];
|
||||
buf[0] = IAC;
|
||||
buf[1] = SB;
|
||||
buf[2] = o->option;
|
||||
buf[3] = TELQUAL_SEND;
|
||||
buf[4] = IAC;
|
||||
buf[5] = SE;
|
||||
sel_write(telnet->net, buf, 6);
|
||||
o->option == TELOPT_OLD_ENVIRON ||
|
||||
o->option == TELOPT_TTYPE) {
|
||||
char buf[6];
|
||||
buf[0] = IAC;
|
||||
buf[1] = SB;
|
||||
buf[2] = o->option;
|
||||
buf[3] = TELQUAL_SEND;
|
||||
buf[4] = IAC;
|
||||
buf[5] = SE;
|
||||
sel_write(telnet->net, buf, 6);
|
||||
}
|
||||
option_side_effects(telnet, o, 1);
|
||||
}
|
||||
|
@ -242,15 +242,15 @@ static void activate_option(Telnet *telnet, const struct Opt *o)
|
|||
static void done_option(Telnet *telnet, int option)
|
||||
{
|
||||
if (option == TELOPT_OLD_ENVIRON)
|
||||
telnet->old_environ_done = 1;
|
||||
telnet->old_environ_done = 1;
|
||||
else if (option == TELOPT_NEW_ENVIRON)
|
||||
telnet->new_environ_done = 1;
|
||||
telnet->new_environ_done = 1;
|
||||
else if (option == TELOPT_TTYPE)
|
||||
telnet->ttype_done = 1;
|
||||
telnet->ttype_done = 1;
|
||||
|
||||
if (telnet->old_environ_done && telnet->new_environ_done &&
|
||||
telnet->ttype_done) {
|
||||
telnet->shell_ok = 1;
|
||||
telnet->ttype_done) {
|
||||
telnet->shell_ok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,10 +258,10 @@ static void refused_option(Telnet *telnet, const struct Opt *o)
|
|||
{
|
||||
done_option(telnet, o->option);
|
||||
if (o->send == WILL && o->option == TELOPT_NEW_ENVIRON &&
|
||||
telnet->opt_states[o_oenv.index] == INACTIVE) {
|
||||
send_opt(telnet, WILL, TELOPT_OLD_ENVIRON);
|
||||
telnet->opt_states[o_oenv.index] = REQUESTED;
|
||||
telnet->old_environ_done = 0;
|
||||
telnet->opt_states[o_oenv.index] == INACTIVE) {
|
||||
send_opt(telnet, WILL, TELOPT_OLD_ENVIRON);
|
||||
telnet->opt_states[o_oenv.index] = REQUESTED;
|
||||
telnet->old_environ_done = 0;
|
||||
}
|
||||
option_side_effects(telnet, o, 0);
|
||||
}
|
||||
|
@ -271,41 +271,41 @@ static void proc_rec_opt(Telnet *telnet, int cmd, int option)
|
|||
const struct Opt *const *o;
|
||||
|
||||
for (o = opts; *o; o++) {
|
||||
if ((*o)->option == option && (*o)->ack == cmd) {
|
||||
switch (telnet->opt_states[(*o)->index]) {
|
||||
case REQUESTED:
|
||||
telnet->opt_states[(*o)->index] = ACTIVE;
|
||||
activate_option(telnet, *o);
|
||||
break;
|
||||
case ACTIVE:
|
||||
break;
|
||||
case INACTIVE:
|
||||
telnet->opt_states[(*o)->index] = ACTIVE;
|
||||
send_opt(telnet, (*o)->send, option);
|
||||
activate_option(telnet, *o);
|
||||
break;
|
||||
case REALLY_INACTIVE:
|
||||
send_opt(telnet, (*o)->nsend, option);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
} else if ((*o)->option == option && (*o)->nak == cmd) {
|
||||
switch (telnet->opt_states[(*o)->index]) {
|
||||
case REQUESTED:
|
||||
telnet->opt_states[(*o)->index] = INACTIVE;
|
||||
refused_option(telnet, *o);
|
||||
break;
|
||||
case ACTIVE:
|
||||
telnet->opt_states[(*o)->index] = INACTIVE;
|
||||
send_opt(telnet, (*o)->nsend, option);
|
||||
option_side_effects(telnet, *o, 0);
|
||||
break;
|
||||
case INACTIVE:
|
||||
case REALLY_INACTIVE:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((*o)->option == option && (*o)->ack == cmd) {
|
||||
switch (telnet->opt_states[(*o)->index]) {
|
||||
case REQUESTED:
|
||||
telnet->opt_states[(*o)->index] = ACTIVE;
|
||||
activate_option(telnet, *o);
|
||||
break;
|
||||
case ACTIVE:
|
||||
break;
|
||||
case INACTIVE:
|
||||
telnet->opt_states[(*o)->index] = ACTIVE;
|
||||
send_opt(telnet, (*o)->send, option);
|
||||
activate_option(telnet, *o);
|
||||
break;
|
||||
case REALLY_INACTIVE:
|
||||
send_opt(telnet, (*o)->nsend, option);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
} else if ((*o)->option == option && (*o)->nak == cmd) {
|
||||
switch (telnet->opt_states[(*o)->index]) {
|
||||
case REQUESTED:
|
||||
telnet->opt_states[(*o)->index] = INACTIVE;
|
||||
refused_option(telnet, *o);
|
||||
break;
|
||||
case ACTIVE:
|
||||
telnet->opt_states[(*o)->index] = INACTIVE;
|
||||
send_opt(telnet, (*o)->nsend, option);
|
||||
option_side_effects(telnet, *o, 0);
|
||||
break;
|
||||
case INACTIVE:
|
||||
case REALLY_INACTIVE:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If we reach here, the option was one we weren't prepared to
|
||||
|
@ -324,52 +324,52 @@ static void process_subneg(Telnet *telnet)
|
|||
switch (telnet->sb_opt) {
|
||||
case TELOPT_OLD_ENVIRON:
|
||||
case TELOPT_NEW_ENVIRON:
|
||||
if (telnet->sb_buf[0] == TELQUAL_IS) {
|
||||
if (telnet->sb_opt == TELOPT_NEW_ENVIRON) {
|
||||
var = RFC_VAR;
|
||||
value = RFC_VALUE;
|
||||
} else {
|
||||
if (telnet->sb_len > 1 && !(telnet->sb_buf[0] &~ 1)) {
|
||||
var = telnet->sb_buf[0];
|
||||
value = BSD_VAR ^ BSD_VALUE ^ var;
|
||||
} else {
|
||||
var = BSD_VAR;
|
||||
value = BSD_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
n = 1;
|
||||
while (n < telnet->sb_len && telnet->sb_buf[n] == var) {
|
||||
int varpos, varlen, valpos, vallen;
|
||||
char *result;
|
||||
if (telnet->sb_buf[0] == TELQUAL_IS) {
|
||||
if (telnet->sb_opt == TELOPT_NEW_ENVIRON) {
|
||||
var = RFC_VAR;
|
||||
value = RFC_VALUE;
|
||||
} else {
|
||||
if (telnet->sb_len > 1 && !(telnet->sb_buf[0] &~ 1)) {
|
||||
var = telnet->sb_buf[0];
|
||||
value = BSD_VAR ^ BSD_VALUE ^ var;
|
||||
} else {
|
||||
var = BSD_VAR;
|
||||
value = BSD_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
n = 1;
|
||||
while (n < telnet->sb_len && telnet->sb_buf[n] == var) {
|
||||
int varpos, varlen, valpos, vallen;
|
||||
char *result;
|
||||
|
||||
varpos = ++n;
|
||||
while (n < telnet->sb_len && telnet->sb_buf[n] != value)
|
||||
n++;
|
||||
if (n == telnet->sb_len)
|
||||
break;
|
||||
varlen = n - varpos;
|
||||
valpos = ++n;
|
||||
while (n < telnet->sb_len && telnet->sb_buf[n] != var)
|
||||
n++;
|
||||
vallen = n - valpos;
|
||||
varpos = ++n;
|
||||
while (n < telnet->sb_len && telnet->sb_buf[n] != value)
|
||||
n++;
|
||||
if (n == telnet->sb_len)
|
||||
break;
|
||||
varlen = n - varpos;
|
||||
valpos = ++n;
|
||||
while (n < telnet->sb_len && telnet->sb_buf[n] != var)
|
||||
n++;
|
||||
vallen = n - valpos;
|
||||
|
||||
result = snewn(varlen + vallen + 2, char);
|
||||
sprintf(result, "%.*s=%.*s",
|
||||
varlen, telnet->sb_buf+varpos,
|
||||
vallen, telnet->sb_buf+valpos);
|
||||
if (telnet->shdata.nenvvars >= telnet->envvarsize) {
|
||||
telnet->envvarsize = telnet->shdata.nenvvars * 3 / 2 + 16;
|
||||
telnet->shdata.envvars = sresize(telnet->shdata.envvars,
|
||||
telnet->envvarsize, char *);
|
||||
}
|
||||
telnet->shdata.envvars[telnet->shdata.nenvvars++] = result;
|
||||
}
|
||||
done_option(telnet, telnet->sb_opt);
|
||||
break;
|
||||
result = snewn(varlen + vallen + 2, char);
|
||||
sprintf(result, "%.*s=%.*s",
|
||||
varlen, telnet->sb_buf+varpos,
|
||||
vallen, telnet->sb_buf+valpos);
|
||||
if (telnet->shdata.nenvvars >= telnet->envvarsize) {
|
||||
telnet->envvarsize = telnet->shdata.nenvvars * 3 / 2 + 16;
|
||||
telnet->shdata.envvars = sresize(telnet->shdata.envvars,
|
||||
telnet->envvarsize, char *);
|
||||
}
|
||||
telnet->shdata.envvars[telnet->shdata.nenvvars++] = result;
|
||||
}
|
||||
done_option(telnet, telnet->sb_opt);
|
||||
break;
|
||||
case TELOPT_TTYPE:
|
||||
if (telnet->sb_len >= 1 && telnet->sb_buf[0] == TELQUAL_IS) {
|
||||
telnet->shdata.termtype = snewn(5 + telnet->sb_len, char);
|
||||
if (telnet->sb_len >= 1 && telnet->sb_buf[0] == TELQUAL_IS) {
|
||||
telnet->shdata.termtype = snewn(5 + telnet->sb_len, char);
|
||||
strcpy(telnet->shdata.termtype, "TERM=");
|
||||
for (n = 0; n < telnet->sb_len-1; n++) {
|
||||
char c = telnet->sb_buf[n+1];
|
||||
|
@ -377,117 +377,117 @@ static void process_subneg(Telnet *telnet)
|
|||
c = c + 'a' - 'A';
|
||||
telnet->shdata.termtype[n+5] = c;
|
||||
}
|
||||
telnet->shdata.termtype[telnet->sb_len+5-1] = '\0';
|
||||
}
|
||||
done_option(telnet, telnet->sb_opt);
|
||||
break;
|
||||
telnet->shdata.termtype[telnet->sb_len+5-1] = '\0';
|
||||
}
|
||||
done_option(telnet, telnet->sb_opt);
|
||||
break;
|
||||
case TELOPT_NAWS:
|
||||
if (telnet->sb_len == 4) {
|
||||
int w, h;
|
||||
w = (unsigned char)telnet->sb_buf[0];
|
||||
w = (w << 8) | (unsigned char)telnet->sb_buf[1];
|
||||
h = (unsigned char)telnet->sb_buf[2];
|
||||
h = (h << 8) | (unsigned char)telnet->sb_buf[3];
|
||||
pty_resize(w, h);
|
||||
}
|
||||
break;
|
||||
if (telnet->sb_len == 4) {
|
||||
int w, h;
|
||||
w = (unsigned char)telnet->sb_buf[0];
|
||||
w = (w << 8) | (unsigned char)telnet->sb_buf[1];
|
||||
h = (unsigned char)telnet->sb_buf[2];
|
||||
h = (h << 8) | (unsigned char)telnet->sb_buf[3];
|
||||
pty_resize(w, h);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void telnet_from_net(Telnet *telnet, char *buf, int len)
|
||||
{
|
||||
while (len--) {
|
||||
int c = (unsigned char) *buf++;
|
||||
int c = (unsigned char) *buf++;
|
||||
|
||||
switch (telnet->state) {
|
||||
case TOP_LEVEL:
|
||||
case SEENCR:
|
||||
/*
|
||||
* PuTTY sends Telnet's new line sequence (CR LF on
|
||||
* the wire) in response to the return key. We must
|
||||
* therefore treat that as equivalent to CR NUL, and
|
||||
* send CR to the pty.
|
||||
*/
|
||||
if ((c == NUL || c == '\n') && telnet->state == SEENCR)
|
||||
telnet->state = TOP_LEVEL;
|
||||
else if (c == IAC)
|
||||
telnet->state = SEENIAC;
|
||||
else {
|
||||
char cc = c;
|
||||
sel_write(telnet->pty, &cc, 1);
|
||||
switch (telnet->state) {
|
||||
case TOP_LEVEL:
|
||||
case SEENCR:
|
||||
/*
|
||||
* PuTTY sends Telnet's new line sequence (CR LF on
|
||||
* the wire) in response to the return key. We must
|
||||
* therefore treat that as equivalent to CR NUL, and
|
||||
* send CR to the pty.
|
||||
*/
|
||||
if ((c == NUL || c == '\n') && telnet->state == SEENCR)
|
||||
telnet->state = TOP_LEVEL;
|
||||
else if (c == IAC)
|
||||
telnet->state = SEENIAC;
|
||||
else {
|
||||
char cc = c;
|
||||
sel_write(telnet->pty, &cc, 1);
|
||||
|
||||
if (c == CR)
|
||||
telnet->state = SEENCR;
|
||||
else
|
||||
telnet->state = TOP_LEVEL;
|
||||
}
|
||||
break;
|
||||
case SEENIAC:
|
||||
if (c == DO)
|
||||
telnet->state = SEENDO;
|
||||
else if (c == DONT)
|
||||
telnet->state = SEENDONT;
|
||||
else if (c == WILL)
|
||||
telnet->state = SEENWILL;
|
||||
else if (c == WONT)
|
||||
telnet->state = SEENWONT;
|
||||
else if (c == SB)
|
||||
telnet->state = SEENSB;
|
||||
else if (c == DM)
|
||||
telnet->state = TOP_LEVEL;
|
||||
else {
|
||||
/* ignore everything else; print it if it's IAC */
|
||||
if (c == IAC) {
|
||||
char cc = c;
|
||||
sel_write(telnet->pty, &cc, 1);
|
||||
}
|
||||
telnet->state = TOP_LEVEL;
|
||||
}
|
||||
break;
|
||||
case SEENWILL:
|
||||
proc_rec_opt(telnet, WILL, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENWONT:
|
||||
proc_rec_opt(telnet, WONT, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENDO:
|
||||
proc_rec_opt(telnet, DO, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENDONT:
|
||||
proc_rec_opt(telnet, DONT, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENSB:
|
||||
telnet->sb_opt = c;
|
||||
telnet->sb_len = 0;
|
||||
telnet->state = SUBNEGOT;
|
||||
break;
|
||||
case SUBNEGOT:
|
||||
if (c == IAC)
|
||||
telnet->state = SUBNEG_IAC;
|
||||
else {
|
||||
subneg_addchar:
|
||||
if (telnet->sb_len >= telnet->sb_size) {
|
||||
telnet->sb_size += SB_DELTA;
|
||||
telnet->sb_buf = sresize(telnet->sb_buf, telnet->sb_size,
|
||||
unsigned char);
|
||||
}
|
||||
telnet->sb_buf[telnet->sb_len++] = c;
|
||||
telnet->state = SUBNEGOT; /* in case we came here by goto */
|
||||
}
|
||||
break;
|
||||
case SUBNEG_IAC:
|
||||
if (c != SE)
|
||||
goto subneg_addchar; /* yes, it's a hack, I know, but... */
|
||||
else {
|
||||
process_subneg(telnet);
|
||||
telnet->state = TOP_LEVEL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c == CR)
|
||||
telnet->state = SEENCR;
|
||||
else
|
||||
telnet->state = TOP_LEVEL;
|
||||
}
|
||||
break;
|
||||
case SEENIAC:
|
||||
if (c == DO)
|
||||
telnet->state = SEENDO;
|
||||
else if (c == DONT)
|
||||
telnet->state = SEENDONT;
|
||||
else if (c == WILL)
|
||||
telnet->state = SEENWILL;
|
||||
else if (c == WONT)
|
||||
telnet->state = SEENWONT;
|
||||
else if (c == SB)
|
||||
telnet->state = SEENSB;
|
||||
else if (c == DM)
|
||||
telnet->state = TOP_LEVEL;
|
||||
else {
|
||||
/* ignore everything else; print it if it's IAC */
|
||||
if (c == IAC) {
|
||||
char cc = c;
|
||||
sel_write(telnet->pty, &cc, 1);
|
||||
}
|
||||
telnet->state = TOP_LEVEL;
|
||||
}
|
||||
break;
|
||||
case SEENWILL:
|
||||
proc_rec_opt(telnet, WILL, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENWONT:
|
||||
proc_rec_opt(telnet, WONT, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENDO:
|
||||
proc_rec_opt(telnet, DO, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENDONT:
|
||||
proc_rec_opt(telnet, DONT, c);
|
||||
telnet->state = TOP_LEVEL;
|
||||
break;
|
||||
case SEENSB:
|
||||
telnet->sb_opt = c;
|
||||
telnet->sb_len = 0;
|
||||
telnet->state = SUBNEGOT;
|
||||
break;
|
||||
case SUBNEGOT:
|
||||
if (c == IAC)
|
||||
telnet->state = SUBNEG_IAC;
|
||||
else {
|
||||
subneg_addchar:
|
||||
if (telnet->sb_len >= telnet->sb_size) {
|
||||
telnet->sb_size += SB_DELTA;
|
||||
telnet->sb_buf = sresize(telnet->sb_buf, telnet->sb_size,
|
||||
unsigned char);
|
||||
}
|
||||
telnet->sb_buf[telnet->sb_len++] = c;
|
||||
telnet->state = SUBNEGOT; /* in case we came here by goto */
|
||||
}
|
||||
break;
|
||||
case SUBNEG_IAC:
|
||||
if (c != SE)
|
||||
goto subneg_addchar; /* yes, it's a hack, I know, but... */
|
||||
else {
|
||||
process_subneg(telnet);
|
||||
telnet->state = TOP_LEVEL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -509,13 +509,13 @@ Telnet *telnet_new(sel_wfd *net, sel_wfd *pty)
|
|||
* Initialise option states.
|
||||
*/
|
||||
{
|
||||
const struct Opt *const *o;
|
||||
const struct Opt *const *o;
|
||||
|
||||
for (o = opts; *o; o++) {
|
||||
telnet->opt_states[(*o)->index] = (*o)->initial_state;
|
||||
if (telnet->opt_states[(*o)->index] == REQUESTED)
|
||||
send_opt(telnet, (*o)->send, (*o)->option);
|
||||
}
|
||||
for (o = opts; *o; o++) {
|
||||
telnet->opt_states[(*o)->index] = (*o)->initial_state;
|
||||
if (telnet->opt_states[(*o)->index] == REQUESTED)
|
||||
send_opt(telnet, (*o)->send, (*o)->option);
|
||||
}
|
||||
}
|
||||
|
||||
telnet->old_environ_done = 1; /* initially don't want to bother */
|
||||
|
@ -544,22 +544,22 @@ void telnet_from_pty(Telnet *telnet, char *buf, int len)
|
|||
p = (unsigned char *)buf;
|
||||
end = (unsigned char *)(buf + len);
|
||||
while (p < end) {
|
||||
unsigned char *q = p;
|
||||
unsigned char *q = p;
|
||||
|
||||
while (p < end && iswritable(*p))
|
||||
p++;
|
||||
sel_write(telnet->net, q, p - q);
|
||||
while (p < end && iswritable(*p))
|
||||
p++;
|
||||
sel_write(telnet->net, q, p - q);
|
||||
|
||||
while (p < end && !iswritable(*p)) {
|
||||
sel_write(telnet->net, *p == IAC ? iac : cr, 2);
|
||||
p++;
|
||||
}
|
||||
while (p < end && !iswritable(*p)) {
|
||||
sel_write(telnet->net, *p == IAC ? iac : cr, 2);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int telnet_shell_ok(Telnet *telnet, struct shell_data *shdata)
|
||||
{
|
||||
if (telnet->shell_ok)
|
||||
*shdata = telnet->shdata; /* structure copy */
|
||||
*shdata = telnet->shdata; /* structure copy */
|
||||
return telnet->shell_ok;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
typedef struct Telnet Telnet;
|
||||
|
||||
struct shell_data {
|
||||
char **envvars; /* array of "VAR=value" terms */
|
||||
char **envvars; /* array of "VAR=value" terms */
|
||||
int nenvvars;
|
||||
char *termtype;
|
||||
};
|
||||
|
|
|
@ -36,78 +36,78 @@ my %chan_by_id = (); # indexed by 'c%d' or 's%d' for client and server ids
|
|||
my %globalreq = (); # indexed by 'i' or 'o'
|
||||
|
||||
my %packets = (
|
||||
#define SSH2_MSG_DISCONNECT 1 /* 0x1 */
|
||||
#define SSH2_MSG_DISCONNECT 1 /* 0x1 */
|
||||
'SSH2_MSG_DISCONNECT' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($reason, $description, $lang) = &parse("uss", $data);
|
||||
printf "%s\n", &str($description);
|
||||
},
|
||||
#define SSH2_MSG_IGNORE 2 /* 0x2 */
|
||||
#define SSH2_MSG_IGNORE 2 /* 0x2 */
|
||||
'SSH2_MSG_IGNORE' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($str) = &parse("s", $data);
|
||||
printf "(%d bytes)\n", length $str;
|
||||
},
|
||||
#define SSH2_MSG_UNIMPLEMENTED 3 /* 0x3 */
|
||||
#define SSH2_MSG_UNIMPLEMENTED 3 /* 0x3 */
|
||||
'SSH2_MSG_UNIMPLEMENTED' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rseq) = &parse("u", $data);
|
||||
printf "i%d\n", $rseq;
|
||||
},
|
||||
#define SSH2_MSG_DEBUG 4 /* 0x4 */
|
||||
#define SSH2_MSG_DEBUG 4 /* 0x4 */
|
||||
'SSH2_MSG_DEBUG' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($disp, $message, $lang) = &parse("bss", $data);
|
||||
printf "%s\n", &str($message);
|
||||
},
|
||||
#define SSH2_MSG_SERVICE_REQUEST 5 /* 0x5 */
|
||||
#define SSH2_MSG_SERVICE_REQUEST 5 /* 0x5 */
|
||||
'SSH2_MSG_SERVICE_REQUEST' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($service) = &parse("s", $data);
|
||||
printf "%s\n", &str($service);
|
||||
},
|
||||
#define SSH2_MSG_SERVICE_ACCEPT 6 /* 0x6 */
|
||||
#define SSH2_MSG_SERVICE_ACCEPT 6 /* 0x6 */
|
||||
'SSH2_MSG_SERVICE_ACCEPT' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($service) = &parse("s", $data);
|
||||
printf "%s\n", &str($service);
|
||||
},
|
||||
#define SSH2_MSG_KEXINIT 20 /* 0x14 */
|
||||
#define SSH2_MSG_KEXINIT 20 /* 0x14 */
|
||||
'SSH2_MSG_KEXINIT' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_NEWKEYS 21 /* 0x15 */
|
||||
#define SSH2_MSG_NEWKEYS 21 /* 0x15 */
|
||||
'SSH2_MSG_NEWKEYS' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */
|
||||
#define SSH2_MSG_KEXDH_INIT 30 /* 0x1e */
|
||||
'SSH2_MSG_KEXDH_INIT' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_KEXDH_REPLY 31 /* 0x1f */
|
||||
#define SSH2_MSG_KEXDH_REPLY 31 /* 0x1f */
|
||||
'SSH2_MSG_KEXDH_REPLY' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_KEX_DH_GEX_REQUEST 30 /* 0x1e */
|
||||
#define SSH2_MSG_KEX_DH_GEX_REQUEST 30 /* 0x1e */
|
||||
'SSH2_MSG_KEX_DH_GEX_REQUEST' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_KEX_DH_GEX_GROUP 31 /* 0x1f */
|
||||
#define SSH2_MSG_KEX_DH_GEX_GROUP 31 /* 0x1f */
|
||||
'SSH2_MSG_KEX_DH_GEX_GROUP' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_KEX_DH_GEX_INIT 32 /* 0x20 */
|
||||
#define SSH2_MSG_KEX_DH_GEX_INIT 32 /* 0x20 */
|
||||
'SSH2_MSG_KEX_DH_GEX_INIT' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_KEX_DH_GEX_REPLY 33 /* 0x21 */
|
||||
#define SSH2_MSG_KEX_DH_GEX_REPLY 33 /* 0x21 */
|
||||
'SSH2_MSG_KEX_DH_GEX_REPLY' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
|
@ -172,7 +172,7 @@ my %packets = (
|
|||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_REQUEST 50 /* 0x32 */
|
||||
#define SSH2_MSG_USERAUTH_REQUEST 50 /* 0x32 */
|
||||
'SSH2_MSG_USERAUTH_REQUEST' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($user, $service, $method) = &parse("sss", $data);
|
||||
|
@ -187,43 +187,43 @@ my %packets = (
|
|||
}
|
||||
print "$out\n";
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_FAILURE 51 /* 0x33 */
|
||||
#define SSH2_MSG_USERAUTH_FAILURE 51 /* 0x33 */
|
||||
'SSH2_MSG_USERAUTH_FAILURE' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($options) = &parse("s", $data);
|
||||
printf "%s\n", &str($options);
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_SUCCESS 52 /* 0x34 */
|
||||
#define SSH2_MSG_USERAUTH_SUCCESS 52 /* 0x34 */
|
||||
'SSH2_MSG_USERAUTH_SUCCESS' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_BANNER 53 /* 0x35 */
|
||||
#define SSH2_MSG_USERAUTH_BANNER 53 /* 0x35 */
|
||||
'SSH2_MSG_USERAUTH_BANNER' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_PK_OK 60 /* 0x3c */
|
||||
#define SSH2_MSG_USERAUTH_PK_OK 60 /* 0x3c */
|
||||
'SSH2_MSG_USERAUTH_PK_OK' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 /* 0x3c */
|
||||
#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 /* 0x3c */
|
||||
'SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_INFO_REQUEST 60 /* 0x3c */
|
||||
#define SSH2_MSG_USERAUTH_INFO_REQUEST 60 /* 0x3c */
|
||||
'SSH2_MSG_USERAUTH_INFO_REQUEST' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 /* 0x3d */
|
||||
#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 /* 0x3d */
|
||||
'SSH2_MSG_USERAUTH_INFO_RESPONSE' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_GLOBAL_REQUEST 80 /* 0x50 */
|
||||
#define SSH2_MSG_GLOBAL_REQUEST 80 /* 0x50 */
|
||||
'SSH2_MSG_GLOBAL_REQUEST' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($type, $wantreply) = &parse("sb", $data);
|
||||
|
@ -237,7 +237,7 @@ my %packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_REQUEST_SUCCESS 81 /* 0x51 */
|
||||
#define SSH2_MSG_REQUEST_SUCCESS 81 /* 0x51 */
|
||||
'SSH2_MSG_REQUEST_SUCCESS' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my $otherdir = ($direction eq "i" ? "o" : "i");
|
||||
|
@ -253,7 +253,7 @@ my %packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_REQUEST_FAILURE 82 /* 0x52 */
|
||||
#define SSH2_MSG_REQUEST_FAILURE 82 /* 0x52 */
|
||||
'SSH2_MSG_REQUEST_FAILURE' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my $otherdir = ($direction eq "i" ? "o" : "i");
|
||||
|
@ -265,7 +265,7 @@ my %packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_OPEN 90 /* 0x5a */
|
||||
#define SSH2_MSG_CHANNEL_OPEN 90 /* 0x5a */
|
||||
'SSH2_MSG_CHANNEL_OPEN' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($type, $sid, $winsize, $packet) = &parse("suuu", $data);
|
||||
|
@ -275,14 +275,14 @@ my %packets = (
|
|||
# quote the _recipient's_ id of the channel.
|
||||
$sid = ($direction eq "i" ? "s" : "c") . $sid;
|
||||
my $chan = {'id'=>$sid, 'state'=>'halfopen',
|
||||
'i'=>{'win'=>0, 'seq'=>0},
|
||||
'o'=>{'win'=>0, 'seq'=>0}};
|
||||
$chan->{$direction}{'win'} = $winsize;
|
||||
'i'=>{'win'=>0, 'seq'=>0},
|
||||
'o'=>{'win'=>0, 'seq'=>0}};
|
||||
$chan->{$direction}{'win'} = $winsize;
|
||||
push @channels, $chan;
|
||||
my $index = $#channels;
|
||||
$chan_by_id{$sid} = $index;
|
||||
printf "ch%d (%s) %s (--%d)", $index, $chan->{'id'}, $type,
|
||||
$chan->{$direction}{'win'};
|
||||
$chan->{$direction}{'win'};
|
||||
if ($type eq "x11") {
|
||||
my ($addr, $port) = &parse("su", $data);
|
||||
printf " from %s:%s", $addr, $port;
|
||||
|
@ -295,7 +295,7 @@ my %packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 /* 0x5b */
|
||||
#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 /* 0x5b */
|
||||
'SSH2_MSG_CHANNEL_OPEN_CONFIRMATION' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid, $sid, $winsize, $packet) = &parse("uuuu", $data);
|
||||
|
@ -310,11 +310,11 @@ my %packets = (
|
|||
my $chan = $channels[$index];
|
||||
$chan->{'id'} = ($direction eq "i" ? "$rid/$sid" : "$sid/$rid");
|
||||
$chan->{'state'} = 'open';
|
||||
$chan->{$direction}{'win'} = $winsize;
|
||||
$chan->{$direction}{'win'} = $winsize;
|
||||
printf "ch%d (%s) (--%d)\n", $index, $chan->{'id'},
|
||||
$chan->{$direction}{'win'};
|
||||
$chan->{$direction}{'win'};
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 /* 0x5c */
|
||||
#define SSH2_MSG_CHANNEL_OPEN_FAILURE 92 /* 0x5c */
|
||||
'SSH2_MSG_CHANNEL_OPEN_FAILURE' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid, $reason, $desc, $lang) = &parse("uuss", $data);
|
||||
|
@ -328,7 +328,7 @@ my %packets = (
|
|||
$chan->{'state'} = 'rejected';
|
||||
printf "ch%d (%s) %s\n", $index, $chan->{'id'}, &str($reason);
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 /* 0x5d */
|
||||
#define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93 /* 0x5d */
|
||||
'SSH2_MSG_CHANNEL_WINDOW_ADJUST' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid, $bytes) = &parse("uu", $data);
|
||||
|
@ -339,11 +339,11 @@ my %packets = (
|
|||
return;
|
||||
}
|
||||
my $chan = $channels[$index];
|
||||
$chan->{$direction}{'win'} += $bytes;
|
||||
$chan->{$direction}{'win'} += $bytes;
|
||||
printf "ch%d (%s) +%d (--%d)\n", $index, $chan->{'id'}, $bytes,
|
||||
$chan->{$direction}{'win'};
|
||||
$chan->{$direction}{'win'};
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_DATA 94 /* 0x5e */
|
||||
#define SSH2_MSG_CHANNEL_DATA 94 /* 0x5e */
|
||||
'SSH2_MSG_CHANNEL_DATA' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid, $bytes) = &parse("uu", $data);
|
||||
|
@ -354,9 +354,9 @@ my %packets = (
|
|||
return;
|
||||
}
|
||||
my $chan = $channels[$index];
|
||||
$chan->{$direction}{'seq'} += $bytes;
|
||||
$chan->{$direction}{'seq'} += $bytes;
|
||||
printf "ch%d (%s), %s bytes (%d--%d)\n", $index, $chan->{'id'}, $bytes,
|
||||
$chan->{$direction}{'seq'}-$bytes, $chan->{$direction}{'seq'};
|
||||
$chan->{$direction}{'seq'}-$bytes, $chan->{$direction}{'seq'};
|
||||
my @realdata = splice @$data, 0, $bytes;
|
||||
if ($dumpdata) {
|
||||
my $filekey = $direction . "file";
|
||||
|
@ -377,7 +377,7 @@ my %packets = (
|
|||
$chan->{$direction."data"}->($chan, $index, $direction, $rawdata);
|
||||
}
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 /* 0x5f */
|
||||
#define SSH2_MSG_CHANNEL_EXTENDED_DATA 95 /* 0x5f */
|
||||
'SSH2_MSG_CHANNEL_EXTENDED_DATA' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid, $type, $bytes) = &parse("uuu", $data);
|
||||
|
@ -392,7 +392,7 @@ my %packets = (
|
|||
return;
|
||||
}
|
||||
my $chan = $channels[$index];
|
||||
$chan->{$direction}{'seq'} += $bytes;
|
||||
$chan->{$direction}{'seq'} += $bytes;
|
||||
printf "ch%d (%s), type %s, %s bytes (%d--%d)\n", $index,$chan->{'id'},
|
||||
$type, $bytes, $chan->{$direction}{'seq'}-$bytes,
|
||||
$chan->{$direction}{'seq'};
|
||||
|
@ -421,7 +421,7 @@ my %packets = (
|
|||
$chan->{$direction."data"}->($chan, $index, $direction, $rawdata);
|
||||
}
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_EOF 96 /* 0x60 */
|
||||
#define SSH2_MSG_CHANNEL_EOF 96 /* 0x60 */
|
||||
'SSH2_MSG_CHANNEL_EOF' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid) = &parse("uu", $data);
|
||||
|
@ -434,7 +434,7 @@ my %packets = (
|
|||
my $chan = $channels[$index];
|
||||
printf "ch%d (%s)\n", $index, $chan->{'id'};
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_CLOSE 97 /* 0x61 */
|
||||
#define SSH2_MSG_CHANNEL_CLOSE 97 /* 0x61 */
|
||||
'SSH2_MSG_CHANNEL_CLOSE' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid) = &parse("uu", $data);
|
||||
|
@ -454,7 +454,7 @@ my %packets = (
|
|||
}
|
||||
printf "ch%d (%s)\n", $index, $chan->{'id'};
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_REQUEST 98 /* 0x62 */
|
||||
#define SSH2_MSG_CHANNEL_REQUEST 98 /* 0x62 */
|
||||
'SSH2_MSG_CHANNEL_REQUEST' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid, $type, $wantreply) = &parse("usb", $data);
|
||||
|
@ -469,7 +469,7 @@ my %packets = (
|
|||
printf "ch%d (%s) %s (%s)", $index, $chan->{'id'},
|
||||
$type, $wantreply eq "yes" ? "reply" : "noreply";
|
||||
push @{$chan->{'requests_'.$direction}}, [$seq, $type]
|
||||
if $wantreply eq "yes";
|
||||
if $wantreply eq "yes";
|
||||
}
|
||||
if ($type eq "pty-req") {
|
||||
my ($term, $w, $h, $pw, $ph, $modes) = &parse("suuuus", $data);
|
||||
|
@ -506,7 +506,7 @@ my %packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */
|
||||
#define SSH2_MSG_CHANNEL_SUCCESS 99 /* 0x63 */
|
||||
'SSH2_MSG_CHANNEL_SUCCESS' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid) = &parse("uu", $data);
|
||||
|
@ -527,7 +527,7 @@ my %packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH2_MSG_CHANNEL_FAILURE 100 /* 0x64 */
|
||||
#define SSH2_MSG_CHANNEL_FAILURE 100 /* 0x64 */
|
||||
'SSH2_MSG_CHANNEL_FAILURE' => sub {
|
||||
my ($direction, $seq, $data) = @_;
|
||||
my ($rid) = &parse("uu", $data);
|
||||
|
@ -796,19 +796,19 @@ my %verbose_packet_dump_functions = (
|
|||
);
|
||||
|
||||
my %sftp_packets = (
|
||||
#define SSH_FXP_INIT 1 /* 0x1 */
|
||||
#define SSH_FXP_INIT 1 /* 0x1 */
|
||||
0x1 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($ver) = &parse("u", $data);
|
||||
printf "SSH_FXP_INIT %d\n", $ver;
|
||||
},
|
||||
#define SSH_FXP_VERSION 2 /* 0x2 */
|
||||
#define SSH_FXP_VERSION 2 /* 0x2 */
|
||||
0x2 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($ver) = &parse("u", $data);
|
||||
printf "SSH_FXP_VERSION %d\n", $ver;
|
||||
},
|
||||
#define SSH_FXP_OPEN 3 /* 0x3 */
|
||||
#define SSH_FXP_OPEN 3 /* 0x3 */
|
||||
0x3 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path, $pflags) = &parse("usu", $data);
|
||||
|
@ -828,7 +828,7 @@ my %sftp_packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_CLOSE 4 /* 0x4 */
|
||||
#define SSH_FXP_CLOSE 4 /* 0x4 */
|
||||
0x4 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $handle) = &parse("us", $data);
|
||||
|
@ -836,7 +836,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", &stringescape($handle);
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_READ 5 /* 0x5 */
|
||||
#define SSH_FXP_READ 5 /* 0x5 */
|
||||
0x5 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $handle, $offset, $len) = &parse("usUu", $data);
|
||||
|
@ -844,7 +844,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\" %d %d", &stringescape($handle), $offset, $len;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_WRITE 6 /* 0x6 */
|
||||
#define SSH_FXP_WRITE 6 /* 0x6 */
|
||||
0x6 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $handle, $offset, $wdata) = &parse("usUs", $data);
|
||||
|
@ -852,7 +852,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\" %d [%d bytes]", &stringescape($handle), $offset, length $wdata;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_LSTAT 7 /* 0x7 */
|
||||
#define SSH_FXP_LSTAT 7 /* 0x7 */
|
||||
0x7 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -860,7 +860,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $path;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_FSTAT 8 /* 0x8 */
|
||||
#define SSH_FXP_FSTAT 8 /* 0x8 */
|
||||
0x8 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $handle) = &parse("us", $data);
|
||||
|
@ -868,7 +868,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", &stringescape($handle);
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_SETSTAT 9 /* 0x9 */
|
||||
#define SSH_FXP_SETSTAT 9 /* 0x9 */
|
||||
0x9 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -877,7 +877,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\" %s", $path, $attrs;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_FSETSTAT 10 /* 0xa */
|
||||
#define SSH_FXP_FSETSTAT 10 /* 0xa */
|
||||
0xa => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $handle) = &parse("us", $data);
|
||||
|
@ -886,7 +886,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\" %s", &stringescape($handle), $attrs;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_OPENDIR 11 /* 0xb */
|
||||
#define SSH_FXP_OPENDIR 11 /* 0xb */
|
||||
0xb => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -894,7 +894,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $path;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_READDIR 12 /* 0xc */
|
||||
#define SSH_FXP_READDIR 12 /* 0xc */
|
||||
0xc => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $handle) = &parse("us", $data);
|
||||
|
@ -902,7 +902,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", &stringescape($handle);
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_REMOVE 13 /* 0xd */
|
||||
#define SSH_FXP_REMOVE 13 /* 0xd */
|
||||
0xd => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -910,7 +910,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $path;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_MKDIR 14 /* 0xe */
|
||||
#define SSH_FXP_MKDIR 14 /* 0xe */
|
||||
0xe => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -918,7 +918,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $path;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_RMDIR 15 /* 0xf */
|
||||
#define SSH_FXP_RMDIR 15 /* 0xf */
|
||||
0xf => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -926,7 +926,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $path;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_REALPATH 16 /* 0x10 */
|
||||
#define SSH_FXP_REALPATH 16 /* 0x10 */
|
||||
0x10 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -934,7 +934,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $path;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_STAT 17 /* 0x11 */
|
||||
#define SSH_FXP_STAT 17 /* 0x11 */
|
||||
0x11 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $path) = &parse("us", $data);
|
||||
|
@ -942,7 +942,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $path;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_RENAME 18 /* 0x12 */
|
||||
#define SSH_FXP_RENAME 18 /* 0x12 */
|
||||
0x12 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $srcpath, $dstpath) = &parse("uss", $data);
|
||||
|
@ -950,7 +950,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\" \"%s\"", $srcpath, $dstpath;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_STATUS 101 /* 0x65 */
|
||||
#define SSH_FXP_STATUS 101 /* 0x65 */
|
||||
0x65 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $status) = &parse("uu", $data);
|
||||
|
@ -968,7 +968,7 @@ my %sftp_packets = (
|
|||
else { printf "[unknown status %d]", $status; }
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_HANDLE 102 /* 0x66 */
|
||||
#define SSH_FXP_HANDLE 102 /* 0x66 */
|
||||
0x66 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $handle) = &parse("us", $data);
|
||||
|
@ -976,7 +976,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", &stringescape($handle);
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_DATA 103 /* 0x67 */
|
||||
#define SSH_FXP_DATA 103 /* 0x67 */
|
||||
0x67 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $retdata) = &parse("us", $data);
|
||||
|
@ -984,7 +984,7 @@ my %sftp_packets = (
|
|||
printf " [%d bytes]", length $retdata;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_NAME 104 /* 0x68 */
|
||||
#define SSH_FXP_NAME 104 /* 0x68 */
|
||||
0x68 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $count) = &parse("uu", $data);
|
||||
|
@ -996,7 +996,7 @@ my %sftp_packets = (
|
|||
}
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_ATTRS 105 /* 0x69 */
|
||||
#define SSH_FXP_ATTRS 105 /* 0x69 */
|
||||
0x69 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid) = &parse("u", $data);
|
||||
|
@ -1005,7 +1005,7 @@ my %sftp_packets = (
|
|||
printf " %s", $attrs;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_EXTENDED 200 /* 0xc8 */
|
||||
#define SSH_FXP_EXTENDED 200 /* 0xc8 */
|
||||
0xc8 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid, $type) = &parse("us", $data);
|
||||
|
@ -1013,7 +1013,7 @@ my %sftp_packets = (
|
|||
printf " \"%s\"", $type;
|
||||
print "\n";
|
||||
},
|
||||
#define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */
|
||||
#define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */
|
||||
0xc9 => sub {
|
||||
my ($chan, $index, $direction, $id, $data) = @_;
|
||||
my ($reqid) = &parse("u", $data);
|
||||
|
|
232
cproxy.c
232
cproxy.c
|
@ -16,7 +16,7 @@
|
|||
#include "marshal.h"
|
||||
|
||||
static void hmacmd5_chap(const unsigned char *challenge, int challen,
|
||||
const char *passwd, unsigned char *response)
|
||||
const char *passwd, unsigned char *response)
|
||||
{
|
||||
mac_simple(&ssh_hmac_md5, ptrlen_from_asciz(passwd),
|
||||
make_ptrlen(challenge, challen), response);
|
||||
|
@ -42,103 +42,103 @@ int proxy_socks5_handlechap (ProxySocket *p)
|
|||
unsigned char outbuf[20];
|
||||
|
||||
while(p->chap_num_attributes == 0 ||
|
||||
p->chap_num_attributes_processed < p->chap_num_attributes) {
|
||||
if (p->chap_num_attributes == 0 ||
|
||||
p->chap_current_attribute == -1) {
|
||||
/* CHAP normally reads in two bytes, either at the
|
||||
* beginning or for each attribute/value pair. But if
|
||||
* we're waiting for the value's data, we might not want
|
||||
* to read 2 bytes.
|
||||
*/
|
||||
|
||||
if (bufchain_size(&p->pending_input_data) < 2)
|
||||
return 1; /* not got anything yet */
|
||||
p->chap_num_attributes_processed < p->chap_num_attributes) {
|
||||
if (p->chap_num_attributes == 0 ||
|
||||
p->chap_current_attribute == -1) {
|
||||
/* CHAP normally reads in two bytes, either at the
|
||||
* beginning or for each attribute/value pair. But if
|
||||
* we're waiting for the value's data, we might not want
|
||||
* to read 2 bytes.
|
||||
*/
|
||||
|
||||
/* get the response */
|
||||
bufchain_fetch(&p->pending_input_data, data, 2);
|
||||
bufchain_consume(&p->pending_input_data, 2);
|
||||
}
|
||||
if (bufchain_size(&p->pending_input_data) < 2)
|
||||
return 1; /* not got anything yet */
|
||||
|
||||
if (p->chap_num_attributes == 0) {
|
||||
/* If there are no attributes, this is our first msg
|
||||
* with the server, where we negotiate version and
|
||||
* number of attributes
|
||||
*/
|
||||
if (data[0] != 0x01) {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy wants"
|
||||
" a different CHAP version",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (data[1] == 0x00) {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy won't"
|
||||
" negotiate CHAP with us",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
p->chap_num_attributes = data[1];
|
||||
} else {
|
||||
if (p->chap_current_attribute == -1) {
|
||||
/* We have to read in each attribute/value pair -
|
||||
* those we don't understand can be ignored, but
|
||||
* there are a few we'll need to handle.
|
||||
*/
|
||||
p->chap_current_attribute = data[0];
|
||||
p->chap_current_datalen = data[1];
|
||||
}
|
||||
if (bufchain_size(&p->pending_input_data) <
|
||||
p->chap_current_datalen)
|
||||
return 1; /* not got everything yet */
|
||||
/* get the response */
|
||||
bufchain_fetch(&p->pending_input_data, data, 2);
|
||||
bufchain_consume(&p->pending_input_data, 2);
|
||||
}
|
||||
|
||||
/* get the response */
|
||||
bufchain_fetch(&p->pending_input_data, data,
|
||||
p->chap_current_datalen);
|
||||
if (p->chap_num_attributes == 0) {
|
||||
/* If there are no attributes, this is our first msg
|
||||
* with the server, where we negotiate version and
|
||||
* number of attributes
|
||||
*/
|
||||
if (data[0] != 0x01) {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy wants"
|
||||
" a different CHAP version",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (data[1] == 0x00) {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy won't"
|
||||
" negotiate CHAP with us",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
p->chap_num_attributes = data[1];
|
||||
} else {
|
||||
if (p->chap_current_attribute == -1) {
|
||||
/* We have to read in each attribute/value pair -
|
||||
* those we don't understand can be ignored, but
|
||||
* there are a few we'll need to handle.
|
||||
*/
|
||||
p->chap_current_attribute = data[0];
|
||||
p->chap_current_datalen = data[1];
|
||||
}
|
||||
if (bufchain_size(&p->pending_input_data) <
|
||||
p->chap_current_datalen)
|
||||
return 1; /* not got everything yet */
|
||||
|
||||
bufchain_consume(&p->pending_input_data,
|
||||
p->chap_current_datalen);
|
||||
/* get the response */
|
||||
bufchain_fetch(&p->pending_input_data, data,
|
||||
p->chap_current_datalen);
|
||||
|
||||
switch (p->chap_current_attribute) {
|
||||
case 0x00:
|
||||
/* Successful authentication */
|
||||
if (data[0] == 0x00)
|
||||
p->state = 2;
|
||||
else {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy"
|
||||
" refused CHAP authentication",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
outbuf[0] = 0x01; /* Version */
|
||||
outbuf[1] = 0x01; /* One attribute */
|
||||
outbuf[2] = 0x04; /* Response */
|
||||
outbuf[3] = 0x10; /* Length */
|
||||
hmacmd5_chap(data, p->chap_current_datalen,
|
||||
conf_get_str(p->conf, CONF_proxy_password),
|
||||
&outbuf[4]);
|
||||
sk_write(p->sub_socket, outbuf, 20);
|
||||
break;
|
||||
case 0x11:
|
||||
/* Chose a protocol */
|
||||
if (data[0] != 0x85) {
|
||||
plug_closing(p->plug, "Proxy error: Server chose "
|
||||
"CHAP of other than HMAC-MD5 but we "
|
||||
"didn't offer it!",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
p->chap_current_attribute = -1;
|
||||
p->chap_num_attributes_processed++;
|
||||
}
|
||||
if (p->state == 8 &&
|
||||
p->chap_num_attributes_processed >= p->chap_num_attributes) {
|
||||
p->chap_num_attributes = 0;
|
||||
p->chap_num_attributes_processed = 0;
|
||||
p->chap_current_datalen = 0;
|
||||
}
|
||||
bufchain_consume(&p->pending_input_data,
|
||||
p->chap_current_datalen);
|
||||
|
||||
switch (p->chap_current_attribute) {
|
||||
case 0x00:
|
||||
/* Successful authentication */
|
||||
if (data[0] == 0x00)
|
||||
p->state = 2;
|
||||
else {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy"
|
||||
" refused CHAP authentication",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
outbuf[0] = 0x01; /* Version */
|
||||
outbuf[1] = 0x01; /* One attribute */
|
||||
outbuf[2] = 0x04; /* Response */
|
||||
outbuf[3] = 0x10; /* Length */
|
||||
hmacmd5_chap(data, p->chap_current_datalen,
|
||||
conf_get_str(p->conf, CONF_proxy_password),
|
||||
&outbuf[4]);
|
||||
sk_write(p->sub_socket, outbuf, 20);
|
||||
break;
|
||||
case 0x11:
|
||||
/* Chose a protocol */
|
||||
if (data[0] != 0x85) {
|
||||
plug_closing(p->plug, "Proxy error: Server chose "
|
||||
"CHAP of other than HMAC-MD5 but we "
|
||||
"didn't offer it!",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
p->chap_current_attribute = -1;
|
||||
p->chap_num_attributes_processed++;
|
||||
}
|
||||
if (p->state == 8 &&
|
||||
p->chap_num_attributes_processed >= p->chap_num_attributes) {
|
||||
p->chap_num_attributes = 0;
|
||||
p->chap_num_attributes_processed = 0;
|
||||
p->chap_current_datalen = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -148,32 +148,32 @@ int proxy_socks5_selectchap(ProxySocket *p)
|
|||
char *username = conf_get_str(p->conf, CONF_proxy_username);
|
||||
char *password = conf_get_str(p->conf, CONF_proxy_password);
|
||||
if (username[0] || password[0]) {
|
||||
char chapbuf[514];
|
||||
int ulen;
|
||||
chapbuf[0] = '\x01'; /* Version */
|
||||
chapbuf[1] = '\x02'; /* Number of attributes sent */
|
||||
chapbuf[2] = '\x11'; /* First attribute - algorithms list */
|
||||
chapbuf[3] = '\x01'; /* Only one CHAP algorithm */
|
||||
chapbuf[4] = '\x85'; /* ...and it's HMAC-MD5, the core one */
|
||||
chapbuf[5] = '\x02'; /* Second attribute - username */
|
||||
char chapbuf[514];
|
||||
int ulen;
|
||||
chapbuf[0] = '\x01'; /* Version */
|
||||
chapbuf[1] = '\x02'; /* Number of attributes sent */
|
||||
chapbuf[2] = '\x11'; /* First attribute - algorithms list */
|
||||
chapbuf[3] = '\x01'; /* Only one CHAP algorithm */
|
||||
chapbuf[4] = '\x85'; /* ...and it's HMAC-MD5, the core one */
|
||||
chapbuf[5] = '\x02'; /* Second attribute - username */
|
||||
|
||||
ulen = strlen(username);
|
||||
if (ulen > 255) ulen = 255;
|
||||
if (ulen < 1) ulen = 1;
|
||||
ulen = strlen(username);
|
||||
if (ulen > 255) ulen = 255;
|
||||
if (ulen < 1) ulen = 1;
|
||||
|
||||
chapbuf[6] = ulen;
|
||||
memcpy(chapbuf+7, username, ulen);
|
||||
chapbuf[6] = ulen;
|
||||
memcpy(chapbuf+7, username, ulen);
|
||||
|
||||
sk_write(p->sub_socket, chapbuf, ulen + 7);
|
||||
p->chap_num_attributes = 0;
|
||||
p->chap_num_attributes_processed = 0;
|
||||
p->chap_current_attribute = -1;
|
||||
p->chap_current_datalen = 0;
|
||||
sk_write(p->sub_socket, chapbuf, ulen + 7);
|
||||
p->chap_num_attributes = 0;
|
||||
p->chap_num_attributes_processed = 0;
|
||||
p->chap_current_attribute = -1;
|
||||
p->chap_current_datalen = 0;
|
||||
|
||||
p->state = 8;
|
||||
} else
|
||||
plug_closing(p->plug, "Proxy error: Server chose "
|
||||
"CHAP authentication but we didn't offer it!",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
p->state = 8;
|
||||
} else
|
||||
plug_closing(p->plug, "Proxy error: Server chose "
|
||||
"CHAP authentication but we didn't offer it!",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
|
166
dialog.c
166
dialog.c
|
@ -17,8 +17,8 @@ int ctrl_path_elements(const char *path)
|
|||
{
|
||||
int i = 1;
|
||||
while (*path) {
|
||||
if (*path == '/') i++;
|
||||
path++;
|
||||
if (*path == '/') i++;
|
||||
path++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
@ -29,14 +29,14 @@ int ctrl_path_compare(const char *p1, const char *p2)
|
|||
{
|
||||
int i = 0;
|
||||
while (*p1 || *p2) {
|
||||
if ((*p1 == '/' || *p1 == '\0') &&
|
||||
(*p2 == '/' || *p2 == '\0'))
|
||||
i++; /* a whole element matches, ooh */
|
||||
if (*p1 != *p2)
|
||||
return i; /* mismatch */
|
||||
p1++, p2++;
|
||||
if ((*p1 == '/' || *p1 == '\0') &&
|
||||
(*p2 == '/' || *p2 == '\0'))
|
||||
i++; /* a whole element matches, ooh */
|
||||
if (*p1 != *p2)
|
||||
return i; /* mismatch */
|
||||
p1++, p2++;
|
||||
}
|
||||
return INT_MAX; /* exact match */
|
||||
return INT_MAX; /* exact match */
|
||||
}
|
||||
|
||||
struct controlbox *ctrl_new_box(void)
|
||||
|
@ -57,10 +57,10 @@ void ctrl_free_box(struct controlbox *b)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < b->nctrlsets; i++) {
|
||||
ctrl_free_set(b->ctrlsets[i]);
|
||||
ctrl_free_set(b->ctrlsets[i]);
|
||||
}
|
||||
for (i = 0; i < b->nfrees; i++)
|
||||
b->freefuncs[i](b->frees[i]);
|
||||
b->freefuncs[i](b->frees[i]);
|
||||
sfree(b->ctrlsets);
|
||||
sfree(b->frees);
|
||||
sfree(b->freefuncs);
|
||||
|
@ -75,7 +75,7 @@ void ctrl_free_set(struct controlset *s)
|
|||
sfree(s->boxname);
|
||||
sfree(s->boxtitle);
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
ctrl_free(s->ctrls[i]);
|
||||
ctrl_free(s->ctrls[i]);
|
||||
}
|
||||
sfree(s->ctrls);
|
||||
sfree(s);
|
||||
|
@ -92,19 +92,19 @@ static int ctrl_find_set(struct controlbox *b, const char *path, bool start)
|
|||
|
||||
last = 0;
|
||||
for (i = 0; i < b->nctrlsets; i++) {
|
||||
thisone = ctrl_path_compare(path, b->ctrlsets[i]->pathname);
|
||||
/*
|
||||
* If `start' is true and there exists a controlset with
|
||||
* exactly the path we've been given, we should return the
|
||||
* index of the first such controlset we find. Otherwise,
|
||||
* we should return the index of the first entry in which
|
||||
* _fewer_ path elements match than they did last time.
|
||||
*/
|
||||
if ((start && thisone == INT_MAX) || thisone < last)
|
||||
return i;
|
||||
last = thisone;
|
||||
thisone = ctrl_path_compare(path, b->ctrlsets[i]->pathname);
|
||||
/*
|
||||
* If `start' is true and there exists a controlset with
|
||||
* exactly the path we've been given, we should return the
|
||||
* index of the first such controlset we find. Otherwise,
|
||||
* we should return the index of the first entry in which
|
||||
* _fewer_ path elements match than they did last time.
|
||||
*/
|
||||
if ((start && thisone == INT_MAX) || thisone < last)
|
||||
return i;
|
||||
last = thisone;
|
||||
}
|
||||
return b->nctrlsets; /* insert at end */
|
||||
return b->nctrlsets; /* insert at end */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -115,33 +115,33 @@ static int ctrl_find_set(struct controlbox *b, const char *path, bool start)
|
|||
int ctrl_find_path(struct controlbox *b, const char *path, int index)
|
||||
{
|
||||
if (index < 0)
|
||||
index = ctrl_find_set(b, path, true);
|
||||
index = ctrl_find_set(b, path, true);
|
||||
else
|
||||
index++;
|
||||
index++;
|
||||
|
||||
if (index < b->nctrlsets && !strcmp(path, b->ctrlsets[index]->pathname))
|
||||
return index;
|
||||
return index;
|
||||
else
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set up a panel title. */
|
||||
struct controlset *ctrl_settitle(struct controlbox *b,
|
||||
const char *path, const char *title)
|
||||
const char *path, const char *title)
|
||||
{
|
||||
|
||||
|
||||
struct controlset *s = snew(struct controlset);
|
||||
int index = ctrl_find_set(b, path, true);
|
||||
s->pathname = dupstr(path);
|
||||
s->boxname = NULL;
|
||||
s->boxtitle = dupstr(title);
|
||||
s->ncontrols = s->ctrlsize = 0;
|
||||
s->ncolumns = 0; /* this is a title! */
|
||||
s->ncolumns = 0; /* this is a title! */
|
||||
s->ctrls = NULL;
|
||||
sgrowarray(b->ctrlsets, b->ctrlsetsize, b->nctrlsets);
|
||||
if (index < b->nctrlsets)
|
||||
memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
|
||||
(b->nctrlsets-index) * sizeof(*b->ctrlsets));
|
||||
memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
|
||||
(b->nctrlsets-index) * sizeof(*b->ctrlsets));
|
||||
b->ctrlsets[index] = s;
|
||||
b->nctrlsets++;
|
||||
return s;
|
||||
|
@ -154,11 +154,11 @@ struct controlset *ctrl_getset(struct controlbox *b, const char *path,
|
|||
struct controlset *s;
|
||||
int index = ctrl_find_set(b, path, true);
|
||||
while (index < b->nctrlsets &&
|
||||
!strcmp(b->ctrlsets[index]->pathname, path)) {
|
||||
if (b->ctrlsets[index]->boxname &&
|
||||
!strcmp(b->ctrlsets[index]->boxname, name))
|
||||
return b->ctrlsets[index];
|
||||
index++;
|
||||
!strcmp(b->ctrlsets[index]->pathname, path)) {
|
||||
if (b->ctrlsets[index]->boxname &&
|
||||
!strcmp(b->ctrlsets[index]->boxname, name))
|
||||
return b->ctrlsets[index];
|
||||
index++;
|
||||
}
|
||||
s = snew(struct controlset);
|
||||
s->pathname = dupstr(path);
|
||||
|
@ -169,8 +169,8 @@ struct controlset *ctrl_getset(struct controlbox *b, const char *path,
|
|||
s->ctrls = NULL;
|
||||
sgrowarray(b->ctrlsets, b->ctrlsetsize, b->nctrlsets);
|
||||
if (index < b->nctrlsets)
|
||||
memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
|
||||
(b->nctrlsets-index) * sizeof(*b->ctrlsets));
|
||||
memmove(&b->ctrlsets[index+1], &b->ctrlsets[index],
|
||||
(b->nctrlsets-index) * sizeof(*b->ctrlsets));
|
||||
b->ctrlsets[index] = s;
|
||||
b->nctrlsets++;
|
||||
return s;
|
||||
|
@ -205,8 +205,8 @@ void *ctrl_alloc(struct controlbox *b, size_t size)
|
|||
}
|
||||
|
||||
static union control *ctrl_new(struct controlset *s, int type,
|
||||
intorptr helpctx, handler_fn handler,
|
||||
intorptr context)
|
||||
intorptr helpctx, handler_fn handler,
|
||||
intorptr context)
|
||||
{
|
||||
union control *c = snew(union control);
|
||||
sgrowarray(s->ctrls, s->ctrlsize, s->ncontrols);
|
||||
|
@ -232,23 +232,23 @@ union control *ctrl_columns(struct controlset *s, int ncolumns, ...)
|
|||
c->columns.ncols = ncolumns;
|
||||
s->ncolumns = ncolumns;
|
||||
if (ncolumns == 1) {
|
||||
c->columns.percentages = NULL;
|
||||
c->columns.percentages = NULL;
|
||||
} else {
|
||||
va_list ap;
|
||||
int i;
|
||||
c->columns.percentages = snewn(ncolumns, int);
|
||||
va_start(ap, ncolumns);
|
||||
for (i = 0; i < ncolumns; i++)
|
||||
c->columns.percentages[i] = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
va_list ap;
|
||||
int i;
|
||||
c->columns.percentages = snewn(ncolumns, int);
|
||||
va_start(ap, ncolumns);
|
||||
for (i = 0; i < ncolumns; i++)
|
||||
c->columns.percentages[i] = va_arg(ap, int);
|
||||
va_end(ap);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
union control *ctrl_editbox(struct controlset *s, const char *label,
|
||||
char shortcut, int percentage,
|
||||
intorptr helpctx, handler_fn handler,
|
||||
intorptr context, intorptr context2)
|
||||
intorptr helpctx, handler_fn handler,
|
||||
intorptr context, intorptr context2)
|
||||
{
|
||||
union control *c = ctrl_new(s, CTRL_EDITBOX, helpctx, handler, context);
|
||||
c->editbox.label = label ? dupstr(label) : NULL;
|
||||
|
@ -262,8 +262,8 @@ union control *ctrl_editbox(struct controlset *s, const char *label,
|
|||
|
||||
union control *ctrl_combobox(struct controlset *s, const char *label,
|
||||
char shortcut, int percentage,
|
||||
intorptr helpctx, handler_fn handler,
|
||||
intorptr context, intorptr context2)
|
||||
intorptr helpctx, handler_fn handler,
|
||||
intorptr context, intorptr context2)
|
||||
{
|
||||
union control *c = ctrl_new(s, CTRL_EDITBOX, helpctx, handler, context);
|
||||
c->editbox.label = label ? dupstr(label) : NULL;
|
||||
|
@ -282,8 +282,8 @@ union control *ctrl_combobox(struct controlset *s, const char *label,
|
|||
* is NO_SHORTCUT.
|
||||
*/
|
||||
union control *ctrl_radiobuttons(struct controlset *s, const char *label,
|
||||
char shortcut, int ncolumns, intorptr helpctx,
|
||||
handler_fn handler, intorptr context, ...)
|
||||
char shortcut, int ncolumns, intorptr helpctx,
|
||||
handler_fn handler, intorptr context, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
|
@ -298,17 +298,17 @@ union control *ctrl_radiobuttons(struct controlset *s, const char *label,
|
|||
va_start(ap, context);
|
||||
i = 0;
|
||||
while (va_arg(ap, char *) != NULL) {
|
||||
i++;
|
||||
if (c->radio.shortcut == NO_SHORTCUT)
|
||||
(void)va_arg(ap, int); /* char promotes to int in arg lists */
|
||||
(void)va_arg(ap, intorptr);
|
||||
i++;
|
||||
if (c->radio.shortcut == NO_SHORTCUT)
|
||||
(void)va_arg(ap, int); /* char promotes to int in arg lists */
|
||||
(void)va_arg(ap, intorptr);
|
||||
}
|
||||
va_end(ap);
|
||||
c->radio.nbuttons = i;
|
||||
if (c->radio.shortcut == NO_SHORTCUT)
|
||||
c->radio.shortcuts = snewn(c->radio.nbuttons, char);
|
||||
c->radio.shortcuts = snewn(c->radio.nbuttons, char);
|
||||
else
|
||||
c->radio.shortcuts = NULL;
|
||||
c->radio.shortcuts = NULL;
|
||||
c->radio.buttons = snewn(c->radio.nbuttons, char *);
|
||||
c->radio.buttondata = snewn(c->radio.nbuttons, intorptr);
|
||||
/*
|
||||
|
@ -317,11 +317,11 @@ union control *ctrl_radiobuttons(struct controlset *s, const char *label,
|
|||
*/
|
||||
va_start(ap, context);
|
||||
for (i = 0; i < c->radio.nbuttons; i++) {
|
||||
c->radio.buttons[i] = dupstr(va_arg(ap, char *));
|
||||
if (c->radio.shortcut == NO_SHORTCUT)
|
||||
c->radio.shortcuts[i] = va_arg(ap, int);
|
||||
/* char promotes to int in arg lists */
|
||||
c->radio.buttondata[i] = va_arg(ap, intorptr);
|
||||
c->radio.buttons[i] = dupstr(va_arg(ap, char *));
|
||||
if (c->radio.shortcut == NO_SHORTCUT)
|
||||
c->radio.shortcuts[i] = va_arg(ap, int);
|
||||
/* char promotes to int in arg lists */
|
||||
c->radio.buttondata[i] = va_arg(ap, intorptr);
|
||||
}
|
||||
va_end(ap);
|
||||
return c;
|
||||
|
@ -346,7 +346,7 @@ union control *ctrl_listbox(struct controlset *s, const char *label,
|
|||
union control *c = ctrl_new(s, CTRL_LISTBOX, helpctx, handler, context);
|
||||
c->listbox.label = label ? dupstr(label) : NULL;
|
||||
c->listbox.shortcut = shortcut;
|
||||
c->listbox.height = 5; /* *shrug* a plausible default */
|
||||
c->listbox.height = 5; /* *shrug* a plausible default */
|
||||
c->listbox.draglist = false;
|
||||
c->listbox.multisel = 0;
|
||||
c->listbox.percentwidth = 100;
|
||||
|
@ -358,12 +358,12 @@ union control *ctrl_listbox(struct controlset *s, const char *label,
|
|||
|
||||
union control *ctrl_droplist(struct controlset *s, const char *label,
|
||||
char shortcut, int percentage, intorptr helpctx,
|
||||
handler_fn handler, intorptr context)
|
||||
handler_fn handler, intorptr context)
|
||||
{
|
||||
union control *c = ctrl_new(s, CTRL_LISTBOX, helpctx, handler, context);
|
||||
c->listbox.label = label ? dupstr(label) : NULL;
|
||||
c->listbox.shortcut = shortcut;
|
||||
c->listbox.height = 0; /* means it's a drop-down list */
|
||||
c->listbox.height = 0; /* means it's a drop-down list */
|
||||
c->listbox.draglist = false;
|
||||
c->listbox.multisel = 0;
|
||||
c->listbox.percentwidth = percentage;
|
||||
|
@ -380,7 +380,7 @@ union control *ctrl_draglist(struct controlset *s, const char *label,
|
|||
union control *c = ctrl_new(s, CTRL_LISTBOX, helpctx, handler, context);
|
||||
c->listbox.label = label ? dupstr(label) : NULL;
|
||||
c->listbox.shortcut = shortcut;
|
||||
c->listbox.height = 5; /* *shrug* a plausible default */
|
||||
c->listbox.height = 5; /* *shrug* a plausible default */
|
||||
c->listbox.draglist = true;
|
||||
c->listbox.multisel = 0;
|
||||
c->listbox.percentwidth = 100;
|
||||
|
@ -446,21 +446,21 @@ void ctrl_free(union control *ctrl)
|
|||
sfree(ctrl->generic.label);
|
||||
switch (ctrl->generic.type) {
|
||||
case CTRL_RADIO:
|
||||
for (i = 0; i < ctrl->radio.nbuttons; i++)
|
||||
sfree(ctrl->radio.buttons[i]);
|
||||
sfree(ctrl->radio.buttons);
|
||||
sfree(ctrl->radio.shortcuts);
|
||||
sfree(ctrl->radio.buttondata);
|
||||
break;
|
||||
for (i = 0; i < ctrl->radio.nbuttons; i++)
|
||||
sfree(ctrl->radio.buttons[i]);
|
||||
sfree(ctrl->radio.buttons);
|
||||
sfree(ctrl->radio.shortcuts);
|
||||
sfree(ctrl->radio.buttondata);
|
||||
break;
|
||||
case CTRL_COLUMNS:
|
||||
sfree(ctrl->columns.percentages);
|
||||
break;
|
||||
sfree(ctrl->columns.percentages);
|
||||
break;
|
||||
case CTRL_LISTBOX:
|
||||
sfree(ctrl->listbox.percentages);
|
||||
break;
|
||||
sfree(ctrl->listbox.percentages);
|
||||
break;
|
||||
case CTRL_FILESELECT:
|
||||
sfree(ctrl->fileselect.title);
|
||||
break;
|
||||
sfree(ctrl->fileselect.title);
|
||||
break;
|
||||
}
|
||||
sfree(ctrl);
|
||||
}
|
||||
|
|
608
dialog.h
608
dialog.h
|
@ -5,7 +5,7 @@
|
|||
/*
|
||||
* This is the big union which defines a single control, of any
|
||||
* type.
|
||||
*
|
||||
*
|
||||
* General principles:
|
||||
* - _All_ pointers in this structure are expected to point to
|
||||
* dynamically allocated things, unless otherwise indicated.
|
||||
|
@ -20,16 +20,16 @@
|
|||
#define NO_SHORTCUT '\0'
|
||||
|
||||
enum {
|
||||
CTRL_TEXT, /* just a static line of text */
|
||||
CTRL_EDITBOX, /* label plus edit box */
|
||||
CTRL_RADIO, /* label plus radio buttons */
|
||||
CTRL_CHECKBOX, /* checkbox (contains own label) */
|
||||
CTRL_BUTTON, /* simple push button (no label) */
|
||||
CTRL_LISTBOX, /* label plus list box */
|
||||
CTRL_COLUMNS, /* divide window into columns */
|
||||
CTRL_FILESELECT, /* label plus filename selector */
|
||||
CTRL_FONTSELECT, /* label plus font selector */
|
||||
CTRL_TABDELAY /* see `tabdelay' below */
|
||||
CTRL_TEXT, /* just a static line of text */
|
||||
CTRL_EDITBOX, /* label plus edit box */
|
||||
CTRL_RADIO, /* label plus radio buttons */
|
||||
CTRL_CHECKBOX, /* checkbox (contains own label) */
|
||||
CTRL_BUTTON, /* simple push button (no label) */
|
||||
CTRL_LISTBOX, /* label plus list box */
|
||||
CTRL_COLUMNS, /* divide window into columns */
|
||||
CTRL_FILESELECT, /* label plus filename selector */
|
||||
CTRL_FONTSELECT, /* label plus font selector */
|
||||
CTRL_TABDELAY /* see `tabdelay' below */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -37,7 +37,7 @@ enum {
|
|||
* since the user might reasonably want to store either an integer
|
||||
* or a void * pointer. Here I define a union, and two convenience
|
||||
* functions to create that union from actual integers or pointers.
|
||||
*
|
||||
*
|
||||
* The convenience functions are declared as inline if possible.
|
||||
* Otherwise, they're declared here and defined when this header is
|
||||
* included with DEFINE_INTORPTR_FNS defined. This is a total pain,
|
||||
|
@ -65,7 +65,7 @@ PREFIX intorptr P(void *p) { intorptr ret; ret.p = p; return ret; }
|
|||
* Each control has an `int' field specifying which columns it
|
||||
* occupies in a multi-column part of the dialog box. These macros
|
||||
* pack and unpack that field.
|
||||
*
|
||||
*
|
||||
* If a control belongs in exactly one column, just specifying the
|
||||
* column number is perfectly adequate.
|
||||
*/
|
||||
|
@ -104,15 +104,15 @@ enum {
|
|||
EVENT_CALLBACK
|
||||
};
|
||||
typedef void (*handler_fn)(union control *ctrl, dlgparam *dp,
|
||||
void *data, int event);
|
||||
void *data, int event);
|
||||
|
||||
#define STANDARD_PREFIX \
|
||||
int type; \
|
||||
char *label; \
|
||||
bool tabdelay; \
|
||||
int column; \
|
||||
int type; \
|
||||
char *label; \
|
||||
bool tabdelay; \
|
||||
int column; \
|
||||
handler_fn handler; \
|
||||
intorptr context; \
|
||||
intorptr context; \
|
||||
intorptr helpctx
|
||||
|
||||
union control {
|
||||
|
@ -122,223 +122,223 @@ union control {
|
|||
* to access through any one of them.
|
||||
*/
|
||||
struct {
|
||||
int type;
|
||||
/*
|
||||
* Every control except CTRL_COLUMNS has _some_ sort of
|
||||
* label. By putting it in the `generic' union as well as
|
||||
* everywhere else, we avoid having to have an irritating
|
||||
* switch statement when we go through and deallocate all
|
||||
* the memory in a config-box structure.
|
||||
*
|
||||
* Yes, this does mean that any non-NULL value in this
|
||||
* field is expected to be dynamically allocated and
|
||||
* freeable.
|
||||
*
|
||||
* For CTRL_COLUMNS, this field MUST be NULL.
|
||||
*/
|
||||
char *label;
|
||||
/*
|
||||
* If `tabdelay' is non-zero, it indicates that this
|
||||
* particular control should not yet appear in the tab
|
||||
* order. A subsequent CTRL_TABDELAY entry will place it.
|
||||
*/
|
||||
bool tabdelay;
|
||||
/*
|
||||
* Indicate which column(s) this control occupies. This can
|
||||
* be unpacked into starting column and column span by the
|
||||
* COLUMN macros above.
|
||||
*/
|
||||
int column;
|
||||
/*
|
||||
* Most controls need to provide a function which gets
|
||||
* called when that control's setting is changed, or when
|
||||
* the control's setting needs initialising.
|
||||
*
|
||||
* The `data' parameter points to the writable data being
|
||||
* modified as a result of the configuration activity; for
|
||||
* example, the PuTTY `Conf' structure, although not
|
||||
* necessarily.
|
||||
*
|
||||
* The `dlg' parameter is passed back to the platform-
|
||||
* specific routines to read and write the actual control
|
||||
* state.
|
||||
*/
|
||||
handler_fn handler;
|
||||
/*
|
||||
* Almost all of the above functions will find it useful to
|
||||
* be able to store a piece of `void *' or `int' data.
|
||||
*/
|
||||
intorptr context;
|
||||
/*
|
||||
* For any control, we also allow the storage of a piece of
|
||||
* data for use by context-sensitive help. For example, on
|
||||
* Windows you can click the magic question mark and then
|
||||
* click a control, and help for that control should spring
|
||||
* up. Hence, here is a slot in which to store per-control
|
||||
* data that a particular platform-specific driver can use
|
||||
* to ensure it brings up the right piece of help text.
|
||||
*/
|
||||
intorptr helpctx;
|
||||
int type;
|
||||
/*
|
||||
* Every control except CTRL_COLUMNS has _some_ sort of
|
||||
* label. By putting it in the `generic' union as well as
|
||||
* everywhere else, we avoid having to have an irritating
|
||||
* switch statement when we go through and deallocate all
|
||||
* the memory in a config-box structure.
|
||||
*
|
||||
* Yes, this does mean that any non-NULL value in this
|
||||
* field is expected to be dynamically allocated and
|
||||
* freeable.
|
||||
*
|
||||
* For CTRL_COLUMNS, this field MUST be NULL.
|
||||
*/
|
||||
char *label;
|
||||
/*
|
||||
* If `tabdelay' is non-zero, it indicates that this
|
||||
* particular control should not yet appear in the tab
|
||||
* order. A subsequent CTRL_TABDELAY entry will place it.
|
||||
*/
|
||||
bool tabdelay;
|
||||
/*
|
||||
* Indicate which column(s) this control occupies. This can
|
||||
* be unpacked into starting column and column span by the
|
||||
* COLUMN macros above.
|
||||
*/
|
||||
int column;
|
||||
/*
|
||||
* Most controls need to provide a function which gets
|
||||
* called when that control's setting is changed, or when
|
||||
* the control's setting needs initialising.
|
||||
*
|
||||
* The `data' parameter points to the writable data being
|
||||
* modified as a result of the configuration activity; for
|
||||
* example, the PuTTY `Conf' structure, although not
|
||||
* necessarily.
|
||||
*
|
||||
* The `dlg' parameter is passed back to the platform-
|
||||
* specific routines to read and write the actual control
|
||||
* state.
|
||||
*/
|
||||
handler_fn handler;
|
||||
/*
|
||||
* Almost all of the above functions will find it useful to
|
||||
* be able to store a piece of `void *' or `int' data.
|
||||
*/
|
||||
intorptr context;
|
||||
/*
|
||||
* For any control, we also allow the storage of a piece of
|
||||
* data for use by context-sensitive help. For example, on
|
||||
* Windows you can click the magic question mark and then
|
||||
* click a control, and help for that control should spring
|
||||
* up. Hence, here is a slot in which to store per-control
|
||||
* data that a particular platform-specific driver can use
|
||||
* to ensure it brings up the right piece of help text.
|
||||
*/
|
||||
intorptr helpctx;
|
||||
} generic;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
union control *ctrl;
|
||||
STANDARD_PREFIX;
|
||||
union control *ctrl;
|
||||
} tabdelay;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
STANDARD_PREFIX;
|
||||
} text;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
char shortcut; /* keyboard shortcut */
|
||||
/*
|
||||
* Percentage of the dialog-box width used by the edit box.
|
||||
* If this is set to 100, the label is on its own line;
|
||||
* otherwise the label is on the same line as the box
|
||||
* itself.
|
||||
*/
|
||||
int percentwidth;
|
||||
bool password; /* details of input are hidden */
|
||||
/*
|
||||
* A special case of the edit box is the combo box, which
|
||||
* has a drop-down list built in. (Note that a _non_-
|
||||
* editable drop-down list is done as a special case of a
|
||||
* list box.)
|
||||
*
|
||||
* Don't try setting has_list and password on the same
|
||||
* control; front ends are not required to support that
|
||||
* combination.
|
||||
*/
|
||||
bool has_list;
|
||||
/*
|
||||
* Edit boxes tend to need two items of context, so here's
|
||||
* a spare.
|
||||
*/
|
||||
intorptr context2;
|
||||
STANDARD_PREFIX;
|
||||
char shortcut; /* keyboard shortcut */
|
||||
/*
|
||||
* Percentage of the dialog-box width used by the edit box.
|
||||
* If this is set to 100, the label is on its own line;
|
||||
* otherwise the label is on the same line as the box
|
||||
* itself.
|
||||
*/
|
||||
int percentwidth;
|
||||
bool password; /* details of input are hidden */
|
||||
/*
|
||||
* A special case of the edit box is the combo box, which
|
||||
* has a drop-down list built in. (Note that a _non_-
|
||||
* editable drop-down list is done as a special case of a
|
||||
* list box.)
|
||||
*
|
||||
* Don't try setting has_list and password on the same
|
||||
* control; front ends are not required to support that
|
||||
* combination.
|
||||
*/
|
||||
bool has_list;
|
||||
/*
|
||||
* Edit boxes tend to need two items of context, so here's
|
||||
* a spare.
|
||||
*/
|
||||
intorptr context2;
|
||||
} editbox;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
/*
|
||||
* `shortcut' here is a single keyboard shortcut which is
|
||||
* expected to select the whole group of radio buttons. It
|
||||
* can be NO_SHORTCUT if required, and there is also a way
|
||||
* to place individual shortcuts on each button; see below.
|
||||
*/
|
||||
char shortcut;
|
||||
/*
|
||||
* There are separate fields for `ncolumns' and `nbuttons'
|
||||
* for several reasons.
|
||||
*
|
||||
* Firstly, we sometimes want the last of a set of buttons
|
||||
* to have a longer label than the rest; we achieve this by
|
||||
* setting `ncolumns' higher than `nbuttons', and the
|
||||
* layout code is expected to understand that the final
|
||||
* button should be given all the remaining space on the
|
||||
* line. This sounds like a ludicrously specific special
|
||||
* case (if we're doing this sort of thing, why not have
|
||||
* the general ability to have a particular button span
|
||||
* more than one column whether it's the last one or not?)
|
||||
* but actually it's reasonably common for the sort of
|
||||
* three-way control you get a lot of in PuTTY: `yes'
|
||||
* versus `no' versus `some more complex way to decide'.
|
||||
*
|
||||
* Secondly, setting `nbuttons' higher than `ncolumns' lets
|
||||
* us have more than one line of radio buttons for a single
|
||||
* setting. A very important special case of this is
|
||||
* setting `ncolumns' to 1, so that each button is on its
|
||||
* own line.
|
||||
*/
|
||||
int ncolumns;
|
||||
int nbuttons;
|
||||
/*
|
||||
* This points to a dynamically allocated array of `char *'
|
||||
* pointers, each of which points to a dynamically
|
||||
* allocated string.
|
||||
*/
|
||||
char **buttons; /* `nbuttons' button labels */
|
||||
/*
|
||||
* This points to a dynamically allocated array of `char'
|
||||
* giving the individual keyboard shortcuts for each radio
|
||||
* button. The array may be NULL if none are required.
|
||||
*/
|
||||
char *shortcuts; /* `nbuttons' shortcuts; may be NULL */
|
||||
/*
|
||||
* This points to a dynamically allocated array of
|
||||
* intorptr, giving helpful data for each button.
|
||||
*/
|
||||
intorptr *buttondata; /* `nbuttons' entries; may be NULL */
|
||||
STANDARD_PREFIX;
|
||||
/*
|
||||
* `shortcut' here is a single keyboard shortcut which is
|
||||
* expected to select the whole group of radio buttons. It
|
||||
* can be NO_SHORTCUT if required, and there is also a way
|
||||
* to place individual shortcuts on each button; see below.
|
||||
*/
|
||||
char shortcut;
|
||||
/*
|
||||
* There are separate fields for `ncolumns' and `nbuttons'
|
||||
* for several reasons.
|
||||
*
|
||||
* Firstly, we sometimes want the last of a set of buttons
|
||||
* to have a longer label than the rest; we achieve this by
|
||||
* setting `ncolumns' higher than `nbuttons', and the
|
||||
* layout code is expected to understand that the final
|
||||
* button should be given all the remaining space on the
|
||||
* line. This sounds like a ludicrously specific special
|
||||
* case (if we're doing this sort of thing, why not have
|
||||
* the general ability to have a particular button span
|
||||
* more than one column whether it's the last one or not?)
|
||||
* but actually it's reasonably common for the sort of
|
||||
* three-way control you get a lot of in PuTTY: `yes'
|
||||
* versus `no' versus `some more complex way to decide'.
|
||||
*
|
||||
* Secondly, setting `nbuttons' higher than `ncolumns' lets
|
||||
* us have more than one line of radio buttons for a single
|
||||
* setting. A very important special case of this is
|
||||
* setting `ncolumns' to 1, so that each button is on its
|
||||
* own line.
|
||||
*/
|
||||
int ncolumns;
|
||||
int nbuttons;
|
||||
/*
|
||||
* This points to a dynamically allocated array of `char *'
|
||||
* pointers, each of which points to a dynamically
|
||||
* allocated string.
|
||||
*/
|
||||
char **buttons; /* `nbuttons' button labels */
|
||||
/*
|
||||
* This points to a dynamically allocated array of `char'
|
||||
* giving the individual keyboard shortcuts for each radio
|
||||
* button. The array may be NULL if none are required.
|
||||
*/
|
||||
char *shortcuts; /* `nbuttons' shortcuts; may be NULL */
|
||||
/*
|
||||
* This points to a dynamically allocated array of
|
||||
* intorptr, giving helpful data for each button.
|
||||
*/
|
||||
intorptr *buttondata; /* `nbuttons' entries; may be NULL */
|
||||
} radio;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
} checkbox;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
/*
|
||||
* At least Windows has the concept of a `default push
|
||||
* button', which gets implicitly pressed when you hit
|
||||
* Return even if it doesn't have the input focus.
|
||||
*/
|
||||
bool isdefault;
|
||||
/*
|
||||
* Also, the reverse of this: a default cancel-type button,
|
||||
* which is implicitly pressed when you hit Escape.
|
||||
*/
|
||||
bool iscancel;
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
/*
|
||||
* At least Windows has the concept of a `default push
|
||||
* button', which gets implicitly pressed when you hit
|
||||
* Return even if it doesn't have the input focus.
|
||||
*/
|
||||
bool isdefault;
|
||||
/*
|
||||
* Also, the reverse of this: a default cancel-type button,
|
||||
* which is implicitly pressed when you hit Escape.
|
||||
*/
|
||||
bool iscancel;
|
||||
} button;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
char shortcut; /* keyboard shortcut */
|
||||
/*
|
||||
* Height of the list box, in approximate number of lines.
|
||||
* If this is zero, the list is a drop-down list.
|
||||
*/
|
||||
int height; /* height in lines */
|
||||
/*
|
||||
* If this is set, the list elements can be reordered by
|
||||
* the user (by drag-and-drop or by Up and Down buttons,
|
||||
* whatever the per-platform implementation feels
|
||||
* comfortable with). This is not guaranteed to work on a
|
||||
* drop-down list, so don't try it!
|
||||
*/
|
||||
bool draglist;
|
||||
/*
|
||||
* If this is non-zero, the list can have more than one
|
||||
* element selected at a time. This is not guaranteed to
|
||||
* work on a drop-down list, so don't try it!
|
||||
*
|
||||
* Different non-zero values request slightly different
|
||||
* types of multi-selection (this may well be meaningful
|
||||
* only in GTK, so everyone else can ignore it if they
|
||||
* want). 1 means the list box expects to have individual
|
||||
* items selected, whereas 2 means it expects the user to
|
||||
* want to select a large contiguous range at a time.
|
||||
*/
|
||||
int multisel;
|
||||
/*
|
||||
* Percentage of the dialog-box width used by the list box.
|
||||
* If this is set to 100, the label is on its own line;
|
||||
* otherwise the label is on the same line as the box
|
||||
* itself. Setting this to anything other than 100 is not
|
||||
* guaranteed to work on a _non_-drop-down list, so don't
|
||||
* try it!
|
||||
*/
|
||||
int percentwidth;
|
||||
/*
|
||||
* Some list boxes contain strings that contain tab
|
||||
* characters. If `ncols' is greater than 0, then
|
||||
* `percentages' is expected to be non-zero and to contain
|
||||
* the respective widths of `ncols' columns, which together
|
||||
* will exactly fit the width of the list box. Otherwise
|
||||
* `percentages' must be NULL.
|
||||
*
|
||||
* There should never be more than one column in a
|
||||
* drop-down list (one with height==0), because front ends
|
||||
* may have to implement it as a special case of an
|
||||
* editable combo box.
|
||||
*/
|
||||
int ncols; /* number of columns */
|
||||
int *percentages; /* % width of each column */
|
||||
STANDARD_PREFIX;
|
||||
char shortcut; /* keyboard shortcut */
|
||||
/*
|
||||
* Height of the list box, in approximate number of lines.
|
||||
* If this is zero, the list is a drop-down list.
|
||||
*/
|
||||
int height; /* height in lines */
|
||||
/*
|
||||
* If this is set, the list elements can be reordered by
|
||||
* the user (by drag-and-drop or by Up and Down buttons,
|
||||
* whatever the per-platform implementation feels
|
||||
* comfortable with). This is not guaranteed to work on a
|
||||
* drop-down list, so don't try it!
|
||||
*/
|
||||
bool draglist;
|
||||
/*
|
||||
* If this is non-zero, the list can have more than one
|
||||
* element selected at a time. This is not guaranteed to
|
||||
* work on a drop-down list, so don't try it!
|
||||
*
|
||||
* Different non-zero values request slightly different
|
||||
* types of multi-selection (this may well be meaningful
|
||||
* only in GTK, so everyone else can ignore it if they
|
||||
* want). 1 means the list box expects to have individual
|
||||
* items selected, whereas 2 means it expects the user to
|
||||
* want to select a large contiguous range at a time.
|
||||
*/
|
||||
int multisel;
|
||||
/*
|
||||
* Percentage of the dialog-box width used by the list box.
|
||||
* If this is set to 100, the label is on its own line;
|
||||
* otherwise the label is on the same line as the box
|
||||
* itself. Setting this to anything other than 100 is not
|
||||
* guaranteed to work on a _non_-drop-down list, so don't
|
||||
* try it!
|
||||
*/
|
||||
int percentwidth;
|
||||
/*
|
||||
* Some list boxes contain strings that contain tab
|
||||
* characters. If `ncols' is greater than 0, then
|
||||
* `percentages' is expected to be non-zero and to contain
|
||||
* the respective widths of `ncols' columns, which together
|
||||
* will exactly fit the width of the list box. Otherwise
|
||||
* `percentages' must be NULL.
|
||||
*
|
||||
* There should never be more than one column in a
|
||||
* drop-down list (one with height==0), because front ends
|
||||
* may have to implement it as a special case of an
|
||||
* editable combo box.
|
||||
*/
|
||||
int ncols; /* number of columns */
|
||||
int *percentages; /* % width of each column */
|
||||
/*
|
||||
* Flag which can be set to false to suppress the horizontal
|
||||
* scroll bar if a list box entry goes off the right-hand
|
||||
|
@ -347,62 +347,62 @@ union control {
|
|||
bool hscroll;
|
||||
} listbox;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
/*
|
||||
* `filter' dictates what type of files will be selected by
|
||||
* default; for example, when selecting private key files
|
||||
* the file selector would do well to only show .PPK files
|
||||
* (on those systems where this is the chosen extension).
|
||||
*
|
||||
* The precise contents of `filter' are platform-defined,
|
||||
* unfortunately. The special value NULL means `all files'
|
||||
* and is always a valid fallback.
|
||||
*
|
||||
* Unlike almost all strings in this structure, this value
|
||||
* is NOT expected to require freeing (although of course
|
||||
* you can always use ctrl_alloc if you do need to create
|
||||
* one on the fly). This is because the likely mode of use
|
||||
* is to define string constants in a platform-specific
|
||||
* header file, and directly reference those. Or worse, a
|
||||
* particular platform might choose to cast integers into
|
||||
* this pointer type...
|
||||
*/
|
||||
char const *filter;
|
||||
/*
|
||||
* Some systems like to know whether a file selector is
|
||||
* choosing a file to read or one to write (and possibly
|
||||
* create).
|
||||
*/
|
||||
bool for_writing;
|
||||
/*
|
||||
* On at least some platforms, the file selector is a
|
||||
* separate dialog box, and contains a user-settable title.
|
||||
*
|
||||
* This value _is_ expected to require freeing.
|
||||
*/
|
||||
char *title;
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
/*
|
||||
* `filter' dictates what type of files will be selected by
|
||||
* default; for example, when selecting private key files
|
||||
* the file selector would do well to only show .PPK files
|
||||
* (on those systems where this is the chosen extension).
|
||||
*
|
||||
* The precise contents of `filter' are platform-defined,
|
||||
* unfortunately. The special value NULL means `all files'
|
||||
* and is always a valid fallback.
|
||||
*
|
||||
* Unlike almost all strings in this structure, this value
|
||||
* is NOT expected to require freeing (although of course
|
||||
* you can always use ctrl_alloc if you do need to create
|
||||
* one on the fly). This is because the likely mode of use
|
||||
* is to define string constants in a platform-specific
|
||||
* header file, and directly reference those. Or worse, a
|
||||
* particular platform might choose to cast integers into
|
||||
* this pointer type...
|
||||
*/
|
||||
char const *filter;
|
||||
/*
|
||||
* Some systems like to know whether a file selector is
|
||||
* choosing a file to read or one to write (and possibly
|
||||
* create).
|
||||
*/
|
||||
bool for_writing;
|
||||
/*
|
||||
* On at least some platforms, the file selector is a
|
||||
* separate dialog box, and contains a user-settable title.
|
||||
*
|
||||
* This value _is_ expected to require freeing.
|
||||
*/
|
||||
char *title;
|
||||
} fileselect;
|
||||
struct {
|
||||
/* In this variant, `label' MUST be NULL. */
|
||||
STANDARD_PREFIX;
|
||||
int ncols; /* number of columns */
|
||||
int *percentages; /* % width of each column */
|
||||
/*
|
||||
* Every time this control type appears, exactly one of
|
||||
* `ncols' and the previous number of columns MUST be one.
|
||||
* Attempting to allow a seamless transition from a four-
|
||||
* to a five-column layout, for example, would be way more
|
||||
* trouble than it was worth. If you must lay things out
|
||||
* like that, define eight unevenly sized columns and use
|
||||
* column-spanning a lot. But better still, just don't.
|
||||
*
|
||||
* `percentages' may be NULL if ncols==1, to save space.
|
||||
*/
|
||||
/* In this variant, `label' MUST be NULL. */
|
||||
STANDARD_PREFIX;
|
||||
int ncols; /* number of columns */
|
||||
int *percentages; /* % width of each column */
|
||||
/*
|
||||
* Every time this control type appears, exactly one of
|
||||
* `ncols' and the previous number of columns MUST be one.
|
||||
* Attempting to allow a seamless transition from a four-
|
||||
* to a five-column layout, for example, would be way more
|
||||
* trouble than it was worth. If you must lay things out
|
||||
* like that, define eight unevenly sized columns and use
|
||||
* column-spanning a lot. But better still, just don't.
|
||||
*
|
||||
* `percentages' may be NULL if ncols==1, to save space.
|
||||
*/
|
||||
} columns;
|
||||
struct {
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
STANDARD_PREFIX;
|
||||
char shortcut;
|
||||
} fontselect;
|
||||
};
|
||||
|
||||
|
@ -413,18 +413,18 @@ union control {
|
|||
* structures, together with a panel name and a title for the whole
|
||||
* set. In Windows and any similar-looking GUI, each `controlset'
|
||||
* in the config will be a container box within a panel.
|
||||
*
|
||||
*
|
||||
* Special case: if `boxname' is NULL, the control set gives an
|
||||
* overall title for an entire panel of controls.
|
||||
*/
|
||||
struct controlset {
|
||||
char *pathname; /* panel path, e.g. "SSH/Tunnels" */
|
||||
char *boxname; /* internal short name of controlset */
|
||||
char *boxtitle; /* title of container box */
|
||||
int ncolumns; /* current no. of columns at bottom */
|
||||
char *pathname; /* panel path, e.g. "SSH/Tunnels" */
|
||||
char *boxname; /* internal short name of controlset */
|
||||
char *boxtitle; /* title of container box */
|
||||
int ncolumns; /* current no. of columns at bottom */
|
||||
size_t ncontrols; /* number of `union control' in array */
|
||||
size_t ctrlsize; /* allocated size of array */
|
||||
union control **ctrls; /* actual array */
|
||||
union control **ctrls; /* actual array */
|
||||
};
|
||||
|
||||
typedef void (*ctrl_freefn_t)(void *); /* used by ctrl_alloc_with_free */
|
||||
|
@ -434,12 +434,12 @@ typedef void (*ctrl_freefn_t)(void *); /* used by ctrl_alloc_with_free */
|
|||
* controls.
|
||||
*/
|
||||
struct controlbox {
|
||||
size_t nctrlsets; /* number of ctrlsets */
|
||||
size_t ctrlsetsize; /* ctrlset size */
|
||||
size_t nctrlsets; /* number of ctrlsets */
|
||||
size_t ctrlsetsize; /* ctrlset size */
|
||||
struct controlset **ctrlsets; /* actual array of ctrlsets */
|
||||
size_t nfrees;
|
||||
size_t freesize;
|
||||
void **frees; /* array of aux data areas to free */
|
||||
void **frees; /* array of aux data areas to free */
|
||||
ctrl_freefn_t *freefuncs; /* parallel array of free functions */
|
||||
};
|
||||
|
||||
|
@ -452,7 +452,7 @@ void ctrl_free_box(struct controlbox *);
|
|||
|
||||
/* Set up a panel title. */
|
||||
struct controlset *ctrl_settitle(struct controlbox *,
|
||||
const char *path, const char *title);
|
||||
const char *path, const char *title);
|
||||
/* Retrieve a pointer to a controlset, creating it if absent. */
|
||||
struct controlset *ctrl_getset(struct controlbox *, const char *path,
|
||||
const char *name, const char *boxtitle);
|
||||
|
@ -478,7 +478,7 @@ void *ctrl_alloc_with_free(struct controlbox *b, size_t size,
|
|||
|
||||
/*
|
||||
* Individual routines to create `union control' structures in a controlset.
|
||||
*
|
||||
*
|
||||
* Most of these routines allow the most common fields to be set
|
||||
* directly, and put default values in the rest. Each one returns a
|
||||
* pointer to the `union control' it created, so that final tweaks
|
||||
|
@ -489,12 +489,12 @@ void *ctrl_alloc_with_free(struct controlbox *b, size_t size,
|
|||
union control *ctrl_columns(struct controlset *, int ncolumns, ...);
|
||||
union control *ctrl_editbox(struct controlset *, const char *label,
|
||||
char shortcut, int percentage, intorptr helpctx,
|
||||
handler_fn handler,
|
||||
intorptr context, intorptr context2);
|
||||
handler_fn handler,
|
||||
intorptr context, intorptr context2);
|
||||
union control *ctrl_combobox(struct controlset *, const char *label,
|
||||
char shortcut, int percentage, intorptr helpctx,
|
||||
handler_fn handler,
|
||||
intorptr context, intorptr context2);
|
||||
handler_fn handler,
|
||||
intorptr context, intorptr context2);
|
||||
/*
|
||||
* `ncolumns' is followed by (alternately) radio button titles and
|
||||
* intorptrs, until a NULL in place of a title string is seen. Each
|
||||
|
@ -502,32 +502,32 @@ union control *ctrl_combobox(struct controlset *, const char *label,
|
|||
* is NO_SHORTCUT.
|
||||
*/
|
||||
union control *ctrl_radiobuttons(struct controlset *, const char *label,
|
||||
char shortcut, int ncolumns, intorptr helpctx,
|
||||
handler_fn handler, intorptr context, ...);
|
||||
char shortcut, int ncolumns, intorptr helpctx,
|
||||
handler_fn handler, intorptr context, ...);
|
||||
union control *ctrl_pushbutton(struct controlset *, const char *label,
|
||||
char shortcut, intorptr helpctx,
|
||||
handler_fn handler, intorptr context);
|
||||
handler_fn handler, intorptr context);
|
||||
union control *ctrl_listbox(struct controlset *, const char *label,
|
||||
char shortcut, intorptr helpctx,
|
||||
handler_fn handler, intorptr context);
|
||||
handler_fn handler, intorptr context);
|
||||
union control *ctrl_droplist(struct controlset *, const char *label,
|
||||
char shortcut, int percentage, intorptr helpctx,
|
||||
handler_fn handler, intorptr context);
|
||||
handler_fn handler, intorptr context);
|
||||
union control *ctrl_draglist(struct controlset *, const char *label,
|
||||
char shortcut, intorptr helpctx,
|
||||
handler_fn handler, intorptr context);
|
||||
handler_fn handler, intorptr context);
|
||||
union control *ctrl_filesel(struct controlset *, const char *label,
|
||||
char shortcut, const char *filter, bool write,
|
||||
const char *title, intorptr helpctx,
|
||||
handler_fn handler, intorptr context);
|
||||
handler_fn handler, intorptr context);
|
||||
union control *ctrl_fontsel(struct controlset *, const char *label,
|
||||
char shortcut, intorptr helpctx,
|
||||
handler_fn handler, intorptr context);
|
||||
handler_fn handler, intorptr context);
|
||||
union control *ctrl_text(struct controlset *, const char *text,
|
||||
intorptr helpctx);
|
||||
union control *ctrl_checkbox(struct controlset *, const char *label,
|
||||
char shortcut, intorptr helpctx,
|
||||
handler_fn handler, intorptr context);
|
||||
handler_fn handler, intorptr context);
|
||||
union control *ctrl_tabdelay(struct controlset *, union control *);
|
||||
|
||||
/*
|
||||
|
@ -552,7 +552,7 @@ void dlg_listbox_add(union control *ctrl, dlgparam *dp, char const *text);
|
|||
* IDs and expect to get meaningful results back.
|
||||
*/
|
||||
void dlg_listbox_addwithid(union control *ctrl, dlgparam *dp,
|
||||
char const *text, int id);
|
||||
char const *text, int id);
|
||||
int dlg_listbox_getid(union control *ctrl, dlgparam *dp, int index);
|
||||
/* dlg_listbox_index returns <0 if no single element is selected. */
|
||||
int dlg_listbox_index(union control *ctrl, dlgparam *dp);
|
||||
|
@ -612,12 +612,12 @@ void dlg_end(dlgparam *dp, int value);
|
|||
* dlg_coloursel_results() fetches the results, as integers from 0
|
||||
* to 255; it returns nonzero on success, or zero if the colour
|
||||
* selector was dismissed by hitting Cancel or similar.
|
||||
*
|
||||
*
|
||||
* dlg_coloursel_start() accepts an RGB triple which is used to
|
||||
* initialise the colour selector to its starting value.
|
||||
*/
|
||||
void dlg_coloursel_start(union control *ctrl, dlgparam *dp,
|
||||
int r, int g, int b);
|
||||
int r, int g, int b);
|
||||
bool dlg_coloursel_results(union control *ctrl, dlgparam *dp,
|
||||
int *r, int *g, int *b);
|
||||
|
||||
|
@ -626,7 +626,7 @@ bool dlg_coloursel_results(union control *ctrl, dlgparam *dp,
|
|||
* indicate that the value of a particular control is likely to
|
||||
* have changed. It triggers a call of the handler for that control
|
||||
* with `event' set to EVENT_REFRESH.
|
||||
*
|
||||
*
|
||||
* If `ctrl' is NULL, _all_ controls in the dialog get refreshed
|
||||
* (for loading or saving entire sets of settings).
|
||||
*/
|
||||
|
@ -640,8 +640,8 @@ void dlg_refresh(union control *ctrl, dlgparam *dp);
|
|||
* Find the index of next controlset in a controlbox for a given
|
||||
* path, or -1 if no such controlset exists. If -1 is passed as
|
||||
* input, finds the first. Intended usage is something like
|
||||
*
|
||||
* for (index=-1; (index=ctrl_find_path(ctrlbox, index, path)) >= 0 ;) {
|
||||
*
|
||||
* for (index=-1; (index=ctrl_find_path(ctrlbox, index, path)) >= 0 ;) {
|
||||
* ... process this controlset ...
|
||||
* }
|
||||
*/
|
||||
|
|
|
@ -359,8 +359,8 @@ Most servers send two control characters, \i{CR} and \i{LF}, to start a
|
|||
left-hand side of the screen. The LF character makes the cursor move
|
||||
one line down (and might make the screen scroll).
|
||||
|
||||
Some servers only send CR, and so the newly
|
||||
written line is overwritten by the following line. This option causes
|
||||
Some servers only send CR, and so the newly
|
||||
written line is overwritten by the following line. This option causes
|
||||
a line feed so that all lines are displayed.
|
||||
|
||||
\S{config-erase} \q{Use \i{background colour} to erase screen}
|
||||
|
@ -1194,7 +1194,7 @@ characters should be treated as single-width for the purposes of \I{wrapping,
|
|||
terminal}wrapping and so on; however, in some CJK contexts, they are better
|
||||
treated as double-width for historical reasons, and some server-side
|
||||
applications may expect them to be displayed as such. Setting this option
|
||||
will cause PuTTY to take the double-width interpretation.
|
||||
will cause PuTTY to take the double-width interpretation.
|
||||
|
||||
If you use legacy CJK applications, and you find your lines are
|
||||
wrapping in the wrong places, or you are having other display
|
||||
|
@ -1508,7 +1508,7 @@ If you enable \q{Copy to clipboard in RTF as well as plain text},
|
|||
PuTTY will write formatting information to the clipboard as well as
|
||||
the actual text you copy. The effect of this is
|
||||
that if you paste into (say) a word processor, the text will appear
|
||||
in the word processor in the same \i{font}, \i{colour}, and style
|
||||
in the word processor in the same \i{font}, \i{colour}, and style
|
||||
(e.g. bold, underline) PuTTY was using to display it.
|
||||
|
||||
This option can easily be inconvenient, so by default it is
|
||||
|
@ -2053,7 +2053,7 @@ itself.
|
|||
|
||||
Also, the special strings \c{%host} and \c{%port} will be replaced
|
||||
by the host name and port number you want to connect to. The strings
|
||||
\c{%user} and \c{%pass} will be replaced by the proxy username and
|
||||
\c{%user} and \c{%pass} will be replaced by the proxy username and
|
||||
password you specify. The strings \c{%proxyhost} and \c{%proxyport}
|
||||
will be replaced by the host details specified on the \e{Proxy} panel,
|
||||
if any (this is most likely to be useful for the Local proxy type).
|
||||
|
@ -2064,8 +2064,8 @@ before commands can be sent, you can use a command such as:
|
|||
|
||||
\c %user\n%pass\nconnect %host %port\n
|
||||
|
||||
This will send your username and password as the first two lines to
|
||||
the proxy, followed by a command to connect to the desired host and
|
||||
This will send your username and password as the first two lines to
|
||||
the proxy, followed by a command to connect to the desired host and
|
||||
port. Note that if you do not include the \c{%user} or \c{%pass}
|
||||
tokens in the Telnet command, then the \q{Username} and \q{Password}
|
||||
configuration fields will be ignored.
|
||||
|
@ -3565,13 +3565,13 @@ once it's been successfully saved back to the file.
|
|||
Here is \c{PUTTYDEL.REG}:
|
||||
|
||||
\c REGEDIT4
|
||||
\c
|
||||
\c
|
||||
\c [-HKEY_CURRENT_USER\Software\SimonTatham\PuTTY]
|
||||
|
||||
Here is an example \c{PUTTYRND.REG} file:
|
||||
|
||||
\c REGEDIT4
|
||||
\c
|
||||
\c
|
||||
\c [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY]
|
||||
\c "RandSeedFile"="a:\\putty.rnd"
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ Various forms of this error are printed in the PuTTY window, or
|
|||
written to the PuTTY Event Log (see \k{using-eventlog}) during
|
||||
authentication.
|
||||
|
||||
If you see one of these messages, it means that the server has refused
|
||||
If you see one of these messages, it means that the server has refused
|
||||
all the forms of authentication PuTTY has tried and it has no further
|
||||
ideas.
|
||||
|
||||
|
@ -231,7 +231,7 @@ noticed.
|
|||
|
||||
Occasionally this has been caused by server bugs. An example is the
|
||||
bug described at \k{config-ssh-bug-hmac2}, although you're very
|
||||
unlikely to encounter that one these days.
|
||||
unlikely to encounter that one these days.
|
||||
|
||||
In this context MAC stands for \ii{Message Authentication Code}. It's a
|
||||
cryptographic term, and it has nothing at all to do with Ethernet
|
||||
|
|
|
@ -166,7 +166,7 @@ will not. Adding an option to turn host key checking off completely is
|
|||
the wrong solution and we will not do it.
|
||||
|
||||
If you have host keys available in the common \i\c{known_hosts} format,
|
||||
we have a script called
|
||||
we have a script called
|
||||
\W{https://git.tartarus.org/?p=simon/putty.git;a=blob;f=contrib/kh2reg.py;hb=HEAD}\c{kh2reg.py}
|
||||
to convert them to a Windows .REG file, which can be installed ahead of
|
||||
time by double-clicking or using \c{REGEDIT}.
|
||||
|
@ -241,7 +241,7 @@ present time. If anyone told you we had an Android port, or an iOS
|
|||
port, or any other port of PuTTY, they were mistaken. We don't.
|
||||
|
||||
There are some third-party ports to various platforms, mentioned
|
||||
on the
|
||||
on the
|
||||
\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/links.html}{Links page of our website}.
|
||||
|
||||
\S{faq-unix}{Question} \I{Unix version}Is there a port to Unix?
|
||||
|
@ -991,7 +991,7 @@ means you need to use non-\cw{127.0.0.1} addresses to forward
|
|||
Terminal Services in the first place.)
|
||||
|
||||
\S{faq-missing-slash}{Question} PSFTP commands seem to be missing a
|
||||
directory separator (slash).
|
||||
directory separator (slash).
|
||||
|
||||
Some people have reported the following incorrect behaviour with
|
||||
PSFTP:
|
||||
|
|
|
@ -148,7 +148,7 @@ information:
|
|||
use the \q{About PuTTY} option from the System menu. Please \e{do
|
||||
not} just tell us \q{I'm running the latest version}; e-mail can be
|
||||
delayed and it may not be obvious which version was the latest at
|
||||
the time you sent the message.
|
||||
the time you sent the message.
|
||||
|
||||
\b PuTTY is a multi-platform application; tell us what version of what
|
||||
OS you are running PuTTY on. (If you're running on Unix, or Windows
|
||||
|
@ -218,7 +218,7 @@ Secure Contact Key. See \k{pgpkeys-pubkey} for details of this.
|
|||
much information as possible about them, the same way you would with
|
||||
any other bug report.)
|
||||
|
||||
\H{feedback-features} Requesting extra features
|
||||
\H{feedback-features} Requesting extra features
|
||||
|
||||
If you want to request a new feature in PuTTY, the very first things
|
||||
you should do are:
|
||||
|
|
|
@ -290,7 +290,7 @@ zero exit status if a usable \q{upstream} exists, nonzero otherwise.
|
|||
In some situations, Plink applies a sanitisation pass to the output
|
||||
received from the server, to strip out control characters such as
|
||||
backspace and the escape character.
|
||||
|
||||
|
||||
The idea of this is to prevent remote processes from sending confusing
|
||||
escape sequences through the standard error channel when Plink is
|
||||
being used as a transport for something like \cw{git} or CVS. If the
|
||||
|
@ -418,7 +418,7 @@ labelled \q{Check for an alternate \cw{rsh} name} and in the text
|
|||
entry field to the right enter the full path to \c{plink.exe}.
|
||||
Select \q{OK} on the \q{Preferences} dialogue box.
|
||||
|
||||
Next, select \q{Command Line} from the WinCVS \q{Admin} menu, and type
|
||||
Next, select \q{Command Line} from the WinCVS \q{Admin} menu, and type
|
||||
a CVS command as in \k{plink-cvs}, for example:
|
||||
|
||||
\c cvs -d :ext:user@hostname:/path/to/repository co module
|
||||
|
|
14
doc/pscp.but
14
doc/pscp.but
|
@ -78,7 +78,7 @@ familiar with that.)
|
|||
|
||||
\S{pscp-usage-basics} The basics
|
||||
|
||||
To \I{receiving files}receive (a) file(s) from a remote server:
|
||||
To \I{receiving files}receive (a) file(s) from a remote server:
|
||||
|
||||
\c pscp [options] [user@]host:source target
|
||||
|
||||
|
@ -87,7 +87,7 @@ user \c{fred} to the file \c{c:\\temp\\example-hosts.txt}, you would type:
|
|||
|
||||
\c pscp fred@example.com:/etc/hosts c:\temp\example-hosts.txt
|
||||
|
||||
To \I{sending files}send (a) file(s) to a remote server:
|
||||
To \I{sending files}send (a) file(s) to a remote server:
|
||||
|
||||
\c pscp [options] source [source...] [user@]host:target
|
||||
|
||||
|
@ -146,7 +146,7 @@ trying to get out of that directory using pathnames including
|
|||
\S2{pscp-usage-basics-user} \c{user}
|
||||
|
||||
The \i{login name} on the remote server. If this is omitted, and \c{host}
|
||||
is a PuTTY saved session, PSCP will use any username specified by that
|
||||
is a PuTTY saved session, PSCP will use any username specified by that
|
||||
saved session. Otherwise, PSCP will attempt to use the local Windows
|
||||
username.
|
||||
|
||||
|
@ -160,8 +160,8 @@ number, cipher type and username will be used.
|
|||
|
||||
One or more source files. \ii{Wildcards} are allowed. The syntax of
|
||||
wildcards depends on the system to which they apply, so if you are
|
||||
copying \e{from} a Windows system \e{to} a UNIX system, you should use
|
||||
Windows wildcard syntax (e.g. \c{*.*}), but if you are copying \e{from}
|
||||
copying \e{from} a Windows system \e{to} a UNIX system, you should use
|
||||
Windows wildcard syntax (e.g. \c{*.*}), but if you are copying \e{from}
|
||||
a UNIX system \e{to} a Windows system, you would use the wildcard
|
||||
syntax allowed by your UNIX shell (e.g. \c{*}).
|
||||
|
||||
|
@ -179,7 +179,7 @@ target of \c{.}. For example:
|
|||
|
||||
\c pscp fred@example.com:/home/tom/.emacs .
|
||||
|
||||
...would copy \c{/home/tom/.emacs} on the remote server to the current
|
||||
...would copy \c{/home/tom/.emacs} on the remote server to the current
|
||||
directory.
|
||||
|
||||
As with the \c{source} parameter, if the target is on a remote server
|
||||
|
@ -235,7 +235,7 @@ these statistics.
|
|||
|
||||
By default, PSCP will only copy files. Any directories you specify to
|
||||
copy will be skipped, as will their contents. The \c{-r} option tells
|
||||
PSCP to descend into any directories you specify, and to copy them and
|
||||
PSCP to descend into any directories you specify, and to copy them and
|
||||
their contents. This allows you to use PSCP to transfer whole
|
||||
directory structures between machines.
|
||||
|
||||
|
|
2
ecc.c
2
ecc.c
|
@ -524,7 +524,7 @@ unsigned ecc_weierstrass_point_valid(WeierstrassPoint *P)
|
|||
mp_int *z6 = monty_mul(wc->mc, z2, z4);
|
||||
mp_int *bz6 = monty_mul(wc->mc, wc->b, z6);
|
||||
mp_int *rhs = monty_add(wc->mc, x3_plus_axz4, bz6);
|
||||
|
||||
|
||||
unsigned valid = mp_cmp_eq(lhs, rhs);
|
||||
|
||||
mp_free(lhs);
|
||||
|
|
|
@ -21,7 +21,7 @@ static Plug *sk_error_plug(Socket *s, Plug *p)
|
|||
ErrorSocket *es = container_of(s, ErrorSocket, sock);
|
||||
Plug *ret = es->plug;
|
||||
if (p)
|
||||
es->plug = p;
|
||||
es->plug = p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
60
fuzzterm.c
60
fuzzterm.c
|
@ -13,34 +13,34 @@ static const TermWinVtable fuzz_termwin_vt;
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char blk[512];
|
||||
size_t len;
|
||||
Terminal *term;
|
||||
Conf *conf;
|
||||
struct unicode_data ucsdata;
|
||||
char blk[512];
|
||||
size_t len;
|
||||
Terminal *term;
|
||||
Conf *conf;
|
||||
struct unicode_data ucsdata;
|
||||
TermWin termwin;
|
||||
|
||||
termwin.vt = &fuzz_termwin_vt;
|
||||
|
||||
conf = conf_new();
|
||||
do_defaults(NULL, conf);
|
||||
init_ucs(&ucsdata, conf_get_str(conf, CONF_line_codepage),
|
||||
conf_get_bool(conf, CONF_utf8_override),
|
||||
CS_NONE, conf_get_int(conf, CONF_vtmode));
|
||||
conf = conf_new();
|
||||
do_defaults(NULL, conf);
|
||||
init_ucs(&ucsdata, conf_get_str(conf, CONF_line_codepage),
|
||||
conf_get_bool(conf, CONF_utf8_override),
|
||||
CS_NONE, conf_get_int(conf, CONF_vtmode));
|
||||
|
||||
term = term_init(conf, &ucsdata, &termwin);
|
||||
term_size(term, 24, 80, 10000);
|
||||
term->ldisc = NULL;
|
||||
/* Tell american fuzzy lop that this is a good place to fork. */
|
||||
term = term_init(conf, &ucsdata, &termwin);
|
||||
term_size(term, 24, 80, 10000);
|
||||
term->ldisc = NULL;
|
||||
/* Tell american fuzzy lop that this is a good place to fork. */
|
||||
#ifdef __AFL_HAVE_MANUAL_CONTROL
|
||||
__AFL_INIT();
|
||||
__AFL_INIT();
|
||||
#endif
|
||||
while (!feof(stdin)) {
|
||||
len = fread(blk, 1, sizeof(blk), stdin);
|
||||
term_data(term, false, blk, len);
|
||||
}
|
||||
term_update(term);
|
||||
return 0;
|
||||
while (!feof(stdin)) {
|
||||
len = fread(blk, 1, sizeof(blk), stdin);
|
||||
term_data(term, false, blk, len);
|
||||
}
|
||||
term_update(term);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* functions required by terminal.c */
|
||||
|
@ -53,7 +53,7 @@ static void fuzz_draw_text(
|
|||
|
||||
printf("TEXT[attr=%08lx,lattr=%02x]@(%d,%d):", attr, lattr, x, y);
|
||||
for (i = 0; i < len; i++) {
|
||||
printf(" %x", (unsigned)text[i]);
|
||||
printf(" %x", (unsigned)text[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ static void fuzz_draw_cursor(
|
|||
|
||||
printf("CURS[attr=%08lx,lattr=%02x]@(%d,%d):", attr, lattr, x, y);
|
||||
for (i = 0; i < len; i++) {
|
||||
printf(" %x", (unsigned)text[i]);
|
||||
printf(" %x", (unsigned)text[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ void dlg_listbox_clear(union control *ctrl, void *dlg) { }
|
|||
void dlg_listbox_del(union control *ctrl, void *dlg, int index) { }
|
||||
void dlg_listbox_add(union control *ctrl, void *dlg, char const *text) { }
|
||||
void dlg_listbox_addwithid(union control *ctrl, void *dlg,
|
||||
char const *text, int id) { }
|
||||
char const *text, int id) { }
|
||||
int dlg_listbox_getid(union control *ctrl, void *dlg, int index) { return 0; }
|
||||
int dlg_listbox_index(union control *ctrl, void *dlg) { return -1; }
|
||||
int dlg_listbox_issel(union control *ctrl, void *dlg, int index) { return 0; }
|
||||
|
@ -171,7 +171,7 @@ void dlg_beep(void *dlg) { }
|
|||
void dlg_error_msg(void *dlg, const char *msg) { }
|
||||
void dlg_end(void *dlg, int value) { }
|
||||
void dlg_coloursel_start(union control *ctrl, void *dlg,
|
||||
int r, int g, int b) { }
|
||||
int r, int g, int b) { }
|
||||
bool dlg_coloursel_results(union control *ctrl, void *dlg,
|
||||
int *r, int *g, int *b) { return false; }
|
||||
void dlg_refresh(union control *ctrl, void *dlg) { }
|
||||
|
@ -188,9 +188,9 @@ const struct keyvalwhere gsslibkeywords[0] = { };
|
|||
char *platform_default_s(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "TermType"))
|
||||
return dupstr(getenv("TERM"));
|
||||
return dupstr(getenv("TERM"));
|
||||
if (!strcmp(name, "SerialLine"))
|
||||
return dupstr("/dev/ttyS0");
|
||||
return dupstr("/dev/ttyS0");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -212,12 +212,12 @@ FontSpec *platform_default_fontspec(const char *name)
|
|||
Filename *platform_default_filename(const char *name)
|
||||
{
|
||||
if (!strcmp(name, "LogFileName"))
|
||||
return filename_from_str("putty.log");
|
||||
return filename_from_str("putty.log");
|
||||
else
|
||||
return filename_from_str("");
|
||||
return filename_from_str("");
|
||||
}
|
||||
|
||||
char *x_get_default(const char *key)
|
||||
{
|
||||
return NULL; /* this is a stub */
|
||||
return NULL; /* this is a stub */
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/perl
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Given a list of input PNGs, create a C source file containing a
|
||||
# const array of XPMs, named by a given C identifier.
|
||||
|
|
152
icons/icon.pl
152
icons/icon.pl
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/perl
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Take a collection of input image files and convert them into a
|
||||
# multi-resolution Windows .ICO icon file.
|
||||
|
@ -87,11 +87,11 @@
|
|||
$depth = undef;
|
||||
foreach $_ (@ARGV) {
|
||||
if (/^-(24|8|4|1)$/) {
|
||||
$depth = $1;
|
||||
$depth = $1;
|
||||
} elsif (defined $depth) {
|
||||
&readicon($_, $depth);
|
||||
&readicon($_, $depth);
|
||||
} else {
|
||||
$usage = 1;
|
||||
$usage = 1;
|
||||
}
|
||||
}
|
||||
if ($usage || length @hdr == 0) {
|
||||
|
@ -149,86 +149,86 @@ sub readicon {
|
|||
my $alpha = "";
|
||||
|
||||
for ($y = 0; $y < $h; $y++) {
|
||||
my $currbyte = 0, $currbits = 0;
|
||||
for ($x = 0; $x < (($w+31)|31)-31; $x++) {
|
||||
$pix = ($x < $w ? $data->[$y*$w+$x] : "\x00\x00\x00\xFF");
|
||||
my @rgba = unpack "CCCC", $pix;
|
||||
$currbyte <<= 1;
|
||||
$currbits++;
|
||||
if ($rgba[3] < 0x80) {
|
||||
if ($x < $w) {
|
||||
$data->[$y*$w+$x] = undef;
|
||||
}
|
||||
$currbyte |= 1; # MS has the alpha channel inverted :-)
|
||||
} else {
|
||||
# Might as well flip RGBA into BGR0 while we're here.
|
||||
if ($x < $w) {
|
||||
$data->[$y*$w+$x] = pack "CCCC",
|
||||
$rgba[2], $rgba[1], $rgba[0], 0;
|
||||
}
|
||||
}
|
||||
if ($currbits >= 8) {
|
||||
$alpha .= pack "C", $currbyte;
|
||||
$currbits -= 8;
|
||||
}
|
||||
}
|
||||
my $currbyte = 0, $currbits = 0;
|
||||
for ($x = 0; $x < (($w+31)|31)-31; $x++) {
|
||||
$pix = ($x < $w ? $data->[$y*$w+$x] : "\x00\x00\x00\xFF");
|
||||
my @rgba = unpack "CCCC", $pix;
|
||||
$currbyte <<= 1;
|
||||
$currbits++;
|
||||
if ($rgba[3] < 0x80) {
|
||||
if ($x < $w) {
|
||||
$data->[$y*$w+$x] = undef;
|
||||
}
|
||||
$currbyte |= 1; # MS has the alpha channel inverted :-)
|
||||
} else {
|
||||
# Might as well flip RGBA into BGR0 while we're here.
|
||||
if ($x < $w) {
|
||||
$data->[$y*$w+$x] = pack "CCCC",
|
||||
$rgba[2], $rgba[1], $rgba[0], 0;
|
||||
}
|
||||
}
|
||||
if ($currbits >= 8) {
|
||||
$alpha .= pack "C", $currbyte;
|
||||
$currbits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# For an 8-bit image, check we have at most 256 distinct
|
||||
# colours, and build the palette.
|
||||
%pal = ();
|
||||
if ($depth == 8) {
|
||||
my $palindex = 0;
|
||||
foreach $pix (@$data) {
|
||||
next unless defined $pix;
|
||||
$pal{$pix} = $palindex++ unless defined $pal{$pix};
|
||||
}
|
||||
die "too many colours in 8-bit image $filename\n" unless $palindex <= 256;
|
||||
my $palindex = 0;
|
||||
foreach $pix (@$data) {
|
||||
next unless defined $pix;
|
||||
$pal{$pix} = $palindex++ unless defined $pal{$pix};
|
||||
}
|
||||
die "too many colours in 8-bit image $filename\n" unless $palindex <= 256;
|
||||
} elsif ($depth == 4) {
|
||||
%pal = %win16pal;
|
||||
%pal = %win16pal;
|
||||
} elsif ($depth == 1) {
|
||||
%pal = %win2pal;
|
||||
%pal = %win2pal;
|
||||
}
|
||||
|
||||
my $raster = "";
|
||||
if ($depth < 24) {
|
||||
# For a non-24-bit image, flatten the image into one palette
|
||||
# index per pixel.
|
||||
$pad = 32 / $depth; # number of pixels to pad scanline to 4-byte align
|
||||
$pmask = $pad-1;
|
||||
for ($y = 0; $y < $h; $y++) {
|
||||
my $currbyte = 0, $currbits = 0;
|
||||
for ($x = 0; $x < (($w+$pmask)|$pmask)-$pmask; $x++) {
|
||||
$currbyte <<= $depth;
|
||||
$currbits += $depth;
|
||||
if ($x < $w && defined ($pix = $data->[$y*$w+$x])) {
|
||||
if (!defined $pal{$pix}) {
|
||||
# For a non-24-bit image, flatten the image into one palette
|
||||
# index per pixel.
|
||||
$pad = 32 / $depth; # number of pixels to pad scanline to 4-byte align
|
||||
$pmask = $pad-1;
|
||||
for ($y = 0; $y < $h; $y++) {
|
||||
my $currbyte = 0, $currbits = 0;
|
||||
for ($x = 0; $x < (($w+$pmask)|$pmask)-$pmask; $x++) {
|
||||
$currbyte <<= $depth;
|
||||
$currbits += $depth;
|
||||
if ($x < $w && defined ($pix = $data->[$y*$w+$x])) {
|
||||
if (!defined $pal{$pix}) {
|
||||
$pixhex = sprintf "%02x%02x%02x", unpack "CCC", $pix;
|
||||
die "illegal colour value $pixhex at pixel ($x,$y) in $filename\n";
|
||||
}
|
||||
$currbyte |= $pal{$pix};
|
||||
}
|
||||
if ($currbits >= 8) {
|
||||
$raster .= pack "C", $currbyte;
|
||||
$currbits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
die "illegal colour value $pixhex at pixel ($x,$y) in $filename\n";
|
||||
}
|
||||
$currbyte |= $pal{$pix};
|
||||
}
|
||||
if ($currbits >= 8) {
|
||||
$raster .= pack "C", $currbyte;
|
||||
$currbits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# For a 24-bit image, reverse the order of the R,G,B values
|
||||
# and stick a padding zero on the end.
|
||||
#
|
||||
# (In this loop we don't need to bother padding the
|
||||
# scanline out to a multiple of four bytes, because every
|
||||
# pixel takes four whole bytes anyway.)
|
||||
for ($i = 0; $i < scalar @$data; $i++) {
|
||||
if (defined $data->[$i]) {
|
||||
$raster .= $data->[$i];
|
||||
} else {
|
||||
$raster .= "\x00\x00\x00\x00";
|
||||
}
|
||||
}
|
||||
$depth = 32; # and adjust this
|
||||
# For a 24-bit image, reverse the order of the R,G,B values
|
||||
# and stick a padding zero on the end.
|
||||
#
|
||||
# (In this loop we don't need to bother padding the
|
||||
# scanline out to a multiple of four bytes, because every
|
||||
# pixel takes four whole bytes anyway.)
|
||||
for ($i = 0; $i < scalar @$data; $i++) {
|
||||
if (defined $data->[$i]) {
|
||||
$raster .= $data->[$i];
|
||||
} else {
|
||||
$raster .= "\x00\x00\x00\x00";
|
||||
}
|
||||
}
|
||||
$depth = 32; # and adjust this
|
||||
}
|
||||
|
||||
# Prepare the icon data. First the header...
|
||||
|
@ -243,12 +243,12 @@ sub readicon {
|
|||
0, 0, 0, 0; # resolution, colours used, colours important (ignored)
|
||||
# ... then the palette ...
|
||||
if ($depth <= 8) {
|
||||
my $ncols = (1 << $depth);
|
||||
my $palette = "\x00\x00\x00\x00" x $ncols;
|
||||
foreach $i (keys %pal) {
|
||||
substr($palette, $pal{$i}*4, 4) = $i;
|
||||
}
|
||||
$data .= $palette;
|
||||
my $ncols = (1 << $depth);
|
||||
my $palette = "\x00\x00\x00\x00" x $ncols;
|
||||
foreach $i (keys %pal) {
|
||||
substr($palette, $pal{$i}*4, 4) = $i;
|
||||
}
|
||||
$data .= $palette;
|
||||
}
|
||||
# ... the raster data we already had ready ...
|
||||
$data .= $raster;
|
||||
|
|
|
@ -223,7 +223,7 @@ def sysbox(size, out={}):
|
|||
for y in range(depth):
|
||||
grey = 3
|
||||
if x >= width-1 - highlight:
|
||||
grey = grey + 1
|
||||
grey = grey + 1
|
||||
pixel(x+(y+1), -(y+1), greypix(grey/4.0), canvas)
|
||||
|
||||
# And draw a border.
|
||||
|
|
576
import.c
576
import.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
358
ldisc.c
358
ldisc.c
|
@ -28,48 +28,48 @@ static void c_write(Ldisc *ldisc, const void *buf, int len)
|
|||
static int plen(Ldisc *ldisc, unsigned char c)
|
||||
{
|
||||
if ((c >= 32 && c <= 126) || (c >= 160 && !in_utf(ldisc->term)))
|
||||
return 1;
|
||||
return 1;
|
||||
else if (c < 128)
|
||||
return 2; /* ^x for some x */
|
||||
return 2; /* ^x for some x */
|
||||
else if (in_utf(ldisc->term) && c >= 0xC0)
|
||||
return 1; /* UTF-8 introducer character
|
||||
* (FIXME: combining / wide chars) */
|
||||
return 1; /* UTF-8 introducer character
|
||||
* (FIXME: combining / wide chars) */
|
||||
else if (in_utf(ldisc->term) && c >= 0x80 && c < 0xC0)
|
||||
return 0; /* UTF-8 followup character */
|
||||
return 0; /* UTF-8 followup character */
|
||||
else
|
||||
return 4; /* <XY> hex representation */
|
||||
return 4; /* <XY> hex representation */
|
||||
}
|
||||
|
||||
static void pwrite(Ldisc *ldisc, unsigned char c)
|
||||
{
|
||||
if ((c >= 32 && c <= 126) ||
|
||||
(!in_utf(ldisc->term) && c >= 0xA0) ||
|
||||
(in_utf(ldisc->term) && c >= 0x80)) {
|
||||
c_write(ldisc, &c, 1);
|
||||
(!in_utf(ldisc->term) && c >= 0xA0) ||
|
||||
(in_utf(ldisc->term) && c >= 0x80)) {
|
||||
c_write(ldisc, &c, 1);
|
||||
} else if (c < 128) {
|
||||
char cc[2];
|
||||
cc[1] = (c == 127 ? '?' : c + 0x40);
|
||||
cc[0] = '^';
|
||||
c_write(ldisc, cc, 2);
|
||||
char cc[2];
|
||||
cc[1] = (c == 127 ? '?' : c + 0x40);
|
||||
cc[0] = '^';
|
||||
c_write(ldisc, cc, 2);
|
||||
} else {
|
||||
char cc[5];
|
||||
sprintf(cc, "<%02X>", c);
|
||||
c_write(ldisc, cc, 4);
|
||||
char cc[5];
|
||||
sprintf(cc, "<%02X>", c);
|
||||
c_write(ldisc, cc, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static bool char_start(Ldisc *ldisc, unsigned char c)
|
||||
{
|
||||
if (in_utf(ldisc->term))
|
||||
return (c < 0x80 || c >= 0xC0);
|
||||
return (c < 0x80 || c >= 0xC0);
|
||||
else
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bsb(Ldisc *ldisc, int n)
|
||||
{
|
||||
while (n--)
|
||||
c_write(ldisc, "\010 \010", 3);
|
||||
c_write(ldisc, "\010 \010", 3);
|
||||
}
|
||||
|
||||
#define CTRL(x) (x^'@')
|
||||
|
@ -92,7 +92,7 @@ Ldisc *ldisc_create(Conf *conf, Terminal *term, Backend *backend, Seat *seat)
|
|||
|
||||
/* Link ourselves into the backend and the terminal */
|
||||
if (term)
|
||||
term->ldisc = ldisc;
|
||||
term->ldisc = ldisc;
|
||||
if (backend)
|
||||
backend_provide_ldisc(backend, ldisc);
|
||||
|
||||
|
@ -111,11 +111,11 @@ void ldisc_configure(Ldisc *ldisc, Conf *conf)
|
|||
void ldisc_free(Ldisc *ldisc)
|
||||
{
|
||||
if (ldisc->term)
|
||||
ldisc->term->ldisc = NULL;
|
||||
ldisc->term->ldisc = NULL;
|
||||
if (ldisc->backend)
|
||||
backend_provide_ldisc(ldisc->backend, NULL);
|
||||
if (ldisc->buf)
|
||||
sfree(ldisc->buf);
|
||||
sfree(ldisc->buf);
|
||||
sfree(ldisc);
|
||||
}
|
||||
|
||||
|
@ -148,65 +148,65 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, bool interactive)
|
|||
* Less than zero means null terminated special string.
|
||||
*/
|
||||
if (len < 0) {
|
||||
len = strlen(buf);
|
||||
keyflag = KCTRL('@');
|
||||
len = strlen(buf);
|
||||
keyflag = KCTRL('@');
|
||||
}
|
||||
/*
|
||||
* Either perform local editing, or just send characters.
|
||||
*/
|
||||
if (EDITING) {
|
||||
while (len--) {
|
||||
int c;
|
||||
c = (unsigned char)(*buf++) + keyflag;
|
||||
if (!interactive && c == '\r')
|
||||
c += KCTRL('@');
|
||||
switch (ldisc->quotenext ? ' ' : c) {
|
||||
/*
|
||||
* ^h/^?: delete, and output BSBs, to return to
|
||||
* last character boundary (in UTF-8 mode this may
|
||||
* be more than one byte)
|
||||
* ^w: delete, and output BSBs, to return to last
|
||||
* space/nonspace boundary
|
||||
* ^u: delete, and output BSBs, to return to BOL
|
||||
* ^c: Do a ^u then send a telnet IP
|
||||
* ^z: Do a ^u then send a telnet SUSP
|
||||
* ^\: Do a ^u then send a telnet ABORT
|
||||
* ^r: echo "^R\n" and redraw line
|
||||
* ^v: quote next char
|
||||
* ^d: if at BOL, end of file and close connection,
|
||||
* else send line and reset to BOL
|
||||
* ^m: send line-plus-\r\n and reset to BOL
|
||||
*/
|
||||
case KCTRL('H'):
|
||||
case KCTRL('?'): /* backspace/delete */
|
||||
if (ldisc->buflen > 0) {
|
||||
do {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
} while (!char_start(ldisc, ldisc->buf[ldisc->buflen]));
|
||||
}
|
||||
break;
|
||||
case CTRL('W'): /* delete word */
|
||||
while (ldisc->buflen > 0) {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
if (ldisc->buflen > 0 &&
|
||||
isspace((unsigned char)ldisc->buf[ldisc->buflen-1]) &&
|
||||
!isspace((unsigned char)ldisc->buf[ldisc->buflen]))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CTRL('U'): /* delete line */
|
||||
case CTRL('C'): /* Send IP */
|
||||
case CTRL('\\'): /* Quit */
|
||||
case CTRL('Z'): /* Suspend */
|
||||
while (ldisc->buflen > 0) {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
}
|
||||
while (len--) {
|
||||
int c;
|
||||
c = (unsigned char)(*buf++) + keyflag;
|
||||
if (!interactive && c == '\r')
|
||||
c += KCTRL('@');
|
||||
switch (ldisc->quotenext ? ' ' : c) {
|
||||
/*
|
||||
* ^h/^?: delete, and output BSBs, to return to
|
||||
* last character boundary (in UTF-8 mode this may
|
||||
* be more than one byte)
|
||||
* ^w: delete, and output BSBs, to return to last
|
||||
* space/nonspace boundary
|
||||
* ^u: delete, and output BSBs, to return to BOL
|
||||
* ^c: Do a ^u then send a telnet IP
|
||||
* ^z: Do a ^u then send a telnet SUSP
|
||||
* ^\: Do a ^u then send a telnet ABORT
|
||||
* ^r: echo "^R\n" and redraw line
|
||||
* ^v: quote next char
|
||||
* ^d: if at BOL, end of file and close connection,
|
||||
* else send line and reset to BOL
|
||||
* ^m: send line-plus-\r\n and reset to BOL
|
||||
*/
|
||||
case KCTRL('H'):
|
||||
case KCTRL('?'): /* backspace/delete */
|
||||
if (ldisc->buflen > 0) {
|
||||
do {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
} while (!char_start(ldisc, ldisc->buf[ldisc->buflen]));
|
||||
}
|
||||
break;
|
||||
case CTRL('W'): /* delete word */
|
||||
while (ldisc->buflen > 0) {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
if (ldisc->buflen > 0 &&
|
||||
isspace((unsigned char)ldisc->buf[ldisc->buflen-1]) &&
|
||||
!isspace((unsigned char)ldisc->buf[ldisc->buflen]))
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CTRL('U'): /* delete line */
|
||||
case CTRL('C'): /* Send IP */
|
||||
case CTRL('\\'): /* Quit */
|
||||
case CTRL('Z'): /* Suspend */
|
||||
while (ldisc->buflen > 0) {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
}
|
||||
backend_special(ldisc->backend, SS_EL, 0);
|
||||
/*
|
||||
* We don't send IP, SUSP or ABORT if the user has
|
||||
|
@ -215,130 +215,130 @@ void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, bool interactive)
|
|||
*/
|
||||
if (!ldisc->telnet_keyboard)
|
||||
goto default_case;
|
||||
if (c == CTRL('C'))
|
||||
if (c == CTRL('C'))
|
||||
backend_special(ldisc->backend, SS_IP, 0);
|
||||
if (c == CTRL('Z'))
|
||||
if (c == CTRL('Z'))
|
||||
backend_special(ldisc->backend, SS_SUSP, 0);
|
||||
if (c == CTRL('\\'))
|
||||
if (c == CTRL('\\'))
|
||||
backend_special(ldisc->backend, SS_ABORT, 0);
|
||||
break;
|
||||
case CTRL('R'): /* redraw line */
|
||||
if (ECHOING) {
|
||||
int i;
|
||||
c_write(ldisc, "^R\r\n", 4);
|
||||
for (i = 0; i < ldisc->buflen; i++)
|
||||
pwrite(ldisc, ldisc->buf[i]);
|
||||
}
|
||||
break;
|
||||
case CTRL('V'): /* quote next char */
|
||||
ldisc->quotenext = true;
|
||||
break;
|
||||
case CTRL('D'): /* logout or send */
|
||||
if (ldisc->buflen == 0) {
|
||||
break;
|
||||
case CTRL('R'): /* redraw line */
|
||||
if (ECHOING) {
|
||||
int i;
|
||||
c_write(ldisc, "^R\r\n", 4);
|
||||
for (i = 0; i < ldisc->buflen; i++)
|
||||
pwrite(ldisc, ldisc->buf[i]);
|
||||
}
|
||||
break;
|
||||
case CTRL('V'): /* quote next char */
|
||||
ldisc->quotenext = true;
|
||||
break;
|
||||
case CTRL('D'): /* logout or send */
|
||||
if (ldisc->buflen == 0) {
|
||||
backend_special(ldisc->backend, SS_EOF, 0);
|
||||
} else {
|
||||
} else {
|
||||
backend_send(ldisc->backend, ldisc->buf, ldisc->buflen);
|
||||
ldisc->buflen = 0;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
* This particularly hideous bit of code from RDB
|
||||
* allows ordinary ^M^J to do the same thing as
|
||||
* magic-^M when in Raw protocol. The line `case
|
||||
* KCTRL('M'):' is _inside_ the if block. Thus:
|
||||
*
|
||||
* - receiving regular ^M goes straight to the
|
||||
* default clause and inserts as a literal ^M.
|
||||
* - receiving regular ^J _not_ directly after a
|
||||
* literal ^M (or not in Raw protocol) fails the
|
||||
* if condition, leaps to the bottom of the if,
|
||||
* and falls through into the default clause
|
||||
* again.
|
||||
* - receiving regular ^J just after a literal ^M
|
||||
* in Raw protocol passes the if condition,
|
||||
* deletes the literal ^M, and falls through
|
||||
* into the magic-^M code
|
||||
* - receiving a magic-^M empties the line buffer,
|
||||
* signals end-of-line in one of the various
|
||||
* entertaining ways, and _doesn't_ fall out of
|
||||
* the bottom of the if and through to the
|
||||
* default clause because of the break.
|
||||
*/
|
||||
case CTRL('J'):
|
||||
if (ldisc->protocol == PROT_RAW &&
|
||||
ldisc->buflen > 0 && ldisc->buf[ldisc->buflen - 1] == '\r') {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
/* FALLTHROUGH */
|
||||
case KCTRL('M'): /* send with newline */
|
||||
if (ldisc->buflen > 0)
|
||||
ldisc->buflen = 0;
|
||||
}
|
||||
break;
|
||||
/*
|
||||
* This particularly hideous bit of code from RDB
|
||||
* allows ordinary ^M^J to do the same thing as
|
||||
* magic-^M when in Raw protocol. The line `case
|
||||
* KCTRL('M'):' is _inside_ the if block. Thus:
|
||||
*
|
||||
* - receiving regular ^M goes straight to the
|
||||
* default clause and inserts as a literal ^M.
|
||||
* - receiving regular ^J _not_ directly after a
|
||||
* literal ^M (or not in Raw protocol) fails the
|
||||
* if condition, leaps to the bottom of the if,
|
||||
* and falls through into the default clause
|
||||
* again.
|
||||
* - receiving regular ^J just after a literal ^M
|
||||
* in Raw protocol passes the if condition,
|
||||
* deletes the literal ^M, and falls through
|
||||
* into the magic-^M code
|
||||
* - receiving a magic-^M empties the line buffer,
|
||||
* signals end-of-line in one of the various
|
||||
* entertaining ways, and _doesn't_ fall out of
|
||||
* the bottom of the if and through to the
|
||||
* default clause because of the break.
|
||||
*/
|
||||
case CTRL('J'):
|
||||
if (ldisc->protocol == PROT_RAW &&
|
||||
ldisc->buflen > 0 && ldisc->buf[ldisc->buflen - 1] == '\r') {
|
||||
if (ECHOING)
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
/* FALLTHROUGH */
|
||||
case KCTRL('M'): /* send with newline */
|
||||
if (ldisc->buflen > 0)
|
||||
backend_send(ldisc->backend,
|
||||
ldisc->buf, ldisc->buflen);
|
||||
if (ldisc->protocol == PROT_RAW)
|
||||
if (ldisc->protocol == PROT_RAW)
|
||||
backend_send(ldisc->backend, "\r\n", 2);
|
||||
else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
|
||||
else if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
|
||||
backend_special(ldisc->backend, SS_EOL, 0);
|
||||
else
|
||||
else
|
||||
backend_send(ldisc->backend, "\r", 1);
|
||||
if (ECHOING)
|
||||
c_write(ldisc, "\r\n", 2);
|
||||
ldisc->buflen = 0;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default: /* get to this label from ^V handler */
|
||||
if (ECHOING)
|
||||
c_write(ldisc, "\r\n", 2);
|
||||
ldisc->buflen = 0;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default: /* get to this label from ^V handler */
|
||||
default_case:
|
||||
sgrowarray(ldisc->buf, ldisc->bufsiz, ldisc->buflen);
|
||||
ldisc->buf[ldisc->buflen++] = c;
|
||||
if (ECHOING)
|
||||
pwrite(ldisc, (unsigned char) c);
|
||||
ldisc->quotenext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ldisc->buf[ldisc->buflen++] = c;
|
||||
if (ECHOING)
|
||||
pwrite(ldisc, (unsigned char) c);
|
||||
ldisc->quotenext = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ldisc->buflen != 0) {
|
||||
if (ldisc->buflen != 0) {
|
||||
backend_send(ldisc->backend, ldisc->buf, ldisc->buflen);
|
||||
while (ldisc->buflen > 0) {
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
}
|
||||
}
|
||||
if (len > 0) {
|
||||
if (ECHOING)
|
||||
c_write(ldisc, buf, len);
|
||||
if (keyflag && ldisc->protocol == PROT_TELNET && len == 1) {
|
||||
switch (buf[0]) {
|
||||
case CTRL('M'):
|
||||
if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
|
||||
while (ldisc->buflen > 0) {
|
||||
bsb(ldisc, plen(ldisc, ldisc->buf[ldisc->buflen - 1]));
|
||||
ldisc->buflen--;
|
||||
}
|
||||
}
|
||||
if (len > 0) {
|
||||
if (ECHOING)
|
||||
c_write(ldisc, buf, len);
|
||||
if (keyflag && ldisc->protocol == PROT_TELNET && len == 1) {
|
||||
switch (buf[0]) {
|
||||
case CTRL('M'):
|
||||
if (ldisc->protocol == PROT_TELNET && ldisc->telnet_newline)
|
||||
backend_special(ldisc->backend, SS_EOL, 0);
|
||||
else
|
||||
else
|
||||
backend_send(ldisc->backend, "\r", 1);
|
||||
break;
|
||||
case CTRL('?'):
|
||||
case CTRL('H'):
|
||||
if (ldisc->telnet_keyboard) {
|
||||
break;
|
||||
case CTRL('?'):
|
||||
case CTRL('H'):
|
||||
if (ldisc->telnet_keyboard) {
|
||||
backend_special(ldisc->backend, SS_EC, 0);
|
||||
break;
|
||||
}
|
||||
case CTRL('C'):
|
||||
if (ldisc->telnet_keyboard) {
|
||||
break;
|
||||
}
|
||||
case CTRL('C'):
|
||||
if (ldisc->telnet_keyboard) {
|
||||
backend_special(ldisc->backend, SS_IP, 0);
|
||||
break;
|
||||
}
|
||||
case CTRL('Z'):
|
||||
if (ldisc->telnet_keyboard) {
|
||||
break;
|
||||
}
|
||||
case CTRL('Z'):
|
||||
if (ldisc->telnet_keyboard) {
|
||||
backend_special(ldisc->backend, SS_SUSP, 0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
default:
|
||||
backend_send(ldisc->backend, buf, len);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
} else
|
||||
backend_send(ldisc->backend, buf, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
298
logging.c
298
logging.c
|
@ -19,7 +19,7 @@ struct LogContext {
|
|||
Filename *currlogfilename;
|
||||
LogPolicy *lp;
|
||||
Conf *conf;
|
||||
int logtype; /* cached out of conf */
|
||||
int logtype; /* cached out of conf */
|
||||
};
|
||||
|
||||
static Filename *xlatlognam(Filename *s, char *hostname, int port,
|
||||
|
@ -39,19 +39,19 @@ static void logwrite(LogContext *ctx, ptrlen data)
|
|||
* those three _after_ processing L_CLOSED.
|
||||
*/
|
||||
if (ctx->state == L_CLOSED)
|
||||
logfopen(ctx);
|
||||
logfopen(ctx);
|
||||
|
||||
if (ctx->state == L_OPENING) {
|
||||
bufchain_add(&ctx->queue, data.ptr, data.len);
|
||||
bufchain_add(&ctx->queue, data.ptr, data.len);
|
||||
} else if (ctx->state == L_OPEN) {
|
||||
assert(ctx->lgfp);
|
||||
if (fwrite(data.ptr, 1, data.len, ctx->lgfp) < data.len) {
|
||||
logfclose(ctx);
|
||||
ctx->state = L_ERROR;
|
||||
assert(ctx->lgfp);
|
||||
if (fwrite(data.ptr, 1, data.len, ctx->lgfp) < data.len) {
|
||||
logfclose(ctx);
|
||||
ctx->state = L_ERROR;
|
||||
lp_eventlog(ctx->lp, "Disabled writing session log "
|
||||
"due to error while writing");
|
||||
}
|
||||
} /* else L_ERROR, so ignore the write */
|
||||
}
|
||||
} /* else L_ERROR, so ignore the write */
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -77,8 +77,8 @@ static void logprintf(LogContext *ctx, const char *fmt, ...)
|
|||
void logflush(LogContext *ctx)
|
||||
{
|
||||
if (ctx->logtype > 0)
|
||||
if (ctx->state == L_OPEN)
|
||||
fflush(ctx->lgfp);
|
||||
if (ctx->state == L_OPEN)
|
||||
fflush(ctx->lgfp);
|
||||
}
|
||||
|
||||
static void logfopen_callback(void *vctx, int mode)
|
||||
|
@ -90,36 +90,36 @@ static void logfopen_callback(void *vctx, int mode)
|
|||
bool shout = false;
|
||||
|
||||
if (mode == 0) {
|
||||
ctx->state = L_ERROR; /* disable logging */
|
||||
ctx->state = L_ERROR; /* disable logging */
|
||||
} else {
|
||||
fmode = (mode == 1 ? "ab" : "wb");
|
||||
ctx->lgfp = f_open(ctx->currlogfilename, fmode, false);
|
||||
if (ctx->lgfp) {
|
||||
ctx->state = L_OPEN;
|
||||
fmode = (mode == 1 ? "ab" : "wb");
|
||||
ctx->lgfp = f_open(ctx->currlogfilename, fmode, false);
|
||||
if (ctx->lgfp) {
|
||||
ctx->state = L_OPEN;
|
||||
} else {
|
||||
ctx->state = L_ERROR;
|
||||
ctx->state = L_ERROR;
|
||||
shout = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->state == L_OPEN && conf_get_bool(ctx->conf, CONF_logheader)) {
|
||||
/* Write header line into log file. */
|
||||
tm = ltime();
|
||||
strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
|
||||
logprintf(ctx, "=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s"
|
||||
" =~=~=~=~=~=~=~=~=~=~=~=\r\n", buf);
|
||||
/* Write header line into log file. */
|
||||
tm = ltime();
|
||||
strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
|
||||
logprintf(ctx, "=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s"
|
||||
" =~=~=~=~=~=~=~=~=~=~=~=\r\n", buf);
|
||||
}
|
||||
|
||||
event = dupprintf("%s session log (%s mode) to file: %s",
|
||||
ctx->state == L_ERROR ?
|
||||
(mode == 0 ? "Disabled writing" : "Error writing") :
|
||||
(mode == 1 ? "Appending" : "Writing new"),
|
||||
(ctx->logtype == LGTYP_ASCII ? "ASCII" :
|
||||
ctx->logtype == LGTYP_DEBUG ? "raw" :
|
||||
ctx->logtype == LGTYP_PACKETS ? "SSH packets" :
|
||||
ctx->logtype == LGTYP_SSHRAW ? "SSH raw data" :
|
||||
"unknown"),
|
||||
filename_to_str(ctx->currlogfilename));
|
||||
ctx->state == L_ERROR ?
|
||||
(mode == 0 ? "Disabled writing" : "Error writing") :
|
||||
(mode == 1 ? "Appending" : "Writing new"),
|
||||
(ctx->logtype == LGTYP_ASCII ? "ASCII" :
|
||||
ctx->logtype == LGTYP_DEBUG ? "raw" :
|
||||
ctx->logtype == LGTYP_PACKETS ? "SSH packets" :
|
||||
ctx->logtype == LGTYP_SSHRAW ? "SSH raw data" :
|
||||
"unknown"),
|
||||
filename_to_str(ctx->currlogfilename));
|
||||
lp_eventlog(ctx->lp, event);
|
||||
if (shout) {
|
||||
/*
|
||||
|
@ -138,8 +138,8 @@ static void logfopen_callback(void *vctx, int mode)
|
|||
assert(ctx->state != L_OPENING); /* make _sure_ it won't be requeued */
|
||||
while (bufchain_size(&ctx->queue)) {
|
||||
ptrlen data = bufchain_prefix(&ctx->queue);
|
||||
logwrite(ctx, data);
|
||||
bufchain_consume(&ctx->queue, data.len);
|
||||
logwrite(ctx, data);
|
||||
bufchain_consume(&ctx->queue, data.len);
|
||||
}
|
||||
logflush(ctx);
|
||||
}
|
||||
|
@ -156,42 +156,42 @@ void logfopen(LogContext *ctx)
|
|||
|
||||
/* Prevent repeat calls */
|
||||
if (ctx->state != L_CLOSED)
|
||||
return;
|
||||
return;
|
||||
|
||||
if (!ctx->logtype)
|
||||
return;
|
||||
return;
|
||||
|
||||
tm = ltime();
|
||||
|
||||
/* substitute special codes in file name */
|
||||
if (ctx->currlogfilename)
|
||||
filename_free(ctx->currlogfilename);
|
||||
ctx->currlogfilename =
|
||||
ctx->currlogfilename =
|
||||
xlatlognam(conf_get_filename(ctx->conf, CONF_logfilename),
|
||||
conf_get_str(ctx->conf, CONF_host),
|
||||
conf_get_int(ctx->conf, CONF_port), &tm);
|
||||
|
||||
if (open_for_write_would_lose_data(ctx->currlogfilename)) {
|
||||
int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr);
|
||||
if (logxfovr != LGXF_ASK) {
|
||||
mode = ((logxfovr == LGXF_OVR) ? 2 : 1);
|
||||
} else
|
||||
int logxfovr = conf_get_int(ctx->conf, CONF_logxfovr);
|
||||
if (logxfovr != LGXF_ASK) {
|
||||
mode = ((logxfovr == LGXF_OVR) ? 2 : 1);
|
||||
} else
|
||||
mode = lp_askappend(ctx->lp, ctx->currlogfilename,
|
||||
logfopen_callback, ctx);
|
||||
} else
|
||||
mode = 2; /* create == overwrite */
|
||||
mode = 2; /* create == overwrite */
|
||||
|
||||
if (mode < 0)
|
||||
ctx->state = L_OPENING;
|
||||
ctx->state = L_OPENING;
|
||||
else
|
||||
logfopen_callback(ctx, mode); /* open the file */
|
||||
logfopen_callback(ctx, mode); /* open the file */
|
||||
}
|
||||
|
||||
void logfclose(LogContext *ctx)
|
||||
{
|
||||
if (ctx->lgfp) {
|
||||
fclose(ctx->lgfp);
|
||||
ctx->lgfp = NULL;
|
||||
fclose(ctx->lgfp);
|
||||
ctx->lgfp = NULL;
|
||||
}
|
||||
ctx->state = L_CLOSED;
|
||||
}
|
||||
|
@ -202,8 +202,8 @@ void logfclose(LogContext *ctx)
|
|||
void logtraffic(LogContext *ctx, unsigned char c, int logmode)
|
||||
{
|
||||
if (ctx->logtype > 0) {
|
||||
if (ctx->logtype == logmode)
|
||||
logwrite(ctx, make_ptrlen(&c, 1));
|
||||
if (ctx->logtype == logmode)
|
||||
logwrite(ctx, make_ptrlen(&c, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,9 +274,9 @@ void logeventf(LogContext *ctx, const char *fmt, ...)
|
|||
* Set of blanking areas must be in increasing order.
|
||||
*/
|
||||
void log_packet(LogContext *ctx, int direction, int type,
|
||||
const char *texttype, const void *data, size_t len,
|
||||
int n_blanks, const struct logblank_t *blanks,
|
||||
const unsigned long *seq,
|
||||
const char *texttype, const void *data, size_t len,
|
||||
int n_blanks, const struct logblank_t *blanks,
|
||||
const unsigned long *seq,
|
||||
unsigned downstream_id, const char *additional_log_text)
|
||||
{
|
||||
char dumpdata[128], smalldata[5];
|
||||
|
@ -285,20 +285,20 @@ void log_packet(LogContext *ctx, int direction, int type,
|
|||
|
||||
if (!(ctx->logtype == LGTYP_SSHRAW ||
|
||||
(ctx->logtype == LGTYP_PACKETS && texttype)))
|
||||
return;
|
||||
return;
|
||||
|
||||
/* Packet header. */
|
||||
if (texttype) {
|
||||
logprintf(ctx, "%s packet ",
|
||||
direction == PKT_INCOMING ? "Incoming" : "Outgoing");
|
||||
|
||||
if (seq)
|
||||
logprintf(ctx, "#0x%lx, ", *seq);
|
||||
if (seq)
|
||||
logprintf(ctx, "#0x%lx, ", *seq);
|
||||
|
||||
logprintf(ctx, "type %d / 0x%02x (%s)", type, type, texttype);
|
||||
|
||||
if (downstream_id) {
|
||||
logprintf(ctx, " on behalf of downstream #%u", downstream_id);
|
||||
logprintf(ctx, " on behalf of downstream #%u", downstream_id);
|
||||
if (additional_log_text)
|
||||
logprintf(ctx, " (%s)", additional_log_text);
|
||||
}
|
||||
|
@ -315,8 +315,8 @@ void log_packet(LogContext *ctx, int direction, int type,
|
|||
*/
|
||||
char buf[256];
|
||||
struct tm tm;
|
||||
tm = ltime();
|
||||
strftime(buf, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
tm = ltime();
|
||||
strftime(buf, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
logprintf(ctx, "%s raw data at %s\r\n",
|
||||
direction == PKT_INCOMING ? "Incoming" : "Outgoing",
|
||||
buf);
|
||||
|
@ -327,68 +327,68 @@ void log_packet(LogContext *ctx, int direction, int type,
|
|||
* parts as specified.
|
||||
*/
|
||||
while (p < len) {
|
||||
int blktype;
|
||||
int blktype;
|
||||
|
||||
/* Move to a current entry in the blanking array. */
|
||||
while ((b < n_blanks) &&
|
||||
(p >= blanks[b].offset + blanks[b].len))
|
||||
b++;
|
||||
/* Work out what type of blanking to apply to
|
||||
* this byte. */
|
||||
blktype = PKTLOG_EMIT; /* default */
|
||||
if ((b < n_blanks) &&
|
||||
(p >= blanks[b].offset) &&
|
||||
(p < blanks[b].offset + blanks[b].len))
|
||||
blktype = blanks[b].type;
|
||||
/* Move to a current entry in the blanking array. */
|
||||
while ((b < n_blanks) &&
|
||||
(p >= blanks[b].offset + blanks[b].len))
|
||||
b++;
|
||||
/* Work out what type of blanking to apply to
|
||||
* this byte. */
|
||||
blktype = PKTLOG_EMIT; /* default */
|
||||
if ((b < n_blanks) &&
|
||||
(p >= blanks[b].offset) &&
|
||||
(p < blanks[b].offset + blanks[b].len))
|
||||
blktype = blanks[b].type;
|
||||
|
||||
/* If we're about to stop omitting, it's time to say how
|
||||
* much we omitted. */
|
||||
if ((blktype != PKTLOG_OMIT) && omitted) {
|
||||
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
||||
omitted, (omitted==1?"":"s"));
|
||||
omitted = 0;
|
||||
}
|
||||
/* If we're about to stop omitting, it's time to say how
|
||||
* much we omitted. */
|
||||
if ((blktype != PKTLOG_OMIT) && omitted) {
|
||||
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
||||
omitted, (omitted==1?"":"s"));
|
||||
omitted = 0;
|
||||
}
|
||||
|
||||
/* (Re-)initialise dumpdata as necessary
|
||||
* (start of row, or if we've just stopped omitting) */
|
||||
if (!output_pos && !omitted)
|
||||
sprintf(dumpdata, " %08zx%*s\r\n", p-(p%16), 1+3*16+2+16, "");
|
||||
/* (Re-)initialise dumpdata as necessary
|
||||
* (start of row, or if we've just stopped omitting) */
|
||||
if (!output_pos && !omitted)
|
||||
sprintf(dumpdata, " %08zx%*s\r\n", p-(p%16), 1+3*16+2+16, "");
|
||||
|
||||
/* Deal with the current byte. */
|
||||
if (blktype == PKTLOG_OMIT) {
|
||||
omitted++;
|
||||
} else {
|
||||
int c;
|
||||
if (blktype == PKTLOG_BLANK) {
|
||||
c = 'X';
|
||||
sprintf(smalldata, "XX");
|
||||
} else { /* PKTLOG_EMIT */
|
||||
c = ((unsigned char *)data)[p];
|
||||
sprintf(smalldata, "%02x", c);
|
||||
}
|
||||
dumpdata[10+2+3*(p%16)] = smalldata[0];
|
||||
dumpdata[10+2+3*(p%16)+1] = smalldata[1];
|
||||
dumpdata[10+1+3*16+2+(p%16)] = (c >= 0x20 && c < 0x7F ? c : '.');
|
||||
output_pos = (p%16) + 1;
|
||||
}
|
||||
/* Deal with the current byte. */
|
||||
if (blktype == PKTLOG_OMIT) {
|
||||
omitted++;
|
||||
} else {
|
||||
int c;
|
||||
if (blktype == PKTLOG_BLANK) {
|
||||
c = 'X';
|
||||
sprintf(smalldata, "XX");
|
||||
} else { /* PKTLOG_EMIT */
|
||||
c = ((unsigned char *)data)[p];
|
||||
sprintf(smalldata, "%02x", c);
|
||||
}
|
||||
dumpdata[10+2+3*(p%16)] = smalldata[0];
|
||||
dumpdata[10+2+3*(p%16)+1] = smalldata[1];
|
||||
dumpdata[10+1+3*16+2+(p%16)] = (c >= 0x20 && c < 0x7F ? c : '.');
|
||||
output_pos = (p%16) + 1;
|
||||
}
|
||||
|
||||
p++;
|
||||
p++;
|
||||
|
||||
/* Flush row if necessary */
|
||||
if (((p % 16) == 0) || (p == len) || omitted) {
|
||||
if (output_pos) {
|
||||
strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n");
|
||||
logwrite(ctx, ptrlen_from_asciz(dumpdata));
|
||||
output_pos = 0;
|
||||
}
|
||||
}
|
||||
/* Flush row if necessary */
|
||||
if (((p % 16) == 0) || (p == len) || omitted) {
|
||||
if (output_pos) {
|
||||
strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n");
|
||||
logwrite(ctx, ptrlen_from_asciz(dumpdata));
|
||||
output_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Tidy up */
|
||||
if (omitted)
|
||||
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
||||
omitted, (omitted==1?"":"s"));
|
||||
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
||||
omitted, (omitted==1?"":"s"));
|
||||
logflush(ctx);
|
||||
}
|
||||
|
||||
|
@ -420,15 +420,15 @@ void log_reconfig(LogContext *ctx, Conf *conf)
|
|||
bool reset_logging;
|
||||
|
||||
if (!filename_equal(conf_get_filename(ctx->conf, CONF_logfilename),
|
||||
conf_get_filename(conf, CONF_logfilename)) ||
|
||||
conf_get_int(ctx->conf, CONF_logtype) !=
|
||||
conf_get_int(conf, CONF_logtype))
|
||||
reset_logging = true;
|
||||
conf_get_filename(conf, CONF_logfilename)) ||
|
||||
conf_get_int(ctx->conf, CONF_logtype) !=
|
||||
conf_get_int(conf, CONF_logtype))
|
||||
reset_logging = true;
|
||||
else
|
||||
reset_logging = false;
|
||||
reset_logging = false;
|
||||
|
||||
if (reset_logging)
|
||||
logfclose(ctx);
|
||||
logfclose(ctx);
|
||||
|
||||
conf_free(ctx->conf);
|
||||
ctx->conf = conf_copy(conf);
|
||||
|
@ -436,7 +436,7 @@ void log_reconfig(LogContext *ctx, Conf *conf)
|
|||
ctx->logtype = conf_get_int(ctx->conf, CONF_logtype);
|
||||
|
||||
if (reset_logging)
|
||||
logfopen(ctx);
|
||||
logfopen(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -459,48 +459,48 @@ static Filename *xlatlognam(Filename *src, char *hostname, int port,
|
|||
|
||||
while (*s) {
|
||||
bool sanitise = false;
|
||||
/* Let (bufp, len) be the string to append. */
|
||||
bufp = buf; /* don't usually override this */
|
||||
if (*s == '&') {
|
||||
char c;
|
||||
s++;
|
||||
size = 0;
|
||||
if (*s) switch (c = *s++, tolower((unsigned char)c)) {
|
||||
case 'y':
|
||||
size = strftime(buf, sizeof(buf), "%Y", tm);
|
||||
break;
|
||||
case 'm':
|
||||
size = strftime(buf, sizeof(buf), "%m", tm);
|
||||
break;
|
||||
case 'd':
|
||||
size = strftime(buf, sizeof(buf), "%d", tm);
|
||||
break;
|
||||
case 't':
|
||||
size = strftime(buf, sizeof(buf), "%H%M%S", tm);
|
||||
break;
|
||||
case 'h':
|
||||
bufp = hostname;
|
||||
size = strlen(bufp);
|
||||
break;
|
||||
case 'p':
|
||||
/* Let (bufp, len) be the string to append. */
|
||||
bufp = buf; /* don't usually override this */
|
||||
if (*s == '&') {
|
||||
char c;
|
||||
s++;
|
||||
size = 0;
|
||||
if (*s) switch (c = *s++, tolower((unsigned char)c)) {
|
||||
case 'y':
|
||||
size = strftime(buf, sizeof(buf), "%Y", tm);
|
||||
break;
|
||||
case 'm':
|
||||
size = strftime(buf, sizeof(buf), "%m", tm);
|
||||
break;
|
||||
case 'd':
|
||||
size = strftime(buf, sizeof(buf), "%d", tm);
|
||||
break;
|
||||
case 't':
|
||||
size = strftime(buf, sizeof(buf), "%H%M%S", tm);
|
||||
break;
|
||||
case 'h':
|
||||
bufp = hostname;
|
||||
size = strlen(bufp);
|
||||
break;
|
||||
case 'p':
|
||||
size = sprintf(buf, "%d", port);
|
||||
break;
|
||||
default:
|
||||
buf[0] = '&';
|
||||
size = 1;
|
||||
if (c != '&')
|
||||
buf[size++] = c;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
buf[0] = '&';
|
||||
size = 1;
|
||||
if (c != '&')
|
||||
buf[size++] = c;
|
||||
}
|
||||
/* Never allow path separators - or any other illegal
|
||||
* filename character - to come out of any of these
|
||||
* auto-format directives. E.g. 'hostname' can contain
|
||||
* colons, if it's an IPv6 address, and colons aren't
|
||||
* legal in filenames on Windows. */
|
||||
sanitise = true;
|
||||
} else {
|
||||
buf[0] = *s++;
|
||||
size = 1;
|
||||
}
|
||||
} else {
|
||||
buf[0] = *s++;
|
||||
size = 1;
|
||||
}
|
||||
while (size-- > 0) {
|
||||
char c = *bufp++;
|
||||
if (sanitise)
|
||||
|
|
12
mainchan.c
12
mainchan.c
|
@ -134,15 +134,15 @@ static void mainchan_open_confirmation(Channel *chan)
|
|||
sshfwd_hint_channel_is_simple(mc->sc);
|
||||
|
||||
if (mc->type == MAINCHAN_SESSION) {
|
||||
/*
|
||||
* Send the CHANNEL_REQUESTS for the main session channel.
|
||||
/*
|
||||
* Send the CHANNEL_REQUESTS for the main session channel.
|
||||
*/
|
||||
char *key, *val, *cmd;
|
||||
struct X11Display *x11disp;
|
||||
struct X11FakeAuth *x11auth;
|
||||
bool retry_cmd_now = false;
|
||||
|
||||
if (conf_get_bool(mc->conf, CONF_x11_forward)) {;
|
||||
if (conf_get_bool(mc->conf, CONF_x11_forward)) {;
|
||||
char *x11_setup_err;
|
||||
if ((x11disp = x11_setup_display(
|
||||
conf_get_str(mc->conf, CONF_x11_display),
|
||||
|
@ -161,12 +161,12 @@ static void mainchan_open_confirmation(Channel *chan)
|
|||
}
|
||||
}
|
||||
|
||||
if (ssh_agent_forwarding_permitted(mc->cl)) {
|
||||
if (ssh_agent_forwarding_permitted(mc->cl)) {
|
||||
sshfwd_request_agent_forwarding(mc->sc, true);
|
||||
mc->req_agent = true;
|
||||
}
|
||||
|
||||
if (!conf_get_bool(mc->conf, CONF_nopty)) {
|
||||
if (!conf_get_bool(mc->conf, CONF_nopty)) {
|
||||
sshfwd_request_pty(
|
||||
mc->sc, true, mc->conf, mc->term_width, mc->term_height);
|
||||
mc->req_pty = true;
|
||||
|
@ -327,7 +327,7 @@ static void mainchan_ready(mainchan *mc)
|
|||
/* If an EOF arrived before we were ready, handle it now. */
|
||||
if (mc->eof_pending) {
|
||||
mc->eof_pending = false;
|
||||
mainchan_special_cmd(mc, SS_EOF, 0);
|
||||
mainchan_special_cmd(mc, SS_EOF, 0);
|
||||
}
|
||||
|
||||
ssh_ldisc_update(mc->ppl->ssh);
|
||||
|
|
22
memory.c
22
memory.c
|
@ -46,22 +46,22 @@ void *saferealloc(void *ptr, size_t n, size_t size)
|
|||
void *p;
|
||||
|
||||
if (n > INT_MAX / size) {
|
||||
p = NULL;
|
||||
p = NULL;
|
||||
} else {
|
||||
size *= n;
|
||||
if (!ptr) {
|
||||
size *= n;
|
||||
if (!ptr) {
|
||||
#ifdef MINEFIELD
|
||||
p = minefield_c_malloc(size);
|
||||
p = minefield_c_malloc(size);
|
||||
#else
|
||||
p = malloc(size);
|
||||
p = malloc(size);
|
||||
#endif
|
||||
} else {
|
||||
} else {
|
||||
#ifdef MINEFIELD
|
||||
p = minefield_c_realloc(ptr, size);
|
||||
p = minefield_c_realloc(ptr, size);
|
||||
#else
|
||||
p = realloc(ptr, size);
|
||||
p = realloc(ptr, size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!p)
|
||||
|
@ -74,9 +74,9 @@ void safefree(void *ptr)
|
|||
{
|
||||
if (ptr) {
|
||||
#ifdef MINEFIELD
|
||||
minefield_c_free(ptr);
|
||||
minefield_c_free(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
1254
minibidi.c
1254
minibidi.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
18
misc.c
18
misc.c
|
@ -85,11 +85,11 @@ void free_prompts(prompts_t *p)
|
|||
{
|
||||
size_t i;
|
||||
for (i=0; i < p->n_prompts; i++) {
|
||||
prompt_t *pr = p->prompts[i];
|
||||
smemclr(pr->result, pr->resultsize); /* burn the evidence */
|
||||
sfree(pr->result);
|
||||
sfree(pr->prompt);
|
||||
sfree(pr);
|
||||
prompt_t *pr = p->prompts[i];
|
||||
smemclr(pr->result, pr->resultsize); /* burn the evidence */
|
||||
sfree(pr->result);
|
||||
sfree(pr->prompt);
|
||||
sfree(pr);
|
||||
}
|
||||
sfree(p->prompts);
|
||||
sfree(p->name);
|
||||
|
@ -104,17 +104,17 @@ void free_prompts(prompts_t *p)
|
|||
bool conf_launchable(Conf *conf)
|
||||
{
|
||||
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
|
||||
return conf_get_str(conf, CONF_serline)[0] != 0;
|
||||
return conf_get_str(conf, CONF_serline)[0] != 0;
|
||||
else
|
||||
return conf_get_str(conf, CONF_host)[0] != 0;
|
||||
return conf_get_str(conf, CONF_host)[0] != 0;
|
||||
}
|
||||
|
||||
char const *conf_dest(Conf *conf)
|
||||
{
|
||||
if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
|
||||
return conf_get_str(conf, CONF_serline);
|
||||
return conf_get_str(conf, CONF_serline);
|
||||
else
|
||||
return conf_get_str(conf, CONF_host);
|
||||
return conf_get_str(conf, CONF_host);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
4
misc.h
4
misc.h
|
@ -9,8 +9,8 @@
|
|||
#include "puttymem.h"
|
||||
#include "marshal.h"
|
||||
|
||||
#include <stdio.h> /* for FILE * */
|
||||
#include <stdarg.h> /* for va_list */
|
||||
#include <stdio.h> /* for FILE * */
|
||||
#include <stdarg.h> /* for va_list */
|
||||
#include <stdlib.h> /* for abort */
|
||||
#include <time.h> /* for struct tm */
|
||||
#include <limits.h> /* for INT_MAX/MIN */
|
||||
|
|
514
mkfiles.pl
514
mkfiles.pl
|
@ -67,9 +67,9 @@ while (<IN>) {
|
|||
# If we're gathering help text, keep doing so.
|
||||
if (defined $divert) {
|
||||
if ((defined $_[0]) && $_[0] eq "!end") {
|
||||
$divert = undef;
|
||||
$divert = undef;
|
||||
} else {
|
||||
${$divert} .= "$_\n";
|
||||
${$divert} .= "$_\n";
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
@ -99,13 +99,13 @@ while (<IN>) {
|
|||
if ($_[0] eq "!forceobj") { $forceobj{$_[1]} = 1; next; }
|
||||
if ($_[0] eq "!begin") {
|
||||
if ($_[1] =~ /^>(.*)/) {
|
||||
$divert = \$auxfiles{$1};
|
||||
$divert = \$auxfiles{$1};
|
||||
} elsif (&mfval($_[1])) {
|
||||
$sect = $_[2] ? $_[2] : "end";
|
||||
$divert = \($makefile_extra{$_[1]}->{$sect});
|
||||
$divert = \($makefile_extra{$_[1]}->{$sect});
|
||||
} else {
|
||||
$dummy = '';
|
||||
$divert = \$dummy;
|
||||
$dummy = '';
|
||||
$divert = \$dummy;
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ sub mfval($) {
|
|||
# Returns true if the argument is a known makefile type. Otherwise,
|
||||
# prints a warning and returns false;
|
||||
if (grep { $type eq $_ }
|
||||
("vc","vcproj","cygwin","lcc","devcppproj","gtk","unix",
|
||||
("vc","vcproj","cygwin","lcc","devcppproj","gtk","unix",
|
||||
"am","osx","vstudio10","vstudio12","clangcl")) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -290,13 +290,13 @@ sub dirpfx {
|
|||
my $i;
|
||||
|
||||
while (($i = index $path, $sep) >= 0 ||
|
||||
($j = index $path, "/") >= 0) {
|
||||
($j = index $path, "/") >= 0) {
|
||||
if ($i >= 0 and ($j < 0 or $i < $j)) {
|
||||
$path = substr $path, ($i + length $sep);
|
||||
} else {
|
||||
$path = substr $path, ($j + 1);
|
||||
}
|
||||
$ret .= "..$sep";
|
||||
$path = substr $path, ($i + length $sep);
|
||||
} else {
|
||||
$path = substr $path, ($j + 1);
|
||||
}
|
||||
$ret .= "..$sep";
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
@ -560,13 +560,13 @@ if (defined $makefiles{'clangcl'}) {
|
|||
print &splitline("all:" . join "", map { " \$(BUILDDIR)$_.exe" } &progrealnames("G:C"));
|
||||
print "\n\n";
|
||||
foreach $p (&prognames("G:C")) {
|
||||
($prog, $type) = split ",", $p;
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
|
||||
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
|
||||
($prog, $type) = split ",", $p;
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
|
||||
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
|
||||
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
|
||||
$subsys = ($type eq "G") ? "windows" : "console";
|
||||
print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ".
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
|
||||
$subsys = ($type eq "G") ? "windows" : "console";
|
||||
print &splitline("\t\$(LD) \$(LFLAGS) \$(XLFLAGS) ".
|
||||
"/out:\$(BUILDDIR)$prog.exe ".
|
||||
"/lldmap:\$(BUILDDIR)$prog.map ".
|
||||
"/subsystem:$subsys\$(SUBSYSVER) ".
|
||||
|
@ -590,7 +590,7 @@ if (defined $makefiles{'clangcl'}) {
|
|||
sprintf("%s: %s", $rcpp, join " ", @incdeps)) ."\n" .
|
||||
"\t\$(RCPREPROC) \$(RCPPFLAGS) /Fi\$\@ \$<\n\n";
|
||||
$rcdeps[0] = $rcpp;
|
||||
} else {
|
||||
} else {
|
||||
$rule = "\$(CC) /Fo\$(BUILDDIR) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) /c \$<";
|
||||
}
|
||||
print &splitline(sprintf("%s: %s", $d->{obj},
|
||||
|
@ -634,8 +634,8 @@ if (defined $makefiles{'cygwin'}) {
|
|||
"\n".
|
||||
&splitline("CFLAGS = -Wall -O2 -std=gnu99 -Wvla -D_WINDOWS".
|
||||
" -DWIN32S_COMPAT -D_NO_OLDNAMES -D__USE_MINGW_ANSI_STDIO=1 " .
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs)) .
|
||||
"\n".
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs)) .
|
||||
"\n".
|
||||
"LDFLAGS = -s\n".
|
||||
&splitline("RCFLAGS = \$(RCINC) --define WIN32=1 --define _WIN32=1 ".
|
||||
"--define WINVER=0x0400 ".(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
|
||||
|
@ -664,9 +664,9 @@ if (defined $makefiles{'cygwin'}) {
|
|||
join " ", @{$d->{deps}})), "\n";
|
||||
}
|
||||
if ($d->{obj} =~ /\.res\.o$/) {
|
||||
print "\t\$(RC) \$(RCFL) \$(RCFLAGS) ".$d->{deps}->[0]." -o ".$d->{obj}."\n\n";
|
||||
print "\t\$(RC) \$(RCFL) \$(RCFLAGS) ".$d->{deps}->[0]." -o ".$d->{obj}."\n\n";
|
||||
} else {
|
||||
print "\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c ".$d->{deps}->[0]."\n\n";
|
||||
print "\t\$(CC) \$(COMPAT) \$(CFLAGS) \$(XFLAGS) -c ".$d->{deps}->[0]."\n\n";
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
|
@ -709,35 +709,35 @@ if (defined $makefiles{'vc'}) {
|
|||
print &splitline("all:" . join "", map { " \$(BUILDDIR)$_.exe" } &progrealnames("G:C"));
|
||||
print "\n\n";
|
||||
foreach $p (&prognames("G:C")) {
|
||||
($prog, $type) = split ",", $p;
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
|
||||
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
|
||||
($prog, $type) = split ",", $p;
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", undef);
|
||||
print &splitline("\$(BUILDDIR)$prog.exe: " . $objstr), "\n";
|
||||
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
|
||||
$subsys = ($type eq "G") ? "windows" : "console";
|
||||
$objstr = &objects($p, "\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", "X.lib");
|
||||
$subsys = ($type eq "G") ? "windows" : "console";
|
||||
$inlinefilename = "link_$prog";
|
||||
print "\ttype <<$inlinefilename\n";
|
||||
@objlist = split " ", $objstr;
|
||||
@objlines = ("");
|
||||
foreach $i (@objlist) {
|
||||
if (length($objlines[$#objlines] . " $i") > 72) {
|
||||
push @objlines, "";
|
||||
}
|
||||
$objlines[$#objlines] .= " $i";
|
||||
}
|
||||
for ($i=0; $i<=$#objlines; $i++) {
|
||||
print "$objlines[$i]\n";
|
||||
}
|
||||
print "<<\n";
|
||||
print "\tlink \$(LFLAGS) \$(XLFLAGS) -out:\$(BUILDDIR)$prog.exe -map:\$(BUILDDIR)$prog.map -nologo -subsystem:$subsys\$(SUBSYSVER) \@$inlinefilename\n\n";
|
||||
@objlist = split " ", $objstr;
|
||||
@objlines = ("");
|
||||
foreach $i (@objlist) {
|
||||
if (length($objlines[$#objlines] . " $i") > 72) {
|
||||
push @objlines, "";
|
||||
}
|
||||
$objlines[$#objlines] .= " $i";
|
||||
}
|
||||
for ($i=0; $i<=$#objlines; $i++) {
|
||||
print "$objlines[$i]\n";
|
||||
}
|
||||
print "<<\n";
|
||||
print "\tlink \$(LFLAGS) \$(XLFLAGS) -out:\$(BUILDDIR)$prog.exe -map:\$(BUILDDIR)$prog.map -nologo -subsystem:$subsys\$(SUBSYSVER) \@$inlinefilename\n\n";
|
||||
}
|
||||
foreach $d (&deps("\$(BUILDDIR)X.obj", "\$(BUILDDIR)X.res", $dirpfx, "\\", "vc")) {
|
||||
$extradeps = $forceobj{$d->{obj_orig}} ? ["*.c","*.h","*.rc"] : [];
|
||||
print &splitline(sprintf("%s: %s", $d->{obj},
|
||||
join " ", @$extradeps, @{$d->{deps}})), "\n";
|
||||
if ($d->{obj} =~ /.res$/) {
|
||||
print "\trc /Fo@{[$d->{obj}]} \$(RCFL) -r \$(RCFLAGS) ".$d->{deps}->[0],"\n\n";
|
||||
}
|
||||
print "\trc /Fo@{[$d->{obj}]} \$(RCFL) -r \$(RCFLAGS) ".$d->{deps}->[0],"\n\n";
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
foreach $real_srcdir ("", @srcdirs) {
|
||||
|
@ -814,7 +814,7 @@ if (defined $makefiles{'vcproj'}) {
|
|||
# List projects
|
||||
foreach $progname (@prognames) {
|
||||
($windows_project, $type) = split ",", $progname;
|
||||
print "Project: \"$windows_project\"=\".\\$windows_project\\$windows_project.dsp\" - Package Owner=<4>\r\n";
|
||||
print "Project: \"$windows_project\"=\".\\$windows_project\\$windows_project.dsp\" - Package Owner=<4>\r\n";
|
||||
}
|
||||
print
|
||||
"\r\n".
|
||||
|
@ -844,200 +844,200 @@ if (defined $makefiles{'vcproj'}) {
|
|||
chdir $orig_dir;
|
||||
|
||||
sub create_vc_project {
|
||||
my ($all_object_deps, $progname) = @_;
|
||||
# Construct program's dependency info
|
||||
%seen_objects = ();
|
||||
%lib_files = ();
|
||||
%source_files = ();
|
||||
%header_files = ();
|
||||
%resource_files = ();
|
||||
@object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib");
|
||||
foreach $object_file (@object_files) {
|
||||
next if defined $seen_objects{$object_file};
|
||||
$seen_objects{$object_file} = 1;
|
||||
if($object_file =~ /\.lib$/io) {
|
||||
$lib_files{$object_file} = 1;
|
||||
next;
|
||||
}
|
||||
$object_deps = $all_object_deps{$object_file};
|
||||
foreach $object_dep (@$object_deps) {
|
||||
if($object_dep =~ /\.c$/io) {
|
||||
$source_files{$object_dep} = 1;
|
||||
next;
|
||||
}
|
||||
if($object_dep =~ /\.h$/io) {
|
||||
$header_files{$object_dep} = 1;
|
||||
next;
|
||||
}
|
||||
if($object_dep =~ /\.(rc|ico)$/io) {
|
||||
$resource_files{$object_dep} = 1;
|
||||
next;
|
||||
}
|
||||
}
|
||||
}
|
||||
$libs = join " ", sort keys %lib_files;
|
||||
@source_files = sort keys %source_files;
|
||||
@header_files = sort keys %header_files;
|
||||
@resources = sort keys %resource_files;
|
||||
($windows_project, $type) = split ",", $progname;
|
||||
mkdir $windows_project
|
||||
if(! -d $windows_project);
|
||||
chdir $windows_project;
|
||||
$subsys = ($type eq "G") ? "windows" : "console";
|
||||
open OUT, ">$windows_project.dsp"; binmode OUT; select OUT;
|
||||
print
|
||||
"# Microsoft Developer Studio Project File - Name=\"$windows_project\" - Package Owner=<4>\r\n".
|
||||
"# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n".
|
||||
"# ** DO NOT EDIT **\r\n".
|
||||
"\r\n".
|
||||
"# TARGTYPE \"Win32 (x86) Application\" 0x0101\r\n".
|
||||
"\r\n".
|
||||
"CFG=$windows_project - Win32 Debug\r\n".
|
||||
"!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n".
|
||||
"!MESSAGE use the Export Makefile command and run\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE NMAKE /f \"$windows_project.mak\".\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE You can specify a configuration when running NMAKE\r\n".
|
||||
"!MESSAGE by defining the macro CFG on the command line. For example:\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE NMAKE /f \"$windows_project.mak\" CFG=\"$windows_project - Win32 Debug\"\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE Possible choices for configuration are:\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE \"$windows_project - Win32 Release\" (based on \"Win32 (x86) Application\")\r\n".
|
||||
"!MESSAGE \"$windows_project - Win32 Debug\" (based on \"Win32 (x86) Application\")\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"\r\n".
|
||||
"# Begin Project\r\n".
|
||||
"# PROP AllowPerConfigDependencies 0\r\n".
|
||||
"# PROP Scc_ProjName \"\"\r\n".
|
||||
"# PROP Scc_LocalPath \"\"\r\n".
|
||||
"CPP=cl.exe\r\n".
|
||||
"MTL=midl.exe\r\n".
|
||||
"RSC=rc.exe\r\n".
|
||||
"\r\n".
|
||||
"!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP BASE Use_MFC 0\r\n".
|
||||
"# PROP BASE Use_Debug_Libraries 0\r\n".
|
||||
"# PROP BASE Output_Dir \"Release\"\r\n".
|
||||
"# PROP BASE Intermediate_Dir \"Release\"\r\n".
|
||||
"# PROP BASE Target_Dir \"\"\r\n".
|
||||
"# PROP Use_MFC 0\r\n".
|
||||
"# PROP Use_Debug_Libraries 0\r\n".
|
||||
"# PROP Output_Dir \"Release\"\r\n".
|
||||
"# PROP Intermediate_Dir \"Release\"\r\n".
|
||||
"# PROP Ignore_Export_Lib 0\r\n".
|
||||
"# PROP Target_Dir \"\"\r\n".
|
||||
"# ADD BASE CPP /nologo /W3 /GX /O2 ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
|
||||
"# ADD CPP /nologo /W3 /GX /O2 ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
|
||||
"# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n".
|
||||
"# ADD RSC /l 0x809 /d \"NDEBUG\"\r\n".
|
||||
"BSC32=bscmake.exe\r\n".
|
||||
"# ADD BASE BSC32 /nologo\r\n".
|
||||
"# ADD BSC32 /nologo\r\n".
|
||||
"LINK32=link.exe\r\n".
|
||||
"# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /machine:I386\r\n".
|
||||
"# ADD LINK32 $libs /nologo /subsystem:$subsys /machine:I386\r\n".
|
||||
"# SUBTRACT LINK32 /pdb:none\r\n".
|
||||
"\r\n".
|
||||
"!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP BASE Use_MFC 0\r\n".
|
||||
"# PROP BASE Use_Debug_Libraries 1\r\n".
|
||||
"# PROP BASE Output_Dir \"Debug\"\r\n".
|
||||
"# PROP BASE Intermediate_Dir \"Debug\"\r\n".
|
||||
"# PROP BASE Target_Dir \"\"\r\n".
|
||||
"# PROP Use_MFC 0\r\n".
|
||||
"# PROP Use_Debug_Libraries 1\r\n".
|
||||
"# PROP Output_Dir \"Debug\"\r\n".
|
||||
"# PROP Intermediate_Dir \"Debug\"\r\n".
|
||||
"# PROP Ignore_Export_Lib 0\r\n".
|
||||
"# PROP Target_Dir \"\"\r\n".
|
||||
"# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
|
||||
"# ADD CPP /nologo /W3 /Gm /GX /ZI /Od ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
|
||||
"# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD BASE RSC /l 0x809 /d \"_DEBUG\"\r\n".
|
||||
"# ADD RSC /l 0x809 /d \"_DEBUG\"\r\n".
|
||||
"BSC32=bscmake.exe\r\n".
|
||||
"# ADD BASE BSC32 /nologo\r\n".
|
||||
"# ADD BSC32 /nologo\r\n".
|
||||
"LINK32=link.exe\r\n".
|
||||
"# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n".
|
||||
"# ADD LINK32 $libs /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n".
|
||||
"# SUBTRACT LINK32 /pdb:none\r\n".
|
||||
"\r\n".
|
||||
"!ENDIF \r\n".
|
||||
"\r\n".
|
||||
"# Begin Target\r\n".
|
||||
"\r\n".
|
||||
"# Name \"$windows_project - Win32 Release\"\r\n".
|
||||
"# Name \"$windows_project - Win32 Debug\"\r\n".
|
||||
"# Begin Group \"Source Files\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n";
|
||||
foreach $source_file (@source_files) {
|
||||
print
|
||||
"# Begin Source File\r\n".
|
||||
"\r\n".
|
||||
"SOURCE=..\\..\\$source_file\r\n";
|
||||
if($source_file =~ /ssh\.c/io) {
|
||||
# Disable 'Edit and continue' as Visual Studio can't handle the macros
|
||||
print
|
||||
"\r\n".
|
||||
"!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
|
||||
"\r\n".
|
||||
"!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
|
||||
"\r\n".
|
||||
"# ADD CPP /Zi\r\n".
|
||||
"\r\n".
|
||||
"!ENDIF \r\n".
|
||||
"\r\n";
|
||||
}
|
||||
print "# End Source File\r\n";
|
||||
}
|
||||
print
|
||||
"# End Group\r\n".
|
||||
"# Begin Group \"Header Files\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n";
|
||||
foreach $header_file (@header_files) {
|
||||
print
|
||||
"# Begin Source File\r\n".
|
||||
"\r\n".
|
||||
"SOURCE=..\\..\\$header_file\r\n".
|
||||
"# End Source File\r\n";
|
||||
}
|
||||
print
|
||||
"# End Group\r\n".
|
||||
"# Begin Group \"Resource Files\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n";
|
||||
foreach $resource_file (@resources) {
|
||||
print
|
||||
"# Begin Source File\r\n".
|
||||
"\r\n".
|
||||
"SOURCE=..\\..\\$resource_file\r\n".
|
||||
"# End Source File\r\n";
|
||||
}
|
||||
print
|
||||
"# End Group\r\n".
|
||||
"# End Target\r\n".
|
||||
"# End Project\r\n";
|
||||
select STDOUT; close OUT;
|
||||
chdir "..";
|
||||
my ($all_object_deps, $progname) = @_;
|
||||
# Construct program's dependency info
|
||||
%seen_objects = ();
|
||||
%lib_files = ();
|
||||
%source_files = ();
|
||||
%header_files = ();
|
||||
%resource_files = ();
|
||||
@object_files = split " ", &objects($progname, "X.obj", "X.res", "X.lib");
|
||||
foreach $object_file (@object_files) {
|
||||
next if defined $seen_objects{$object_file};
|
||||
$seen_objects{$object_file} = 1;
|
||||
if($object_file =~ /\.lib$/io) {
|
||||
$lib_files{$object_file} = 1;
|
||||
next;
|
||||
}
|
||||
$object_deps = $all_object_deps{$object_file};
|
||||
foreach $object_dep (@$object_deps) {
|
||||
if($object_dep =~ /\.c$/io) {
|
||||
$source_files{$object_dep} = 1;
|
||||
next;
|
||||
}
|
||||
if($object_dep =~ /\.h$/io) {
|
||||
$header_files{$object_dep} = 1;
|
||||
next;
|
||||
}
|
||||
if($object_dep =~ /\.(rc|ico)$/io) {
|
||||
$resource_files{$object_dep} = 1;
|
||||
next;
|
||||
}
|
||||
}
|
||||
}
|
||||
$libs = join " ", sort keys %lib_files;
|
||||
@source_files = sort keys %source_files;
|
||||
@header_files = sort keys %header_files;
|
||||
@resources = sort keys %resource_files;
|
||||
($windows_project, $type) = split ",", $progname;
|
||||
mkdir $windows_project
|
||||
if(! -d $windows_project);
|
||||
chdir $windows_project;
|
||||
$subsys = ($type eq "G") ? "windows" : "console";
|
||||
open OUT, ">$windows_project.dsp"; binmode OUT; select OUT;
|
||||
print
|
||||
"# Microsoft Developer Studio Project File - Name=\"$windows_project\" - Package Owner=<4>\r\n".
|
||||
"# Microsoft Developer Studio Generated Build File, Format Version 6.00\r\n".
|
||||
"# ** DO NOT EDIT **\r\n".
|
||||
"\r\n".
|
||||
"# TARGTYPE \"Win32 (x86) Application\" 0x0101\r\n".
|
||||
"\r\n".
|
||||
"CFG=$windows_project - Win32 Debug\r\n".
|
||||
"!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r\n".
|
||||
"!MESSAGE use the Export Makefile command and run\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE NMAKE /f \"$windows_project.mak\".\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE You can specify a configuration when running NMAKE\r\n".
|
||||
"!MESSAGE by defining the macro CFG on the command line. For example:\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE NMAKE /f \"$windows_project.mak\" CFG=\"$windows_project - Win32 Debug\"\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE Possible choices for configuration are:\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"!MESSAGE \"$windows_project - Win32 Release\" (based on \"Win32 (x86) Application\")\r\n".
|
||||
"!MESSAGE \"$windows_project - Win32 Debug\" (based on \"Win32 (x86) Application\")\r\n".
|
||||
"!MESSAGE \r\n".
|
||||
"\r\n".
|
||||
"# Begin Project\r\n".
|
||||
"# PROP AllowPerConfigDependencies 0\r\n".
|
||||
"# PROP Scc_ProjName \"\"\r\n".
|
||||
"# PROP Scc_LocalPath \"\"\r\n".
|
||||
"CPP=cl.exe\r\n".
|
||||
"MTL=midl.exe\r\n".
|
||||
"RSC=rc.exe\r\n".
|
||||
"\r\n".
|
||||
"!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP BASE Use_MFC 0\r\n".
|
||||
"# PROP BASE Use_Debug_Libraries 0\r\n".
|
||||
"# PROP BASE Output_Dir \"Release\"\r\n".
|
||||
"# PROP BASE Intermediate_Dir \"Release\"\r\n".
|
||||
"# PROP BASE Target_Dir \"\"\r\n".
|
||||
"# PROP Use_MFC 0\r\n".
|
||||
"# PROP Use_Debug_Libraries 0\r\n".
|
||||
"# PROP Output_Dir \"Release\"\r\n".
|
||||
"# PROP Intermediate_Dir \"Release\"\r\n".
|
||||
"# PROP Ignore_Export_Lib 0\r\n".
|
||||
"# PROP Target_Dir \"\"\r\n".
|
||||
"# ADD BASE CPP /nologo /W3 /GX /O2 ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
|
||||
"# ADD CPP /nologo /W3 /GX /O2 ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /c\r\n".
|
||||
"# ADD BASE MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD MTL /nologo /D \"NDEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD BASE RSC /l 0x809 /d \"NDEBUG\"\r\n".
|
||||
"# ADD RSC /l 0x809 /d \"NDEBUG\"\r\n".
|
||||
"BSC32=bscmake.exe\r\n".
|
||||
"# ADD BASE BSC32 /nologo\r\n".
|
||||
"# ADD BSC32 /nologo\r\n".
|
||||
"LINK32=link.exe\r\n".
|
||||
"# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /machine:I386\r\n".
|
||||
"# ADD LINK32 $libs /nologo /subsystem:$subsys /machine:I386\r\n".
|
||||
"# SUBTRACT LINK32 /pdb:none\r\n".
|
||||
"\r\n".
|
||||
"!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP BASE Use_MFC 0\r\n".
|
||||
"# PROP BASE Use_Debug_Libraries 1\r\n".
|
||||
"# PROP BASE Output_Dir \"Debug\"\r\n".
|
||||
"# PROP BASE Intermediate_Dir \"Debug\"\r\n".
|
||||
"# PROP BASE Target_Dir \"\"\r\n".
|
||||
"# PROP Use_MFC 0\r\n".
|
||||
"# PROP Use_Debug_Libraries 1\r\n".
|
||||
"# PROP Output_Dir \"Debug\"\r\n".
|
||||
"# PROP Intermediate_Dir \"Debug\"\r\n".
|
||||
"# PROP Ignore_Export_Lib 0\r\n".
|
||||
"# PROP Target_Dir \"\"\r\n".
|
||||
"# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
|
||||
"# ADD CPP /nologo /W3 /Gm /GX /ZI /Od ".
|
||||
(join " ", map {"/I \"..\\..\\$dirpfx$_\""} @srcdirs) .
|
||||
" /D \"WIN32\" /D \"_DEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" /YX /FD /GZ /c\r\n".
|
||||
"# ADD BASE MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD MTL /nologo /D \"_DEBUG\" /mktyplib203 /win32\r\n".
|
||||
"# ADD BASE RSC /l 0x809 /d \"_DEBUG\"\r\n".
|
||||
"# ADD RSC /l 0x809 /d \"_DEBUG\"\r\n".
|
||||
"BSC32=bscmake.exe\r\n".
|
||||
"# ADD BASE BSC32 /nologo\r\n".
|
||||
"# ADD BSC32 /nologo\r\n".
|
||||
"LINK32=link.exe\r\n".
|
||||
"# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n".
|
||||
"# ADD LINK32 $libs /nologo /subsystem:$subsys /debug /machine:I386 /pdbtype:sept\r\n".
|
||||
"# SUBTRACT LINK32 /pdb:none\r\n".
|
||||
"\r\n".
|
||||
"!ENDIF \r\n".
|
||||
"\r\n".
|
||||
"# Begin Target\r\n".
|
||||
"\r\n".
|
||||
"# Name \"$windows_project - Win32 Release\"\r\n".
|
||||
"# Name \"$windows_project - Win32 Debug\"\r\n".
|
||||
"# Begin Group \"Source Files\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP Default_Filter \"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat\"\r\n";
|
||||
foreach $source_file (@source_files) {
|
||||
print
|
||||
"# Begin Source File\r\n".
|
||||
"\r\n".
|
||||
"SOURCE=..\\..\\$source_file\r\n";
|
||||
if($source_file =~ /ssh\.c/io) {
|
||||
# Disable 'Edit and continue' as Visual Studio can't handle the macros
|
||||
print
|
||||
"\r\n".
|
||||
"!IF \"\$(CFG)\" == \"$windows_project - Win32 Release\"\r\n".
|
||||
"\r\n".
|
||||
"!ELSEIF \"\$(CFG)\" == \"$windows_project - Win32 Debug\"\r\n".
|
||||
"\r\n".
|
||||
"# ADD CPP /Zi\r\n".
|
||||
"\r\n".
|
||||
"!ENDIF \r\n".
|
||||
"\r\n";
|
||||
}
|
||||
print "# End Source File\r\n";
|
||||
}
|
||||
print
|
||||
"# End Group\r\n".
|
||||
"# Begin Group \"Header Files\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP Default_Filter \"h;hpp;hxx;hm;inl\"\r\n";
|
||||
foreach $header_file (@header_files) {
|
||||
print
|
||||
"# Begin Source File\r\n".
|
||||
"\r\n".
|
||||
"SOURCE=..\\..\\$header_file\r\n".
|
||||
"# End Source File\r\n";
|
||||
}
|
||||
print
|
||||
"# End Group\r\n".
|
||||
"# Begin Group \"Resource Files\"\r\n".
|
||||
"\r\n".
|
||||
"# PROP Default_Filter \"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe\"\r\n";
|
||||
foreach $resource_file (@resources) {
|
||||
print
|
||||
"# Begin Source File\r\n".
|
||||
"\r\n".
|
||||
"SOURCE=..\\..\\$resource_file\r\n".
|
||||
"# End Source File\r\n";
|
||||
}
|
||||
print
|
||||
"# End Group\r\n".
|
||||
"# End Target\r\n".
|
||||
"# End Project\r\n";
|
||||
select STDOUT; close OUT;
|
||||
chdir "..";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1080,7 @@ if (defined $makefiles{'vstudio10'} || defined $makefiles{'vstudio12'}) {
|
|||
|
||||
$projguids{$windows_project} = $guid =
|
||||
&invent_guid("project:$progname");
|
||||
|
||||
|
||||
print
|
||||
"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$windows_project\", \"$windows_project\\$windows_project.vcxproj\", \"{$guid}\"\n" .
|
||||
"EndProject\n";
|
||||
|
@ -1115,7 +1115,7 @@ if (defined $makefiles{'vstudio10'} || defined $makefiles{'vstudio12'}) {
|
|||
($windows_project, $type) = split ",", $progname;
|
||||
create_vs_project(\%all_object_deps, $windows_project, $type, $projguids{$windows_project}, $toolsver);
|
||||
}
|
||||
|
||||
|
||||
chdir $orig_dir;
|
||||
}
|
||||
|
||||
|
@ -1426,9 +1426,9 @@ if (defined $makefiles{'gtk'}) {
|
|||
"unexport CFLAGS # work around a weird issue with krb5-config\n".
|
||||
"\n".
|
||||
&splitline("CFLAGS = -O2 -Wall -Werror -std=gnu99 -Wvla -g " .
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
|
||||
" \$(shell \$(GTK_CONFIG) --cflags)").
|
||||
" -D _FILE_OFFSET_BITS=64\n".
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs) .
|
||||
" \$(shell \$(GTK_CONFIG) --cflags)").
|
||||
" -D _FILE_OFFSET_BITS=64\n".
|
||||
"XLDFLAGS = \$(LDFLAGS) \$(shell \$(GTK_CONFIG) --libs)\n".
|
||||
"ULDFLAGS = \$(LDFLAGS)\n".
|
||||
"ifeq (,\$(findstring NO_GSSAPI,\$(COMPAT)))\n".
|
||||
|
@ -1507,8 +1507,8 @@ if (defined $makefiles{'unix'}) {
|
|||
"unexport CFLAGS # work around a weird issue with krb5-config\n".
|
||||
"\n".
|
||||
&splitline("CFLAGS = -O2 -Wall -Werror -std=gnu99 -Wvla -g " .
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs)).
|
||||
" -D _FILE_OFFSET_BITS=64\n".
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs)).
|
||||
" -D _FILE_OFFSET_BITS=64\n".
|
||||
"ULDFLAGS = \$(LDFLAGS)\n".
|
||||
"INSTALL=install\n".
|
||||
"INSTALL_PROGRAM=\$(INSTALL)\n".
|
||||
|
@ -1714,8 +1714,8 @@ if (defined $makefiles{'lcc'}) {
|
|||
join " ", @{$d->{deps}})), "\n";
|
||||
}
|
||||
if ($d->{obj} =~ /\.obj$/) {
|
||||
print &splitline("\tlcc -O -p6 \$(COMPAT)".
|
||||
" \$(CFLAGS) \$(XFLAGS) ".$d->{deps}->[0],69)."\n";
|
||||
print &splitline("\tlcc -O -p6 \$(COMPAT)".
|
||||
" \$(CFLAGS) \$(XFLAGS) ".$d->{deps}->[0],69)."\n";
|
||||
} else {
|
||||
print &splitline("\tlrc \$(RCFL) -r \$(RCFLAGS) ".
|
||||
$d->{deps}->[0],69)."\n";
|
||||
|
@ -1749,7 +1749,7 @@ if (defined $makefiles{'osx'}) {
|
|||
"CC = \$(TOOLPATH)gcc\n".
|
||||
"\n".
|
||||
&splitline("CFLAGS = -O2 -Wall -Werror -std=gnu99 -Wvla -g " .
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
|
||||
(join " ", map {"-I$dirpfx$_"} @srcdirs))."\n".
|
||||
"MLDFLAGS = -framework Cocoa\n".
|
||||
"ULDFLAGS =\n".
|
||||
"\n" .
|
||||
|
@ -1767,18 +1767,18 @@ if (defined $makefiles{'osx'}) {
|
|||
print "${prog}.app/Contents/MacOS: ${prog}.app/Contents\n\tmkdir -p \$\@\n";
|
||||
$targets = "${prog}.app/Contents/MacOS/$prog";
|
||||
if (defined $icon) {
|
||||
print "${prog}.app/Contents/Resources: ${prog}.app/Contents\n\tmkdir -p \$\@\n";
|
||||
print "${prog}.app/Contents/Resources/${prog}.icns: ${prog}.app/Contents/Resources $icon\n\tcp $icon \$\@\n";
|
||||
$targets .= " ${prog}.app/Contents/Resources/${prog}.icns";
|
||||
print "${prog}.app/Contents/Resources: ${prog}.app/Contents\n\tmkdir -p \$\@\n";
|
||||
print "${prog}.app/Contents/Resources/${prog}.icns: ${prog}.app/Contents/Resources $icon\n\tcp $icon \$\@\n";
|
||||
$targets .= " ${prog}.app/Contents/Resources/${prog}.icns";
|
||||
}
|
||||
if (defined $infoplist) {
|
||||
print "${prog}.app/Contents/Info.plist: ${prog}.app/Contents/Resources $infoplist\n\tcp $infoplist \$\@\n";
|
||||
$targets .= " ${prog}.app/Contents/Info.plist";
|
||||
print "${prog}.app/Contents/Info.plist: ${prog}.app/Contents/Resources $infoplist\n\tcp $infoplist \$\@\n";
|
||||
$targets .= " ${prog}.app/Contents/Info.plist";
|
||||
}
|
||||
$targets .= " \$(${prog}_extra)";
|
||||
print &splitline("${prog}: $targets", 69) . "\n\n";
|
||||
print &splitline("${prog}.app/Contents/MacOS/$prog: ".
|
||||
"${prog}.app/Contents/MacOS " . $objstr), "\n";
|
||||
"${prog}.app/Contents/MacOS " . $objstr), "\n";
|
||||
$libstr = &objects($p, undef, undef, "-lX");
|
||||
print &splitline("\t\$(CC) \$(MLDFLAGS) -o \$@ " .
|
||||
$objstr . " $libstr", 69), "\n\n";
|
||||
|
@ -1800,9 +1800,9 @@ if (defined $makefiles{'osx'}) {
|
|||
}
|
||||
$firstdep = $d->{deps}->[0];
|
||||
if ($firstdep =~ /\.c$/) {
|
||||
print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
|
||||
print "\t\$(CC) \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
|
||||
} elsif ($firstdep =~ /\.m$/) {
|
||||
print "\t\$(CC) -x objective-c \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
|
||||
print "\t\$(CC) -x objective-c \$(COMPAT) \$(FWHACK) \$(CFLAGS) \$(XFLAGS) -c \$<\n";
|
||||
}
|
||||
}
|
||||
print "\n".&def($makefile_extra{'osx'}->{'end'});
|
||||
|
|
2
mpint.c
2
mpint.c
|
@ -1846,7 +1846,7 @@ void mp_divmod_into(mp_int *n, mp_int *d, mp_int *q_out, mp_int *r_out)
|
|||
*
|
||||
* So when we multiply n (the input numerator) by our final
|
||||
* reciprocal approximation r, but actually r differs from R/d by
|
||||
* up to 2, then it follows that
|
||||
* up to 2, then it follows that
|
||||
*
|
||||
* n/d - nr/R = n/d - [ n (R/d + e) ] / R
|
||||
* = n/d - [ (n/d) R + n e ] / R
|
||||
|
|
|
@ -228,7 +228,7 @@
|
|||
(ret) = (BignumInt)ADC_temp; \
|
||||
(retc) = (BignumCarry)(ADC_temp >> BIGNUM_INT_BITS); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define BignumMUL(rh, rl, a, b) do \
|
||||
{ \
|
||||
DEFINE_BIGNUMDBLINT; \
|
||||
|
@ -237,7 +237,7 @@
|
|||
(rh) = (BignumInt)(MUL_temp >> BIGNUM_INT_BITS); \
|
||||
(rl) = (BignumInt)(MUL_temp); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define BignumMULADD(rh, rl, a, b, addend) do \
|
||||
{ \
|
||||
DEFINE_BIGNUMDBLINT; \
|
||||
|
@ -247,7 +247,7 @@
|
|||
(rh) = (BignumInt)(MUL_temp >> BIGNUM_INT_BITS); \
|
||||
(rl) = (BignumInt)(MUL_temp); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define BignumMULADD2(rh, rl, a, b, addend1, addend2) do \
|
||||
{ \
|
||||
DEFINE_BIGNUMDBLINT; \
|
||||
|
|
32
network.h
32
network.h
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* The way this works is: a back end can choose to open any number
|
||||
* of sockets - including zero, which might be necessary in some.
|
||||
* It can register a bunch of callbacks (most notably for when
|
||||
* It can register a bunch of callbacks (most notably for when
|
||||
* data is received) for each socket, and it can call the networking
|
||||
* abstraction to send data without having to worry about blocking.
|
||||
* The stuff behind the abstraction takes care of selects and
|
||||
|
@ -46,18 +46,18 @@ struct Plug {
|
|||
|
||||
struct PlugVtable {
|
||||
void (*log)(Plug *p, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code);
|
||||
const char *error_msg, int error_code);
|
||||
/*
|
||||
* Passes the client progress reports on the process of setting
|
||||
* up the connection.
|
||||
*
|
||||
* - type==0 means we are about to try to connect to address
|
||||
* `addr' (error_msg and error_code are ignored)
|
||||
* - type==1 means we have failed to connect to address `addr'
|
||||
* (error_msg and error_code are supplied). This is not a
|
||||
* fatal error - we may well have other candidate addresses
|
||||
* to fall back to. When it _is_ fatal, the closing()
|
||||
* function will be called.
|
||||
*
|
||||
* - type==0 means we are about to try to connect to address
|
||||
* `addr' (error_msg and error_code are ignored)
|
||||
* - type==1 means we have failed to connect to address `addr'
|
||||
* (error_msg and error_code are supplied). This is not a
|
||||
* fatal error - we may well have other candidate addresses
|
||||
* to fall back to. When it _is_ fatal, the closing()
|
||||
* function will be called.
|
||||
* - type==2 means that error_msg contains a line of generic
|
||||
* logging information about setting up the connection. This
|
||||
* will typically be a wodge of standard-error output from a
|
||||
|
@ -73,10 +73,10 @@ struct PlugVtable {
|
|||
/*
|
||||
* - urgent==0. `data' points to `len' bytes of perfectly
|
||||
* ordinary data.
|
||||
*
|
||||
*
|
||||
* - urgent==1. `data' points to `len' bytes of data,
|
||||
* which were read from before an Urgent pointer.
|
||||
*
|
||||
*
|
||||
* - urgent==2. `data' points to `len' bytes of data,
|
||||
* the first of which was the one at the Urgent mark.
|
||||
*/
|
||||
|
@ -117,8 +117,8 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname,
|
|||
|
||||
/* socket functions */
|
||||
|
||||
void sk_init(void); /* called once at program startup */
|
||||
void sk_cleanup(void); /* called just before program exit */
|
||||
void sk_init(void); /* called once at program startup */
|
||||
void sk_cleanup(void); /* called just before program exit */
|
||||
|
||||
SockAddr *sk_namelookup(const char *host, char **canonicalname, int address_family);
|
||||
SockAddr *sk_nonamelookup(const char *host);
|
||||
|
@ -183,13 +183,13 @@ static inline const char *sk_socket_error(Socket *s)
|
|||
* which all READABLE notifications are ignored, so that data is
|
||||
* not accepted from the peer until the socket is unfrozen. This
|
||||
* exists for two purposes:
|
||||
*
|
||||
*
|
||||
* - Port forwarding: when a local listening port receives a
|
||||
* connection, we do not want to receive data from the new
|
||||
* socket until we have somewhere to send it. Hence, we freeze
|
||||
* the socket until its associated SSH channel is ready; then we
|
||||
* unfreeze it and pending data is delivered.
|
||||
*
|
||||
*
|
||||
* - Socket buffering: if an SSH channel (or the whole connection)
|
||||
* backs up or presents a zero window, we must freeze the
|
||||
* associated local socket in order to avoid unbounded buffer
|
||||
|
|
|
@ -21,15 +21,15 @@ int proxy_socks5_handlechap (ProxySocket *p)
|
|||
{
|
||||
|
||||
plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request"
|
||||
" in telnet-only build",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
" in telnet-only build",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int proxy_socks5_selectchap(ProxySocket *p)
|
||||
{
|
||||
plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request"
|
||||
" in telnet-only build",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
" in telnet-only build",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* notiming.c: stub version of timing API.
|
||||
*
|
||||
*
|
||||
* Used in any tool which needs a subsystem linked against the
|
||||
* timing API but doesn't want to actually provide timing. For
|
||||
* example, key generation tools need the random number generator,
|
||||
|
|
|
@ -13,7 +13,7 @@ static void nullplug_socket_log(Plug *plug, int type, SockAddr *addr, int port,
|
|||
}
|
||||
|
||||
static void nullplug_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
bool calling_back)
|
||||
bool calling_back)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
618
pageant.c
618
pageant.c
|
@ -66,18 +66,18 @@ static int cmpkeys_ssh2_asymm(void *av, void *bv)
|
|||
c = 0;
|
||||
for (i = 0; i < ablob->len && i < bblob->len; i++) {
|
||||
unsigned char abyte = ((unsigned char *)ablob->ptr)[i];
|
||||
if (abyte < bblob->u[i]) {
|
||||
c = -1;
|
||||
break;
|
||||
} else if (abyte > bblob->u[i]) {
|
||||
c = +1;
|
||||
break;
|
||||
}
|
||||
if (abyte < bblob->u[i]) {
|
||||
c = -1;
|
||||
break;
|
||||
} else if (abyte > bblob->u[i]) {
|
||||
c = +1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (c == 0 && i < ablob->len)
|
||||
c = +1; /* a is longer */
|
||||
c = +1; /* a is longer */
|
||||
if (c == 0 && i < bblob->len)
|
||||
c = -1; /* a is longer */
|
||||
c = -1; /* a is longer */
|
||||
|
||||
strbuf_free(bblob);
|
||||
|
||||
|
@ -111,7 +111,7 @@ void pageant_make_keylist1(BinarySink *bs)
|
|||
put_uint32(bs, count234(rsakeys));
|
||||
for (i = 0; NULL != (key = index234(rsakeys, i)); i++) {
|
||||
rsa_ssh1_public_blob(bs, key, RSA_SSH1_EXPONENT_FIRST);
|
||||
put_stringz(bs, key->comment);
|
||||
put_stringz(bs, key->comment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ void pageant_make_keylist2(BinarySink *bs)
|
|||
strbuf *blob = strbuf_new();
|
||||
ssh_key_public_blob(key->key, BinarySink_UPCAST(blob));
|
||||
put_stringsb(bs, blob);
|
||||
put_stringz(bs, key->comment);
|
||||
put_stringz(bs, key->comment);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,13 +171,13 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
|
||||
switch (type) {
|
||||
case SSH1_AGENTC_REQUEST_RSA_IDENTITIES:
|
||||
/*
|
||||
* Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
|
||||
*/
|
||||
{
|
||||
/*
|
||||
* Reply with SSH1_AGENT_RSA_IDENTITIES_ANSWER.
|
||||
*/
|
||||
{
|
||||
plog(logctx, logfn, "request: SSH1_AGENTC_REQUEST_RSA_IDENTITIES");
|
||||
|
||||
put_byte(bs, SSH1_AGENT_RSA_IDENTITIES_ANSWER);
|
||||
put_byte(bs, SSH1_AGENT_RSA_IDENTITIES_ANSWER);
|
||||
pageant_make_keylist1(bs);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH1_AGENT_RSA_IDENTITIES_ANSWER");
|
||||
|
@ -190,16 +190,16 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
sfree(fingerprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH2_AGENTC_REQUEST_IDENTITIES:
|
||||
/*
|
||||
* Reply with SSH2_AGENT_IDENTITIES_ANSWER.
|
||||
*/
|
||||
{
|
||||
/*
|
||||
* Reply with SSH2_AGENT_IDENTITIES_ANSWER.
|
||||
*/
|
||||
{
|
||||
plog(logctx, logfn, "request: SSH2_AGENTC_REQUEST_IDENTITIES");
|
||||
|
||||
put_byte(bs, SSH2_AGENT_IDENTITIES_ANSWER);
|
||||
put_byte(bs, SSH2_AGENT_IDENTITIES_ANSWER);
|
||||
pageant_make_keylist2(bs);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH2_AGENT_IDENTITIES_ANSWER");
|
||||
|
@ -213,21 +213,21 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
sfree(fingerprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH1_AGENTC_RSA_CHALLENGE:
|
||||
/*
|
||||
* Reply with either SSH1_AGENT_RSA_RESPONSE or
|
||||
* SSH_AGENT_FAILURE, depending on whether we have that key
|
||||
* or not.
|
||||
*/
|
||||
{
|
||||
RSAKey reqkey, *key;
|
||||
mp_int *challenge, *response;
|
||||
/*
|
||||
* Reply with either SSH1_AGENT_RSA_RESPONSE or
|
||||
* SSH_AGENT_FAILURE, depending on whether we have that key
|
||||
* or not.
|
||||
*/
|
||||
{
|
||||
RSAKey reqkey, *key;
|
||||
mp_int *challenge, *response;
|
||||
ptrlen session_id;
|
||||
unsigned response_type;
|
||||
unsigned char response_md5[16];
|
||||
int i;
|
||||
unsigned char response_md5[16];
|
||||
int i;
|
||||
|
||||
plog(logctx, logfn, "request: SSH1_AGENTC_RSA_CHALLENGE");
|
||||
|
||||
|
@ -237,7 +237,7 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
get_rsa_ssh1_pub(msg, &reqkey, RSA_SSH1_EXPONENT_FIRST);
|
||||
challenge = get_mp_ssh1(msg);
|
||||
session_id = get_data(msg, 16);
|
||||
response_type = get_uint32(msg);
|
||||
response_type = get_uint32(msg);
|
||||
|
||||
if (get_err(msg)) {
|
||||
pageant_failure_msg(bs, "unable to decode request",
|
||||
|
@ -261,8 +261,8 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
if ((key = find234(rsakeys, &reqkey, NULL)) == NULL) {
|
||||
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||
goto challenge1_cleanup;
|
||||
}
|
||||
response = rsa_ssh1_decrypt(challenge, key);
|
||||
}
|
||||
response = rsa_ssh1_decrypt(challenge, key);
|
||||
|
||||
{
|
||||
ssh_hash *h = ssh_hash_new(&ssh_md5);
|
||||
|
@ -272,8 +272,8 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
ssh_hash_final(h, response_md5);
|
||||
}
|
||||
|
||||
put_byte(bs, SSH1_AGENT_RSA_RESPONSE);
|
||||
put_data(bs, response_md5, 16);
|
||||
put_byte(bs, SSH1_AGENT_RSA_RESPONSE);
|
||||
put_data(bs, response_md5, 16);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH1_AGENT_RSA_RESPONSE");
|
||||
|
||||
|
@ -282,16 +282,16 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
mp_free(response);
|
||||
mp_free(challenge);
|
||||
freersakey(&reqkey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH2_AGENTC_SIGN_REQUEST:
|
||||
/*
|
||||
* Reply with either SSH2_AGENT_SIGN_RESPONSE or
|
||||
* SSH_AGENT_FAILURE, depending on whether we have that key
|
||||
* or not.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *key;
|
||||
/*
|
||||
* Reply with either SSH2_AGENT_SIGN_RESPONSE or
|
||||
* SSH_AGENT_FAILURE, depending on whether we have that key
|
||||
* or not.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *key;
|
||||
ptrlen keyblob, sigdata;
|
||||
strbuf *signature;
|
||||
uint32_t flags, supported_flags;
|
||||
|
@ -326,7 +326,7 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
sfree(fingerprint);
|
||||
}
|
||||
key = find234(ssh2keys, &keyblob, cmpkeys_ssh2_asymm);
|
||||
if (!key) {
|
||||
if (!key) {
|
||||
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||
return;
|
||||
}
|
||||
|
@ -367,20 +367,20 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
put_stringsb(bs, signature);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH2_AGENT_SIGN_RESPONSE");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH1_AGENTC_ADD_RSA_IDENTITY:
|
||||
/*
|
||||
* Add to the list and return SSH_AGENT_SUCCESS, or
|
||||
* SSH_AGENT_FAILURE if the key was malformed.
|
||||
*/
|
||||
{
|
||||
RSAKey *key;
|
||||
/*
|
||||
* Add to the list and return SSH_AGENT_SUCCESS, or
|
||||
* SSH_AGENT_FAILURE if the key was malformed.
|
||||
*/
|
||||
{
|
||||
RSAKey *key;
|
||||
|
||||
plog(logctx, logfn, "request: SSH1_AGENTC_ADD_RSA_IDENTITY");
|
||||
|
||||
key = snew(RSAKey);
|
||||
memset(key, 0, sizeof(RSAKey));
|
||||
key = snew(RSAKey);
|
||||
memset(key, 0, sizeof(RSAKey));
|
||||
|
||||
get_rsa_ssh1_pub(msg, key, RSA_SSH1_MODULUS_FIRST);
|
||||
get_rsa_ssh1_priv(msg, key);
|
||||
|
@ -388,11 +388,11 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
/* SSH-1 names p and q the other way round, i.e. we have
|
||||
* the inverse of p mod q and not of q mod p. We swap the
|
||||
* names, because our internal RSA wants iqmp. */
|
||||
key->iqmp = get_mp_ssh1(msg);
|
||||
key->q = get_mp_ssh1(msg);
|
||||
key->p = get_mp_ssh1(msg);
|
||||
key->iqmp = get_mp_ssh1(msg);
|
||||
key->q = get_mp_ssh1(msg);
|
||||
key->p = get_mp_ssh1(msg);
|
||||
|
||||
key->comment = mkstr(get_string(msg));
|
||||
key->comment = mkstr(get_string(msg));
|
||||
|
||||
if (get_err(msg)) {
|
||||
pageant_failure_msg(bs, "unable to decode request",
|
||||
|
@ -402,7 +402,7 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
|
||||
if (!rsa_verify(key)) {
|
||||
pageant_failure_msg(bs, "key is invalid", logctx, logfn);
|
||||
goto add1_cleanup;
|
||||
goto add1_cleanup;
|
||||
}
|
||||
|
||||
if (logfn) {
|
||||
|
@ -411,30 +411,30 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
sfree(fingerprint);
|
||||
}
|
||||
|
||||
if (add234(rsakeys, key) == key) {
|
||||
keylist_update();
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
if (add234(rsakeys, key) == key) {
|
||||
keylist_update();
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||
key = NULL; /* don't free it in cleanup */
|
||||
} else {
|
||||
} else {
|
||||
pageant_failure_msg(bs, "key already present",
|
||||
logctx, logfn);
|
||||
}
|
||||
}
|
||||
|
||||
add1_cleanup:
|
||||
if (key) {
|
||||
freersakey(key);
|
||||
sfree(key);
|
||||
freersakey(key);
|
||||
sfree(key);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH2_AGENTC_ADD_IDENTITY:
|
||||
/*
|
||||
* Add to the list and return SSH_AGENT_SUCCESS, or
|
||||
* SSH_AGENT_FAILURE if the key was malformed.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *key = NULL;
|
||||
/*
|
||||
* Add to the list and return SSH_AGENT_SUCCESS, or
|
||||
* SSH_AGENT_FAILURE if the key was malformed.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *key = NULL;
|
||||
ptrlen algpl;
|
||||
const ssh_keyalg *alg;
|
||||
|
||||
|
@ -442,23 +442,23 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
|
||||
algpl = get_string(msg);
|
||||
|
||||
key = snew(ssh2_userkey);
|
||||
key = snew(ssh2_userkey);
|
||||
key->key = NULL;
|
||||
key->comment = NULL;
|
||||
alg = find_pubkey_alg_len(algpl);
|
||||
if (!alg) {
|
||||
if (!alg) {
|
||||
pageant_failure_msg(bs, "algorithm unknown", logctx, logfn);
|
||||
goto add2_cleanup;
|
||||
}
|
||||
goto add2_cleanup;
|
||||
}
|
||||
|
||||
key->key = ssh_key_new_priv_openssh(alg, msg);
|
||||
|
||||
if (!key->key) {
|
||||
if (!key->key) {
|
||||
pageant_failure_msg(bs, "key setup failed", logctx, logfn);
|
||||
goto add2_cleanup;
|
||||
}
|
||||
goto add2_cleanup;
|
||||
}
|
||||
|
||||
key->comment = mkstr(get_string(msg));
|
||||
key->comment = mkstr(get_string(msg));
|
||||
|
||||
if (get_err(msg)) {
|
||||
pageant_failure_msg(bs, "unable to decode request",
|
||||
|
@ -473,17 +473,17 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
sfree(fingerprint);
|
||||
}
|
||||
|
||||
if (add234(ssh2keys, key) == key) {
|
||||
keylist_update();
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
if (add234(ssh2keys, key) == key) {
|
||||
keylist_update();
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||
|
||||
key = NULL; /* don't clean it up */
|
||||
} else {
|
||||
} else {
|
||||
pageant_failure_msg(bs, "key already present",
|
||||
logctx, logfn);
|
||||
}
|
||||
}
|
||||
|
||||
add2_cleanup:
|
||||
if (key) {
|
||||
|
@ -491,18 +491,18 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
ssh_key_free(key->key);
|
||||
if (key->comment)
|
||||
sfree(key->comment);
|
||||
sfree(key);
|
||||
sfree(key);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
|
||||
/*
|
||||
* Remove from the list and return SSH_AGENT_SUCCESS, or
|
||||
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to
|
||||
* start with.
|
||||
*/
|
||||
{
|
||||
RSAKey reqkey, *key;
|
||||
/*
|
||||
* Remove from the list and return SSH_AGENT_SUCCESS, or
|
||||
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to
|
||||
* start with.
|
||||
*/
|
||||
{
|
||||
RSAKey reqkey, *key;
|
||||
|
||||
plog(logctx, logfn, "request: SSH1_AGENTC_REMOVE_RSA_IDENTITY");
|
||||
|
||||
|
@ -524,31 +524,31 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
sfree(fingerprint);
|
||||
}
|
||||
|
||||
key = find234(rsakeys, &reqkey, NULL);
|
||||
key = find234(rsakeys, &reqkey, NULL);
|
||||
freersakey(&reqkey);
|
||||
if (key) {
|
||||
if (key) {
|
||||
plog(logctx, logfn, "found with comment: %s", key->comment);
|
||||
|
||||
del234(rsakeys, key);
|
||||
keylist_update();
|
||||
freersakey(key);
|
||||
sfree(key);
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
del234(rsakeys, key);
|
||||
keylist_update();
|
||||
freersakey(key);
|
||||
sfree(key);
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||
} else {
|
||||
} else {
|
||||
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_IDENTITY:
|
||||
/*
|
||||
* Remove from the list and return SSH_AGENT_SUCCESS, or
|
||||
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to
|
||||
* start with.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *key;
|
||||
/*
|
||||
* Remove from the list and return SSH_AGENT_SUCCESS, or
|
||||
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to
|
||||
* start with.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *key;
|
||||
ptrlen blob;
|
||||
|
||||
plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_IDENTITY");
|
||||
|
@ -568,7 +568,7 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
}
|
||||
|
||||
key = find234(ssh2keys, &blob, cmpkeys_ssh2_asymm);
|
||||
if (!key) {
|
||||
if (!key) {
|
||||
pageant_failure_msg(bs, "key not found", logctx, logfn);
|
||||
return;
|
||||
}
|
||||
|
@ -583,56 +583,56 @@ void pageant_handle_msg(BinarySink *bs,
|
|||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
|
||||
/*
|
||||
* Remove all SSH-1 keys. Always returns success.
|
||||
*/
|
||||
{
|
||||
RSAKey *rkey;
|
||||
/*
|
||||
* Remove all SSH-1 keys. Always returns success.
|
||||
*/
|
||||
{
|
||||
RSAKey *rkey;
|
||||
|
||||
plog(logctx, logfn, "request:"
|
||||
" SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES");
|
||||
|
||||
while ((rkey = index234(rsakeys, 0)) != NULL) {
|
||||
del234(rsakeys, rkey);
|
||||
freersakey(rkey);
|
||||
sfree(rkey);
|
||||
}
|
||||
keylist_update();
|
||||
while ((rkey = index234(rsakeys, 0)) != NULL) {
|
||||
del234(rsakeys, rkey);
|
||||
freersakey(rkey);
|
||||
sfree(rkey);
|
||||
}
|
||||
keylist_update();
|
||||
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
|
||||
/*
|
||||
* Remove all SSH-2 keys. Always returns success.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *skey;
|
||||
/*
|
||||
* Remove all SSH-2 keys. Always returns success.
|
||||
*/
|
||||
{
|
||||
ssh2_userkey *skey;
|
||||
|
||||
plog(logctx, logfn, "request: SSH2_AGENTC_REMOVE_ALL_IDENTITIES");
|
||||
|
||||
while ((skey = index234(ssh2keys, 0)) != NULL) {
|
||||
del234(ssh2keys, skey);
|
||||
while ((skey = index234(ssh2keys, 0)) != NULL) {
|
||||
del234(ssh2keys, skey);
|
||||
ssh_key_free(skey->key);
|
||||
sfree(skey->comment);
|
||||
sfree(skey);
|
||||
}
|
||||
keylist_update();
|
||||
sfree(skey);
|
||||
}
|
||||
keylist_update();
|
||||
|
||||
put_byte(bs, SSH_AGENT_SUCCESS);
|
||||
|
||||
plog(logctx, logfn, "reply: SSH_AGENT_SUCCESS");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
plog(logctx, logfn, "request: unknown message type %d", type);
|
||||
pageant_failure_msg(bs, "unrecognised message", logctx, logfn);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -729,7 +729,7 @@ struct pageant_conn_state {
|
|||
};
|
||||
|
||||
static void pageant_conn_closing(Plug *plug, const char *error_msg,
|
||||
int error_code, bool calling_back)
|
||||
int error_code, bool calling_back)
|
||||
{
|
||||
struct pageant_conn_state *pc = container_of(
|
||||
plug, struct pageant_conn_state, plug);
|
||||
|
@ -824,7 +824,7 @@ struct pageant_listen_state {
|
|||
};
|
||||
|
||||
static void pageant_listen_closing(Plug *plug, const char *error_msg,
|
||||
int error_code, bool calling_back)
|
||||
int error_code, bool calling_back)
|
||||
{
|
||||
struct pageant_listen_state *pl = container_of(
|
||||
plug, struct pageant_listen_state, plug);
|
||||
|
@ -861,7 +861,7 @@ static int pageant_listen_accepting(Plug *plug,
|
|||
if ((err = sk_socket_error(pc->connsock)) != NULL) {
|
||||
sk_close(pc->connsock);
|
||||
sfree(pc);
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
sk_set_frozen(pc->connsock, 0);
|
||||
|
@ -933,10 +933,10 @@ void pageant_forget_passphrases(void)
|
|||
return;
|
||||
|
||||
while (count234(passphrases) > 0) {
|
||||
char *pp = index234(passphrases, 0);
|
||||
smemclr(pp, strlen(pp));
|
||||
delpos234(passphrases, 0);
|
||||
sfree(pp);
|
||||
char *pp = index234(passphrases, 0);
|
||||
smemclr(pp, strlen(pp));
|
||||
delpos234(passphrases, 0);
|
||||
sfree(pp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -946,30 +946,30 @@ void *pageant_get_keylist1(int *length)
|
|||
|
||||
if (!pageant_local) {
|
||||
strbuf *request;
|
||||
unsigned char *response;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
unsigned char *response;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
|
||||
request = strbuf_new_for_agent_query();
|
||||
put_byte(request, SSH1_AGENTC_REQUEST_RSA_IDENTITIES);
|
||||
put_byte(request, SSH1_AGENTC_REQUEST_RSA_IDENTITIES);
|
||||
agent_query_synchronous(request, &vresponse, &resplen);
|
||||
strbuf_free(request);
|
||||
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
|
||||
sfree(response);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = snewn(resplen-5, unsigned char);
|
||||
memcpy(ret, response+5, resplen-5);
|
||||
sfree(response);
|
||||
ret = snewn(resplen-5, unsigned char);
|
||||
memcpy(ret, response+5, resplen-5);
|
||||
sfree(response);
|
||||
|
||||
if (length)
|
||||
*length = resplen-5;
|
||||
if (length)
|
||||
*length = resplen-5;
|
||||
} else {
|
||||
strbuf *buf = strbuf_new();
|
||||
pageant_make_keylist1(BinarySink_UPCAST(buf));
|
||||
pageant_make_keylist1(BinarySink_UPCAST(buf));
|
||||
*length = buf->len;
|
||||
ret = strbuf_to_str(buf);
|
||||
}
|
||||
|
@ -982,30 +982,30 @@ void *pageant_get_keylist2(int *length)
|
|||
|
||||
if (!pageant_local) {
|
||||
strbuf *request;
|
||||
unsigned char *response;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
unsigned char *response;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
|
||||
request = strbuf_new_for_agent_query();
|
||||
put_byte(request, SSH2_AGENTC_REQUEST_IDENTITIES);
|
||||
put_byte(request, SSH2_AGENTC_REQUEST_IDENTITIES);
|
||||
agent_query_synchronous(request, &vresponse, &resplen);
|
||||
strbuf_free(request);
|
||||
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
|
||||
sfree(response);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = snewn(resplen-5, unsigned char);
|
||||
memcpy(ret, response+5, resplen-5);
|
||||
sfree(response);
|
||||
ret = snewn(resplen-5, unsigned char);
|
||||
memcpy(ret, response+5, resplen-5);
|
||||
sfree(response);
|
||||
|
||||
if (length)
|
||||
*length = resplen-5;
|
||||
if (length)
|
||||
*length = resplen-5;
|
||||
} else {
|
||||
strbuf *buf = strbuf_new();
|
||||
pageant_make_keylist2(BinarySink_UPCAST(buf));
|
||||
pageant_make_keylist2(BinarySink_UPCAST(buf));
|
||||
*length = buf->len;
|
||||
ret = strbuf_to_str(buf);
|
||||
}
|
||||
|
@ -1033,9 +1033,9 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
|
||||
type = key_type(filename);
|
||||
if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) {
|
||||
*retstr = dupprintf("Couldn't load this key (%s)",
|
||||
*retstr = dupprintf("Couldn't load this key (%s)",
|
||||
key_type_to_str(type));
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1043,126 +1043,126 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
* which may or may not be us).
|
||||
*/
|
||||
{
|
||||
strbuf *blob = strbuf_new();
|
||||
unsigned char *keylist, *p;
|
||||
int i, nkeys, keylistlen;
|
||||
strbuf *blob = strbuf_new();
|
||||
unsigned char *keylist, *p;
|
||||
int i, nkeys, keylistlen;
|
||||
|
||||
if (type == SSH_KEYTYPE_SSH1) {
|
||||
if (!rsa_ssh1_loadpub(filename, BinarySink_UPCAST(blob), NULL, &error)) {
|
||||
if (type == SSH_KEYTYPE_SSH1) {
|
||||
if (!rsa_ssh1_loadpub(filename, BinarySink_UPCAST(blob), NULL, &error)) {
|
||||
*retstr = dupprintf("Couldn't load private key (%s)", error);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
keylist = pageant_get_keylist1(&keylistlen);
|
||||
} else {
|
||||
/* For our purposes we want the blob prefixed with its
|
||||
}
|
||||
keylist = pageant_get_keylist1(&keylistlen);
|
||||
} else {
|
||||
/* For our purposes we want the blob prefixed with its
|
||||
* length, so add a placeholder here to fill in
|
||||
* afterwards */
|
||||
put_uint32(blob, 0);
|
||||
if (!ssh2_userkey_loadpub(filename, NULL, BinarySink_UPCAST(blob),
|
||||
if (!ssh2_userkey_loadpub(filename, NULL, BinarySink_UPCAST(blob),
|
||||
NULL, &error)) {
|
||||
*retstr = dupprintf("Couldn't load private key (%s)", error);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
PUT_32BIT_MSB_FIRST(blob->s, blob->len - 4);
|
||||
keylist = pageant_get_keylist2(&keylistlen);
|
||||
}
|
||||
if (keylist) {
|
||||
if (keylistlen < 4) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
PUT_32BIT_MSB_FIRST(blob->s, blob->len - 4);
|
||||
keylist = pageant_get_keylist2(&keylistlen);
|
||||
}
|
||||
if (keylist) {
|
||||
if (keylistlen < 4) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
nkeys = toint(GET_32BIT_MSB_FIRST(keylist));
|
||||
if (nkeys < 0) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
nkeys = toint(GET_32BIT_MSB_FIRST(keylist));
|
||||
if (nkeys < 0) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
p = keylist + 4;
|
||||
keylistlen -= 4;
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
p = keylist + 4;
|
||||
keylistlen -= 4;
|
||||
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
if (!memcmp(blob->s, p, blob->len)) {
|
||||
/* Key is already present; we can now leave. */
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
for (i = 0; i < nkeys; i++) {
|
||||
if (!memcmp(blob->s, p, blob->len)) {
|
||||
/* Key is already present; we can now leave. */
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_OK;
|
||||
}
|
||||
/* Now skip over public blob */
|
||||
if (type == SSH_KEYTYPE_SSH1) {
|
||||
int n = rsa_ssh1_public_blob_len(
|
||||
}
|
||||
/* Now skip over public blob */
|
||||
if (type == SSH_KEYTYPE_SSH1) {
|
||||
int n = rsa_ssh1_public_blob_len(
|
||||
make_ptrlen(p, keylistlen));
|
||||
if (n < 0) {
|
||||
if (n < 0) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
p += n;
|
||||
keylistlen -= n;
|
||||
} else {
|
||||
int n;
|
||||
if (keylistlen < 4) {
|
||||
}
|
||||
p += n;
|
||||
keylistlen -= n;
|
||||
} else {
|
||||
int n;
|
||||
if (keylistlen < 4) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
n = GET_32BIT_MSB_FIRST(p);
|
||||
}
|
||||
n = GET_32BIT_MSB_FIRST(p);
|
||||
p += 4;
|
||||
keylistlen -= 4;
|
||||
|
||||
if (n < 0 || n > keylistlen) {
|
||||
if (n < 0 || n > keylistlen) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
p += n;
|
||||
keylistlen -= n;
|
||||
}
|
||||
/* Now skip over comment field */
|
||||
{
|
||||
int n;
|
||||
if (keylistlen < 4) {
|
||||
}
|
||||
p += n;
|
||||
keylistlen -= n;
|
||||
}
|
||||
/* Now skip over comment field */
|
||||
{
|
||||
int n;
|
||||
if (keylistlen < 4) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
n = GET_32BIT_MSB_FIRST(p);
|
||||
}
|
||||
n = GET_32BIT_MSB_FIRST(p);
|
||||
p += 4;
|
||||
keylistlen -= 4;
|
||||
|
||||
if (n < 0 || n > keylistlen) {
|
||||
if (n < 0 || n > keylistlen) {
|
||||
*retstr = dupstr("Received broken key list from agent");
|
||||
sfree(keylist);
|
||||
strbuf_free(blob);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
}
|
||||
p += n;
|
||||
keylistlen -= n;
|
||||
}
|
||||
}
|
||||
}
|
||||
p += n;
|
||||
keylistlen -= n;
|
||||
}
|
||||
}
|
||||
|
||||
sfree(keylist);
|
||||
}
|
||||
sfree(keylist);
|
||||
}
|
||||
|
||||
strbuf_free(blob);
|
||||
strbuf_free(blob);
|
||||
}
|
||||
|
||||
error = NULL;
|
||||
if (type == SSH_KEYTYPE_SSH1)
|
||||
needs_pass = rsa_ssh1_encrypted(filename, &comment);
|
||||
needs_pass = rsa_ssh1_encrypted(filename, &comment);
|
||||
else
|
||||
needs_pass = ssh2_userkey_encrypted(filename, &comment);
|
||||
needs_pass = ssh2_userkey_encrypted(filename, &comment);
|
||||
attempts = 0;
|
||||
if (type == SSH_KEYTYPE_SSH1)
|
||||
rkey = snew(RSAKey);
|
||||
rkey = snew(RSAKey);
|
||||
|
||||
/*
|
||||
* Loop round repeatedly trying to load the key, until we either
|
||||
|
@ -1170,7 +1170,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
* passphrases to try.
|
||||
*/
|
||||
while (1) {
|
||||
if (needs_pass) {
|
||||
if (needs_pass) {
|
||||
|
||||
/*
|
||||
* If we've been given a passphrase on input, try using
|
||||
|
@ -1191,20 +1191,20 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
sfree(rkey);
|
||||
return PAGEANT_ACTION_NEED_PP;
|
||||
}
|
||||
} else
|
||||
this_passphrase = "";
|
||||
} else
|
||||
this_passphrase = "";
|
||||
|
||||
if (type == SSH_KEYTYPE_SSH1)
|
||||
ret = rsa_ssh1_loadkey(filename, rkey, this_passphrase, &error);
|
||||
else {
|
||||
skey = ssh2_load_userkey(filename, this_passphrase, &error);
|
||||
if (skey == SSH2_WRONG_PASSPHRASE)
|
||||
ret = -1;
|
||||
else if (!skey)
|
||||
ret = 0;
|
||||
else
|
||||
ret = 1;
|
||||
}
|
||||
if (type == SSH_KEYTYPE_SSH1)
|
||||
ret = rsa_ssh1_loadkey(filename, rkey, this_passphrase, &error);
|
||||
else {
|
||||
skey = ssh2_load_userkey(filename, this_passphrase, &error);
|
||||
if (skey == SSH2_WRONG_PASSPHRASE)
|
||||
ret = -1;
|
||||
else if (!skey)
|
||||
ret = 0;
|
||||
else
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
|
@ -1240,7 +1240,7 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
*/
|
||||
{
|
||||
char *pp_copy = dupstr(this_passphrase);
|
||||
if (addpos234(passphrases, pp_copy, 0) != pp_copy) {
|
||||
if (addpos234(passphrases, pp_copy, 0) != pp_copy) {
|
||||
/* No need; it was already there. */
|
||||
smemclr(pp_copy, strlen(pp_copy));
|
||||
sfree(pp_copy);
|
||||
|
@ -1248,31 +1248,31 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
}
|
||||
|
||||
if (comment)
|
||||
sfree(comment);
|
||||
sfree(comment);
|
||||
|
||||
if (type == SSH_KEYTYPE_SSH1) {
|
||||
if (!pageant_local) {
|
||||
if (!pageant_local) {
|
||||
strbuf *request;
|
||||
unsigned char *response;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
unsigned char *response;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
|
||||
request = strbuf_new_for_agent_query();
|
||||
put_byte(request, SSH1_AGENTC_ADD_RSA_IDENTITY);
|
||||
put_uint32(request, mp_get_nbits(rkey->modulus));
|
||||
put_mp_ssh1(request, rkey->modulus);
|
||||
put_mp_ssh1(request, rkey->exponent);
|
||||
put_mp_ssh1(request, rkey->private_exponent);
|
||||
put_mp_ssh1(request, rkey->iqmp);
|
||||
put_mp_ssh1(request, rkey->q);
|
||||
put_mp_ssh1(request, rkey->p);
|
||||
put_stringz(request, rkey->comment);
|
||||
agent_query_synchronous(request, &vresponse, &resplen);
|
||||
request = strbuf_new_for_agent_query();
|
||||
put_byte(request, SSH1_AGENTC_ADD_RSA_IDENTITY);
|
||||
put_uint32(request, mp_get_nbits(rkey->modulus));
|
||||
put_mp_ssh1(request, rkey->modulus);
|
||||
put_mp_ssh1(request, rkey->exponent);
|
||||
put_mp_ssh1(request, rkey->private_exponent);
|
||||
put_mp_ssh1(request, rkey->iqmp);
|
||||
put_mp_ssh1(request, rkey->q);
|
||||
put_mp_ssh1(request, rkey->p);
|
||||
put_stringz(request, rkey->comment);
|
||||
agent_query_synchronous(request, &vresponse, &resplen);
|
||||
strbuf_free(request);
|
||||
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||
*retstr = dupstr("The already running Pageant "
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||
*retstr = dupstr("The already running Pageant "
|
||||
"refused to add the key.");
|
||||
freersakey(rkey);
|
||||
sfree(rkey);
|
||||
|
@ -1281,31 +1281,31 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
}
|
||||
freersakey(rkey);
|
||||
sfree(rkey);
|
||||
sfree(response);
|
||||
} else {
|
||||
if (!pageant_add_ssh1_key(rkey)) {
|
||||
sfree(response);
|
||||
} else {
|
||||
if (!pageant_add_ssh1_key(rkey)) {
|
||||
freersakey(rkey);
|
||||
sfree(rkey); /* already present, don't waste RAM */
|
||||
sfree(rkey); /* already present, don't waste RAM */
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!pageant_local) {
|
||||
strbuf *request;
|
||||
if (!pageant_local) {
|
||||
strbuf *request;
|
||||
unsigned char *response;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
void *vresponse;
|
||||
int resplen;
|
||||
|
||||
request = strbuf_new_for_agent_query();
|
||||
put_byte(request, SSH2_AGENTC_ADD_IDENTITY);
|
||||
put_stringz(request, ssh_key_ssh_id(skey->key));
|
||||
request = strbuf_new_for_agent_query();
|
||||
put_byte(request, SSH2_AGENTC_ADD_IDENTITY);
|
||||
put_stringz(request, ssh_key_ssh_id(skey->key));
|
||||
ssh_key_openssh_blob(skey->key, BinarySink_UPCAST(request));
|
||||
put_stringz(request, skey->comment);
|
||||
agent_query_synchronous(request, &vresponse, &resplen);
|
||||
put_stringz(request, skey->comment);
|
||||
agent_query_synchronous(request, &vresponse, &resplen);
|
||||
strbuf_free(request);
|
||||
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||
*retstr = dupstr("The already running Pageant "
|
||||
response = vresponse;
|
||||
if (resplen < 5 || response[4] != SSH_AGENT_SUCCESS) {
|
||||
*retstr = dupstr("The already running Pageant "
|
||||
"refused to add the key.");
|
||||
sfree(response);
|
||||
return PAGEANT_ACTION_FAILURE;
|
||||
|
@ -1313,13 +1313,13 @@ int pageant_add_keyfile(Filename *filename, const char *passphrase,
|
|||
|
||||
ssh_key_free(skey->key);
|
||||
sfree(skey);
|
||||
sfree(response);
|
||||
} else {
|
||||
if (!pageant_add_ssh2_key(skey)) {
|
||||
sfree(response);
|
||||
} else {
|
||||
if (!pageant_add_ssh2_key(skey)) {
|
||||
ssh_key_free(skey->key);
|
||||
sfree(skey); /* already present, don't waste RAM */
|
||||
}
|
||||
}
|
||||
sfree(skey); /* already present, don't waste RAM */
|
||||
}
|
||||
}
|
||||
}
|
||||
return PAGEANT_ACTION_OK;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
#ifdef STATIC_GSSAPI
|
||||
#include <gssapi/gssapi.h>
|
||||
typedef gss_OID const_gss_OID; /* for our prototypes below */
|
||||
typedef gss_OID const_gss_OID; /* for our prototypes below */
|
||||
#else /* STATIC_GSSAPI */
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
18
pinger.c
18
pinger.c
|
@ -20,8 +20,8 @@ static void pinger_timer(void *ctx, unsigned long now)
|
|||
|
||||
if (pinger->pending && now == pinger->next) {
|
||||
backend_special(pinger->backend, SS_PING, 0);
|
||||
pinger->pending = false;
|
||||
pinger_schedule(pinger);
|
||||
pinger->pending = false;
|
||||
pinger_schedule(pinger);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,17 +30,17 @@ static void pinger_schedule(Pinger *pinger)
|
|||
unsigned long next;
|
||||
|
||||
if (!pinger->interval) {
|
||||
pinger->pending = false; /* cancel any pending ping */
|
||||
return;
|
||||
pinger->pending = false; /* cancel any pending ping */
|
||||
return;
|
||||
}
|
||||
|
||||
next = schedule_timer(pinger->interval * TICKSPERSEC,
|
||||
pinger_timer, pinger);
|
||||
pinger_timer, pinger);
|
||||
if (!pinger->pending ||
|
||||
(next - pinger->when_set) < (pinger->next - pinger->when_set)) {
|
||||
pinger->next = next;
|
||||
pinger->next = next;
|
||||
pinger->when_set = timing_last_clock();
|
||||
pinger->pending = true;
|
||||
pinger->pending = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,8 +60,8 @@ void pinger_reconfig(Pinger *pinger, Conf *oldconf, Conf *newconf)
|
|||
{
|
||||
int newinterval = conf_get_int(newconf, CONF_ping_interval);
|
||||
if (conf_get_int(oldconf, CONF_ping_interval) != newinterval) {
|
||||
pinger->interval = newinterval;
|
||||
pinger_schedule(pinger);
|
||||
pinger->interval = newinterval;
|
||||
pinger_schedule(pinger);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
60
portfwd.c
60
portfwd.c
|
@ -96,13 +96,13 @@ static void free_portlistener_state(struct PortListener *pl)
|
|||
}
|
||||
|
||||
static void pfd_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
/* we have to dump these since we have no interface to logging.c */
|
||||
}
|
||||
|
||||
static void pfl_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
/* we have to dump these since we have no interface to logging.c */
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ static void pfl_log(Plug *plug, int type, SockAddr *addr, int port,
|
|||
static void pfd_close(struct PortForwarding *pf);
|
||||
|
||||
static void pfd_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
bool calling_back)
|
||||
bool calling_back)
|
||||
{
|
||||
struct PortForwarding *pf =
|
||||
container_of(plug, struct PortForwarding, plug);
|
||||
|
@ -143,7 +143,7 @@ static void pfd_closing(Plug *plug, const char *error_msg, int error_code,
|
|||
static void pfl_terminate(struct PortListener *pl);
|
||||
|
||||
static void pfl_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
bool calling_back)
|
||||
bool calling_back)
|
||||
{
|
||||
struct PortListener *pl = (struct PortListener *) plug;
|
||||
pfl_terminate(pl);
|
||||
|
@ -399,16 +399,16 @@ static void pfd_receive(Plug *plug, int urgent, const char *data, size_t len)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We come here when we're ready to make an actual
|
||||
* connection.
|
||||
*/
|
||||
/*
|
||||
* We come here when we're ready to make an actual
|
||||
* connection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Freeze the socket until the SSH server confirms the
|
||||
* connection.
|
||||
*/
|
||||
sk_set_frozen(pf->s, 1);
|
||||
/*
|
||||
* Freeze the socket until the SSH server confirms the
|
||||
* connection.
|
||||
*/
|
||||
sk_set_frozen(pf->s, 1);
|
||||
|
||||
pf->c = wrap_lportfwd_open(pf->cl, pf->hostname, pf->port, pf->s,
|
||||
&pf->chan);
|
||||
|
@ -423,7 +423,7 @@ static void pfd_sent(Plug *plug, size_t bufsize)
|
|||
container_of(plug, struct PortForwarding, plug);
|
||||
|
||||
if (pf->c)
|
||||
sshfwd_unthrottle(pf->c, bufsize);
|
||||
sshfwd_unthrottle(pf->c, bufsize);
|
||||
}
|
||||
|
||||
static const PlugVtable PortForwarding_plugvt = {
|
||||
|
@ -526,22 +526,22 @@ static int pfl_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
|
|||
chan = portfwd_raw_new(pl->cl, &plug);
|
||||
s = constructor(ctx, plug);
|
||||
if ((err = sk_socket_error(s)) != NULL) {
|
||||
portfwd_raw_free(chan);
|
||||
return 1;
|
||||
portfwd_raw_free(chan);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pf = container_of(chan, struct PortForwarding, chan);
|
||||
|
||||
if (pl->is_dynamic) {
|
||||
pf->s = s;
|
||||
pf->socks_state = SOCKS_INITIAL;
|
||||
pf->socks_state = SOCKS_INITIAL;
|
||||
pf->socksbuf = strbuf_new();
|
||||
pf->socksbuf_consumed = 0;
|
||||
pf->port = 0; /* "hostname" buffer is so far empty */
|
||||
sk_set_frozen(s, 0); /* we want to receive SOCKS _now_! */
|
||||
pf->port = 0; /* "hostname" buffer is so far empty */
|
||||
sk_set_frozen(s, 0); /* we want to receive SOCKS _now_! */
|
||||
} else {
|
||||
pf->hostname = dupstr(pl->hostname);
|
||||
pf->port = pl->port;
|
||||
pf->hostname = dupstr(pl->hostname);
|
||||
pf->port = pl->port;
|
||||
portfwd_raw_setup(
|
||||
chan, s,
|
||||
wrap_lportfwd_open(pl->cl, pf->hostname, pf->port, s, &pf->chan));
|
||||
|
@ -580,11 +580,11 @@ static char *pfl_listen(const char *desthost, int destport,
|
|||
pl = *pl_ret = new_portlistener_state();
|
||||
pl->plug.vt = &PortListener_plugvt;
|
||||
if (desthost) {
|
||||
pl->hostname = dupstr(desthost);
|
||||
pl->port = destport;
|
||||
pl->is_dynamic = false;
|
||||
pl->hostname = dupstr(desthost);
|
||||
pl->port = destport;
|
||||
pl->is_dynamic = false;
|
||||
} else
|
||||
pl->is_dynamic = true;
|
||||
pl->is_dynamic = true;
|
||||
pl->cl = cl;
|
||||
|
||||
pl->s = new_listener(srcaddr, port, &pl->plug,
|
||||
|
@ -593,9 +593,9 @@ static char *pfl_listen(const char *desthost, int destport,
|
|||
if ((err = sk_socket_error(pl->s)) != NULL) {
|
||||
char *err_ret = dupstr(err);
|
||||
sk_close(pl->s);
|
||||
free_portlistener_state(pl);
|
||||
free_portlistener_state(pl);
|
||||
*pl_ret = NULL;
|
||||
return err_ret;
|
||||
return err_ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -609,7 +609,7 @@ static char *pfd_log_close_msg(Channel *chan)
|
|||
static void pfd_close(struct PortForwarding *pf)
|
||||
{
|
||||
if (!pf)
|
||||
return;
|
||||
return;
|
||||
|
||||
sk_close(pf->s);
|
||||
free_portfwd_state(pf);
|
||||
|
@ -621,7 +621,7 @@ static void pfd_close(struct PortForwarding *pf)
|
|||
static void pfl_terminate(struct PortListener *pl)
|
||||
{
|
||||
if (!pl)
|
||||
return;
|
||||
return;
|
||||
|
||||
sk_close(pl->s);
|
||||
free_portlistener_state(pl);
|
||||
|
@ -669,7 +669,7 @@ static void pfd_open_confirmation(Channel *chan)
|
|||
sk_set_frozen(pf->s, 0);
|
||||
sk_write(pf->s, NULL, 0);
|
||||
if (pf->socksbuf) {
|
||||
sshfwd_write(pf->c, pf->socksbuf->u + pf->socksbuf_consumed,
|
||||
sshfwd_write(pf->c, pf->socksbuf->u + pf->socksbuf_consumed,
|
||||
pf->socksbuf->len - pf->socksbuf_consumed);
|
||||
strbuf_free(pf->socksbuf);
|
||||
pf->socksbuf = NULL;
|
||||
|
|
1572
proxy.c
1572
proxy.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
8
proxy.h
8
proxy.h
|
@ -32,10 +32,10 @@ struct ProxySocket {
|
|||
#define PROXY_STATE_ACTIVE 0
|
||||
|
||||
int state; /* proxy states greater than 0 are implementation
|
||||
* dependent, but represent various stages/states
|
||||
* of the initialization/setup/negotiation with the
|
||||
* proxy server.
|
||||
*/
|
||||
* dependent, but represent various stages/states
|
||||
* of the initialization/setup/negotiation with the
|
||||
* proxy server.
|
||||
*/
|
||||
bool freeze; /* should we freeze the underlying socket when
|
||||
* we are done with the proxy negotiation? this
|
||||
* simply caches the value of sk_set_frozen calls.
|
||||
|
|
2118
pscp.c
2118
pscp.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
2372
psftp.c
2372
psftp.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
22
psftp.h
22
psftp.h
|
@ -24,7 +24,7 @@ char *psftp_lcd(char *newdir);
|
|||
* longs in POSIX time_t format.
|
||||
*/
|
||||
void get_file_times(char *filename, unsigned long *mtime,
|
||||
unsigned long *atime);
|
||||
unsigned long *atime);
|
||||
|
||||
/*
|
||||
* One iteration of the PSFTP event loop: wait for network data and
|
||||
|
@ -35,7 +35,7 @@ int ssh_sftp_loop_iteration(void);
|
|||
/*
|
||||
* Read a command line for PSFTP from standard input. Caller must
|
||||
* free.
|
||||
*
|
||||
*
|
||||
* If `backend_required' is true, should also listen for activity
|
||||
* at the backend (rekeys, clientalives, unexpected closures etc)
|
||||
* and respond as necessary, and if the backend closes it should
|
||||
|
@ -64,9 +64,9 @@ int psftp_main(int argc, char *argv[]);
|
|||
* can safely be stubs on all other platforms.
|
||||
*/
|
||||
void gui_update_stats(const char *name, unsigned long size,
|
||||
int percentage, unsigned long elapsed,
|
||||
unsigned long done, unsigned long eta,
|
||||
unsigned long ratebs);
|
||||
int percentage, unsigned long elapsed,
|
||||
unsigned long done, unsigned long eta,
|
||||
unsigned long ratebs);
|
||||
void gui_send_errcount(int list, int errs);
|
||||
void gui_send_char(int is_stderr, int c);
|
||||
void gui_enable(const char *arg);
|
||||
|
@ -76,13 +76,13 @@ void gui_enable(const char *arg);
|
|||
* transfer utilities is going to want to do things with them that
|
||||
* aren't present in stdio. Hence we supply an alternative
|
||||
* abstraction for file access functions.
|
||||
*
|
||||
*
|
||||
* This abstraction tells you the size and access times when you
|
||||
* open an existing file (platforms may choose the meaning of the
|
||||
* file times if it's not clear; whatever they choose will be what
|
||||
* PSCP sends to the server as mtime and atime), and lets you set
|
||||
* the times when saving a new file.
|
||||
*
|
||||
*
|
||||
* On the other hand, the abstraction is pretty simple: it supports
|
||||
* only opening a file and reading it, or creating a file and writing
|
||||
* it. None of this read-and-write, seeking-back-and-forth stuff.
|
||||
|
@ -92,7 +92,7 @@ typedef struct WFile WFile;
|
|||
/* Output params size, perms, mtime and atime can all be NULL if
|
||||
* desired. perms will be -1 if the OS does not support POSIX permissions. */
|
||||
RFile *open_existing_file(const char *name, uint64_t *size,
|
||||
unsigned long *mtime, unsigned long *atime,
|
||||
unsigned long *mtime, unsigned long *atime,
|
||||
long *perms);
|
||||
WFile *open_existing_wfile(const char *name, uint64_t *size);
|
||||
/* Returns <0 on error, 0 on eof, or number of bytes read, as usual */
|
||||
|
@ -135,11 +135,11 @@ void close_directory(DirHandle *dir);
|
|||
/*
|
||||
* Test a filespec to see whether it's a local wildcard or not.
|
||||
* Return values:
|
||||
*
|
||||
*
|
||||
* - WCTYPE_WILDCARD (this is a wildcard).
|
||||
* - WCTYPE_FILENAME (this is a single file name).
|
||||
* - WCTYPE_NONEXISTENT (whichever it was, nothing of that name exists).
|
||||
*
|
||||
*
|
||||
* Some platforms may choose not to support local wildcards when
|
||||
* they come from the command line; in this case they simply never
|
||||
* return WCTYPE_WILDCARD, but still test the file's existence.
|
||||
|
@ -165,7 +165,7 @@ void finish_wildcard_matching(WildcardMatcher *dir);
|
|||
* in some way malicious. The idea is that this function is applied
|
||||
* to filenames returned from FXP_READDIR, which means we can panic
|
||||
* if we see _anything_ resembling a directory separator.
|
||||
*
|
||||
*
|
||||
* Returns true if the filename is kosher, false if dangerous.
|
||||
*/
|
||||
bool vet_filename(const char *name);
|
||||
|
|
186
putty.h
186
putty.h
|
@ -1,7 +1,7 @@
|
|||
#ifndef PUTTY_PUTTY_H
|
||||
#define PUTTY_PUTTY_H
|
||||
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <limits.h> /* for INT_MAX */
|
||||
|
||||
/*
|
||||
|
@ -28,7 +28,7 @@
|
|||
* clip some values so that the resulting number of ticks does not overflow an
|
||||
* integer value.
|
||||
*/
|
||||
#define MAX_TICK_MINS (INT_MAX / (60 * TICKSPERSEC))
|
||||
#define MAX_TICK_MINS (INT_MAX / (60 * TICKSPERSEC))
|
||||
|
||||
/*
|
||||
* Fingerprints of the current and previous PGP master keys, to
|
||||
|
@ -43,7 +43,7 @@
|
|||
#define PGP_PREV_MASTER_KEY_FP \
|
||||
"440D E3B5 B7A1 CA85 B3CC 1718 AB58 5DC6 0467 6F7C"
|
||||
|
||||
/* Three attribute types:
|
||||
/* Three attribute types:
|
||||
* The ATTRs (normal attributes) are stored with the characters in
|
||||
* the main display arrays
|
||||
*
|
||||
|
@ -52,7 +52,7 @@
|
|||
*
|
||||
* The LATTRs (line attributes) are an entirely disjoint space of
|
||||
* flags.
|
||||
*
|
||||
*
|
||||
* The DATTRs (display attributes) are internal to terminal.c (but
|
||||
* defined here because their values have to match the others
|
||||
* here); they reuse the TATTR_* space but are always masked off
|
||||
|
@ -61,10 +61,10 @@
|
|||
* ATTR_INVALID is an illegal colour combination.
|
||||
*/
|
||||
|
||||
#define TATTR_ACTCURS 0x40000000UL /* active cursor (block) */
|
||||
#define TATTR_PASCURS 0x20000000UL /* passive cursor (box) */
|
||||
#define TATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */
|
||||
#define TATTR_COMBINING 0x80000000UL /* combining characters */
|
||||
#define TATTR_ACTCURS 0x40000000UL /* active cursor (block) */
|
||||
#define TATTR_PASCURS 0x20000000UL /* passive cursor (box) */
|
||||
#define TATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */
|
||||
#define TATTR_COMBINING 0x80000000UL /* combining characters */
|
||||
|
||||
#define DATTR_STARTRUN 0x80000000UL /* start of redraw run */
|
||||
|
||||
|
@ -79,8 +79,8 @@
|
|||
#define LATTR_MODE 0x00000003UL
|
||||
#define LATTR_WRAPPED 0x00000010UL /* this line wraps to next */
|
||||
#define LATTR_WRAPPED2 0x00000020UL /* with WRAPPED: CJK wide character
|
||||
wrapped to next line, so last
|
||||
single-width cell is empty */
|
||||
wrapped to next line, so last
|
||||
single-width cell is empty */
|
||||
|
||||
#define ATTR_INVALID 0x03FFFFU
|
||||
|
||||
|
@ -98,7 +98,7 @@
|
|||
#define DIRECT_CHAR(c) ((c&0xFFFFFC00)==0xD800)
|
||||
#define DIRECT_FONT(c) ((c&0xFFFFFE00)==0xF000)
|
||||
|
||||
#define UCSERR (CSET_LINEDRW|'a') /* UCS Format error character. */
|
||||
#define UCSERR (CSET_LINEDRW|'a') /* UCS Format error character. */
|
||||
/*
|
||||
* UCSWIDE is a special value used in the terminal data to signify
|
||||
* the character cell containing the right-hand half of a CJK wide
|
||||
|
@ -107,7 +107,7 @@
|
|||
* to input it via UTF-8 because our UTF-8 decoder correctly
|
||||
* rejects surrogates).
|
||||
*/
|
||||
#define UCSWIDE 0xDFFF
|
||||
#define UCSWIDE 0xDFFF
|
||||
|
||||
#define ATTR_NARROW 0x0800000U
|
||||
#define ATTR_WIDE 0x0400000U
|
||||
|
@ -125,7 +125,7 @@
|
|||
/*
|
||||
* The definitive list of colour numbers stored in terminal
|
||||
* attribute words is kept here. It is:
|
||||
*
|
||||
*
|
||||
* - 0-7 are ANSI colours (KRGYBMCW).
|
||||
* - 8-15 are the bold versions of those colours.
|
||||
* - 16-255 are the remains of the xterm 256-colour mode (a
|
||||
|
@ -148,7 +148,7 @@
|
|||
struct sesslist {
|
||||
int nsessions;
|
||||
const char **sessions;
|
||||
char *buffer; /* so memory can be freed later */
|
||||
char *buffer; /* so memory can be freed later */
|
||||
};
|
||||
|
||||
struct unicode_data {
|
||||
|
@ -164,14 +164,14 @@ struct unicode_data {
|
|||
unsigned char unitab_ctrl[256];
|
||||
};
|
||||
|
||||
#define LGXF_OVR 1 /* existing logfile overwrite */
|
||||
#define LGXF_APN 0 /* existing logfile append */
|
||||
#define LGXF_ASK -1 /* existing logfile ask */
|
||||
#define LGTYP_NONE 0 /* logmode: no logging */
|
||||
#define LGTYP_ASCII 1 /* logmode: pure ascii */
|
||||
#define LGTYP_DEBUG 2 /* logmode: all chars of traffic */
|
||||
#define LGTYP_PACKETS 3 /* logmode: SSH data packets */
|
||||
#define LGTYP_SSHRAW 4 /* logmode: SSH raw data */
|
||||
#define LGXF_OVR 1 /* existing logfile overwrite */
|
||||
#define LGXF_APN 0 /* existing logfile append */
|
||||
#define LGXF_ASK -1 /* existing logfile ask */
|
||||
#define LGTYP_NONE 0 /* logmode: no logging */
|
||||
#define LGTYP_ASCII 1 /* logmode: pure ascii */
|
||||
#define LGTYP_DEBUG 2 /* logmode: all chars of traffic */
|
||||
#define LGTYP_PACKETS 3 /* logmode: SSH data packets */
|
||||
#define LGTYP_SSHRAW 4 /* logmode: SSH raw data */
|
||||
|
||||
/*
|
||||
* Enumeration of 'special commands' that can be sent during a
|
||||
|
@ -228,8 +228,8 @@ typedef enum {
|
|||
* backend_get_specials() will use them to specify the structure
|
||||
* of the GUI specials menu.
|
||||
*/
|
||||
SS_SEP, /* Separator */
|
||||
SS_SUBMENU, /* Start a new submenu with specified name */
|
||||
SS_SEP, /* Separator */
|
||||
SS_SUBMENU, /* Start a new submenu with specified name */
|
||||
SS_EXITMENU, /* Exit current submenu, or end of entire specials list */
|
||||
} SessionSpecialCode;
|
||||
|
||||
|
@ -259,32 +259,32 @@ typedef enum {
|
|||
|
||||
/* Keyboard modifiers -- keys the user is actually holding down */
|
||||
|
||||
#define PKM_SHIFT 0x01
|
||||
#define PKM_CONTROL 0x02
|
||||
#define PKM_META 0x04
|
||||
#define PKM_ALT 0x08
|
||||
#define PKM_SHIFT 0x01
|
||||
#define PKM_CONTROL 0x02
|
||||
#define PKM_META 0x04
|
||||
#define PKM_ALT 0x08
|
||||
|
||||
/* Keyboard flags that aren't really modifiers */
|
||||
#define PKF_CAPSLOCK 0x10
|
||||
#define PKF_NUMLOCK 0x20
|
||||
#define PKF_REPEAT 0x40
|
||||
#define PKF_CAPSLOCK 0x10
|
||||
#define PKF_NUMLOCK 0x20
|
||||
#define PKF_REPEAT 0x40
|
||||
|
||||
/* Stand-alone keysyms for function keys */
|
||||
|
||||
typedef enum {
|
||||
PK_NULL, /* No symbol for this key */
|
||||
PK_NULL, /* No symbol for this key */
|
||||
/* Main keypad keys */
|
||||
PK_ESCAPE, PK_TAB, PK_BACKSPACE, PK_RETURN, PK_COMPOSE,
|
||||
/* Editing keys */
|
||||
PK_HOME, PK_INSERT, PK_DELETE, PK_END, PK_PAGEUP, PK_PAGEDOWN,
|
||||
/* Cursor keys */
|
||||
PK_UP, PK_DOWN, PK_RIGHT, PK_LEFT, PK_REST,
|
||||
/* Numeric keypad */ /* Real one looks like: */
|
||||
PK_PF1, PK_PF2, PK_PF3, PK_PF4, /* PF1 PF2 PF3 PF4 */
|
||||
PK_KPCOMMA, PK_KPMINUS, PK_KPDECIMAL, /* 7 8 9 - */
|
||||
PK_KP0, PK_KP1, PK_KP2, PK_KP3, PK_KP4, /* 4 5 6 , */
|
||||
PK_KP5, PK_KP6, PK_KP7, PK_KP8, PK_KP9, /* 1 2 3 en- */
|
||||
PK_KPBIGPLUS, PK_KPENTER, /* 0 . ter */
|
||||
/* Numeric keypad */ /* Real one looks like: */
|
||||
PK_PF1, PK_PF2, PK_PF3, PK_PF4, /* PF1 PF2 PF3 PF4 */
|
||||
PK_KPCOMMA, PK_KPMINUS, PK_KPDECIMAL, /* 7 8 9 - */
|
||||
PK_KP0, PK_KP1, PK_KP2, PK_KP3, PK_KP4, /* 4 5 6 , */
|
||||
PK_KP5, PK_KP6, PK_KP7, PK_KP8, PK_KP9, /* 1 2 3 en- */
|
||||
PK_KPBIGPLUS, PK_KPENTER, /* 0 . ter */
|
||||
/* Top row */
|
||||
PK_F1, PK_F2, PK_F3, PK_F4, PK_F5,
|
||||
PK_F6, PK_F7, PK_F8, PK_F9, PK_F10,
|
||||
|
@ -293,10 +293,10 @@ typedef enum {
|
|||
PK_PAUSE
|
||||
} Key_Sym;
|
||||
|
||||
#define PK_ISEDITING(k) ((k) >= PK_HOME && (k) <= PK_PAGEDOWN)
|
||||
#define PK_ISCURSOR(k) ((k) >= PK_UP && (k) <= PK_REST)
|
||||
#define PK_ISKEYPAD(k) ((k) >= PK_PF1 && (k) <= PK_KPENTER)
|
||||
#define PK_ISFKEY(k) ((k) >= PK_F1 && (k) <= PK_F20)
|
||||
#define PK_ISEDITING(k) ((k) >= PK_HOME && (k) <= PK_PAGEDOWN)
|
||||
#define PK_ISCURSOR(k) ((k) >= PK_UP && (k) <= PK_REST)
|
||||
#define PK_ISKEYPAD(k) ((k) >= PK_PF1 && (k) <= PK_KPENTER)
|
||||
#define PK_ISFKEY(k) ((k) >= PK_F1 && (k) <= PK_F20)
|
||||
|
||||
enum {
|
||||
VT_XWINDOWS, VT_OEMANSI, VT_OEMONLY, VT_POORMAN, VT_UNICODE
|
||||
|
@ -331,14 +331,14 @@ enum {
|
|||
/*
|
||||
* SSH ciphers (both SSH-1 and SSH-2)
|
||||
*/
|
||||
CIPHER_WARN, /* pseudo 'cipher' */
|
||||
CIPHER_WARN, /* pseudo 'cipher' */
|
||||
CIPHER_3DES,
|
||||
CIPHER_BLOWFISH,
|
||||
CIPHER_AES, /* (SSH-2 only) */
|
||||
CIPHER_AES, /* (SSH-2 only) */
|
||||
CIPHER_DES,
|
||||
CIPHER_ARCFOUR,
|
||||
CIPHER_CHACHA20,
|
||||
CIPHER_MAX /* no. ciphers (inc warn) */
|
||||
CIPHER_MAX /* no. ciphers (inc warn) */
|
||||
};
|
||||
|
||||
enum TriState {
|
||||
|
@ -366,7 +366,7 @@ enum {
|
|||
/*
|
||||
* Line discipline options which the backend might try to control.
|
||||
*/
|
||||
LD_EDIT, /* local line editing */
|
||||
LD_EDIT, /* local line editing */
|
||||
LD_ECHO, /* local echo */
|
||||
LD_N_OPTIONS
|
||||
};
|
||||
|
@ -580,18 +580,18 @@ extern const char *const appname;
|
|||
|
||||
/*
|
||||
* Some global flags denoting the type of application.
|
||||
*
|
||||
*
|
||||
* FLAG_VERBOSE is set when the user requests verbose details.
|
||||
*
|
||||
*
|
||||
* FLAG_INTERACTIVE is set when a full interactive shell session is
|
||||
* being run, _either_ because no remote command has been provided
|
||||
* _or_ because the application is GUI and can't run non-
|
||||
* interactively.
|
||||
*
|
||||
*
|
||||
* These flags describe the type of _application_ - they wouldn't
|
||||
* vary between individual sessions - and so it's OK to have this
|
||||
* variable be GLOBAL.
|
||||
*
|
||||
*
|
||||
* Note that additional flags may be defined in platform-specific
|
||||
* headers. It's probably best if those ones start from 0x1000, to
|
||||
* avoid collision.
|
||||
|
@ -668,16 +668,16 @@ typedef struct {
|
|||
*/
|
||||
bool from_server;
|
||||
|
||||
char *name; /* Short description, perhaps for dialog box title */
|
||||
char *name; /* Short description, perhaps for dialog box title */
|
||||
bool name_reqd; /* Display of `name' required or optional? */
|
||||
char *instruction; /* Long description, maybe with embedded newlines */
|
||||
char *instruction; /* Long description, maybe with embedded newlines */
|
||||
bool instr_reqd; /* Display of `instruction' required or optional? */
|
||||
size_t n_prompts; /* May be zero (in which case display the foregoing,
|
||||
* if any, and return success) */
|
||||
size_t prompts_size; /* allocated storage capacity for prompts[] */
|
||||
prompt_t **prompts;
|
||||
void *data; /* slot for housekeeping data, managed by
|
||||
* seat_get_userpass_input(); initially NULL */
|
||||
void *data; /* slot for housekeeping data, managed by
|
||||
* seat_get_userpass_input(); initially NULL */
|
||||
} prompts_t;
|
||||
prompts_t *new_prompts();
|
||||
void add_prompt(prompts_t *p, char *promptstr, bool echo);
|
||||
|
@ -741,11 +741,11 @@ enum { ALL_CLIPBOARDS(CLIP_ID) N_CLIPBOARDS };
|
|||
* by seat_set_busy_status. Initial state is assumed to be
|
||||
* BUSY_NOT. */
|
||||
typedef enum BusyStatus {
|
||||
BUSY_NOT, /* Not busy, all user interaction OK */
|
||||
BUSY_NOT, /* Not busy, all user interaction OK */
|
||||
BUSY_WAITING, /* Waiting for something; local event loops still
|
||||
running so some local interaction (e.g. menus)
|
||||
OK, but network stuff is suspended */
|
||||
BUSY_CPU /* Locally busy (e.g. crypto); user interaction
|
||||
running so some local interaction (e.g. menus)
|
||||
OK, but network stuff is suspended */
|
||||
BUSY_CPU /* Locally busy (e.g. crypto); user interaction
|
||||
* suspended */
|
||||
} BusyStatus;
|
||||
|
||||
|
@ -1494,7 +1494,7 @@ enum config_primary_key { CONFIG_OPTIONS(CONF_ENUM_DEF) N_CONFIG_OPTIONS };
|
|||
#define NCFGCOLOURS 22 /* number of colours in CONF_colours above */
|
||||
|
||||
/* Functions handling configuration structures. */
|
||||
Conf *conf_new(void); /* create an empty configuration */
|
||||
Conf *conf_new(void); /* create an empty configuration */
|
||||
void conf_free(Conf *conf);
|
||||
Conf *conf_copy(Conf *oldconf);
|
||||
void conf_copy_into(Conf *dest, Conf *src);
|
||||
|
@ -1521,7 +1521,7 @@ void conf_set_int(Conf *conf, int key, int value);
|
|||
void conf_set_int_int(Conf *conf, int key, int subkey, int value);
|
||||
void conf_set_str(Conf *conf, int key, const char *value);
|
||||
void conf_set_str_str(Conf *conf, int key,
|
||||
const char *subkey, const char *val);
|
||||
const char *subkey, const char *val);
|
||||
void conf_del_str_str(Conf *conf, int key, const char *subkey);
|
||||
void conf_set_filename(Conf *conf, int key, const Filename *val);
|
||||
void conf_set_fontspec(Conf *conf, int key, const FontSpec *val);
|
||||
|
@ -1590,7 +1590,7 @@ void registry_cleanup(void);
|
|||
/*
|
||||
* Functions used by settings.c to provide platform-specific
|
||||
* default settings.
|
||||
*
|
||||
*
|
||||
* (The integer one is expected to return `def' if it has no clear
|
||||
* opinion of its own. This is because there's no integer value
|
||||
* which I can reliably set aside to indicate `nil'. The string
|
||||
|
@ -1621,9 +1621,9 @@ void term_scroll_to_selection(Terminal *, int);
|
|||
void term_pwron(Terminal *, bool);
|
||||
void term_clrsb(Terminal *);
|
||||
void term_mouse(Terminal *, Mouse_Button, Mouse_Button, Mouse_Action,
|
||||
int, int, bool, bool, bool);
|
||||
int, int, bool, bool, bool);
|
||||
void term_key(Terminal *, Key_Sym, wchar_t *, size_t, unsigned int,
|
||||
unsigned int);
|
||||
unsigned int);
|
||||
void term_lost_clipboard_ownership(Terminal *, int clipboard);
|
||||
void term_update(Terminal *);
|
||||
void term_invalidate(Terminal *);
|
||||
|
@ -1634,7 +1634,7 @@ void term_copyall(Terminal *, const int *, int);
|
|||
void term_reconfig(Terminal *, Conf *);
|
||||
void term_request_copy(Terminal *, const int *clipboards, int n_clipboards);
|
||||
void term_request_paste(Terminal *, int clipboard);
|
||||
void term_seen_key_event(Terminal *);
|
||||
void term_seen_key_event(Terminal *);
|
||||
size_t term_data(Terminal *, bool is_stderr, const void *data, size_t len);
|
||||
void term_provide_backend(Terminal *term, Backend *backend);
|
||||
void term_provide_logctx(Terminal *term, LogContext *logctx);
|
||||
|
@ -1732,9 +1732,9 @@ struct logblank_t {
|
|||
int type;
|
||||
};
|
||||
void log_packet(LogContext *logctx, int direction, int type,
|
||||
const char *texttype, const void *data, size_t len,
|
||||
int n_blanks, const struct logblank_t *blanks,
|
||||
const unsigned long *sequence,
|
||||
const char *texttype, const void *data, size_t len,
|
||||
int n_blanks, const struct logblank_t *blanks,
|
||||
const unsigned long *sequence,
|
||||
unsigned downstream_id, const char *additional_log_text);
|
||||
|
||||
/* This is defined by applications that have an obvious logging
|
||||
|
@ -1834,7 +1834,7 @@ void prepare_session(Conf *conf);
|
|||
* Exports from sercfg.c.
|
||||
*/
|
||||
void ser_setup_config_box(struct controlbox *b, bool midsession,
|
||||
int parity_mask, int flow_mask);
|
||||
int parity_mask, int flow_mask);
|
||||
|
||||
/*
|
||||
* Exports from version.c.
|
||||
|
@ -1851,10 +1851,10 @@ extern const char commitid[];
|
|||
/* void init_ucs(void); -- this is now in platform-specific headers */
|
||||
bool is_dbcs_leadbyte(int codepage, char byte);
|
||||
int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
|
||||
wchar_t *wcstr, int wclen);
|
||||
wchar_t *wcstr, int wclen);
|
||||
int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
|
||||
char *mbstr, int mblen, const char *defchr,
|
||||
struct unicode_data *ucsdata);
|
||||
char *mbstr, int mblen, const char *defchr,
|
||||
struct unicode_data *ucsdata);
|
||||
wchar_t xlat_uskbd2cyrllic(int ch);
|
||||
int check_compose(int first, int second);
|
||||
int decode_codepage(char *cp_name);
|
||||
|
@ -1872,12 +1872,12 @@ int mk_wcswidth_cjk(const unsigned int *pwcs, size_t n);
|
|||
|
||||
/*
|
||||
* Exports from pageantc.c.
|
||||
*
|
||||
*
|
||||
* agent_query returns NULL for here's-a-response, and non-NULL for
|
||||
* query-in- progress. In the latter case there will be a call to
|
||||
* `callback' at some future point, passing callback_ctx as the first
|
||||
* parameter and the actual reply data as the second and third.
|
||||
*
|
||||
*
|
||||
* The response may be a NULL pointer (in either of the synchronous
|
||||
* or asynchronous cases), which indicates failure to receive a
|
||||
* response.
|
||||
|
@ -1975,21 +1975,21 @@ void cmdline_error(const char *, ...);
|
|||
struct controlbox;
|
||||
union control;
|
||||
void conf_radiobutton_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event);
|
||||
void *data, int event);
|
||||
#define CHECKBOX_INVERT (1<<30)
|
||||
void conf_checkbox_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event);
|
||||
void *data, int event);
|
||||
void conf_editbox_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event);
|
||||
void *data, int event);
|
||||
void conf_filesel_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event);
|
||||
void *data, int event);
|
||||
void conf_fontsel_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event);
|
||||
void *data, int event);
|
||||
/* Much more special-purpose function needed by sercfg.c */
|
||||
void config_protocolbuttons_handler(union control *, dlgparam *, void *, int);
|
||||
|
||||
void setup_config_box(struct controlbox *b, bool midsession,
|
||||
int protocol, int protcfginfo);
|
||||
int protocol, int protcfginfo);
|
||||
|
||||
/*
|
||||
* Exports from minibidi.c.
|
||||
|
@ -2009,7 +2009,7 @@ bool is_rtl(int c);
|
|||
enum {
|
||||
X11_NO_AUTH,
|
||||
X11_MIT, /* MIT-MAGIC-COOKIE-1 */
|
||||
X11_XDM, /* XDM-AUTHORIZATION-1 */
|
||||
X11_XDM, /* XDM-AUTHORIZATION-1 */
|
||||
X11_NAUTHS
|
||||
};
|
||||
extern const char *const x11_authnames[]; /* declared in x11fwd.c */
|
||||
|
@ -2038,7 +2038,7 @@ Filename *filename_copy(const Filename *fn);
|
|||
void filename_free(Filename *fn);
|
||||
void filename_serialise(BinarySink *bs, const Filename *f);
|
||||
Filename *filename_deserialise(BinarySource *src);
|
||||
char *get_username(void); /* return value needs freeing */
|
||||
char *get_username(void); /* return value needs freeing */
|
||||
char *get_random_data(int bytes, const char *device); /* used in cmdgen.c */
|
||||
char filename_char_sanitise(char c); /* rewrite special pathname chars */
|
||||
bool open_for_write_would_lose_data(const Filename *fn);
|
||||
|
@ -2056,24 +2056,24 @@ bool open_for_write_would_lose_data(const Filename *fn);
|
|||
* structure as the time when that event is due. The first time a
|
||||
* callback function gives you that value or more as `now', you do
|
||||
* the thing.
|
||||
*
|
||||
*
|
||||
* expire_timer_context() drops all current timers associated with
|
||||
* a given value of ctx (for when you're about to free ctx).
|
||||
*
|
||||
*
|
||||
* run_timers() is called from the front end when it has reason to
|
||||
* think some timers have reached their moment, or when it simply
|
||||
* needs to know how long to wait next. We pass it the time we
|
||||
* think it is. It returns true and places the time when the next
|
||||
* timer needs to go off in `next', or alternatively it returns
|
||||
* false if there are no timers at all pending.
|
||||
*
|
||||
*
|
||||
* timer_change_notify() must be supplied by the front end; it
|
||||
* notifies the front end that a new timer has been added to the
|
||||
* list which is sooner than any existing ones. It provides the
|
||||
* time when that timer needs to go off.
|
||||
*
|
||||
*
|
||||
* *** FRONT END IMPLEMENTORS NOTE:
|
||||
*
|
||||
*
|
||||
* There's an important subtlety in the front-end implementation of
|
||||
* the timer interface. When a front end is given a `next' value,
|
||||
* either returned from run_timers() or via timer_change_notify(),
|
||||
|
@ -2081,7 +2081,7 @@ bool open_for_write_would_lose_data(const Filename *fn);
|
|||
* parameter to its next run_timers call. It should _not_ simply
|
||||
* call GETTICKCOUNT() to get the `now' parameter when invoking
|
||||
* run_timers().
|
||||
*
|
||||
*
|
||||
* The reason for this is that an OS's system clock might not agree
|
||||
* exactly with the timing mechanisms it supplies to wait for a
|
||||
* given interval. I'll illustrate this by the simple example of
|
||||
|
@ -2090,7 +2090,7 @@ bool open_for_write_would_lose_data(const Filename *fn);
|
|||
* Suppose, for the sake of argument, that this wait() function
|
||||
* tends to return early by 1%. Then a possible sequence of actions
|
||||
* is:
|
||||
*
|
||||
*
|
||||
* - run_timers() tells the front end that the next timer firing
|
||||
* is 10000ms from now.
|
||||
* - Front end calls wait(10000ms), but according to
|
||||
|
@ -2103,29 +2103,29 @@ bool open_for_write_would_lose_data(const Filename *fn);
|
|||
* - Front end calls run_timers() yet again, passing time T-1ms.
|
||||
* - run_timers() says there's still 1ms to wait.
|
||||
* - Front end calls wait(1ms).
|
||||
*
|
||||
*
|
||||
* If you're _lucky_ at this point, wait(1ms) will actually wait
|
||||
* for 1ms and you'll only have woken the program up three times.
|
||||
* If you're unlucky, wait(1ms) might do nothing at all due to
|
||||
* being below some minimum threshold, and you might find your
|
||||
* program spends the whole of the last millisecond tight-looping
|
||||
* between wait() and run_timers().
|
||||
*
|
||||
*
|
||||
* Instead, what you should do is to _save_ the precise `next'
|
||||
* value provided by run_timers() or via timer_change_notify(), and
|
||||
* use that precise value as the input to the next run_timers()
|
||||
* call. So:
|
||||
*
|
||||
*
|
||||
* - run_timers() tells the front end that the next timer firing
|
||||
* is at time T, 10000ms from now.
|
||||
* - Front end calls wait(10000ms).
|
||||
* - Front end then immediately calls run_timers() and passes it
|
||||
* time T, without stopping to check GETTICKCOUNT() at all.
|
||||
*
|
||||
*
|
||||
* This guarantees that the program wakes up only as many times as
|
||||
* there are actual timer actions to be taken, and that the timing
|
||||
* mechanism will never send it into a tight loop.
|
||||
*
|
||||
*
|
||||
* (It does also mean that the timer action in the above example
|
||||
* will occur 100ms early, but this is not generally critical. And
|
||||
* the hypothetical 1% error in wait() will be partially corrected
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#ifndef PUTTY_PUTTYMEM_H
|
||||
#define PUTTY_PUTTYMEM_H
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
#include <string.h> /* for memcpy() */
|
||||
#include <stddef.h> /* for size_t */
|
||||
#include <string.h> /* for memcpy() */
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
|
|
34
raw.c
34
raw.c
|
@ -34,7 +34,7 @@ static void c_write(Raw *raw, const void *buf, size_t len)
|
|||
}
|
||||
|
||||
static void raw_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
Raw *raw = container_of(plug, Raw, plug);
|
||||
backend_socket_log(raw->seat, raw->logctx, type, addr, port,
|
||||
|
@ -57,7 +57,7 @@ static void raw_check_close(Raw *raw)
|
|||
}
|
||||
|
||||
static void raw_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
bool calling_back)
|
||||
bool calling_back)
|
||||
{
|
||||
Raw *raw = container_of(plug, Raw, plug);
|
||||
|
||||
|
@ -113,7 +113,7 @@ static const PlugVtable Raw_plugvt = {
|
|||
|
||||
/*
|
||||
* Called to set up the raw connection.
|
||||
*
|
||||
*
|
||||
* Returns an error message, or NULL on success.
|
||||
*
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
|
@ -121,7 +121,7 @@ static const PlugVtable Raw_plugvt = {
|
|||
*/
|
||||
static const char *raw_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
const char *host, int port, char **realhost,
|
||||
bool nodelay, bool keepalive)
|
||||
{
|
||||
SockAddr *addr;
|
||||
|
@ -154,12 +154,12 @@ static const char *raw_init(Seat *seat, Backend **backend_handle,
|
|||
addr = name_lookup(host, port, realhost, conf, addressfamily,
|
||||
raw->logctx, "main connection");
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (port < 0)
|
||||
port = 23; /* default telnet port */
|
||||
port = 23; /* default telnet port */
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
|
@ -167,18 +167,18 @@ static const char *raw_init(Seat *seat, Backend **backend_handle,
|
|||
raw->s = new_connection(addr, *realhost, port, false, true, nodelay,
|
||||
keepalive, &raw->plug, conf);
|
||||
if ((err = sk_socket_error(raw->s)) != NULL)
|
||||
return err;
|
||||
return err;
|
||||
|
||||
loghost = conf_get_str(conf, CONF_loghost);
|
||||
if (*loghost) {
|
||||
char *colon;
|
||||
char *colon;
|
||||
|
||||
sfree(*realhost);
|
||||
*realhost = dupstr(loghost);
|
||||
sfree(*realhost);
|
||||
*realhost = dupstr(loghost);
|
||||
|
||||
colon = host_strrchr(*realhost, ':');
|
||||
if (colon)
|
||||
*colon++ = '\0';
|
||||
colon = host_strrchr(*realhost, ':');
|
||||
if (colon)
|
||||
*colon++ = '\0';
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -189,7 +189,7 @@ static void raw_free(Backend *be)
|
|||
Raw *raw = container_of(be, Raw, backend);
|
||||
|
||||
if (raw->s)
|
||||
sk_close(raw->s);
|
||||
sk_close(raw->s);
|
||||
conf_free(raw->conf);
|
||||
sfree(raw);
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ static size_t raw_send(Backend *be, const char *buf, size_t len)
|
|||
Raw *raw = container_of(be, Raw, backend);
|
||||
|
||||
if (raw->s == NULL)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
raw->bufsize = sk_write(raw->s, buf, len);
|
||||
|
||||
|
@ -278,7 +278,7 @@ static void raw_unthrottle(Backend *be, size_t backlog)
|
|||
static bool raw_ldisc(Backend *be, int option)
|
||||
{
|
||||
if (option == LD_EDIT || option == LD_ECHO)
|
||||
return true;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use File::Find;
|
|||
use File::Temp qw/tempdir/;
|
||||
use LWP::UserAgent;
|
||||
|
||||
my $version = undef;
|
||||
my $version = undef;
|
||||
my $setver = 0;
|
||||
my $upload = 0;
|
||||
my $precheck = 0;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
|
|
94
rlogin.c
94
rlogin.c
|
@ -38,7 +38,7 @@ static void c_write(Rlogin *rlogin, const void *buf, size_t len)
|
|||
}
|
||||
|
||||
static void rlogin_log(Plug *plug, int type, SockAddr *addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
Rlogin *rlogin = container_of(plug, Rlogin, plug);
|
||||
backend_socket_log(rlogin->seat, rlogin->logctx, type, addr, port,
|
||||
|
@ -47,7 +47,7 @@ static void rlogin_log(Plug *plug, int type, SockAddr *addr, int port,
|
|||
}
|
||||
|
||||
static void rlogin_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
bool calling_back)
|
||||
bool calling_back)
|
||||
{
|
||||
Rlogin *rlogin = container_of(plug, Rlogin, plug);
|
||||
|
||||
|
@ -62,13 +62,13 @@ static void rlogin_closing(Plug *plug, const char *error_msg, int error_code,
|
|||
rlogin->s = NULL;
|
||||
if (error_msg)
|
||||
rlogin->closed_on_socket_error = true;
|
||||
seat_notify_remote_exit(rlogin->seat);
|
||||
seat_notify_remote_exit(rlogin->seat);
|
||||
}
|
||||
if (error_msg) {
|
||||
/* A socket error has occurred. */
|
||||
/* A socket error has occurred. */
|
||||
logevent(rlogin->logctx, error_msg);
|
||||
seat_connection_fatal(rlogin->seat, "%s", error_msg);
|
||||
} /* Otherwise, the remote side closed the connection normally. */
|
||||
} /* Otherwise, the remote side closed the connection normally. */
|
||||
}
|
||||
|
||||
static void rlogin_receive(
|
||||
|
@ -78,35 +78,35 @@ static void rlogin_receive(
|
|||
if (len == 0)
|
||||
return;
|
||||
if (urgent == 2) {
|
||||
char c;
|
||||
char c;
|
||||
|
||||
c = *data++;
|
||||
len--;
|
||||
if (c == '\x80') {
|
||||
rlogin->cansize = true;
|
||||
c = *data++;
|
||||
len--;
|
||||
if (c == '\x80') {
|
||||
rlogin->cansize = true;
|
||||
backend_size(&rlogin->backend,
|
||||
rlogin->term_width, rlogin->term_height);
|
||||
}
|
||||
/*
|
||||
* We should flush everything (aka Telnet SYNCH) if we see
|
||||
* 0x02, and we should turn off and on _local_ flow control
|
||||
* on 0x10 and 0x20 respectively. I'm not convinced it's
|
||||
* worth it...
|
||||
*/
|
||||
/*
|
||||
* We should flush everything (aka Telnet SYNCH) if we see
|
||||
* 0x02, and we should turn off and on _local_ flow control
|
||||
* on 0x10 and 0x20 respectively. I'm not convinced it's
|
||||
* worth it...
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* Main rlogin protocol. This is really simple: the first
|
||||
* byte is expected to be NULL and is ignored, and the rest
|
||||
* is printed.
|
||||
*/
|
||||
if (rlogin->firstbyte) {
|
||||
if (data[0] == '\0') {
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
rlogin->firstbyte = false;
|
||||
}
|
||||
if (len > 0)
|
||||
/*
|
||||
* Main rlogin protocol. This is really simple: the first
|
||||
* byte is expected to be NULL and is ignored, and the rest
|
||||
* is printed.
|
||||
*/
|
||||
if (rlogin->firstbyte) {
|
||||
if (data[0] == '\0') {
|
||||
data++;
|
||||
len--;
|
||||
}
|
||||
rlogin->firstbyte = false;
|
||||
}
|
||||
if (len > 0)
|
||||
c_write(rlogin, data, len);
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ static const PlugVtable Rlogin_plugvt = {
|
|||
|
||||
/*
|
||||
* Called to set up the rlogin connection.
|
||||
*
|
||||
*
|
||||
* Returns an error message, or NULL on success.
|
||||
*
|
||||
* Also places the canonical host name into `realhost'. It must be
|
||||
|
@ -155,8 +155,8 @@ static const PlugVtable Rlogin_plugvt = {
|
|||
*/
|
||||
static const char *rlogin_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
bool nodelay, bool keepalive)
|
||||
const char *host, int port, char **realhost,
|
||||
bool nodelay, bool keepalive)
|
||||
{
|
||||
SockAddr *addr;
|
||||
const char *err;
|
||||
|
@ -187,31 +187,31 @@ static const char *rlogin_init(Seat *seat, Backend **backend_handle,
|
|||
addr = name_lookup(host, port, realhost, conf, addressfamily,
|
||||
rlogin->logctx, "rlogin connection");
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (port < 0)
|
||||
port = 513; /* default rlogin port */
|
||||
port = 513; /* default rlogin port */
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
rlogin->s = new_connection(addr, *realhost, port, true, false,
|
||||
nodelay, keepalive, &rlogin->plug, conf);
|
||||
nodelay, keepalive, &rlogin->plug, conf);
|
||||
if ((err = sk_socket_error(rlogin->s)) != NULL)
|
||||
return err;
|
||||
return err;
|
||||
|
||||
loghost = conf_get_str(conf, CONF_loghost);
|
||||
if (*loghost) {
|
||||
char *colon;
|
||||
char *colon;
|
||||
|
||||
sfree(*realhost);
|
||||
*realhost = dupstr(loghost);
|
||||
sfree(*realhost);
|
||||
*realhost = dupstr(loghost);
|
||||
|
||||
colon = host_strrchr(*realhost, ':');
|
||||
if (colon)
|
||||
*colon++ = '\0';
|
||||
colon = host_strrchr(*realhost, ':');
|
||||
if (colon)
|
||||
*colon++ = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -232,7 +232,7 @@ static const char *rlogin_init(Seat *seat, Backend **backend_handle,
|
|||
rlogin->prompt->to_server = true;
|
||||
rlogin->prompt->from_server = false;
|
||||
rlogin->prompt->name = dupstr("Rlogin login name");
|
||||
add_prompt(rlogin->prompt, dupstr("rlogin username: "), true);
|
||||
add_prompt(rlogin->prompt, dupstr("rlogin username: "), true);
|
||||
ret = seat_get_userpass_input(rlogin->seat, rlogin->prompt, NULL);
|
||||
if (ret >= 0) {
|
||||
/* Next terminal output will come from server */
|
||||
|
@ -251,7 +251,7 @@ static void rlogin_free(Backend *be)
|
|||
if (rlogin->prompt)
|
||||
free_prompts(rlogin->prompt);
|
||||
if (rlogin->s)
|
||||
sk_close(rlogin->s);
|
||||
sk_close(rlogin->s);
|
||||
conf_free(rlogin->conf);
|
||||
sfree(rlogin);
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ static size_t rlogin_send(Backend *be, const char *buf, size_t len)
|
|||
bufchain bc;
|
||||
|
||||
if (rlogin->s == NULL)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
bufchain_init(&bc);
|
||||
bufchain_add(&bc, buf, len);
|
||||
|
@ -326,7 +326,7 @@ static void rlogin_size(Backend *be, int width, int height)
|
|||
rlogin->term_height = height;
|
||||
|
||||
if (rlogin->s == NULL || !rlogin->cansize)
|
||||
return;
|
||||
return;
|
||||
|
||||
b[6] = rlogin->term_width >> 8;
|
||||
b[7] = rlogin->term_width & 0xFF;
|
||||
|
|
|
@ -458,7 +458,7 @@ static void scp_source_abort(ScpSource *scp, const char *fmt, ...)
|
|||
static void scp_source_push_name(
|
||||
ScpSource *scp, ptrlen pathname, struct fxp_attrs attrs, const char *wc)
|
||||
{
|
||||
if (!(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
|
||||
if (!(attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS)) {
|
||||
scp_source_err(scp, "unable to read file permissions for %.*s",
|
||||
PTRLEN_PRINTF(pathname));
|
||||
return;
|
||||
|
@ -555,7 +555,7 @@ static void scp_source_send_CD(
|
|||
while ((slash = memchr(name.ptr, '/', name.len)) != NULL)
|
||||
name = make_ptrlen(
|
||||
slash+1, name.len - (slash+1 - (const char *)name.ptr));
|
||||
|
||||
|
||||
scp->pending_commands[scp->n_pending_commands++] = cmd = strbuf_new();
|
||||
strbuf_catf(cmd, "%c%04o %"PRIu64" %.*s\012", cmdchar,
|
||||
(unsigned)(attrs.permissions & 07777),
|
||||
|
|
250
sercfg.c
250
sercfg.c
|
@ -17,149 +17,149 @@
|
|||
#include "storage.h"
|
||||
|
||||
static void serial_parity_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event)
|
||||
void *data, int event)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
int val;
|
||||
const char *name;
|
||||
int val;
|
||||
} parities[] = {
|
||||
{"None", SER_PAR_NONE},
|
||||
{"Odd", SER_PAR_ODD},
|
||||
{"Even", SER_PAR_EVEN},
|
||||
{"Mark", SER_PAR_MARK},
|
||||
{"Space", SER_PAR_SPACE},
|
||||
{"None", SER_PAR_NONE},
|
||||
{"Odd", SER_PAR_ODD},
|
||||
{"Even", SER_PAR_EVEN},
|
||||
{"Mark", SER_PAR_MARK},
|
||||
{"Space", SER_PAR_SPACE},
|
||||
};
|
||||
int mask = ctrl->listbox.context.i;
|
||||
int i, j;
|
||||
Conf *conf = (Conf *)data;
|
||||
|
||||
if (event == EVENT_REFRESH) {
|
||||
/* Fetching this once at the start of the function ensures we
|
||||
* remember what the right value is supposed to be when
|
||||
* operations below cause reentrant calls to this function. */
|
||||
int oldparity = conf_get_int(conf, CONF_serparity);
|
||||
/* Fetching this once at the start of the function ensures we
|
||||
* remember what the right value is supposed to be when
|
||||
* operations below cause reentrant calls to this function. */
|
||||
int oldparity = conf_get_int(conf, CONF_serparity);
|
||||
|
||||
dlg_update_start(ctrl, dlg);
|
||||
dlg_listbox_clear(ctrl, dlg);
|
||||
for (i = 0; i < lenof(parities); i++) {
|
||||
if (mask & (1 << i))
|
||||
dlg_listbox_addwithid(ctrl, dlg, parities[i].name,
|
||||
parities[i].val);
|
||||
}
|
||||
for (i = j = 0; i < lenof(parities); i++) {
|
||||
if (mask & (1 << i)) {
|
||||
if (oldparity == parities[i].val) {
|
||||
dlg_listbox_select(ctrl, dlg, j);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (i == lenof(parities)) { /* an unsupported setting was chosen */
|
||||
dlg_listbox_select(ctrl, dlg, 0);
|
||||
oldparity = SER_PAR_NONE;
|
||||
}
|
||||
dlg_update_done(ctrl, dlg);
|
||||
conf_set_int(conf, CONF_serparity, oldparity); /* restore */
|
||||
dlg_update_start(ctrl, dlg);
|
||||
dlg_listbox_clear(ctrl, dlg);
|
||||
for (i = 0; i < lenof(parities); i++) {
|
||||
if (mask & (1 << i))
|
||||
dlg_listbox_addwithid(ctrl, dlg, parities[i].name,
|
||||
parities[i].val);
|
||||
}
|
||||
for (i = j = 0; i < lenof(parities); i++) {
|
||||
if (mask & (1 << i)) {
|
||||
if (oldparity == parities[i].val) {
|
||||
dlg_listbox_select(ctrl, dlg, j);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (i == lenof(parities)) { /* an unsupported setting was chosen */
|
||||
dlg_listbox_select(ctrl, dlg, 0);
|
||||
oldparity = SER_PAR_NONE;
|
||||
}
|
||||
dlg_update_done(ctrl, dlg);
|
||||
conf_set_int(conf, CONF_serparity, oldparity); /* restore */
|
||||
} else if (event == EVENT_SELCHANGE) {
|
||||
int i = dlg_listbox_index(ctrl, dlg);
|
||||
if (i < 0)
|
||||
i = SER_PAR_NONE;
|
||||
else
|
||||
i = dlg_listbox_getid(ctrl, dlg, i);
|
||||
conf_set_int(conf, CONF_serparity, i);
|
||||
int i = dlg_listbox_index(ctrl, dlg);
|
||||
if (i < 0)
|
||||
i = SER_PAR_NONE;
|
||||
else
|
||||
i = dlg_listbox_getid(ctrl, dlg, i);
|
||||
conf_set_int(conf, CONF_serparity, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void serial_flow_handler(union control *ctrl, dlgparam *dlg,
|
||||
void *data, int event)
|
||||
void *data, int event)
|
||||
{
|
||||
static const struct {
|
||||
const char *name;
|
||||
int val;
|
||||
const char *name;
|
||||
int val;
|
||||
} flows[] = {
|
||||
{"None", SER_FLOW_NONE},
|
||||
{"XON/XOFF", SER_FLOW_XONXOFF},
|
||||
{"RTS/CTS", SER_FLOW_RTSCTS},
|
||||
{"DSR/DTR", SER_FLOW_DSRDTR},
|
||||
{"None", SER_FLOW_NONE},
|
||||
{"XON/XOFF", SER_FLOW_XONXOFF},
|
||||
{"RTS/CTS", SER_FLOW_RTSCTS},
|
||||
{"DSR/DTR", SER_FLOW_DSRDTR},
|
||||
};
|
||||
int mask = ctrl->listbox.context.i;
|
||||
int i, j;
|
||||
Conf *conf = (Conf *)data;
|
||||
|
||||
if (event == EVENT_REFRESH) {
|
||||
/* Fetching this once at the start of the function ensures we
|
||||
* remember what the right value is supposed to be when
|
||||
* operations below cause reentrant calls to this function. */
|
||||
int oldflow = conf_get_int(conf, CONF_serflow);
|
||||
/* Fetching this once at the start of the function ensures we
|
||||
* remember what the right value is supposed to be when
|
||||
* operations below cause reentrant calls to this function. */
|
||||
int oldflow = conf_get_int(conf, CONF_serflow);
|
||||
|
||||
dlg_update_start(ctrl, dlg);
|
||||
dlg_listbox_clear(ctrl, dlg);
|
||||
for (i = 0; i < lenof(flows); i++) {
|
||||
if (mask & (1 << i))
|
||||
dlg_listbox_addwithid(ctrl, dlg, flows[i].name, flows[i].val);
|
||||
}
|
||||
for (i = j = 0; i < lenof(flows); i++) {
|
||||
if (mask & (1 << i)) {
|
||||
if (oldflow == flows[i].val) {
|
||||
dlg_listbox_select(ctrl, dlg, j);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (i == lenof(flows)) { /* an unsupported setting was chosen */
|
||||
dlg_listbox_select(ctrl, dlg, 0);
|
||||
oldflow = SER_FLOW_NONE;
|
||||
}
|
||||
dlg_update_done(ctrl, dlg);
|
||||
conf_set_int(conf, CONF_serflow, oldflow);/* restore */
|
||||
dlg_update_start(ctrl, dlg);
|
||||
dlg_listbox_clear(ctrl, dlg);
|
||||
for (i = 0; i < lenof(flows); i++) {
|
||||
if (mask & (1 << i))
|
||||
dlg_listbox_addwithid(ctrl, dlg, flows[i].name, flows[i].val);
|
||||
}
|
||||
for (i = j = 0; i < lenof(flows); i++) {
|
||||
if (mask & (1 << i)) {
|
||||
if (oldflow == flows[i].val) {
|
||||
dlg_listbox_select(ctrl, dlg, j);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (i == lenof(flows)) { /* an unsupported setting was chosen */
|
||||
dlg_listbox_select(ctrl, dlg, 0);
|
||||
oldflow = SER_FLOW_NONE;
|
||||
}
|
||||
dlg_update_done(ctrl, dlg);
|
||||
conf_set_int(conf, CONF_serflow, oldflow);/* restore */
|
||||
} else if (event == EVENT_SELCHANGE) {
|
||||
int i = dlg_listbox_index(ctrl, dlg);
|
||||
if (i < 0)
|
||||
i = SER_FLOW_NONE;
|
||||
else
|
||||
i = dlg_listbox_getid(ctrl, dlg, i);
|
||||
conf_set_int(conf, CONF_serflow, i);
|
||||
int i = dlg_listbox_index(ctrl, dlg);
|
||||
if (i < 0)
|
||||
i = SER_FLOW_NONE;
|
||||
else
|
||||
i = dlg_listbox_getid(ctrl, dlg, i);
|
||||
conf_set_int(conf, CONF_serflow, i);
|
||||
}
|
||||
}
|
||||
|
||||
void ser_setup_config_box(struct controlbox *b, bool midsession,
|
||||
int parity_mask, int flow_mask)
|
||||
int parity_mask, int flow_mask)
|
||||
{
|
||||
struct controlset *s;
|
||||
union control *c;
|
||||
|
||||
if (!midsession) {
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Add the serial back end to the protocols list at the
|
||||
* top of the config box.
|
||||
*/
|
||||
s = ctrl_getset(b, "Session", "hostport",
|
||||
"Specify the destination you want to connect to");
|
||||
/*
|
||||
* Add the serial back end to the protocols list at the
|
||||
* top of the config box.
|
||||
*/
|
||||
s = ctrl_getset(b, "Session", "hostport",
|
||||
"Specify the destination you want to connect to");
|
||||
|
||||
for (i = 0; i < s->ncontrols; i++) {
|
||||
c = s->ctrls[i];
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.handler == config_protocolbuttons_handler) {
|
||||
c->radio.nbuttons++;
|
||||
c->radio.ncolumns++;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Serial");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL);
|
||||
if (c->radio.shortcuts) {
|
||||
c->radio.shortcuts =
|
||||
sresize(c->radio.shortcuts, c->radio.nbuttons, char);
|
||||
c->radio.shortcuts[c->radio.nbuttons-1] = 'r';
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c->generic.type == CTRL_RADIO &&
|
||||
c->generic.handler == config_protocolbuttons_handler) {
|
||||
c->radio.nbuttons++;
|
||||
c->radio.ncolumns++;
|
||||
c->radio.buttons =
|
||||
sresize(c->radio.buttons, c->radio.nbuttons, char *);
|
||||
c->radio.buttons[c->radio.nbuttons-1] =
|
||||
dupstr("Serial");
|
||||
c->radio.buttondata =
|
||||
sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
|
||||
c->radio.buttondata[c->radio.nbuttons-1] = I(PROT_SERIAL);
|
||||
if (c->radio.shortcuts) {
|
||||
c->radio.shortcuts =
|
||||
sresize(c->radio.shortcuts, c->radio.nbuttons, char);
|
||||
c->radio.shortcuts[c->radio.nbuttons-1] = 'r';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -167,38 +167,38 @@ void ser_setup_config_box(struct controlbox *b, bool midsession,
|
|||
* configuration.
|
||||
*/
|
||||
ctrl_settitle(b, "Connection/Serial",
|
||||
"Options controlling local serial lines");
|
||||
"Options controlling local serial lines");
|
||||
|
||||
if (!midsession) {
|
||||
/*
|
||||
* We don't permit switching to a different serial port in
|
||||
* midflight, although we do allow all other
|
||||
* reconfiguration.
|
||||
*/
|
||||
s = ctrl_getset(b, "Connection/Serial", "serline",
|
||||
"Select a serial line");
|
||||
ctrl_editbox(s, "Serial line to connect to", 'l', 40,
|
||||
HELPCTX(serial_line),
|
||||
conf_editbox_handler, I(CONF_serline), I(1));
|
||||
/*
|
||||
* We don't permit switching to a different serial port in
|
||||
* midflight, although we do allow all other
|
||||
* reconfiguration.
|
||||
*/
|
||||
s = ctrl_getset(b, "Connection/Serial", "serline",
|
||||
"Select a serial line");
|
||||
ctrl_editbox(s, "Serial line to connect to", 'l', 40,
|
||||
HELPCTX(serial_line),
|
||||
conf_editbox_handler, I(CONF_serline), I(1));
|
||||
}
|
||||
|
||||
s = ctrl_getset(b, "Connection/Serial", "sercfg", "Configure the serial line");
|
||||
ctrl_editbox(s, "Speed (baud)", 's', 40,
|
||||
HELPCTX(serial_speed),
|
||||
conf_editbox_handler, I(CONF_serspeed), I(-1));
|
||||
HELPCTX(serial_speed),
|
||||
conf_editbox_handler, I(CONF_serspeed), I(-1));
|
||||
ctrl_editbox(s, "Data bits", 'b', 40,
|
||||
HELPCTX(serial_databits),
|
||||
conf_editbox_handler, I(CONF_serdatabits), I(-1));
|
||||
HELPCTX(serial_databits),
|
||||
conf_editbox_handler, I(CONF_serdatabits), I(-1));
|
||||
/*
|
||||
* Stop bits come in units of one half.
|
||||
*/
|
||||
ctrl_editbox(s, "Stop bits", 't', 40,
|
||||
HELPCTX(serial_stopbits),
|
||||
conf_editbox_handler, I(CONF_serstopbits), I(-2));
|
||||
HELPCTX(serial_stopbits),
|
||||
conf_editbox_handler, I(CONF_serstopbits), I(-2));
|
||||
ctrl_droplist(s, "Parity", 'p', 40,
|
||||
HELPCTX(serial_parity),
|
||||
serial_parity_handler, I(parity_mask));
|
||||
HELPCTX(serial_parity),
|
||||
serial_parity_handler, I(parity_mask));
|
||||
ctrl_droplist(s, "Flow control", 'f', 40,
|
||||
HELPCTX(serial_flow),
|
||||
serial_flow_handler, I(flow_mask));
|
||||
HELPCTX(serial_flow),
|
||||
serial_flow_handler, I(flow_mask));
|
||||
}
|
||||
|
|
|
@ -368,7 +368,7 @@ static int xfwd_accepting(Plug *p, accept_fn_t constructor, accept_ctx_t ctx)
|
|||
chan = portfwd_raw_new(sess->c->cl, &plug);
|
||||
s = constructor(ctx, plug);
|
||||
if ((err = sk_socket_error(s)) != NULL) {
|
||||
portfwd_raw_free(chan);
|
||||
portfwd_raw_free(chan);
|
||||
return 1;
|
||||
}
|
||||
pi = sk_peer_info(s);
|
||||
|
@ -444,7 +444,7 @@ static int agentfwd_accepting(
|
|||
chan = portfwd_raw_new(sess->c->cl, &plug);
|
||||
s = constructor(ctx, plug);
|
||||
if ((err = sk_socket_error(s)) != NULL) {
|
||||
portfwd_raw_free(chan);
|
||||
portfwd_raw_free(chan);
|
||||
return 1;
|
||||
}
|
||||
portfwd_raw_setup(chan, s, ssh_serverside_agent_open(sess->c->cl, chan));
|
||||
|
|
598
settings.c
598
settings.c
|
@ -56,12 +56,12 @@ static const struct keyvalwhere hknames[] = {
|
|||
* gppmap() invocation for "TerminalModes".
|
||||
*/
|
||||
const char *const ttymodes[] = {
|
||||
"INTR", "QUIT", "ERASE", "KILL", "EOF",
|
||||
"EOL", "EOL2", "START", "STOP", "SUSP",
|
||||
"DSUSP", "REPRINT", "WERASE", "LNEXT", "FLUSH",
|
||||
"SWTCH", "STATUS", "DISCARD", "IGNPAR", "PARMRK",
|
||||
"INPCK", "ISTRIP", "INLCR", "IGNCR", "ICRNL",
|
||||
"IUCLC", "IXON", "IXANY", "IXOFF", "IMAXBEL",
|
||||
"INTR", "QUIT", "ERASE", "KILL", "EOF",
|
||||
"EOL", "EOL2", "START", "STOP", "SUSP",
|
||||
"DSUSP", "REPRINT", "WERASE", "LNEXT", "FLUSH",
|
||||
"SWTCH", "STATUS", "DISCARD", "IGNPAR", "PARMRK",
|
||||
"INPCK", "ISTRIP", "INLCR", "IGNCR", "ICRNL",
|
||||
"IUCLC", "IXON", "IXANY", "IXOFF", "IMAXBEL",
|
||||
"IUTF8", "ISIG", "ICANON", "XCASE", "ECHO",
|
||||
"ECHOE", "ECHOK", "ECHONL", "NOFLSH", "TOSTOP",
|
||||
"IEXTEN", "ECHOCTL", "ECHOKE", "PENDIN", "OPOST",
|
||||
|
@ -78,8 +78,8 @@ const struct BackendVtable *backend_vt_from_name(const char *name)
|
|||
{
|
||||
const struct BackendVtable *const *p;
|
||||
for (p = backends; *p != NULL; p++)
|
||||
if (!strcmp((*p)->name, name))
|
||||
return *p;
|
||||
if (!strcmp((*p)->name, name))
|
||||
return *p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -87,8 +87,8 @@ const struct BackendVtable *backend_vt_from_proto(int proto)
|
|||
{
|
||||
const struct BackendVtable *const *p;
|
||||
for (p = backends; *p != NULL; p++)
|
||||
if ((*p)->protocol == proto)
|
||||
return *p;
|
||||
if ((*p)->protocol == proto)
|
||||
return *p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -96,12 +96,12 @@ char *get_remote_username(Conf *conf)
|
|||
{
|
||||
char *username = conf_get_str(conf, CONF_username);
|
||||
if (*username) {
|
||||
return dupstr(username);
|
||||
return dupstr(username);
|
||||
} else if (conf_get_bool(conf, CONF_username_from_env)) {
|
||||
/* Use local username. */
|
||||
return get_username(); /* might still be NULL */
|
||||
/* Use local username. */
|
||||
return get_username(); /* might still be NULL */
|
||||
} else {
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,14 +109,14 @@ static char *gpps_raw(settings_r *sesskey, const char *name, const char *def)
|
|||
{
|
||||
char *ret = read_setting_s(sesskey, name);
|
||||
if (!ret)
|
||||
ret = platform_default_s(name);
|
||||
ret = platform_default_s(name);
|
||||
if (!ret)
|
||||
ret = def ? dupstr(def) : NULL; /* permit NULL as final fallback */
|
||||
ret = def ? dupstr(def) : NULL; /* permit NULL as final fallback */
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void gpps(settings_r *sesskey, const char *name, const char *def,
|
||||
Conf *conf, int primary)
|
||||
Conf *conf, int primary)
|
||||
{
|
||||
char *val = gpps_raw(sesskey, name, def);
|
||||
conf_set_str(conf, primary, val);
|
||||
|
@ -142,7 +142,7 @@ static void gppfile(settings_r *sesskey, const char *name,
|
|||
{
|
||||
Filename *result = read_setting_filename(sesskey, name);
|
||||
if (!result)
|
||||
result = platform_default_filename(name);
|
||||
result = platform_default_filename(name);
|
||||
conf_set_filename(conf, primary, result);
|
||||
filename_free(result);
|
||||
}
|
||||
|
@ -195,27 +195,27 @@ static bool gppmap(settings_r *sesskey, const char *name,
|
|||
*/
|
||||
buf = gpps_raw(sesskey, name, NULL);
|
||||
if (!buf)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
p = buf;
|
||||
while (*p) {
|
||||
q = buf;
|
||||
val = NULL;
|
||||
while (*p && *p != ',') {
|
||||
int c = *p++;
|
||||
if (c == '=')
|
||||
c = '\0';
|
||||
if (c == '\\')
|
||||
c = *p++;
|
||||
*q++ = c;
|
||||
if (!c)
|
||||
val = q;
|
||||
}
|
||||
if (*p == ',')
|
||||
p++;
|
||||
if (!val)
|
||||
val = q;
|
||||
*q = '\0';
|
||||
q = buf;
|
||||
val = NULL;
|
||||
while (*p && *p != ',') {
|
||||
int c = *p++;
|
||||
if (c == '=')
|
||||
c = '\0';
|
||||
if (c == '\\')
|
||||
c = *p++;
|
||||
*q++ = c;
|
||||
if (!c)
|
||||
val = q;
|
||||
}
|
||||
if (*p == ',')
|
||||
p++;
|
||||
if (!val)
|
||||
val = q;
|
||||
*q = '\0';
|
||||
|
||||
if (primary == CONF_portfwd && strchr(buf, 'D') != NULL) {
|
||||
/*
|
||||
|
@ -253,19 +253,19 @@ static void wmap(settings_w *sesskey, char const *outkey, Conf *conf,
|
|||
const char *val, *q;
|
||||
int len;
|
||||
|
||||
len = 1; /* allow for NUL */
|
||||
len = 1; /* allow for NUL */
|
||||
|
||||
for (val = conf_get_str_strs(conf, primary, NULL, &key);
|
||||
val != NULL;
|
||||
val = conf_get_str_strs(conf, primary, key, &key))
|
||||
len += 2 + 2 * (strlen(key) + strlen(val)); /* allow for escaping */
|
||||
val != NULL;
|
||||
val = conf_get_str_strs(conf, primary, key, &key))
|
||||
len += 2 + 2 * (strlen(key) + strlen(val)); /* allow for escaping */
|
||||
|
||||
buf = snewn(len, char);
|
||||
p = buf;
|
||||
|
||||
for (val = conf_get_str_strs(conf, primary, NULL, &key);
|
||||
val != NULL;
|
||||
val = conf_get_str_strs(conf, primary, key, &key)) {
|
||||
val != NULL;
|
||||
val = conf_get_str_strs(conf, primary, key, &key)) {
|
||||
|
||||
if (primary == CONF_portfwd && !strcmp(val, "D")) {
|
||||
/*
|
||||
|
@ -286,13 +286,13 @@ static void wmap(settings_w *sesskey, char const *outkey, Conf *conf,
|
|||
realkey = NULL;
|
||||
}
|
||||
|
||||
if (p != buf)
|
||||
*p++ = ',';
|
||||
for (q = key; *q; q++) {
|
||||
if (*q == '=' || *q == ',' || *q == '\\')
|
||||
*p++ = '\\';
|
||||
*p++ = *q;
|
||||
}
|
||||
if (p != buf)
|
||||
*p++ = ',';
|
||||
for (q = key; *q; q++) {
|
||||
if (*q == '=' || *q == ',' || *q == '\\')
|
||||
*p++ = '\\';
|
||||
*p++ = *q;
|
||||
}
|
||||
if (include_values) {
|
||||
*p++ = '=';
|
||||
for (q = val; *q; q++) {
|
||||
|
@ -317,7 +317,7 @@ static int key2val(const struct keyvalwhere *mapping,
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < nmaps; i++)
|
||||
if (!strcmp(mapping[i].s, key)) return mapping[i].v;
|
||||
if (!strcmp(mapping[i].s, key)) return mapping[i].v;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,7 @@ static const char *val2key(const struct keyvalwhere *mapping,
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < nmaps; i++)
|
||||
if (mapping[i].v == val) return mapping[i].s;
|
||||
if (mapping[i].v == val) return mapping[i].s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -337,13 +337,13 @@ static const char *val2key(const struct keyvalwhere *mapping,
|
|||
* XXX: assumes vals in 'mapping' are small +ve integers
|
||||
*/
|
||||
static void gprefs_from_str(const char *str,
|
||||
const struct keyvalwhere *mapping, int nvals,
|
||||
Conf *conf, int primary)
|
||||
const struct keyvalwhere *mapping, int nvals,
|
||||
Conf *conf, int primary)
|
||||
{
|
||||
char *commalist = dupstr(str);
|
||||
char *p, *q;
|
||||
int i, j, n, v, pos;
|
||||
unsigned long seen = 0; /* bitmap for weeding dups etc */
|
||||
unsigned long seen = 0; /* bitmap for weeding dups etc */
|
||||
|
||||
/*
|
||||
* Go through that list and convert it into values.
|
||||
|
@ -361,10 +361,10 @@ static void gprefs_from_str(const char *str,
|
|||
|
||||
v = key2val(mapping, nvals, q);
|
||||
if (v != -1 && !(seen & (1 << v))) {
|
||||
seen |= (1 << v);
|
||||
seen |= (1 << v);
|
||||
conf_set_int_int(conf, primary, n, v);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sfree(commalist);
|
||||
|
@ -377,10 +377,10 @@ static void gprefs_from_str(const char *str,
|
|||
*/
|
||||
while (n < nvals) {
|
||||
for (i = 0; i < nvals; i++) {
|
||||
assert(mapping[i].v >= 0);
|
||||
assert(mapping[i].v < 32);
|
||||
assert(mapping[i].v >= 0);
|
||||
assert(mapping[i].v < 32);
|
||||
|
||||
if (!(seen & (1 << mapping[i].v))) {
|
||||
if (!(seen & (1 << mapping[i].v))) {
|
||||
/*
|
||||
* This element needs adding. But can we add it yet?
|
||||
*/
|
||||
|
@ -420,8 +420,8 @@ static void gprefs_from_str(const char *str,
|
|||
* Read a preference list.
|
||||
*/
|
||||
static void gprefs(settings_r *sesskey, const char *name, const char *def,
|
||||
const struct keyvalwhere *mapping, int nvals,
|
||||
Conf *conf, int primary)
|
||||
const struct keyvalwhere *mapping, int nvals,
|
||||
Conf *conf, int primary)
|
||||
{
|
||||
/*
|
||||
* Fetch the string which we'll parse as a comma-separated list.
|
||||
|
@ -431,20 +431,20 @@ static void gprefs(settings_r *sesskey, const char *name, const char *def,
|
|||
sfree(value);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* Write out a preference list.
|
||||
*/
|
||||
static void wprefs(settings_w *sesskey, const char *name,
|
||||
const struct keyvalwhere *mapping, int nvals,
|
||||
Conf *conf, int primary)
|
||||
const struct keyvalwhere *mapping, int nvals,
|
||||
Conf *conf, int primary)
|
||||
{
|
||||
char *buf, *p;
|
||||
int i, maxlen;
|
||||
|
||||
for (maxlen = i = 0; i < nvals; i++) {
|
||||
const char *s = val2key(mapping, nvals,
|
||||
const char *s = val2key(mapping, nvals,
|
||||
conf_get_int_int(conf, primary, i));
|
||||
if (s) {
|
||||
if (s) {
|
||||
maxlen += (maxlen > 0 ? 1 : 0) + strlen(s);
|
||||
}
|
||||
}
|
||||
|
@ -453,11 +453,11 @@ static void wprefs(settings_w *sesskey, const char *name,
|
|||
p = buf;
|
||||
|
||||
for (i = 0; i < nvals; i++) {
|
||||
const char *s = val2key(mapping, nvals,
|
||||
const char *s = val2key(mapping, nvals,
|
||||
conf_get_int_int(conf, primary, i));
|
||||
if (s) {
|
||||
if (s) {
|
||||
p += sprintf(p, "%s%s", (p > buf ? "," : ""), s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(p - buf == maxlen);
|
||||
|
@ -529,7 +529,7 @@ char *save_settings(const char *section, Conf *conf)
|
|||
|
||||
sesskey = open_settings_w(section, &errmsg);
|
||||
if (!sesskey)
|
||||
return errmsg;
|
||||
return errmsg;
|
||||
save_open_settings(sesskey, conf);
|
||||
close_settings_w(sesskey);
|
||||
return NULL;
|
||||
|
@ -562,8 +562,8 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
|
|||
* the standard FORCE_ON / FORCE_OFF / AUTO. */
|
||||
write_setting_i(sesskey, "CloseOnExit", (conf_get_int(conf, CONF_close_on_exit)+2)%3);
|
||||
write_setting_b(sesskey, "WarnOnClose", !!conf_get_bool(conf, CONF_warn_on_close));
|
||||
write_setting_i(sesskey, "PingInterval", conf_get_int(conf, CONF_ping_interval) / 60); /* minutes */
|
||||
write_setting_i(sesskey, "PingIntervalSecs", conf_get_int(conf, CONF_ping_interval) % 60); /* seconds */
|
||||
write_setting_i(sesskey, "PingInterval", conf_get_int(conf, CONF_ping_interval) / 60); /* minutes */
|
||||
write_setting_i(sesskey, "PingIntervalSecs", conf_get_int(conf, CONF_ping_interval) % 60); /* seconds */
|
||||
write_setting_b(sesskey, "TCPNoDelay", conf_get_bool(conf, CONF_tcp_nodelay));
|
||||
write_setting_b(sesskey, "TCPKeepalives", conf_get_bool(conf, CONF_tcp_keepalives));
|
||||
write_setting_s(sesskey, "TerminalType", conf_get_str(conf, CONF_termtype));
|
||||
|
@ -666,14 +666,14 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
|
|||
write_setting_i(sesskey, "BellOverloadN", conf_get_int(conf, CONF_bellovl_n));
|
||||
write_setting_i(sesskey, "BellOverloadT", conf_get_int(conf, CONF_bellovl_t)
|
||||
#ifdef PUTTY_UNIX_H
|
||||
* 1000
|
||||
* 1000
|
||||
#endif
|
||||
);
|
||||
);
|
||||
write_setting_i(sesskey, "BellOverloadS", conf_get_int(conf, CONF_bellovl_s)
|
||||
#ifdef PUTTY_UNIX_H
|
||||
* 1000
|
||||
* 1000
|
||||
#endif
|
||||
);
|
||||
);
|
||||
write_setting_i(sesskey, "ScrollbackLines", conf_get_int(conf, CONF_savelines));
|
||||
write_setting_b(sesskey, "DECOriginMode", conf_get_bool(conf, CONF_dec_om));
|
||||
write_setting_b(sesskey, "AutoWrapMode", conf_get_bool(conf, CONF_wrap_mode));
|
||||
|
@ -696,13 +696,13 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
|
|||
write_setting_i(sesskey, "BoldAsColour", conf_get_int(conf, CONF_bold_style)-1);
|
||||
|
||||
for (i = 0; i < 22; i++) {
|
||||
char buf[20], buf2[30];
|
||||
sprintf(buf, "Colour%d", i);
|
||||
sprintf(buf2, "%d,%d,%d",
|
||||
conf_get_int_int(conf, CONF_colours, i*3+0),
|
||||
conf_get_int_int(conf, CONF_colours, i*3+1),
|
||||
conf_get_int_int(conf, CONF_colours, i*3+2));
|
||||
write_setting_s(sesskey, buf, buf2);
|
||||
char buf[20], buf2[30];
|
||||
sprintf(buf, "Colour%d", i);
|
||||
sprintf(buf2, "%d,%d,%d",
|
||||
conf_get_int_int(conf, CONF_colours, i*3+0),
|
||||
conf_get_int_int(conf, CONF_colours, i*3+1),
|
||||
conf_get_int_int(conf, CONF_colours, i*3+2));
|
||||
write_setting_s(sesskey, buf, buf2);
|
||||
}
|
||||
write_setting_b(sesskey, "RawCNP", conf_get_bool(conf, CONF_rawcnp));
|
||||
write_setting_b(sesskey, "UTF8linedraw", conf_get_bool(conf, CONF_utf8linedraw));
|
||||
|
@ -712,16 +712,16 @@ void save_open_settings(settings_w *sesskey, Conf *conf)
|
|||
write_setting_b(sesskey, "PasteControls", conf_get_bool(conf, CONF_paste_controls));
|
||||
write_setting_b(sesskey, "MouseOverride", conf_get_bool(conf, CONF_mouse_override));
|
||||
for (i = 0; i < 256; i += 32) {
|
||||
char buf[20], buf2[256];
|
||||
int j;
|
||||
sprintf(buf, "Wordness%d", i);
|
||||
*buf2 = '\0';
|
||||
for (j = i; j < i + 32; j++) {
|
||||
sprintf(buf2 + strlen(buf2), "%s%d",
|
||||
(*buf2 ? "," : ""),
|
||||
conf_get_int_int(conf, CONF_wordness, j));
|
||||
}
|
||||
write_setting_s(sesskey, buf, buf2);
|
||||
char buf[20], buf2[256];
|
||||
int j;
|
||||
sprintf(buf, "Wordness%d", i);
|
||||
*buf2 = '\0';
|
||||
for (j = i; j < i + 32; j++) {
|
||||
sprintf(buf2 + strlen(buf2), "%s%d",
|
||||
(*buf2 ? "," : ""),
|
||||
conf_get_int_int(conf, CONF_wordness, j));
|
||||
}
|
||||
write_setting_s(sesskey, buf, buf2);
|
||||
}
|
||||
write_setting_b(sesskey, "MouseAutocopy",
|
||||
conf_get_bool(conf, CONF_mouseautocopy));
|
||||
|
@ -826,8 +826,8 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
const struct BackendVtable *vt = backend_vt_from_name(prot);
|
||||
if (vt) {
|
||||
conf_set_int(conf, CONF_protocol, vt->protocol);
|
||||
gppi(sesskey, "PortNumber", default_port, conf, CONF_port);
|
||||
}
|
||||
gppi(sesskey, "PortNumber", default_port, conf, CONF_port);
|
||||
}
|
||||
}
|
||||
sfree(prot);
|
||||
|
||||
|
@ -839,65 +839,65 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
i = gppi_raw(sesskey, "CloseOnExit", 1); conf_set_int(conf, CONF_close_on_exit, (i+1)%3);
|
||||
gppb(sesskey, "WarnOnClose", true, conf, CONF_warn_on_close);
|
||||
{
|
||||
/* This is two values for backward compatibility with 0.50/0.51 */
|
||||
int pingmin, pingsec;
|
||||
pingmin = gppi_raw(sesskey, "PingInterval", 0);
|
||||
pingsec = gppi_raw(sesskey, "PingIntervalSecs", 0);
|
||||
conf_set_int(conf, CONF_ping_interval, pingmin * 60 + pingsec);
|
||||
/* This is two values for backward compatibility with 0.50/0.51 */
|
||||
int pingmin, pingsec;
|
||||
pingmin = gppi_raw(sesskey, "PingInterval", 0);
|
||||
pingsec = gppi_raw(sesskey, "PingIntervalSecs", 0);
|
||||
conf_set_int(conf, CONF_ping_interval, pingmin * 60 + pingsec);
|
||||
}
|
||||
gppb(sesskey, "TCPNoDelay", true, conf, CONF_tcp_nodelay);
|
||||
gppb(sesskey, "TCPKeepalives", false, conf, CONF_tcp_keepalives);
|
||||
gpps(sesskey, "TerminalType", "xterm", conf, CONF_termtype);
|
||||
gpps(sesskey, "TerminalSpeed", "38400,38400", conf, CONF_termspeed);
|
||||
if (gppmap(sesskey, "TerminalModes", conf, CONF_ttymodes)) {
|
||||
/*
|
||||
* Backwards compatibility with old saved settings.
|
||||
*
|
||||
* From the invention of this setting through 0.67, the set of
|
||||
* terminal modes was fixed, and absence of a mode from this
|
||||
* setting meant the user had explicitly removed it from the
|
||||
* UI and we shouldn't send it.
|
||||
*
|
||||
* In 0.68, the IUTF8 mode was added, and in handling old
|
||||
* settings we inadvertently removed the ability to not send
|
||||
* a mode. Any mode not mentioned was treated as if it was
|
||||
* set to 'auto' (A).
|
||||
*
|
||||
* After 0.68, we added explicit notation to the setting format
|
||||
* when the user removes a known terminal mode from the list.
|
||||
*
|
||||
* So: if any of the modes from the original set is missing, we
|
||||
* assume this was an intentional removal by the user and add
|
||||
* an explicit removal ('N'); but if IUTF8 (or any other mode
|
||||
* added after 0.67) is missing, we assume that its absence is
|
||||
* due to the setting being old rather than intentional, and
|
||||
* add it with its default setting.
|
||||
*
|
||||
* (This does mean that if a 0.68 user explicitly removed IUTF8,
|
||||
* we add it back; but removing IUTF8 had no effect in 0.68, so
|
||||
* we're preserving behaviour, which is the best we can do.)
|
||||
*/
|
||||
for (i = 0; ttymodes[i]; i++) {
|
||||
if (!conf_get_str_str_opt(conf, CONF_ttymodes, ttymodes[i])) {
|
||||
/* Mode not mentioned in setting. */
|
||||
const char *def;
|
||||
if (!strcmp(ttymodes[i], "IUTF8")) {
|
||||
/* Any new modes we add in future should be treated
|
||||
* this way too. */
|
||||
def = "A"; /* same as new-setting default below */
|
||||
} else {
|
||||
/* One of the original modes. Absence is probably
|
||||
* deliberate. */
|
||||
def = "N"; /* don't send */
|
||||
}
|
||||
conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], def);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Backwards compatibility with old saved settings.
|
||||
*
|
||||
* From the invention of this setting through 0.67, the set of
|
||||
* terminal modes was fixed, and absence of a mode from this
|
||||
* setting meant the user had explicitly removed it from the
|
||||
* UI and we shouldn't send it.
|
||||
*
|
||||
* In 0.68, the IUTF8 mode was added, and in handling old
|
||||
* settings we inadvertently removed the ability to not send
|
||||
* a mode. Any mode not mentioned was treated as if it was
|
||||
* set to 'auto' (A).
|
||||
*
|
||||
* After 0.68, we added explicit notation to the setting format
|
||||
* when the user removes a known terminal mode from the list.
|
||||
*
|
||||
* So: if any of the modes from the original set is missing, we
|
||||
* assume this was an intentional removal by the user and add
|
||||
* an explicit removal ('N'); but if IUTF8 (or any other mode
|
||||
* added after 0.67) is missing, we assume that its absence is
|
||||
* due to the setting being old rather than intentional, and
|
||||
* add it with its default setting.
|
||||
*
|
||||
* (This does mean that if a 0.68 user explicitly removed IUTF8,
|
||||
* we add it back; but removing IUTF8 had no effect in 0.68, so
|
||||
* we're preserving behaviour, which is the best we can do.)
|
||||
*/
|
||||
for (i = 0; ttymodes[i]; i++) {
|
||||
if (!conf_get_str_str_opt(conf, CONF_ttymodes, ttymodes[i])) {
|
||||
/* Mode not mentioned in setting. */
|
||||
const char *def;
|
||||
if (!strcmp(ttymodes[i], "IUTF8")) {
|
||||
/* Any new modes we add in future should be treated
|
||||
* this way too. */
|
||||
def = "A"; /* same as new-setting default below */
|
||||
} else {
|
||||
/* One of the original modes. Absence is probably
|
||||
* deliberate. */
|
||||
def = "N"; /* don't send */
|
||||
}
|
||||
conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], def);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* This hardcodes a big set of defaults in any new saved
|
||||
* sessions. Let's hope we don't change our mind. */
|
||||
for (i = 0; ttymodes[i]; i++)
|
||||
conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], "A");
|
||||
/* This hardcodes a big set of defaults in any new saved
|
||||
* sessions. Let's hope we don't change our mind. */
|
||||
for (i = 0; ttymodes[i]; i++)
|
||||
conf_set_str_str(conf, CONF_ttymodes, ttymodes[i], "A");
|
||||
}
|
||||
|
||||
/* proxy settings */
|
||||
|
@ -929,7 +929,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
gpps(sesskey, "ProxyUsername", "", conf, CONF_proxy_username);
|
||||
gpps(sesskey, "ProxyPassword", "", conf, CONF_proxy_password);
|
||||
gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",
|
||||
conf, CONF_proxy_telnet_command);
|
||||
conf, CONF_proxy_telnet_command);
|
||||
gppi(sesskey, "ProxyLogToTerm", FORCE_OFF, conf, CONF_proxy_log_to_term);
|
||||
gppmap(sesskey, "Environment", conf, CONF_environmt);
|
||||
gpps(sesskey, "UserName", "", conf, CONF_username);
|
||||
|
@ -945,53 +945,53 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
gppb(sesskey, "GssapiFwd", false, conf, CONF_gssapifwd);
|
||||
#endif
|
||||
gprefs(sesskey, "Cipher", "\0",
|
||||
ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);
|
||||
ciphernames, CIPHER_MAX, conf, CONF_ssh_cipherlist);
|
||||
{
|
||||
/* Backward-compatibility: before 0.58 (when the "KEX"
|
||||
* preference was first added), we had an option to
|
||||
* disable gex under the "bugs" panel after one report of
|
||||
* a server which offered it then choked, but we never got
|
||||
* a server version string or any other reports. */
|
||||
const char *default_kexes,
|
||||
*normal_default = "ecdh,dh-gex-sha1,dh-group14-sha1,rsa,"
|
||||
"WARN,dh-group1-sha1",
|
||||
*bugdhgex2_default = "ecdh,dh-group14-sha1,rsa,"
|
||||
"WARN,dh-group1-sha1,dh-gex-sha1";
|
||||
char *raw;
|
||||
i = 2 - gppi_raw(sesskey, "BugDHGEx2", 0);
|
||||
if (i == FORCE_ON)
|
||||
/* Backward-compatibility: before 0.58 (when the "KEX"
|
||||
* preference was first added), we had an option to
|
||||
* disable gex under the "bugs" panel after one report of
|
||||
* a server which offered it then choked, but we never got
|
||||
* a server version string or any other reports. */
|
||||
const char *default_kexes,
|
||||
*normal_default = "ecdh,dh-gex-sha1,dh-group14-sha1,rsa,"
|
||||
"WARN,dh-group1-sha1",
|
||||
*bugdhgex2_default = "ecdh,dh-group14-sha1,rsa,"
|
||||
"WARN,dh-group1-sha1,dh-gex-sha1";
|
||||
char *raw;
|
||||
i = 2 - gppi_raw(sesskey, "BugDHGEx2", 0);
|
||||
if (i == FORCE_ON)
|
||||
default_kexes = bugdhgex2_default;
|
||||
else
|
||||
else
|
||||
default_kexes = normal_default;
|
||||
/* Migration: after 0.67 we decided we didn't like
|
||||
* dh-group1-sha1. If it looks like the user never changed
|
||||
* the defaults, quietly upgrade their settings to demote it.
|
||||
* (If they did, they're on their own.) */
|
||||
raw = gpps_raw(sesskey, "KEX", default_kexes);
|
||||
assert(raw != NULL);
|
||||
/* Lack of 'ecdh' tells us this was saved by 0.58-0.67
|
||||
* inclusive. If it was saved by a later version, we need
|
||||
* to leave it alone. */
|
||||
if (strcmp(raw, "dh-group14-sha1,dh-group1-sha1,rsa,"
|
||||
"WARN,dh-gex-sha1") == 0) {
|
||||
/* Previously migrated from BugDHGEx2. */
|
||||
sfree(raw);
|
||||
raw = dupstr(bugdhgex2_default);
|
||||
} else if (strcmp(raw, "dh-gex-sha1,dh-group14-sha1,"
|
||||
"dh-group1-sha1,rsa,WARN") == 0) {
|
||||
/* Untouched old default setting. */
|
||||
sfree(raw);
|
||||
raw = dupstr(normal_default);
|
||||
}
|
||||
/* (For the record: after 0.70, the default algorithm list
|
||||
* very briefly contained the string 'gss-sha1-krb5'; this was
|
||||
* never used in any committed version of code, but was left
|
||||
* over from a pre-commit version of GSS key exchange.
|
||||
* Mentioned here as it is remotely possible that it will turn
|
||||
* up in someone's saved settings in future.) */
|
||||
/* Migration: after 0.67 we decided we didn't like
|
||||
* dh-group1-sha1. If it looks like the user never changed
|
||||
* the defaults, quietly upgrade their settings to demote it.
|
||||
* (If they did, they're on their own.) */
|
||||
raw = gpps_raw(sesskey, "KEX", default_kexes);
|
||||
assert(raw != NULL);
|
||||
/* Lack of 'ecdh' tells us this was saved by 0.58-0.67
|
||||
* inclusive. If it was saved by a later version, we need
|
||||
* to leave it alone. */
|
||||
if (strcmp(raw, "dh-group14-sha1,dh-group1-sha1,rsa,"
|
||||
"WARN,dh-gex-sha1") == 0) {
|
||||
/* Previously migrated from BugDHGEx2. */
|
||||
sfree(raw);
|
||||
raw = dupstr(bugdhgex2_default);
|
||||
} else if (strcmp(raw, "dh-gex-sha1,dh-group14-sha1,"
|
||||
"dh-group1-sha1,rsa,WARN") == 0) {
|
||||
/* Untouched old default setting. */
|
||||
sfree(raw);
|
||||
raw = dupstr(normal_default);
|
||||
}
|
||||
/* (For the record: after 0.70, the default algorithm list
|
||||
* very briefly contained the string 'gss-sha1-krb5'; this was
|
||||
* never used in any committed version of code, but was left
|
||||
* over from a pre-commit version of GSS key exchange.
|
||||
* Mentioned here as it is remotely possible that it will turn
|
||||
* up in someone's saved settings in future.) */
|
||||
|
||||
gprefs_from_str(raw, kexnames, KEX_MAX, conf, CONF_ssh_kexlist);
|
||||
sfree(raw);
|
||||
sfree(raw);
|
||||
}
|
||||
gprefs(sesskey, "HostKey", "ed25519,ecdsa,rsa,dsa,WARN",
|
||||
hknames, HK_MAX, conf, CONF_ssh_hklist);
|
||||
|
@ -1001,13 +1001,13 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
#endif
|
||||
gpps(sesskey, "RekeyBytes", "1G", conf, CONF_ssh_rekey_data);
|
||||
{
|
||||
/* SSH-2 only by default */
|
||||
int sshprot = gppi_raw(sesskey, "SshProt", 3);
|
||||
/* Old sessions may contain the values corresponding to the fallbacks
|
||||
* we used to allow; migrate them */
|
||||
if (sshprot == 1) sshprot = 0; /* => "SSH-1 only" */
|
||||
else if (sshprot == 2) sshprot = 3; /* => "SSH-2 only" */
|
||||
conf_set_int(conf, CONF_sshprot, sshprot);
|
||||
/* SSH-2 only by default */
|
||||
int sshprot = gppi_raw(sesskey, "SshProt", 3);
|
||||
/* Old sessions may contain the values corresponding to the fallbacks
|
||||
* we used to allow; migrate them */
|
||||
if (sshprot == 1) sshprot = 0; /* => "SSH-1 only" */
|
||||
else if (sshprot == 2) sshprot = 3; /* => "SSH-2 only" */
|
||||
conf_set_int(conf, CONF_sshprot, sshprot);
|
||||
}
|
||||
gpps(sesskey, "LogHost", "", conf, CONF_loghost);
|
||||
gppb(sesskey, "SSH2DES", false, conf, CONF_ssh2_des_cbc);
|
||||
|
@ -1019,7 +1019,7 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
gppb(sesskey, "AuthGSSAPI", true, conf, CONF_try_gssapi_auth);
|
||||
gppb(sesskey, "AuthGSSAPIKEX", true, conf, CONF_try_gssapi_kex);
|
||||
gprefs(sesskey, "GSSLibs", "\0",
|
||||
gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);
|
||||
gsslibkeywords, ngsslibs, conf, CONF_ssh_gsslist);
|
||||
gppfile(sesskey, "GSSCustom", conf, CONF_ssh_gss_custom);
|
||||
#endif
|
||||
gppb(sesskey, "SshNoShell", false, conf, CONF_ssh_no_shell);
|
||||
|
@ -1039,14 +1039,14 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
gppb(sesskey, "NoRemoteClearScroll", false,
|
||||
conf, CONF_no_remote_clearscroll);
|
||||
{
|
||||
/* Backward compatibility */
|
||||
int no_remote_qtitle = gppi_raw(sesskey, "NoRemoteQTitle", 1);
|
||||
/* We deliberately interpret the old setting of "no response" as
|
||||
* "empty string". This changes the behaviour, but hopefully for
|
||||
* the better; the user can always recover the old behaviour. */
|
||||
gppi(sesskey, "RemoteQTitleAction",
|
||||
no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,
|
||||
conf, CONF_remote_qtitle_action);
|
||||
/* Backward compatibility */
|
||||
int no_remote_qtitle = gppi_raw(sesskey, "NoRemoteQTitle", 1);
|
||||
/* We deliberately interpret the old setting of "no response" as
|
||||
* "empty string". This changes the behaviour, but hopefully for
|
||||
* the better; the user can always recover the old behaviour. */
|
||||
gppi(sesskey, "RemoteQTitleAction",
|
||||
no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,
|
||||
conf, CONF_remote_qtitle_action);
|
||||
}
|
||||
gppb(sesskey, "NoDBackspace", false, conf, CONF_no_dbackspace);
|
||||
gppb(sesskey, "NoRemoteCharset", false, conf, CONF_no_remote_charset);
|
||||
|
@ -1083,24 +1083,24 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
gppi(sesskey, "BellOverloadN", 5, conf, CONF_bellovl_n);
|
||||
i = gppi_raw(sesskey, "BellOverloadT", 2*TICKSPERSEC
|
||||
#ifdef PUTTY_UNIX_H
|
||||
*1000
|
||||
*1000
|
||||
#endif
|
||||
);
|
||||
);
|
||||
conf_set_int(conf, CONF_bellovl_t, i
|
||||
#ifdef PUTTY_UNIX_H
|
||||
/ 1000
|
||||
/ 1000
|
||||
#endif
|
||||
);
|
||||
);
|
||||
i = gppi_raw(sesskey, "BellOverloadS", 5*TICKSPERSEC
|
||||
#ifdef PUTTY_UNIX_H
|
||||
*1000
|
||||
*1000
|
||||
#endif
|
||||
);
|
||||
);
|
||||
conf_set_int(conf, CONF_bellovl_s, i
|
||||
#ifdef PUTTY_UNIX_H
|
||||
/ 1000
|
||||
/ 1000
|
||||
#endif
|
||||
);
|
||||
);
|
||||
gppi(sesskey, "ScrollbackLines", 2000, conf, CONF_savelines);
|
||||
gppb(sesskey, "DECOriginMode", false, conf, CONF_dec_om);
|
||||
gppb(sesskey, "AutoWrapMode", true, conf, CONF_wrap_mode);
|
||||
|
@ -1123,23 +1123,23 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
i = gppi_raw(sesskey, "BoldAsColour", 1); conf_set_int(conf, CONF_bold_style, i+1);
|
||||
|
||||
for (i = 0; i < 22; i++) {
|
||||
static const char *const defaults[] = {
|
||||
"187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
|
||||
"0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
|
||||
"0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
|
||||
"85,85,255", "187,0,187", "255,85,255", "0,187,187",
|
||||
"85,255,255", "187,187,187", "255,255,255"
|
||||
};
|
||||
char buf[20], *buf2;
|
||||
int c0, c1, c2;
|
||||
sprintf(buf, "Colour%d", i);
|
||||
buf2 = gpps_raw(sesskey, buf, defaults[i]);
|
||||
if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
|
||||
conf_set_int_int(conf, CONF_colours, i*3+0, c0);
|
||||
conf_set_int_int(conf, CONF_colours, i*3+1, c1);
|
||||
conf_set_int_int(conf, CONF_colours, i*3+2, c2);
|
||||
}
|
||||
sfree(buf2);
|
||||
static const char *const defaults[] = {
|
||||
"187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
|
||||
"0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
|
||||
"0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
|
||||
"85,85,255", "187,0,187", "255,85,255", "0,187,187",
|
||||
"85,255,255", "187,187,187", "255,255,255"
|
||||
};
|
||||
char buf[20], *buf2;
|
||||
int c0, c1, c2;
|
||||
sprintf(buf, "Colour%d", i);
|
||||
buf2 = gpps_raw(sesskey, buf, defaults[i]);
|
||||
if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
|
||||
conf_set_int_int(conf, CONF_colours, i*3+0, c0);
|
||||
conf_set_int_int(conf, CONF_colours, i*3+1, c1);
|
||||
conf_set_int_int(conf, CONF_colours, i*3+2, c2);
|
||||
}
|
||||
sfree(buf2);
|
||||
}
|
||||
gppb(sesskey, "RawCNP", false, conf, CONF_rawcnp);
|
||||
gppb(sesskey, "UTF8linedraw", false, conf, CONF_utf8linedraw);
|
||||
|
@ -1149,30 +1149,30 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
gppb(sesskey, "PasteControls", false, conf, CONF_paste_controls);
|
||||
gppb(sesskey, "MouseOverride", true, conf, CONF_mouse_override);
|
||||
for (i = 0; i < 256; i += 32) {
|
||||
static const char *const defaults[] = {
|
||||
"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
|
||||
"0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
|
||||
"1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
|
||||
"1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
|
||||
"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
|
||||
"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
|
||||
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
|
||||
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
|
||||
};
|
||||
char buf[20], *buf2, *p;
|
||||
int j;
|
||||
sprintf(buf, "Wordness%d", i);
|
||||
buf2 = gpps_raw(sesskey, buf, defaults[i / 32]);
|
||||
p = buf2;
|
||||
for (j = i; j < i + 32; j++) {
|
||||
char *q = p;
|
||||
while (*p && *p != ',')
|
||||
p++;
|
||||
if (*p == ',')
|
||||
*p++ = '\0';
|
||||
conf_set_int_int(conf, CONF_wordness, j, atoi(q));
|
||||
}
|
||||
sfree(buf2);
|
||||
static const char *const defaults[] = {
|
||||
"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
|
||||
"0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
|
||||
"1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
|
||||
"1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
|
||||
"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
|
||||
"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
|
||||
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
|
||||
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
|
||||
};
|
||||
char buf[20], *buf2, *p;
|
||||
int j;
|
||||
sprintf(buf, "Wordness%d", i);
|
||||
buf2 = gpps_raw(sesskey, buf, defaults[i / 32]);
|
||||
p = buf2;
|
||||
for (j = i; j < i + 32; j++) {
|
||||
char *q = p;
|
||||
while (*p && *p != ',')
|
||||
p++;
|
||||
if (*p == ',')
|
||||
*p++ = '\0';
|
||||
conf_set_int_int(conf, CONF_wordness, j, atoi(q));
|
||||
}
|
||||
sfree(buf2);
|
||||
}
|
||||
gppb(sesskey, "MouseAutocopy", CLIPUI_DEFAULT_AUTOCOPY,
|
||||
conf, CONF_mouseautocopy);
|
||||
|
@ -1213,13 +1213,13 @@ void load_open_settings(settings_r *sesskey, Conf *conf)
|
|||
i = gppi_raw(sesskey, "BugRSA1", 0); conf_set_int(conf, CONF_sshbug_rsa1, 2-i);
|
||||
i = gppi_raw(sesskey, "BugIgnore2", 0); conf_set_int(conf, CONF_sshbug_ignore2, 2-i);
|
||||
{
|
||||
int i;
|
||||
i = gppi_raw(sesskey, "BugHMAC2", 0); conf_set_int(conf, CONF_sshbug_hmac2, 2-i);
|
||||
if (2-i == AUTO) {
|
||||
i = gppi_raw(sesskey, "BuggyMAC", 0);
|
||||
if (i == 1)
|
||||
conf_set_int(conf, CONF_sshbug_hmac2, FORCE_ON);
|
||||
}
|
||||
int i;
|
||||
i = gppi_raw(sesskey, "BugHMAC2", 0); conf_set_int(conf, CONF_sshbug_hmac2, 2-i);
|
||||
if (2-i == AUTO) {
|
||||
i = gppi_raw(sesskey, "BuggyMAC", 0);
|
||||
if (i == 1)
|
||||
conf_set_int(conf, CONF_sshbug_hmac2, FORCE_ON);
|
||||
}
|
||||
}
|
||||
i = gppi_raw(sesskey, "BugDeriveKey2", 0); conf_set_int(conf, CONF_sshbug_derivekey2, 2-i);
|
||||
i = gppi_raw(sesskey, "BugRSAPad2", 0); conf_set_int(conf, CONF_sshbug_rsapad2, 2-i);
|
||||
|
@ -1269,14 +1269,14 @@ static int sessioncmp(const void *av, const void *bv)
|
|||
* special case and comes first.
|
||||
*/
|
||||
if (!strcmp(a, "Default Settings"))
|
||||
return -1; /* a comes first */
|
||||
return -1; /* a comes first */
|
||||
if (!strcmp(b, "Default Settings"))
|
||||
return +1; /* b comes first */
|
||||
return +1; /* b comes first */
|
||||
/*
|
||||
* FIXME: perhaps we should ignore the first & in determining
|
||||
* sort order.
|
||||
*/
|
||||
return strcmp(a, b); /* otherwise, compare normally */
|
||||
return strcmp(a, b); /* otherwise, compare normally */
|
||||
}
|
||||
|
||||
void get_sesslist(struct sesslist *list, bool allocate)
|
||||
|
@ -1288,47 +1288,47 @@ void get_sesslist(struct sesslist *list, bool allocate)
|
|||
if (allocate) {
|
||||
strbuf *sb = strbuf_new();
|
||||
|
||||
if ((handle = enum_settings_start()) != NULL) {
|
||||
if ((handle = enum_settings_start()) != NULL) {
|
||||
while (enum_settings_next(handle, sb))
|
||||
put_byte(sb, '\0');
|
||||
enum_settings_finish(handle);
|
||||
}
|
||||
enum_settings_finish(handle);
|
||||
}
|
||||
put_byte(sb, '\0');
|
||||
list->buffer = strbuf_to_str(sb);
|
||||
list->buffer = strbuf_to_str(sb);
|
||||
|
||||
/*
|
||||
* Now set up the list of sessions. Note that "Default
|
||||
* Settings" must always be claimed to exist, even if it
|
||||
* doesn't really.
|
||||
*/
|
||||
/*
|
||||
* Now set up the list of sessions. Note that "Default
|
||||
* Settings" must always be claimed to exist, even if it
|
||||
* doesn't really.
|
||||
*/
|
||||
|
||||
p = list->buffer;
|
||||
list->nsessions = 1; /* "Default Settings" counts as one */
|
||||
while (*p) {
|
||||
if (strcmp(p, "Default Settings"))
|
||||
list->nsessions++;
|
||||
while (*p)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
p = list->buffer;
|
||||
list->nsessions = 1; /* "Default Settings" counts as one */
|
||||
while (*p) {
|
||||
if (strcmp(p, "Default Settings"))
|
||||
list->nsessions++;
|
||||
while (*p)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
|
||||
list->sessions = snewn(list->nsessions + 1, const char *);
|
||||
list->sessions[0] = "Default Settings";
|
||||
p = list->buffer;
|
||||
i = 1;
|
||||
while (*p) {
|
||||
if (strcmp(p, "Default Settings"))
|
||||
list->sessions[i++] = p;
|
||||
while (*p)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
list->sessions = snewn(list->nsessions + 1, const char *);
|
||||
list->sessions[0] = "Default Settings";
|
||||
p = list->buffer;
|
||||
i = 1;
|
||||
while (*p) {
|
||||
if (strcmp(p, "Default Settings"))
|
||||
list->sessions[i++] = p;
|
||||
while (*p)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
|
||||
qsort(list->sessions, i, sizeof(const char *), sessioncmp);
|
||||
qsort(list->sessions, i, sizeof(const char *), sessioncmp);
|
||||
} else {
|
||||
sfree(list->buffer);
|
||||
sfree(list->sessions);
|
||||
list->buffer = NULL;
|
||||
list->sessions = NULL;
|
||||
sfree(list->buffer);
|
||||
sfree(list->sessions);
|
||||
list->buffer = NULL;
|
||||
list->sessions = NULL;
|
||||
}
|
||||
}
|
||||
|
|
440
sftp.c
440
sftp.c
|
@ -36,18 +36,18 @@ struct sftp_packet *sftp_recv(void)
|
|||
char x[4];
|
||||
|
||||
if (!sftp_recvdata(x, 4))
|
||||
return NULL;
|
||||
return NULL;
|
||||
|
||||
pkt = sftp_recv_prepare(GET_32BIT_MSB_FIRST(x));
|
||||
|
||||
if (!sftp_recvdata(pkt->data, pkt->length)) {
|
||||
sftp_pkt_free(pkt);
|
||||
return NULL;
|
||||
sftp_pkt_free(pkt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!sftp_recv_finish(pkt)) {
|
||||
sftp_pkt_free(pkt);
|
||||
return NULL;
|
||||
sftp_pkt_free(pkt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pkt;
|
||||
|
@ -70,9 +70,9 @@ static int sftp_reqcmp(void *av, void *bv)
|
|||
struct sftp_request *a = (struct sftp_request *)av;
|
||||
struct sftp_request *b = (struct sftp_request *)bv;
|
||||
if (a->id < b->id)
|
||||
return -1;
|
||||
return -1;
|
||||
if (a->id > b->id)
|
||||
return +1;
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
static int sftp_reqfind(void *av, void *bv)
|
||||
|
@ -80,9 +80,9 @@ static int sftp_reqfind(void *av, void *bv)
|
|||
unsigned *a = (unsigned *) av;
|
||||
struct sftp_request *b = (struct sftp_request *)bv;
|
||||
if (*a < b->id)
|
||||
return -1;
|
||||
return -1;
|
||||
if (*a > b->id)
|
||||
return +1;
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ static struct sftp_request *sftp_alloc_request(void)
|
|||
struct sftp_request *r;
|
||||
|
||||
if (sftp_requests == NULL)
|
||||
sftp_requests = newtree234(sftp_reqcmp);
|
||||
sftp_requests = newtree234(sftp_reqcmp);
|
||||
|
||||
/*
|
||||
* First-fit allocation of request IDs: always pick the lowest
|
||||
|
@ -110,20 +110,20 @@ static struct sftp_request *sftp_alloc_request(void)
|
|||
low = -1;
|
||||
high = tsize;
|
||||
while (high - low > 1) {
|
||||
mid = (high + low) / 2;
|
||||
r = index234(sftp_requests, mid);
|
||||
if (r->id == mid + REQUEST_ID_OFFSET)
|
||||
low = mid; /* this one is fine */
|
||||
else
|
||||
high = mid; /* this one is past it */
|
||||
mid = (high + low) / 2;
|
||||
r = index234(sftp_requests, mid);
|
||||
if (r->id == mid + REQUEST_ID_OFFSET)
|
||||
low = mid; /* this one is fine */
|
||||
else
|
||||
high = mid; /* this one is past it */
|
||||
}
|
||||
/*
|
||||
* Now low points to either -1, or the tree index of the
|
||||
* largest ID in the initial sequence.
|
||||
*/
|
||||
{
|
||||
unsigned i = low + 1 + REQUEST_ID_OFFSET;
|
||||
assert(NULL == find234(sftp_requests, &i, sftp_reqfind));
|
||||
unsigned i = low + 1 + REQUEST_ID_OFFSET;
|
||||
assert(NULL == find234(sftp_requests, &i, sftp_reqfind));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -141,8 +141,8 @@ static struct sftp_request *sftp_alloc_request(void)
|
|||
void sftp_cleanup_request(void)
|
||||
{
|
||||
if (sftp_requests != NULL) {
|
||||
freetree234(sftp_requests);
|
||||
sftp_requests = NULL;
|
||||
freetree234(sftp_requests);
|
||||
sftp_requests = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,20 +157,20 @@ struct sftp_request *sftp_find_request(struct sftp_packet *pktin)
|
|||
struct sftp_request *req;
|
||||
|
||||
if (!pktin) {
|
||||
fxp_internal_error("did not receive a valid SFTP packet\n");
|
||||
return NULL;
|
||||
fxp_internal_error("did not receive a valid SFTP packet\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
id = get_uint32(pktin);
|
||||
if (get_err(pktin)) {
|
||||
fxp_internal_error("did not receive a valid SFTP packet\n");
|
||||
return NULL;
|
||||
fxp_internal_error("did not receive a valid SFTP packet\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
req = find234(sftp_requests, &id, sftp_reqfind);
|
||||
if (!req || !req->registered) {
|
||||
fxp_internal_error("request ID mismatch\n");
|
||||
return NULL;
|
||||
fxp_internal_error("request ID mismatch\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
del234(sftp_requests, req);
|
||||
|
@ -190,42 +190,42 @@ struct sftp_request *sftp_find_request(struct sftp_packet *pktin)
|
|||
static int fxp_got_status(struct sftp_packet *pktin)
|
||||
{
|
||||
static const char *const messages[] = {
|
||||
/* SSH_FX_OK. The only time we will display a _message_ for this
|
||||
* is if we were expecting something other than FXP_STATUS on
|
||||
* success, so this is actually an error message! */
|
||||
"unexpected OK response",
|
||||
"end of file",
|
||||
"no such file or directory",
|
||||
"permission denied",
|
||||
"failure",
|
||||
"bad message",
|
||||
"no connection",
|
||||
"connection lost",
|
||||
"operation unsupported",
|
||||
/* SSH_FX_OK. The only time we will display a _message_ for this
|
||||
* is if we were expecting something other than FXP_STATUS on
|
||||
* success, so this is actually an error message! */
|
||||
"unexpected OK response",
|
||||
"end of file",
|
||||
"no such file or directory",
|
||||
"permission denied",
|
||||
"failure",
|
||||
"bad message",
|
||||
"no connection",
|
||||
"connection lost",
|
||||
"operation unsupported",
|
||||
};
|
||||
|
||||
if (pktin->type != SSH_FXP_STATUS) {
|
||||
fxp_error_message = "expected FXP_STATUS packet";
|
||||
fxp_errtype = -1;
|
||||
fxp_error_message = "expected FXP_STATUS packet";
|
||||
fxp_errtype = -1;
|
||||
} else {
|
||||
fxp_errtype = get_uint32(pktin);
|
||||
if (get_err(pktin)) {
|
||||
fxp_error_message = "malformed FXP_STATUS packet";
|
||||
fxp_errtype = -1;
|
||||
} else {
|
||||
if (fxp_errtype < 0 || fxp_errtype >= lenof(messages))
|
||||
fxp_error_message = "unknown error code";
|
||||
else
|
||||
fxp_error_message = messages[fxp_errtype];
|
||||
}
|
||||
fxp_errtype = get_uint32(pktin);
|
||||
if (get_err(pktin)) {
|
||||
fxp_error_message = "malformed FXP_STATUS packet";
|
||||
fxp_errtype = -1;
|
||||
} else {
|
||||
if (fxp_errtype < 0 || fxp_errtype >= lenof(messages))
|
||||
fxp_error_message = "unknown error code";
|
||||
else
|
||||
fxp_error_message = messages[fxp_errtype];
|
||||
}
|
||||
}
|
||||
|
||||
if (fxp_errtype == SSH_FX_OK)
|
||||
return 1;
|
||||
return 1;
|
||||
else if (fxp_errtype == SSH_FX_EOF)
|
||||
return 0;
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void fxp_internal_error(const char *msg)
|
||||
|
@ -258,25 +258,25 @@ bool fxp_init(void)
|
|||
|
||||
pktin = sftp_recv();
|
||||
if (!pktin) {
|
||||
fxp_internal_error("could not connect");
|
||||
return false;
|
||||
fxp_internal_error("could not connect");
|
||||
return false;
|
||||
}
|
||||
if (pktin->type != SSH_FXP_VERSION) {
|
||||
fxp_internal_error("did not receive FXP_VERSION");
|
||||
fxp_internal_error("did not receive FXP_VERSION");
|
||||
sftp_pkt_free(pktin);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
remotever = get_uint32(pktin);
|
||||
if (get_err(pktin)) {
|
||||
fxp_internal_error("malformed FXP_VERSION packet");
|
||||
fxp_internal_error("malformed FXP_VERSION packet");
|
||||
sftp_pkt_free(pktin);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
if (remotever > SFTP_PROTO_VERSION) {
|
||||
fxp_internal_error
|
||||
("remote protocol is more advanced than we support");
|
||||
fxp_internal_error
|
||||
("remote protocol is more advanced than we support");
|
||||
sftp_pkt_free(pktin);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* In principle, this packet might also contain extension-
|
||||
|
@ -310,29 +310,29 @@ char *fxp_realpath_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
|||
sfree(req);
|
||||
|
||||
if (pktin->type == SSH_FXP_NAME) {
|
||||
unsigned long count;
|
||||
unsigned long count;
|
||||
char *path;
|
||||
ptrlen name;
|
||||
|
||||
count = get_uint32(pktin);
|
||||
if (get_err(pktin) || count != 1) {
|
||||
fxp_internal_error("REALPATH did not return name count of 1\n");
|
||||
if (get_err(pktin) || count != 1) {
|
||||
fxp_internal_error("REALPATH did not return name count of 1\n");
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
name = get_string(pktin);
|
||||
if (get_err(pktin)) {
|
||||
fxp_internal_error("REALPATH returned malformed FXP_NAME\n");
|
||||
if (get_err(pktin)) {
|
||||
fxp_internal_error("REALPATH returned malformed FXP_NAME\n");
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
path = mkstr(name);
|
||||
sftp_pkt_free(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return path;
|
||||
} else {
|
||||
fxp_got_status(pktin);
|
||||
fxp_got_status(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -374,16 +374,16 @@ static struct fxp_handle *fxp_got_handle(struct sftp_packet *pktin)
|
|||
}
|
||||
|
||||
struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req)
|
||||
struct sftp_request *req)
|
||||
{
|
||||
sfree(req);
|
||||
|
||||
if (pktin->type == SSH_FXP_HANDLE) {
|
||||
return fxp_got_handle(pktin);
|
||||
} else {
|
||||
fxp_got_status(pktin);
|
||||
fxp_got_status(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,15 +404,15 @@ struct sftp_request *fxp_opendir_send(const char *path)
|
|||
}
|
||||
|
||||
struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req)
|
||||
struct sftp_request *req)
|
||||
{
|
||||
sfree(req);
|
||||
if (pktin->type == SSH_FXP_HANDLE) {
|
||||
return fxp_got_handle(pktin);
|
||||
} else {
|
||||
fxp_got_status(pktin);
|
||||
fxp_got_status(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -565,15 +565,15 @@ static bool fxp_got_attrs(struct sftp_packet *pktin, struct fxp_attrs *attrs)
|
|||
}
|
||||
|
||||
bool fxp_stat_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
||||
struct fxp_attrs *attrs)
|
||||
struct fxp_attrs *attrs)
|
||||
{
|
||||
sfree(req);
|
||||
if (pktin->type == SSH_FXP_ATTRS) {
|
||||
return fxp_got_attrs(pktin, attrs);
|
||||
} else {
|
||||
fxp_got_status(pktin);
|
||||
fxp_got_status(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,9 +597,9 @@ bool fxp_fstat_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
|||
if (pktin->type == SSH_FXP_ATTRS) {
|
||||
return fxp_got_attrs(pktin, attrs);
|
||||
} else {
|
||||
fxp_got_status(pktin);
|
||||
fxp_got_status(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -631,7 +631,7 @@ bool fxp_setstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
|||
}
|
||||
|
||||
struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle,
|
||||
struct fxp_attrs attrs)
|
||||
struct fxp_attrs attrs)
|
||||
{
|
||||
struct sftp_request *req = sftp_alloc_request();
|
||||
struct sftp_packet *pktout;
|
||||
|
@ -661,7 +661,7 @@ bool fxp_fsetstat_recv(struct sftp_packet *pktin, struct sftp_request *req)
|
|||
* error indicator. It might even depend on the SFTP server.)
|
||||
*/
|
||||
struct sftp_request *fxp_read_send(struct fxp_handle *handle,
|
||||
uint64_t offset, int len)
|
||||
uint64_t offset, int len)
|
||||
{
|
||||
struct sftp_request *req = sftp_alloc_request();
|
||||
struct sftp_packet *pktout;
|
||||
|
@ -677,32 +677,32 @@ struct sftp_request *fxp_read_send(struct fxp_handle *handle,
|
|||
}
|
||||
|
||||
int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
||||
char *buffer, int len)
|
||||
char *buffer, int len)
|
||||
{
|
||||
sfree(req);
|
||||
if (pktin->type == SSH_FXP_DATA) {
|
||||
ptrlen data;
|
||||
|
||||
data = get_string(pktin);
|
||||
if (get_err(pktin)) {
|
||||
fxp_internal_error("READ returned malformed SSH_FXP_DATA packet");
|
||||
if (get_err(pktin)) {
|
||||
fxp_internal_error("READ returned malformed SSH_FXP_DATA packet");
|
||||
sftp_pkt_free(pktin);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data.len > len) {
|
||||
fxp_internal_error("READ returned more bytes than requested");
|
||||
if (data.len > len) {
|
||||
fxp_internal_error("READ returned more bytes than requested");
|
||||
sftp_pkt_free(pktin);
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(buffer, data.ptr, data.len);
|
||||
memcpy(buffer, data.ptr, data.len);
|
||||
sftp_pkt_free(pktin);
|
||||
return data.len;
|
||||
return data.len;
|
||||
} else {
|
||||
fxp_got_status(pktin);
|
||||
fxp_got_status(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,50 +723,50 @@ struct sftp_request *fxp_readdir_send(struct fxp_handle *handle)
|
|||
}
|
||||
|
||||
struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req)
|
||||
struct sftp_request *req)
|
||||
{
|
||||
sfree(req);
|
||||
if (pktin->type == SSH_FXP_NAME) {
|
||||
struct fxp_names *ret;
|
||||
unsigned long i;
|
||||
struct fxp_names *ret;
|
||||
unsigned long i;
|
||||
|
||||
i = get_uint32(pktin);
|
||||
|
||||
/*
|
||||
* Sanity-check the number of names. Minimum is obviously
|
||||
* zero. Maximum is the remaining space in the packet
|
||||
* divided by the very minimum length of a name, which is
|
||||
* 12 bytes (4 for an empty filename, 4 for an empty
|
||||
* longname, 4 for a set of attribute flags indicating that
|
||||
* no other attributes are supplied).
|
||||
*/
|
||||
if (get_err(pktin) || i > get_avail(pktin) / 12) {
|
||||
fxp_internal_error("malformed FXP_NAME packet");
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Sanity-check the number of names. Minimum is obviously
|
||||
* zero. Maximum is the remaining space in the packet
|
||||
* divided by the very minimum length of a name, which is
|
||||
* 12 bytes (4 for an empty filename, 4 for an empty
|
||||
* longname, 4 for a set of attribute flags indicating that
|
||||
* no other attributes are supplied).
|
||||
*/
|
||||
if (get_err(pktin) || i > get_avail(pktin) / 12) {
|
||||
fxp_internal_error("malformed FXP_NAME packet");
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the implicit multiplication in the snewn() call
|
||||
* doesn't suffer integer overflow and cause us to malloc
|
||||
* too little space.
|
||||
*/
|
||||
if (i > INT_MAX / sizeof(struct fxp_name)) {
|
||||
fxp_internal_error("unreasonably large FXP_NAME packet");
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* Ensure the implicit multiplication in the snewn() call
|
||||
* doesn't suffer integer overflow and cause us to malloc
|
||||
* too little space.
|
||||
*/
|
||||
if (i > INT_MAX / sizeof(struct fxp_name)) {
|
||||
fxp_internal_error("unreasonably large FXP_NAME packet");
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = snew(struct fxp_names);
|
||||
ret->nnames = i;
|
||||
ret->names = snewn(ret->nnames, struct fxp_name);
|
||||
for (i = 0; i < (unsigned long)ret->nnames; i++) {
|
||||
ret->names[i].filename = mkstr(get_string(pktin));
|
||||
ret->names[i].longname = mkstr(get_string(pktin));
|
||||
ret = snew(struct fxp_names);
|
||||
ret->nnames = i;
|
||||
ret->names = snewn(ret->nnames, struct fxp_name);
|
||||
for (i = 0; i < (unsigned long)ret->nnames; i++) {
|
||||
ret->names[i].filename = mkstr(get_string(pktin));
|
||||
ret->names[i].longname = mkstr(get_string(pktin));
|
||||
get_fxp_attrs(pktin, &ret->names[i].attrs);
|
||||
}
|
||||
|
||||
if (get_err(pktin)) {
|
||||
if (get_err(pktin)) {
|
||||
fxp_internal_error("malformed FXP_NAME packet");
|
||||
for (i = 0; i < (unsigned long)ret->nnames; i++) {
|
||||
sfree(ret->names[i].filename);
|
||||
|
@ -776,13 +776,13 @@ struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
|
|||
sfree(ret);
|
||||
sfree(pktin);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
sftp_pkt_free(pktin);
|
||||
return ret;
|
||||
return ret;
|
||||
} else {
|
||||
fxp_got_status(pktin);
|
||||
fxp_got_status(pktin);
|
||||
sftp_pkt_free(pktin);
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -790,7 +790,7 @@ struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
|
|||
* Write to a file. Returns 0 on error, 1 on OK.
|
||||
*/
|
||||
struct sftp_request *fxp_write_send(struct fxp_handle *handle,
|
||||
void *buffer, uint64_t offset, int len)
|
||||
void *buffer, uint64_t offset, int len)
|
||||
{
|
||||
struct sftp_request *req = sftp_alloc_request();
|
||||
struct sftp_packet *pktout;
|
||||
|
@ -821,8 +821,8 @@ void fxp_free_names(struct fxp_names *names)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < names->nnames; i++) {
|
||||
sfree(names->names[i].filename);
|
||||
sfree(names->names[i].longname);
|
||||
sfree(names->names[i].filename);
|
||||
sfree(names->names[i].longname);
|
||||
}
|
||||
sfree(names->names);
|
||||
sfree(names);
|
||||
|
@ -837,7 +837,7 @@ struct fxp_name *fxp_dup_name(struct fxp_name *name)
|
|||
ret = snew(struct fxp_name);
|
||||
ret->filename = dupstr(name->filename);
|
||||
ret->longname = dupstr(name->longname);
|
||||
ret->attrs = name->attrs; /* structure copy */
|
||||
ret->attrs = name->attrs; /* structure copy */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -912,33 +912,33 @@ bool xfer_done(struct fxp_xfer *xfer)
|
|||
void xfer_download_queue(struct fxp_xfer *xfer)
|
||||
{
|
||||
while (xfer->req_totalsize < xfer->req_maxsize &&
|
||||
!xfer->eof && !xfer->err) {
|
||||
/*
|
||||
* Queue a new read request.
|
||||
*/
|
||||
struct req *rr;
|
||||
struct sftp_request *req;
|
||||
!xfer->eof && !xfer->err) {
|
||||
/*
|
||||
* Queue a new read request.
|
||||
*/
|
||||
struct req *rr;
|
||||
struct sftp_request *req;
|
||||
|
||||
rr = snew(struct req);
|
||||
rr->offset = xfer->offset;
|
||||
rr->complete = 0;
|
||||
if (xfer->tail) {
|
||||
xfer->tail->next = rr;
|
||||
rr->prev = xfer->tail;
|
||||
} else {
|
||||
xfer->head = rr;
|
||||
rr->prev = NULL;
|
||||
}
|
||||
xfer->tail = rr;
|
||||
rr->next = NULL;
|
||||
rr = snew(struct req);
|
||||
rr->offset = xfer->offset;
|
||||
rr->complete = 0;
|
||||
if (xfer->tail) {
|
||||
xfer->tail->next = rr;
|
||||
rr->prev = xfer->tail;
|
||||
} else {
|
||||
xfer->head = rr;
|
||||
rr->prev = NULL;
|
||||
}
|
||||
xfer->tail = rr;
|
||||
rr->next = NULL;
|
||||
|
||||
rr->len = 32768;
|
||||
rr->buffer = snewn(rr->len, char);
|
||||
sftp_register(req = fxp_read_send(xfer->fh, rr->offset, rr->len));
|
||||
fxp_set_userdata(req, rr);
|
||||
rr->len = 32768;
|
||||
rr->buffer = snewn(rr->len, char);
|
||||
sftp_register(req = fxp_read_send(xfer->fh, rr->offset, rr->len));
|
||||
fxp_set_userdata(req, rr);
|
||||
|
||||
xfer->offset += rr->len;
|
||||
xfer->req_totalsize += rr->len;
|
||||
xfer->offset += rr->len;
|
||||
xfer->req_totalsize += rr->len;
|
||||
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
printf("queueing read request %p at %"PRIu64"\n", rr, rr->offset);
|
||||
|
@ -971,7 +971,7 @@ int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
|
|||
rr = (struct req *)fxp_get_userdata(rreq);
|
||||
if (!rr) {
|
||||
fxp_internal_error("request ID is not part of the current download");
|
||||
return INT_MIN; /* this packet isn't ours */
|
||||
return INT_MIN; /* this packet isn't ours */
|
||||
}
|
||||
rr->retlen = fxp_read_recv(pktin, rreq, rr->buffer, rr->len);
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
|
@ -979,17 +979,17 @@ int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
|
|||
#endif
|
||||
|
||||
if ((rr->retlen < 0 && fxp_error_type()==SSH_FX_EOF) || rr->retlen == 0) {
|
||||
xfer->eof = true;
|
||||
xfer->eof = true;
|
||||
rr->retlen = 0;
|
||||
rr->complete = -1;
|
||||
rr->complete = -1;
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
printf("setting eof\n");
|
||||
printf("setting eof\n");
|
||||
#endif
|
||||
} else if (rr->retlen < 0) {
|
||||
/* some error other than EOF; signal it back to caller */
|
||||
xfer_set_error(xfer);
|
||||
rr->complete = -1;
|
||||
return -1;
|
||||
/* some error other than EOF; signal it back to caller */
|
||||
xfer_set_error(xfer);
|
||||
rr->complete = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rr->complete = 1;
|
||||
|
@ -1007,31 +1007,31 @@ int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
|
|||
* the first place...
|
||||
*/
|
||||
if (rr->retlen > 0 && xfer->furthestdata < rr->offset) {
|
||||
xfer->furthestdata = rr->offset;
|
||||
xfer->furthestdata = rr->offset;
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
printf("setting furthestdata = %"PRIu64"\n", xfer->furthestdata);
|
||||
printf("setting furthestdata = %"PRIu64"\n", xfer->furthestdata);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rr->retlen < rr->len) {
|
||||
uint64_t filesize = rr->offset + (rr->retlen < 0 ? 0 : rr->retlen);
|
||||
uint64_t filesize = rr->offset + (rr->retlen < 0 ? 0 : rr->retlen);
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
printf("short block! trying filesize = %"PRIu64"\n", filesize);
|
||||
printf("short block! trying filesize = %"PRIu64"\n", filesize);
|
||||
#endif
|
||||
if (xfer->filesize > filesize) {
|
||||
xfer->filesize = filesize;
|
||||
if (xfer->filesize > filesize) {
|
||||
xfer->filesize = filesize;
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
printf("actually changing filesize\n");
|
||||
#endif
|
||||
}
|
||||
printf("actually changing filesize\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (xfer->furthestdata > xfer->filesize) {
|
||||
fxp_error_message = "received a short buffer from FXP_READ, but not"
|
||||
" at EOF";
|
||||
fxp_errtype = -1;
|
||||
xfer_set_error(xfer);
|
||||
return -1;
|
||||
fxp_error_message = "received a short buffer from FXP_READ, but not"
|
||||
" at EOF";
|
||||
fxp_errtype = -1;
|
||||
xfer_set_error(xfer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -1052,35 +1052,35 @@ bool xfer_download_data(struct fxp_xfer *xfer, void **buf, int *len)
|
|||
* 0; return the first thing with complete > 0.
|
||||
*/
|
||||
while (xfer->head && xfer->head->complete && !retbuf) {
|
||||
struct req *rr = xfer->head;
|
||||
struct req *rr = xfer->head;
|
||||
|
||||
if (rr->complete > 0) {
|
||||
retbuf = rr->buffer;
|
||||
retlen = rr->retlen;
|
||||
if (rr->complete > 0) {
|
||||
retbuf = rr->buffer;
|
||||
retlen = rr->retlen;
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
printf("handing back data from read request %p\n", rr);
|
||||
printf("handing back data from read request %p\n", rr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_DOWNLOAD
|
||||
else
|
||||
printf("skipping failed read request %p\n", rr);
|
||||
else
|
||||
printf("skipping failed read request %p\n", rr);
|
||||
#endif
|
||||
|
||||
xfer->head = xfer->head->next;
|
||||
if (xfer->head)
|
||||
xfer->head->prev = NULL;
|
||||
else
|
||||
xfer->tail = NULL;
|
||||
xfer->req_totalsize -= rr->len;
|
||||
sfree(rr);
|
||||
xfer->head = xfer->head->next;
|
||||
if (xfer->head)
|
||||
xfer->head->prev = NULL;
|
||||
else
|
||||
xfer->tail = NULL;
|
||||
xfer->req_totalsize -= rr->len;
|
||||
sfree(rr);
|
||||
}
|
||||
|
||||
if (retbuf) {
|
||||
*buf = retbuf;
|
||||
*len = retlen;
|
||||
return true;
|
||||
*buf = retbuf;
|
||||
*len = retlen;
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct fxp_xfer *xfer_upload_init(struct fxp_handle *fh, uint64_t offset)
|
||||
|
@ -1114,11 +1114,11 @@ void xfer_upload_data(struct fxp_xfer *xfer, char *buffer, int len)
|
|||
rr->offset = xfer->offset;
|
||||
rr->complete = 0;
|
||||
if (xfer->tail) {
|
||||
xfer->tail->next = rr;
|
||||
rr->prev = xfer->tail;
|
||||
xfer->tail->next = rr;
|
||||
rr->prev = xfer->tail;
|
||||
} else {
|
||||
xfer->head = rr;
|
||||
rr->prev = NULL;
|
||||
xfer->head = rr;
|
||||
rr->prev = NULL;
|
||||
}
|
||||
xfer->tail = rr;
|
||||
rr->next = NULL;
|
||||
|
@ -1153,7 +1153,7 @@ int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
|
|||
rr = (struct req *)fxp_get_userdata(rreq);
|
||||
if (!rr) {
|
||||
fxp_internal_error("request ID is not part of the current upload");
|
||||
return INT_MIN; /* this packet isn't ours */
|
||||
return INT_MIN; /* this packet isn't ours */
|
||||
}
|
||||
ret = fxp_write_recv(pktin, rreq);
|
||||
#ifdef DEBUG_UPLOAD
|
||||
|
@ -1166,18 +1166,18 @@ int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin)
|
|||
prev = rr->prev;
|
||||
next = rr->next;
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
prev->next = next;
|
||||
else
|
||||
xfer->head = next;
|
||||
xfer->head = next;
|
||||
if (next)
|
||||
next->prev = prev;
|
||||
next->prev = prev;
|
||||
else
|
||||
xfer->tail = prev;
|
||||
xfer->tail = prev;
|
||||
xfer->req_totalsize -= rr->len;
|
||||
sfree(rr);
|
||||
|
||||
if (!ret)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -1186,10 +1186,10 @@ void xfer_cleanup(struct fxp_xfer *xfer)
|
|||
{
|
||||
struct req *rr;
|
||||
while (xfer->head) {
|
||||
rr = xfer->head;
|
||||
xfer->head = xfer->head->next;
|
||||
sfree(rr->buffer);
|
||||
sfree(rr);
|
||||
rr = xfer->head;
|
||||
xfer->head = xfer->head->next;
|
||||
sfree(rr->buffer);
|
||||
sfree(rr);
|
||||
}
|
||||
sfree(xfer);
|
||||
}
|
||||
|
|
66
sftp.h
66
sftp.h
|
@ -4,31 +4,31 @@
|
|||
|
||||
#include "defs.h"
|
||||
|
||||
#define SSH_FXP_INIT 1 /* 0x1 */
|
||||
#define SSH_FXP_VERSION 2 /* 0x2 */
|
||||
#define SSH_FXP_OPEN 3 /* 0x3 */
|
||||
#define SSH_FXP_CLOSE 4 /* 0x4 */
|
||||
#define SSH_FXP_READ 5 /* 0x5 */
|
||||
#define SSH_FXP_WRITE 6 /* 0x6 */
|
||||
#define SSH_FXP_LSTAT 7 /* 0x7 */
|
||||
#define SSH_FXP_FSTAT 8 /* 0x8 */
|
||||
#define SSH_FXP_SETSTAT 9 /* 0x9 */
|
||||
#define SSH_FXP_FSETSTAT 10 /* 0xa */
|
||||
#define SSH_FXP_OPENDIR 11 /* 0xb */
|
||||
#define SSH_FXP_READDIR 12 /* 0xc */
|
||||
#define SSH_FXP_REMOVE 13 /* 0xd */
|
||||
#define SSH_FXP_MKDIR 14 /* 0xe */
|
||||
#define SSH_FXP_RMDIR 15 /* 0xf */
|
||||
#define SSH_FXP_REALPATH 16 /* 0x10 */
|
||||
#define SSH_FXP_STAT 17 /* 0x11 */
|
||||
#define SSH_FXP_RENAME 18 /* 0x12 */
|
||||
#define SSH_FXP_STATUS 101 /* 0x65 */
|
||||
#define SSH_FXP_HANDLE 102 /* 0x66 */
|
||||
#define SSH_FXP_DATA 103 /* 0x67 */
|
||||
#define SSH_FXP_NAME 104 /* 0x68 */
|
||||
#define SSH_FXP_ATTRS 105 /* 0x69 */
|
||||
#define SSH_FXP_EXTENDED 200 /* 0xc8 */
|
||||
#define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */
|
||||
#define SSH_FXP_INIT 1 /* 0x1 */
|
||||
#define SSH_FXP_VERSION 2 /* 0x2 */
|
||||
#define SSH_FXP_OPEN 3 /* 0x3 */
|
||||
#define SSH_FXP_CLOSE 4 /* 0x4 */
|
||||
#define SSH_FXP_READ 5 /* 0x5 */
|
||||
#define SSH_FXP_WRITE 6 /* 0x6 */
|
||||
#define SSH_FXP_LSTAT 7 /* 0x7 */
|
||||
#define SSH_FXP_FSTAT 8 /* 0x8 */
|
||||
#define SSH_FXP_SETSTAT 9 /* 0x9 */
|
||||
#define SSH_FXP_FSETSTAT 10 /* 0xa */
|
||||
#define SSH_FXP_OPENDIR 11 /* 0xb */
|
||||
#define SSH_FXP_READDIR 12 /* 0xc */
|
||||
#define SSH_FXP_REMOVE 13 /* 0xd */
|
||||
#define SSH_FXP_MKDIR 14 /* 0xe */
|
||||
#define SSH_FXP_RMDIR 15 /* 0xf */
|
||||
#define SSH_FXP_REALPATH 16 /* 0x10 */
|
||||
#define SSH_FXP_STAT 17 /* 0x11 */
|
||||
#define SSH_FXP_RENAME 18 /* 0x12 */
|
||||
#define SSH_FXP_STATUS 101 /* 0x65 */
|
||||
#define SSH_FXP_HANDLE 102 /* 0x66 */
|
||||
#define SSH_FXP_DATA 103 /* 0x67 */
|
||||
#define SSH_FXP_NAME 104 /* 0x68 */
|
||||
#define SSH_FXP_ATTRS 105 /* 0x69 */
|
||||
#define SSH_FXP_EXTENDED 200 /* 0xc8 */
|
||||
#define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */
|
||||
|
||||
#define SSH_FX_OK 0
|
||||
#define SSH_FX_EOF 1
|
||||
|
@ -60,11 +60,11 @@
|
|||
/*
|
||||
* External references. The sftp client module sftp.c expects to be
|
||||
* able to get at these functions.
|
||||
*
|
||||
*
|
||||
* sftp_recvdata must never return less than len. It either blocks
|
||||
* until len is available and then returns true, or it returns false
|
||||
* for failure.
|
||||
*
|
||||
*
|
||||
* sftp_senddata returns true on success, false on failure.
|
||||
*
|
||||
* sftp_sendbuffer returns the size of the backlog of data in the
|
||||
|
@ -182,14 +182,14 @@ char *fxp_realpath_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
|||
struct sftp_request *fxp_open_send(const char *path, int type,
|
||||
const struct fxp_attrs *attrs);
|
||||
struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req);
|
||||
struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Open a directory.
|
||||
*/
|
||||
struct sftp_request *fxp_opendir_send(const char *path);
|
||||
struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req);
|
||||
struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Close a file/dir. Returns true on success, false on error.
|
||||
|
@ -240,14 +240,14 @@ struct sftp_request *fxp_setstat_send(const char *fname,
|
|||
struct fxp_attrs attrs);
|
||||
bool fxp_setstat_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle,
|
||||
struct fxp_attrs attrs);
|
||||
struct fxp_attrs attrs);
|
||||
bool fxp_fsetstat_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Read from a file.
|
||||
*/
|
||||
struct sftp_request *fxp_read_send(struct fxp_handle *handle,
|
||||
uint64_t offset, int len);
|
||||
uint64_t offset, int len);
|
||||
int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
||||
char *buffer, int len);
|
||||
|
||||
|
@ -255,7 +255,7 @@ int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
|||
* Write to a file.
|
||||
*/
|
||||
struct sftp_request *fxp_write_send(struct fxp_handle *handle,
|
||||
void *buffer, uint64_t offset, int len);
|
||||
void *buffer, uint64_t offset, int len);
|
||||
bool fxp_write_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
|
@ -263,7 +263,7 @@ bool fxp_write_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
|||
*/
|
||||
struct sftp_request *fxp_readdir_send(struct fxp_handle *handle);
|
||||
struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req);
|
||||
struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Free up an fxp_names structure.
|
||||
|
|
62
sftpcommon.c
62
sftpcommon.c
|
@ -42,23 +42,23 @@ void BinarySink_put_fxp_attrs(BinarySink *bs, struct fxp_attrs attrs)
|
|||
{
|
||||
put_uint32(bs, attrs.flags);
|
||||
if (attrs.flags & SSH_FILEXFER_ATTR_SIZE)
|
||||
put_uint64(bs, attrs.size);
|
||||
put_uint64(bs, attrs.size);
|
||||
if (attrs.flags & SSH_FILEXFER_ATTR_UIDGID) {
|
||||
put_uint32(bs, attrs.uid);
|
||||
put_uint32(bs, attrs.gid);
|
||||
put_uint32(bs, attrs.uid);
|
||||
put_uint32(bs, attrs.gid);
|
||||
}
|
||||
if (attrs.flags & SSH_FILEXFER_ATTR_PERMISSIONS) {
|
||||
put_uint32(bs, attrs.permissions);
|
||||
put_uint32(bs, attrs.permissions);
|
||||
}
|
||||
if (attrs.flags & SSH_FILEXFER_ATTR_ACMODTIME) {
|
||||
put_uint32(bs, attrs.atime);
|
||||
put_uint32(bs, attrs.mtime);
|
||||
put_uint32(bs, attrs.atime);
|
||||
put_uint32(bs, attrs.mtime);
|
||||
}
|
||||
if (attrs.flags & SSH_FILEXFER_ATTR_EXTENDED) {
|
||||
/*
|
||||
* We currently don't support sending any extended
|
||||
* attributes.
|
||||
*/
|
||||
/*
|
||||
* We currently don't support sending any extended
|
||||
* attributes.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,31 +73,31 @@ bool BinarySource_get_fxp_attrs(BinarySource *src, struct fxp_attrs *attrs)
|
|||
if (attrs->flags & SSH_FILEXFER_ATTR_SIZE)
|
||||
attrs->size = get_uint64(src);
|
||||
if (attrs->flags & SSH_FILEXFER_ATTR_UIDGID) {
|
||||
attrs->uid = get_uint32(src);
|
||||
attrs->gid = get_uint32(src);
|
||||
attrs->uid = get_uint32(src);
|
||||
attrs->gid = get_uint32(src);
|
||||
}
|
||||
if (attrs->flags & SSH_FILEXFER_ATTR_PERMISSIONS)
|
||||
attrs->permissions = get_uint32(src);
|
||||
attrs->permissions = get_uint32(src);
|
||||
if (attrs->flags & SSH_FILEXFER_ATTR_ACMODTIME) {
|
||||
attrs->atime = get_uint32(src);
|
||||
attrs->mtime = get_uint32(src);
|
||||
attrs->atime = get_uint32(src);
|
||||
attrs->mtime = get_uint32(src);
|
||||
}
|
||||
if (attrs->flags & SSH_FILEXFER_ATTR_EXTENDED) {
|
||||
unsigned long count = get_uint32(src);
|
||||
while (count--) {
|
||||
if (get_err(src)) {
|
||||
/* Truncated packet. Don't waste time looking for
|
||||
* attributes that aren't there. Caller should spot
|
||||
* the truncation. */
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We should try to analyse these, if we ever find one
|
||||
* we recognise.
|
||||
*/
|
||||
get_string(src);
|
||||
get_string(src);
|
||||
}
|
||||
unsigned long count = get_uint32(src);
|
||||
while (count--) {
|
||||
if (get_err(src)) {
|
||||
/* Truncated packet. Don't waste time looking for
|
||||
* attributes that aren't there. Caller should spot
|
||||
* the truncation. */
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* We should try to analyse these, if we ever find one
|
||||
* we recognise.
|
||||
*/
|
||||
get_string(src);
|
||||
get_string(src);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ bool BinarySource_get_fxp_attrs(BinarySource *src, struct fxp_attrs *attrs)
|
|||
void sftp_pkt_free(struct sftp_packet *pkt)
|
||||
{
|
||||
if (pkt->data)
|
||||
sfree(pkt->data);
|
||||
sfree(pkt->data);
|
||||
sfree(pkt);
|
||||
}
|
||||
|
||||
|
|
2
sign.sh
2
sign.sh
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
# Generate GPG signatures on a PuTTY release/snapshot directory as
|
||||
# delivered by Buildscr.
|
||||
|
|
88
ssh.c
88
ssh.c
|
@ -22,11 +22,11 @@
|
|||
#ifndef NO_GSSAPI
|
||||
#include "sshgssc.h"
|
||||
#include "sshgss.h"
|
||||
#define MIN_CTXT_LIFETIME 5 /* Avoid rekey with short lifetime (seconds) */
|
||||
#define GSS_KEX_CAPABLE (1<<0) /* Can do GSS KEX */
|
||||
#define MIN_CTXT_LIFETIME 5 /* Avoid rekey with short lifetime (seconds) */
|
||||
#define GSS_KEX_CAPABLE (1<<0) /* Can do GSS KEX */
|
||||
#define GSS_CRED_UPDATED (1<<1) /* Cred updated since previous delegation */
|
||||
#define GSS_CTXT_EXPIRES (1<<2) /* Context expires before next timer */
|
||||
#define GSS_CTXT_MAYFAIL (1<<3) /* Context may expire during handshake */
|
||||
#define GSS_CTXT_EXPIRES (1<<2) /* Context expires before next timer */
|
||||
#define GSS_CTXT_MAYFAIL (1<<3) /* Context may expire during handshake */
|
||||
#endif
|
||||
|
||||
struct Ssh {
|
||||
|
@ -240,7 +240,7 @@ static void ssh_got_ssh_version(struct ssh_version_receiver *rcv,
|
|||
#endif
|
||||
|
||||
connection_layer = ssh2_connection_new(
|
||||
ssh, ssh->connshare, is_simple, ssh->conf,
|
||||
ssh, ssh->connshare, is_simple, ssh->conf,
|
||||
ssh_verstring_get_remote(old_bpp), &ssh->cl);
|
||||
ssh_connect_ppl(ssh, connection_layer);
|
||||
|
||||
|
@ -596,7 +596,7 @@ static void ssh_socket_log(Plug *plug, int type, SockAddr *addr, int port,
|
|||
}
|
||||
|
||||
static void ssh_closing(Plug *plug, const char *error_msg, int error_code,
|
||||
bool calling_back)
|
||||
bool calling_back)
|
||||
{
|
||||
Ssh *ssh = container_of(plug, Ssh, plug);
|
||||
if (error_msg) {
|
||||
|
@ -613,8 +613,8 @@ static void ssh_receive(Plug *plug, int urgent, const char *data, size_t len)
|
|||
|
||||
/* Log raw data, if we're in that mode. */
|
||||
if (ssh->logctx)
|
||||
log_packet(ssh->logctx, PKT_INCOMING, -1, NULL, data, len,
|
||||
0, NULL, NULL, 0, NULL);
|
||||
log_packet(ssh->logctx, PKT_INCOMING, -1, NULL, data, len,
|
||||
0, NULL, NULL, 0, NULL);
|
||||
|
||||
bufchain_add(&ssh->in_raw, data, len);
|
||||
if (!ssh->logically_frozen && ssh->bpp)
|
||||
|
@ -633,7 +633,7 @@ static void ssh_sent(Plug *plug, size_t bufsize)
|
|||
* some more data off its bufchain.
|
||||
*/
|
||||
if (bufsize < SSH_MAX_BACKLOG) {
|
||||
ssh_throttle_all(ssh, false, bufsize);
|
||||
ssh_throttle_all(ssh, false, bufsize);
|
||||
queue_idempotent_callback(&ssh->ic_out_raw);
|
||||
}
|
||||
}
|
||||
|
@ -647,31 +647,31 @@ static void ssh_hostport_setup(const char *host, int port, Conf *conf,
|
|||
*loghost_ret = loghost;
|
||||
|
||||
if (*loghost) {
|
||||
char *tmphost;
|
||||
char *tmphost;
|
||||
char *colon;
|
||||
|
||||
tmphost = dupstr(loghost);
|
||||
*savedport = 22; /* default ssh port */
|
||||
*savedport = 22; /* default ssh port */
|
||||
|
||||
/*
|
||||
* A colon suffix on the hostname string also lets us affect
|
||||
* savedport. (Unless there are multiple colons, in which case
|
||||
* we assume this is an unbracketed IPv6 literal.)
|
||||
*/
|
||||
colon = host_strrchr(tmphost, ':');
|
||||
if (colon && colon == host_strchr(tmphost, ':')) {
|
||||
*colon++ = '\0';
|
||||
if (*colon)
|
||||
*savedport = atoi(colon);
|
||||
}
|
||||
/*
|
||||
* A colon suffix on the hostname string also lets us affect
|
||||
* savedport. (Unless there are multiple colons, in which case
|
||||
* we assume this is an unbracketed IPv6 literal.)
|
||||
*/
|
||||
colon = host_strrchr(tmphost, ':');
|
||||
if (colon && colon == host_strchr(tmphost, ':')) {
|
||||
*colon++ = '\0';
|
||||
if (*colon)
|
||||
*savedport = atoi(colon);
|
||||
}
|
||||
|
||||
*savedhost = host_strduptrim(tmphost);
|
||||
sfree(tmphost);
|
||||
} else {
|
||||
*savedhost = host_strduptrim(host);
|
||||
if (port < 0)
|
||||
port = 22; /* default ssh port */
|
||||
*savedport = port;
|
||||
*savedhost = host_strduptrim(host);
|
||||
if (port < 0)
|
||||
port = 22; /* default ssh port */
|
||||
*savedport = port;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -786,11 +786,11 @@ static const char *connect_to_host(
|
|||
sshprot = conf_get_int(ssh->conf, CONF_sshprot);
|
||||
assert(sshprot == 0 || sshprot == 3);
|
||||
if (sshprot == 0)
|
||||
/* SSH-1 only */
|
||||
ssh->version = 1;
|
||||
/* SSH-1 only */
|
||||
ssh->version = 1;
|
||||
if (sshprot == 3 || ssh->bare_connection) {
|
||||
/* SSH-2 only */
|
||||
ssh->version = 2;
|
||||
/* SSH-2 only */
|
||||
ssh->version = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -810,8 +810,8 @@ static const char *connect_to_host(
|
|||
* loghost, if configured, overrides realhost.
|
||||
*/
|
||||
if (*loghost) {
|
||||
sfree(*realhost);
|
||||
*realhost = dupstr(loghost);
|
||||
sfree(*realhost);
|
||||
*realhost = dupstr(loghost);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -847,7 +847,7 @@ void ssh_throttle_conn(Ssh *ssh, int adjust)
|
|||
static void ssh_throttle_all(Ssh *ssh, bool enable, size_t bufsize)
|
||||
{
|
||||
if (enable == ssh->throttled_all)
|
||||
return;
|
||||
return;
|
||||
ssh->throttled_all = enable;
|
||||
ssh->overall_bufsize = bufsize;
|
||||
|
||||
|
@ -868,7 +868,7 @@ static void ssh_cache_conf_values(Ssh *ssh)
|
|||
static const char *ssh_init(Seat *seat, Backend **backend_handle,
|
||||
LogContext *logctx, Conf *conf,
|
||||
const char *host, int port, char **realhost,
|
||||
bool nodelay, bool keepalive)
|
||||
bool nodelay, bool keepalive)
|
||||
{
|
||||
const char *p;
|
||||
Ssh *ssh;
|
||||
|
@ -907,7 +907,7 @@ static const char *ssh_init(Seat *seat, Backend **backend_handle,
|
|||
* the random seed won't be re-saved. */
|
||||
ssh->need_random_unref = false;
|
||||
random_unref();
|
||||
return p;
|
||||
return p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -929,13 +929,13 @@ static void ssh_free(Backend *be)
|
|||
|
||||
#ifndef NO_GSSAPI
|
||||
if (ssh->gss_state.srv_name)
|
||||
ssh->gss_state.lib->release_name(
|
||||
ssh->gss_state.lib->release_name(
|
||||
ssh->gss_state.lib, &ssh->gss_state.srv_name);
|
||||
if (ssh->gss_state.ctx != NULL)
|
||||
ssh->gss_state.lib->release_cred(
|
||||
ssh->gss_state.lib, &ssh->gss_state.ctx);
|
||||
if (ssh->gss_state.libs)
|
||||
ssh_gss_cleanup(ssh->gss_state.libs);
|
||||
ssh_gss_cleanup(ssh->gss_state.libs);
|
||||
#endif
|
||||
|
||||
sfree(ssh->deferred_abort_message);
|
||||
|
@ -974,7 +974,7 @@ static size_t ssh_send(Backend *be, const char *buf, size_t len)
|
|||
Ssh *ssh = container_of(be, Ssh, backend);
|
||||
|
||||
if (ssh == NULL || ssh->s == NULL)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
bufchain_add(&ssh->user_input, buf, len);
|
||||
if (ssh->base_layer)
|
||||
|
@ -992,7 +992,7 @@ static size_t ssh_sendbuffer(Backend *be)
|
|||
size_t backlog;
|
||||
|
||||
if (!ssh || !ssh->s || !ssh->cl)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
backlog = ssh_stdin_backlog(ssh->cl);
|
||||
|
||||
|
@ -1003,7 +1003,7 @@ static size_t ssh_sendbuffer(Backend *be)
|
|||
* size on that to any individual buffer on the stdin channel.
|
||||
*/
|
||||
if (ssh->throttled_all)
|
||||
backlog += ssh->overall_bufsize;
|
||||
backlog += ssh->overall_bufsize;
|
||||
|
||||
return backlog;
|
||||
}
|
||||
|
@ -1110,7 +1110,7 @@ void ssh_ldisc_update(Ssh *ssh)
|
|||
/* Called when the connection layer wants to propagate an update
|
||||
* to the line discipline options */
|
||||
if (ssh->ldisc)
|
||||
ldisc_echoedit_update(ssh->ldisc);
|
||||
ldisc_echoedit_update(ssh->ldisc);
|
||||
}
|
||||
|
||||
static bool ssh_ldisc(Backend *be, int option)
|
||||
|
@ -1148,11 +1148,11 @@ static int ssh_cfg_info(Backend *be)
|
|||
{
|
||||
Ssh *ssh = container_of(be, Ssh, backend);
|
||||
if (ssh->version == 0)
|
||||
return 0; /* don't know yet */
|
||||
return 0; /* don't know yet */
|
||||
else if (ssh->bare_connection)
|
||||
return -1;
|
||||
return -1;
|
||||
else
|
||||
return ssh->version;
|
||||
return ssh->version;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
76
ssh.h
76
ssh.h
|
@ -624,7 +624,7 @@ struct ssh_cipheralg {
|
|||
* different. */
|
||||
int padded_keybytes;
|
||||
unsigned int flags;
|
||||
#define SSH_CIPHER_IS_CBC 1
|
||||
#define SSH_CIPHER_IS_CBC 1
|
||||
#define SSH_CIPHER_SEPARATE_LENGTH 2
|
||||
const char *text_name;
|
||||
/* If set, this takes priority over other MAC. */
|
||||
|
@ -879,7 +879,7 @@ static inline const ssh_compression_alg *ssh_decompressor_alg(
|
|||
|
||||
struct ssh2_userkey {
|
||||
ssh_key *key; /* the key itself */
|
||||
char *comment; /* the key comment */
|
||||
char *comment; /* the key comment */
|
||||
};
|
||||
|
||||
/* The maximum length of any hash algorithm. (bytes) */
|
||||
|
@ -965,7 +965,7 @@ bool platform_sha256_hw_available(void);
|
|||
bool platform_sha1_hw_available(void);
|
||||
|
||||
/*
|
||||
* PuTTY version number formatted as an SSH version string.
|
||||
* PuTTY version number formatted as an SSH version string.
|
||||
*/
|
||||
extern const char sshver[];
|
||||
|
||||
|
@ -1105,7 +1105,7 @@ char *platform_get_x_display(void);
|
|||
* calling this function to do the rest of the work.
|
||||
*/
|
||||
void x11_get_auth_from_authfile(struct X11Display *display,
|
||||
const char *authfilename);
|
||||
const char *authfilename);
|
||||
void x11_format_auth_for_authfile(
|
||||
BinarySink *bs, SockAddr *addr, int display_no,
|
||||
ptrlen authproto, ptrlen authdata);
|
||||
|
@ -1217,7 +1217,7 @@ bool import_possible(int type);
|
|||
int import_target_type(int type);
|
||||
bool import_encrypted(const Filename *filename, int type, char **comment);
|
||||
int import_ssh1(const Filename *filename, int type,
|
||||
RSAKey *key, char *passphrase, const char **errmsg_p);
|
||||
RSAKey *key, char *passphrase, const char **errmsg_p);
|
||||
ssh2_userkey *import_ssh2(const Filename *filename, int type,
|
||||
char *passphrase, const char **errmsg_p);
|
||||
bool export_ssh1(const Filename *filename, int type,
|
||||
|
@ -1228,9 +1228,9 @@ bool export_ssh2(const Filename *filename, int type,
|
|||
void des3_decrypt_pubkey(const void *key, void *blk, int len);
|
||||
void des3_encrypt_pubkey(const void *key, void *blk, int len);
|
||||
void des3_decrypt_pubkey_ossh(const void *key, const void *iv,
|
||||
void *blk, int len);
|
||||
void *blk, int len);
|
||||
void des3_encrypt_pubkey_ossh(const void *key, const void *iv,
|
||||
void *blk, int len);
|
||||
void *blk, int len);
|
||||
void aes256_encrypt_pubkey(const void *key, void *blk, int len);
|
||||
void aes256_decrypt_pubkey(const void *key, void *blk, int len);
|
||||
|
||||
|
@ -1253,9 +1253,9 @@ void openssh_bcrypt(const char *passphrase,
|
|||
typedef void (*progfn_t) (void *param, int action, int phase, int progress);
|
||||
|
||||
int rsa_generate(RSAKey *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
void *pfnparam);
|
||||
int dsa_generate(struct dss_key *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
void *pfnparam);
|
||||
int ecdsa_generate(struct ecdsa_key *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
int eddsa_generate(struct eddsa_key *key, int bits, progfn_t pfn,
|
||||
|
@ -1328,16 +1328,16 @@ void platform_ssh_share_cleanup(const char *name);
|
|||
X(y, SSH1_CMSG_AUTH_CCARD_RESPONSE, 72) \
|
||||
/* end of list */
|
||||
|
||||
#define SSH1_AUTH_RHOSTS 1 /* 0x1 */
|
||||
#define SSH1_AUTH_RSA 2 /* 0x2 */
|
||||
#define SSH1_AUTH_PASSWORD 3 /* 0x3 */
|
||||
#define SSH1_AUTH_RHOSTS_RSA 4 /* 0x4 */
|
||||
#define SSH1_AUTH_TIS 5 /* 0x5 */
|
||||
#define SSH1_AUTH_CCARD 16 /* 0x10 */
|
||||
#define SSH1_AUTH_RHOSTS 1 /* 0x1 */
|
||||
#define SSH1_AUTH_RSA 2 /* 0x2 */
|
||||
#define SSH1_AUTH_PASSWORD 3 /* 0x3 */
|
||||
#define SSH1_AUTH_RHOSTS_RSA 4 /* 0x4 */
|
||||
#define SSH1_AUTH_TIS 5 /* 0x5 */
|
||||
#define SSH1_AUTH_CCARD 16 /* 0x10 */
|
||||
|
||||
#define SSH1_PROTOFLAG_SCREEN_NUMBER 1 /* 0x1 */
|
||||
#define SSH1_PROTOFLAG_SCREEN_NUMBER 1 /* 0x1 */
|
||||
/* Mask for protoflags we will echo back to server if seen */
|
||||
#define SSH1_PROTOFLAGS_SUPPORTED 0 /* 0x1 */
|
||||
#define SSH1_PROTOFLAGS_SUPPORTED 0 /* 0x1 */
|
||||
|
||||
/*
|
||||
* List macro defining SSH-2 message type codes. Some of these depend
|
||||
|
@ -1423,7 +1423,7 @@ enum {
|
|||
#define SSH1_AGENT_RSA_RESPONSE 4
|
||||
#define SSH1_AGENTC_ADD_RSA_IDENTITY 7
|
||||
#define SSH1_AGENTC_REMOVE_RSA_IDENTITY 8
|
||||
#define SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* openssh private? */
|
||||
#define SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* openssh private? */
|
||||
|
||||
/*
|
||||
* Messages common to SSH-1 and OpenSSH's SSH-2.
|
||||
|
@ -1445,28 +1445,28 @@ enum {
|
|||
/*
|
||||
* Assorted other SSH-related enumerations.
|
||||
*/
|
||||
#define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 /* 0x1 */
|
||||
#define SSH2_DISCONNECT_PROTOCOL_ERROR 2 /* 0x2 */
|
||||
#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 /* 0x3 */
|
||||
#define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 /* 0x4 */
|
||||
#define SSH2_DISCONNECT_MAC_ERROR 5 /* 0x5 */
|
||||
#define SSH2_DISCONNECT_COMPRESSION_ERROR 6 /* 0x6 */
|
||||
#define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 /* 0x7 */
|
||||
#define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 /* 0x8 */
|
||||
#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 /* 0x9 */
|
||||
#define SSH2_DISCONNECT_CONNECTION_LOST 10 /* 0xa */
|
||||
#define SSH2_DISCONNECT_BY_APPLICATION 11 /* 0xb */
|
||||
#define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 /* 0xc */
|
||||
#define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 /* 0xd */
|
||||
#define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 /* 0xe */
|
||||
#define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 /* 0xf */
|
||||
#define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 /* 0x1 */
|
||||
#define SSH2_DISCONNECT_PROTOCOL_ERROR 2 /* 0x2 */
|
||||
#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3 /* 0x3 */
|
||||
#define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4 /* 0x4 */
|
||||
#define SSH2_DISCONNECT_MAC_ERROR 5 /* 0x5 */
|
||||
#define SSH2_DISCONNECT_COMPRESSION_ERROR 6 /* 0x6 */
|
||||
#define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7 /* 0x7 */
|
||||
#define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8 /* 0x8 */
|
||||
#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9 /* 0x9 */
|
||||
#define SSH2_DISCONNECT_CONNECTION_LOST 10 /* 0xa */
|
||||
#define SSH2_DISCONNECT_BY_APPLICATION 11 /* 0xb */
|
||||
#define SSH2_DISCONNECT_TOO_MANY_CONNECTIONS 12 /* 0xc */
|
||||
#define SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER 13 /* 0xd */
|
||||
#define SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE 14 /* 0xe */
|
||||
#define SSH2_DISCONNECT_ILLEGAL_USER_NAME 15 /* 0xf */
|
||||
|
||||
#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 /* 0x1 */
|
||||
#define SSH2_OPEN_CONNECT_FAILED 2 /* 0x2 */
|
||||
#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 /* 0x3 */
|
||||
#define SSH2_OPEN_RESOURCE_SHORTAGE 4 /* 0x4 */
|
||||
#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1 /* 0x1 */
|
||||
#define SSH2_OPEN_CONNECT_FAILED 2 /* 0x2 */
|
||||
#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3 /* 0x3 */
|
||||
#define SSH2_OPEN_RESOURCE_SHORTAGE 4 /* 0x4 */
|
||||
|
||||
#define SSH2_EXTENDED_DATA_STDERR 1 /* 0x1 */
|
||||
#define SSH2_EXTENDED_DATA_STDERR 1 /* 0x1 */
|
||||
|
||||
enum {
|
||||
/* TTY modes with opcodes defined consistently in the SSH specs. */
|
||||
|
|
|
@ -286,7 +286,7 @@ static void ssh1_bpp_handle_input(BinaryPacketProtocol *bpp)
|
|||
static PktOut *ssh1_bpp_new_pktout(int pkt_type)
|
||||
{
|
||||
PktOut *pkt = ssh_new_packet();
|
||||
pkt->length = 4 + 8; /* space for length + max padding */
|
||||
pkt->length = 4 + 8; /* space for length + max padding */
|
||||
put_byte(pkt, pkt_type);
|
||||
pkt->prefix = pkt->length;
|
||||
pkt->type = pkt_type;
|
||||
|
|
|
@ -468,16 +468,16 @@ static void ssh1_rportfwd_response(struct ssh1_connection_state *s,
|
|||
struct ssh_rportfwd *rpf = (struct ssh_rportfwd *)ctx;
|
||||
|
||||
if (success) {
|
||||
ppl_logevent("Remote port forwarding from %s enabled",
|
||||
ppl_logevent("Remote port forwarding from %s enabled",
|
||||
rpf->log_description);
|
||||
} else {
|
||||
ppl_logevent("Remote port forwarding from %s refused",
|
||||
ppl_logevent("Remote port forwarding from %s refused",
|
||||
rpf->log_description);
|
||||
|
||||
struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
|
||||
assert(realpf == rpf);
|
||||
struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
|
||||
assert(realpf == rpf);
|
||||
portfwdmgr_close(s->portfwdmgr, rpf->pfr);
|
||||
free_rportfwd(rpf);
|
||||
free_rportfwd(rpf);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,15 +19,15 @@ static int ssh1_rportfwd_cmp(void *av, void *bv)
|
|||
struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;
|
||||
int i;
|
||||
if ( (i = strcmp(a->dhost, b->dhost)) != 0)
|
||||
return i < 0 ? -1 : +1;
|
||||
return i < 0 ? -1 : +1;
|
||||
if (a->dport > b->dport)
|
||||
return +1;
|
||||
return +1;
|
||||
if (a->dport < b->dport)
|
||||
return -1;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ssh1_connection_free(PacketProtocolLayer *);
|
||||
static void ssh1_connection_free(PacketProtocolLayer *);
|
||||
static void ssh1_connection_process_queue(PacketProtocolLayer *);
|
||||
static void ssh1_connection_special_cmd(PacketProtocolLayer *ppl,
|
||||
SessionSpecialCode code, int arg);
|
||||
|
@ -134,9 +134,9 @@ static int ssh1_channelcmp(void *av, void *bv)
|
|||
const struct ssh1_channel *a = (const struct ssh1_channel *) av;
|
||||
const struct ssh1_channel *b = (const struct ssh1_channel *) bv;
|
||||
if (a->localid < b->localid)
|
||||
return -1;
|
||||
return -1;
|
||||
if (a->localid > b->localid)
|
||||
return +1;
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -145,9 +145,9 @@ static int ssh1_channelfind(void *av, void *bv)
|
|||
const unsigned *a = (const unsigned *) av;
|
||||
const struct ssh1_channel *b = (const struct ssh1_channel *) bv;
|
||||
if (*a < b->localid)
|
||||
return -1;
|
||||
return -1;
|
||||
if (*a > b->localid)
|
||||
return +1;
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ static void ssh1_connection_free(PacketProtocolLayer *ppl)
|
|||
chan_free(s->mainchan_chan);
|
||||
|
||||
if (s->x11disp)
|
||||
x11_free_display(s->x11disp);
|
||||
x11_free_display(s->x11disp);
|
||||
while ((auth = delpos234(s->x11authtree, 0)) != NULL)
|
||||
x11_free_fake_auth(auth);
|
||||
freetree234(s->x11authtree);
|
||||
|
@ -270,7 +270,7 @@ static bool ssh1_connection_filter_queue(struct ssh1_connection_state *s)
|
|||
localid);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
switch (pktin->type) {
|
||||
case SSH1_MSG_CHANNEL_OPEN_CONFIRMATION:
|
||||
assert(c->halfopen);
|
||||
|
@ -427,19 +427,19 @@ static void ssh1_connection_process_queue(PacketProtocolLayer *ppl)
|
|||
|
||||
while (1) {
|
||||
|
||||
/*
|
||||
* By this point, most incoming packets are already being
|
||||
* handled by filter_queue, and we need only pay attention to
|
||||
* the unusual ones.
|
||||
*/
|
||||
/*
|
||||
* By this point, most incoming packets are already being
|
||||
* handled by filter_queue, and we need only pay attention to
|
||||
* the unusual ones.
|
||||
*/
|
||||
|
||||
if ((pktin = ssh1_connection_pop(s)) != NULL) {
|
||||
if ((pktin = ssh1_connection_pop(s)) != NULL) {
|
||||
ssh_proto_error(s->ppl.ssh, "Unexpected packet received, "
|
||||
"type %d (%s)", pktin->type,
|
||||
ssh1_pkt_type(pktin->type));
|
||||
return;
|
||||
}
|
||||
crReturnV;
|
||||
}
|
||||
crReturnV;
|
||||
}
|
||||
|
||||
crFinishV;
|
||||
|
@ -462,7 +462,7 @@ static void ssh1_channel_check_close(struct ssh1_channel *c)
|
|||
if ((!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes) ||
|
||||
chan_want_close(c->chan, (c->closes & CLOSES_SENT_CLOSE),
|
||||
(c->closes & CLOSES_RCVD_CLOSE))) &&
|
||||
!(c->closes & CLOSES_SENT_CLOSECONF)) {
|
||||
!(c->closes & CLOSES_SENT_CLOSECONF)) {
|
||||
/*
|
||||
* We have both sent and received CLOSE (or the channel type
|
||||
* doesn't need us to), which means the channel is in final
|
||||
|
@ -625,8 +625,8 @@ static void ssh1channel_unthrottle(SshChannel *sc, size_t bufsize)
|
|||
struct ssh1_connection_state *s = c->connlayer;
|
||||
|
||||
if (c->throttling_conn && bufsize <= SSH1_BUFFER_LIMIT) {
|
||||
c->throttling_conn = false;
|
||||
ssh_throttle_conn(s->ppl.ssh, -1);
|
||||
c->throttling_conn = false;
|
||||
ssh_throttle_conn(s->ppl.ssh, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ struct ssh1_connection_state {
|
|||
Conf *conf;
|
||||
int local_protoflags, remote_protoflags;
|
||||
|
||||
tree234 *channels; /* indexed by local id */
|
||||
tree234 *channels; /* indexed by local id */
|
||||
|
||||
/* In SSH-1, the main session doesn't take the form of a 'channel'
|
||||
* according to the wire protocol. But we want to use the same API
|
||||
|
|
|
@ -43,7 +43,7 @@ struct ssh1_login_server_state {
|
|||
PacketProtocolLayer ppl;
|
||||
};
|
||||
|
||||
static void ssh1_login_server_free(PacketProtocolLayer *);
|
||||
static void ssh1_login_server_free(PacketProtocolLayer *);
|
||||
static void ssh1_login_server_process_queue(PacketProtocolLayer *);
|
||||
|
||||
static bool ssh1_login_server_get_specials(
|
||||
|
|
26
ssh1login.c
26
ssh1login.c
|
@ -63,7 +63,7 @@ struct ssh1_login_state {
|
|||
PacketProtocolLayer ppl;
|
||||
};
|
||||
|
||||
static void ssh1_login_free(PacketProtocolLayer *);
|
||||
static void ssh1_login_free(PacketProtocolLayer *);
|
||||
static void ssh1_login_process_queue(PacketProtocolLayer *);
|
||||
static void ssh1_login_dialog_callback(void *, int);
|
||||
static void ssh1_login_special_cmd(PacketProtocolLayer *ppl,
|
||||
|
@ -292,8 +292,8 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
|||
bool cipher_chosen = false, warn = false;
|
||||
const char *cipher_string = NULL;
|
||||
int i;
|
||||
for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) {
|
||||
int next_cipher = conf_get_int_int(
|
||||
for (i = 0; !cipher_chosen && i < CIPHER_MAX; i++) {
|
||||
int next_cipher = conf_get_int_int(
|
||||
s->conf, CONF_ssh_cipherlist, i);
|
||||
if (next_cipher == CIPHER_WARN) {
|
||||
/* If/when we choose a cipher, warn about it */
|
||||
|
@ -953,29 +953,29 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
|||
* SSH1_MSG_IGNORE packets. This way a passive
|
||||
* listener can't tell which is the password, and
|
||||
* hence can't deduce the password length.
|
||||
*
|
||||
*
|
||||
* Anybody with a password length greater than 16
|
||||
* bytes is going to have enough entropy in their
|
||||
* password that a listener won't find it _that_
|
||||
* much help to know how long it is. So what we'll
|
||||
* do is:
|
||||
*
|
||||
*
|
||||
* - if password length < 16, we send 15 packets
|
||||
* containing string lengths 1 through 15
|
||||
*
|
||||
*
|
||||
* - otherwise, we let N be the nearest multiple
|
||||
* of 8 below the password length, and send 8
|
||||
* packets containing string lengths N through
|
||||
* N+7. This won't obscure the order of
|
||||
* magnitude of the password length, but it will
|
||||
* introduce a bit of extra uncertainty.
|
||||
*
|
||||
*
|
||||
* A few servers can't deal with SSH1_MSG_IGNORE, at
|
||||
* least in this context. For these servers, we need
|
||||
* an alternative defence. We make use of the fact
|
||||
* that the password is interpreted as a C string:
|
||||
* so we can append a NUL, then some random data.
|
||||
*
|
||||
*
|
||||
* A few servers can deal with neither SSH1_MSG_IGNORE
|
||||
* here _nor_ a padded password string.
|
||||
* For these servers we are left with no defences
|
||||
|
@ -1015,7 +1015,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
|||
}
|
||||
}
|
||||
ppl_logevent("Sending password with camouflage packets");
|
||||
}
|
||||
}
|
||||
else if (!(s->ppl.remote_bugs & BUG_NEEDS_SSH1_PLAIN_PASSWORD)) {
|
||||
/*
|
||||
* The server can't deal with SSH1_MSG_IGNORE
|
||||
|
@ -1070,7 +1070,7 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
|||
put_uint32(pkt, 6); /* gzip compression level */
|
||||
pq_push(s->ppl.out_pq, pkt);
|
||||
crMaybeWaitUntilV((pktin = ssh1_login_pop(s)) != NULL);
|
||||
if (pktin->type == SSH1_SMSG_SUCCESS) {
|
||||
if (pktin->type == SSH1_SMSG_SUCCESS) {
|
||||
/*
|
||||
* We don't have to actually do anything here: the SSH-1
|
||||
* BPP will take care of automatically starting the
|
||||
|
@ -1079,15 +1079,15 @@ static void ssh1_login_process_queue(PacketProtocolLayer *ppl)
|
|||
* easiest way to avoid race conditions if other packets
|
||||
* cross in transit.)
|
||||
*/
|
||||
} else if (pktin->type == SSH1_SMSG_FAILURE) {
|
||||
} else if (pktin->type == SSH1_SMSG_FAILURE) {
|
||||
ppl_logevent("Server refused to enable compression");
|
||||
ppl_printf("Server refused to compress\r\n");
|
||||
ppl_printf("Server refused to compress\r\n");
|
||||
} else {
|
||||
ssh_proto_error(s->ppl.ssh, "Received unexpected packet"
|
||||
" in response to compression request, type %d "
|
||||
"(%s)", pktin->type, ssh1_pkt_type(pktin->type));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssh1_connection_set_protoflags(
|
||||
|
|
|
@ -181,11 +181,11 @@ static int ssh2_rportfwd_cmp(void *av, void *bv)
|
|||
struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;
|
||||
int i;
|
||||
if ( (i = strcmp(a->shost, b->shost)) != 0)
|
||||
return i < 0 ? -1 : +1;
|
||||
return i < 0 ? -1 : +1;
|
||||
if (a->sport > b->sport)
|
||||
return +1;
|
||||
return +1;
|
||||
if (a->sport < b->sport)
|
||||
return -1;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -196,16 +196,16 @@ static void ssh2_rportfwd_globreq_response(struct ssh2_connection_state *s,
|
|||
struct ssh_rportfwd *rpf = (struct ssh_rportfwd *)ctx;
|
||||
|
||||
if (pktin->type == SSH2_MSG_REQUEST_SUCCESS) {
|
||||
ppl_logevent("Remote port forwarding from %s enabled",
|
||||
ppl_logevent("Remote port forwarding from %s enabled",
|
||||
rpf->log_description);
|
||||
} else {
|
||||
ppl_logevent("Remote port forwarding from %s refused",
|
||||
ppl_logevent("Remote port forwarding from %s refused",
|
||||
rpf->log_description);
|
||||
|
||||
struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
|
||||
assert(realpf == rpf);
|
||||
struct ssh_rportfwd *realpf = del234(s->rportfwds, rpf);
|
||||
assert(realpf == rpf);
|
||||
portfwdmgr_close(s->portfwdmgr, rpf->pfr);
|
||||
free_rportfwd(rpf);
|
||||
free_rportfwd(rpf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,8 +410,8 @@ void ssh2channel_request_pty(
|
|||
put_stringz(pktout, conf_get_str(conf, CONF_termtype));
|
||||
put_uint32(pktout, w);
|
||||
put_uint32(pktout, h);
|
||||
put_uint32(pktout, 0); /* pixel width */
|
||||
put_uint32(pktout, 0); /* pixel height */
|
||||
put_uint32(pktout, 0); /* pixel width */
|
||||
put_uint32(pktout, 0); /* pixel height */
|
||||
modebuf = strbuf_new();
|
||||
write_ttymodes_to_packet(
|
||||
BinarySink_UPCAST(modebuf), 2,
|
||||
|
@ -470,8 +470,8 @@ void ssh2channel_send_terminal_size_change(SshChannel *sc, int w, int h)
|
|||
PktOut *pktout = ssh2_chanreq_init(c, "window-change", NULL, NULL);
|
||||
put_uint32(pktout, w);
|
||||
put_uint32(pktout, h);
|
||||
put_uint32(pktout, 0); /* pixel width */
|
||||
put_uint32(pktout, 0); /* pixel height */
|
||||
put_uint32(pktout, 0); /* pixel width */
|
||||
put_uint32(pktout, 0); /* pixel height */
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
}
|
||||
|
||||
|
|
118
ssh2connection.c
118
ssh2connection.c
|
@ -12,7 +12,7 @@
|
|||
#include "sshcr.h"
|
||||
#include "ssh2connection.h"
|
||||
|
||||
static void ssh2_connection_free(PacketProtocolLayer *);
|
||||
static void ssh2_connection_free(PacketProtocolLayer *);
|
||||
static void ssh2_connection_process_queue(PacketProtocolLayer *);
|
||||
static bool ssh2_connection_get_specials(
|
||||
PacketProtocolLayer *ppl, add_special_fn_t add_special, void *ctx);
|
||||
|
@ -191,9 +191,9 @@ static int ssh2_channelcmp(void *av, void *bv)
|
|||
const struct ssh2_channel *a = (const struct ssh2_channel *) av;
|
||||
const struct ssh2_channel *b = (const struct ssh2_channel *) bv;
|
||||
if (a->localid < b->localid)
|
||||
return -1;
|
||||
return -1;
|
||||
if (a->localid > b->localid)
|
||||
return +1;
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -202,9 +202,9 @@ static int ssh2_channelfind(void *av, void *bv)
|
|||
const unsigned *a = (const unsigned *) av;
|
||||
const struct ssh2_channel *b = (const struct ssh2_channel *) bv;
|
||||
if (*a < b->localid)
|
||||
return -1;
|
||||
return -1;
|
||||
if (*a > b->localid)
|
||||
return +1;
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -410,7 +410,7 @@ static bool ssh2_connection_filter_queue(struct ssh2_connection_state *s)
|
|||
put_uint32(pktout, c->remoteid);
|
||||
put_uint32(pktout, chanopen_result.u.failure.reason_code);
|
||||
put_stringz(pktout, chanopen_result.u.failure.wire_message);
|
||||
put_stringz(pktout, "en"); /* language tag */
|
||||
put_stringz(pktout, "en"); /* language tag */
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
ppl_logevent("Rejected channel open: %s",
|
||||
chanopen_result.u.failure.wire_message);
|
||||
|
@ -481,7 +481,7 @@ static bool ssh2_connection_filter_queue(struct ssh2_connection_state *s)
|
|||
localid);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
switch (pktin->type) {
|
||||
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
|
||||
assert(c->halfopen);
|
||||
|
@ -856,7 +856,7 @@ static bool ssh2_connection_filter_queue(struct ssh2_connection_state *s)
|
|||
}
|
||||
|
||||
static void ssh2_handle_winadj_response(struct ssh2_channel *c,
|
||||
PktIn *pktin, void *ctx)
|
||||
PktIn *pktin, void *ctx)
|
||||
{
|
||||
unsigned *sizep = ctx;
|
||||
|
||||
|
@ -876,7 +876,7 @@ static void ssh2_handle_winadj_response(struct ssh2_channel *c,
|
|||
* complete.
|
||||
*/
|
||||
if (c->throttle_state == UNTHROTTLING)
|
||||
c->throttle_state = UNTHROTTLED;
|
||||
c->throttle_state = UNTHROTTLED;
|
||||
}
|
||||
|
||||
static void ssh2_set_window(struct ssh2_channel *c, int newwin)
|
||||
|
@ -890,7 +890,7 @@ static void ssh2_set_window(struct ssh2_channel *c, int newwin)
|
|||
* CLOSE.
|
||||
*/
|
||||
if (c->closes & (CLOSES_RCVD_EOF | CLOSES_SENT_CLOSE))
|
||||
return;
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the client-side Channel is in an initial setup phase with a
|
||||
|
@ -907,7 +907,7 @@ static void ssh2_set_window(struct ssh2_channel *c, int newwin)
|
|||
* window as well).
|
||||
*/
|
||||
if ((s->ppl.remote_bugs & BUG_SSH2_MAXPKT) && newwin > OUR_V2_MAXPKT)
|
||||
newwin = OUR_V2_MAXPKT;
|
||||
newwin = OUR_V2_MAXPKT;
|
||||
|
||||
/*
|
||||
* Only send a WINDOW_ADJUST if there's significantly more window
|
||||
|
@ -917,39 +917,39 @@ static void ssh2_set_window(struct ssh2_channel *c, int newwin)
|
|||
* "Significant" is arbitrarily defined as half the window size.
|
||||
*/
|
||||
if (newwin / 2 >= c->locwindow) {
|
||||
PktOut *pktout;
|
||||
unsigned *up;
|
||||
PktOut *pktout;
|
||||
unsigned *up;
|
||||
|
||||
/*
|
||||
* In order to keep track of how much window the client
|
||||
* actually has available, we'd like it to acknowledge each
|
||||
* WINDOW_ADJUST. We can't do that directly, so we accompany
|
||||
* it with a CHANNEL_REQUEST that has to be acknowledged.
|
||||
*
|
||||
* This is only necessary if we're opening the window wide.
|
||||
* If we're not, then throughput is being constrained by
|
||||
* something other than the maximum window size anyway.
|
||||
*/
|
||||
if (newwin == c->locmaxwin &&
|
||||
/*
|
||||
* In order to keep track of how much window the client
|
||||
* actually has available, we'd like it to acknowledge each
|
||||
* WINDOW_ADJUST. We can't do that directly, so we accompany
|
||||
* it with a CHANNEL_REQUEST that has to be acknowledged.
|
||||
*
|
||||
* This is only necessary if we're opening the window wide.
|
||||
* If we're not, then throughput is being constrained by
|
||||
* something other than the maximum window size anyway.
|
||||
*/
|
||||
if (newwin == c->locmaxwin &&
|
||||
!(s->ppl.remote_bugs & BUG_CHOKES_ON_WINADJ)) {
|
||||
up = snew(unsigned);
|
||||
*up = newwin - c->locwindow;
|
||||
pktout = ssh2_chanreq_init(c, "winadj@putty.projects.tartarus.org",
|
||||
ssh2_handle_winadj_response, up);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
up = snew(unsigned);
|
||||
*up = newwin - c->locwindow;
|
||||
pktout = ssh2_chanreq_init(c, "winadj@putty.projects.tartarus.org",
|
||||
ssh2_handle_winadj_response, up);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
|
||||
if (c->throttle_state != UNTHROTTLED)
|
||||
c->throttle_state = UNTHROTTLING;
|
||||
} else {
|
||||
/* Pretend the WINDOW_ADJUST was acked immediately. */
|
||||
c->remlocwin = newwin;
|
||||
c->throttle_state = THROTTLED;
|
||||
}
|
||||
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_CHANNEL_WINDOW_ADJUST);
|
||||
put_uint32(pktout, c->remoteid);
|
||||
put_uint32(pktout, newwin - c->locwindow);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
c->locwindow = newwin;
|
||||
if (c->throttle_state != UNTHROTTLED)
|
||||
c->throttle_state = UNTHROTTLING;
|
||||
} else {
|
||||
/* Pretend the WINDOW_ADJUST was acked immediately. */
|
||||
c->remlocwin = newwin;
|
||||
c->throttle_state = THROTTLED;
|
||||
}
|
||||
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_CHANNEL_WINDOW_ADJUST);
|
||||
put_uint32(pktout, c->remoteid);
|
||||
put_uint32(pktout, newwin - c->locwindow);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
c->locwindow = newwin;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1027,13 +1027,13 @@ static void ssh2_connection_process_queue(PacketProtocolLayer *ppl)
|
|||
*/
|
||||
|
||||
while (1) {
|
||||
if ((pktin = ssh2_connection_pop(s)) != NULL) {
|
||||
if ((pktin = ssh2_connection_pop(s)) != NULL) {
|
||||
|
||||
/*
|
||||
* _All_ the connection-layer packets we expect to
|
||||
* receive are now handled by the dispatch table.
|
||||
* Anything that reaches here must be bogus.
|
||||
*/
|
||||
/*
|
||||
* _All_ the connection-layer packets we expect to
|
||||
* receive are now handled by the dispatch table.
|
||||
* Anything that reaches here must be bogus.
|
||||
*/
|
||||
|
||||
ssh_proto_error(s->ppl.ssh, "Received unexpected connection-layer "
|
||||
"packet, type %d (%s)", pktin->type,
|
||||
|
@ -1041,8 +1041,8 @@ static void ssh2_connection_process_queue(PacketProtocolLayer *ppl)
|
|||
s->ppl.bpp->pls->actx,
|
||||
pktin->type));
|
||||
return;
|
||||
}
|
||||
crReturnV;
|
||||
}
|
||||
crReturnV;
|
||||
}
|
||||
|
||||
crFinishV;
|
||||
|
@ -1064,22 +1064,22 @@ static void ssh2_channel_check_close(struct ssh2_channel *c)
|
|||
|
||||
if (chan_want_close(c->chan, (c->closes & CLOSES_SENT_EOF),
|
||||
(c->closes & CLOSES_RCVD_EOF)) &&
|
||||
!c->chanreq_head &&
|
||||
!(c->closes & CLOSES_SENT_CLOSE)) {
|
||||
!c->chanreq_head &&
|
||||
!(c->closes & CLOSES_SENT_CLOSE)) {
|
||||
/*
|
||||
* We have both sent and received EOF (or the channel is a
|
||||
* zombie), and we have no outstanding channel requests, which
|
||||
* means the channel is in final wind-up. But we haven't sent
|
||||
* CLOSE, so let's do so now.
|
||||
*/
|
||||
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_CHANNEL_CLOSE);
|
||||
put_uint32(pktout, c->remoteid);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_CHANNEL_CLOSE);
|
||||
put_uint32(pktout, c->remoteid);
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
c->closes |= CLOSES_SENT_EOF | CLOSES_SENT_CLOSE;
|
||||
}
|
||||
|
||||
if (!((CLOSES_SENT_CLOSE | CLOSES_RCVD_CLOSE) & ~c->closes)) {
|
||||
assert(c->chanreq_head == NULL);
|
||||
assert(c->chanreq_head == NULL);
|
||||
/*
|
||||
* We have both sent and received CLOSE, which means we're
|
||||
* completely done with the channel.
|
||||
|
@ -1164,7 +1164,7 @@ static void ssh2_try_send_and_unthrottle(struct ssh2_channel *c)
|
|||
{
|
||||
int bufsize;
|
||||
if (c->closes & CLOSES_SENT_EOF)
|
||||
return; /* don't send on channels we've EOFed */
|
||||
return; /* don't send on channels we've EOFed */
|
||||
bufsize = ssh2_try_send(c);
|
||||
if (bufsize == 0) {
|
||||
c->throttled_by_backlog = false;
|
||||
|
@ -1388,8 +1388,8 @@ static void ssh2channel_unthrottle(SshChannel *sc, size_t bufsize)
|
|||
ssh2_set_window(c, buflimit - bufsize);
|
||||
|
||||
if (c->throttling_conn && bufsize <= buflimit) {
|
||||
c->throttling_conn = false;
|
||||
ssh_throttle_conn(s->ppl.ssh, -1);
|
||||
c->throttling_conn = false;
|
||||
ssh_throttle_conn(s->ppl.ssh, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1616,7 +1616,7 @@ static void ssh2_connection_special_cmd(PacketProtocolLayer *ppl,
|
|||
pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_IGNORE);
|
||||
put_stringz(pktout, "");
|
||||
pq_push(s->ppl.out_pq, pktout);
|
||||
}
|
||||
}
|
||||
} else if (s->mainchan) {
|
||||
mainchan_special_cmd(s->mainchan, code, arg);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ struct ssh2_connection_state {
|
|||
|
||||
Conf *conf;
|
||||
|
||||
tree234 *channels; /* indexed by local id */
|
||||
tree234 *channels; /* indexed by local id */
|
||||
bool all_channels_throttled;
|
||||
|
||||
bool X11_fwd_enabled;
|
||||
|
|
|
@ -261,9 +261,9 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
|
|||
if (!s->rsa_kex_key) {
|
||||
ppl_logevent("Generating a %d-bit RSA key", extra->minklen);
|
||||
|
||||
s->rsa_kex_key = snew(RSAKey);
|
||||
rsa_generate(s->rsa_kex_key, extra->minklen, no_progress, NULL);
|
||||
s->rsa_kex_key->comment = NULL;
|
||||
s->rsa_kex_key = snew(RSAKey);
|
||||
rsa_generate(s->rsa_kex_key, extra->minklen, no_progress, NULL);
|
||||
s->rsa_kex_key->comment = NULL;
|
||||
s->rsa_kex_key_needs_freeing = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1579,7 +1579,7 @@ static void ssh2_transport_timer(void *ctx, unsigned long now)
|
|||
|
||||
mins = sanitise_rekey_time(conf_get_int(s->conf, CONF_ssh_rekey_time), 60);
|
||||
if (mins == 0)
|
||||
return;
|
||||
return;
|
||||
|
||||
/* Rekey if enough time has elapsed */
|
||||
ticks = mins * 60 * TICKSPERSEC;
|
||||
|
@ -1884,18 +1884,18 @@ static void ssh2_transport_special_cmd(PacketProtocolLayer *ppl,
|
|||
container_of(ppl, struct ssh2_transport_state, ppl);
|
||||
|
||||
if (code == SS_REKEY) {
|
||||
if (!s->kex_in_progress) {
|
||||
if (!s->kex_in_progress) {
|
||||
s->rekey_reason = "at user request";
|
||||
s->rekey_class = RK_NORMAL;
|
||||
queue_idempotent_callback(&s->ppl.ic_process_queue);
|
||||
}
|
||||
}
|
||||
} else if (code == SS_XCERT) {
|
||||
if (!s->kex_in_progress) {
|
||||
if (!s->kex_in_progress) {
|
||||
s->cross_certifying = s->hostkey_alg = ssh2_hostkey_algs[arg].alg;
|
||||
s->rekey_reason = "cross-certifying new host key";
|
||||
s->rekey_class = RK_NORMAL;
|
||||
queue_idempotent_callback(&s->ppl.ic_process_queue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Send everything else to the next layer up. This includes
|
||||
* SS_PING/SS_NOP, which we _could_ handle here - but it's
|
||||
|
@ -1938,7 +1938,7 @@ static void ssh2_transport_reconfigure(PacketProtocolLayer *ppl, Conf *conf)
|
|||
old_max_data_size = s->max_data_size;
|
||||
ssh2_transport_set_max_data_size(s);
|
||||
if (old_max_data_size != s->max_data_size &&
|
||||
s->max_data_size != 0) {
|
||||
s->max_data_size != 0) {
|
||||
if (s->max_data_size < old_max_data_size) {
|
||||
unsigned long diff = old_max_data_size - s->max_data_size;
|
||||
|
||||
|
@ -1956,19 +1956,19 @@ static void ssh2_transport_reconfigure(PacketProtocolLayer *ppl, Conf *conf)
|
|||
}
|
||||
|
||||
if (conf_get_bool(s->conf, CONF_compression) !=
|
||||
conf_get_bool(conf, CONF_compression)) {
|
||||
conf_get_bool(conf, CONF_compression)) {
|
||||
rekey_reason = "compression setting changed";
|
||||
rekey_mandatory = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < CIPHER_MAX; i++)
|
||||
if (conf_get_int_int(s->conf, CONF_ssh_cipherlist, i) !=
|
||||
conf_get_int_int(conf, CONF_ssh_cipherlist, i)) {
|
||||
if (conf_get_int_int(s->conf, CONF_ssh_cipherlist, i) !=
|
||||
conf_get_int_int(conf, CONF_ssh_cipherlist, i)) {
|
||||
rekey_reason = "cipher settings changed";
|
||||
rekey_mandatory = true;
|
||||
}
|
||||
if (conf_get_bool(s->conf, CONF_ssh2_des_cbc) !=
|
||||
conf_get_bool(conf, CONF_ssh2_des_cbc)) {
|
||||
conf_get_bool(conf, CONF_ssh2_des_cbc)) {
|
||||
rekey_reason = "cipher settings changed";
|
||||
rekey_mandatory = true;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ struct ssh2_userauth_state {
|
|||
PacketProtocolLayer ppl;
|
||||
};
|
||||
|
||||
static void ssh2_userauth_free(PacketProtocolLayer *);
|
||||
static void ssh2_userauth_free(PacketProtocolLayer *);
|
||||
static void ssh2_userauth_process_queue(PacketProtocolLayer *);
|
||||
static bool ssh2_userauth_get_specials(
|
||||
PacketProtocolLayer *ppl, add_special_fn_t add_special, void *ctx);
|
||||
|
@ -372,16 +372,16 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
|||
* beginning to try another username, if this is configured on.
|
||||
* (If they specify a username in the config, they are never
|
||||
* asked, even if they do give a wrong password.)
|
||||
*
|
||||
*
|
||||
* I think this best serves the needs of
|
||||
*
|
||||
*
|
||||
* - the people who have no configuration, no keys, and just
|
||||
* want to try repeated (username,password) pairs until they
|
||||
* type both correctly
|
||||
*
|
||||
*
|
||||
* - people who have keys and configuration but occasionally
|
||||
* need to fall back to passwords
|
||||
*
|
||||
*
|
||||
* - people with a key held in Pageant, who might not have
|
||||
* logged in to a particular machine before; so they want to
|
||||
* type a username, and then _either_ their key will be
|
||||
|
@ -405,7 +405,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
|||
s->cur_prompt->to_server = true;
|
||||
s->cur_prompt->from_server = false;
|
||||
s->cur_prompt->name = dupstr("SSH login name");
|
||||
add_prompt(s->cur_prompt, dupstr("login as: "), true);
|
||||
add_prompt(s->cur_prompt, dupstr("login as: "), true);
|
||||
s->userpass_ret = seat_get_userpass_input(
|
||||
s->ppl.seat, s->cur_prompt, NULL);
|
||||
while (1) {
|
||||
|
@ -1199,7 +1199,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
|||
put_stringz(s->pktout, ""); /* lang */
|
||||
put_stringz(s->pktout, ""); /* submethods */
|
||||
pq_push(s->ppl.out_pq, s->pktout);
|
||||
|
||||
|
||||
ppl_logevent("Attempting keyboard-interactive authentication");
|
||||
|
||||
if (!s->ki_scc_initialised) {
|
||||
|
@ -1492,7 +1492,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
|||
|
||||
while (pktin->type == SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ) {
|
||||
|
||||
/*
|
||||
/*
|
||||
* We're being asked for a new password
|
||||
* (perhaps not for the first time).
|
||||
* Loop until the server accepts it.
|
||||
|
@ -1500,7 +1500,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
|||
|
||||
bool got_new = false; /* not live over crReturn */
|
||||
ptrlen prompt; /* not live over crReturn */
|
||||
|
||||
|
||||
{
|
||||
const char *msg;
|
||||
if (changereq_first_time)
|
||||
|
@ -1620,7 +1620,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl)
|
|||
s->pktout->minlen = 256;
|
||||
pq_push(s->ppl.out_pq, s->pktout);
|
||||
ppl_logevent("Sent new password");
|
||||
|
||||
|
||||
/*
|
||||
* Now see what the server has to say about it.
|
||||
* (If it's CHANGEREQ again, it's not happy with the
|
||||
|
@ -1752,42 +1752,42 @@ static void ssh2_userauth_add_sigblob(
|
|||
if ((s->ppl.remote_bugs & BUG_SSH2_RSA_PADDING) &&
|
||||
ptrlen_eq_string(get_string(pk), "ssh-rsa") &&
|
||||
ptrlen_eq_string(get_string(sig), "ssh-rsa")) {
|
||||
ptrlen mod_mp, sig_mp;
|
||||
ptrlen mod_mp, sig_mp;
|
||||
size_t sig_prefix_len;
|
||||
|
||||
/*
|
||||
* Find the modulus and signature integers.
|
||||
*/
|
||||
/*
|
||||
* Find the modulus and signature integers.
|
||||
*/
|
||||
get_string(pk); /* skip over exponent */
|
||||
mod_mp = get_string(pk); /* remember modulus */
|
||||
sig_prefix_len = sig->pos;
|
||||
sig_mp = get_string(sig);
|
||||
sig_mp = get_string(sig);
|
||||
if (get_err(pk) || get_err(sig))
|
||||
goto give_up;
|
||||
|
||||
/*
|
||||
* Find the byte length of the modulus, not counting leading
|
||||
* zeroes.
|
||||
* zeroes.
|
||||
*/
|
||||
while (mod_mp.len > 0 && *(const char *)mod_mp.ptr == 0) {
|
||||
while (mod_mp.len > 0 && *(const char *)mod_mp.ptr == 0) {
|
||||
mod_mp.len--;
|
||||
mod_mp.ptr = (const char *)mod_mp.ptr + 1;
|
||||
}
|
||||
|
||||
/* debug("modulus length is %d\n", len); */
|
||||
/* debug("signature length is %d\n", siglen); */
|
||||
/* debug("modulus length is %d\n", len); */
|
||||
/* debug("signature length is %d\n", siglen); */
|
||||
|
||||
if (mod_mp.len != sig_mp.len) {
|
||||
if (mod_mp.len != sig_mp.len) {
|
||||
strbuf *substr = strbuf_new();
|
||||
put_data(substr, sigblob.ptr, sig_prefix_len);
|
||||
put_uint32(substr, mod_mp.len);
|
||||
put_padding(substr, mod_mp.len - sig_mp.len, 0);
|
||||
put_datapl(substr, sig_mp);
|
||||
put_data(substr, sigblob.ptr, sig_prefix_len);
|
||||
put_uint32(substr, mod_mp.len);
|
||||
put_padding(substr, mod_mp.len - sig_mp.len, 0);
|
||||
put_datapl(substr, sig_mp);
|
||||
put_stringsb(pkt, substr);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Otherwise fall through and do it the easy way. We also come
|
||||
/* Otherwise fall through and do it the easy way. We also come
|
||||
* here as a fallback if we discover above that the key blob
|
||||
* is misformatted in some way. */
|
||||
give_up:;
|
||||
|
|
16
sshaes.c
16
sshaes.c
|
@ -856,7 +856,7 @@ static void aes_sliced_key_setup(
|
|||
* Prepare a word of round key in the low 4 bits of each
|
||||
* integer in slices[].
|
||||
*/
|
||||
if (i < key_words) {
|
||||
if (i < key_words) {
|
||||
memcpy(inblk, key + 4*i, 4);
|
||||
TO_BITSLICES(slices, inblk, uint16_t, =, 0);
|
||||
} else {
|
||||
|
@ -905,7 +905,7 @@ static void aes_sliced_key_setup(
|
|||
prevslices = sk->roundkeys_serial + 8 * (wordindex >> 2);
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
slices[i] ^= prevslices[i] >> bitshift;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now copy it into sk.
|
||||
|
@ -1321,10 +1321,10 @@ static FUNC_ISA void aes_ni_key_expand(
|
|||
unsigned rconpos = 0;
|
||||
|
||||
for (size_t i = 0; i < sched_words; i++) {
|
||||
if (i < key_words) {
|
||||
if (i < key_words) {
|
||||
sched[i] = GET_32BIT_LSB_FIRST(key + 4 * i);
|
||||
} else {
|
||||
uint32_t temp = sched[i - 1];
|
||||
uint32_t temp = sched[i - 1];
|
||||
|
||||
bool rotate_and_round_constant = (i % key_words == 0);
|
||||
bool only_sub = (key_words == 8 && i % 8 == 4);
|
||||
|
@ -1343,7 +1343,7 @@ static FUNC_ISA void aes_ni_key_expand(
|
|||
}
|
||||
|
||||
sched[i] = sched[i - key_words] ^ temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1625,10 +1625,10 @@ static FUNC_ISA void aes_neon_key_expand(
|
|||
unsigned rconpos = 0;
|
||||
|
||||
for (size_t i = 0; i < sched_words; i++) {
|
||||
if (i < key_words) {
|
||||
if (i < key_words) {
|
||||
sched[i] = GET_32BIT_LSB_FIRST(key + 4 * i);
|
||||
} else {
|
||||
uint32_t temp = sched[i - 1];
|
||||
uint32_t temp = sched[i - 1];
|
||||
|
||||
bool rotate_and_round_constant = (i % key_words == 0);
|
||||
bool sub = rotate_and_round_constant ||
|
||||
|
@ -1651,7 +1651,7 @@ static FUNC_ISA void aes_neon_key_expand(
|
|||
}
|
||||
|
||||
sched[i] = sched[i - key_words] ^ temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
20
ssharcf.c
20
ssharcf.c
|
@ -22,16 +22,16 @@ static void arcfour_block(void *handle, void *vblk, int len)
|
|||
s = ctx->s;
|
||||
i = ctx->i; j = ctx->j;
|
||||
for (k = 0; (int)k < len; k++) {
|
||||
i = (i + 1) & 0xff;
|
||||
j = (j + s[i]) & 0xff;
|
||||
tmp = s[i]; s[i] = s[j]; s[j] = tmp;
|
||||
blk[k] ^= s[(s[i]+s[j]) & 0xff];
|
||||
i = (i + 1) & 0xff;
|
||||
j = (j + s[i]) & 0xff;
|
||||
tmp = s[i]; s[i] = s[j]; s[j] = tmp;
|
||||
blk[k] ^= s[(s[i]+s[j]) & 0xff];
|
||||
}
|
||||
ctx->i = i; ctx->j = j;
|
||||
}
|
||||
|
||||
static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
|
||||
unsigned keybytes)
|
||||
unsigned keybytes)
|
||||
{
|
||||
unsigned char tmp, k[256], *s;
|
||||
unsigned i, j;
|
||||
|
@ -40,13 +40,13 @@ static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
|
|||
assert(keybytes <= 256);
|
||||
ctx->i = ctx->j = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
s[i] = i;
|
||||
k[i] = key[i % keybytes];
|
||||
s[i] = i;
|
||||
k[i] = key[i % keybytes];
|
||||
}
|
||||
j = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
j = (j + s[i] + k[i]) & 0xff;
|
||||
tmp = s[i]; s[i] = s[j]; s[j] = tmp;
|
||||
j = (j + s[i] + k[i]) & 0xff;
|
||||
tmp = s[i]; s[i] = s[j]; s[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
|
|||
* We don't implement Arcfour in SSH-1 because it's utterly insecure in
|
||||
* several ways. See CERT Vulnerability Notes VU#25309, VU#665372,
|
||||
* and VU#565052.
|
||||
*
|
||||
*
|
||||
* We don't implement the "arcfour" algorithm in SSH-2 because it doesn't
|
||||
* stir the cipher state before emitting keystream, and hence is likely
|
||||
* to leak data about the key.
|
||||
|
|
|
@ -88,7 +88,7 @@ static ssh_cipher *des3_pubkey_ossh_cipher(const void *vkey, const void *viv)
|
|||
}
|
||||
|
||||
void des3_decrypt_pubkey_ossh(const void *vkey, const void *viv,
|
||||
void *vblk, int len)
|
||||
void *vblk, int len)
|
||||
{
|
||||
ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
|
||||
ssh_cipher_decrypt(c, vblk, len);
|
||||
|
@ -96,7 +96,7 @@ void des3_decrypt_pubkey_ossh(const void *vkey, const void *viv,
|
|||
}
|
||||
|
||||
void des3_encrypt_pubkey_ossh(const void *vkey, const void *viv,
|
||||
void *vblk, int len)
|
||||
void *vblk, int len)
|
||||
{
|
||||
ssh_cipher *c = des3_pubkey_ossh_cipher(vkey, viv);
|
||||
ssh_cipher_encrypt(c, vblk, len);
|
||||
|
@ -119,14 +119,14 @@ static ssh_cipher *des_xdmauth_cipher(const void *vkeydata)
|
|||
nbits = 0;
|
||||
j = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (nbits < 7) {
|
||||
bits = (bits << 8) | keydata[j];
|
||||
nbits += 8;
|
||||
j++;
|
||||
}
|
||||
key[i] = (bits >> (nbits - 7)) << 1;
|
||||
bits &= ~(0x7F << (nbits - 7));
|
||||
nbits -= 7;
|
||||
if (nbits < 7) {
|
||||
bits = (bits << 8) | keydata[j];
|
||||
nbits += 8;
|
||||
j++;
|
||||
}
|
||||
key[i] = (bits >> (nbits - 7)) << 1;
|
||||
bits &= ~(0x7F << (nbits - 7));
|
||||
nbits -= 7;
|
||||
}
|
||||
|
||||
ssh_cipher *c = ssh_cipher_new(&ssh_des);
|
||||
|
|
188
sshblowf.c
188
sshblowf.c
|
@ -11,7 +11,7 @@
|
|||
|
||||
struct BlowfishContext {
|
||||
uint32_t S0[256], S1[256], S2[256], S3[256], P[18];
|
||||
uint32_t iv0, iv1; /* for CBC mode */
|
||||
uint32_t iv0, iv1; /* for CBC mode */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -234,7 +234,7 @@ static const uint32_t sbox3[] = {
|
|||
#define ROUND(n) ( xL ^= P[n], t = xL, xL = F(xL) ^ xR, xR = t )
|
||||
|
||||
static void blowfish_encrypt(uint32_t xL, uint32_t xR, uint32_t *output,
|
||||
BlowfishContext * ctx)
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
uint32_t *S0 = ctx->S0;
|
||||
uint32_t *S1 = ctx->S1;
|
||||
|
@ -267,7 +267,7 @@ static void blowfish_encrypt(uint32_t xL, uint32_t xR, uint32_t *output,
|
|||
}
|
||||
|
||||
static void blowfish_decrypt(uint32_t xL, uint32_t xR, uint32_t *output,
|
||||
BlowfishContext * ctx)
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
uint32_t *S0 = ctx->S0;
|
||||
uint32_t *S1 = ctx->S1;
|
||||
|
@ -310,17 +310,17 @@ static void blowfish_lsb_encrypt_cbc(unsigned char *blk, int len,
|
|||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
iv0 ^= xL;
|
||||
iv1 ^= xR;
|
||||
blowfish_encrypt(iv0, iv1, out, ctx);
|
||||
iv0 = out[0];
|
||||
iv1 = out[1];
|
||||
PUT_32BIT_LSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, iv1);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
iv0 ^= xL;
|
||||
iv1 ^= xR;
|
||||
blowfish_encrypt(iv0, iv1, out, ctx);
|
||||
iv0 = out[0];
|
||||
iv1 = out[1];
|
||||
PUT_32BIT_LSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, iv1);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
|
@ -335,18 +335,18 @@ void blowfish_lsb_encrypt_ecb(void *vblk, int len, BlowfishContext * ctx)
|
|||
assert((len & 7) == 0);
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
blowfish_encrypt(xL, xR, out, ctx);
|
||||
PUT_32BIT_LSB_FIRST(blk, out[0]);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, out[1]);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
blowfish_encrypt(xL, xR, out, ctx);
|
||||
PUT_32BIT_LSB_FIRST(blk, out[0]);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, out[1]);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
uint32_t xL, xR, out[2], iv0, iv1;
|
||||
|
||||
|
@ -356,17 +356,17 @@ static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len,
|
|||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
blowfish_decrypt(xL, xR, out, ctx);
|
||||
iv0 ^= out[0];
|
||||
iv1 ^= out[1];
|
||||
PUT_32BIT_LSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, iv1);
|
||||
iv0 = xL;
|
||||
iv1 = xR;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
blowfish_decrypt(xL, xR, out, ctx);
|
||||
iv0 ^= out[0];
|
||||
iv1 ^= out[1];
|
||||
PUT_32BIT_LSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, iv1);
|
||||
iv0 = xL;
|
||||
iv1 = xR;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
|
@ -374,7 +374,7 @@ static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len,
|
|||
}
|
||||
|
||||
static void blowfish_msb_encrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
uint32_t xL, xR, out[2], iv0, iv1;
|
||||
|
||||
|
@ -384,17 +384,17 @@ static void blowfish_msb_encrypt_cbc(unsigned char *blk, int len,
|
|||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
iv0 ^= xL;
|
||||
iv1 ^= xR;
|
||||
blowfish_encrypt(iv0, iv1, out, ctx);
|
||||
iv0 = out[0];
|
||||
iv1 = out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, iv1);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
iv0 ^= xL;
|
||||
iv1 ^= xR;
|
||||
blowfish_encrypt(iv0, iv1, out, ctx);
|
||||
iv0 = out[0];
|
||||
iv1 = out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, iv1);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
|
@ -402,7 +402,7 @@ static void blowfish_msb_encrypt_cbc(unsigned char *blk, int len,
|
|||
}
|
||||
|
||||
static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
uint32_t xL, xR, out[2], iv0, iv1;
|
||||
|
||||
|
@ -412,17 +412,17 @@ static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len,
|
|||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
blowfish_decrypt(xL, xR, out, ctx);
|
||||
iv0 ^= out[0];
|
||||
iv1 ^= out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, iv1);
|
||||
iv0 = xL;
|
||||
iv1 = xR;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
blowfish_decrypt(xL, xR, out, ctx);
|
||||
iv0 ^= out[0];
|
||||
iv1 ^= out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, iv1);
|
||||
iv0 = xL;
|
||||
iv1 = xR;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
|
@ -430,7 +430,7 @@ static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len,
|
|||
}
|
||||
|
||||
static void blowfish_msb_sdctr(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
uint32_t b[2], iv0, iv1, tmp;
|
||||
|
||||
|
@ -440,15 +440,15 @@ static void blowfish_msb_sdctr(unsigned char *blk, int len,
|
|||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
blowfish_encrypt(iv0, iv1, b, ctx);
|
||||
tmp = GET_32BIT_MSB_FIRST(blk);
|
||||
PUT_32BIT_MSB_FIRST(blk, tmp ^ b[0]);
|
||||
tmp = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, tmp ^ b[1]);
|
||||
if ((iv1 = (iv1 + 1) & 0xffffffff) == 0)
|
||||
iv0 = (iv0 + 1) & 0xffffffff;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
blowfish_encrypt(iv0, iv1, b, ctx);
|
||||
tmp = GET_32BIT_MSB_FIRST(blk);
|
||||
PUT_32BIT_MSB_FIRST(blk, tmp ^ b[0]);
|
||||
tmp = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, tmp ^ b[1]);
|
||||
if ((iv1 = (iv1 + 1) & 0xffffffff) == 0)
|
||||
iv0 = (iv0 + 1) & 0xffffffff;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
|
@ -460,14 +460,14 @@ void blowfish_initkey(BlowfishContext *ctx)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 18; i++) {
|
||||
ctx->P[i] = parray[i];
|
||||
ctx->P[i] = parray[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ctx->S0[i] = sbox0[i];
|
||||
ctx->S1[i] = sbox1[i];
|
||||
ctx->S2[i] = sbox2[i];
|
||||
ctx->S3[i] = sbox3[i];
|
||||
ctx->S0[i] = sbox0[i];
|
||||
ctx->S1[i] = sbox1[i];
|
||||
ctx->S2[i] = sbox2[i];
|
||||
ctx->S3[i] = sbox3[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,13 +495,13 @@ void blowfish_expandkey(BlowfishContext * ctx,
|
|||
}
|
||||
|
||||
for (i = 0; i < 18; i++) {
|
||||
P[i] ^=
|
||||
((uint32_t) (unsigned char) (key[(i * 4 + 0) % keybytes])) << 24;
|
||||
P[i] ^=
|
||||
((uint32_t) (unsigned char) (key[(i * 4 + 1) % keybytes])) << 16;
|
||||
P[i] ^=
|
||||
((uint32_t) (unsigned char) (key[(i * 4 + 2) % keybytes])) << 8;
|
||||
P[i] ^= ((uint32_t) (unsigned char) (key[(i * 4 + 3) % keybytes]));
|
||||
P[i] ^=
|
||||
((uint32_t) (unsigned char) (key[(i * 4 + 0) % keybytes])) << 24;
|
||||
P[i] ^=
|
||||
((uint32_t) (unsigned char) (key[(i * 4 + 1) % keybytes])) << 16;
|
||||
P[i] ^=
|
||||
((uint32_t) (unsigned char) (key[(i * 4 + 2) % keybytes])) << 8;
|
||||
P[i] ^= ((uint32_t) (unsigned char) (key[(i * 4 + 3) % keybytes]));
|
||||
}
|
||||
|
||||
str[0] = str[1] = 0;
|
||||
|
@ -510,38 +510,38 @@ void blowfish_expandkey(BlowfishContext * ctx,
|
|||
for (j = 0; j < 8; j++)
|
||||
str[j/4] ^= ((uint32_t)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
|
||||
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
P[i] = str[0];
|
||||
P[i + 1] = str[1];
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
P[i] = str[0];
|
||||
P[i + 1] = str[1];
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
for (j = 0; j < 8; j++)
|
||||
str[j/4] ^= ((uint32_t)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S0[i] = str[0];
|
||||
S0[i + 1] = str[1];
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S0[i] = str[0];
|
||||
S0[i + 1] = str[1];
|
||||
}
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
for (j = 0; j < 8; j++)
|
||||
str[j/4] ^= ((uint32_t)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S1[i] = str[0];
|
||||
S1[i + 1] = str[1];
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S1[i] = str[0];
|
||||
S1[i + 1] = str[1];
|
||||
}
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
for (j = 0; j < 8; j++)
|
||||
str[j/4] ^= ((uint32_t)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S2[i] = str[0];
|
||||
S2[i + 1] = str[1];
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S2[i] = str[0];
|
||||
S2[i + 1] = str[1];
|
||||
}
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
for (j = 0; j < 8; j++)
|
||||
str[j/4] ^= ((uint32_t)salt[saltpos++ % saltbytes]) << (24-8*(j%4));
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S3[i] = str[0];
|
||||
S3[i + 1] = str[1];
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S3[i] = str[0];
|
||||
S3[i + 1] = str[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
2
sshbpp.h
2
sshbpp.h
|
@ -6,7 +6,7 @@
|
|||
#define PUTTY_SSHBPP_H
|
||||
|
||||
struct BinaryPacketProtocolVtable {
|
||||
void (*free)(BinaryPacketProtocol *);
|
||||
void (*free)(BinaryPacketProtocol *);
|
||||
void (*handle_input)(BinaryPacketProtocol *);
|
||||
void (*handle_output)(BinaryPacketProtocol *);
|
||||
PktOut *(*new_pktout)(int type);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче