source: trunk/src/sh_utils.c @ 11

Last change on this file since 11 was 11, checked in by rainer, 15 years ago

Minor optimisations for server

File size: 37.5 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  static char  zap[KEY_BLOCK] = { 
530    (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 
531    (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 
532    (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, 
533    (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00, (char)0x00
534  };
535  char        K[KEY_BLOCK];
536  char        outer[KEY_BLOCK];
537  char      * inner;
538  UINT32    * h1;
539  UINT32    * h2;
540  UINT32      cc[KEY_LEN/4];
541  char      * res;
542
543  size_t      i;
544
545  SL_ENTER(_("sh_util_hmac_tiger"));
546  ASSERT((KEY_BLOCK <= (KEY_LEN/2)), _("KEY_BLOCK <= (KEY_LEN/2)"))
547
548  if (KEY_BLOCK > (KEY_LEN/2))
549    {
550      res = sh_tiger_hash (NULL, TIGER_DATA, 0);
551      SL_RETURN(res, _("sh_util_hmac_tiger"));
552    }
553
554  memcpy (K, zap, KEY_BLOCK);
555
556  if (sh_util_hextobinary (K, hexkey, KEY_LEN) < 0)
557    {
558      res = sh_tiger_hash (NULL, TIGER_DATA, 0);
559      SL_RETURN(res, _("sh_util_hmac_tiger"));
560    }
561
562  inner = (char *) SH_ALLOC (textlen + KEY_BLOCK); 
563
564  for (i = 0; i < KEY_BLOCK; ++i)
565    {
566      outer[i]  = K[i] ^ opad[i];
567      inner[i]  = K[i] ^ ipad[i];
568    }
569  for (i = KEY_BLOCK; i < (KEY_BLOCK+textlen); ++i)
570    {
571      inner[i] = text[i - KEY_BLOCK];
572    }
573
574  /* now compute the hash
575   */
576  h1 = sh_tiger_hash_uint32 ( outer,
577                              TIGER_DATA,
578                              KEY_BLOCK);
579  for (i = 0; i < (KEY_LEN/8); ++i)
580    {
581      /* cc[i] = h1[i]; */
582      copy_four ( (unsigned char *) &(cc[i]), h1[i]);
583    }
584
585  h2 = sh_tiger_hash_uint32 ( inner,
586                              TIGER_DATA,
587                              (unsigned long) KEY_BLOCK+textlen);
588  for (i = KEY_LEN/8; i < (KEY_LEN/4); ++i)
589    {
590      copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]);
591      /* cc[i] = h2[i - (KEY_LEN/8)]; */
592    }
593  SH_FREE(inner);
594 
595  res = sh_tiger_hash ((char *) &cc[0],
596                       TIGER_DATA,
597                       (unsigned long) (KEY_LEN/4 * sizeof(UINT32)));
598
599  SL_RETURN(res, _("sh_util_hmac_tiger"));
600}
601
602static char * sh_util_hash_tiger ( char * hexkey, 
603                                   char * text, size_t textlen)
604{
605  char         * res;
606  char           h2[2*KEY_LEN+1];
607  SL_ENTER(_("sh_util_hash_tiger"));
608
609  (void) sl_strlcpy(h2, hexkey, KEY_LEN+1); 
610  (void) sl_strlcat(h2, sh_tiger_hash(text, TIGER_DATA, 
611                                      (unsigned long) textlen), 2*KEY_LEN+1);
612
613  res = sh_tiger_hash(h2, TIGER_DATA, 2*KEY_LEN);
614
615  SL_RETURN(res, _("sh_util_hash_tiger"));
616}
617
618/* --- compute signature on data ---
619 */
620#define TYPE_HMAC 0
621#define TYPE_HASH 1
622
623static int sigtype = TYPE_HMAC;
624
625int sh_util_sigtype (char * c)
626{
627  SL_ENTER(_("sh_util_sigtype"));
628  if (c == NULL)
629    SL_RETURN( -1, _("sh_util_sigtype"));
630
631  if (0 == strcmp(_("HMAC-TIGER"), c))
632    sigtype = TYPE_HMAC;
633  else if  (0 == strcmp(_("HASH-TIGER"), c))
634    sigtype = TYPE_HASH;
635  else
636    SL_RETURN( -1, _("sh_util_sigtype"));
637
638  SL_RETURN( 0, _("sh_util_sigtype"));
639}
640
641char * sh_util_siggen (char * hexkey, 
642                       char * text, size_t textlen) 
643{
644  char * p;
645 
646  SL_ENTER(_("sh_util_siggen"));
647  if (sigtype == TYPE_HMAC)
648    p = sh_util_hmac_tiger (hexkey, 
649                            text, textlen);
650  else
651    p = sh_util_hash_tiger (hexkey, 
652                            text, textlen);
653  SL_RETURN(p, _("sh_util_siggen"));
654}   
655
656 
657 
658/* a simple compressor
659 */
660long sh_util_compress (char * dest, char * src, size_t dest_size)
661{
662  char * add;
663  char * get;
664  size_t   count = 0;
665  size_t   dest_end;
666
667  SL_ENTER(_("sh_util_compress"));
668
669  if (dest_size == 0)
670    SL_RETURN((0), _("sh_util_compress"));
671 
672  if ((dest == NULL) || (src == NULL))
673    SL_RETURN((0), _("sh_util_compress"));
674 
675  dest_end = sl_strlen(dest);
676
677  if (dest_end > dest_size)
678    SL_RETURN((0), _("sh_util_compress"));
679
680  add      = &dest[dest_end];
681  get      = src;
682
683  while (count < (dest_size-dest_end))
684    {
685      if (isalnum((int) *get)) 
686        {
687          *add = *get;
688          ++add;
689          ++count;
690        }
691      ++get; 
692      if (*get == '\0' && (count < (dest_size-dest_end))) 
693        /* end of src reached */
694        {
695          *add = *get;  /* copy the '\0'      */
696          break;        /* and stop copying   */
697        }
698    }
699
700  dest[dest_size-1] = '\0'; /* paranoia       */
701  SL_RETURN(((long)count), _("sh_util_compress")); /* no of chars copied */   
702}
703
704
705/* copy the four least significant bytes
706 */
707void sh_util_cpylong (char * dest, const char * src, int len )
708{
709  int i, j;
710  union
711  {
712    long l;
713    char c[sizeof(long)];
714  } u;
715
716  SL_ENTER(_("sh_util_cpylong"));   
717
718  u.l = 1;
719
720  /* MSB is first
721   */
722  if (sizeof(long)>4 &&/*@+charint@*/(u.c[sizeof(long)-1] == 1)/*@-charint@*/)
723    {
724      j = (int) (sizeof(long)-4);
725      for (i = 0; i < j; ++i) ++src;
726    }
727
728  i = 0;
729
730  while (i < 4)
731    {
732      *dest = (*src);
733      ++dest; ++src;
734      if (i == (len-1)) break;
735      ++i;
736    }
737  SL_RET0(_("sh_util_cpylong"));
738}
739
740/*  This is a maximally equidistributed combined Tausworthe
741 *  generator. The sequence is,
742 *
743 *   x_n = (s1_n ^ s2_n ^ s3_n)
744 *
745 *   s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
746 *   s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
747 *   s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
748 *
749 *   computed modulo 2^32. In the three formulas above '^' means
750 *   exclusive-or (C-notation), not exponentiation. Note that the
751 *   algorithm relies on the properties of 32-bit unsigned integers (it
752 *   is formally defined on bit-vectors of length 32).
753 *
754 *   Stolen from GSL (GNU scientific library) and modified somewhat.
755 *   I am using UINT32, which is guaranteed to be 32 bits. Also made
756 *   sure that the initialization vector is valid.
757 */
758
759
760/* interval [0, 4294967296]
761 */
762static UINT32 taus_get_long (void *vstate)
763{
764  UINT32 * state = (UINT32 *) vstate;
765
766  if (skey->rngI == BAD)
767    (void)taus_seed();
768
769#define TAUSWORTHE(s,a,b,c,d) ((s &c) <<d) ^ (((s <<a) ^s) >>b)
770  /*@+ignorequals@*/
771  state[0] = TAUSWORTHE (state[0], 13, 19, 4294967294UL, 12);
772  state[1] = TAUSWORTHE (state[1],  2, 25, 4294967288UL,  4);
773  state[2] = TAUSWORTHE (state[2],  3, 11, 4294967280UL, 17);
774  /*@-ignorequals@*/
775  return (state[0] ^ state[1] ^ state[2]);
776}
777
778/* Hide the internal state of the PRNG by using its output as
779 * input for a one-way hash function.
780 */
781UINT32   taus_svec[6];
782
783UINT32 taus_get (void *state1, void *state2, void *state3)
784{
785  UINT32   retval;
786  UINT32 * res;
787  register int i;
788
789  taus_svec[0] = taus_get_long (state1);
790  taus_svec[1] = taus_get_long (state2);
791  taus_svec[2] = taus_get_long (state3);
792  taus_svec[3] = taus_get_long (state1);
793  taus_svec[4] = taus_get_long (state2);
794  taus_svec[5] = taus_get_long (state3);
795
796  res     = sh_tiger_hash_uint32 ( (char *) &taus_svec[0], 
797                                   TIGER_DATA, 
798                                   (unsigned long)(6 * sizeof(UINT32)));
799
800  for (i = 1; i < KEY_BYT/4; ++i)
801    { 
802      res[0] ^= res[i];
803      res[i]  = 0;
804    }
805  retval = res[0];
806
807  taus_svec[0] = 0; taus_svec[1] = 0; taus_svec[2] = 0; 
808  taus_svec[3] = 0; taus_svec[4] = 0; taus_svec[5] = 0; 
809
810  return retval;
811}
812
813/* interval [0,1)
814 */
815double taus_get_double (void *vstate)
816{
817  return taus_get_long (vstate) / (4294967296.0 + 1.0) ;
818}
819
820#define LCG(n) ((69069 * n) & 0xffffffffUL)
821
822/* TAKE CARE: state[0], state[1], state[2] must be > 2,8,16, respectively
823 */
824static void taus_set_from_ulong (void *vstate, unsigned long int s)
825{
826  UINT32  *state = (UINT32  *) vstate;
827
828  if (s == 0)
829    s = 1;      /* default seed is 1 */
830
831  state[0] = (UINT32)(LCG (s)        | (UINT32) 0x03);
832  state[1] = (UINT32)(LCG (state[0]) | (UINT32) 0x09);
833  state[2] = (UINT32)(LCG (state[1]) | (UINT32) 0x17);
834
835  /* 'warm up'
836   */
837  (void) taus_get_long (state);
838  (void) taus_get_long (state);
839  (void) taus_get_long (state);
840  (void) taus_get_long (state);
841  (void) taus_get_long (state);
842  (void) taus_get_long (state);
843
844  return;
845}
846
847static void taus_set_from_state (void *vstate, void *init_state)
848{
849  UINT32  *state  = (UINT32  *) vstate;
850  UINT32  *state0 = (UINT32  *) init_state;
851
852  state[0] = state0[0]  | (UINT32) 0x03;
853  state[1] = state0[1]  | (UINT32) 0x09;
854  state[2] = state0[2]  | (UINT32) 0x17;
855 
856  return;
857}
858
859 
860int taus_seed ()
861{
862  char                 bufx[9 * sizeof(UINT32) + 1];
863  int                  status;
864  static unsigned long seed_time = 0;
865
866  SL_ENTER(_("taus_seed"));
867
868  if (skey->rngI == GOOD)
869    {
870      if ( (sh_unix_longtime () - seed_time) < 3600)
871        SL_RETURN( (0), _("taus_seed"));
872    }
873 
874  seed_time = sh_unix_longtime ();
875
876  status = sh_entropy (24, bufx);
877
878  if (!SL_ISERROR(status))
879    {
880      skey->rngI = GOOD;
881      memcpy (&skey->rng0[0], &bufx[0],                  2*sizeof(UINT32));
882      memcpy (&skey->rng1[0], &bufx[2*sizeof(UINT32)],   2*sizeof(UINT32));
883      memcpy (&skey->rng2[0], &bufx[4*sizeof(UINT32)],   2*sizeof(UINT32));
884      memset (bufx, 0, 9 * sizeof(UINT32) + 1);
885
886      skey->rng0[2] = 0;
887      skey->rng1[2] = 0;
888      skey->rng2[2] = 0;
889
890      taus_set_from_state( &(skey->rng0[0]), &(skey->rng0[0]));
891      taus_set_from_state( &(skey->rng1[0]), &(skey->rng1[0]));
892      taus_set_from_state( &(skey->rng2[0]), &(skey->rng2[0]));
893
894      SL_RETURN( (0), _("taus_seed"));
895    }
896
897  sh_error_handle ((-1), FIL__, __LINE__, status, MSG_ES_ENT,
898                   _("sh_entropy"));
899
900  /* emergency backup - unsafe !
901   */
902  skey->rngI = GOOD;
903#ifdef HAVE_GETTIMEOFDAY
904  taus_set_from_ulong ( &(skey->rng0[0]), LCG (sh_unix_notime())      );
905#else
906  taus_set_from_ulong ( &(skey->rng0[0]), LCG (seed_time)      );
907#endif
908  taus_set_from_ulong ( &(skey->rng1[0]), LCG (skey->rng0[0])  );
909  taus_set_from_ulong ( &(skey->rng2[0]), LCG (skey->rng1[0])  );
910  skey->rngI = BAD;
911
912  SL_RETURN( (-1), _("taus_seed"));
913}
914
915/*@+charint@*/
916static unsigned char new_key[] = { 0xA7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xA7 };
917/*@-charint@*/
918static void copy_four (unsigned char * dest, UINT32 in);
919
920int sh_util_set_newkey (char * new)
921{
922  size_t i, j = 0;
923  size_t len;
924  SL_TICKET fp;
925  SL_TICKET fout;
926  char * key;
927  char * path;
928  char * outpath;
929  unsigned char * image = NULL;
930  long s = 0;
931  long ilen = 0;
932  long ii, k = 0;
933  UINT32    * h1;
934
935  if (0 != sl_is_suid())
936    {
937      fprintf(stderr, _("ERROR: insufficient privilege\n"));
938      _exit (EXIT_FAILURE);
939      /*@notreached@*/
940      return -1;  /* braindead MAC OSX compiler needs this */
941    }
942       
943  if (new == NULL || new[0] == '\0')
944    {
945      fprintf(stderr, 
946              _("ERROR: no key given\n Argument must be 'key@path'\n"));
947      _exit (EXIT_FAILURE);
948      /*@notreached@*/
949      return -1;
950    }
951  key = new;
952  len = strlen(new);
953  for (i = 1; i < (len-2); ++i)
954    {
955      if (new[i] == '@' && new[i+1] == '/')
956        {
957          j = i+1; new[i] = '\0'; break;
958        }
959    }
960  if (j == 0)
961    {
962      fprintf(stderr, 
963              _("ERROR: no path to executable given\n Argument must be 'key@path'\n"));
964      _exit (EXIT_FAILURE);
965      /*@notreached@*/
966      return -1;
967    }
968  else
969    path = &new[j];
970  /*@-usedef@*/
971  if (NULL == (outpath = malloc(strlen(path) + 1 + 4)))
972    goto bail_mem;
973  /*@-usedef@*/
974  /*@-bufferoverflowhigh@*/
975  sprintf (outpath, _("%s.out"), path);               /* known to fit  */ 
976  /*@+bufferoverflowhigh@*/
977
978  fp = sl_open_read(path, SL_NOPRIV);
979  if (SL_ISERROR(fp))
980    {
981      fprintf(stderr, 
982              _("ERROR: cannot open %s for read (errnum = %ld)\n"), path, fp);
983      _exit (EXIT_FAILURE);
984      /*@notreached@*/
985      return -1;
986    }
987 
988  fout = sl_open_write(outpath, SL_NOPRIV);
989  if (SL_ISERROR(fout))
990    {
991      fprintf(stderr, 
992              _("ERROR: cannot open %s (errnum = %ld)\n"), outpath, fout);
993      _exit (EXIT_FAILURE);
994      /*@notreached@*/
995      return -1;
996    }
997
998
999  image = malloc (4096);
1000  if (!image)
1001    goto bail_mem;
1002  while (0 < (ii = sl_read (fp, &image[s], 4096)))
1003    {
1004      ilen += ii;
1005      s    += 4096;
1006      image = realloc (image, (size_t) (4096 + s));
1007      if (!image)
1008        goto bail_mem;
1009    }
1010
1011  printf(_("%ld bytes read\n"), ilen);
1012
1013 
1014  for (k = 0; k < (ilen - 8); ++k) 
1015    {
1016      if (image[k]   == new_key[0] &&
1017          image[k+1] == new_key[1] &&
1018          image[k+2] == new_key[2] &&
1019          image[k+3] == new_key[3] &&
1020          image[k+4] == new_key[4] &&
1021          image[k+5] == new_key[5] &&
1022          image[k+6] == new_key[6] &&
1023          image[k+7] == new_key[7])
1024        {
1025          printf(_("old key found\n")); 
1026          h1 = sh_tiger_hash_uint32 (key, TIGER_DATA, 
1027                                     (unsigned long)strlen(key));
1028          copy_four( (unsigned char *) &(image[k]),   h1[0]);
1029          copy_four( (unsigned char *) &(image[k+4]), h1[1]);
1030          (void) sl_write (fout, image, ilen);
1031          (void) sl_close (fout);
1032          printf(_("new file %s written\n"), outpath);
1033          _exit (EXIT_SUCCESS);
1034          /*@notreached@*/
1035          return 0;
1036        }
1037    }
1038
1039  fprintf(stderr, 
1040          _("ERROR: old key not found\n"));
1041  _exit (EXIT_FAILURE);
1042  /*@notreached@*/
1043  return -1;
1044
1045
1046 bail_mem:
1047  fprintf(stderr, 
1048          _("ERROR: out of memory\n"));
1049  _exit (EXIT_FAILURE);
1050  /*@notreached@*/
1051  return -1;
1052}
1053
1054 
1055
1056       
1057/* A simple en-/decoder, based on Vernam cipher. We use the
1058 * message as salt to hide the key by obtaining a different one-time
1059 * pad each time.
1060 * Should be safe against a listener on the network, but not against someone
1061 * with read access to the binary.
1062 */
1063void sh_util_encode (char * data, char * salt, int mode, char fill)
1064{
1065  static char     cc1[17] = N_("0123456789ABCDEF");
1066  char            cc[17] = "\0";
1067  register int    i, j, j1 = 0, j2 = 0, j3;
1068  char          * dez; 
1069
1070  SL_ENTER(_("sh_util_encode"));
1071
1072  /* init
1073   */
1074  (void) sl_strlcpy( cc, _(cc1), sizeof(cc));
1075
1076  /* max 128 bits keyspace
1077   */
1078  memset (skey->vernam, (int)fill, KEY_LEN+1);
1079
1080  dez    = (char *) &(skey->ErrFlag[0]);
1081  sh_util_cpylong (skey->vernam,     dez, 4);
1082  dez    = (char *) &(skey->ErrFlag[1]);
1083  sh_util_cpylong (&skey->vernam[4], dez, 4);
1084
1085  skey->vernam[KEY_LEN] = '\0';
1086
1087  (void) sl_strlcpy(skey->vernam, 
1088                    sh_tiger_hash(skey->vernam, TIGER_DATA, KEY_LEN), 
1089                    KEY_LEN+1);
1090
1091  (void) sl_strlcpy(skey->vernam, 
1092                    sh_util_hmac_tiger (skey->vernam, salt, strlen(salt)),
1093             KEY_LEN+1);
1094
1095  (void) sl_strlcpy(skey->vernam, 
1096                    sh_util_hmac_tiger (skey->vernam, (char*) new_key, 8),
1097                    KEY_LEN+1);
1098
1099  /* The following routine adds/subtracts  data[j] and vernam[j] mod 16.
1100   */
1101  j = 0;
1102  while (j < KEY_LEN)
1103    {
1104      for (i = 0; i < 16; ++i)
1105        {
1106          if (cc[i] == data[j])   j1 = i;
1107          if (cc[i] == skey->vernam[j])    j2 = i;
1108        }
1109      if (mode == 0)
1110        {
1111          j3 = j1 + j2;
1112          if (j3 > 15) j3 -= 16;
1113          data[j] = cc[j3];
1114        }
1115      else
1116        {
1117          j3 = j1 - j2;
1118          if (j3 <  0) j3 += 16;
1119          data[j] = cc[j3];
1120        }
1121      ++j;
1122    }
1123  SL_RET0(_("sh_util_encode"));
1124}
1125
1126/* server mode
1127 */
1128int sh_util_setserver (char * dummy)
1129{
1130  SL_ENTER(_("sh_util_setserver"));
1131
1132  if (dummy)
1133    sh.flag.isserver = GOOD;
1134  else
1135    sh.flag.isserver = GOOD;
1136  SL_RETURN((0),_("sh_util_setserver"));
1137}
1138
1139
1140int sh_util_setlooptime (char * str)
1141{
1142  int i = atoi (str);
1143 
1144  SL_ENTER(_("sh_util_setlooptime"));
1145
1146  if (i >= 0 && i < INT_MAX) {
1147    sh.looptime = i;
1148    SL_RETURN((0),_("sh_util_setlooptime"));
1149  } else {
1150    sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1151                     _("loop time"), str);
1152    SL_RETURN((-1),_("sh_util_setlooptime"));
1153  }
1154}
1155
1156#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1157int  sh_util_setchecksum (char * str)
1158{
1159  static int reject = 0;
1160
1161  SL_ENTER(_("sh_util_setchecksum"));
1162
1163  if (reject == 1)
1164    SL_RETURN((0), _("sh_util_setchecksum"));
1165  reject = 1;
1166
1167  if (sl_strncmp (str, _("init"), sizeof("init")-1) == 0)
1168    {
1169      sh.flag.checkSum = SH_CHECK_INIT;
1170    }
1171  else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1172    {
1173      if (S_TRUE == file_is_remote()) 
1174        {
1175          sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1176                           _("checksum testing"), str);
1177          SL_RETURN((-1), _("sh_util_setchecksum"));
1178        }
1179      else
1180        {
1181          sh.flag.checkSum = SH_CHECK_CHECK;
1182          sh.flag.update   = S_TRUE;
1183        }
1184    }
1185  else if (sl_strncmp (str, _("check"), sizeof("check")-1) == 0)
1186    {
1187      sh.flag.checkSum = SH_CHECK_CHECK;
1188    }
1189  /*
1190  else if (sl_strncmp (str, _("update"), sizeof("update")-1) == 0)
1191    {
1192      sh.flag.checkSum = SH_CHECK_INIT;
1193      sh.flag.update   = S_TRUE;
1194    }
1195  */
1196  else if (sl_strncmp (str, _("none"), sizeof("none")-1) == 0)
1197    {
1198      sh.flag.checkSum = SH_CHECK_NONE;
1199    }
1200  else 
1201    {
1202      sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1203                       _("checksum testing"), str);
1204      SL_RETURN((-1), _("sh_util_setchecksum"));
1205    }
1206  SL_RETURN((0), _("sh_util_setchecksum"));
1207}
1208#endif
1209 
1210/*@+charint@*/
1211unsigned char TcpFlag[8][PW_LEN+1] = { 
1212#if (POS_TF == 1)
1213  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1214#endif
1215  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1216#if (POS_TF == 2)
1217  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1218#endif
1219  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1220#if (POS_TF == 3)
1221  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1222#endif
1223  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1224#if (POS_TF == 4)
1225  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1226#endif
1227  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1228#if (POS_TF == 5)
1229  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1230#endif
1231  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1232#if (POS_TF == 6)
1233  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1234#endif
1235  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1236#if (POS_TF == 7)
1237  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1238#endif
1239  { 0xFF,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xFF,0x00 },
1240#if (POS_TF == 8)
1241  { 0xF7,0xC3,0x12,0xAA,0xAA,0x12,0xC3,0xF7,0x00 },
1242#endif
1243};
1244/*@-charint@*/
1245
1246/* initialize a key to a random value
1247 * rev 0.8
1248 */
1249int sh_util_keyinit (char * buf, long size)
1250{
1251  UINT32       bufy[6];
1252  int          i;
1253  int          status = 0;
1254  char       * p;
1255
1256  SL_ENTER(_("sh_util_keyinit"));
1257
1258  ASSERT((size <= KEY_LEN+1), _("size <= KEY_LEN+1"))
1259
1260  if (size > KEY_LEN+1)
1261    size = KEY_LEN+1;
1262
1263  /* seed / re-seed the PRNG if required
1264   */
1265  status = taus_seed ();
1266
1267  if (status == -1)
1268    sh_error_handle ((-1), FIL__, __LINE__, -1, MSG_ES_KEY1,
1269                     _("taus_seed"));
1270
1271  for (i = 0; i < 6; ++i)
1272    bufy[i] = taus_get(&(skey->rng0[0]), &(skey->rng1[0]), &(skey->rng2[0]));
1273
1274  p = sh_tiger_hash ((char *) bufy, TIGER_DATA, 
1275                     (unsigned long)(6*sizeof(UINT32)));
1276  p[size-1] = '\0';
1277
1278  i = sl_strlcpy(buf, p, (size_t)size);
1279
1280  memset (bufy, 0, 6*sizeof(UINT32));
1281
1282  if ((status == 0) && (!SL_ISERROR(i)) )
1283    SL_RETURN((0),_("sh_util_keyinit"));
1284
1285  if (SL_ISERROR(i))
1286    sh_error_handle ((-1), FIL__, __LINE__, i, MSG_ES_KEY2, 
1287                     _("sl_strlcpy"));
1288
1289  SL_RETURN((-1),_("sh_util_keyinit"));
1290}
1291
1292#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1293
1294static unsigned char sh_obscure_index[256];
1295
1296int sh_util_obscure_ok (char * str)
1297{
1298  unsigned long   i;
1299  char * endptr = str;
1300
1301  SL_ENTER(_("sh_util_obscure_ex"));
1302
1303  if (0 == sl_strncmp("all", str, 3))
1304    {
1305      for (i = 0; i < 255; ++i)
1306        {
1307          sh_obscure_index[i] = (unsigned char)1;
1308        }
1309      SL_RETURN(0, _("sh_util_obscure_ex"));
1310    }
1311
1312  for (i = 0; i < 255; ++i)
1313    {
1314      sh_obscure_index[i] = (unsigned char)0;
1315    }
1316
1317  while (*endptr != '\0')
1318    {
1319      i = strtoul (endptr, &endptr, 0);
1320      if (i > 255)
1321        {
1322          SL_RETURN(-1, _("sh_util_obscure_ex"));
1323        }
1324      sh_obscure_index[i] = (unsigned char)1;
1325      if (*endptr == ',')
1326        ++endptr;
1327    }
1328  SL_RETURN(0, _("sh_util_obscure_ex"));
1329}
1330
1331int sh_util_obscurename (ShErrLevel level, char * name_orig, int flag)
1332{
1333  char * name = name_orig;
1334  char * safe;
1335  unsigned int i;
1336
1337  SL_ENTER(_("sh_util_obscurename"));
1338
1339  ASSERT_RET((name != NULL), _("name != NULL"), (0))
1340
1341  /* -- Check name. --
1342   */
1343  while (*name != '\0') 
1344    {
1345      if ( (*name) == '"'  || (*name) == '\t' ||
1346           (*name) == '\b' || (*name) == '\f' || 
1347           (*name) == '\n' || (*name) == '\r' ||
1348           (*name) == '\v' || iscntrl((int) *name) || 
1349           ((*name) != ' ' && !isgraph ((int) *name)) ) 
1350        {
1351          i = (unsigned char) *name;
1352          if (sh_obscure_index[i] != (unsigned char)1)
1353            {
1354              if (flag == S_TRUE)
1355                {
1356                  safe = sh_util_safe_name (name_orig); 
1357                  sh_error_handle (level, FIL__, __LINE__, 0, MSG_FI_OBSC, 
1358                                   safe);
1359                  SH_FREE(safe);
1360                }
1361              SL_RETURN((-1),_("sh_util_obscurename"));
1362            }
1363        }
1364      name++;
1365    }
1366
1367  SL_RETURN((0),_("sh_util_obscurename"));
1368}
1369#endif
1370
1371/* returns freshly allocated memory, return value should be free'd
1372 */
1373char * sh_util_basename(char * fullpath)
1374{
1375  char * retval;
1376  size_t i;
1377
1378  SL_ENTER(_("sh_util_basename"));
1379
1380  ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1381
1382  i = sl_strlen (fullpath);  /* fullpath[i] is terminating '\0' */
1383
1384  while (i > 0) {
1385    --i;
1386    if (fullpath[i] == '/') break;
1387  }
1388
1389  /* -- Not a valid path. --
1390   */
1391  if ((fullpath[i] != '/') && (i == 0) ) 
1392    SL_RETURN(NULL, _("sh_util_basename"));
1393
1394  retval = SH_ALLOC(i + 1);
1395
1396  (void) sl_strlcpy (retval, fullpath, i+1);
1397
1398  SL_RETURN(retval, _("sh_util_basename"));
1399}
1400
1401/* returns freshly allocated memory, return value should be free'd
1402 */
1403char * sh_util_filename(char * fullpath)
1404{
1405  char * retval;
1406  char * c;
1407  size_t i;
1408
1409  SL_ENTER(_("sh_util_filename"));
1410
1411  ASSERT_RET ((fullpath != NULL), _("fullpath != NULL"), (NULL))
1412
1413  c = strrchr(fullpath, '/');
1414  i = sl_strlen (c);
1415  if (i <= 1) SL_RETURN(NULL, _("sh_util_filename")); /* ends in '/' */
1416  ++c;
1417  --i;
1418
1419  retval = SH_ALLOC(i + 1);
1420
1421  (void) sl_strlcpy (retval, c, i+1);
1422
1423  SL_RETURN(retval, _("sh_util_filename"));
1424}
1425
1426   
1427/* returns freshly allocated memory, return value should be free'd
1428 */
1429char * sh_util_safe_name (const char * name)
1430{
1431  register int  i = 0;
1432  const char  * p;
1433  char        * retval;
1434  char          oct[32];
1435  char          format[16];
1436
1437  SL_ENTER(_("sh_util_safe_name"));
1438
1439  if (name == NULL)
1440    {
1441      /* return an allocated array
1442       */
1443      retval = SH_ALLOC(7);
1444      (void) sl_strlcpy(retval, _("(null)"), 7);
1445      SL_RETURN(retval, _("sh_util_safe_name"));
1446    }
1447
1448  /*
1449  ASSERT_RET ((name != NULL), _("name != NULL"), _("NULL"))
1450  */
1451
1452#ifdef SH_USE_XML
1453  retval = SH_ALLOC(6 * sl_strlen(name) + 2);
1454#else
1455  retval = SH_ALLOC(4 * sl_strlen(name) + 2);
1456#endif
1457
1458  (void) sl_strncpy(format, _("%c%03o"), 16);
1459
1460  p = name;
1461
1462  while (*p != '\0') {
1463    /* Most frequent cases first
1464     */
1465    if ( ((*p) >= 'a' && (*p) <= 'z')  || ((*p) == '/') || ((*p) == '.') ||
1466         ((*p) >= '0' && (*p) <= '9')  || 
1467         ((*p) >= 'A' && (*p) <= 'Z')) {
1468      retval[i] = *p; 
1469    } else if ( (*p) == '\\') {           /* backslash        */
1470      retval[i] = '\\'; ++i; 
1471      retval[i] = '\\';
1472    } else if ( (*p) == '\n') {    /* newline          */
1473      retval[i] = '\\'; ++i; 
1474      retval[i] = 'n';
1475    } else if ( (*p) == '\b') {    /* backspace        */
1476      retval[i] = '\\'; ++i; 
1477      retval[i] = 'b';
1478    } else if ( (*p) == '\r') {    /* carriage  return */
1479      retval[i] = '\\'; ++i; 
1480      retval[i] = 'r';
1481    } else if ( (*p) == '\t') {    /* horizontal tab   */
1482      retval[i] = '\\'; ++i; 
1483      retval[i] = 't';
1484    } else if ( (*p) == '\v') {    /* vertical tab     */
1485      retval[i] = '\\'; ++i; 
1486      retval[i] = 'v';
1487    } else if ( (*p) == '\f') {    /* form-feed        */
1488      retval[i] = '\\'; ++i; 
1489      retval[i] = 'f';
1490#ifdef WITH_DATABASE
1491    } else if ( (*p) == '\'') {    /* single quote     */
1492      retval[i] = '\\'; ++i; 
1493      retval[i] = '\'';
1494#endif
1495    } else if ( (*p) == ' ') {     /* space            */
1496      retval[i] = '\\'; ++i; 
1497      retval[i] = ' ';
1498#ifdef SH_USE_XML
1499    } else if ( (*p) == '"') {     /* double quote     */
1500      retval[i] = '&'; ++i; 
1501      retval[i] = 'q'; ++i;
1502      retval[i] = 'u'; ++i;
1503      retval[i] = 'o'; ++i;
1504      retval[i] = 't'; ++i;
1505      retval[i] = ';';
1506    } else if ( (*p) == '&') {     /* ampersand        */
1507      retval[i] = '&'; ++i; 
1508      retval[i] = 'a'; ++i;
1509      retval[i] = 'm'; ++i;
1510      retval[i] = 'p'; ++i;
1511      retval[i] = ';';
1512    } else if ( (*p) == '<') {     /* left angle       */
1513      retval[i] = '&'; ++i; 
1514      retval[i] = 'l'; ++i;
1515      retval[i] = 't'; ++i;
1516      retval[i] = ';';
1517    } else if ( (*p) == '>') {     /* right angle      */
1518      retval[i] = '&'; ++i; 
1519      retval[i] = 'g'; ++i;
1520      retval[i] = 't'; ++i;
1521      retval[i] = ';';
1522#else
1523    } else if ( (*p) == '"') {     /* double quote     */
1524      retval[i] = '\\'; ++i; 
1525      retval[i] = '\"';
1526#endif
1527    } else if (!isgraph ((int) *p)) {    /* not printable    */
1528      /*@-bufferoverflowhigh -formatconst@*/
1529      sprintf(oct, format, '\\',                 /* known to fit  */
1530              (unsigned char) *p);
1531      /*@+bufferoverflowhigh +formatconst@*/
1532      retval[i] = oct[0]; ++i;
1533      retval[i] = oct[1]; ++i;
1534      retval[i] = oct[2]; ++i;
1535      retval[i] = oct[3]; 
1536    } else {
1537      retval[i] = *p;
1538    }
1539    ++p;
1540    ++i;
1541  }
1542  retval[i] = '\0';
1543  SL_RETURN(retval, _("sh_util_safe_name"));
1544}
1545
1546int sh_util_isnum (char *str)
1547{
1548  char *p = str;
1549
1550  SL_ENTER(_("sh_util_isnum"));
1551
1552  ASSERT_RET ((str != NULL), _("str != NULL"), (-1))
1553
1554  while (p) {
1555    if (!isdigit((int) *p) ) 
1556      SL_RETURN((-1), _("sh_util_isnum"));
1557    ++p;
1558  }
1559  SL_RETURN((0), _("sh_util_isnum"));
1560}
1561
1562char * sh_util_strconcat (const char * arg1, ...)
1563{
1564  size_t    length;
1565  char    * s;
1566  char    * strnew;
1567  va_list vl;
1568
1569  SL_ENTER(_("sh_util_strconcat"));
1570
1571  ASSERT_RET ((arg1 != NULL), _("arg1 != NULL"), (NULL))
1572
1573  length = sl_strlen (arg1) + 1;
1574
1575  va_start (vl, arg1);
1576  s = va_arg (vl, char * );
1577  while (s != NULL)
1578    {
1579      length = length + sl_strlen (s);
1580      s = va_arg (vl, char * );
1581    }
1582  va_end (vl);
1583
1584  strnew = SH_ALLOC( length + 2 ); 
1585  strnew[0] = '\0';
1586
1587  (void) sl_strlcpy (strnew, arg1, length + 2); 
1588
1589  va_start (vl, arg1);
1590  s = va_arg (vl, char * );
1591  while (s)
1592    {
1593      (void) sl_strlcat (strnew, s, length + 2);
1594      s = va_arg (vl, char * );
1595    }
1596  va_end (vl);
1597
1598  SL_RETURN(strnew, _("sh_util_strconcat"));
1599}
1600
1601
1602#ifdef HAVE_REGEX_H
1603
1604#include <regex.h>
1605
1606int sh_util_regcmp (char * regex_str, char * in_str)
1607{
1608#if defined(REG_ESPACE)
1609  int        status = REG_ESPACE;
1610#else
1611  int        status = -1;
1612#endif
1613  regex_t    preg;
1614  char     * errbuf;
1615
1616  SL_ENTER(_("sh_util_regcmp"));
1617
1618  status = regcomp(&preg, regex_str, REG_NOSUB|REG_EXTENDED);
1619
1620  if (status == 0)
1621    {
1622      if ((status = regexec(&preg, in_str, 0, NULL, 0)) == 0) 
1623        {
1624          regfree (&preg);
1625          SL_RETURN((0), _("sh_util_regcmp"));
1626        }
1627    }
1628
1629  if (status != 0 && status != REG_NOMATCH) 
1630    {
1631      errbuf = SH_ALLOC(BUFSIZ+2);
1632      (void) regerror(status, &preg, errbuf, BUFSIZ); 
1633      errbuf[BUFSIZ] = '\0';
1634      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_E_REGEX,
1635                       errbuf, regex_str);
1636      SH_FREE(errbuf);
1637    }
1638       
1639  regfree (&preg);
1640  SL_RETURN((-1), _("sh_util_regcmp"));
1641}
1642
1643#endif
1644
1645
1646
1647
1648
1649
1650
1651
Note: See TracBrowser for help on using the repository browser.