Make the backend_init error message dynamic. (NFC)

Now, instead of a 'const char *' in the static data segment, error
messages returned from backend setup are dynamically allocated and
freed by the caller.

This will allow me to make the messages much more specific (including
errno values and the like). However, this commit is pure refactoring:
I've _just_ changed the allocation policy, and left all the messages
alone.
This commit is contained in:
Simon Tatham 2020-04-18 13:28:33 +01:00
Родитель d9c4ce9fd8
Коммит df2994a05a
14 изменённых файлов: 88 добавлений и 87 удалений

10
putty.h
Просмотреть файл

@ -495,10 +495,10 @@ struct Backend {
const BackendVtable *vt;
};
struct BackendVtable {
const char *(*init) (const BackendVtable *vt, Seat *seat,
Backend **backend_out, LogContext *logctx, Conf *conf,
const char *host, int port,
char **realhost, bool nodelay, bool keepalive);
char *(*init) (const BackendVtable *vt, Seat *seat,
Backend **backend_out, LogContext *logctx, Conf *conf,
const char *host, int port, char **realhost,
bool nodelay, bool keepalive);
void (*free) (Backend *be);
/* Pass in a replacement configuration. */
@ -540,7 +540,7 @@ struct BackendVtable {
unsigned serial_parity_mask, serial_flow_mask;
};
static inline const char *backend_init(
static inline char *backend_init(
const BackendVtable *vt, Seat *seat, Backend **out, LogContext *logctx,
Conf *conf, const char *host, int port, char **rhost, bool nd, bool ka)
{ return vt->init(vt, seat, out, logctx, conf, host, port, rhost, nd, ka); }

12
raw.c
Просмотреть файл

@ -119,10 +119,10 @@ static const PlugVtable Raw_plugvt = {
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *raw_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
static char *raw_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
{
SockAddr *addr;
const char *err;
@ -155,7 +155,7 @@ static const char *raw_init(const BackendVtable *vt, Seat *seat,
raw->logctx, "main connection");
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
return dupstr(err);
}
if (port < 0)
@ -167,7 +167,7 @@ static const char *raw_init(const BackendVtable *vt, Seat *seat,
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 dupstr(err);
loghost = conf_get_str(conf, CONF_loghost);
if (*loghost) {

Просмотреть файл

@ -153,10 +153,10 @@ static const PlugVtable Rlogin_plugvt = {
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *rlogin_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
static char *rlogin_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
{
SockAddr *addr;
const char *err;
@ -188,7 +188,7 @@ static const char *rlogin_init(const BackendVtable *vt, Seat *seat,
rlogin->logctx, "rlogin connection");
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
return dupstr(err);
}
if (port < 0)
@ -200,7 +200,7 @@ static const char *rlogin_init(const BackendVtable *vt, Seat *seat,
rlogin->s = new_connection(addr, *realhost, port, true, false,
nodelay, keepalive, &rlogin->plug, conf);
if ((err = sk_socket_error(rlogin->s)) != NULL)
return err;
return dupstr(err);
loghost = conf_get_str(conf, CONF_loghost);
if (*loghost) {

22
ssh.c
Просмотреть файл

@ -704,7 +704,7 @@ static const PlugVtable Ssh_plugvt = {
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *connect_to_host(
static char *connect_to_host(
Ssh *ssh, const char *host, int port, char **realhost,
bool nodelay, bool keepalive)
{
@ -765,7 +765,7 @@ static const char *connect_to_host(
ssh->logctx, "SSH connection");
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
return dupstr(err);
}
ssh->fullhostname = dupstr(*realhost); /* save in case of GSSAPI */
@ -775,7 +775,7 @@ static const char *connect_to_host(
if ((err = sk_socket_error(ssh->s)) != NULL) {
ssh->s = NULL;
seat_notify_remote_exit(ssh->seat);
return err;
return dupstr(err);
}
}
@ -870,12 +870,11 @@ bool ssh_is_bare(Ssh *ssh)
*
* Returns an error message, or NULL on success.
*/
static const char *ssh_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
static char *ssh_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
{
const char *p;
Ssh *ssh;
ssh = snew(Ssh);
@ -906,15 +905,16 @@ static const char *ssh_init(const BackendVtable *vt, Seat *seat,
random_ref(); /* do this now - may be needed by sharing setup code */
ssh->need_random_unref = true;
p = connect_to_host(ssh, host, port, realhost, nodelay, keepalive);
if (p != NULL) {
char *conn_err = connect_to_host(
ssh, host, port, realhost, nodelay, keepalive);
if (conn_err) {
/* Call random_unref now instead of waiting until the caller
* frees this useless Ssh object, in case the caller is
* impatient and just exits without bothering, in which case
* the random seed won't be re-saved. */
ssh->need_random_unref = false;
random_unref();
return p;
return conn_err;
}
return NULL;

Просмотреть файл

@ -635,11 +635,11 @@ static void supdup_send_config(Supdup *supdup)
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *supdup_init(const BackendVtable *x, Seat *seat,
Backend **backend_handle,
LogContext *logctx, Conf *conf,
const char *host, int port, char **realhost,
bool nodelay, bool keepalive)
static char *supdup_init(const BackendVtable *x, Seat *seat,
Backend **backend_handle,
LogContext *logctx, Conf *conf,
const char *host, int port, char **realhost,
bool nodelay, bool keepalive)
{
static const PlugVtable fn_table = {
.log = supdup_log,
@ -696,7 +696,7 @@ static const char *supdup_init(const BackendVtable *x, Seat *seat,
addr = name_lookup(host, port, realhost, supdup->conf, addressfamily, NULL, "");
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
return dupstr(err);
}
if (port < 0)
@ -708,7 +708,7 @@ static const char *supdup_init(const BackendVtable *x, Seat *seat,
supdup->s = new_connection(addr, *realhost, port, false, true,
nodelay, keepalive, &supdup->plug, supdup->conf);
if ((err = sk_socket_error(supdup->s)) != NULL)
return err;
return dupstr(err);
supdup->pinger = pinger_new(supdup->conf, &supdup->backend);

Просмотреть файл

@ -678,10 +678,10 @@ static const PlugVtable Telnet_plugvt = {
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *telnet_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
static char *telnet_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
{
SockAddr *addr;
const char *err;
@ -720,7 +720,7 @@ static const char *telnet_init(const BackendVtable *vt, Seat *seat,
telnet->logctx, "Telnet connection");
if ((err = sk_addr_error(addr)) != NULL) {
sk_addr_free(addr);
return err;
return dupstr(err);
}
if (port < 0)
@ -732,7 +732,7 @@ static const char *telnet_init(const BackendVtable *vt, Seat *seat,
telnet->s = new_connection(addr, *realhost, port, false, true, nodelay,
keepalive, &telnet->plug, telnet->conf);
if ((err = sk_socket_error(telnet->s)) != NULL)
return err;
return dupstr(err);
telnet->pinger = pinger_new(telnet->conf, &telnet->backend);

Просмотреть файл

@ -32,12 +32,10 @@
#include "putty.h"
static const char *null_init(const BackendVtable *, Seat *, Backend **,
LogContext *, Conf *, const char *, int, char **,
bool, bool);
static const char *loop_init(const BackendVtable *, Seat *, Backend **,
LogContext *, Conf *, const char *, int, char **,
bool, bool);
static char *null_init(const BackendVtable *, Seat *, Backend **, LogContext *,
Conf *, const char *, int, char **, bool, bool);
static char *loop_init(const BackendVtable *, Seat *, Backend **, LogContext *,
Conf *, const char *, int, char **, bool, bool);
static void null_free(Backend *);
static void loop_free(Backend *);
static void null_reconfig(Backend *, Conf *);
@ -104,10 +102,10 @@ struct loop_state {
Backend backend;
};
static const char *null_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive) {
static char *null_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive) {
/* No local authentication phase in this protocol */
seat_set_trust_status(seat, false);
@ -115,10 +113,10 @@ static const char *null_init(const BackendVtable *vt, Seat *seat,
return NULL;
}
static const char *loop_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive) {
static char *loop_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive) {
struct loop_state *st = snew(struct loop_state);
/* No local authentication phase in this protocol */

Просмотреть файл

@ -5088,8 +5088,7 @@ static void gtk_seat_update_specials_menu(Seat *seat)
static void start_backend(GtkFrontend *inst)
{
const struct BackendVtable *vt;
char *realhost;
const char *error;
char *error, *realhost;
char *s;
vt = select_backend(inst->conf);
@ -5107,6 +5106,7 @@ static void start_backend(GtkFrontend *inst)
seat_connection_fatal(&inst->seat,
"Unable to open connection to %s:\n%s",
conf_dest(inst->conf), error);
sfree(error);
inst->exited = true;
return;
}

Просмотреть файл

@ -914,8 +914,7 @@ int main(int argc, char **argv)
*/
logctx = log_init(console_cli_logpolicy, conf);
{
const char *error;
char *realhost;
char *error, *realhost;
/* nodelay is only useful if stdin is a terminal device */
bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) && isatty(0);
@ -931,6 +930,7 @@ int main(int argc, char **argv)
conf_get_bool(conf, CONF_tcp_keepalives));
if (error) {
fprintf(stderr, "Unable to open connection:\n%s\n", error);
sfree(error);
return 1;
}
ldisc_create(conf, NULL, backend, plink_seat);

Просмотреть файл

@ -1270,10 +1270,10 @@ Backend *pty_backend_create(
* it gets the argv array from the global variable pty_argv, expecting
* that it will have been invoked by pterm.
*/
static const char *pty_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
static char *pty_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
{
const char *cmd = NULL;
struct ssh_ttymodes modes;

Просмотреть файл

@ -63,14 +63,15 @@ static void serial_select_result(int fd, int event);
static void serial_uxsel_setup(Serial *serial);
static void serial_try_write(Serial *serial);
static const char *serial_configure(Serial *serial, Conf *conf)
static char *serial_configure(Serial *serial, Conf *conf)
{
struct termios options;
int bflag, bval, speed, flow, parity;
const char *str;
if (serial->fd < 0)
return "Unable to reconfigure already-closed serial connection";
return dupstr("Unable to reconfigure already-closed "
"serial connection");
tcgetattr(serial->fd, &options);
@ -189,7 +190,8 @@ static const char *serial_configure(Serial *serial, Conf *conf)
case 6: options.c_cflag |= CS6; break;
case 7: options.c_cflag |= CS7; break;
case 8: options.c_cflag |= CS8; break;
default: return "Invalid number of data bits (need 5, 6, 7 or 8)";
default: return dupstr("Invalid number of data bits "
"(need 5, 6, 7 or 8)");
}
logeventf(serial->logctx, "Configuring %d data bits",
conf_get_int(conf, CONF_serdatabits));
@ -266,7 +268,7 @@ static const char *serial_configure(Serial *serial, Conf *conf)
options.c_cc[VTIME] = 0;
if (tcsetattr(serial->fd, TCSANOW, &options) < 0)
return "Unable to configure serial port";
return dupstr("Unable to configure serial port");
return NULL;
}
@ -279,13 +281,13 @@ static const char *serial_configure(Serial *serial, Conf *conf)
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *serial_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
static char *serial_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
{
Serial *serial;
const char *err;
char *err;
char *line;
/* No local authentication phase in this protocol */
@ -306,7 +308,7 @@ static const char *serial_init(const BackendVtable *vt, Seat *seat,
serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (serial->fd < 0)
return "Unable to open serial port";
return dupstr("Unable to open serial port");
cloexec(serial->fd);

Просмотреть файл

@ -368,9 +368,8 @@ static WinGuiSeat wgs = { .seat.vt = &win_seat_vt,
static void start_backend(void)
{
const struct BackendVtable *vt;
const char *error;
const char *title;
char *realhost;
char *error, *realhost;
int i;
/*
@ -397,6 +396,7 @@ static void start_backend(void)
char *str = dupprintf("%s Error", appname);
char *msg = dupprintf("Unable to open connection to\n%s\n%s",
conf_dest(conf), error);
sfree(error);
MessageBox(NULL, msg, str, MB_ICONERROR | MB_OK);
sfree(str);
sfree(msg);

Просмотреть файл

@ -492,8 +492,7 @@ int main(int argc, char **argv)
*/
winselcli_setup(); /* ensure event object exists */
{
const char *error;
char *realhost;
char *error, *realhost;
/* nodelay is only useful if stdin is a character device (console) */
bool nodelay = conf_get_bool(conf, CONF_tcp_nodelay) &&
(GetFileType(GetStdHandle(STD_INPUT_HANDLE)) == FILE_TYPE_CHAR);
@ -505,6 +504,7 @@ int main(int argc, char **argv)
conf_get_bool(conf, CONF_tcp_keepalives));
if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error);
sfree(error);
return 1;
}
sfree(realhost);

Просмотреть файл

@ -91,7 +91,7 @@ static void serial_sentdata(struct handle *h, size_t new_backlog, int err)
}
}
static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
static char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
{
DCB dcb;
COMMTIMEOUTS timeouts;
@ -134,7 +134,8 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
case 2: dcb.StopBits = ONESTOPBIT; str = "1 stop bit"; break;
case 3: dcb.StopBits = ONE5STOPBITS; str = "1.5 stop bits"; break;
case 4: dcb.StopBits = TWOSTOPBITS; str = "2 stop bits"; break;
default: return "Invalid number of stop bits (need 1, 1.5 or 2)";
default: return dupstr("Invalid number of stop bits "
"(need 1, 1.5 or 2)");
}
logeventf(serial->logctx, "Configuring %s", str);
@ -169,7 +170,7 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
logeventf(serial->logctx, "Configuring %s flow control", str);
if (!SetCommState(serport, &dcb))
return "Unable to configure serial port";
return dupstr("Unable to configure serial port");
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 0;
@ -177,7 +178,7 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(serport, &timeouts))
return "Unable to configure serial timeouts";
return dupstr("Unable to configure serial timeouts");
}
return NULL;
@ -191,14 +192,14 @@ static const char *serial_configure(Serial *serial, HANDLE serport, Conf *conf)
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
static const char *serial_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
static char *serial_init(const BackendVtable *vt, Seat *seat,
Backend **backend_handle, LogContext *logctx,
Conf *conf, const char *host, int port,
char **realhost, bool nodelay, bool keepalive)
{
Serial *serial;
HANDLE serport;
const char *err;
char *err;
char *serline;
/* No local authentication phase in this protocol */
@ -250,7 +251,7 @@ static const char *serial_init(const BackendVtable *vt, Seat *seat,
}
if (serport == INVALID_HANDLE_VALUE)
return "Unable to open serial port";
return dupstr("Unable to open serial port");
err = serial_configure(serial, serport, conf);
if (err)