source: trunk/src/sh_utils.c @ 1

Last change on this file since 1 was 1, checked in by katerina, 14 years ago

Initial import

File size: 37.1 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <string.h>
26#include <ctype.h>
27#include <unistd.h>
28
29#if TIME_WITH_SYS_TIME
30#include <sys/time.h>
31#include <time.h>
32#else
33#if HAVE_SYS_TIME_H
34#include <sys/time.h>
35#else
36#include <time.h>
37#endif
38#endif
39
40
41#include "samhain.h"
42#include "sh_error.h"
43#include "sh_utils.h"
44#include "sh_unix.h"
45#include "sh_tiger.h"
46#include "sh_entropy.h"
47
48#undef  FIL__
49#define FIL__  _("sh_utils.c")
50
51UINT32 ErrFlag[2];
52
53int sh_util_flagval(char * c, int * fval)
54{
55  SL_ENTER(_("sh_util_flagval"));
56  if (c == NULL)
57    SL_RETURN( (-1), _("sh_util_flagval"));
58  if ( c[0] == '1'  || c[0] == 'y'  || c[0] == 'Y' ||
59       c[0] == 't'  || c[0] == 'T')
60    {
61      *fval = S_TRUE;
62      SL_RETURN( (0), _("sh_util_flagval"));
63    }
64  if ( c[0] == '0'  || c[0] == 'n'  || c[0] == 'N' ||
65       c[0] == 'f'  || c[0] == 'F')
66    {
67      *fval = S_FALSE;
68      SL_RETURN( (0), _("sh_util_flagval"));
69    }
70  SL_RETURN( (-1), _("sh_util_flagval"));
71}
72
73int sh_util_timeout_check (SH_TIMEOUT * sh_timer)
74{
75  UINT64 now = (UINT64) time(NULL);
76  UINT64 dif;
77 
78  if (sh_timer->flag_ok == S_FALSE)
79    {
80      /* first time
81       */
82      if (sh_timer->time_last == 0)
83        {
84          sh_timer->time_last = now;
85          return S_TRUE;
86        }
87      /* later on
88       */
89      dif = now - sh_timer->time_last;
90      if (dif < sh_timer->time_dist)
91        {
92          return S_FALSE;
93        }
94      sh_timer->time_last = now;
95      return S_TRUE;
96    }
97  sh_timer->time_last = now;
98  return S_FALSE;
99}
100
101static int sh_ask_update = S_FALSE;
102
103int sh_util_set_interactive(char * str)
104{
105  if (str == NULL)
106    sh_ask_update = S_TRUE;
107  else
108    sh_ask_update = S_TRUE;
109
110  sh_unix_setnodeamon(NULL);
111
112  return 0;
113}
114
115#if !defined(STDIN_FILENO)
116#define STDIN_FILENO 0
117#endif
118#if !defined(STDERR_FILENO)
119#define STDERR_FILENO 0
120#endif
121
122int sh_util_ask_update(char * path)
123{
124  int    inchar, c;
125  int    i = S_TRUE;
126  char * tmp = NULL;
127
128  SL_ENTER(_("sh_util_ask_update"));
129
130  if (sh_ask_update != S_TRUE)
131    {
132      SL_RETURN(i, _("sh_util_ask_update"));
133    }
134
135#ifdef HAVE_TTYNAME
136  if (!ttyname(STDIN_FILENO))
137    {
138      if (NULL != ttyname(STDERR_FILENO))
139        {
140          if (NULL == freopen(ttyname(STDERR_FILENO), "r", stdin))
141            {
142              sh_error_handle ((-1), FIL__, __LINE__, 0, 
143                               MSG_E_SUBGEN,
144                               _("Cannot continue: stdin is not a terminal"),
145                               _("sh_util_ask_update"));
146              exit(EXIT_FAILURE);
147            }
148        }
149      else
150        {
151          sh_error_handle ((-1), FIL__, __LINE__, 0, 
152                           MSG_E_SUBGEN,
153                           _("Cannot continue: stdin is not a terminal"),
154                           _("sh_util_ask_update"));
155          exit(EXIT_FAILURE);
156        }
157    }
158#endif
159
160  if (sh_ask_update == S_TRUE)
161    {
162      tmp = sh_util_safe_name (path);
163      fprintf (stderr, _("Update %s [Y/n] ? "), tmp);
164      SH_FREE(tmp);
165      while (1 == 1)
166        {
167          c = fgetc(stdin); inchar = c;
168          /*@+charintliteral@*/
169          while (c != '\n' && c != EOF)
170            c = fgetc(stdin);
171          /* fprintf(stderr, "CHAR (1): %c\n", inchar); */
172          if (inchar == 'Y' || inchar == 'y' || inchar == '\n')
173            {
174              break;
175            }
176          else if (inchar == 'n' || inchar == 'N')
177            {
178              i = S_FALSE;
179              break;
180            }
181          else
182            {
183              fprintf(stderr, _("Please answer y(es) or n(o)\n"));
184            }
185          /*@-charintliteral@*/
186        }
187    }
188
189  SL_RETURN(i, _("sh_util_ask_update"));
190}
191
192int sh_util_hidesetup(char * c)
193{
194  int i;
195  SL_ENTER(_("sh_util_hidesetup"));
196  i = sh_util_flagval(c, &(sh.flag.hidefile));
197
198  SL_RETURN(i, _("sh_util_hidesetup"));
199}
200   
201char * sh_util_strdup (const char * str) 
202{
203  char * p = NULL;
204  size_t len;
205
206  SL_ENTER(_("sh_util_strdup"));
207
208  if (str != NULL)
209    {
210      len = sl_strlen(str);
211      p   = SH_ALLOC (len + 1);
212      (void) sl_strlcpy (p, str, len+1);
213    }
214  SL_RETURN( p, _("sh_util_strdup"));
215}
216
217/* by the eircom.net computer incident
218 * response team
219 */
220char * sh_util_strsep (char **str, const char *delim) 
221{
222  char *ret, *c, *d;
223
224  SL_ENTER(_("sh_util_strsep"));
225  ret = *str;
226
227  if (ret == NULL) {
228    SL_RETURN(ret, _("sh_util_strsep"));
229  }
230
231  for (c = *str; *c != '\0'; c++) {
232    for (d = (char *) delim; *d != '\0'; d++) {
233      if (*c == *d) {
234        *c = '\0';
235        *str = c + 1;
236        SL_RETURN(ret, _("sh_util_strsep"));
237      }
238    }
239  }
240
241  /* If we get to here, there's no delimiters in the string */
242  *str = NULL;
243  SL_RETURN(ret, _("sh_util_strsep"));
244}
245
246
247/* returned string must be free'd by caller
248 */
249char * sh_util_formatted (const char * formatt, st_format * ftab)
250{
251  struct tm   * time_ptr;
252  size_t size;
253  size_t isiz;
254  char * fmt = NULL;
255  char * p;
256  char * q;
257  char * outstr;
258  int    i;
259  int    j;
260  time_t inpp;
261
262  char * clist[16];
263  int    nn = 0;
264
265  SL_ENTER(_("sh_util_formatted"));
266
267  if (formatt == NULL || ftab == NULL)
268    SL_RETURN(NULL, _("sh_util_formatted"));
269
270  /* -- save the format (we overwrite it !!) --
271   */
272  size = sl_strlen(formatt);
273  if (size > 0)
274    {
275      fmt = (char *) SH_ALLOC(size + 1);
276      (void) sl_strlcpy(fmt, formatt, size + 1);
277    }
278  else
279    SL_RETURN(NULL, _("sh_util_formatted"));
280
281  p = fmt;
282
283  j = 0;
284  while (ftab[j].fchar != '\0')
285    {
286      if (ftab[j].type != S_FMT_STRING)
287        ftab[j].data_str = NULL;
288      ++j;
289    }
290
291  for (j = 0; j < 16; ++j)
292    clist[j] = NULL;
293
294  while (p != NULL && *p != '\0' && NULL != (q = strchr(p, '%')))
295    {
296      ++q;
297
298      /* fprintf(stderr, "p ==  %s   q == %s\n", p, q); */
299
300      /* -- end of string is a '%' --
301       */
302      if (*q == '\0')
303        {
304          --q;
305          *q = '\0';
306          break;
307        }
308
309      i = 0;
310      j = 0;
311
312      /* -- search the format char in input table --
313       * put (nn < 16) here -> all remaining %foo will be
314       * converted to %%
315       */
316      while (ftab[j].fchar != '\0' && nn < 16)
317        {
318          if (ftab[j].fchar == *q)
319            {
320              /* -- Convert it to a string format (%s). --
321               */
322              *q = 's'
323;
324              i  = 1;
325             
326              if (ftab[j].type == S_FMT_STRING)
327                {
328                  isiz = sl_strlen(ftab[j].data_str);
329                  if (isiz > 0)
330                    {
331                      size += isiz;
332                      clist[nn] = ftab[j].data_str;
333                      ++nn;
334                    }
335                  else
336                    *q = '%';
337                  break;
338                }
339              else if (ftab[j].type == S_FMT_ULONG)
340                {
341                  ftab[j].data_str = (char *) SH_ALLOC(64);
342                  /*@-bufferoverflowhigh@*/
343                  sprintf (ftab[j].data_str, "%lu",      /* known to fit  */
344                           ftab[j].data_ulong);
345                  /*@+bufferoverflowhigh@*/
346                  isiz = sl_strlen(ftab[j].data_str);
347                  if (isiz > 0)
348                    {
349                      size += isiz;
350                      clist[nn] = ftab[j].data_str;
351                      ++nn;
352                    }
353                  else
354                    *q = '%';
355                  break;
356                }
357              else if (ftab[j].type == S_FMT_LONG)
358                {
359                  ftab[j].data_str = (char *) SH_ALLOC(64);
360                  /*@-bufferoverflowhigh@*/
361                  sprintf (ftab[j].data_str, "%ld",      /* known to fit  */
362                           ftab[j].data_long);
363                  /*@+bufferoverflowhigh@*/
364                  isiz = sl_strlen(ftab[j].data_str);
365                  if (isiz > 0)
366                    {
367                      size += isiz;
368                      clist[nn] = ftab[j].data_str;
369                      ++nn;
370                    }
371                  else
372                    *q = '%';
373                  break;
374                }
375              else if (ftab[j].type == S_FMT_TIME)
376                {
377                  ftab[j].data_str = (char *) SH_ALLOC(64);
378                  inpp = (time_t)ftab[j].data_ulong;
379                  if (inpp != 0)
380                    {
381                      time_ptr = localtime (&(inpp));
382                      if (time_ptr != NULL) 
383                        (void) strftime(ftab[j].data_str, 64, 
384                                        _("%d-%m-%Y %H:%M:%S"), time_ptr);
385                      else
386                        (void) sl_strlcpy(ftab[j].data_str, 
387                                          _("00-00-0000 00:00:00"), 64);
388                    }
389                  else
390                    {
391                      (void) sl_strlcpy(ftab[j].data_str, 
392                                        _("(None)"), 64);
393                    }
394                  isiz = sl_strlen(ftab[j].data_str);
395                  if (isiz > 0)
396                    {
397                      size += isiz;
398                      clist[nn] = ftab[j].data_str;
399                      ++nn;
400                    }
401                  else
402                    *q = '%';
403                  break;
404                }
405
406            }
407          else
408            ++j;
409        }
410
411      /* -- not found -- */
412      if (i == 0)
413        {
414          *q = '%';
415          p = q;
416          ++p;
417        }
418      else
419        {
420          p = q;
421        }
422    }
423
424  /* -- Format string evaluated.
425     clist[]   List of strings
426     size      Total size of format string + clist[] strings
427     -- */
428 
429  /* -- closing '\0' --
430   */
431  size++;
432  outstr = (char *) SH_ALLOC(size);
433
434  /* -- print it --
435   */
436  (void) sl_snprintf( outstr, size, fmt,
437                      clist[0],  clist[1], clist[2],  clist[3], 
438                      clist[4],  clist[5], clist[6],  clist[7], 
439                      clist[8],  clist[9], clist[10], clist[11], 
440                      clist[12], clist[13], clist[14], clist[15]); 
441 
442  /* -- cleanup --
443   */
444  j = 0;
445  while (ftab[j].fchar != '\0')
446    {
447      if (ftab[j].type != S_FMT_STRING && ftab[j].data_str != NULL)
448        SH_FREE(ftab[j].data_str);
449      ++j;
450    }
451  SH_FREE(fmt);
452
453  SL_RETURN(outstr, _("sh_util_formatted"));
454}
455
456/* can't inline (AIX)
457 */
458int sh_util_hexchar( char c )
459{
460  /*@+charint@*/
461  if      ( c >= '0' && c <= '9' )
462    return c - '0';
463  else if ( c >= 'a' && c <= 'f' )
464    return c - 'a' + 10;
465  else if ( c >= 'A' && c <= 'F' )
466    return c - 'A' + 10;
467  else return -1;
468  /*@-charint@*/
469}
470
471/* read a hexadecimal key, convert to binary
472 */
473int sh_util_hextobinary (char * binary, char * hex, int bytes)
474{
475  int i = 0, j, k, l = 0;
476
477  SL_ENTER(_("sh_util_hextobinary"));
478
479  while (i < bytes)
480    {
481      k = sh_util_hexchar(hex[i]); j = sh_util_hexchar(hex[i+1]); 
482      if (k != -1 && j != -1) 
483        {
484          binary[l] = (char)(k * 16 + j);
485          ++l; i+= 2;
486        }
487      else
488        {
489          SL_RETURN((-1), _("sh_util_hextobinary"));
490        }
491    }
492 
493  SL_RETURN((0), _("sh_util_hextobinary"));
494}
495
496static void copy_four (unsigned char * dest, UINT32 in)
497{
498  UINT32 i, j;
499  int    count;
500
501  SL_ENTER(_("copy_four"));
502  for (count = 0; count < 4; ++count)
503    {
504      i  = in / 256;
505      j  = in - (i*256);
506      dest[count] = (unsigned char) j;
507      in = i;
508    }
509  SL_RET0(_("copy_four"));
510}
511
512/* compute HMAC-TIGER
513 */
514static char * sh_util_hmac_tiger (char * hexkey, 
515                                  char * text, size_t textlen)
516{
517  static char opad[KEY_BLOCK] = { 
518    (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, 
519    (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, 
520    (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, 
521    (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C, (char)0x5C
522  };
523  static char ipad[KEY_BLOCK] = { 
524    (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, 
525    (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, 
526    (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, 
527    (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36, (char)0x36
528  };
529  char        K[KEY_BLOCK];
530  char        outer[KEY_BLOCK];
531  char      * inner;
532  UINT32    * h1;
533  UINT32    * h2;
534  UINT32      cc[KEY_LEN/4];
535  char      * res;
536
537  size_t      i;
538
539  SL_ENTER(_("sh_util_hmac_tiger"));
540  ASSERT((KEY_BLOCK <= (KEY_LEN/2)), _("KEY_BLOCK <= (KEY_LEN/2)"))
541
542  if (KEY_BLOCK > (KEY_LEN/2))
543    {
544      res = sh_tiger_hash (NULL, TIGER_DATA, 0);
545      SL_RETURN(res, _("sh_util_hmac_tiger"));
546    }
547
548  memset (K, 0x00, KEY_BLOCK);
549
550  if (sh_util_hextobinary (K, hexkey, KEY_LEN) < 0)
551    {
552      res = sh_tiger_hash (NULL, TIGER_DATA, 0);
553      SL_RETURN(res, _("sh_util_hmac_tiger"));
554    }
555
556  inner = (char *) SH_ALLOC (textlen + KEY_BLOCK); 
557
558  for (i = 0; i < KEY_BLOCK; ++i)
559    {
560      outer[i]  = K[i] ^ opad[i];
561      inner[i]  = K[i] ^ ipad[i];
562    }
563  for (i = KEY_BLOCK; i < (KEY_BLOCK+textlen); ++i)
564    {
565      inner[i] = text[i - KEY_BLOCK];
566    }
567
568  /* now compute the hash
569   */
570  h1 = sh_tiger_hash_uint32 ( outer,
571                              TIGER_DATA,
572                              KEY_BLOCK);
573  for (i = 0; i < (KEY_LEN/8); ++i)
574    {
575      /* cc[i] = h1[i]; */
576      copy_four ( (unsigned char *) &(cc[i]), h1[i]);
577    }
578
579  h2 = sh_tiger_hash_uint32 ( inner,
580                              TIGER_DATA,
581                              (unsigned long) KEY_BLOCK+textlen);
582  for (i = KEY_LEN/8; i < (KEY_LEN/4); ++i)
583    {
584      copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]);
585      /* cc[i] = h2[i - (KEY_LEN/8)]; */
586    }
587  SH_FREE(inner);
588 
589  res = sh_tiger_hash ((char *) &cc[0],
590                       TIGER_DATA,
591                       (unsigned long) (KEY_LEN/4 * sizeof(UINT32)));
592
593  SL_RETURN(res, _("sh_util_hmac_tiger"));
594}
595
596static char * sh_util_hash_tiger ( char * hexkey, 
597                                   char * text, size_t textlen)
598{
599  char         * res;
600  char           h2[2*KEY_LEN+1];
601  SL_ENTER(_("sh_util_hash_tiger"));
602
603  (void) sl_strlcpy(h2, hexkey, KEY_LEN+1); 
604  (void) sl_strlcat(h2, sh_tiger_hash(text, TIGER_DATA, 
605                                      (unsigned long) textlen), 2*KEY_LEN+1);
606
607  res = sh_tiger_hash(h2, TIGER_DATA, 2*KEY_LEN);
608
609  SL_RETURN(res, _("sh_util_hash_tiger"));
610}
611
612/* --- compute signature on data ---
613 */
614#define TYPE_HMAC 0
615#define TYPE_HASH 1
616
617static int sigtype = TYPE_HMAC;
618
619int sh_util_sigtype (char * c)
620{
621  SL_ENTER(_("sh_util_sigtype"));
622  if (c == NULL)
623    SL_RETURN( -1, _("sh_util_sigtype"));
624
625  if (0 == strcmp(_("HMAC-TIGER"), c))
626    sigtype = TYPE_HMAC;
627  else if  (0 == strcmp(_("HASH-TIGER"), c))
628    sigtype = TYPE_HASH;
629  else
630    SL_RETURN( -1, _("sh_util_sigtype"));
631
632  SL_RETURN( 0, _("sh_util_sigtype"));
633}
634
635char * sh_util_siggen (char * hexkey, 
636                       char * text, size_t textlen) 
637{
638  char * p;
639 
640  SL_ENTER(_("sh_util_siggen"));
641  if (sigtype == TYPE_HMAC)
642    p = sh_util_hmac_tiger (hexkey, 
643                            text, textlen);
644  else
645    p = sh_util_hash_tiger (hexkey, 
646                            text, textlen);
647  SL_RETURN(p, _("sh_util_siggen"));
648}   
649
650 
651 
652/* a simple compressor
653 */
654long sh_util_compress (char * dest, char * src, size_t dest_size)
655{
656  char * add;
657  char * get;
658  size_t   count = 0;
659  size_t   dest_end;
660
661  SL_ENTER(_("sh_util_compress"));
662
663  if (dest_size == 0)
664    SL_RETURN((0), _("sh_util_compress"));
665 
666  if ((dest == NULL) || (src == NULL))
667    SL_RETURN((0), _("sh_util_compress"));
668 
669  dest_end = sl_strlen(dest);
670
671  if (dest_end > dest_size)
672    SL_RETURN((0), _("sh_util_compress"));
673
674  add      = &dest[dest_end];
675  get      = src;
676
677  while (count < (dest_size-dest_end))
678    {
679      if (isalnum((int) *get)) 
680        {
681          *add = *get;
682          ++add;
683          ++count;
684        }
685      ++get; 
686      if (*get == '\0' && (count < (dest_size-dest_end))) 
687        /* end of src reached */
688        {
689          *add = *get;  /* copy the '\0'      */
690          break;        /* and stop copying   */
691        }
692    }
693
694  dest[dest_size-1] = '\0'; /* paranoia       */
695  SL_RETURN(((long)count), _("sh_util_compress")); /* no of chars copied */   
696}
697
698
699/* copy the four least significant bytes
700 */
701void sh_util_cpylong (char * dest, const char * src, int len )
702{
703  int i, j;
704  union
705  {
706    long l;
707    char c[sizeof(long)];
708  } u;
709
710  SL_ENTER(_("sh_util_cpylong"));   
711
712  u.l = 1;
713
714  /* MSB is first
715   */
716  if (sizeof(long)>4 &&/*@+charint@*/(u.c[sizeof(long)-1] == 1)/*@-charint@*/)
717    {
718      j = (int) (sizeof(long)-4);
719      for (i = 0; i < j; ++i) ++src;
720    }
721
722  i = 0;
723
724  while (i < 4)
725    {
726      *dest = (*src);
727      ++dest; ++src;
728      if (i == (len-1)) break;
729      ++i;
730    }
731  SL_RET0(_("sh_util_cpylong"));
732}
733
734/*  This is a maximally equidistributed combined Tausworthe
735 *  generator. The sequence is,
736 *
737 *   x_n = (s1_n ^ s2_n ^ s3_n)
738 *
739 *   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
740 *   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
741 *   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
742 *
743 *   computed modulo 2^32. In the three formulas above '^' means
744 *   exclusive-or (C-notation), not exponentiation. Note that the
745 *   algorithm relies on the properties of 32-bit unsigned integers (it
746 *   is formally defined on bit-vectors of length 32).
747 *
748 *   Stolen from GSL (GNU scientific library) and modified somewhat.
749 *   I am using UINT32, which is guaranteed to be 32 bits. Also made
750 *   sure that the initialization vector is valid.
751 */
752
753
754/* interval [0, 4294967296]
755 */
756static UINT32 taus_get_long (void *vstate)
757{
758  UINT32 * state = (UINT32 *) vstate;
759
760  if (skey->rngI == BAD)
761    (void)taus_seed();
762
763#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
764  /*@+ignorequals@*/
765  state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12);
766  state[1] = TAUSWORTHE (state[1],  2, 25, 4294967288UL,  4);
767  state[2] = TAUSWORTHE (state[2],  3, 11, 4294967280UL, 17);
768  /*@-ignorequals@*/
769  return (state[0] ^ state[1] ^ state[2]);
770}
771
772/* Hide the internal state of the PRNG by using its output as
773 * input for a one-way hash function.
774 */
775UINT32 taus_get (void *state1, void *state2, void *state3)
776{
777  UINT32   svec[6];
778  UINT32   retval;
779  UINT32 * res;
780  register int i;
781
782  svec[0] = taus_get_long (state1);
783  svec[1] = taus_get_long (state2);
784  svec[2] = taus_get_long (state3);
785  svec[3] = taus_get_long (state1);
786  svec[4] = taus_get_long (state2);
787  svec[5] = taus_get_long (state3);
788
789  res     = sh_tiger_hash_uint32 ( (char *) &svec[0], 
790                                   TIGER_DATA, 
791                                   (unsigned long)(6 * sizeof(UINT32)));
792
793  for (i = 1; i < KEY_BYT/4; ++i)
794    res[0] ^= res[i];
795  retval = res[0];
796
797  memset (res,  0,            KEY_BYT);
798  memset (svec, 0, 6 * sizeof(UINT32));
799
800  return retval;
801}
802
803/* interval [0,1)
804 */
805double taus_get_double (void *vstate)
806{
807  return taus_get_long (vstate) / (4294967296.0 + 1.0) ;
808}
809
810#define LCG(n) ((69069 * n) & 0xffffffffUL)
811
812/* TAKE CARE: state[0], state[1], state[2] must be > 2,8,16, respectively
813 */
814static void taus_set_from_ulong (void *vstate, unsigned long int s)
815{
816  UINT32  *state = (UINT32  *) vstate;
817
818  if (s == 0)
819    s = 1;      /* default seed is 1 */
820
821  state[0] = (UINT32)(LCG (s)        | (UINT32) 0x03);
822  state[1] = (UINT32)(LCG (state[0]) | (UINT32) 0x09);
823  state[2] = (UINT32)(LCG (state[1]) | (UINT32) 0x17);
824
825  /* 'warm up'
826   */
827  (void) taus_get_long (state);
828  (void) taus_get_long (state);
829  (void) taus_get_long (state);
830  (void) taus_get_long (state);
831  (void) taus_get_long (state);
832  (void) taus_get_long (state);
833
834  return;
835}
836
837static void taus_set_from_state (void *vstate, void *init_state)
838{
839  UINT32  *state  = (UINT32  *) vstate;
840  UINT32  *state0 = (UINT32  *) init_state;
841
842  state[0] = state0[0]  | (UINT32) 0x03;
843  state[1] = state0[1]  | (UINT32) 0x09;
844  state[2] = state0[2]  | (UINT32) 0x17;
845 
846  return;
847}
848
849 
850int taus_seed ()
851{
852  char                 bufx[9 * sizeof(UINT32) + 1];
853  int                  status;
854  static unsigned long seed_time = 0;
855
856  SL_ENTER(_("taus_seed"));
857
858  if (skey->rngI == GOOD)
859    {
860      if ( (sh_unix_longtime () - seed_time) < 3600)
861        SL_RETURN( (0), _("taus_seed"));
862    }
863 
864  seed_time = sh_unix_longtime ();
865
866  status = sh_entropy (24, bufx);
867
868  if (!SL_ISERROR(status))
869    {
870      skey->rngI = GOOD;
871      memcpy (&skey->rng0[0], &bufx[0],                  2*sizeof(UINT32));
872      memcpy (&skey->rng1[0], &bufx[2*sizeof(UINT32)],   2*sizeof(UINT32));
873      memcpy (&skey->rng2[0], &bufx[4*sizeof(UINT32)],   2*sizeof(UINT32));
874      memset (bufx, 0, 9 * sizeof(UINT32) + 1);
875
876      skey->rng0[2] = 0;
877      skey->rng1[2] = 0;
878      skey->rng2[2] = 0;
879
880      taus_set_from_state( &(skey->rng0[0]), &(skey->rng0[0]));
881      taus_set_from_state( &(skey->rng1[0]), &(skey->rng1[0]));
882      taus_set_from_state( &(skey->rng2[0]), &(skey->rng2[0]));
883
884      SL_RETURN( (0), _("taus_seed"));
885    }
886
887  sh_error_handle ((-1), FIL__, __LINE__, status, MSG_ES_ENT,
888                   _("sh_entropy"));
889
890  /* emergency backup - unsafe !
891   */
892  skey->rngI = GOOD;
893#ifdef HAVE_GETTIMEOFDAY
894  taus_set_from_ulong ( &(skey->rng0[0]), LCG (sh_unix_notime())      );
895#else
896  taus_set_from_ulong ( &(skey->rng0[0]), LCG (seed_time)      );
897#endif
898  taus_set_from_ulong ( &(skey->rng1[0]), LCG (skey->rng0[0])  );
899  taus_set_from_ulong ( &(skey->rng2[0]), LCG (skey->rng1[0])  );
900  skey->rngI = BAD;
901
902  SL_RETURN( (-1), _("taus_seed"));
903}
904
905/*@+charint@*/
906static unsigned char new_key[] = { 0xA7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xA7 };
907/*@-charint@*/
908static void copy_four (unsigned char * dest, UINT32 in);
909
910int sh_util_set_newkey (char * new)
911{
912  size_t i, j = 0;
913  size_t len;
914  SL_TICKET fp;
915  SL_TICKET fout;
916  char * key;
917  char * path;
918  char * outpath;
919  unsigned char * image = NULL;
920  long s = 0;
921  long ilen = 0;
922  long ii, k = 0;
923  UINT32    * h1;
924
925  if (0 != sl_is_suid())
926    {
927      fprintf(stderr, _("ERROR: insufficient privilege\n"));
928      _exit (EXIT_FAILURE);
929      /*@notreached@*/
930      return -1;  /* braindead MAC OSX compiler needs this */
931    }
932       
933  if (new == NULL || new[0] == '\0')
934    {
935      fprintf(stderr, 
936              _("ERROR: no key given\n Argument must be 'key@path'\n"));
937      _exit (EXIT_FAILURE);
938      /*@notreached@*/
939      return -1;
940    }
941  key = new;
942  len = strlen(new);
943  for (i = 1; i < (len-2); ++i)
944    {
945      if (new[i] == '@' && new[i+1] == '/')
946        {
947          j = i+1; new[i] = '\0'; break;
948        }
949    }
950  if (j == 0)
951    {
952      fprintf(stderr, 
953              _("ERROR: no path to executable given\n Argument must be 'key@path'\n"));
954      _exit (EXIT_FAILURE);
955      /*@notreached@*/
956      return -1;
957    }
958  else
959    path = &new[j];
960  /*@-usedef@*/
961  if (NULL == (outpath = malloc(strlen(path) + 1 + 4)))
962    goto bail_mem;
963  /*@-usedef@*/
964  /*@-bufferoverflowhigh@*/
965  sprintf (outpath, _("%s.out"), path);               /* known to fit  */ 
966  /*@+bufferoverflowhigh@*/
967
968  fp = sl_open_read(path, SL_NOPRIV);
969  if (SL_ISERROR(fp))
970    {
971      fprintf(stderr, 
972              _("ERROR: cannot open %s for read (errnum = %ld)\n"), path, fp);
973      _exit (EXIT_FAILURE);
974      /*@notreached@*/
975      return -1;
976    }
977 
978  fout = sl_open_write(outpath, SL_NOPRIV);
979  if (SL_ISERROR(fout))
980    {
981      fprintf(stderr, 
982              _("ERROR: cannot open %s (errnum = %ld)\n"), outpath, fout);
983      _exit (EXIT_FAILURE);
984      /*@notreached@*/
985      return -1;
986    }
987
988
989  image = malloc (4096);
990  if (!image)
991    goto bail_mem;
992  while (0 < (ii = sl_read (fp, &image[s], 4096)))
993    {
994      ilen += ii;
995      s    += 4096;
996      image = realloc (image, (size_t) (4096 + s));
997      if (!image)
998        goto bail_mem;
999    }
1000
1001  printf(_("%ld bytes read\n"), ilen);
1002
1003 
1004  for (k = 0; k < (ilen - 8); ++k) 
1005    {
1006      if (image[k]   == new_key[0] &&
1007          image[k+1] == new_key[1] &&
1008          image[k+2] == new_key[2] &&
1009          image[k+3] == new_key[3] &&
1010          image[k+4] == new_key[4] &&
1011          image[k+5] == new_key[5] &&
1012          image[k+6] == new_key[6] &&
1013          image[k+7] == new_key[7])
1014        {
1015          printf(_("old key found\n")); 
1016          h1 = sh_tiger_hash_uint32 (key, TIGER_DATA, 
1017                                     (unsigned long)strlen(key));
1018          copy_four( (unsigned char *) &(image[k]),   h1[0]);
1019          copy_four( (unsigned char *) &(image[k+4]), h1[1]);
1020          (void) sl_write (fout, image, ilen);
1021          (void) sl_close (fout);
1022          printf(_("new file %s written\n"), outpath);
1023          _exit (EXIT_SUCCESS);
1024          /*@notreached@*/
1025          return 0;
1026        }
1027    }
1028
1029  fprintf(stderr, 
1030          _("ERROR: old key not found\n"));
1031  _exit (EXIT_FAILURE);
1032  /*@notreached@*/
1033  return -1;
1034
1035
1036 bail_mem:
1037  fprintf(stderr, 
1038          _("ERROR: out of memory\n"));
1039  _exit (EXIT_FAILURE);
1040  /*@notreached@*/
1041  return -1;
1042}
1043
1044 
1045
1046       
1047/* A simple en-/decoder, based on Vernam cipher. We use the
1048 * message as salt to hide the key by obtaining a different one-time
1049 * pad each time.
1050 * Should be safe against a listener on the network, but not against someone
1051 * with read access to the binary.
1052 */
1053void sh_util_encode (char * data, char * salt, int mode, char fill)
1054{
1055  static char     cc1[17] = N_("0123456789ABCDEF");
1056  char            cc[17] = "\0";
1057  register int    i, j, j1 = 0, j2 = 0, j3;
1058  char          * dez; 
1059
1060  SL_ENTER(_("sh_util_encode"));
1061
1062  /* init
1063   */
1064  (void) sl_strlcpy( cc, _(cc1), sizeof(cc));
1065
1066  /* max 128 bits keyspace
1067   */
1068  memset (skey->vernam, (int)fill, KEY_LEN+1);
1069
1070  dez    = (char *) &(skey->ErrFlag[0]);
1071  sh_util_cpylong (skey->vernam,     dez, 4);
1072  dez    = (char *) &(skey->ErrFlag[1]);
1073  sh_util_cpylong (&skey->vernam[4], dez, 4);
1074
1075  skey->vernam[KEY_LEN] = '\0';
1076
1077  (void) sl_strlcpy(skey->vernam, 
1078                    sh_tiger_hash(skey->vernam, TIGER_DATA, KEY_LEN), 
1079                    KEY_LEN+1);
1080
1081  (void) sl_strlcpy(skey->vernam, 
1082                    sh_util_hmac_tiger (skey->vernam, salt, strlen(salt)),
1083             KEY_LEN+1);
1084
1085  (void) sl_strlcpy(skey->vernam, 
1086                    sh_util_hmac_tiger (skey->vernam, (char*) new_key, 8),
1087                    KEY_LEN+1);
1088
1089  /* The following routine adds/subtracts  data[j] and vernam[j] mod 16.
1090   */
1091  j = 0;
1092  while (j < KEY_LEN)
1093    {
1094      for (i = 0; i < 16; ++i)
1095        {
1096          if (cc[i] == data[j])   j1 = i;
1097          if (cc[i] == skey->vernam[j])    j2 = i;
1098        }
1099      if (mode == 0)
1100        {
1101          j3 = j1 + j2;
1102          if (j3 > 15) j3 -= 16;
1103          data[j] = cc[j3];
1104        }
1105      else
1106        {
1107          j3 = j1 - j2;
1108          if (j3 <  0) j3 += 16;
1109          data[j] = cc[j3];
1110        }
1111      ++j;
1112    }
1113  SL_RET0(_("sh_util_encode"));
1114}
1115
1116/* server mode
1117 */
1118int sh_util_setserver (char * dummy)
1119{
1120  SL_ENTER(_("sh_util_setserver"));
1121
1122  if (dummy)
1123    sh.flag.isserver = GOOD;
1124  else
1125    sh.flag.isserver = GOOD;
1126  SL_RETURN((0),_("sh_util_setserver"));
1127}
1128
1129
1130int sh_util_setlooptime (char * str)
1131{
1132  int i = atoi (str);
1133 
1134  SL_ENTER(_("sh_util_setlooptime"));
1135
1136  if (i >= 0 && i < INT_MAX) {
1137    sh.looptime = i;
1138    SL_RETURN((0),_("sh_util_setlooptime"));
1139  } else {
1140    sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1141                     _("loop time"), str);
1142    SL_RETURN((-1),_("sh_util_setlooptime"));
1143  }
1144}
1145
1146#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1147int  sh_util_setchecksum (char * str)
1148{
1149  static int reject = 0;
1150
1151  SL_ENTER(_("sh_util_setchecksum"));
1152
1153  if (reject == 1)
1154    SL_RETURN((0), _("sh_util_setchecksum"));
1155  reject = 1;
1156
1157  if (sl_strncmp (str, _("init"), sizeof("init")-1) == 0)
1158    {
1159      sh.flag.checkSum = SH_CHECK_INIT;
1160    }
1161  else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1162    {
1163      if (S_TRUE == file_is_remote()) 
1164        {
1165          sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1166                           _("checksum testing"), str);
1167          SL_RETURN((-1), _("sh_util_setchecksum"));
1168        }
1169      else
1170        {
1171          sh.flag.checkSum = SH_CHECK_CHECK;
1172          sh.flag.update   = S_TRUE;
1173        }
1174    }
1175  else if (sl_strncmp (str, _("check"), sizeof("check")-1) == 0)
1176    {
1177      sh.flag.checkSum = SH_CHECK_CHECK;
1178    }
1179  /*
1180  else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1181    {
1182      sh.flag.checkSum = SH_CHECK_INIT;
1183      sh.flag.update   = S_TRUE;
1184    }
1185  */
1186  else if (sl_strncmp (str, _("none"), sizeof("none")-1) == 0)
1187    {
1188      sh.flag.checkSum = SH_CHECK_NONE;
1189    }
1190  else 
1191    {
1192      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1193                       _("checksum testing"), str);
1194      SL_RETURN((-1), _("sh_util_setchecksum"));
1195    }
1196  SL_RETURN((0), _("sh_util_setchecksum"));
1197}
1198#endif
1199 
1200/*@+charint@*/
1201unsigned char TcpFlag[8][PW_LEN+1] = { 
1202#if (POS_TF == 1)
1203  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1204#endif
1205  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1206#if (POS_TF == 2)
1207  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1208#endif
1209  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1210#if (POS_TF == 3)
1211  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1212#endif
1213  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1214#if (POS_TF == 4)
1215  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1216#endif
1217  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1218#if (POS_TF == 5)
1219  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1220#endif
1221  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1222#if (POS_TF == 6)
1223  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1224#endif
1225  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1226#if (POS_TF == 7)
1227  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1228#endif
1229  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1230#if (POS_TF == 8)
1231  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1232#endif
1233};
1234/*@-charint@*/
1235
1236/* initialize a key to a random value
1237 * rev 0.8
1238 */
1239int sh_util_keyinit (char * buf, long size)
1240{
1241  UINT32       bufy[6];
1242  int          i;
1243  int          status = 0;
1244  char       * p;
1245
1246  SL_ENTER(_("sh_util_keyinit"));
1247
1248  ASSERT((size <= KEY_LEN+1), _("size <= KEY_LEN+1"))
1249
1250  if (size > KEY_LEN+1)
1251    size = KEY_LEN+1;
1252
1253  /* seed / re-seed the PRNG if required
1254   */
1255  status = taus_seed ();
1256
1257  if (status == -1)
1258    sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_ES_KEY1,
1259                     _("taus_seed"));
1260
1261  for (i = 0; i < 6; ++i)
1262    bufy[i] = taus_get(&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1263
1264  p = sh_tiger_hash ((char *) bufy, TIGER_DATA, 
1265                     (unsigned long)(6*sizeof(UINT32)));
1266  p[size-1] = '\0';
1267
1268  i = sl_strlcpy(buf, p, (size_t)size);
1269
1270  memset (bufy, 0, 6*sizeof(UINT32));
1271
1272  if ((status == 0) && (!SL_ISERROR(i)) )
1273    SL_RETURN((0),_("sh_util_keyinit"));
1274
1275  if (SL_ISERROR(i))
1276    sh_error_handle ((-1), FIL__, __LINE__, i, MSG_ES_KEY2, 
1277                     _("sl_strlcpy"));
1278
1279  SL_RETURN((-1),_("sh_util_keyinit"));
1280}
1281
1282#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1283
1284static unsigned char sh_obscure_index[256];
1285
1286int sh_util_obscure_ok (char * str)
1287{
1288  unsigned long   i;
1289  char * endptr = str;
1290
1291  SL_ENTER(_("sh_util_obscure_ex"));
1292
1293  if (0 == sl_strncmp("all", str, 3))
1294    {
1295      for (i = 0; i < 255; ++i)
1296        {
1297          sh_obscure_index[i] = (unsigned char)1;
1298        }
1299      SL_RETURN(0, _("sh_util_obscure_ex"));
1300    }
1301
1302  for (i = 0; i < 255; ++i)
1303    {
1304      sh_obscure_index[i] = (unsigned char)0;
1305    }
1306
1307  while (*endptr != '\0')
1308    {
1309      i = strtoul (endptr, &endptr, 0);
1310      if (i > 255)
1311        {
1312          SL_RETURN(-1, _("sh_util_obscure_ex"));
1313        }
1314      sh_obscure_index[i] = (unsigned char)1;
1315      if (*endptr == ',')
1316        ++endptr;
1317    }
1318  SL_RETURN(0, _("sh_util_obscure_ex"));
1319}
1320
1321int sh_util_obscurename (ShErrLevel level, char * name_orig, int flag)
1322{
1323  char * name = name_orig;
1324  char * safe;
1325  unsigned int i;
1326
1327  SL_ENTER(_("sh_util_obscurename"));
1328
1329  ASSERT_RET((name != NULL), _("name != NULL"), (0))
1330
1331  /* -- Check name. --
1332   */
1333  while (*name != '\0') 
1334    {
1335      if ( (*name) == '"'  || (*name) == '\t' ||
1336           (*name) == '\b' || (*name) == '\f' || 
1337           (*name) == '\n' || (*name) == '\r' ||
1338           (*name) == '\v' || iscntrl((int) *name) || 
1339           ((*name) != ' ' && !isgraph ((int) *name)) ) 
1340        {
1341          i = (unsigned char) *name;
1342          if (sh_obscure_index[i] != (unsigned char)1)
1343            {
1344              if (flag == S_TRUE)
1345                {
1346                  safe = sh_util_safe_name (name_orig); 
1347                  sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC, 
1348                                   safe);
1349                  SH_FREE(safe);
1350                }
1351              SL_RETURN((-1),_("sh_util_obscurename"));
1352            }
1353        }
1354      name++;
1355    }
1356
1357  SL_RETURN((0),_("sh_util_obscurename"));
1358}
1359#endif
1360
1361/* returns freshly allocated memory, return value should be free'd
1362 */
1363char * sh_util_basename(char * fullpath)
1364{
1365  char * retval;
1366  size_t i;
1367
1368  SL_ENTER(_("sh_util_basename"));
1369
1370  ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1371
1372  i = sl_strlen (fullpath);  /* fullpath[i] is terminating '\0' */
1373
1374  while (i > 0) {
1375    --i;
1376    if (fullpath[i] == '/') break;
1377  }
1378
1379  /* -- Not a valid path. --
1380   */
1381  if ((fullpath[i] != '/') && (i == 0) ) 
1382    SL_RETURN(NULL, _("sh_util_basename"));
1383
1384  retval = SH_ALLOC(i + 1);
1385
1386  (void) sl_strlcpy (retval, fullpath, i+1);
1387
1388  SL_RETURN(retval, _("sh_util_basename"));
1389}
1390
1391/* returns freshly allocated memory, return value should be free'd
1392 */
1393char * sh_util_filename(char * fullpath)
1394{
1395  char * retval;
1396  char * c;
1397  size_t i;
1398
1399  SL_ENTER(_("sh_util_filename"));
1400
1401  ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1402
1403  c = strrchr(fullpath, '/');
1404  i = sl_strlen (c);
1405  if (i <= 1) SL_RETURN(NULL, _("sh_util_filename")); /* ends in '/' */
1406  ++c;
1407  --i;
1408
1409  retval = SH_ALLOC(i + 1);
1410
1411  (void) sl_strlcpy (retval, c, i+1);
1412
1413  SL_RETURN(retval, _("sh_util_filename"));
1414}
1415
1416   
1417/* returns freshly allocated memory, return value should be free'd
1418 */
1419char * sh_util_safe_name (const char * name)
1420{
1421  register int  i = 0;
1422  const char  * p;
1423  char        * retval;
1424  char          oct[32];
1425  char          format[16];
1426
1427  SL_ENTER(_("sh_util_safe_name"));
1428
1429  if (name == NULL)
1430    {
1431      /* return an allocated array
1432       */
1433      retval = SH_ALLOC(7);
1434      (void) sl_strlcpy(retval, _("(null)"), 7);
1435      SL_RETURN(retval, _("sh_util_safe_name"));
1436    }
1437
1438  /*
1439  ASSERT_RET ((name != NULL), _("name != NULL"), _("NULL"))
1440  */
1441
1442#ifdef SH_USE_XML
1443  retval = SH_ALLOC(6 * sl_strlen(name) + 2);
1444#else
1445  retval = SH_ALLOC(4 * sl_strlen(name) + 2);
1446#endif
1447
1448  (void) sl_strncpy(format, _("%c%03o"), 16);
1449
1450  p = name;
1451
1452  while (*p != '\0') {
1453    /* Most frequent cases first
1454     */
1455    if ( ((*p) >= 'a' && (*p) <= 'z')  || ((*p) == '/') || ((*p) == '.') ||
1456         ((*p) >= '0' && (*p) <= '9')  || 
1457         ((*p) >= 'A' && (*p) <= 'Z')) {
1458      retval[i] = *p; 
1459    } else if ( (*p) == '\\') {           /* backslash        */
1460      retval[i] = '\\'; ++i; 
1461      retval[i] = '\\';
1462    } else if ( (*p) == '\n') {    /* newline          */
1463      retval[i] = '\\'; ++i; 
1464      retval[i] = 'n';
1465    } else if ( (*p) == '\b') {    /* backspace        */
1466      retval[i] = '\\'; ++i; 
1467      retval[i] = 'b';
1468    } else if ( (*p) == '\r') {    /* carriage  return */
1469      retval[i] = '\\'; ++i; 
1470      retval[i] = 'r';
1471    } else if ( (*p) == '\t') {    /* horizontal tab   */
1472      retval[i] = '\\'; ++i; 
1473      retval[i] = 't';
1474    } else if ( (*p) == '\v') {    /* vertical tab     */
1475      retval[i] = '\\'; ++i; 
1476      retval[i] = 'v';
1477    } else if ( (*p) == '\f') {    /* form-feed        */
1478      retval[i] = '\\'; ++i; 
1479      retval[i] = 'f';
1480#ifdef WITH_DATABASE
1481    } else if ( (*p) == '\'') {    /* single quote     */
1482      retval[i] = '\\'; ++i; 
1483      retval[i] = '\'';
1484#endif
1485    } else if ( (*p) == ' ') {     /* space            */
1486      retval[i] = '\\'; ++i; 
1487      retval[i] = ' ';
1488#ifdef SH_USE_XML
1489    } else if ( (*p) == '"') {     /* double quote     */
1490      retval[i] = '&'; ++i; 
1491      retval[i] = 'q'; ++i;
1492      retval[i] = 'u'; ++i;
1493      retval[i] = 'o'; ++i;
1494      retval[i] = 't'; ++i;
1495      retval[i] = ';';
1496    } else if ( (*p) == '&') {     /* ampersand        */
1497      retval[i] = '&'; ++i; 
1498      retval[i] = 'a'; ++i;
1499      retval[i] = 'm'; ++i;
1500      retval[i] = 'p'; ++i;
1501      retval[i] = ';';
1502    } else if ( (*p) == '<') {     /* left angle       */
1503      retval[i] = '&'; ++i; 
1504      retval[i] = 'l'; ++i;
1505      retval[i] = 't'; ++i;
1506      retval[i] = ';';
1507    } else if ( (*p) == '>') {     /* right angle      */
1508      retval[i] = '&'; ++i; 
1509      retval[i] = 'g'; ++i;
1510      retval[i] = 't'; ++i;
1511      retval[i] = ';';
1512#else
1513    } else if ( (*p) == '"') {     /* double quote     */
1514      retval[i] = '\\'; ++i; 
1515      retval[i] = '\"';
1516#endif
1517    } else if (!isgraph ((int) *p)) {    /* not printable    */
1518      /*@-bufferoverflowhigh -formatconst@*/
1519      sprintf(oct, format, '\\',                 /* known to fit  */
1520              (unsigned char) *p);
1521      /*@+bufferoverflowhigh +formatconst@*/
1522      retval[i] = oct[0]; ++i;
1523      retval[i] = oct[1]; ++i;
1524      retval[i] = oct[2]; ++i;
1525      retval[i] = oct[3]; 
1526    } else {
1527      retval[i] = *p;
1528    }
1529    ++p;
1530    ++i;
1531  }
1532  retval[i] = '\0';
1533  SL_RETURN(retval, _("sh_util_safe_name"));
1534}
1535
1536int sh_util_isnum (char *str)
1537{
1538  char *p = str;
1539
1540  SL_ENTER(_("sh_util_isnum"));
1541
1542  ASSERT_RET ((str != NULL), _("str != NULL"), (-1))
1543
1544  while (p) {
1545    if (!isdigit((int) *p) ) 
1546      SL_RETURN((-1), _("sh_util_isnum"));
1547    ++p;
1548  }
1549  SL_RETURN((0), _("sh_util_isnum"));
1550}
1551
1552char * sh_util_strconcat (const char * arg1, ...)
1553{
1554  size_t    length;
1555  char    * s;
1556  char    * strnew;
1557  va_list vl;
1558
1559  SL_ENTER(_("sh_util_strconcat"));
1560
1561  ASSERT_RET ((arg1 != NULL), _("arg1 != NULL"), (NULL))
1562
1563  length = sl_strlen (arg1) + 1;
1564
1565  va_start (vl, arg1);
1566  s = va_arg (vl, char * );
1567  while (s != NULL)
1568    {
1569      length = length + sl_strlen (s);
1570      s = va_arg (vl, char * );
1571    }
1572  va_end (vl);
1573
1574  strnew = SH_ALLOC( length + 2 ); 
1575  strnew[0] = '\0';
1576
1577  (void) sl_strlcpy (strnew, arg1, length + 2); 
1578
1579  va_start (vl, arg1);
1580  s = va_arg (vl, char * );
1581  while (s)
1582    {
1583      (void) sl_strlcat (strnew, s, length + 2);
1584      s = va_arg (vl, char * );
1585    }
1586  va_end (vl);
1587
1588  SL_RETURN(strnew, _("sh_util_strconcat"));
1589}
1590
1591
1592#ifdef HAVE_REGEX_H
1593
1594#include <regex.h>
1595
1596int sh_util_regcmp (char * regex_str, char * in_str)
1597{
1598#if defined(REG_ESPACE)
1599  int        status = REG_ESPACE;
1600#else
1601  int        status = -1;
1602#endif
1603  regex_t    preg;
1604  char     * errbuf;
1605
1606  SL_ENTER(_("sh_util_regcmp"));
1607
1608  status = regcomp(&preg, regex_str, REG_NOSUB|REG_EXTENDED);
1609
1610  if (status == 0)
1611    {
1612      if ((status = regexec(&preg, in_str, 0, NULL, 0)) == 0) 
1613        {
1614          regfree (&preg);
1615          SL_RETURN((0), _("sh_util_regcmp"));
1616        }
1617    }
1618
1619  if (status != 0 && status != REG_NOMATCH) 
1620    {
1621      errbuf = SH_ALLOC(BUFSIZ+2);
1622      (void) regerror(status, &preg, errbuf, BUFSIZ); 
1623      errbuf[BUFSIZ] = '\0';
1624      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX,
1625                       errbuf, regex_str);
1626      SH_FREE(errbuf);
1627    }
1628       
1629  regfree (&preg);
1630  SL_RETURN((-1), _("sh_util_regcmp"));
1631}
1632
1633#endif
1634
1635
1636
1637
1638
1639
1640
1641
Note: See TracBrowser for help on using the repository browser.