blob: 8dde1cdf4e0f4f9743fa118f867f070e9f9bd621 [file] [log] [blame]
Deokgyu Yang2c7e86b2020-04-28 10:56:11 +09001/*
2 * wiringPiD.c:
3 * Copyright (c) 2012-2017 Gordon Henderson
4 ***********************************************************************
5 * This file is part of wiringPi:
6 * https://projects.drogon.net/raspberry-pi/wiringpi/
7 *
8 * wiringPi is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * wiringPi is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with wiringPi. If not, see <http://www.gnu.org/licenses/>.
20 ***********************************************************************
21 */
22
23#include <arpa/inet.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <stdint.h>
27#include <unistd.h>
28#include <string.h>
29#include <stdarg.h>
30#include <syslog.h>
31#include <signal.h>
32#include <errno.h>
33
34#include <wiringPi.h>
35#include <wpiExtensions.h>
36
37#include "drcNetCmd.h"
38#include "network.h"
39#include "runRemote.h"
40#include "daemonise.h"
41
42
43#define PIDFILE "/var/run/wiringPiD.pid"
44
45
46// Globals
47
48static const char *usage = "[-h] [-d] [-g | -1 | -z] [[-x extension:pin:params] ...] password" ;
49static int doDaemon = FALSE ;
50
51//
52
53static void logMsg (const char *message, ...)
54{
55 va_list argp ;
56 char buffer [1024] ;
57
58 va_start (argp, message) ;
59 vsnprintf (buffer, 1023, message, argp) ;
60 va_end (argp) ;
61
62 if (doDaemon)
63 syslog (LOG_DAEMON | LOG_INFO, "%s", buffer) ;
64 else
65 printf ("%s\n", buffer) ;
66}
67
68
69/*
70 * sigHandler:
71 * setupSigHandler:
72 * Somehing has happened that would normally terminate the program so try
73 * to close down nicely.
74 *********************************************************************************
75 */
76
77void sigHandler (int sig)
78{
79 logMsg ("Exiting on signal %d: %s", sig, strsignal (sig)) ;
80 (void)unlink (PIDFILE) ;
81 exit (EXIT_FAILURE) ;
82}
83
84void setupSigHandler (void)
85{
86 struct sigaction action ;
87
88 sigemptyset (&action.sa_mask) ;
89 action.sa_flags = 0 ;
90
91// Ignore what we can
92
93 action.sa_handler = SIG_IGN ;
94
95 sigaction (SIGHUP, &action, NULL) ;
96 sigaction (SIGTTIN, &action, NULL) ;
97 sigaction (SIGTTOU, &action, NULL) ;
98
99// Trap what we can to exit gracefully
100
101 action.sa_handler = sigHandler ;
102
103 sigaction (SIGINT, &action, NULL) ;
104 sigaction (SIGQUIT, &action, NULL) ;
105 sigaction (SIGILL, &action, NULL) ;
106 sigaction (SIGABRT, &action, NULL) ;
107 sigaction (SIGFPE, &action, NULL) ;
108 sigaction (SIGSEGV, &action, NULL) ;
109 sigaction (SIGPIPE, &action, NULL) ;
110 sigaction (SIGALRM, &action, NULL) ;
111 sigaction (SIGTERM, &action, NULL) ;
112 sigaction (SIGUSR1, &action, NULL) ;
113 sigaction (SIGUSR2, &action, NULL) ;
114 sigaction (SIGCHLD, &action, NULL) ;
115 sigaction (SIGTSTP, &action, NULL) ;
116 sigaction (SIGBUS, &action, NULL) ;
117}
118
119
120/*
121 * The works...
122 *********************************************************************************
123 */
124
125int main (int argc, char *argv [])
126{
127 int clientFd ;
128 char *p, *password ;
129 int i ;
130 int port = DEFAULT_SERVER_PORT ;
131 int wpiSetup = 0 ;
132
133 if (argc < 2)
134 {
135 fprintf (stderr, "Usage: %s %s\n", argv [0], usage) ;
136 exit (EXIT_FAILURE) ;
137 }
138
139// Help?
140
141 if (strcasecmp (argv [1], "-h") == 0)
142 {
143 printf ("Usage: %s %s\n", argv [0], usage) ;
144 return 0 ;
145 }
146
147// Daemonize?
148// Must come before the other args as e.g. some extensions
149// open files which get closed on daemonise...
150
151 if (strcasecmp (argv [1], "-d") == 0)
152 {
153 if (geteuid () != 0)
154 {
155 fprintf (stderr, "%s: Must be root to run as a daemon.\n", argv [0]) ;
156 exit (EXIT_FAILURE) ;
157 }
158
159 doDaemon = TRUE ;
160 daemonise (PIDFILE) ;
161
162 for (i = 2 ; i < argc ; ++i)
163 argv [i - 1] = argv [i] ;
164 --argc ;
165 }
166
167// Scan all other arguments
168
169 while (*argv [1] == '-')
170 {
171
172// Look for wiringPi setup arguments:
173// Same as the gpio command and rtb.
174
175// -g - bcm_gpio
176
177 if (strcasecmp (argv [1], "-g") == 0)
178 {
179 if (wpiSetup == 0)
180 {
181 logMsg ("BCM_GPIO mode selected") ;
182 wiringPiSetupGpio () ;
183 }
184
185 for (i = 2 ; i < argc ; ++i)
186 argv [i - 1] = argv [i] ;
187 --argc ;
188 ++wpiSetup ;
189 continue ;
190 }
191
192// -1 - physical pins
193
194 if (strcasecmp (argv [1], "-1") == 0)
195 {
196 if (wpiSetup == 0)
197 {
198 logMsg ("GPIO-PHYS mode selected") ;
199 wiringPiSetupPhys () ;
200 }
201
202 for (i = 2 ; i < argc ; ++i)
203 argv [i - 1] = argv [i] ;
204 --argc ;
205 ++wpiSetup ;
206 continue ;
207 }
208
209// -z - no wiringPi - blocks remotes accessing local pins
210
211 if (strcasecmp (argv [1], "-z") == 0)
212 {
213 if (wpiSetup == 0)
214 logMsg ("No GPIO mode selected") ;
215
216 for (i = 2 ; i < argc ; ++i)
217 argv [i - 1] = argv [i] ;
218 --argc ;
219 noLocalPins = TRUE ;
220 ++wpiSetup ;
221 continue ;
222 }
223
224// -p to select the port
225
226 if (strcasecmp (argv [1], "-p") == 0)
227 {
228 if (argc < 3)
229 {
230 logMsg ("-p missing extension port") ;
231 exit (EXIT_FAILURE) ;
232 }
233
234 logMsg ("Setting port to: %s", argv [2]) ;
235
236 port = atoi (argv [2]) ;
237 if ((port < 1) || (port > 65535))
238 {
239 logMsg ("Invalid server port: %d", port) ;
240 exit (EXIT_FAILURE) ;
241 }
242
243// Shift args down by 2
244
245 for (i = 3 ; i < argc ; ++i)
246 argv [i - 2] = argv [i] ;
247 argc -= 2 ;
248
249 continue ;
250 }
251
252// Check for -x argument to load in a new extension
253// -x extension:base:args
254// Can load many modules to extend the daemon.
255
256 if (strcasecmp (argv [1], "-x") == 0)
257 {
258 if (argc < 3)
259 {
260 logMsg ("-x missing extension name:data:etc.") ;
261 exit (EXIT_FAILURE) ;
262 }
263
264 logMsg ("Loading extension: %s", argv [2]) ;
265
266 if (!loadWPiExtension (argv [0], argv [2], TRUE))
267 {
268 logMsg ("Extension load failed: %s", strerror (errno)) ;
269 exit (EXIT_FAILURE) ;
270 }
271
272// Shift args down by 2
273
274 for (i = 3 ; i < argc ; ++i)
275 argv [i - 2] = argv [i] ;
276 argc -= 2 ;
277
278 continue ;
279 }
280
281 logMsg ("Invalid parameter: %s", argv [1]) ;
282 exit (EXIT_FAILURE) ;
283 }
284
285// Default to wiringPi mode
286
287 if (wpiSetup == 0)
288 {
289 logMsg ("WiringPi GPIO mode selected") ;
290 wiringPiSetup () ;
291 }
292
293// Finally, should just be one arg left - the password...
294
295 if (argc != 2)
296 {
297 logMsg ("No password supplied") ;
298 exit (EXIT_FAILURE) ;
299 }
300
301 if (strlen (argv [1]) < 6)
302 {
303 logMsg ("Password too short - at least 6 chars, not %d", strlen (argv [1])) ;
304 exit (EXIT_FAILURE) ;
305 }
306
307 if ((password = malloc (strlen (argv [1]) + 1)) == NULL)
308 {
309 logMsg ("Out of memory") ;
310 exit (EXIT_FAILURE) ;
311 }
312 strcpy (password, argv [1]) ;
313
314// Wipe out the password on the command-line in a vague attempt to try to
315// hide it from snoopers
316
317 for (p = argv [1] ; *p ; ++p)
318 *p = ' ' ;
319
320 setupSigHandler () ;
321
322// Enter our big loop
323
324 for (;;)
325 {
326
327 if (!doDaemon)
328 printf ("-=-\nWaiting for a new connection...\n") ;
329
330 if ((clientFd = setupServer (port)) < 0)
331 {
332 logMsg ("Unable to setup server: %s", strerror (errno)) ;
333 exit (EXIT_FAILURE) ;
334 }
335
336 logMsg ("New connection from: %s.", getClientIP ()) ;
337
338 if (!doDaemon)
339 printf ("Sending Greeting.\n") ;
340
341 if (sendGreeting (clientFd) < 0)
342 {
343 logMsg ("Unable to send greeting message: %s", strerror (errno)) ;
344 closeServer (clientFd) ;
345 continue ;
346 }
347
348 if (!doDaemon)
349 printf ("Sending Challenge.\n") ;
350
351 if (sendChallenge (clientFd) < 0)
352 {
353 logMsg ("Unable to send challenge message: %s", strerror (errno)) ;
354 closeServer (clientFd) ;
355 continue ;
356 }
357
358 if (!doDaemon)
359 printf ("Waiting for response.\n") ;
360
361 if (getResponse (clientFd) < 0)
362 {
363 logMsg ("Connection closed waiting for response: %s", strerror (errno)) ;
364 closeServer (clientFd) ;
365 continue ;
366 }
367
368 if (!passwordMatch (password))
369 {
370 logMsg ("Password failure") ;
371 closeServer (clientFd) ;
372 continue ;
373 }
374
375 logMsg ("Password OK - Starting") ;
376
377 runRemoteCommands (clientFd) ;
378 closeServer (clientFd) ;
379 }
380
381 return 0 ;
382}