500 lines
12 KiB
C
500 lines
12 KiB
C
/*
|
|
** $Id: vboxrc.c,v 1.1 1998/07/06 09:05:37 michael Exp $
|
|
**
|
|
** Copyright 1996-1998 Michael 'Ghandi' Herold <michael@abadonna.mayn.de>
|
|
**
|
|
** $Log: vboxrc.c,v $
|
|
** Revision 1.1 1998/07/06 09:05:37 michael
|
|
** - New control file code added. The controls are not longer only empty
|
|
** files - they can contain additional informations.
|
|
** - Control "vboxctrl-answer" added.
|
|
** - Control "vboxctrl-suspend" added.
|
|
** - Locking mechanism added.
|
|
** - Configuration parsing added.
|
|
** - Some code cleanups.
|
|
**
|
|
*/
|
|
|
|
#include "../config.h"
|
|
|
|
#if TIME_WITH_SYS_TIME
|
|
# include <sys/time.h>
|
|
# include <time.h>
|
|
#else
|
|
# if HAVE_SYS_TIME_H
|
|
# include <sys/time.h>
|
|
# else
|
|
# include <time.h>
|
|
# endif
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <limits.h>
|
|
|
|
#include "vboxrc.h"
|
|
#include "log.h"
|
|
#include "stringutils.h"
|
|
|
|
/** Variables ************************************************************/
|
|
|
|
static char *weekdaynames[] =
|
|
{
|
|
"SO" , "MO" , "DI" , "MI" , "DO" , "FR" , "SA" ,
|
|
"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT",
|
|
|
|
NULL
|
|
};
|
|
|
|
/** Prototypes ***********************************************************/
|
|
|
|
static int vboxrc_check_user_section(FILE *, struct vboxcall *, char *);
|
|
static int vboxrc_goto_section(FILE *, char *);
|
|
static int vboxrc_parse_time(char *);
|
|
static int vboxrc_parse_days(char *);
|
|
static time_t vboxrc_return_time(time_t, char *, int);
|
|
static void vboxrc_return_timestr(time_t, char *);
|
|
|
|
/*************************************************************************/
|
|
/** vboxrc_parse(): Liest die "vboxrc" eines Benutzers ein und gibt **/
|
|
/** die Anzahl der Klingelzeichen zurück nach denen **/
|
|
/** der Anruf beantwortet werden soll. **/
|
|
/*************************************************************************/
|
|
/** => call Zeiger auf die Call-Struktur. **/
|
|
/** => home Spoolverzeichnis des Benutzers. **/
|
|
/** => id Eingegangene CallerID. **/
|
|
/*************************************************************************/
|
|
|
|
int vboxrc_parse(struct vboxcall *call, char *home, char *id)
|
|
{
|
|
char line[VBOXRC_MAX_RCLINE + 1];
|
|
char name[PATH_MAX + 1];
|
|
FILE *rc;
|
|
int nr;
|
|
char *dummy;
|
|
char *owner;
|
|
char *phone;
|
|
char *table;
|
|
int i;
|
|
|
|
printstring(name, "%s/vboxrc", home);
|
|
|
|
log_line(LOG_D, "Parsing \"%s\"...\n", name);
|
|
|
|
xstrncpy(call->name , "*** Unknown ***", VBOXRC_MAX_RCLINE);
|
|
xstrncpy(call->section, "*** Unknown ***", VBOXRC_MAX_RCLINE);
|
|
xstrncpy(call->script , "answercall.tcl" , VBOXRC_MAX_RCLINE);
|
|
|
|
call->ringring = 0;
|
|
call->tollring = 0;
|
|
call->savetime = 90;
|
|
|
|
if ((rc = fopen(name, "r")))
|
|
{
|
|
if (vboxrc_goto_section(rc, "[CALLERID]") == 0)
|
|
{
|
|
log_line(LOG_D, "Searching callerid \"%s\"...\n", id);
|
|
|
|
while (fgets(line, (VBOXRC_MAX_RCLINE - 3), rc))
|
|
{
|
|
line[strlen(line) - 1] = '\0';
|
|
|
|
if ((*line == '\0') || (*line == '#')) continue;
|
|
if ((*line == '[' ) || (*line == ']')) break;
|
|
|
|
dummy = line;
|
|
owner = NULL;
|
|
table = NULL;
|
|
phone = NULL;
|
|
|
|
while (isspace(*dummy)) dummy++;
|
|
|
|
if ((*dummy) && (dummy)) phone = strsep(&dummy, "\t ");
|
|
|
|
while (isspace(*dummy)) dummy++;
|
|
|
|
if ((*dummy) && (phone)) table = strsep(&dummy, "\t ");
|
|
|
|
while (isspace(*dummy)) dummy++;
|
|
|
|
if ((*dummy) && (table)) owner = dummy;
|
|
|
|
if ((owner) && (phone) && (table))
|
|
{
|
|
if (fnmatch(phone, id, 0) == 0)
|
|
{
|
|
xstrncpy(call->name, owner, VBOXRC_MAX_RCLINE);
|
|
|
|
switch (*table)
|
|
{
|
|
case '*':
|
|
printstring(call->section, "[%s]", "default");
|
|
break;
|
|
|
|
case '-':
|
|
printstring(call->section, "[%s]", owner);
|
|
break;
|
|
|
|
default:
|
|
printstring(call->section, "[%s]", table);
|
|
break;
|
|
}
|
|
|
|
log_line(LOG_D, "Found - name is \"%s\".\n", call->name);
|
|
|
|
for (i = 0; i < strlen(call->section); i++)
|
|
{
|
|
call->section[i] = toupper(call->section[i]);
|
|
}
|
|
|
|
nr = vboxrc_check_user_section(rc, call, call->section);
|
|
|
|
fclose(rc);
|
|
return(nr);
|
|
}
|
|
}
|
|
}
|
|
|
|
log_line(LOG_W, "Unable to locate \"%s\" settings.\n", id);
|
|
}
|
|
else log_line(LOG_W, "Can't seek to section \"[CALLERID]\".\n");
|
|
|
|
fclose(rc);
|
|
}
|
|
else log_line(LOG_W, "Can't open \"%s\".\n", name);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/** vboxrc_check_user_section(): **/
|
|
/*************************************************************************/
|
|
|
|
static int vboxrc_check_user_section(FILE *rc, struct vboxcall *call, char *section)
|
|
{
|
|
char line[VBOXRC_MAX_RCLINE + 1];
|
|
char *time;
|
|
char *days;
|
|
char *name;
|
|
char *save;
|
|
char *ring;
|
|
char *toll;
|
|
char *stop;
|
|
|
|
if (vboxrc_goto_section(rc, section) == 0)
|
|
{
|
|
while (fgets(line, (VBOXRC_MAX_RCLINE - 3), rc))
|
|
{
|
|
line[strlen(line) - 1] = '\0';
|
|
|
|
if ((*line == '\0') || (*line == '#')) continue;
|
|
if ((*line == '[' ) || (*line == ']')) break;
|
|
|
|
time = strtok(line, "\t ");
|
|
days = strtok(NULL, "\t ");
|
|
name = strtok(NULL, "\t ");
|
|
save = strtok(NULL, "\t ");
|
|
ring = strtok(NULL, "\t ");
|
|
toll = strtok(NULL, "\t ");
|
|
|
|
if ((time) && (days) && (name) && (save) && (ring) && (toll))
|
|
{
|
|
if (vboxrc_parse_time(time) == 0)
|
|
{
|
|
if (vboxrc_parse_days(days) == 0)
|
|
{
|
|
call->ringring = xstrtol(ring, 0);
|
|
call->tollring = xstrtol(toll, 0);
|
|
call->savetime = xstrtol(save, 0);
|
|
|
|
if ((stop = rindex(name, '/')))
|
|
{
|
|
stop++;
|
|
|
|
xstrncpy(call->script, stop, VBOXRC_MAX_RCLINE);
|
|
}
|
|
else xstrncpy(call->script, name, VBOXRC_MAX_RCLINE);
|
|
|
|
if (call->tollring > 0)
|
|
{
|
|
}
|
|
|
|
return(call->ringring);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else log_line(LOG_W, "Can't seek to section \"%s\".\n", section);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/** vboxrc_goto_section(): **/
|
|
/*************************************************************************/
|
|
|
|
static int vboxrc_goto_section(FILE *rc, char *section)
|
|
{
|
|
char line[VBOXRC_MAX_RCLINE + 1];
|
|
|
|
log_line(LOG_D, "Seeking to section \"%s\"...\n", section);
|
|
|
|
rewind(rc);
|
|
|
|
while (fgets(line, (VBOXRC_MAX_RCLINE - 3), rc))
|
|
{
|
|
line[strlen(line) - 1] = '\0';
|
|
|
|
if ((*line == '\0') || (*line == '#')) continue;
|
|
|
|
if (strcasecmp(line, section) == 0) return(0);
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/** vboxrc_parse_time(): Checks if one or more timestring match the **/
|
|
/** current time. **/
|
|
/*************************************************************************/
|
|
|
|
static int vboxrc_parse_time(char *timestr)
|
|
{
|
|
char timestring[VBOXRC_MAX_RCLINE + 1];
|
|
char timevaluebeg[8 + 1];
|
|
char timevalueend[8 + 1];
|
|
char timevaluenow[8 + 1];
|
|
char *timeptr;
|
|
char *timenxt;
|
|
char *timebeg;
|
|
char *timeend;
|
|
time_t timenow;
|
|
time_t timesecsbeg;
|
|
time_t timesecsend;
|
|
|
|
log_line(LOG_D, "Parsing time(s) \"%s\"...\n", timestr);
|
|
|
|
xstrncpy(timestring, timestr, VBOXRC_MAX_RCLINE);
|
|
|
|
timeptr = timestring;
|
|
timenow = time(NULL);
|
|
|
|
vboxrc_return_timestr(timenow, timevaluenow);
|
|
|
|
if (strcmp(timestring, "*") == 0)
|
|
{
|
|
log_line(LOG_D, "Range **:**:** - **:**:** (%s): match.\n", timevaluenow);
|
|
|
|
return(0);
|
|
}
|
|
|
|
if ((strcmp(timestring, "!") == 0) || (strcmp(timestring, "-") == 0))
|
|
{
|
|
log_line(LOG_D, "Range --:--:-- - --:--:-- (%s): don't match.\n", timevaluenow);
|
|
|
|
return(-1);
|
|
}
|
|
|
|
while (timeptr)
|
|
{
|
|
if ((timenxt = index(timeptr, ','))) *timenxt++ = '\0';
|
|
|
|
timebeg = timeptr;
|
|
timeend = index(timebeg, '-');
|
|
|
|
if (timeend)
|
|
*timeend++ = '\0';
|
|
else
|
|
timeend = timebeg;
|
|
|
|
if (!timeend) timeend = timebeg;
|
|
|
|
timesecsbeg = vboxrc_return_time(timenow, timebeg, 0);
|
|
timesecsend = vboxrc_return_time(timenow, timeend, 1);
|
|
|
|
if ((timesecsbeg > 0) && (timesecsend > 0))
|
|
{
|
|
if ((timesecsend >= timesecsbeg))
|
|
{
|
|
vboxrc_return_timestr(timesecsbeg, timevaluebeg);
|
|
vboxrc_return_timestr(timesecsend, timevalueend);
|
|
vboxrc_return_timestr(timenow , timevaluenow);
|
|
|
|
log_line(LOG_D, "Range %s - %s (%s): ", timevaluebeg, timevalueend, timevaluenow);
|
|
|
|
if ((timenow >= timesecsbeg) && (timenow <= timesecsend))
|
|
{
|
|
log_text(LOG_D, "match.\n");
|
|
|
|
return(0);
|
|
}
|
|
else log_text(LOG_D, "don't match.\n");
|
|
}
|
|
else log_line(LOG_W, "Bad time; start greater than end (%s-%s) - ignored...\n", timebeg, timeend);
|
|
}
|
|
else log_line(LOG_W, "Bad time; can't convert timestring (%s-%s) - ignored...\n", timebeg, timeend);
|
|
|
|
timeptr = timenxt;
|
|
}
|
|
|
|
log_line(LOG_D, "String contains no matching time!\n");
|
|
|
|
return(-1);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/** vboxrc_parse_days(): Checks if one or more daystrings match the **/
|
|
/** current day. **/
|
|
/*************************************************************************/
|
|
|
|
static int vboxrc_parse_days(char *strdays)
|
|
{
|
|
struct tm *timelocal;
|
|
char *beg;
|
|
char *nxt;
|
|
char days[VBOXRC_MAX_RCLINE + 1];
|
|
int i;
|
|
int d;
|
|
time_t currenttime;
|
|
|
|
xstrncpy(days, strdays, VBOXRC_MAX_RCLINE);
|
|
|
|
log_line(LOG_D, "Parsing day(s) \"%s\"...\n", days);
|
|
|
|
if (strcmp(days, "*") == 0)
|
|
{
|
|
log_line(LOG_D, "Range *: match.\n");
|
|
|
|
return(0);
|
|
}
|
|
|
|
if ((strcmp(days, "-") == 0) || (strcmp(days, "!") == 0))
|
|
{
|
|
log_line(LOG_D, "Range -: don't match.\n");
|
|
|
|
return(-1);
|
|
}
|
|
|
|
currenttime = time(NULL);
|
|
|
|
if (!(timelocal = localtime(¤ttime)))
|
|
{
|
|
log_line(LOG_E, "Can't get local time (don't match)...\n");
|
|
|
|
return(-1);
|
|
}
|
|
|
|
for (i = 0; i < strlen(days); i++)
|
|
{
|
|
if ((!isalpha(days[i])) && (days[i] != ','))
|
|
{
|
|
log_line(LOG_E, "Error in day string \"%s\" (don't match).\n", days);
|
|
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
beg = days;
|
|
|
|
while (beg)
|
|
{
|
|
if ((nxt = index(beg, ','))) *nxt++ = 0;
|
|
|
|
d = 0;
|
|
i = 0;
|
|
|
|
while (weekdaynames[i])
|
|
{
|
|
if (strcasecmp(weekdaynames[i], beg) == 0)
|
|
{
|
|
if (d == timelocal->tm_wday)
|
|
{
|
|
log_line(LOG_D, "Range %s: match.\n", beg);
|
|
|
|
return(0);
|
|
}
|
|
else log_line(LOG_D, "Range %s: don't match.\n", beg);
|
|
}
|
|
|
|
d++;
|
|
i++;
|
|
|
|
if (d >= 7) d = 0;
|
|
}
|
|
|
|
beg = nxt;
|
|
}
|
|
|
|
log_line(LOG_D, "String contains no matching day!\n");
|
|
|
|
return(-1);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/** vboxrc_return_time(): Converts a time string to seconds since the **/
|
|
/** 1st januar 1970. **/
|
|
/*************************************************************************/
|
|
|
|
static time_t vboxrc_return_time(time_t timenow, char *timestr, int mode)
|
|
{
|
|
struct tm *locala;
|
|
struct tm localb;
|
|
|
|
char timestring[5 + 1];
|
|
char *hourstr;
|
|
char *minsstr;
|
|
int hourint;
|
|
int minsint;
|
|
int secsint;
|
|
|
|
xstrncpy(timestring, timestr, 5);
|
|
|
|
hourstr = timestring;
|
|
minsstr = index(hourstr, ':');
|
|
|
|
if (!minsstr)
|
|
{
|
|
if (mode == 0) minsstr = "00";
|
|
if (mode != 0) minsstr = "59";
|
|
}
|
|
else *minsstr++ = '\0';
|
|
|
|
if (mode == 0) secsint = 0;
|
|
else secsint = 59;
|
|
|
|
hourint = atoi(hourstr);
|
|
minsint = atoi(minsstr);
|
|
|
|
if ((hourint < 0) || (hourint > 23)) return(0);
|
|
if ((minsint < 0) || (minsint > 59)) return(0);
|
|
|
|
if (!(locala = localtime(&timenow))) return(0);
|
|
|
|
memcpy(&localb, locala, sizeof(struct tm));
|
|
|
|
localb.tm_sec = secsint;
|
|
localb.tm_min = minsint;
|
|
localb.tm_hour = hourint;
|
|
|
|
return(mktime(&localb));
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/** vboxrc_return_timestr(): Converts a unix time into a string like **/
|
|
/** HH:MM:SS. **/
|
|
/*************************************************************************/
|
|
|
|
static void vboxrc_return_timestr(time_t timeint, char *timestr)
|
|
{
|
|
struct tm *tm;
|
|
|
|
if ((tm = localtime(&timeint)))
|
|
{
|
|
if (strftime(timestr, 20, "%H:%M:%S", tm) == 8) return;
|
|
}
|
|
|
|
xstrncpy(timestr, "??:??:??", 8);
|
|
}
|