LIRC libraries
Linux Infrared Remote Control
irexec.cpp
/****************************************************************************
** irexec.c ****************************************************************
****************************************************************************
*
* irexec - execute programs according to the pressed remote control buttons
*
* Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu>
* Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de>
*
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "lirc_client.h"
#include "lirc_log.h"
static const logchannel_t logchannel = LOG_APP;
static const char* const USAGE =
"Usage: irexec [options] [lircrc config_file]\n"
"\t-d --daemon\t\tRun in background\n"
"\t-D --loglevel=level\t'error', 'info', 'notice',... or 0..10\n"
"\t-n --name=progname\tUse this program name for lircrc matching\n"
"\t-h --help\t\tDisplay usage summary\n"
"\t-v --version\t\tDisplay version\n";
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ "daemon", no_argument, NULL, 'd' },
{ "name", required_argument, NULL, 'n' },
{ "loglevel", required_argument, NULL, 'D' },
{ 0, 0, 0, 0 }
};
static int opt_daemonize = 0;
static loglevel_t opt_loglevel = LIRC_NOLOG;
static const char* opt_progname = "irexec";
static char path[256] = {0};
static void run_command(const char* cmd)
{
pid_t pid1;
pid_t pid2;
pid1 = fork();
if (pid1 < 0) {
log_perror_err("Cannot fork");
perror("Cannot fork()");
exit(EXIT_FAILURE);
}
if (pid1 == 0) {
pid2 = fork();
if (pid2 < 0) {
log_perror_err("Cannot do secondary fork()");
exit(EXIT_FAILURE);
}
if (pid2 == 0) {
log_debug("Execing command \"%s\"", cmd);
char* const vp[] = {strdup(SH_PATH),
strdup("-c"),
strdup(cmd),
NULL
};
execvp(SH_PATH, vp);
/* not reached, unless there was an error */
log_perror_err("execvp failed");
fputs("execvp failed\n", stderr);
exit(EXIT_FAILURE);
} else {
waitpid(pid2, NULL, WNOHANG);
exit(0);
}
} else {
waitpid(pid1, NULL, 0);
}
}
static void process_input(struct lirc_config* config)
{
char* code;
char* c;
int r;
while (lirc_nextcode(&code) == 0) {
if (code == NULL)
continue;
r = lirc_code2char(config, code, &c);
while (r == 0 && c != NULL) {
run_command(c);
r = lirc_code2char(config, code, &c);
}
free(code);
if (r == -1)
break;
}
}
int irexec(const char* configfile)
{
struct lirc_config* config;
if (opt_daemonize) {
if (daemon(0, 0) == -1) {
perror("Can't daemonize");
return EXIT_FAILURE;
}
}
if (lirc_init(opt_progname, opt_daemonize ? 0 : 1) == -1)
return EXIT_FAILURE;
if (lirc_readconfig(configfile, &config, NULL) != 0) {
fputs("Cannot parse config file\n", stderr);
return EXIT_FAILURE;
}
lirc_log_get_clientlog("irexec", path, sizeof(path));
unlink(path);
lirc_log_open("irexec", 1, opt_loglevel);
process_input(config);
lirc_freeconfig(config);
return EXIT_SUCCESS;
}
int main(int argc, char* argv[])
{
int c;
while ((c = getopt_long(argc, argv, "D:hvdn:", options, NULL)) != -1) {
switch (c) {
case 'h':
puts(USAGE);
return EXIT_SUCCESS;
case 'v':
puts("irexec " VERSION);
return EXIT_SUCCESS;
case 'd':
opt_daemonize = 1;
break;
case 'n':
opt_progname = optarg;
break;
case 'D':
opt_loglevel = string2loglevel(optarg);
break;
default:
fputs(USAGE, stderr);
return EXIT_FAILURE;
}
}
if (optind < argc - 1) {
fputs("Too many arguments\n", stderr);
return EXIT_FAILURE;
}
if (opt_loglevel == LIRC_BADLEVEL) {
fprintf(stderr, "Bad debug level: %s\n", optarg);
return EXIT_FAILURE;
}
return irexec(optind != argc ? argv[optind] : NULL);
}
int lirc_deinit(void)
Release resources allocated by lirc_init(), basically disconnect from socket.
Definition: lirc_client.c:365
int lirc_readconfig(const char *file, struct lirc_config **config, int(check)(char *s))
Parse a lircrc configuration file.
Definition: lirc_client.c:1447
void lirc_freeconfig(struct lirc_config *config)
Deallocate an object retrieved using lirc_readconfig().
Definition: lirc_client.c:1534
int lirc_code2char(struct lirc_config *config, char *code, char **string)
Translate a code string to an application string using .lircrc.
Definition: lirc_client.c:1813
int lirc_nextcode(char **code)
Get next available code from the lircd daemon.
Definition: lirc_client.c:1879
int lirc_init(const char *prog, int verbose)
Initial setup: connect to lircd socket.
Definition: lirc_client.c:344
3-rd party application interface.
loglevel_t string2loglevel(const char *s)
Convert a string, either a number or 'info', 'trace1', error etc.
Definition: lirc_log.c:234
void lirc_log_set_file(const char *s)
Set logfile.
Definition: lirc_log.c:84
int lirc_log_open(const char *_progname, int _nodaemon, loglevel_t level)
Open the log for upcoming logging.
Definition: lirc_log.c:95
int lirc_log_get_clientlog(const char *basename, char *buffer, ssize_t size)
Retrieve a client path for logging according to freedesktop specs.
Definition: lirc_log.c:332
Logging functionality.
#define log_debug(fmt,...)
Log a debug message.
Definition: lirc_log.h:124
loglevel_t
The defined loglevels.
Definition: lirc_log.h:36
#define log_perror_err(fmt,...)
perror wrapper logging with level LIRC_ERROR.
Definition: lirc_log.h:89
logchannel_t
Log channels used to filter messages.
Definition: lirc_log.h:53