33#if !defined(POPT_ARGFLAG_SHOW_DEFAULT)
34#define POPT_ARGFLAG_SHOW_DEFAULT 0x00800000
45 unsigned char *p = *pp;
53 if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
56 return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
60 if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
63 return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
67 if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
70 return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
74 if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
75 || (p[4] & 0xC0) != 0x80)
78 return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
82 if ((*p == 0xFC && p[1] < 0x84) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
83 || (p[4] & 0xC0) != 0x80 || (p[5] & 0xC0) != 0x80)
86 return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) +
99static char txqcheck (
char *dir,
char *queue,
char subaddress,
char *channel,
char *callerid,
int wait,
int delay,
int retries,
int concurrent)
107 int ql = strlen (queue), qfl = ql;
109 snprintf (dirname,
sizeof(dirname),
"sms/%s", dir);
110 d = opendir (dirname);
113 while ((fn = readdir (
d))
114 && !(*fn->d_name !=
'.'
115 && ((!ql && (p = strchr (fn->d_name,
'.'))) || (ql && !strncmp (fn->d_name, queue, ql) && fn->d_name[ql] ==
'.'))));
124 qfl = ql = p - queue;
126 p = strchr (queue,
'-');
127 if (p && p < queue + ql)
132 snprintf (temp,
sizeof(temp),
"sms/.smsq-%d", (
int)getpid ());
133 f = fopen (temp,
"w");
140 fprintf (f,
"Channel: ");
142 fprintf (f,
"Local/%.*s\n", ql, queue);
145 p = strchr (channel,
'/');
150 fprintf (f,
"%.*s%c%s\n", (
int)(p - channel), channel, subaddress, p + 1);
152 fprintf (f,
"%s\n", channel);
154 fprintf (f,
"Callerid: SMS <");
156 fprintf (f,
"%.*s", ql, queue);
159 p = strchr (callerid,
'X');
161 fprintf (f,
"%.*s%c%s", (
int)(p - callerid), callerid, subaddress, p + 1);
163 fprintf (f,
"%s", callerid);
166 fprintf (f,
"Application: SMS\n");
167 fprintf (f,
"Data: %.*s", qfl, queue);
170 fprintf (f,
"\nMaxRetries: %d\n", retries);
171 fprintf (f,
"RetryTime: %d\n", delay);
172 fprintf (f,
"WaitTime: %d\n", wait);
177 while (
try < concurrent)
180 snprintf(ogname,
sizeof(ogname),
"outgoing/smsq.%s.%s.%d", dir, queue,
try);
181 if (!link (temp, ogname))
197static void rxqcheck (
char *dir,
char *queue,
char *process)
204 int ql = strlen (queue);
206 snprintf(temp,
sizeof(temp),
"sms/.smsq-%d", (
int)getpid ());
207 snprintf(dirname,
sizeof(dirname),
"sms/%s", dir);
208 d = opendir (dirname);
211 while ((fn = readdir (
d)))
212 if ((*fn->d_name !=
'.'
213 && ((!ql && (p = strchr (fn->d_name,
'.'))) || (ql && !strncmp (fn->d_name, queue, ql) && fn->d_name[ql] ==
'.'))))
217 unsigned short ud[160];
218 unsigned char udl = 0;
220 snprintf (filename,
sizeof(filename),
"sms/%s/%s", dir, fn->d_name);
221 if (rename (filename, temp))
223 f = fopen (temp,
"r");
248 setenv (
"queue", queue, 1);
250 while (fgets (line,
sizeof (line), f))
252 for (p = line; *p && *p !=
'\n' && *p !=
'\r'; p++);
255 if (!*p || *p ==
';')
267 if (!strcmp (line,
"oa") || !strcmp (line,
"da") || !strcmp (line,
"scts") || !strcmp (line,
"pid")
268 || !strcmp (line,
"dcs") || !strcmp (line,
"mr") || !strcmp (line,
"vp"))
270 else if ((!strcmp (line,
"srr") || !strcmp (line,
"rp")) && atoi (p))
272 else if (!strcmp (line,
"ud"))
277 if (v && v <= 0xFFFF)
280 }
else if (*p ==
'#')
286 if (!strcmp (line,
"udh"))
288 else if (!strcmp (line,
"ud"))
291 while (*p && udl < 160)
293 if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3]))
296 (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 12) +
297 (((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF)) << 8) +
298 (((isalpha (p[2]) ? 9 : 0) + (p[2] & 0xF)) << 4) + ((isalpha (p[3]) ? 9 : 0) + (p[3] & 0xF));
306 if (!strcmp (line,
"ud"))
309 while (*p && udl < 160)
311 if (isxdigit (*p) && isxdigit (p[1]))
313 ud[udl++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
327 for (n = 0, x = 0; x < udl; x++)
329 unsigned short v = ud[x];
336 tmp[n++] = (0xC0 + (v >> 6));
337 tmp[n++] = (0x80 + (v & 0x3F));
340 tmp[n++] = (0xE0 + (v >> 12));
341 tmp[n++] = (0x80 + ((v >> 6) & 0x3F));
342 tmp[n++] = (0x80 + (v & 0x3F));
348 for (n = 0, x = 0; x < udl; x++)
350 unsigned short v = ud[x];
351 if (v <
' ' || v ==
'\\')
366 tmp[n++] =
'0' + (v >> 6);
367 tmp[n++] =
'0' + ((v >> 3) & 7);
368 tmp[n++] =
'0' + (v & 7);
374 tmp[n++] = (0xC0 + (v >> 6));
375 tmp[n++] = (0x80 + (v & 0x3F));
378 tmp[n++] = (0xE0 + (v >> 12));
379 tmp[n++] = (0x80 + ((v >> 6) & 0x3F));
380 tmp[n++] = (0x80 + (v & 0x3F));
385 for (x = 0; x < udl && ud[x] < 0x100; x++);
388 for (n = 0, x = 0; x < udl; x++)
390 sprintf (
tmp + n,
"%02hX", ud[x]);
395 for (n = 0, x = 0; x < udl; x++)
397 sprintf (
tmp + n,
"%04hX", ud[x]);
403 if (system (process) == -1) {
404 fprintf(stderr,
"Failed to fork process '%s'\n", process);
412main (
int argc,
const char *argv[])
438 unsigned short ud[160];
439 unsigned char *uds = 0,
446 *spooldir =
"/var/spool/asterisk",
447 *motxchannel =
"Local/1709400X",
450 *mttxcallerid =
"080058752X0",
451 *defaultsubaddress =
"9",
455 const struct poptOption optionsTable[] = {
457 {
"da",
'd', POPT_ARG_STRING, &da, 0,
"Destination address",
"number"},
458 {
"oa",
'o', POPT_ARG_STRING, &oa, 0,
"Origination address",
"number"},
459 {
"ud",
'm', POPT_ARG_STRING, &uds, 0,
"Message",
"text"},
460 {
"ud-file",
'f', POPT_ARG_STRING, &udfile, 0,
"Message file",
"filename"},
461 {
"UTF-8", 0, POPT_ARG_NONE, &utf8, 0,
"File treated as null terminated UTF-8 (default)", 0},
462 {
"UCS-1", 0, POPT_ARG_NONE, &ucs1, 0,
"File treated as UCS-1", 0},
463 {
"UCS-2", 0, POPT_ARG_NONE, &ucs2, 0,
"File treated as UCS-2", 0},
464 {
"mt",
't', POPT_ARG_NONE, &mt, 0,
"Mobile Terminated", 0},
465 {
"mo", 0, POPT_ARG_NONE, &mo, 0,
"Mobile Originated", 0},
466 {
"tx", 0, POPT_ARG_NONE, &tx, 0,
"Send message", 0},
467 {
"rx",
'r', POPT_ARG_NONE, &rx, 0,
"Queue for receipt", 0},
468 {
"process",
'e', POPT_ARG_STRING, &process, 0,
"Rx queue process command",
"command"},
469 {
"no-dial",
'x', POPT_ARG_NONE, &nodial, 0,
"Do not dial", 0},
470 {
"no-wait", 0, POPT_ARG_NONE, &nowait, 0,
"Do not wait if already calling", 0},
473 {
"motx-callerid", 0, POPT_ARG_STRING, &motxcallerid, 0,
474 "Caller ID for motx calls (default is queue name without sub address)",
"number"},
479 {
"mttx-channel", 0, POPT_ARG_STRING, &mttxchannel, 0,
480 "Channel for mttx calls (default is Local/ and queue name without sub address)",
"channel"},
482 "Caller ID for mttx calls (default is queue name without sub address)",
"number"},
487 {
"mr",
'n', POPT_ARG_INT, &mr, 0,
"Message reference",
"n"},
488 {
"pid",
'p', POPT_ARG_INT, &pid, 0,
"Protocol ID",
"n"},
489 {
"dcs",
'c', POPT_ARG_INT, &dcs, 0,
"Data Coding Scheme",
"n"},
490 {
"udh", 0, POPT_ARG_STRING, &udh, 0,
"User data header",
"hex"},
491 {
"srr", 0, POPT_ARG_NONE, &srr, 0,
"Status Report Request", 0},
492 {
"rp", 0, POPT_ARG_NONE, &rp, 0,
"Return Path request", 0},
493 {
"v", 0, POPT_ARG_INT, &vp, 0,
"Validity Period",
"seconds"},
494 {
"scts", 0, POPT_ARG_STRING, &scts, 0,
"Timestamp",
"YYYY-MM-SSTHH:MM:SS"},
495 {
"default-sub-address", 0, POPT_ARG_STRING |
POPT_ARGFLAG_SHOW_DEFAULT, &defaultsubaddress, 0,
"Default sub address",
"X"},
500 optCon = poptGetContext (
NULL, argc, argv, optionsTable, 0);
501 poptSetOtherOptionHelp (optCon,
"<oa/da> <message>");
504 if ((
c = poptGetNextOpt (optCon)) < -1)
507 fprintf (stderr,
"%s: %s\n", poptBadOption (optCon, POPT_BADOPTION_NOALIAS), poptStrerror (
c));
512 if (utf8 + ucs1 + ucs2 > 1)
514 fprintf (stderr,
"Pick one of UTF-8, UCS-1 or UCS-2 only\n");
517 if (!udfile && (ucs1 || ucs2))
519 fprintf (stderr,
"Command line arguments always treated as UTF-8\n");
523 if (!mt && !mo && process)
525 if (!mt && !mo && oa)
531 fprintf (stderr,
"Cannot be --mt and --mo\n");
534 if (!rx && !tx && process)
540 fprintf (stderr,
"Cannot be --tx and --rx\n");
547 fprintf (stderr,
"Cannot have --ud and --ud-file\n");
550 if (mo && !da && poptPeekArg (optCon))
551 da = (
char *) poptGetArg (optCon);
552 if (mt && !oa && poptPeekArg (optCon))
553 oa = (
char *) poptGetArg (optCon);
556 fprintf (stderr,
"--oa makes no sense with --mo as CLI is used (i.e. queue name)\n");
561 fprintf (stderr,
"--da makes no sense with --mt as called number is used (i.e. queue name)\n");
564 if (da && strlen (da) > 20)
566 fprintf (stderr,
"--da too long\n");
569 if (oa && strlen (oa) > 20)
571 fprintf (stderr,
"--oa too long\n");
574 if (queue && strlen (queue) > 20)
576 fprintf (stderr,
"--queue name too long\n");
581 fprintf (stderr,
"scts is set my service centre\n");
586 while (udl < 160 && *uds)
591 fprintf (stderr,
"Invalid character U+%X at %d\n", v, udl);
597 if (!uds && !udfile && poptPeekArg (optCon))
599 while (poptPeekArg (optCon) && udl < 160)
601 unsigned char *
a = (
unsigned char *) poptGetArg (optCon);
602 if (udl && udl < 160)
604 while (udl < 160 && *
a)
609 fprintf (stderr,
"Invalid character U+%X at %d\n", v, udl);
616 if (poptPeekArg (optCon))
618 fprintf (stderr,
"Unknown argument %s\n", poptGetArg (optCon));
623 unsigned char dat[1204],
629 f = open (udfile, O_RDONLY);
637 n = read (f, dat,
sizeof (dat));
648 while (p < e && udl < 160 && *p)
652 while (p < e && udl < 160)
656 while (p + 1 < e && udl < 160)
658 ud[udl++] = (*p << 8) + p[1];
665 char *
d = strrchr (queue,
'-');
669 subaddress = *defaultsubaddress;
672 if (chdir (spooldir))
682 *dir = (mo ? rx ?
"sms/morx" :
"sms/motx" : rx ?
"sms/mtrx" :
"sms/mttx");
684 snprintf (temp,
sizeof(temp),
"sms/.smsq-%d", (
int)getpid ());
687 snprintf (queuename,
sizeof(queuename),
"%s/%s.%ld-%d", dir, *queue ? queue :
"0", (
long)time (0), (
int)getpid ());
688 f = fopen (temp,
"w");
695 fprintf (f,
"oa=%s\n", oa);
697 fprintf (f,
"da=%s\n", da);
699 fprintf (f,
"scts=%s\n", scts);
701 fprintf (f,
"pid=%d\n", pid);
703 fprintf (f,
"dcs=%d\n", dcs);
705 fprintf (f,
"mr=%d\n", mr);
707 fprintf (f,
"srr=1\n");
709 fprintf (f,
"rp=1\n");
711 fprintf (f,
"udh#%s\n", udh);
713 fprintf (f,
"vp=%d\n", vp);
717 for (p = 0; p < udl && ud[p] < 0x100; p++);
720 for (p = 0; p < udl && ud[p] < 0x80 && ud[p] >= 0x20; p++);
724 for (p = 0; p < udl; p++)
729 for (p = 0; p < udl; p++)
730 fprintf (f,
"%02hX", ud[p]);
735 for (p = 0; p < udl; p++)
736 fprintf (f,
"%04hX", ud[p]);
741 if (rename (temp, queuename))
749 if (!nodial && tx && !process)
758 ret =
txqcheck (
"motx", queue, subaddress, motxchannel, motxcallerid, motxwait, motxdelay, motxretries, concurrent);
760 ret =
txqcheck (
"mttx", queue, subaddress, mttxchannel, mttxcallerid, mttxwait, mttxdelay, mttxretries, concurrent);
766 if (ret == 2 && !nowait)
767 fprintf (stderr,
"No call scheduled as already sending\n");
770 rxqcheck (mo ? rx ?
"morx" :
"motx" : rx ?
"mtrx" :
"mttx", queue, process);
Asterisk main include file. File version handling, generic pbx functions.
int unsetenv(const char *name)
int setenv(const char *name, const char *value, int overwrite)
static char txqcheck(char *dir, char *queue, char subaddress, char *channel, char *callerid, int wait, int delay, int retries, int concurrent)
check for any queued messages in specific queue (queue="" means any queue)
#define POPT_ARGFLAG_SHOW_DEFAULT
static int utf8decode(unsigned char **pp)
reads next USC character from null terminated UTF-8 string and advanced pointer for non valid UTF-8 s...
static void rxqcheck(char *dir, char *queue, char *process)
Process received queue entries Run through a process, setting environment variables.
int main(int argc, const char *argv[])
Time-related functions and macros.