isdn4k-utils/isdnlog/tools/telnum.c

479 lines
11 KiB
C

/* telnum.c
* (c) 1999 by Leopold Toetsch <lt@toetsch.at>
*
* telefon number utils
*
* Copyright 1999 by Leopold Toetsch <lt@toetsch.at>
*
* 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* Interface
*
* void initTelNum(void)
* ---------------------
* init the package, call this once on startup
*
* int normalizeNumber(char *number, TELNUM *num, int flag)
* --------------------------------------------------------
* number is "[provider] [country] [area] [msn]"
* country may be name of country
* spaces or '_' are allowd to separate parts of number
* fills struct TELNUM *num with parts of number
* for flag look at telnum.h
* ret 0 .. ok
* ret UNKNOWN .. not found
*
* Input number e.g.
* 10055 0049 89 1234567
* 100550049891234567
* 1033 Deutschland 89 1234567
* +49 89 1234567
* 089 1234567
* 1234567
*
* char * formatNumber(char* format, TELNUM* num)
* ----------------------------------------------
* takes a format string
* %Np .. Provider
* %Nc .. country +49
* %NC .. countryname
* %Nt .. tld = 2 char isdcode for country
* %Na .. area 89 or 089 if no country/Provider
* %NA .. areaname
* %Nm .. msn
* %f .. full +49 89 12356 (Deutschland, Berlin)
* %F .. full +49 89/12345, Berlin
* %s .. short +48 89 123456
* %l .. long +49 89 12356 - Berlin (DE)
* %n .. number 004889123456
*
* N is number of chars to skip in format if part is not present
* e.g. "%1c %1a %m"
* +4930123 => "+49 39 123"
* 123 => "123" not " 123"
*
*
* char* prefix2provider(int prefix, char* provider)
* --------------------------------------------------------------
* returns formatted provider for prefix
*
* int provider2prefix(char* provider, int*prefix)
* ------------------------------------------------------------
* ret len of provider
*
* void clearNum(TELNUM *num)
* --------------------------
* call this if you have a number on stack or want to reuse it
* normalizeNumber calls this for you
*
* void initNum(TELNUM *num)
* inits a number with myarea, mycountry
* you may set the area yourself prior to calling this
*
* TELNUM * getMynum( void )
* returns a pointer to defaultnum (myara, mycountry ...)
* this number should not be modified
*
*/
#include "dest.h"
#define DEFAULT (UNKNOWN-1)
/* #define DEBUG 1 */
static TELNUM defnum;
TELNUM *getMynum(void)
{
return &defnum;
}
static void error(char *fmt,...)
{
va_list ap;
char msg[BUFSIZ];
va_start(ap, fmt);
vsnprintf(msg, BUFSIZ, fmt, ap);
va_end(ap);
#ifdef STANDALONE
fprintf(stderr, "%s\n", msg);
#else
print_msg(PRT_ERR, "%s\n", msg);
#endif
}
static void _init(void);
void initTelNum(void)
{
if (!vbn)
vbn = "";
if (!vbnlen || !*vbnlen) {
error("VBNLEN not defined.\n\tPlease read isdnlog/README\n");
exit(1);
}
_init();
} /* pre_init */
static int split_vbn(char **p, TELNUM * num)
{
int l;
if ((l = provider2prefix(*p, &num->nprovider))) {
Strncpy(num->provider, *p, l + 1);
*p += l;
return l;
}
return 0;
}
static void clearArea(TELNUM * num, int a)
{
strcpy(num->area, a == DEFAULT ? defnum.area : "");
strcpy(num->sarea, a == DEFAULT ? defnum.sarea : "?");
num->narea = a == DEFAULT ? defnum.narea : a;
}
static inline void clearCountry(TELNUM * num, int c)
{
*num->scountry = '\0';
*num->country = '\0';
num->ncountry = c;
}
int normalizeNumber(char *target, TELNUM * num, int flag)
{
char *origp = strdup(target);
char *p = origp;
int res = 0;
char *q;
clearNum(num);
#if DEBUG
print_msg(PRT_V, "NN %s (Prov %d)=> ", target, num->nprovider);
#endif
if (flag & TN_PROVIDER)
if (!split_vbn(&p, num)) {
num->nprovider = pnum2prefix(preselect,0);
Strncpy(num->provider, getProvider(num->nprovider), TN_MAX_PROVIDER_LEN);
}
if (flag & TN_COUNTRY) {
/* subst '00' => '+' */
if (p[0] == '0' && p[1] == '0')
*++p = '+';
if (getSpecial(p)) { /* sondernummer */
goto is_sonder;
}
if (!isdigit(*p)) {
res = getDest(p, num);
/* isdnrate is coming with +4319430 but this may be a
sondernummer */
if (atoi(mycountry + 1) == num->ncountry && (*num->area || *num->msn)) {
q = malloc(strlen(num->area) + strlen(num->msn) + 1);
strcpy(q, num->area);
strcat(q, num->msn);
if (getSpecial(q)) { /* sondernummer */
clearCountry(num, 0);
*num->sarea = '\0';
Strncpy(num->area, q, TN_MAX_AREA_LEN);
num->narea = atoi(num->area);
*num->msn = '\0';
}
free(q);
}
}
else {
if (getSpecial(p)) { /* sondernummer */
is_sonder:
clearCountry(num, 0);
*num->sarea = '\0';
Strncpy(num->area, p, TN_MAX_AREA_LEN);
num->narea = atoi(num->area);
*num->msn = '\0';
}
else {
clearArea(num, DEFAULT);
if (*p == '0') { /* must be distant call in country */
q = malloc(strlen(mycountry) + strlen(p));
strcpy(q, mycountry);
strcat(q, p + 1);
free(origp);
origp = p = q;
if (getSpecial(p)) { /* sondernummer */
goto is_sonder;
}
res = getDest(p, num);
}
else
Strncpy(num->msn, p, TN_MAX_MSN_LEN);
}
}
}
free(origp);
#if DEBUG
print_msg(PRT_V, "(%d) %s\n", res, formatNumber("%l Prov %p", num));
#endif
return (res);
}
int provider2prefix(char *p, int *prefix)
{
int l1, l2 = 0, len, _prefix;
char *q;
char *vbns = strdup(vbn);
q = strtok(vbns, ":");
while (q) {
l1 = strlen(vbns);
if (!memcmp(p, q, l1)) {
/* Strncpy(num->vbn, q, TN_MAX_VBN_LEN); */
#if DEBUG
print_msg(PRT_V, "VBN \"%s\"\n", q);
#endif
if ((_prefix = vbn2prefix(p, &len)) != UNKNOWN) {
*prefix = _prefix;
l2 = len;
}
break;
}
q = strtok(0, ":");
}
free(vbns);
return l2;
}
void initNum(TELNUM * num)
{
char *s;
if (!*num->area)
Strncpy(num->area, myarea, TN_MAX_AREA_LEN);
num->ncountry = defnum.ncountry;
strcpy(num->scountry, defnum.scountry);
strcpy(num->country, defnum.country);
num->narea = atoi(num->area); /* 1.01 */
s = malloc(strlen(mycountry) + strlen(num->area) + 1);
strcpy(s, mycountry);
strcat(s, num->area);
getDest(s, num);
free(s);
strcpy(num->vbn, defnum.vbn);
}
static void _init(void)
{
char *s;
//clearNum(&defnum);
Strncpy(defnum.area, myarea, TN_MAX_AREA_LEN);
s = malloc(strlen(mycountry) + strlen(myarea) + 1);
strcpy(s, mycountry);
strcat(s, myarea);
getDest(s, &defnum);
Strncpy(defnum.vbn, vbn, TN_MAX_VBN_LEN);
defnum.nprovider=pnum2prefix(preselect,0);
Strncpy(defnum.provider, getProvider(defnum.nprovider), TN_MAX_PROVIDER_LEN);
}
void clearNum(TELNUM * num)
{
memcpy(num, &defnum, sizeof(TELNUM));
}
/* %Np .. Provider
* %Nc .. country +49
* %NC .. countryname
* %Na .. area 89 or 089 if no country/Provider
* %NA .. areaname
* %Nm .. msn
* %f .. full +49 89 12356 (Deutschland, Berlin)
* %s .. short +48 89 123456
* %n .. number 004889123456
* N is number of chars to skip in format if part is not present
* e.g. "%1c %1a %m"
* +4930123 => "+49 30 123"
* 123 => "123" not " 123"
*/
#define SKIP if(skip>0) \
while(skip-- && *p && p[1]) \
p++
char *formatNumber(char *format, TELNUM * num)
{
char *s = retstr[++retnum];
char *p, *q, *r;
int first = 1;
int skip;
retnum %= MAXRET;
*s = '\0';
for (p = format, q = s; *p; p++) {
if (*p == '%') {
skip = 0;
again:
switch (*++p) {
case 'p':
if (num->nprovider > 0) {
q = stpcpy(q, num->provider);
first = 0;
}
else
SKIP;
break;
case 'c':
if (num->ncountry > 0 && num->country) {
q = stpcpy(q, num->country);
first = 0;
}
else
SKIP;
break;
case 'C':
if (num->ncountry > 0)
q = stpcpy(q, num->scountry);
else
SKIP;
break;
case 't': /* tld */
if (*num->tld)
q = stpcpy(q, num->tld);
else
SKIP;
break;
case 'a':
if (num->narea > 0) {
/* if(first) *q++ = '0'; / sondernummber - no country */
q = stpcpy(q, num->area);
}
else
SKIP;
break;
case 'A':
if (*num->sarea)
q = stpcpy(q, num->sarea);
else
SKIP;
break;
case 'm':
if (*num->msn)
q = stpcpy(q, num->msn);
else
SKIP;
break;
case 'f':
q = stpcpy(q, formatNumber("%1c %1a %1m (%2C, %A)", num));
break;
case 'F':
if (num->ncountry == defnum.ncountry)
q = stpcpy(q, formatNumber("%1c %1a/%1m, %A", num));
else
q = stpcpy(q, formatNumber("%1c %1a/%1m, %2C, %A", num));
break;
case 's':
q = stpcpy(q, formatNumber("%1c %1a %m", num));
break;
case 'l':
q = stpcpy(q, formatNumber("%1c %1a %1m - %1A (%t)", num));
break;
case 'n':
if (num->ncountry > 0) {
q = stpcpy(r = ++q, formatNumber("%c%a%m", num));
r[0] = r[1] = '0';
}
else
q = stpcpy(q, formatNumber("%a%m", num));
break;
default:
if (isdigit(*p)) {
skip = strtol(p, &p, 10);
p--;
goto again;
}
}
}
else
*q++ = *p;
}
*q = '\0';
return s;
}
#ifdef TEST_TELNUM
int verbose = 0;
static char *myshortname;
static void init()
{
auto char *version, **message;
if (readconfig(myshortname) < 0)
exit(1);
if (verbose)
message = &version;
else
message = NULL;
initHoliday(holifile, message);
if (verbose && *version)
print_msg(PRT_V, "%s\n", version);
initDest("/usr/lib/isdn/dest.gdbm", message); /* Fixme: */
if (verbose && *version)
print_msg(PRT_V, "%s\n", version);
initRate(rateconf, ratefile, zonefile, message);
if (verbose && *version)
print_msg(PRT_V, "%s\n", version);
initTelNum();
} /* init */
static void deinit(void)
{
exitRate();
exitDest();
exitHoliday();
}
int main(int argc, char *argv[], char *envp[])
{
register int i;
TELNUM num;
myname = argv[0];
myshortname = basename(myname);
if (argc > 1) {
init();
i = argc - 1;
argc++;
while (i--) {
normalizeNumber(argv[argc], &num);
printf("%s => %s\n", argv[argc++], formatNumber("%l", &num));
}
}
return EXIT_SUCCESS;
}
#endif