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);