commit
eacec9b628
15 changed files with 1296 additions and 0 deletions
@ -0,0 +1,22 @@
|
||||
# Toplevel Makefile
|
||||
|
||||
SRC := cachesyncd.c configfile.c logging.c multicast.c unixsock.c
|
||||
CFLAGS := -O2 -Wall
|
||||
|
||||
# ############################
|
||||
|
||||
all: cachesyncd |
||||
|
||||
cachesyncd: $(SRC:%.c=%.o) |
||||
$(CC) $(LDFLAGS) $^ -o $@
|
||||
|
||||
%.d: %.c |
||||
$(CC) $(CFLAGS) -MM -c $< -o $@
|
||||
|
||||
%.o: %.c |
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean: |
||||
rm -rf *.d *.o cachesyncd
|
||||
|
||||
-include $(SRC:.c=.d) |
@ -0,0 +1,111 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 06/2006 by Olaf Rempel * |
||||
* razzor@kopf-tisch.de * |
||||
* * |
||||
* 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., * |
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
||||
***************************************************************************/ |
||||
|
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <getopt.h> |
||||
#include <sys/stat.h> |
||||
|
||||
#include "configfile.h" |
||||
#include "logging.h" |
||||
#include "multicast.h" |
||||
#include "unixsock.h" |
||||
|
||||
#define DEFAULT_CONFIG "cachesyncd.conf" |
||||
#define DEFAULT_LOGFILE "cachesyncd.log" |
||||
|
||||
static struct option opts[] = { |
||||
{"config", 1, 0, 'c'}, |
||||
{"debug", 0, 0, 'd'}, |
||||
{"help", 0, 0, 'h'}, |
||||
{0, 0, 0, 0} |
||||
}; |
||||
|
||||
static void run() |
||||
{ |
||||
int usock, msock; |
||||
usock = sock_init(); |
||||
msock = mcast_init(); |
||||
|
||||
mcast_send(msock, "HALLO", 6); |
||||
|
||||
msock_close(msock); |
||||
sock_close(usock); |
||||
} |
||||
|
||||
int main(int argc, char *argv[]) |
||||
{ |
||||
char *config = DEFAULT_CONFIG; |
||||
int code, arg = 0, debug = 0; |
||||
|
||||
do { |
||||
code = getopt_long(argc, argv, "c:dh", opts, &arg); |
||||
|
||||
switch (code) { |
||||
case 'c': /* config */ |
||||
config = optarg; |
||||
break; |
||||
|
||||
case 'd': /* debug */ |
||||
debug = 1; |
||||
break; |
||||
|
||||
case 'h': /* help */ |
||||
printf("Usage: cachesyncd [options]\n" |
||||
"Options: \n" |
||||
" --config -c configfile use this configfile\n" |
||||
" --debug -d do not fork and log to stderr\n" |
||||
" --help -h this help\n" |
||||
"\n"); |
||||
exit(0); |
||||
break; |
||||
|
||||
case '?': /* error */ |
||||
exit(-1); |
||||
break; |
||||
|
||||
default: /* unknown / all options parsed */ |
||||
break; |
||||
} |
||||
} while (code != -1); |
||||
|
||||
/* parse config file */ |
||||
if (!config_parse(config)) |
||||
exit(-1); |
||||
|
||||
/* check logfile */ |
||||
char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE); |
||||
if (logfile != NULL && debug == 0) { |
||||
/* start logging */ |
||||
if (!log_init(logfile)) |
||||
exit(-1); |
||||
|
||||
/* zum daemon mutieren */ |
||||
daemon(-1, 0); |
||||
} |
||||
|
||||
log_print(LOG_EVERYTIME, "cachesyncd started"); |
||||
|
||||
run(); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,17 @@
|
||||
[global] |
||||
# unpriviliged user |
||||
user httpd |
||||
|
||||
# pidfile location |
||||
pidfile ./cachesync.pid |
||||
|
||||
# unix domain socket location |
||||
socket ./cachesync.sock |
||||
|
||||
# bind to multicast interface |
||||
mcastdev eth0 |
||||
mcastgroup 224.0.0.1 |
||||
mcastport 2000 |
||||
|
||||
# smarty cache directory |
||||
basedir /var/www/smarty/cache/ |
@ -0,0 +1,182 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 06/2006 by Olaf Rempel * |
||||
* razzor@kopf-tisch.de * |
||||
* * |
||||
* 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., * |
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
||||
***************************************************************************/ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "list.h" |
||||
|
||||
#include "configfile.h" |
||||
#include "logging.h" |
||||
|
||||
static LIST_HEAD(config_list); |
||||
|
||||
static struct conf_section * config_add_section(char *name) |
||||
{ |
||||
struct conf_section *section; |
||||
|
||||
if (!name) |
||||
return NULL; |
||||
|
||||
section = malloc(sizeof(struct conf_section)); |
||||
if (section) { |
||||
INIT_LIST_HEAD(§ion->list); |
||||
INIT_LIST_HEAD(§ion->tupel); |
||||
|
||||
strncpy(section->name, name, sizeof(section->name)); |
||||
list_add_tail(§ion->list, &config_list); |
||||
} |
||||
return section; |
||||
} |
||||
|
||||
static int config_add_tupel(struct conf_section *section, char *option, char *parameter) |
||||
{ |
||||
struct conf_tupel *tupel; |
||||
|
||||
if (!section || !option || !parameter) |
||||
return 0; |
||||
|
||||
if (!(tupel = malloc(sizeof(struct conf_tupel)))) |
||||
return 0; |
||||
|
||||
INIT_LIST_HEAD(&tupel->list); |
||||
|
||||
tupel->option = strdup(option); |
||||
tupel->parameter = strdup(parameter); |
||||
|
||||
list_add_tail(&tupel->list, §ion->tupel); |
||||
return 1; |
||||
} |
||||
|
||||
static void config_free(void) |
||||
{ |
||||
struct conf_section *section, *section_tmp; |
||||
struct conf_tupel *tupel, *tupel_tmp; |
||||
|
||||
list_for_each_entry_safe(section, section_tmp, &config_list, list) { |
||||
list_for_each_entry_safe(tupel, tupel_tmp, §ion->tupel, list) { |
||||
list_del(&tupel->list); |
||||
free(tupel->option); |
||||
free(tupel->parameter); |
||||
free(tupel); |
||||
} |
||||
list_del(§ion->list); |
||||
free(section); |
||||
} |
||||
} |
||||
|
||||
int config_parse(char *config) |
||||
{ |
||||
struct conf_section *section = NULL; |
||||
FILE *fz; |
||||
int i = 0, ret = 1; |
||||
char *row, *tok, *tok2; |
||||
|
||||
if (!config) |
||||
return 0; |
||||
|
||||
if (!(row = malloc(1024))) |
||||
return 0; |
||||
|
||||
if (!(fz = fopen(config, "r"))) { |
||||
log_print(LOG_ERROR, "config_parse(): %s", config); |
||||
return 0; |
||||
} |
||||
|
||||
while (fgets(row, 1024, fz)) { |
||||
i++; |
||||
|
||||
if (row[0] == '#' || row[0] <= ' ') { |
||||
continue; |
||||
|
||||
} else if (row[0] == '[') { |
||||
tok = strtok(row +1, " ]\n"); |
||||
section = config_add_section(tok); |
||||
if (!section) { |
||||
log_print(LOG_WARN, "config_parse(): invalid section in row %d", i); |
||||
ret = 0; |
||||
break; |
||||
} |
||||
continue; |
||||
|
||||
} else if (!section) { |
||||
log_print(LOG_WARN, "config_parse(): missing section in row %d", i); |
||||
ret = 0; |
||||
break; |
||||
} |
||||
|
||||
if ((tok = strtok(row, " \n")) && (tok2 = strtok(NULL, " \n"))) |
||||
if (!config_add_tupel(section, tok, tok2)) |
||||
log_print(LOG_WARN, "config_parse(): invalid row %d", i); |
||||
} |
||||
|
||||
fclose(fz); |
||||
free(row); |
||||
|
||||
if (atexit(config_free) != 0) { |
||||
log_print(LOG_ERROR, "config_parse(): atexit()"); |
||||
return 0; |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
struct conf_section * config_get_section(char *name) |
||||
{ |
||||
struct conf_section *section; |
||||
|
||||
list_for_each_entry(section, &config_list, list) { |
||||
if (!strcmp(section->name, name)) |
||||
return section; |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
char * config_get_parameter(struct conf_section *section, char *option) |
||||
{ |
||||
struct conf_tupel *tupel; |
||||
|
||||
list_for_each_entry(tupel, §ion->tupel, list) { |
||||
if (!strcmp(tupel->option, option)) |
||||
return tupel->parameter; |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
char * config_get_string(char *section, char *option, char *def) |
||||
{ |
||||
struct conf_section *tmp; |
||||
char *ret; |
||||
|
||||
tmp = config_get_section(section); |
||||
if (tmp && (ret = config_get_parameter(tmp, option))) |
||||
return ret; |
||||
|
||||
return def; |
||||
} |
||||
|
||||
int config_get_int(char *section, char *option, int def) |
||||
{ |
||||
char *ret; |
||||
|
||||
ret = config_get_string(section, option, NULL); |
||||
return ret ? atoi(ret) : def; |
||||
} |
@ -0,0 +1,24 @@
|
||||
#ifndef _CONFIG_H_ |
||||
#define _CONFIG_H_ |
||||
|
||||
#include "list.h" |
||||
|
||||
struct conf_section { |
||||
struct list_head list; |
||||
char name[32]; |
||||
struct list_head tupel; |
||||
}; |
||||
|
||||
struct conf_tupel { |
||||
struct list_head list; |
||||
char *option; |
||||
char *parameter; |
||||
}; |
||||
|
||||
int config_parse(char *config); |
||||
struct conf_section * config_get_section(char *name); |
||||
char * config_get_parameter(struct conf_section *section, char *option); |
||||
char * config_get_string(char *section, char *option, char *def); |
||||
int config_get_int(char *section, char *option, int def); |
||||
|
||||
#endif /* _CONFIG_H_ */ |
@ -0,0 +1,268 @@
|
||||
#ifndef _LIST_H_ |
||||
#define _LIST_H_ |
||||
|
||||
/*
|
||||
* stolen from linux kernel 2.6.11 (http://kernel.org/)
|
||||
* linux/include/linux/stddef.h (offsetoff) |
||||
* linux/include/linux/kernel.h (container_of) |
||||
* linux/include/linux/list.h (*list*) |
||||
* linux/include/linux/netfilter_ipv4/listhelp.h (LIST_FIND) |
||||
* |
||||
* modified by Olaf Rempel <razzor@kopf-tisch.de> |
||||
*/ |
||||
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
||||
|
||||
#define container_of(ptr, type, member) ({ \ |
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );}) |
||||
|
||||
struct list_head { |
||||
struct list_head *next, *prev; |
||||
}; |
||||
|
||||
#define LIST_HEAD_INIT(name) { &(name), &(name) } |
||||
|
||||
#define LIST_HEAD(name) \ |
||||
struct list_head name = LIST_HEAD_INIT(name) |
||||
|
||||
#define INIT_LIST_HEAD(ptr) do { \ |
||||
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
|
||||
} while (0) |
||||
|
||||
/*
|
||||
* Insert a new entry between two known consecutive entries. |
||||
* |
||||
* This is only for internal list manipulation where we know |
||||
* the prev/next entries already! |
||||
*/ |
||||
static inline void __list_add(struct list_head *new, |
||||
struct list_head *prev, |
||||
struct list_head *next) |
||||
{ |
||||
next->prev = new; |
||||
new->next = next; |
||||
new->prev = prev; |
||||
prev->next = new; |
||||
} |
||||
|
||||
/*
|
||||
* list_add - add a new entry |
||||
* @new: new entry to be added |
||||
* @head: list head to add it after |
||||
* |
||||
* Insert a new entry after the specified head. |
||||
* This is good for implementing stacks. |
||||
*/ |
||||
static inline void list_add(struct list_head *new, struct list_head *head) |
||||
{ |
||||
__list_add(new, head, head->next); |
||||
} |
||||
|
||||
/*
|
||||
* list_add_tail - add a new entry |
||||
* @new: new entry to be added |
||||
* @head: list head to add it before |
||||
* |
||||
* Insert a new entry before the specified head. |
||||
* This is useful for implementing queues. |
||||
*/ |
||||
static inline void list_add_tail(struct list_head *new, struct list_head *head) |
||||
{ |
||||
__list_add(new, head->prev, head); |
||||
} |
||||
|
||||
/*
|
||||
* Delete a list entry by making the prev/next entries |
||||
* point to each other. |
||||
* |
||||
* This is only for internal list manipulation where we know |
||||
* the prev/next entries already! |
||||
*/ |
||||
static inline void __list_del(struct list_head * prev, struct list_head * next) |
||||
{ |
||||
next->prev = prev; |
||||
prev->next = next; |
||||
} |
||||
|
||||
/*
|
||||
* list_del - deletes entry from list. |
||||
* @entry: the element to delete from the list. |
||||
* Note: list_empty on entry does not return true after this, the entry is |
||||
* in an undefined state. |
||||
*/ |
||||
static inline void list_del(struct list_head *entry) |
||||
{ |
||||
__list_del(entry->prev, entry->next); |
||||
entry->next = NULL; |
||||
entry->prev = NULL; |
||||
} |
||||
|
||||
/*
|
||||
* list_del_init - deletes entry from list and reinitialize it. |
||||
* entry: the element to delete from the list. |
||||
*/ |
||||
static inline void list_del_init(struct list_head *entry) |
||||
{ |
||||
__list_del(entry->prev, entry->next); |
||||
INIT_LIST_HEAD(entry); |
||||
} |
||||
|
||||
/*
|
||||
* list_move - delete from one list and add as another's head |
||||
* @list: the entry to move |
||||
* @head: the head that will precede our entry |
||||
*/ |
||||
static inline void list_move(struct list_head *list, struct list_head *head) |
||||
{ |
||||
__list_del(list->prev, list->next); |
||||
list_add(list, head); |
||||
} |
||||
|
||||
/*
|
||||
* list_move_tail - delete from one list and add as another's tail |
||||
* @list: the entry to move |
||||
* @head: the head that will follow our entry |
||||
*/ |
||||
static inline void list_move_tail(struct list_head *list, |
||||
struct list_head *head) |
||||
{ |
||||
__list_del(list->prev, list->next); |
||||
list_add_tail(list, head); |
||||
} |
||||
|
||||
/*
|
||||
* list_empty - tests whether a list is empty |
||||
* @head: the list to test. |
||||
*/ |
||||
static inline int list_empty(const struct list_head *head) |
||||
{ |
||||
return head->next == head; |
||||
} |
||||
|
||||
static inline void __list_splice(struct list_head *list, |
||||
struct list_head *head) |
||||
{ |
||||
struct list_head *first = list->next; |
||||
struct list_head *last = list->prev; |
||||
struct list_head *at = head->next; |
||||
|
||||
first->prev = head; |
||||
head->next = first; |
||||
|
||||
last->next = at; |
||||
at->prev = last; |
||||
} |
||||
|
||||
/*
|
||||
* list_splice - join two lists |
||||
* @list: the new list to add. |
||||
* @head: the place to add it in the first list. |
||||
*/ |
||||
static inline void list_splice(struct list_head *list, struct list_head *head) |
||||
{ |
||||
if (!list_empty(list)) |
||||
__list_splice(list, head); |
||||
} |
||||
|
||||
/*
|
||||
* list_splice_init - join two lists and reinitialise the emptied list. |
||||
* @list: the new list to add. |
||||
* @head: the place to add it in the first list. |
||||
* |
||||
* The list at @list is reinitialised |
||||
*/ |
||||
static inline void list_splice_init(struct list_head *list, |
||||
struct list_head *head) |
||||
{ |
||||
if (!list_empty(list)) { |
||||
__list_splice(list, head); |
||||
INIT_LIST_HEAD(list); |
||||
} |
||||
} |
||||
|
||||
/*
|
||||
* list_entry - get the struct for this entry |
||||
* @ptr: the &struct list_head pointer. |
||||
* @type: the type of the struct this is embedded in. |
||||
* @member: the name of the list_struct within the struct. |
||||
*/ |
||||
#define list_entry(ptr, type, member) \ |
||||
container_of(ptr, type, member) |
||||
|
||||
/*
|
||||
* list_for_each - iterate over a list |
||||
* @pos: the &struct list_head to use as a loop counter. |
||||
* @head: the head for your list. |
||||
*/ |
||||
#define list_for_each(pos, head) \ |
||||
for (pos = (head)->next; pos != (head); pos = pos->next) |
||||
|
||||
/*
|
||||
* list_for_each_prev - iterate over a list backwards |
||||
* @pos: the &struct list_head to use as a loop counter. |
||||
* @head: the head for your list. |
||||
*/ |
||||
#define list_for_each_prev(pos, head) \ |
||||
for (pos = (head)->prev; pos != (head); pos = pos->prev) |
||||
|
||||
/*
|
||||
* list_for_each_safe - iterate over a list safe against removal of list entry |
||||
* @pos: the &struct list_head to use as a loop counter. |
||||
* @n: another &struct list_head to use as temporary storage |
||||
* @head: the head for your list. |
||||
*/ |
||||
#define list_for_each_safe(pos, n, head) \ |
||||
for (pos = (head)->next, n = pos->next; pos != (head); \
|
||||
pos = n, n = pos->next) |
||||
|
||||
/*
|
||||
* list_for_each_entry - iterate over list of given type |
||||
* @pos: the type * to use as a loop counter. |
||||
* @head: the head for your list. |
||||
* @member: the name of the list_struct within the struct. |
||||
*/ |
||||
#define list_for_each_entry(pos, head, member) \ |
||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.next, typeof(*pos), member)) |
||||
|
||||
/*
|
||||
* list_for_each_entry_reverse - iterate backwards over list of given type. |
||||
* @pos: the type * to use as a loop counter. |
||||
* @head: the head for your list. |
||||
* @member: the name of the list_struct within the struct. |
||||
*/ |
||||
#define list_for_each_entry_reverse(pos, head, member) \ |
||||
for (pos = list_entry((head)->prev, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry(pos->member.prev, typeof(*pos), member)) |
||||
|
||||
/*
|
||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry |
||||
* @pos: the type * to use as a loop counter. |
||||
* @n: another type * to use as temporary storage |
||||
* @head: the head for your list. |
||||
* @member: the name of the list_struct within the struct. |
||||
*/ |
||||
#define list_for_each_entry_safe(pos, n, head, member) \ |
||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
||||
&pos->member != (head); \
|
||||
pos = n, n = list_entry(n->member.next, typeof(*n), member)) |
||||
|
||||
|
||||
/* Return pointer to first true entry, if any, or NULL. A macro
|
||||
required to allow inlining of cmpfn. */ |
||||
#define LIST_FIND(head, cmpfn, type, args...) \ |
||||
({ \
|
||||
const struct list_head *__i, *__j = NULL; \
|
||||
\
|
||||
list_for_each(__i, (head)) \
|
||||
if (cmpfn((const type)__i , ## args)) { \
|
||||
__j = __i; \
|
||||
break; \
|
||||
} \
|
||||
(type)__j; \
|
||||
}) |
||||
|
||||
#endif /* _LIST_H_ */ |
@ -0,0 +1,103 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 06/2006 by Olaf Rempel * |
||||
* razzor@kopf-tisch.de * |
||||
* * |
||||
* 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., * |
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
||||
***************************************************************************/ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <time.h> |
||||
#include <stdarg.h> |
||||
#include <errno.h> |
||||
#include <string.h> |
||||
|
||||
#include "logging.h" |
||||
|
||||
#define BUFSIZE 8192 |
||||
|
||||
static FILE *log_fd = NULL; |
||||
static char *buffer = NULL; |
||||
|
||||
void log_print(int prio, const char *fmt, ...) |
||||
{ |
||||
va_list az; |
||||
int len; |
||||
|
||||
if (buffer == NULL) { |
||||
buffer = malloc(BUFSIZE); |
||||
if (buffer == NULL) { |
||||
fprintf(stderr, "log_print: out of memory\nBailing out!\n"); |
||||
exit(-1); |
||||
} |
||||
} |
||||
|
||||
va_start(az, fmt); |
||||
len = vsnprintf(buffer, BUFSIZE, fmt, az); |
||||
va_end(az); |
||||
|
||||
if (len < 0 || len >= BUFSIZE) { |
||||
log_print(LOG_ERROR, "log_print: arguments too long"); |
||||
errno = 0; |
||||
return; |
||||
} |
||||
|
||||
if (errno) { |
||||
strncpy(buffer + len, ": ", BUFSIZE - len); |
||||
len += 2; |
||||
strncpy(buffer + len, strerror(errno), BUFSIZE - len); |
||||
} |
||||
|
||||
if (log_fd) { |
||||
char tbuf[64]; |
||||
time_t tzgr; |
||||
|
||||
time(&tzgr); |
||||
strftime(tbuf, sizeof(tbuf), "%b %d %H:%M:%S :", localtime(&tzgr)); |
||||
|
||||
fprintf(log_fd, "%s %s\n", tbuf, buffer); |
||||
fflush(log_fd); |
||||
|
||||
} else { |
||||
fprintf(stderr, "%s\n", buffer); |
||||
} |
||||
|
||||
errno = 0; |
||||
} |
||||
|
||||
static void log_close(void) |
||||
{ |
||||
if (buffer) |
||||
free(buffer); |
||||
|
||||
fclose(log_fd); |
||||
} |
||||
|
||||
int log_init(char *logfile) |
||||
{ |
||||
log_fd = fopen(logfile, "a"); |
||||
if (log_fd == NULL) { |
||||
log_print(LOG_ERROR, "log_open('%s'): %s", logfile); |
||||
return 0; |
||||
} |
||||
|
||||
if (atexit(log_close) != 0) { |
||||
log_print(LOG_ERROR, "log_open(): atexit()"); |
||||
return 0; |
||||
} |
||||
|
||||
log_print(LOG_EVERYTIME, "=========================="); |
||||
return 1; |
||||
} |
@ -0,0 +1,16 @@
|
||||
#ifndef _LOGGING_H_ |
||||
#define _LOGGING_H_ |
||||
|
||||
#define LOG_DEBUG 5 |
||||
#define LOG_INFO 4 |
||||
#define LOG_NOTICE 3 |
||||
#define LOG_WARN 2 |
||||
#define LOG_ERROR 1 |
||||
#define LOG_CRIT 0 |
||||
|
||||
#define LOG_EVERYTIME 0 |
||||
|
||||
int log_init(char *logfile); |
||||
void log_print(int prio, const char *fmt, ... ); |
||||
|
||||
#endif /* _LOGGING_H_ */ |
@ -0,0 +1,117 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 06/2006 by Olaf Rempel * |
||||
* razzor@kopf-tisch.de * |
||||
* * |
||||
* 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., * |
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
||||
***************************************************************************/ |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <sys/ioctl.h> |
||||
#include <sys/types.h> |
||||
#include <sys/socket.h> |
||||
#include <net/if.h> |
||||
#include <netinet/in.h> |
||||
#include <arpa/inet.h> |
||||
|
||||
#include "configfile.h" |
||||
#include "logging.h" |
||||
|
||||
static struct sockaddr_in dest_addr; |
||||
|
||||
int mcast_init() |
||||
{ |
||||
struct ip_mreq multiaddr; |
||||
struct ifreq ifr; |
||||
char *mcastdev, *mcastgroup; |
||||
int mcastport, sock; |
||||
|
||||
// open socket
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0); |
||||
if (sock == -1) { |
||||
log_print(LOG_ERROR, "mcast_init: socket()"); |
||||
return -1; |
||||
} |
||||
|
||||
// get device flags
|
||||
mcastdev = config_get_string("global", "mcastdev", "eth0"); |
||||
strncpy(ifr.ifr_name, mcastdev, sizeof(ifr.ifr_name)); |
||||
if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) { |
||||
log_print(LOG_WARN, "mcast_init: ioctl(SIOCGIFFLAGS)"); |
||||
close(sock); |
||||
return -1; |
||||
} |
||||
|
||||
// check device flags
|
||||
if ((ifr.ifr_flags & (IFF_UP | IFF_MULTICAST)) != (IFF_UP | IFF_MULTICAST)) { |
||||
log_print(LOG_WARN, "mcast_init: device %s not up"); |
||||
close(sock); |
||||
return -1; |
||||
} |
||||
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, sizeof(ifr.ifr_name)) < 0) { |
||||
log_print(LOG_WARN, "mcast_init: setsockopt(SO_BINDTODEVICE)"); |
||||
// close(sock);
|
||||
// return -1;
|
||||
} |
||||
|
||||
mcastgroup = config_get_string("global", "mcastgroup", "224.0.0.1"); |
||||
mcastport = config_get_int("global", "mcastport", 2000); |
||||
|
||||
dest_addr.sin_family = AF_INET; |
||||
inet_aton(mcastgroup, &dest_addr.sin_addr); |
||||
dest_addr.sin_port = htons(mcastport); |
||||
|
||||
if (bind(sock, (struct sockaddr*)&dest_addr, sizeof(dest_addr)) < 0) { |
||||
log_print(LOG_WARN, "mcast_init: bind()"); |
||||
return -1; |
||||
} |
||||
|
||||
// get interface address
|
||||
if (ioctl(sock, SIOCGIFADDR, &ifr) != 0) { |
||||
log_print(LOG_WARN, "mcast_init: ioctl(SIOCGIFADDR)"); |
||||
close(sock); |
||||
return -1; |
||||
} |
||||
|
||||
// check address family
|
||||
if (ifr.ifr_addr.sa_family != AF_INET) { |
||||
log_print(LOG_WARN, "mcast_init: unknown address family"); |
||||
close(sock); |
||||
return -1; |
||||
} |
||||
|
||||
inet_aton(mcastgroup, &multiaddr.imr_multiaddr); |
||||
multiaddr.imr_interface.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr; |
||||
|
||||
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, |
||||
&multiaddr, sizeof(multiaddr)) == -1) { |
||||
log_print(LOG_WARN, "mcast_init: setsockopt(IP_ADD_MEMBERSHIP)"); |
||||
close(sock); |
||||
return -1; |
||||
} |
||||
|
||||
return sock; |
||||
} |
||||
|
||||
int mcast_send(int sock, char *buf, int len) |
||||
{ |
||||
return sendto(sock, buf, len, MSG_NOSIGNAL, (const struct sockaddr*)&dest_addr, sizeof(dest_addr)); |
||||
} |
||||
|
||||
void msock_close(int sock) |
||||
{ |
||||
close(sock); |
||||
} |
@ -0,0 +1,10 @@
|
||||
#ifndef _MULTICAST_H_ |
||||
#define _MULTICAST_H_ |
||||
|
||||
int mcast_init(); |
||||
|
||||
int mcast_send(int sock, char *buf, int len); |
||||
|
||||
void msock_close(int sock); |
||||
|
||||
#endif // _MULTICAST_H_
|
@ -0,0 +1,74 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 06/2006 by Olaf Rempel * |
||||
* razzor@kopf-tisch.de * |
||||
* * |
||||
* 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., * |
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
||||
***************************************************************************/ |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <sys/types.h> |
||||
#include <sys/socket.h> |
||||
#include <sys/un.h> |
||||
#include <sys/stat.h> |
||||
|
||||
#include "configfile.h" |
||||
#include "logging.h" |
||||
|
||||
#define DEFAULT_SOCKET "/tmp/cachesyncd" |
||||
|
||||
int sock_init() |
||||
{ |
||||
struct sockaddr_un addr; |
||||
char *filename; |
||||
mode_t old_umask; |
||||
int sockfd, len, status; |
||||
|
||||
sockfd = socket(AF_UNIX, SOCK_STREAM, 0); |
||||
if (sockfd == -1) { |
||||
log_print(LOG_ERROR, "unixsock: socket()"); |
||||
return -1; |
||||
} |
||||
|
||||
filename = config_get_string("global", "socket", DEFAULT_SOCKET); |
||||
|
||||
addr.sun_family = AF_UNIX; |
||||
strncpy(addr.sun_path, filename, sizeof(addr.sun_path)); |
||||
len = sizeof(addr.sun_family) + strlen(addr.sun_path); |
||||
|
||||
old_umask = umask(0077); |
||||
status = bind(sockfd, (struct sockaddr *) &addr, len); |
||||
umask(old_umask); |
||||
|
||||
if (status == -1) { |
||||
log_print(LOG_ERROR, "unixsock: bind()"); |
||||
return -1; |
||||
} |
||||
|
||||
return sockfd; |
||||
} |
||||
|
||||
void sock_close(int sockfd) |
||||
{ |
||||
char *filename; |
||||
int status; |
||||
|
||||
close(sockfd); |
||||
|
||||
filename = config_get_string("global", "socket", DEFAULT_SOCKET); |
||||
status = unlink(filename); |
||||
if (status == -1) |
||||
log_print(LOG_WARN, "unixsock: unlink()"); |
||||
} |
Loading…
Reference in new issue