Commit 06018f2e authored by Romain Bignon's avatar Romain Bignon

new irssleep project

parents
FILES=main.o
all: $(FILES)
gcc -o irssleep -Wall -Wextra $(FILES)
clean:
rm -rf *.o
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#define IDLE_TIME 30*60
static int is_in_list(const char *elem, const char **list)
{
for(; *list && strcasecmp(elem, *list); ++list)
;
return *list != NULL;
}
int str2mon(const char *str)
{
switch(*str)
{
case 'J':
case 'j':
if (str[1] == 'a')
return 0;
else if (str[2] == 'n')
return 5;
else
return 6;
case 'F':
case 'f':
return 1;
case 'M':
case 'm':
if (str[2] == 'r')
return 2;
else
return 4;
case 'A':
case 'a':
if (strchr("pv", str[1]))
return 3;
else
return 7;
case 'S':
case 's':
return 8;
case 'O':
case 'o':
return 9;
case 'N':
case 'n':
return 10;
case 'D':
case 'd':
return 11;
}
fprintf(stderr, "Unknown month '%s'\n", str);
return 0;
}
#define TS_START 1
#define TS_END 0
static int write_ts(int fd, int start, time_t ts)
{
int ret = 0;
ret |= write(fd, &start, sizeof(start));
ret |= write(fd, &ts, sizeof(ts));
return ret;
}
static int parse_file(int fd, const char **nicknames, const char *filename)
{
char *line = NULL;
size_t len = 0;
ssize_t read;
FILE* fp = fopen(filename, "r");
time_t last = 0, current = 0;
struct tm lt;
if (!fp)
{
fprintf(stderr, "Unable to open %s\n", filename);
return -1;
}
while ((read = getline(&line, &len, fp)) != -1)
{
if (line[0] == '-')
{
char *start = NULL, *tmp;
if (!strncmp(line, "--- Log ", 8))
{
/* --- Log opened DDD MMM dd hh:mm:ss yyyy
* --- Log closed DDD MMM dd hh:mm:ss yyyy
*/
start = strchr(line + 15, ' ') + 1; /* don't care about the day of the week */
}
else if (!strncmp(line, "--- Day changed ", 16))
{
/* --- Day changed DDD MMM dd yyyy */
start = strchr(line + 16, ' ') + 1;
}
else
continue;
localtime_r(&current, &lt);
tmp = strchr(start, ' ');
*tmp++ = '\0';
lt.tm_mon = str2mon(start);
start = tmp;
lt.tm_mday = atoi(start);
start = strchr(start, ' ') + 1;
if (strchr(start, ':'))
{ /* There is a time */
lt.tm_hour = atoi(start);
start = strchr(start, ':') + 1;
lt.tm_min = atoi(start);
start = strchr(start, ':') + 1;
lt.tm_sec = atoi(start);
start = strchr(start, ' ') + 1;
}
else
{
lt.tm_hour = 0;
lt.tm_min = 0;
lt.tm_sec = 0;
}
lt.tm_year = atoi(start) - 1900;
current = mktime(&lt);
if (!last)
{
last = current;
write_ts(fd, TS_START, last);
}
/*
char s[300];
strftime(s, sizeof(s), "%D %H-%M-%S", &lt);
printf("%s\n", s);
*/
}
else
{
/* Assume that the line is in form:
* hh:mm [@+<]nick[> ][message]
*/
char *start = strchr(line, ' ');
char *end;
time_t t;
int hh, mm;
/* Get the nickname. */
while (strchr(" %@+<", *start))
++start; /* skip chan status */
if (strchr(".:-", *start))
continue; /* probably a status line */
end = strchr(start, '>');
if (!end)
end = strchr(start, ' ');
if (!end)
continue;
*end = '\0';
/* Check it's me. */
if (*start != '\0' && !is_in_list(start, nicknames))
continue;
/* Get timestamp */
start = strchr(line, ':') + 1;
hh = atoi(line);
mm = atoi(start);
localtime_r(&current, &lt);
lt.tm_min = mm;
lt.tm_hour = hh;
t = mktime(&lt);
if (t - last > IDLE_TIME)
{
write_ts(fd, TS_END, last);
write_ts(fd, TS_START, t);
}
current = last = t;
}
}
if (line)
free(line);
if (last)
write_ts(fd, TS_END, last);
fclose(fp);
return 0;
}
int start_job(const char *filename, const char **nicks, int* hsock, fd_set *fdset)
{
int notify_pipe[2];
if (pipe(notify_pipe))
return -1;
pid_t pid = fork();
if (!pid)
{
/* child */
close(notify_pipe[0]);
parse_file(notify_pipe[1], nicks, filename);
//printf("Finished %s\n", filename);
exit(0);
}
printf("Started a new job on %s\n", filename);
close(notify_pipe[1]);
if (notify_pipe[0] > *hsock)
*hsock = notify_pipe[0];
FD_SET(notify_pipe[0], fdset);
return 0;
}
void usage(const char* progname, int is_help)
{
FILE* f;
if (is_help)
f = stderr;
else
f = stdout;
fprintf(f, "Usage: %s [-j <nprocess>] logsfiles ...\n", progname);
if (is_help)
{
fprintf(f, "\nThis program blabla\n");
}
}
int main(int argc, char **argv)
{
static struct option long_options[] =
{
{ "forks", 1, NULL, 'j' },
{ "help", 1, NULL, 'h' },
{ NULL, 0, NULL, 0 }
};
int option_index = 0, i;
int nprocess = 1;
int hsock;
fd_set fdset;
const char *nicks[] = {"romain", "Progs", NULL};
while((i = getopt_long(argc, argv, "j:h", long_options, &option_index)) != -1)
switch(i)
{
case 'j':
nprocess = atoi(optarg);
break;
case 'h':
usage(argv[0], 1);
exit(EXIT_SUCCESS);
default:
usage(argv[0], 0);
exit(EXIT_FAILURE);
}
if (!nprocess || nprocess > 10)
{
fprintf(stderr, "Number of forks needs to be between 1 and 10\n");
exit(EXIT_FAILURE);
}
if(optind >= argc)
{
usage(argv[0], 0);
exit(EXIT_FAILURE);
}
FD_ZERO(&fdset);
for (i = 0; i < nprocess && optind < argc; ++i)
if (start_job(argv[optind++], nicks, &hsock, &fdset) != 0)
{
fprintf(stderr, "Error: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
nprocess = i;
while (nprocess)
{
fd_set tmp_fdset = fdset;
int events;
events = select(hsock + 1, &tmp_fdset, NULL, NULL, NULL);
if (events < 0)
{
fprintf(stderr, "Error during select(): %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
for (i = 0; i <= hsock; ++i)
{
if (FD_ISSET(i, &tmp_fdset))
{
time_t t;
int start;
ssize_t r;
r = read(i, &start, sizeof(start));
if (r > 0)
r = read(i, &t, sizeof(t));
if (r <= 0)
{
close(i);
FD_CLR(i, &fdset);
if (optind < argc)
{
if (start_job(argv[optind++], nicks, &hsock, &fdset) != 0)
{
fprintf(stderr, "Error: %s\n", strerror(errno));
continue;
}
}
else
nprocess--;
continue;
}
if (start && 0)
printf("%s: %ld\n", start ? "START" : "END", t);
}
}
}
exit(EXIT_SUCCESS);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment