16 #include <arpa/inet.h>
26 #include <netinet/in.h>
28 #include <sys/socket.h>
30 #include <sys/types.h>
39 static constexpr
const char*
ZM_CONFIG {
"/etc/zm/zm.conf" };
56 int main(
int argc,
char **argv)
60 struct sockaddr_in myaddr {};
61 struct sockaddr_in remoteaddr {};
65 std::array<char,4096> buf {};
70 bool daemon_mode =
false;
77 for (
int argpos = 1; argpos < argc; ++argpos)
79 if (strcmp(argv[argpos],
"-d") == 0 ||
80 strcmp(argv[argpos],
"--daemon") == 0)
84 else if (strcmp(argv[argpos],
"-n") == 0 ||
85 strcmp(argv[argpos],
"--nodaemon") == 0)
89 else if (strcmp(argv[argpos],
"-p") == 0 ||
90 strcmp(argv[argpos],
"--port") == 0)
94 port = atoi(argv[argpos+1]);
96 if (port < 1 || port > 65534)
98 std::cout <<
"Bad port number: " << port << std::endl;
105 std::cout <<
"Missing argument to -p/--port option\n";
109 else if (strcmp(argv[argpos],
"-l") == 0 ||
110 strcmp(argv[argpos],
"--logfile") == 0)
114 logfile = argv[argpos+1];
115 if (logfile[0] ==
'-')
117 std::cerr <<
"Invalid or missing argument to -l/--logfile option\n";
125 std::cerr <<
"Missing argument to -l/--logfile option\n";
129 else if (strcmp(argv[argpos],
"-c") == 0 ||
130 strcmp(argv[argpos],
"--zmconfig") == 0)
134 zmconfig = argv[argpos+1];
135 if (zmconfig[0] ==
'-')
137 std::cerr <<
"Invalid or missing argument to -c/--zmconfig option\n";
145 std::cerr <<
"Missing argument to -c/--zmconfig option\n";
149 else if (strcmp(argv[argpos],
"-o") == 0 ||
150 strcmp(argv[argpos],
"--zmoverrideconfig") == 0)
154 zmconfig = argv[argpos+1];
155 if (zmconfig[0] ==
'-')
157 std::cerr <<
"Invalid or missing argument to -o/--zmoverrideconfig option\n";
165 std::cerr <<
"Missing argument to -o/--zmoverrideconfig option\n";
169 else if (strcmp(argv[argpos],
"-v") == 0 ||
170 strcmp(argv[argpos],
"--verbose") == 0)
176 std::cerr <<
"Invalid argument: " << argv[argpos] << std::endl <<
177 "Valid options are: " << std::endl <<
178 "-p or --port number A port number to listen on (default is 6548) " << std::endl <<
179 "-d or --daemon Runs mythzmserver as a daemon " << std::endl <<
180 "-n or --nodaemon Does not run mythzmserver as a daemon (default)" << std::endl <<
181 "-c or --zmconfig Location of zoneminders default config file (default is " <<
ZM_CONFIG <<
")" << std::endl <<
182 "-o or --zmoverrideconfig Location of zoneminders override config file (default is " <<
ZM_OVERRIDECONFIG <<
")" << std::endl <<
183 "-l or --logfile filename Writes STDERR and STDOUT messages to filename" << std::endl <<
184 "-v or --verbose Prints more debug output" << std::endl;
192 if (!logfile.empty())
194 logfd = open(logfile.c_str(), O_WRONLY|O_CREAT|O_APPEND, 0664);
198 perror(
"open(logfile)");
210 if (logfd != 1 && logfd != 2)
214 if (signal(
SIGPIPE, SIG_IGN) == SIG_ERR)
215 std::cout <<
"Unable to ignore SIGPIPE\n";
222 std::cout <<
"Failed to run as a daemon. Bailing out.\n";
225 std::cout << std::endl;
228 std::map<int, ZMServer*> serverList;
239 std::cout <<
"ZM version not found. Assuming at least v1.34.16 is installed" << std::endl;
251 std::cout <<
"ZM is version '" <<
g_zmversion <<
"'" << std::endl;
255 std::cout <<
"This version of ZM is to old you need 1.24.0 or later '" <<
g_zmversion <<
"'" << std::endl;
268 listener = socket(AF_INET, SOCK_STREAM, 0);
276 if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes,
279 perror(
"setsockopt");
284 myaddr.sin_family = AF_INET;
285 myaddr.sin_addr.s_addr = INADDR_ANY;
286 myaddr.sin_port = htons(port);
287 memset(&(myaddr.sin_zero),
'\0', 8);
288 if (::bind(listener, (
struct sockaddr *)&myaddr,
sizeof(myaddr)) == -1)
295 if (listen(listener, 10) == -1)
301 std::cout <<
"Listening on port: " << port << std::endl;
304 FD_SET(listener, &master);
316 int res = select(fdmax+1, &read_fds,
nullptr,
nullptr, &
timeout);
332 for (
int i = 0; i <= fdmax; i++)
334 if (FD_ISSET(i, &read_fds))
340 socklen_t addrlen =
sizeof(remoteaddr);
341 newfd = accept(listener, (
struct sockaddr *) &remoteaddr,
350 FD_SET(newfd, &master);
351 fdmax = std::max(newfd, fdmax);
355 serverList[newfd] = server;
357 printf(
"new connection from %s on socket %d\n",
358 inet_ntoa(remoteaddr.sin_addr), newfd);
364 int nbytes = recv(i, buf.data(), buf.size(), 0);
371 printf(
"socket %d hung up\n", i);
399 for (
auto & server : serverList)
400 delete server.second;