16 #include <arpa/inet.h>
25 #include <netinet/in.h>
27 #include <sys/socket.h>
29 #include <sys/types.h>
38 static constexpr
const char*
ZM_CONFIG {
"/etc/zm/zm.conf" };
55 int main(
int argc,
char **argv)
59 struct sockaddr_in myaddr {};
60 struct sockaddr_in remoteaddr {};
64 std::array<char,4096> buf {};
69 bool daemon_mode =
false;
76 for (
int argpos = 1; argpos < argc; ++argpos)
78 if (strcmp(argv[argpos],
"-d") == 0 ||
79 strcmp(argv[argpos],
"--daemon") == 0)
83 else if (strcmp(argv[argpos],
"-n") == 0 ||
84 strcmp(argv[argpos],
"--nodaemon") == 0)
88 else if (strcmp(argv[argpos],
"-p") == 0 ||
89 strcmp(argv[argpos],
"--port") == 0)
93 port = atoi(argv[argpos+1]);
95 if (port < 1 || port > 65534)
97 std::cout <<
"Bad port number: " << port << std::endl;
104 std::cout <<
"Missing argument to -p/--port option\n";
108 else if (strcmp(argv[argpos],
"-l") == 0 ||
109 strcmp(argv[argpos],
"--logfile") == 0)
116 std::cerr <<
"Invalid or missing argument to -l/--logfile option\n";
124 std::cerr <<
"Missing argument to -l/--logfile option\n";
128 else if (strcmp(argv[argpos],
"-c") == 0 ||
129 strcmp(argv[argpos],
"--zmconfig") == 0)
133 zmconfig = argv[argpos+1];
134 if (zmconfig[0] ==
'-')
136 std::cerr <<
"Invalid or missing argument to -c/--zmconfig option\n";
144 std::cerr <<
"Missing argument to -c/--zmconfig option\n";
148 else if (strcmp(argv[argpos],
"-o") == 0 ||
149 strcmp(argv[argpos],
"--zmoverrideconfig") == 0)
153 zmconfig = argv[argpos+1];
154 if (zmconfig[0] ==
'-')
156 std::cerr <<
"Invalid or missing argument to -o/--zmoverrideconfig option\n";
164 std::cerr <<
"Missing argument to -o/--zmoverrideconfig option\n";
168 else if (strcmp(argv[argpos],
"-v") == 0 ||
169 strcmp(argv[argpos],
"--verbose") == 0)
175 std::cerr <<
"Invalid argument: " << argv[argpos] << std::endl <<
176 "Valid options are: " << std::endl <<
177 "-p or --port number A port number to listen on (default is 6548) " << std::endl <<
178 "-d or --daemon Runs mythzmserver as a daemon " << std::endl <<
179 "-n or --nodaemon Does not run mythzmserver as a daemon (default)" << std::endl <<
180 "-c or --zmconfig Location of zoneminders default config file (default is " <<
ZM_CONFIG <<
")" << std::endl <<
181 "-o or --zmoverrideconfig Location of zoneminders override config file (default is " <<
ZM_OVERRIDECONFIG <<
")" << std::endl <<
182 "-l or --logfile filename Writes STDERR and STDOUT messages to filename" << std::endl <<
183 "-v or --verbose Prints more debug output" << std::endl;
193 logfd = open(
logfile.c_str(), O_WRONLY|O_CREAT|O_APPEND, 0664);
197 perror(
"open(logfile)");
209 if (logfd != 1 && logfd != 2)
213 if (signal(
SIGPIPE, SIG_IGN) == SIG_ERR)
214 std::cout <<
"Unable to ignore SIGPIPE\n";
221 std::cout <<
"Failed to run as a daemon. Bailing out.\n";
224 std::cout << std::endl;
227 std::map<int, ZMServer*> serverList;
238 std::cout <<
"ZM version not found. Assuming at least v1.34.16 is installed" << std::endl;
250 std::cout <<
"ZM is version '" <<
g_zmversion <<
"'" << std::endl;
254 std::cout <<
"This version of ZM is to old you need 1.24.0 or later '" <<
g_zmversion <<
"'" << std::endl;
267 if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1)
274 if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes,
277 perror(
"setsockopt");
282 myaddr.sin_family = AF_INET;
283 myaddr.sin_addr.s_addr = INADDR_ANY;
284 myaddr.sin_port = htons(port);
285 memset(&(myaddr.sin_zero),
'\0', 8);
286 if (::bind(listener, (
struct sockaddr *)&myaddr,
sizeof(myaddr)) == -1)
293 if (listen(listener, 10) == -1)
299 std::cout <<
"Listening on port: " << port << std::endl;
302 FD_SET(listener, &master);
314 int res = select(fdmax+1, &read_fds,
nullptr,
nullptr, &
timeout);
330 for (
int i = 0; i <= fdmax; i++)
332 if (FD_ISSET(i, &read_fds))
338 socklen_t addrlen =
sizeof(remoteaddr);
339 if ((newfd = accept(listener,
340 (
struct sockaddr *) &remoteaddr,
348 FD_SET(newfd, &master);
356 serverList[newfd] = server;
358 printf(
"new connection from %s on socket %d\n",
359 inet_ntoa(remoteaddr.sin_addr), newfd);
365 int nbytes = recv(i, buf.data(), buf.size(), 0);
372 printf(
"socket %d hung up\n", i);
400 for (
auto & server : serverList)
401 delete server.second;