Skip to content

Commit 9543be4

Browse files
committed
add initial source
1 parent 6c34080 commit 9543be4

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed

mqtt-exec.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
2+
#include <err.h>
3+
#include <getopt.h>
4+
#include <signal.h>
5+
#include <stdio.h>
6+
#include <stdlib.h>
7+
#include <string.h>
8+
#include <unistd.h>
9+
10+
#include <mosquitto.h>
11+
12+
struct userdata {
13+
char *topic;
14+
int command_argc;
15+
int verbose;
16+
char **command_argv;
17+
};
18+
19+
void log_cb(struct mosquitto *mosq, void *obj, int level, const char *str)
20+
{
21+
printf("%s\n", str);
22+
}
23+
24+
void message_cb(struct mosquitto *mosq, void *obj,
25+
const struct mosquitto_message *msg)
26+
{
27+
struct userdata *ud = (struct userdata *)obj;
28+
if (msg->payloadlen) {
29+
if (ud->command_argv && fork() == 0) {
30+
ud->command_argv[ud->command_argc-1] = msg->payload;
31+
execv(ud->command_argv[0], ud->command_argv);
32+
perror(ud->command_argv[0]);
33+
_exit(1);
34+
}
35+
}
36+
}
37+
38+
void connect_cb(struct mosquitto *mosq, void *obj, int result)
39+
{
40+
struct userdata *ud = (struct userdata *)obj;
41+
fflush(stderr);
42+
if (result == 0) {
43+
mosquitto_subscribe(mosq, NULL, ud->topic, 0);
44+
} else {
45+
fprintf(stderr, "%s\n", mosquitto_connack_string(result));
46+
}
47+
}
48+
49+
int usage(int retcode)
50+
{
51+
int major, minor, rev;
52+
53+
mosquitto_lib_version(&major, &minor, &rev);
54+
printf(
55+
"mqtt-exec - execute command on mqtt messages\n"
56+
"libmosquitto version: %d.%d.%d\n"
57+
"\n"
58+
"usage: mqtt-exec -t TOPIC [ARGS...] -- CMD [CMD ARGS...]\n"
59+
"\n", major, minor, rev);
60+
return retcode;
61+
}
62+
63+
static int perror_ret(const char *msg)
64+
{
65+
perror(msg);
66+
return 1;
67+
}
68+
69+
int main(int argc, char *argv[])
70+
{
71+
static struct option opts[] = {
72+
{"debug", no_argument, 0, 'd' },
73+
{"host", required_argument, 0, 'h' },
74+
{"keepalive", required_argument, 0, 'k' },
75+
{"port", required_argument, 0, 'p' },
76+
{"topic", required_argument, 0, 't' },
77+
{ 0, 0, 0, 0}
78+
};
79+
int debug = 0;
80+
const char *host = "localhost";
81+
int port = 1883;
82+
int keepalive = 60;
83+
int i, c, rc;
84+
struct userdata ud;
85+
char hostname[256];
86+
static char id[MOSQ_MQTT_ID_MAX_LENGTH+1];
87+
struct mosquitto *mosq = NULL;
88+
89+
memset(&ud, 0, sizeof(ud));
90+
91+
memset(hostname, 0, sizeof(hostname));
92+
memset(id, 0, sizeof(id));
93+
94+
while ((c = getopt_long(argc, argv, "dh:k:p:t:", opts, &i)) != -1) {
95+
printf("DEBUG: %x\n",c);
96+
switch(c) {
97+
case 'd':
98+
debug = 1;
99+
break;
100+
case 'h':
101+
host = optarg;
102+
break;
103+
case 'k':
104+
keepalive = atoi(optarg);
105+
break;
106+
case 'p':
107+
port = atoi(optarg);
108+
break;
109+
case 't':
110+
ud.topic = optarg;
111+
break;
112+
case '?':
113+
return usage(1);
114+
}
115+
}
116+
117+
if ((ud.topic == NULL) || (optind == argc))
118+
return usage(1);
119+
120+
ud.command_argc = (argc - optind) + 1;
121+
ud.command_argv = malloc((ud.command_argc + 1) * sizeof(char *));
122+
if (ud.command_argv == NULL)
123+
return perror_ret("malloc");
124+
125+
for (i=0; i < ud.command_argc; i++)
126+
ud.command_argv[i] = argv[optind+i];
127+
ud.command_argv[ud.command_argc-1] = NULL;
128+
ud.command_argv[ud.command_argc] = NULL;
129+
130+
/* generate an id */
131+
gethostname(hostname, sizeof(hostname)-1);
132+
snprintf(id, sizeof(id), "mqttexe/%x-%s", getpid(), hostname);
133+
134+
mosquitto_lib_init();
135+
mosq = mosquitto_new(id, true, &ud);
136+
if (mosq == NULL)
137+
return perror_ret("mosquitto_new");
138+
139+
if (debug) {
140+
printf("host=%s:%d\nid=%s\ntopic=%s\ncommand=%s\n",
141+
host, port, id, ud.topic, ud.command_argv[0]);
142+
mosquitto_log_callback_set(mosq, log_cb);
143+
}
144+
mosquitto_connect_callback_set(mosq, connect_cb);
145+
mosquitto_message_callback_set(mosq, message_cb);
146+
147+
/* let kernel reap the children */
148+
signal(SIGCHLD, SIG_IGN);
149+
150+
rc = mosquitto_connect(mosq, host, port, keepalive);
151+
if (rc != MOSQ_ERR_SUCCESS) {
152+
if (rc == MOSQ_ERR_ERRNO)
153+
return perror_ret("mosquitto_connect_bind");
154+
fprintf(stderr, "Unable to connect (%d)\n", rc);
155+
return 1;
156+
}
157+
158+
rc = mosquitto_loop_forever(mosq, -1, 1);
159+
160+
mosquitto_destroy(mosq);
161+
mosquitto_lib_cleanup();
162+
return rc;
163+
164+
}

0 commit comments

Comments
 (0)