Last active
April 16, 2020 04:57
-
-
Save hedgeven/1d95b0fc4e0aaf08e23d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ | |
/* | |
* main.c | |
* Copyright (C) 2014 Vassiliy K <hedgeven@linux.com> | |
* | |
* | |
*/ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdarg.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <sysexits.h> | |
#include <time.h> | |
#include <utime.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <netdb.h> | |
#include <syslog.h> | |
#include <ctype.h> | |
#define BUFFSIZE 4096 | |
#define EXPIRE_TIME 8 // Timeout to update the cache file | |
#define SOCK_TIMEOUT 3 // Timeout to blocking socket operations | |
#define CTRL_TIMEOUT 3 // Timeout to wait for data from the controller | |
#define DEFAULT_PORT 1000 | |
#define GET_PORT "get_port\r\n" | |
#define GET_T "get_t\r\n" | |
#define CACHEDIR "/var/cache/zabbix/mka2/" | |
static char *args; | |
static char msg[200]; | |
int main(int argc, char **argv) | |
{ | |
int port = DEFAULT_PORT; | |
int uptate_status; | |
int i; | |
int argl = 0; | |
char *cache_dir = CACHEDIR; | |
char *host; | |
char cache_file[100]; | |
char pattern[20]; | |
char result[10]; | |
struct stat dst, fst; | |
struct utimbuf t; | |
FILE *fp; | |
setlogmask (LOG_UPTO (LOG_NOTICE)); | |
openlog ("mka2", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); | |
for (i = 0; i<argc; i++) | |
argl+=((int)(strlen(argv[i])) + 1); | |
args = (char *) malloc(argl); | |
for (i = 0; i<argc; i++) { | |
strcat(args, argv[i]); | |
if (argc != i+1) strcat(args, " "); | |
} | |
// Analysis of parameters | |
if (argc > 1) { | |
/* Parse first parameter as search pattern. | |
* ^[0-2].$ - Port #.{1,2} | |
* ^T.$ - T_sensor #. | |
*/ | |
char num[3]; | |
if (isdigit(argv[1][0])) { | |
strcpy(pattern, "Port # "); | |
sscanf(argv[1], "%2s", num); | |
} else if (argv[1][0] == 'T' && isdigit(argv[1][1])) { | |
strcpy(pattern, "T_sensor #"); | |
sscanf(argv[1], "T%1s", num); | |
} else { | |
sprintf (msg, "%s: Invalid search pattern %s\n", args, argv[1]); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_USAGE); | |
} | |
strcat(pattern, num); | |
strcat(pattern, " = "); | |
// Parse second parameter as ip address. | |
if (argc > 2) | |
host = argv[2]; | |
else { | |
sprintf (msg, "Host is not specified\n"); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_USAGE); | |
} | |
// Parse third parameter as port. | |
if (argc > 3) | |
port = atoi(argv[3]); | |
} else { | |
printf("Usage: mta2 pattern host [port]\n"); | |
return (EX_USAGE); | |
} | |
// Create cache directory | |
if (stat(cache_dir, &dst) == -1) | |
if (mkdir(cache_dir, 0755)) { | |
sprintf (msg, "No access to the %s\n", cache_dir); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_NOPERM); | |
} | |
// Create cache file if not exists and get data | |
strcpy(cache_file, cache_dir); | |
strcat(cache_file, host); | |
if ((stat(cache_file, &fst) == -1)) { | |
if ((fp = fopen(cache_file, "a")) == NULL) { | |
sprintf (msg, "No access to the %s\n", cache_file); | |
return (EX_NOPERM); | |
} else { | |
fclose(fp); | |
if (uptate_status = cache_update(host, port, cache_file)) | |
return (uptate_status); | |
} | |
} | |
// If the cache is out of date, then update it | |
if (difftime(time(NULL), fst.st_mtime) > EXPIRE_TIME) { | |
t.modtime = time(NULL); | |
utime(cache_file, &t); | |
if (uptate_status = cache_update(host, port, cache_file)) | |
return (uptate_status); | |
} | |
if ((fp = fopen(cache_file, "r")) == NULL) { | |
sprintf (msg, "No access to the %s\n", cache_file); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_NOPERM); | |
} else { | |
char l[BUFFSIZE]; | |
while(fgets(l, BUFFSIZE, fp)) | |
if (strstr(l, pattern) != NULL) | |
sscanf(l, strcat(pattern, "%s"), result); | |
fclose(fp); | |
} | |
if (isdigit(result[0])) | |
printf ("%s\n", result); | |
else | |
printf ("%s\n", "No data"); | |
closelog (); | |
return (EX_OK); | |
} | |
int cache_update(char *host, int port, char *file) | |
{ | |
int sockfd; | |
char buffer[BUFFSIZE]; | |
char result[BUFFSIZE*2]; | |
FILE *fp; | |
struct sockaddr_in serv_addr; | |
struct hostent *server; | |
struct timeval timeout; | |
timeout.tv_sec = SOCK_TIMEOUT; | |
timeout.tv_usec = 0; | |
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
sprintf (msg, "Error opening socket\n"); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_PROTOCOL); | |
} | |
if ((server = gethostbyname(host)) == NULL) { | |
sprintf (msg, "No such host %s\n", host); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_NOHOST); | |
} | |
bzero((char *) &serv_addr, sizeof(serv_addr)); | |
serv_addr.sin_family = AF_INET; | |
bcopy((char *)server->h_addr, | |
(char *)&serv_addr.sin_addr.s_addr,server->h_length); | |
serv_addr.sin_port = htons(port); | |
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { | |
sprintf (msg, "Error connecting to %s:%d\n", host, port); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_PROTOCOL); | |
} | |
if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, | |
sizeof(timeout)) < 0) | |
syslog (LOG_ERR, "%s: setsockopt failed\n", args); | |
if (setsockopt (sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, | |
sizeof(timeout)) < 0) | |
syslog (LOG_ERR, "%s: setsockopt failed\n", args); | |
if ((read(sockfd,buffer,BUFFSIZE-1)) < 0) { | |
sprintf (msg, "Error reading from socket\n"); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_PROTOCOL); | |
} | |
bzero(buffer,BUFFSIZE); | |
if ((write(sockfd,GET_PORT,strlen(GET_PORT))) < 0) { | |
sprintf (msg, "Error writing to socket\n"); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_PROTOCOL); | |
} | |
sleep (CTRL_TIMEOUT); | |
if ((read(sockfd,buffer,BUFFSIZE-1)) < 0) { | |
sprintf (msg, "Error Reading from socket\n"); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_PROTOCOL); | |
} | |
strcat(result, buffer); | |
bzero(buffer,BUFFSIZE); | |
if ((write(sockfd,GET_T,strlen(GET_T))) < 0) { | |
sprintf (msg, "Error writing to socket\n"); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_PROTOCOL); | |
} | |
sleep (CTRL_TIMEOUT); | |
if ((read(sockfd,buffer,BUFFSIZE-1)) < 0) { | |
sprintf (msg, "Error Reading from socket\n"); | |
printf ("%s", msg); | |
syslog (LOG_ERR, "%s: %s", args, msg); | |
return (EX_PROTOCOL); | |
} | |
strcat(result, buffer); | |
if ((fp = fopen(file, "w")) != NULL) { | |
fputs(result, fp); | |
fclose(fp); | |
} else | |
return (EX_NOPERM); | |
close(sockfd); | |
return (EX_OK); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment