kmscon: implement per-seat configuration
Sorry for the huge commit, but this reworks the whole configuration handler. We now provide conf_ctx contexts which contain a pointer to the backing storage and the config-options that are used. It is also possible to copy config-options now. So we can use the main-config as default value for seat-configurations. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
228a99d4bc
commit
06c6e56d4c
1009
src/conf.c
1009
src/conf.c
File diff suppressed because it is too large
Load Diff
129
src/conf.h
129
src/conf.h
@ -37,7 +37,67 @@
|
||||
#include <stdlib.h>
|
||||
#include "shl_misc.h"
|
||||
|
||||
/* parsed types */
|
||||
struct conf_type;
|
||||
struct conf_option;
|
||||
struct conf_ctx;
|
||||
|
||||
/* Conf Types */
|
||||
|
||||
#define CONF_HAS_ARG 0x0001
|
||||
|
||||
struct conf_type {
|
||||
unsigned int flags;
|
||||
void (*set_default) (struct conf_option *opt);
|
||||
void (*free) (struct conf_option *opt);
|
||||
int (*parse) (struct conf_option *opt, bool on, const char *arg);
|
||||
int (*copy) (struct conf_option *opt, const struct conf_option *src);
|
||||
};
|
||||
|
||||
/*
|
||||
* Bool: expects "mem" to point to a "bool"
|
||||
* Initial state is "false".
|
||||
*/
|
||||
|
||||
extern const struct conf_type conf_bool;
|
||||
|
||||
/*
|
||||
* Int: expects "mem" to point to an "int"
|
||||
* Initial state is "0".
|
||||
*/
|
||||
|
||||
extern const struct conf_type conf_int;
|
||||
|
||||
/*
|
||||
* Uint: expects "mem" to point to an "uint"
|
||||
* Initial state is "0"
|
||||
*/
|
||||
|
||||
extern const struct conf_type conf_uint;
|
||||
|
||||
/*
|
||||
* String: expects "mem" to point to an "char*"
|
||||
* Initial state is NULL. Memory is allocated by the parser and a string is
|
||||
* always zero-terminated.
|
||||
*/
|
||||
|
||||
extern const struct conf_type conf_string;
|
||||
|
||||
/*
|
||||
* Stringlist: expects "mem" to point to an "char**"
|
||||
* Initial state is NULL. The list is NULL-terminated and each entry is a
|
||||
* zero-terminated string. Memory is allocated by the parser.
|
||||
*/
|
||||
|
||||
extern const struct conf_type conf_string_list;
|
||||
|
||||
/*
|
||||
* Grabs: expects "mem" to point to an "struct conf_grab*"
|
||||
* Initial state is NULL. See below for the type definition. The memory for the
|
||||
* type is allocated by the parser.
|
||||
* Two small helpers are available to ease the use.
|
||||
*/
|
||||
|
||||
extern const struct conf_type conf_grab;
|
||||
|
||||
struct conf_grab {
|
||||
unsigned int num;
|
||||
@ -63,25 +123,36 @@ static inline bool conf_grab_matches(const struct conf_grab *grab,
|
||||
.keysyms = (uint32_t*[]) { (uint32_t[]) { (_sym) } }, \
|
||||
}
|
||||
|
||||
/* configuration parser */
|
||||
/*
|
||||
* Configuration Context
|
||||
* A configuration context is initialized with an array of config-options and
|
||||
* then can be used to parse different sources. The backing memory is managed by
|
||||
* the user, not by this context.
|
||||
* All options are set to their default values on startup and reset.
|
||||
*/
|
||||
|
||||
struct conf_type;
|
||||
struct conf_option;
|
||||
struct conf_ctx;
|
||||
|
||||
int conf_ctx_new(struct conf_ctx **out, const struct conf_option *opts,
|
||||
size_t onum, void *mem);
|
||||
void conf_ctx_free(struct conf_ctx *ctx);
|
||||
void conf_ctx_reset(struct conf_ctx *ctx);
|
||||
void *conf_ctx_get_mem(struct conf_ctx *ctx);
|
||||
|
||||
int conf_ctx_parse_ctx(struct conf_ctx *ctx, const struct conf_ctx *src);
|
||||
int conf_ctx_parse_argv(struct conf_ctx *ctx, int argc, char **argv);
|
||||
int conf_ctx_parse_file(struct conf_ctx *ctx, const char *format, ...);
|
||||
|
||||
/*
|
||||
* Configuration Options
|
||||
* A configuration option specifies the name of the option, the type, the
|
||||
* backing memory, the default value and more. Each option is represented by
|
||||
* this structure.
|
||||
*/
|
||||
|
||||
/* config option flags */
|
||||
#define CONF_DONE 0x0001
|
||||
#define CONF_LOCKED 0x0002
|
||||
|
||||
/* config type flags */
|
||||
#define CONF_HAS_ARG 0x0001
|
||||
|
||||
struct conf_type {
|
||||
unsigned int flags;
|
||||
int (*parse) (struct conf_option *opt, bool on, const char *arg);
|
||||
void (*free) (struct conf_option *opt);
|
||||
void (*set_default) (struct conf_option *opt);
|
||||
};
|
||||
|
||||
struct conf_option {
|
||||
unsigned int flags;
|
||||
char short_name;
|
||||
@ -144,32 +215,4 @@ struct conf_option {
|
||||
_mem, \
|
||||
_def)
|
||||
|
||||
void conf_free_value(struct conf_option *opt);
|
||||
int conf_parse_bool(struct conf_option *opt, bool on, const char *arg);
|
||||
void conf_default_bool(struct conf_option *opt);
|
||||
int conf_parse_int(struct conf_option *opt, bool on, const char *arg);
|
||||
void conf_default_int(struct conf_option *opt);
|
||||
int conf_parse_uint(struct conf_option *opt, bool on, const char *arg);
|
||||
void conf_default_uint(struct conf_option *opt);
|
||||
int conf_parse_string(struct conf_option *opt, bool on, const char *arg);
|
||||
void conf_default_string(struct conf_option *opt);
|
||||
int conf_parse_string_list(struct conf_option *opt, bool on, const char *arg);
|
||||
void conf_default_string_list(struct conf_option *opt);
|
||||
int conf_parse_grab(struct conf_option *opt, bool on, const char *arg);
|
||||
void conf_default_grab(struct conf_option *opt);
|
||||
|
||||
extern const struct conf_type conf_bool;
|
||||
extern const struct conf_type conf_int;
|
||||
extern const struct conf_type conf_uint;
|
||||
extern const struct conf_type conf_string;
|
||||
extern const struct conf_type conf_string_list;
|
||||
extern const struct conf_type conf_grab;
|
||||
|
||||
void conf_free(struct conf_option *opts, size_t len);
|
||||
int conf_parse_argv(struct conf_option *opts, size_t len,
|
||||
int argc, char **argv);
|
||||
int conf_parse_file(struct conf_option *opts, size_t len, const char *path);
|
||||
int conf_parse_file_f(struct conf_option *opts, size_t len,
|
||||
const char *format, ...);
|
||||
|
||||
#endif /* CONFIG_CONFIG_H */
|
||||
|
@ -38,8 +38,6 @@
|
||||
#include "shl_misc.h"
|
||||
|
||||
struct kmscon_conf_t kmscon_conf;
|
||||
static struct conf_option *kmscon_opt;
|
||||
static size_t kmscon_onum;
|
||||
|
||||
static void print_help()
|
||||
{
|
||||
@ -149,6 +147,21 @@ static void print_help()
|
||||
*/
|
||||
}
|
||||
|
||||
static void conf_default_vt(struct conf_option *opt)
|
||||
{
|
||||
opt->type->free(opt);
|
||||
*(void**)opt->mem = opt->def;
|
||||
}
|
||||
|
||||
static void conf_free_vt(struct conf_option *opt)
|
||||
{
|
||||
if (*(void**)opt->mem) {
|
||||
if (*(void**)opt->mem != opt->def)
|
||||
free(*(void**)opt->mem);
|
||||
*(void**)opt->mem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int conf_parse_vt(struct conf_option *opt, bool on, const char *arg)
|
||||
{
|
||||
static const char prefix[] = "/dev/";
|
||||
@ -178,18 +191,35 @@ static int conf_parse_vt(struct conf_option *opt, bool on, const char *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void conf_default_vt(struct conf_option *opt)
|
||||
static int conf_copy_vt(struct conf_option *opt,
|
||||
const struct conf_option *src)
|
||||
{
|
||||
*(void**)opt->mem = opt->def;
|
||||
char *val;
|
||||
|
||||
if (!*(void**)src->mem) {
|
||||
val = NULL;
|
||||
} else {
|
||||
val = strdup(*(void**)src->mem);
|
||||
if (!val)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
opt->type->free(opt);
|
||||
*(void**)opt->mem = val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct conf_type conf_vt = {
|
||||
.flags = CONF_HAS_ARG,
|
||||
.parse = conf_parse_vt,
|
||||
.free = conf_free_value,
|
||||
.set_default = conf_default_vt,
|
||||
.free = conf_free_vt,
|
||||
.parse = conf_parse_vt,
|
||||
.copy = conf_copy_vt,
|
||||
};
|
||||
|
||||
#define KMSCON_CONF_FROM_FIELD(_mem, _name) \
|
||||
shl_offsetof((_mem), struct kmscon_conf_t, _name)
|
||||
|
||||
static int aftercheck_debug(struct conf_option *opt, int argc, char **argv,
|
||||
int idx)
|
||||
{
|
||||
@ -281,20 +311,12 @@ static struct conf_grab def_grab_session_close =
|
||||
static struct conf_grab def_grab_terminal_new =
|
||||
CONF_SINGLE_GRAB(SHL_CONTROL_MASK | SHL_ALT_MASK, XKB_KEY_Return);
|
||||
|
||||
void kmscon_conf_init(struct kmscon_conf_t *conf)
|
||||
int kmscon_conf_new(struct conf_ctx **out, struct kmscon_conf_t *conf)
|
||||
{
|
||||
if (!conf)
|
||||
return;
|
||||
struct conf_ctx *ctx;
|
||||
int ret;
|
||||
|
||||
memset(conf, 0, sizeof(*conf));
|
||||
}
|
||||
|
||||
int kmscon_conf_new(struct conf_option **out, size_t *size_out,
|
||||
struct kmscon_conf_t *conf)
|
||||
{
|
||||
struct conf_option *opt;
|
||||
|
||||
if (!out || !size_out || !conf)
|
||||
if (!out || !conf)
|
||||
return -EINVAL;
|
||||
|
||||
struct conf_option options[] = {
|
||||
@ -349,71 +371,47 @@ int kmscon_conf_new(struct conf_option **out, size_t *size_out,
|
||||
CONF_OPTION_UINT(0, "font-dpi", NULL, &conf->font_ppi, 96),
|
||||
};
|
||||
|
||||
opt = malloc(sizeof(options));
|
||||
if (!opt)
|
||||
return -ENOMEM;
|
||||
memcpy(opt, options, sizeof(options));
|
||||
|
||||
*out = opt;
|
||||
*size_out = sizeof(options) / sizeof(*options);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kmscon_conf_free(struct conf_option *opt, size_t onum)
|
||||
{
|
||||
if (!opt || !onum)
|
||||
return;
|
||||
|
||||
conf_free(opt, onum);
|
||||
free(opt);
|
||||
}
|
||||
|
||||
int kmscon_conf_parse_argv(struct conf_option *opt, size_t onum,
|
||||
int argc, char **argv)
|
||||
{
|
||||
if (!opt || !onum)
|
||||
return -EINVAL;
|
||||
|
||||
return conf_parse_argv(opt, onum, argc, argv);
|
||||
}
|
||||
|
||||
int kmscon_load_config(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!kmscon_opt || !kmscon_onum) {
|
||||
kmscon_conf_init(&kmscon_conf);
|
||||
ret = kmscon_conf_new(&kmscon_opt, &kmscon_onum, &kmscon_conf);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = kmscon_conf_parse_argv(kmscon_opt, kmscon_onum, argc, argv);
|
||||
ret = conf_ctx_new(&ctx, options, sizeof(options) / sizeof(*options),
|
||||
conf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (KMSCON_CONF_BOOL(exit))
|
||||
*out = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kmscon_conf_free(struct conf_ctx *ctx)
|
||||
{
|
||||
conf_ctx_free(ctx);
|
||||
}
|
||||
|
||||
int kmscon_conf_load_main(struct conf_ctx *ctx, int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = conf_ctx_parse_argv(ctx, argc, argv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (kmscon_conf.exit)
|
||||
return 0;
|
||||
|
||||
if (!KMSCON_CONF_BOOL(debug) && !KMSCON_CONF_BOOL(verbose) &&
|
||||
KMSCON_CONF_BOOL(silent))
|
||||
if (!kmscon_conf.debug && !kmscon_conf.verbose && kmscon_conf.silent)
|
||||
log_set_config(&LOG_CONFIG_WARNING(0, 0, 0, 0));
|
||||
else
|
||||
log_set_config(&LOG_CONFIG_INFO(KMSCON_CONF_BOOL(debug),
|
||||
KMSCON_CONF_BOOL(verbose)));
|
||||
log_set_config(&LOG_CONFIG_INFO(kmscon_conf.debug,
|
||||
kmscon_conf.verbose));
|
||||
|
||||
log_print_init("kmscon");
|
||||
|
||||
ret = conf_parse_file_f(kmscon_opt, kmscon_onum,
|
||||
"/etc/kmscon/kmscon.conf");
|
||||
ret = conf_ctx_parse_file(ctx, "/etc/kmscon/kmscon.conf");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* TODO: Deprecated! Remove this! */
|
||||
if (!access("/etc/kmscon.conf", F_OK)) {
|
||||
log_error("/etc/kmscon.conf is deprecated, please use /etc/kmscon/kmscon.conf");
|
||||
ret = conf_parse_file_f(kmscon_opt, kmscon_onum,
|
||||
"/etc/kmscon.conf");
|
||||
ret = conf_ctx_parse_file(ctx, "/etc/kmscon.conf");
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -421,12 +419,23 @@ int kmscon_load_config(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kmscon_free_config(void)
|
||||
int kmscon_conf_load_seat(struct conf_ctx *ctx, const struct conf_ctx *main,
|
||||
const char *seat)
|
||||
{
|
||||
if (!kmscon_opt || !kmscon_onum)
|
||||
return;
|
||||
int ret;
|
||||
|
||||
kmscon_conf_free(kmscon_opt, kmscon_onum);
|
||||
kmscon_opt = NULL;
|
||||
kmscon_onum = 0;
|
||||
if (!ctx || !main || !seat)
|
||||
return -EINVAL;
|
||||
|
||||
log_debug("parsing seat configuration for seat %s", seat);
|
||||
|
||||
ret = conf_ctx_parse_ctx(ctx, main);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = conf_ctx_parse_file(ctx, "/etc/kmscon/%s.seat.conf", seat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -131,32 +131,10 @@ struct kmscon_conf_t {
|
||||
|
||||
extern struct kmscon_conf_t kmscon_conf;
|
||||
|
||||
void kmscon_conf_init(struct kmscon_conf_t *conf);
|
||||
int kmscon_conf_new(struct conf_option **out, size_t *size_out,
|
||||
struct kmscon_conf_t *conf);
|
||||
void kmscon_conf_free(struct conf_option *opt, size_t onum);
|
||||
|
||||
int kmscon_conf_parse_argv(struct conf_option *opt, size_t onum,
|
||||
int argc, char **argv);
|
||||
|
||||
int kmscon_load_config(int argc, char **argv);
|
||||
void kmscon_free_config(void);
|
||||
|
||||
#define KMSCON_CONF_FROM_FIELD(_ptr, _field) \
|
||||
shl_offsetof(_ptr, struct kmscon_conf_t, _field)
|
||||
#define KMSCON_CONF_OFFSET(_name) \
|
||||
offsetof(struct kmscon_conf_t, _name)
|
||||
#define KMSCON_CONF(_name, _type) \
|
||||
(*((_type*)(((char*)&kmscon_conf) + KMSCON_CONF_OFFSET(_name))))
|
||||
#define KMSCON_CONF_BOOL(_name) \
|
||||
KMSCON_CONF(_name, bool)
|
||||
#define KMSCON_CONF_UINT(_name) \
|
||||
KMSCON_CONF(_name, unsigned int)
|
||||
#define KMSCON_CONF_STRING(_name) \
|
||||
KMSCON_CONF(_name, char*)
|
||||
#define KMSCON_CONF_GRAB(_name) \
|
||||
KMSCON_CONF(_name, struct conf_grab*)
|
||||
#define KMSCON_CONF_STRINGLIST(_name) \
|
||||
KMSCON_CONF(_name, char**)
|
||||
int kmscon_conf_new(struct conf_ctx **out, struct kmscon_conf_t *conf);
|
||||
void kmscon_conf_free(struct conf_ctx *ctx);
|
||||
int kmscon_conf_load_main(struct conf_ctx *ctx, int argc, char **argv);
|
||||
int kmscon_conf_load_seat(struct conf_ctx *ctx, const struct conf_ctx *main,
|
||||
const char *seat);
|
||||
|
||||
#endif /* KMSCON_MAIN_H */
|
||||
|
@ -56,10 +56,14 @@ struct app_seat {
|
||||
bool awake;
|
||||
char *name;
|
||||
struct kmscon_seat *seat;
|
||||
struct conf_ctx *conf_ctx;
|
||||
struct kmscon_conf_t *conf;
|
||||
struct shl_dlist videos;
|
||||
};
|
||||
|
||||
struct kmscon_app {
|
||||
struct conf_ctx *conf;
|
||||
|
||||
struct ev_eloop *eloop;
|
||||
struct ev_eloop *vt_eloop;
|
||||
unsigned int vt_exit_count;
|
||||
@ -113,11 +117,11 @@ static int app_seat_new(struct kmscon_app *app, struct app_seat **out,
|
||||
bool found;
|
||||
|
||||
found = false;
|
||||
if (KMSCON_CONF_BOOL(all_seats)) {
|
||||
if (kmscon_conf.all_seats) {
|
||||
found = true;
|
||||
} else {
|
||||
for (i = 0; KMSCON_CONF_STRINGLIST(seats)[i]; ++i) {
|
||||
if (!strcmp(KMSCON_CONF_STRINGLIST(seats)[i], sname)) {
|
||||
for (i = 0; kmscon_conf.seats[i]; ++i) {
|
||||
if (!strcmp(kmscon_conf.seats[i], sname)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@ -148,13 +152,15 @@ static int app_seat_new(struct kmscon_app *app, struct app_seat **out,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = kmscon_seat_new(&seat->seat, app->eloop, app->vtm, sname,
|
||||
app_seat_event, seat);
|
||||
ret = kmscon_seat_new(&seat->seat, app->conf, app->eloop, app->vtm,
|
||||
sname, app_seat_event, seat);
|
||||
if (ret) {
|
||||
log_error("cannot create seat object on seat %s: %d",
|
||||
sname, ret);
|
||||
goto err_name;
|
||||
}
|
||||
seat->conf_ctx = kmscon_seat_get_conf(seat->seat);
|
||||
seat->conf = conf_ctx_get_mem(seat->conf_ctx);
|
||||
|
||||
shl_dlist_link(&app->seats, &seat->list);
|
||||
*out = seat;
|
||||
@ -202,7 +208,7 @@ static int app_seat_add_video(struct app_seat *seat,
|
||||
unsigned int mode;
|
||||
struct app_video *vid;
|
||||
|
||||
if (KMSCON_CONF_BOOL(fbdev)) {
|
||||
if (seat->conf->fbdev) {
|
||||
if (type != UTERM_MONITOR_FBDEV &&
|
||||
type != UTERM_MONITOR_FBDEV_DRM) {
|
||||
log_info("ignoring video device %s on seat %s as it is not an fbdev device",
|
||||
@ -237,7 +243,7 @@ static int app_seat_add_video(struct app_seat *seat,
|
||||
}
|
||||
|
||||
if (type == UTERM_MONITOR_DRM) {
|
||||
if (KMSCON_CONF_BOOL(dumb))
|
||||
if (seat->conf->dumb)
|
||||
mode = UTERM_VIDEO_DUMB;
|
||||
else
|
||||
mode = UTERM_VIDEO_DRM;
|
||||
@ -398,10 +404,11 @@ static void destroy_app(struct kmscon_app *app)
|
||||
ev_eloop_unref(app->eloop);
|
||||
}
|
||||
|
||||
static int setup_app(struct kmscon_app *app)
|
||||
static int setup_app(struct kmscon_app *app, struct conf_ctx *conf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
app->conf = conf;
|
||||
shl_dlist_init(&app->seats);
|
||||
|
||||
ret = ev_eloop_new(&app->eloop, log_llog);
|
||||
@ -455,16 +462,23 @@ err_app:
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret;
|
||||
struct conf_ctx *conf;
|
||||
struct kmscon_app app;
|
||||
|
||||
ret = kmscon_load_config(argc, argv);
|
||||
ret = kmscon_conf_new(&conf, &kmscon_conf);
|
||||
if (ret) {
|
||||
log_error("cannot parse configuration: %d", ret);
|
||||
log_error("cannot create configuration: %d", ret);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (KMSCON_CONF_BOOL(exit)) {
|
||||
kmscon_free_config();
|
||||
ret = kmscon_conf_load_main(conf, argc, argv);
|
||||
if (ret) {
|
||||
log_error("cannot load configuration: %d", ret);
|
||||
goto err_conf;
|
||||
}
|
||||
|
||||
if (kmscon_conf.exit) {
|
||||
kmscon_conf_free(conf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -472,18 +486,18 @@ int main(int argc, char **argv)
|
||||
kmscon_text_load_all();
|
||||
|
||||
memset(&app, 0, sizeof(app));
|
||||
ret = setup_app(&app);
|
||||
ret = setup_app(&app, conf);
|
||||
if (ret)
|
||||
goto err_unload;
|
||||
|
||||
if (KMSCON_CONF_BOOL(switchvt)) {
|
||||
if (kmscon_conf.switchvt) {
|
||||
log_debug("activating VTs during startup");
|
||||
uterm_vt_master_activate_all(app.vtm);
|
||||
}
|
||||
|
||||
ev_eloop_run(app.eloop, -1);
|
||||
|
||||
if (KMSCON_CONF_BOOL(switchvt)) {
|
||||
if (kmscon_conf.switchvt) {
|
||||
/* The VT subsystem needs to acknowledge the VT-leave so if it
|
||||
* returns -EINPROGRESS we need to wait for the VT-leave SIGUSR2
|
||||
* signal to arrive. Therefore, we use a separate eloop object
|
||||
@ -509,9 +523,9 @@ int main(int argc, char **argv)
|
||||
err_unload:
|
||||
kmscon_text_unload_all();
|
||||
kmscon_font_unload_all();
|
||||
err_conf:
|
||||
kmscon_conf_free(conf);
|
||||
err_out:
|
||||
kmscon_free_config();
|
||||
|
||||
if (ret)
|
||||
log_err("cannot initialize kmscon, errno %d: %s",
|
||||
ret, strerror(-ret));
|
||||
|
@ -67,6 +67,9 @@ struct kmscon_seat {
|
||||
struct ev_eloop *eloop;
|
||||
struct uterm_vt_master *vtm;
|
||||
|
||||
struct kmscon_conf_t conf;
|
||||
struct conf_ctx *conf_ctx;
|
||||
|
||||
char *name;
|
||||
bool awake;
|
||||
struct uterm_input *input;
|
||||
@ -355,6 +358,7 @@ static void seat_input_event(struct uterm_input *input,
|
||||
}
|
||||
|
||||
int kmscon_seat_new(struct kmscon_seat **out,
|
||||
struct conf_ctx *main_conf,
|
||||
struct ev_eloop *eloop,
|
||||
struct uterm_vt_master *vtm,
|
||||
const char *seatname,
|
||||
@ -386,6 +390,19 @@ int kmscon_seat_new(struct kmscon_seat **out,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ret = kmscon_conf_new(&seat->conf_ctx, &seat->conf);
|
||||
if (ret) {
|
||||
log_error("cannot create seat configuration object: %d", ret);
|
||||
goto err_name;
|
||||
}
|
||||
|
||||
ret = kmscon_conf_load_seat(seat->conf_ctx, main_conf, seat->name);
|
||||
if (ret) {
|
||||
log_error("cannot parse seat configuration on seat %s: %d",
|
||||
seat->name, ret);
|
||||
goto err_conf;
|
||||
}
|
||||
|
||||
ret = uterm_input_new(&seat->input, seat->eloop,
|
||||
kmscon_conf.xkb_layout,
|
||||
kmscon_conf.xkb_variant,
|
||||
@ -393,7 +410,7 @@ int kmscon_seat_new(struct kmscon_seat **out,
|
||||
kmscon_conf.xkb_repeat_delay,
|
||||
kmscon_conf.xkb_repeat_rate);
|
||||
if (ret)
|
||||
goto err_name;
|
||||
goto err_conf;
|
||||
|
||||
ret = uterm_input_register_cb(seat->input, seat_input_event, seat);
|
||||
if (ret)
|
||||
@ -445,6 +462,8 @@ err_input_cb:
|
||||
uterm_input_unregister_cb(seat->input, seat_input_event, seat);
|
||||
err_input:
|
||||
uterm_input_unref(seat->input);
|
||||
err_conf:
|
||||
kmscon_conf_free(seat->conf_ctx);
|
||||
err_name:
|
||||
free(seat->name);
|
||||
err_free:
|
||||
@ -477,6 +496,7 @@ void kmscon_seat_free(struct kmscon_seat *seat)
|
||||
uterm_vt_deallocate(seat->vt);
|
||||
uterm_input_unregister_cb(seat->input, seat_input_event, seat);
|
||||
uterm_input_unref(seat->input);
|
||||
kmscon_conf_free(seat->conf_ctx);
|
||||
free(seat->name);
|
||||
uterm_vt_master_unref(seat->vtm);
|
||||
ev_eloop_unref(seat->eloop);
|
||||
@ -549,6 +569,14 @@ struct ev_eloop *kmscon_seat_get_eloop(struct kmscon_seat *seat)
|
||||
return seat->eloop;
|
||||
}
|
||||
|
||||
struct conf_ctx *kmscon_seat_get_conf(struct kmscon_seat *seat)
|
||||
{
|
||||
if (!seat)
|
||||
return NULL;
|
||||
|
||||
return seat->conf_ctx;
|
||||
}
|
||||
|
||||
int kmscon_seat_register_session(struct kmscon_seat *seat,
|
||||
struct kmscon_session **out,
|
||||
kmscon_session_cb_t cb,
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include "conf.h"
|
||||
#include "eloop.h"
|
||||
#include "uterm.h"
|
||||
|
||||
@ -63,6 +64,7 @@ typedef void (*kmscon_session_cb_t) (struct kmscon_session *session,
|
||||
void *data);
|
||||
|
||||
int kmscon_seat_new(struct kmscon_seat **out,
|
||||
struct conf_ctx *main_conf,
|
||||
struct ev_eloop *eloop,
|
||||
struct uterm_vt_master *vtm,
|
||||
const char *seatname,
|
||||
@ -80,6 +82,7 @@ void kmscon_seat_remove_input(struct kmscon_seat *seat, const char *node);
|
||||
const char *kmscon_seat_get_name(struct kmscon_seat *seat);
|
||||
struct uterm_input *kmscon_seat_get_input(struct kmscon_seat *seat);
|
||||
struct ev_eloop *kmscon_seat_get_eloop(struct kmscon_seat *seat);
|
||||
struct conf_ctx *kmscon_seat_get_conf(struct kmscon_seat *seat);
|
||||
|
||||
int kmscon_seat_register_session(struct kmscon_seat *seat,
|
||||
struct kmscon_session **out,
|
||||
|
28
src/pty.c
28
src/pty.c
@ -39,6 +39,7 @@
|
||||
#include "eloop.h"
|
||||
#include "log.h"
|
||||
#include "pty.h"
|
||||
#include "shl_misc.h"
|
||||
#include "shl_ring.h"
|
||||
|
||||
#define LOG_SUBSYSTEM "pty"
|
||||
@ -141,35 +142,18 @@ int kmscon_pty_set_term(struct kmscon_pty *pty, const char *term)
|
||||
|
||||
int kmscon_pty_set_argv(struct kmscon_pty *pty, char **argv)
|
||||
{
|
||||
char **t, *off;
|
||||
unsigned int size, i;
|
||||
char **t;
|
||||
int ret;
|
||||
|
||||
if (!pty || !argv || !*argv || !**argv)
|
||||
return -EINVAL;
|
||||
|
||||
size = 0;
|
||||
for (i = 0; argv[i]; ++i)
|
||||
size += strlen(argv[i]) + 1;
|
||||
++i;
|
||||
ret = shl_dup_array(&t, argv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
size += i * sizeof(char*);
|
||||
|
||||
t = malloc(size);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
free(pty->argv);
|
||||
pty->argv = t;
|
||||
|
||||
off = (char*)t + i * sizeof(char*);
|
||||
while (*argv) {
|
||||
*t++ = off;
|
||||
for (i = 0; argv[0][i]; ++i)
|
||||
*off++ = argv[0][i];
|
||||
*off++ = 0;
|
||||
argv++;
|
||||
}
|
||||
*t = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -140,6 +140,39 @@ static inline int shl_split_string(const char *arg, char ***out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int shl_dup_array(char ***out, char **argv)
|
||||
{
|
||||
char **t, *off;
|
||||
unsigned int size, i;
|
||||
|
||||
if (!out || !argv)
|
||||
return -EINVAL;
|
||||
|
||||
size = 0;
|
||||
for (i = 0; argv[i]; ++i)
|
||||
size += strlen(argv[i]) + 1;
|
||||
++i;
|
||||
|
||||
size += i * sizeof(char*);
|
||||
|
||||
t = malloc(size);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
*out = t;
|
||||
|
||||
off = (char*)t + i * sizeof(char*);
|
||||
while (*argv) {
|
||||
*t++ = off;
|
||||
for (i = 0; argv[0][i]; ++i)
|
||||
*off++ = argv[0][i];
|
||||
*off++ = 0;
|
||||
argv++;
|
||||
}
|
||||
*t = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: xkbcommon should provide these flags!
|
||||
* We currently copy them into each library API we use so we need to keep
|
||||
* them in sync. Currently, they're used in uterm-input and tsm-vte. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user