Merge branch 'master' of https://github.com/abishai/ZoneMinder into abishai-master

This commit is contained in:
Andrew Bauer 2017-05-10 08:06:48 -05:00
commit c4f471d967
5 changed files with 381 additions and 20 deletions

View File

@ -103,7 +103,8 @@ mark_as_advanced(
ZM_PERL_MM_PARMS
ZM_PERL_SEARCH_PATH
ZM_TARGET_DISTRO
ZM_CONFIG_DIR)
ZM_CONFIG_DIR
ZM_SYSTEMD)
set(ZM_RUNDIR "/var/run/zm" CACHE PATH
"Location of transient process files, default: /var/run/zm")
@ -166,6 +167,8 @@ set(ZM_PERL_SEARCH_PATH "" CACHE PATH
installed outside Perl's default search path.")
set(ZM_TARGET_DISTRO "" CACHE STRING
"Build ZoneMinder for a specific distribution. Currently, valid names are: fc24, fc25, el6, el7, OS13, FreeBSD")
set(ZM_SYSTEMD "OFF" CACHE BOOL
"Set to ON to force building ZM with systemd support. default: OFF")
# Reassign some variables if a target distro has been specified
if((ZM_TARGET_DISTRO STREQUAL "fc24") OR (ZM_TARGET_DISTRO STREQUAL "fc25"))
@ -223,6 +226,11 @@ include_directories("${CMAKE_BINARY_DIR}")
# This is required to enable searching in lib64 (if exists), do not change
set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ON)
# Set the systemd flag if systemd is autodetected or ZM_SYSTEMD has been set
if(ZM_SYSTEMD OR (IS_DIRECTORY /usr/lib/systemd/system) OR (IS_DIRECTORY /lib/systemd/system))
set(WITH_SYSTEMD 1)
endif(ZM_SYSTEMD OR (IS_DIRECTORY /usr/lib/systemd/system) OR (IS_DIRECTORY /lib/systemd/system))
# System checks
check_include_file("libv4l1-videodev.h" HAVE_LIBV4L1_VIDEODEV_H)
if(NOT HAVE_LIBV4L1_VIDEODEV_H)
@ -404,13 +412,13 @@ find_library(MYSQLCLIENT_LIBRARIES mysqlclient PATH_SUFFIXES mysql)
if(MYSQLCLIENT_LIBRARIES)
set(HAVE_LIBMYSQLCLIENT 1)
list(APPEND ZM_BIN_LIBS "${MYSQLCLIENT_LIBRARIES}")
find_path(MYSQLCLIENT_INCLUDE_DIR mysql/mysql.h)
find_path(MYSQLCLIENT_INCLUDE_DIR mysql.h PATH_SUFFIXES mysql)
if(MYSQLCLIENT_INCLUDE_DIR)
include_directories("${MYSQLCLIENT_INCLUDE_DIR}")
set(CMAKE_REQUIRED_INCLUDES "${MYSQLCLIENT_INCLUDE_DIR}")
endif(MYSQLCLIENT_INCLUDE_DIR)
mark_as_advanced(FORCE MYSQLCLIENT_LIBRARIES MYSQLCLIENT_INCLUDE_DIR)
check_include_file("mysql/mysql.h" HAVE_MYSQL_H)
check_include_file("mysql.h" HAVE_MYSQL_H)
if(NOT HAVE_MYSQL_H)
message(FATAL_ERROR
"ZoneMinder requires MySQL headers - check that MySQL development packages are installed")
@ -677,12 +685,14 @@ endif(NOT ZM_WEB_GROUP)
message(STATUS "Using web user: ${ZM_WEB_USER}")
message(STATUS "Using web group: ${ZM_WEB_GROUP}")
# Check for polkit
find_package(Polkit)
if(NOT POLKIT_FOUND)
if(WITH_SYSTEMD)
# Check for polkit
find_package(Polkit)
if(NOT POLKIT_FOUND)
message(FATAL_ERROR
"Running ZoneMinder requires polkit. Building ZoneMinder requires the polkit development package.")
endif(NOT POLKIT_FOUND)
endif(NOT POLKIT_FOUND)
endif(WITH_SYSTEMD)
# Some variables that zm expects
set(ZM_PID "${ZM_RUNDIR}/zm.pid")

View File

@ -1746,11 +1746,9 @@ Image *Image::Highlight( unsigned int n_images, Image *images[], const Rgb thres
{
uint8_t *psrc = images[j]->buffer+c;
#ifndef SOLARIS
if ( (unsigned)abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) )
#else
if ( (unsigned)std::abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) )
#endif
unsigned int diff = ((*psrc)-RGB_VAL(ref_colour,c)) > 0 ? (*psrc)-RGB_VAL(ref_colour,c) : RGB_VAL(ref_colour,c) - (*psrc);
if (diff >= RGB_VAL(threshold,c))
{
count++;
}

View File

@ -31,9 +31,9 @@
#include <signal.h>
#include <stdarg.h>
#include <errno.h>
#include <libgen.h>
#ifdef __FreeBSD__
#include <sys/thr.h>
#include <libgen.h>
#endif
bool Logger::smInitialised = false;
@ -515,7 +515,8 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
va_list argPtr;
struct timeval timeVal;
const char * const file = basename(filepath);
char *filecopy = strdup(filepath);
const char * const file = basename(filecopy);
if ( level < PANIC || level > DEBUG9 )
Panic( "Invalid logger level %d", level );
@ -631,6 +632,8 @@ void Logger::logPrint( bool hex, const char * const filepath, const int line, co
syslog( priority, "%s [%s]", classString, syslogStart );
}
free(filecopy);
if ( level <= FATAL )
{
if ( level <= PANIC )

View File

@ -160,7 +160,7 @@ bool Monitor::MonitorLink::connect()
return( false );
}
mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 );
if ( mem_ptr < 0 )
if ( mem_ptr < (void *)0 )
{
Debug( 3, "Can't shmat link memory: %s", strerror(errno) );
connected = false;
@ -194,7 +194,7 @@ bool Monitor::MonitorLink::disconnect()
connected = false;
#if ZM_MEM_MAPPED
if ( mem_ptr > 0 )
if ( mem_ptr > (void *)0 )
{
msync( mem_ptr, mem_size, MS_ASYNC );
munmap( mem_ptr, mem_size );
@ -558,7 +558,7 @@ bool Monitor::connect() {
exit( -1 );
}
mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 );
if ( mem_ptr < 0 )
if ( mem_ptr < (void *)0 )
{
Error( "Can't shmat: %s", strerror(errno));
exit( -1 );

350
src/zmf.cpp Normal file
View File

@ -0,0 +1,350 @@
//
// ZoneMinder Image File Writer Implementation, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
/*
=head1 NAME
zmf - The ZoneMinder Frame daemon
=head1 SYNOPSIS
zmf -m <monitor_id>
zmf --monitor <monitor_id>
zmf -h
zmf --help
zmf -v
zmf --version
=head1 DESCRIPTION
This is an optional daemon that can run in concert with the Analysis daemon and
whose function it is to actually write captured frames to disk. This frees up
the Analysis daemon to do more analysis (!) and so keep up with the Capture
daemon better. If it isn't running or dies then the Analysis daemon just writes
them itself.
=head1 OPTIONS
-m, --monitor_id - ID of the monitor to use
-h, --help - Display usage information
-v, --version - Print the installed version of ZoneMinder
=cut
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <getopt.h>
#include <signal.h>
#include "zm.h"
#include "zm_db.h"
#include "zm_signal.h"
#include "zm_monitor.h"
#include "zmf.h"
int OpenSocket( int monitor_id )
{
int sd = socket( AF_UNIX, SOCK_STREAM, 0);
if ( sd < 0 )
{
Error( "Can't create socket: %s", strerror(errno) );
return( -1 );
}
char sock_path[PATH_MAX] = "";
snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id );
if ( unlink( sock_path ) < 0 )
{
Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) );
}
struct sockaddr_un addr;
strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) );
addr.sun_family = AF_UNIX;
if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 )
{
Error( "Can't bind: %s", strerror(errno) );
exit( -1 );
}
if ( listen( sd, SOMAXCONN ) < 0 )
{
Error( "Can't listen: %s", strerror(errno) );
return( -1 );
}
struct sockaddr_un rem_addr;
socklen_t rem_addr_len = sizeof(rem_addr);
int new_sd = -1;
if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 )
{
Error( "Can't accept: %s", strerror(errno) );
exit( -1 );
}
close( sd );
sd = new_sd;
Info( "Frame server socket open, awaiting images" );
return( sd );
}
int ReopenSocket( int &sd, int monitor_id )
{
close( sd );
return( sd = OpenSocket( monitor_id ) );
}
void Usage()
{
fprintf( stderr, "zmf -m <monitor_id>\n" );
fprintf( stderr, "Options:\n" );
fprintf( stderr, " -m, --monitor <monitor_id> : Specify which monitor to use\n" );
fprintf( stderr, " -h, --help : This screen\n" );
fprintf( stderr, " -v, --version : Report the installed version of ZoneMinder\n" );
exit( 0 );
}
int main( int argc, char *argv[] )
{
self = argv[0];
srand( getpid() * time( 0 ) );
int id = -1;
static struct option long_options[] = {
{"monitor", 1, 0, 'm'},
{"help", 0, 0, 'h'},
{"version", 0, 0, 'v'},
{0, 0, 0, 0}
};
while (1)
{
int option_index = 0;
int c = getopt_long (argc, argv, "m:h:v", long_options, &option_index);
if (c == -1)
{
break;
}
switch (c)
{
case 'm':
id = atoi(optarg);
break;
case 'h':
case '?':
Usage();
break;
case 'v':
std::cout << ZM_VERSION << "\n";
exit(0);
default:
//fprintf( stderr, "?? getopt returned character code 0%o ??\n", c );
break;
}
}
if (optind < argc)
{
fprintf( stderr, "Extraneous options, " );
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
Usage();
}
if ( id < 0 )
{
fprintf( stderr, "Bogus monitor %d\n", id );
Usage();
exit( 0 );
}
char log_id_string[16];
snprintf( log_id_string, sizeof(log_id_string), "m%d", id );
zmLoadConfig();
logInit( "zmf" );
ssedetect();
Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY );
if ( !monitor )
{
fprintf( stderr, "Can't find monitor with id of %d\n", id );
exit( -1 );
}
char capt_path[PATH_MAX];
char anal_path[PATH_MAX];
snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits );
zmSetDefaultTermHandler();
zmSetDefaultDieHandler();
sigset_t block_set;
sigemptyset( &block_set );
int sd = OpenSocket( monitor->Id() );
FrameHeader frame_header = { 0, 0, false, 0 };
//unsigned char *image_data = 0;
fd_set rfds;
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
while( 1 )
{
struct timeval temp_timeout = timeout;
FD_ZERO(&rfds);
FD_SET(sd, &rfds);
int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout );
if( n_found == 0 )
{
Debug( 1, "Select timed out" );
continue;
}
else if ( n_found < 0)
{
Error( "Select error: %s", strerror(errno) );
ReopenSocket( sd, monitor->Id() );
continue;
}
sigprocmask( SIG_BLOCK, &block_set, 0 );
int n_bytes = read( sd, &frame_header, sizeof(frame_header) );
if ( n_bytes != sizeof(frame_header) )
{
if ( n_bytes < 0 )
{
Error( "Can't read frame header: %s", strerror(errno) );
}
else if ( n_bytes > 0 )
{
Error( "Incomplete read of frame header, %d bytes only", n_bytes );
}
else
{
Warning( "Socket closed at remote end" );
}
ReopenSocket( sd, monitor->Id() );
continue;
}
Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length );
static unsigned char image_data[ZM_MAX_IMAGE_SIZE];
// Read for pipe and loop until bytes expected have been read or an error occurs
int bytes_read = 0;
do
{
n_bytes = read( sd, image_data+bytes_read, frame_header.image_length-bytes_read );
if (n_bytes < 0) break; // break on error
if (n_bytes < (int)frame_header.image_length)
{
// print some informational messages
if (bytes_read == 0)
{
Debug(4,"Image read : Short read %d bytes of %d expected bytes",n_bytes,frame_header.image_length);
}
else if (bytes_read+n_bytes == (int)frame_header.image_length)
{
Debug(5,"Image read : Read rest of short read: %d bytes read total of %d bytes",n_bytes,frame_header.image_length);
}
else
{
Debug(6,"Image read : continuing, read %d bytes (%d so far)", n_bytes, bytes_read+n_bytes);
}
}
bytes_read+= n_bytes;
} while (n_bytes>0 && (bytes_read < (ssize_t)frame_header.image_length) );
// Print errors if there was a problem
if ( n_bytes < 1 )
{
Error( "Only read %d bytes of %d\n", bytes_read, frame_header.image_length);
if ( n_bytes < 0 )
{
Error( "Can't read frame image data: %s", strerror(errno) );
}
else
{
Warning( "Socket closed at remote end" );
}
ReopenSocket( sd, monitor->Id() );
continue;
}
static char subpath[PATH_MAX] = "";
if ( config.use_deep_storage )
{
struct tm *time = localtime( &frame_header.event_time );
snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
}
else
{
snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id );
}
static char path[PATH_MAX] = "";
snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id );
Debug( 1, "Got image, writing to %s", path );
FILE *fd = 0;
if ( (fd = fopen( path, "w" )) == NULL )
{
Error( "Can't fopen '%s': %s", path, strerror(errno) );
exit( -1 );
}
if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) )
{
Error( "Can't fwrite image data: %s", strerror(errno) );
exit( -1 );
}
fclose( fd );
sigprocmask( SIG_UNBLOCK, &block_set, 0 );
}
logTerm();
zmDbClose();
}