Asterisk - The Open Source Telephony Project  18.5.0
Macros | Functions
smsq.c File Reference
#include "asterisk.h"
#include <popt.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <ctype.h>
#include <time.h>
Include dependency graph for smsq.c:

Go to the source code of this file.

Macros

#define POPT_ARGFLAG_SHOW_DEFAULT   0x00800000
 

Functions

int main (int argc, const char *argv[])
 
static void rxqcheck (char *dir, char *queue, char *process)
 Process received queue entries Run through a process, setting environment variables. More...
 
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) More...
 
static int utf8decode (unsigned char **pp)
 reads next USC character from null terminated UTF-8 string and advanced pointer for non valid UTF-8 sequences. More...
 

Macro Definition Documentation

◆ POPT_ARGFLAG_SHOW_DEFAULT

#define POPT_ARGFLAG_SHOW_DEFAULT   0x00800000

Definition at line 34 of file smsq.c.

Referenced by main().

Function Documentation

◆ main()

int main ( int  argc,
const char *  argv[] 
)

Definition at line 412 of file smsq.c.

References a, c, d, NULL, POPT_ARGFLAG_SHOW_DEFAULT, rxqcheck(), txqcheck(), and utf8decode().

413 {
414  char c;
415  int mt = 0,
416  mo = 0,
417  tx = 0,
418  rx = 0,
419  nodial = 0,
420  nowait = 0,
421  concurrent = 1,
422  motxwait = 10,
423  motxdelay = 1,
424  motxretries = 10,
425  mttxwait = 10,
426  mttxdelay = 30,
427  mttxretries = 100,
428  mr = -1,
429  pid = -1,
430  dcs = -1,
431  srr = 0,
432  rp = 0,
433  vp = 0,
434  udl = 0,
435  utf8 = 0,
436  ucs1 = 0,
437  ucs2 = 0;
438  unsigned short ud[160];
439  unsigned char *uds = 0,
440  *udh = 0;
441  char *da = 0,
442  *oa = 0,
443  *queue = "",
444  *udfile = 0,
445  *process = 0,
446  *spooldir = "/var/spool/asterisk",
447  *motxchannel = "Local/1709400X",
448  *motxcallerid = 0,
449  *mttxchannel = 0,
450  *mttxcallerid = "080058752X0",
451  *defaultsubaddress = "9",
452  subaddress = 0,
453  *scts = 0;
454  poptContext optCon; /* context for parsing command-line options */
455  const struct poptOption optionsTable[] = {
456  {"queue", 'q', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &queue, 0, "Queue [inc sub address]", "number[-X]"},
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},
471  {"concurrent", 0, POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &concurrent, 0, "Number of concurrent calls to allow", "n"},
472  {"motx-channel", 0, POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &motxchannel, 0, "Channel for motx calls", "channel"},
473  {"motx-callerid", 0, POPT_ARG_STRING, &motxcallerid, 0,
474  "Caller ID for motx calls (default is queue name without sub address)", "number"},
475  {"motx-wait", 0, POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &motxwait, 0, "Time to wait for motx call to answer",
476  "seconds"},
477  {"motx-delay", 0, POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &motxdelay, 0, "Time between motx call retries", "seconds"},
478  {"motx-retries", 0, POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &motxretries, 0, "Number of retries for motx call", "n"},
479  {"mttx-channel", 0, POPT_ARG_STRING, &mttxchannel, 0,
480  "Channel for mttx calls (default is Local/ and queue name without sub address)", "channel"},
481  {"mttx-callerid", 0, POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &mttxcallerid, 0,
482  "Caller ID for mttx calls (default is queue name without sub address)", "number"},
483  {"mttx-wait", 0, POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &mttxwait, 0, "Time to wait for mttx call to answer",
484  "seconds"},
485  {"mttx-delay", 0, POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &mttxdelay, 0, "Time between mttx call retries", "seconds"},
486  {"mttx-retries", 0, POPT_ARG_INT | POPT_ARGFLAG_SHOW_DEFAULT, &mttxretries, 0, "Number of retries for mttx call", "n"},
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"},
496  {"spool-dir", 0, POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &spooldir, 0, "Asterisk spool dir", "dirname"},
497  POPT_AUTOHELP {NULL, 0, 0, NULL, 0}
498  };
499 
500  optCon = poptGetContext (NULL, argc, argv, optionsTable, 0);
501  poptSetOtherOptionHelp (optCon, "<oa/da> <message>");
502 
503  /* Now do options processing, get portname */
504  if ((c = poptGetNextOpt (optCon)) < -1)
505  {
506  /* an error occurred during option processing */
507  fprintf (stderr, "%s: %s\n", poptBadOption (optCon, POPT_BADOPTION_NOALIAS), poptStrerror (c));
508  return 1;
509  }
510  if (!ucs1 && !ucs2)
511  utf8 = 1;
512  if (utf8 + ucs1 + ucs2 > 1)
513  {
514  fprintf (stderr, "Pick one of UTF-8, UCS-1 or UCS-2 only\n");
515  return 1;
516  }
517  if (!udfile && (ucs1 || ucs2))
518  {
519  fprintf (stderr, "Command line arguments always treated as UTF-8\n");
520  return 1;
521  }
522  /* if (!where && poptPeekArg (optCon)) where = (char *) poptGetArg (optCon); */
523  if (!mt && !mo && process)
524  mt = 1;
525  if (!mt && !mo && oa)
526  mt = 1;
527  if (!mt)
528  mo = 1;
529  if (mt && mo)
530  {
531  fprintf (stderr, "Cannot be --mt and --mo\n");
532  return 1;
533  }
534  if (!rx && !tx && process)
535  rx = 1;
536  if (!rx)
537  tx = 1;
538  if (tx && rx)
539  {
540  fprintf (stderr, "Cannot be --tx and --rx\n");
541  return 1;
542  }
543  if (rx)
544  nodial = 1;
545  if (uds && udfile)
546  {
547  fprintf (stderr, "Cannot have --ud and --ud-file\n");
548  return 1;
549  }
550  if (mo && !da && poptPeekArg (optCon))
551  da = (char *) poptGetArg (optCon);
552  if (mt && !oa && poptPeekArg (optCon))
553  oa = (char *) poptGetArg (optCon);
554  if (tx && oa && mo)
555  {
556  fprintf (stderr, "--oa makes no sense with --mo as CLI is used (i.e. queue name)\n");
557  return 1;
558  }
559  if (tx && da && mt)
560  {
561  fprintf (stderr, "--da makes no sense with --mt as called number is used (i.e. queue name)\n");
562  return 1;
563  }
564  if (da && strlen (da) > 20)
565  {
566  fprintf (stderr, "--da too long\n");
567  return 1;
568  }
569  if (oa && strlen (oa) > 20)
570  {
571  fprintf (stderr, "--oa too long\n");
572  return 1;
573  }
574  if (queue && strlen (queue) > 20)
575  {
576  fprintf (stderr, "--queue name too long\n");
577  return 1;
578  }
579  if (mo && scts)
580  {
581  fprintf (stderr, "scts is set my service centre\n");
582  return 1;
583  }
584  if (uds)
585  { /* simple user data command line option in \UTF-8 */
586  while (udl < 160 && *uds)
587  {
588  int v = utf8decode (&uds);
589  if (v > 0xFFFF)
590  {
591  fprintf (stderr, "Invalid character U+%X at %d\n", v, udl);
592  return 1;
593  }
594  ud[udl++] = v;
595  }
596  }
597  if (!uds && !udfile && poptPeekArg (optCon))
598  { /* multiple command line arguments in UTF-8 */
599  while (poptPeekArg (optCon) && udl < 160)
600  {
601  unsigned char *a = (unsigned char *) poptGetArg (optCon);
602  if (udl && udl < 160)
603  ud[udl++] = ' '; /* space between arguments */
604  while (udl < 160 && *a)
605  {
606  int v = utf8decode (&a);
607  if (v > 0xFFFF)
608  {
609  fprintf (stderr, "Invalid character U+%X at %d\n", v, udl);
610  return 1;
611  }
612  ud[udl++] = v;
613  }
614  }
615  }
616  if (poptPeekArg (optCon))
617  {
618  fprintf (stderr, "Unknown argument %s\n", poptGetArg (optCon));
619  return 1;
620  }
621  if (udfile)
622  { /* get message from file */
623  unsigned char dat[1204],
624  *p = dat,
625  *e;
626  int f,
627  n;
628  if (*udfile)
629  f = open (udfile, O_RDONLY);
630  else
631  f = fileno (stdin);
632  if (f < 0)
633  {
634  perror (udfile);
635  return 1;
636  }
637  n = read (f, dat, sizeof (dat));
638  if (n < 0)
639  {
640  perror (udfile);
641  return 1;
642  }
643  if (*udfile)
644  close (f);
645  e = dat + n;
646  if (utf8)
647  { /* UTF-8 */
648  while (p < e && udl < 160 && *p)
649  ud[udl++] = utf8decode (&p);
650  } else if (ucs1)
651  { /* UCS-1 */
652  while (p < e && udl < 160)
653  ud[udl++] = *p++;
654  } else
655  { /* UCS-2 */
656  while (p + 1 < e && udl < 160)
657  {
658  ud[udl++] = (*p << 8) + p[1];
659  p += 2;
660  }
661  }
662  }
663  if (queue)
664  {
665  char *d = strrchr (queue, '-');
666  if (d && d[1])
667  subaddress = d[1];
668  else
669  subaddress = *defaultsubaddress;
670  }
671 
672  if (chdir (spooldir))
673  {
674  perror (spooldir);
675  return 1;
676  }
677 
678  if (oa || da)
679  { /* send message */
680  char temp[100],
681  queuename[100],
682  *dir = (mo ? rx ? "sms/morx" : "sms/motx" : rx ? "sms/mtrx" : "sms/mttx");
683  FILE *f;
684  snprintf (temp, sizeof(temp), "sms/.smsq-%d", (int)getpid ());
685  mkdir ("sms", 0777); /* ensure directory exists */
686  mkdir (dir, 0777); /* ensure directory exists */
687  snprintf (queuename, sizeof(queuename), "%s/%s.%ld-%d", dir, *queue ? queue : "0", (long)time (0), (int)getpid ());
688  f = fopen (temp, "w");
689  if (!f)
690  {
691  perror (temp);
692  return 1;
693  }
694  if (oa)
695  fprintf (f, "oa=%s\n", oa);
696  if (da)
697  fprintf (f, "da=%s\n", da);
698  if (scts)
699  fprintf (f, "scts=%s\n", scts);
700  if (pid >= 0)
701  fprintf (f, "pid=%d\n", pid);
702  if (dcs >= 0)
703  fprintf (f, "dcs=%d\n", dcs);
704  if (mr >= 0)
705  fprintf (f, "mr=%d\n", mr);
706  if (srr)
707  fprintf (f, "srr=1\n");
708  if (rp)
709  fprintf (f, "rp=1\n");
710  if (udh)
711  fprintf (f, "udh#%s\n", udh);
712  if (vp > 0)
713  fprintf (f, "vp=%d\n", vp);
714  if (udl)
715  {
716  int p;
717  for (p = 0; p < udl && ud[p] < 0x100; p++);
718  if (p == udl)
719  {
720  for (p = 0; p < udl && ud[p] < 0x80 && ud[p] >= 0x20; p++);
721  if (p == udl)
722  { /* use text */
723  fprintf (f, "ud=");
724  for (p = 0; p < udl; p++)
725  fputc (ud[p], f);
726  } else
727  { /* use one byte hex */
728  fprintf (f, "ud#");
729  for (p = 0; p < udl; p++)
730  fprintf (f, "%02hX", ud[p]);
731  }
732  } else
733  { /* use two byte hex */
734  fprintf (f, "ud##");
735  for (p = 0; p < udl; p++)
736  fprintf (f, "%04hX", ud[p]);
737  }
738  fprintf (f, "\n");
739  }
740  fclose (f);
741  if (rename (temp, queuename))
742  {
743  perror (queuename);
744  unlink (temp);
745  return 1;
746  }
747  }
748 
749  if (!nodial && tx && !process)
750  { /* dial to send messages */
751  char ret=0,
752  try = 3;
753  if (nowait)
754  try = 1;
755  while (try--)
756  {
757  if (mo)
758  ret = txqcheck ("motx", queue, subaddress, motxchannel, motxcallerid, motxwait, motxdelay, motxretries, concurrent);
759  else
760  ret = txqcheck ("mttx", queue, subaddress, mttxchannel, mttxcallerid, mttxwait, mttxdelay, mttxretries, concurrent);
761  if (ret < 2)
762  break; /* sent, or queued OK */
763  if (try)
764  sleep (1);
765  }
766  if (ret == 2 && !nowait)
767  fprintf (stderr, "No call scheduled as already sending\n");
768  }
769  if (process)
770  rxqcheck (mo ? rx ? "morx" : "motx" : rx ? "mtrx" : "mttx", queue, process);
771 
772  return 0;
773 }
static struct test_val d
static struct test_val c
#define NULL
Definition: resample.c:96
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)
Definition: smsq.c:99
#define POPT_ARGFLAG_SHOW_DEFAULT
Definition: smsq.c:34
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...
Definition: smsq.c:43
static void rxqcheck(char *dir, char *queue, char *process)
Process received queue entries Run through a process, setting environment variables.
Definition: smsq.c:197
static struct test_val a

◆ rxqcheck()

static void rxqcheck ( char *  dir,
char *  queue,
char *  process 
)
static

Process received queue entries Run through a process, setting environment variables.

Definition at line 197 of file smsq.c.

References d, setenv(), tmp(), unsetenv(), and utf8decode().

Referenced by main().

198 {
199  char *p;
200  void *pp = &p;
201  char dirname[100],
202  temp[100];
203  DIR *d;
204  int ql = strlen (queue);
205  struct dirent *fn;
206  snprintf(temp, sizeof(temp), "sms/.smsq-%d", (int)getpid ());
207  snprintf(dirname, sizeof(dirname), "sms/%s", dir);
208  d = opendir (dirname);
209  if (!d)
210  return;
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] == '.'))))
214  { /* process file */
215  char filename[1010];
216  char line[1000];
217  unsigned short ud[160];
218  unsigned char udl = 0;
219  FILE *f;
220  snprintf (filename, sizeof(filename), "sms/%s/%s", dir, fn->d_name);
221  if (rename (filename, temp))
222  continue; /* cannot access file */
223  f = fopen (temp, "r");
224  unlink (temp);
225  if (!f)
226  {
227  perror (temp);
228  continue;
229  }
230  unsetenv ("oa");
231  unsetenv ("da");
232  unsetenv ("scts");
233  unsetenv ("pid");
234  unsetenv ("dcs");
235  unsetenv ("mr");
236  unsetenv ("srr");
237  unsetenv ("rp");
238  unsetenv ("vp");
239  unsetenv ("udh");
240  unsetenv ("ud");
241  unsetenv ("ude");
242  unsetenv ("ud8");
243  unsetenv ("ud16");
244  unsetenv ("morx");
245  unsetenv ("motx");
246  unsetenv ("queue");
247  if (*queue)
248  setenv ("queue", queue, 1);
249  setenv (dir, "", 1);
250  while (fgets (line, sizeof (line), f))
251  {
252  for (p = line; *p && *p != '\n' && *p != '\r'; p++);
253  *p = 0; /* strip eoln */
254  p = line;
255  if (!*p || *p == ';')
256  continue; /* blank line or comment, ignore */
257  while (isalnum (*p))
258  {
259  *p = tolower (*p);
260  p++;
261  }
262  while (isspace (*p))
263  *p++ = 0;
264  if (*p == '=')
265  { /* = */
266  *p++ = 0;
267  if (!strcmp (line, "oa") || !strcmp (line, "da") || !strcmp (line, "scts") || !strcmp (line, "pid")
268  || !strcmp (line, "dcs") || !strcmp (line, "mr") || !strcmp (line, "vp"))
269  setenv (line, p, 1);
270  else if ((!strcmp (line, "srr") || !strcmp (line, "rp")) && atoi (p))
271  setenv (line, "", 1);
272  else if (!strcmp (line, "ud"))
273  { /* read the user data as UTF-8 */
274  long v;
275  udl = 0;
276  while ((v = utf8decode (pp)) && udl < 160)
277  if (v && v <= 0xFFFF)
278  ud[udl++] = v;
279  }
280  } else if (*p == '#')
281  {
282  *p++ = 0;
283  if (*p == '#')
284  { /* ## */
285  p++;
286  if (!strcmp (line, "udh"))
287  setenv (line, p, 1);
288  else if (!strcmp (line, "ud"))
289  { /* read user data UCS-2 */
290  udl = 0;
291  while (*p && udl < 160)
292  {
293  if (isxdigit (*p) && isxdigit (p[1]) && isxdigit (p[2]) && isxdigit (p[3]))
294  {
295  ud[udl++] =
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));
299  p += 4;
300  } else
301  break;
302  }
303  }
304  } else
305  { /* # */
306  if (!strcmp (line, "ud"))
307  { /* read user data UCS-1 */
308  udl = 0;
309  while (*p && udl < 160)
310  {
311  if (isxdigit (*p) && isxdigit (p[1]))
312  {
313  ud[udl++] = (((isalpha (*p) ? 9 : 0) + (*p & 0xF)) << 4) + ((isalpha (p[1]) ? 9 : 0) + (p[1] & 0xF));
314  p += 2;
315  } else
316  break;
317  }
318  }
319  }
320  }
321  }
322  fclose (f);
323  /* set up user data variables */
324  {
325  char tmp[481];
326  int n, x;
327  for (n = 0, x = 0; x < udl; x++)
328  {
329  unsigned short v = ud[x];
330  if (v)
331  {
332  if (v < 0x80)
333  tmp[n++] = v;
334  else if (v < 0x800)
335  {
336  tmp[n++] = (0xC0 + (v >> 6));
337  tmp[n++] = (0x80 + (v & 0x3F));
338  } else
339  {
340  tmp[n++] = (0xE0 + (v >> 12));
341  tmp[n++] = (0x80 + ((v >> 6) & 0x3F));
342  tmp[n++] = (0x80 + (v & 0x3F));
343  }
344  }
345  }
346  tmp[n] = 0;
347  setenv ("ud", tmp, 1);
348  for (n = 0, x = 0; x < udl; x++)
349  {
350  unsigned short v = ud[x];
351  if (v < ' ' || v == '\\')
352  {
353  tmp[n++] = '\\';
354  if (v == '\\')
355  tmp[n++] = '\\';
356  else if (v == '\n')
357  tmp[n++] = 'n';
358  else if (v == '\r')
359  tmp[n++] = 'r';
360  else if (v == '\t')
361  tmp[n++] = 't';
362  else if (v == '\f')
363  tmp[n++] = 'f';
364  else
365  {
366  tmp[n++] = '0' + (v >> 6);
367  tmp[n++] = '0' + ((v >> 3) & 7);
368  tmp[n++] = '0' + (v & 7);
369  }
370  } else if (v < 0x80)
371  tmp[n++] = v;
372  else if (v < 0x800)
373  {
374  tmp[n++] = (0xC0 + (v >> 6));
375  tmp[n++] = (0x80 + (v & 0x3F));
376  } else
377  {
378  tmp[n++] = (0xE0 + (v >> 12));
379  tmp[n++] = (0x80 + ((v >> 6) & 0x3F));
380  tmp[n++] = (0x80 + (v & 0x3F));
381  }
382  }
383  tmp[n] = 0;
384  setenv ("ude", tmp, 1);
385  for (x = 0; x < udl && ud[x] < 0x100; x++);
386  if (x == udl)
387  {
388  for (n = 0, x = 0; x < udl; x++)
389  {
390  sprintf (tmp + n, "%02hX", ud[x]);
391  n += 2;
392  }
393  setenv ("ud8", tmp, 1);
394  }
395  for (n = 0, x = 0; x < udl; x++)
396  {
397  sprintf (tmp + n, "%04hX", ud[x]);
398  n += 4;
399  }
400  setenv ("ud16", tmp, 1);
401  }
402  /* run the command */
403  if (system (process) == -1) {
404  fprintf(stderr, "Failed to fork process '%s'\n", process);
405  }
406  }
407  closedir (d);
408 }
static struct test_val d
static int tmp()
Definition: bt_open.c:389
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...
Definition: smsq.c:43
int setenv(const char *name, const char *value, int overwrite)
int unsetenv(const char *name)

◆ txqcheck()

static char txqcheck ( char *  dir,
char *  queue,
char  subaddress,
char *  channel,
char *  callerid,
int  wait,
int  delay,
int  retries,
int  concurrent 
)
static

check for any queued messages in specific queue (queue="" means any queue)

Parameters
dir,queue,subaddress,channel,callerid,wait,delay,retries,concurrent
Return values
0if nothing queued
1if queued and outgoing set up OK
2of outgoing exists

Definition at line 99 of file smsq.c.

References d, and NULL.

Referenced by main().

100 {
101  char ogname[300],
102  temp[100],
103  dirname[100],
104  *p=NULL;
105  FILE *f;
106  DIR *d;
107  int ql = strlen (queue), qfl = ql;
108  struct dirent *fn;
109  snprintf (dirname, sizeof(dirname), "sms/%s", dir);
110  d = opendir (dirname);
111  if (!d)
112  return 0;
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] == '.'))));
116  if (!fn)
117  {
118  closedir (d);
119  return 0;
120  }
121  if (!ql)
122  { /* not searching any specific queue, so use whatr we found as the queue */
123  queue = fn->d_name;
124  qfl = ql = p - queue;
125  }
126  p = strchr (queue, '-');
127  if (p && p < queue + ql)
128  {
129  ql = p - queue;
130  subaddress = p[1];
131  }
132  snprintf (temp, sizeof(temp), "sms/.smsq-%d", (int)getpid ());
133  f = fopen (temp, "w");
134  if (!f)
135  {
136  perror (temp);
137  closedir (d);
138  return 0;
139  }
140  fprintf (f, "Channel: ");
141  if (!channel)
142  fprintf (f, "Local/%.*s\n", ql, queue);
143  else
144  {
145  p = strchr (channel, '/');
146  if (!p)
147  p = channel;
148  p = strchr (p, 'X');
149  if (p)
150  fprintf (f, "%.*s%c%s\n", (int)(p - channel), channel, subaddress, p + 1);
151  else
152  fprintf (f, "%s\n", channel);
153  }
154  fprintf (f, "Callerid: SMS <");
155  if (!callerid)
156  fprintf (f, "%.*s", ql, queue);
157  else
158  {
159  p = strchr (callerid, 'X');
160  if (p)
161  fprintf (f, "%.*s%c%s", (int)(p - callerid), callerid, subaddress, p + 1);
162  else
163  fprintf (f, "%s", callerid);
164  }
165  fprintf (f, ">\n");
166  fprintf (f, "Application: SMS\n");
167  fprintf (f, "Data: %.*s", qfl, queue);
168  if (dir[1] == 't')
169  fprintf (f, ",s");
170  fprintf (f, "\nMaxRetries: %d\n", retries);
171  fprintf (f, "RetryTime: %d\n", delay);
172  fprintf (f, "WaitTime: %d\n", wait);
173  fclose (f);
174  closedir (d);
175  {
176  int try = 0;
177  while (try < concurrent)
178  {
179  try++;
180  snprintf(ogname, sizeof(ogname), "outgoing/smsq.%s.%s.%d", dir, queue, try);
181  if (!link (temp, ogname))
182  { /* queued OK */
183  unlink (temp);
184  return 1;
185  }
186  }
187  }
188  /* failed to create call queue */
189  unlink (temp);
190  return 2;
191 }
static struct test_val d
Definition: muted.c:95
#define NULL
Definition: resample.c:96

◆ utf8decode()

static int utf8decode ( unsigned char **  pp)
static

reads next USC character from null terminated UTF-8 string and advanced pointer for non valid UTF-8 sequences.

Returns
character as is Does NOT advance pointer for null termination

Definition at line 43 of file smsq.c.

Referenced by main(), and rxqcheck().

44 {
45  unsigned char *p = *pp;
46  if (!*p)
47  return 0; /* null termination of string */
48  (*pp)++;
49  if (*p < 0xC0)
50  return *p; /* ascii or continuation character */
51  if (*p < 0xE0)
52  {
53  if (*p < 0xC2 || (p[1] & 0xC0) != 0x80)
54  return *p; /* not valid UTF-8 */
55  (*pp)++;
56  return ((*p & 0x1F) << 6) + (p[1] & 0x3F);
57  }
58  if (*p < 0xF0)
59  {
60  if ((*p == 0xE0 && p[1] < 0xA0) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80)
61  return *p; /* not valid UTF-8 */
62  (*pp) += 2;
63  return ((*p & 0x0F) << 12) + ((p[1] & 0x3F) << 6) + (p[2] & 0x3F);
64  }
65  if (*p < 0xF8)
66  {
67  if ((*p == 0xF0 && p[1] < 0x90) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80)
68  return *p; /* not valid UTF-8 */
69  (*pp) += 3;
70  return ((*p & 0x07) << 18) + ((p[1] & 0x3F) << 12) + ((p[2] & 0x3F) << 6) + (p[3] & 0x3F);
71  }
72  if (*p < 0xFC)
73  {
74  if ((*p == 0xF8 && p[1] < 0x88) || (p[1] & 0xC0) != 0x80 || (p[2] & 0xC0) != 0x80 || (p[3] & 0xC0) != 0x80
75  || (p[4] & 0xC0) != 0x80)
76  return *p; /* not valid UTF-8 */
77  (*pp) += 4;
78  return ((*p & 0x03) << 24) + ((p[1] & 0x3F) << 18) + ((p[2] & 0x3F) << 12) + ((p[3] & 0x3F) << 6) + (p[4] & 0x3F);
79  }
80  if (*p < 0xFE)
81  {
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)
84  return *p; /* not valid UTF-8 */
85  (*pp) += 5;
86  return ((*p & 0x01) << 30) + ((p[1] & 0x3F) << 24) + ((p[2] & 0x3F) << 18) + ((p[3] & 0x3F) << 12) + ((p[4] & 0x3F) << 6) +
87  (p[5] & 0x3F);
88  }
89  return *p; /* not sensible */
90 }