Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / contrib / zkt / misc.c
blobcc796b22369c662198fe81ee0c55fc47b92b1e74
1 /* $NetBSD$ */
3 /*****************************************************************
4 **
5 ** @(#) misc.c -- helper functions for the dnssec zone key tools
6 **
7 ** Copyright (c) Jan 2005, Holger Zuleger HZnet. All rights reserved.
8 **
9 ** This software is open source.
11 ** Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions
13 ** are met:
15 ** Redistributions of source code must retain the above copyright notice,
16 ** this list of conditions and the following disclaimer.
18 ** Redistributions in binary form must reproduce the above copyright notice,
19 ** this list of conditions and the following disclaimer in the documentation
20 ** and/or other materials provided with the distribution.
22 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
23 ** be used to endorse or promote products derived from this software without
24 ** specific prior written permission.
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 ** POSSIBILITY OF SUCH DAMAGE.
38 *****************************************************************/
39 # include <stdio.h>
40 # include <string.h>
41 # include <stdlib.h>
42 # include <unistd.h> /* for link(), unlink() */
43 # include <ctype.h>
44 # include <sys/types.h>
45 # include <sys/stat.h>
46 # include <time.h>
47 # include <utime.h>
48 # include <assert.h>
49 # include <errno.h>
50 # include <fcntl.h>
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif
54 # include "config_zkt.h"
55 # include "zconf.h"
56 # include "log.h"
57 # include "debug.h"
58 #define extern
59 # include "misc.h"
60 #undef extern
62 # define TAINTEDCHARS "`$@;&<>|"
64 extern const char *progname;
66 /*****************************************************************
67 ** getnameappendix (progname, basename)
68 ** return a pointer to the substring in progname subsequent
69 ** following "<basename>-".
70 *****************************************************************/
71 const char *getnameappendix (const char *progname, const char *basename)
73 const char *p;
74 int baselen;
76 assert (progname != NULL);
77 assert (basename != NULL);
79 if ( (p = strrchr (progname, '/')) != NULL )
80 p++;
81 else
82 p = progname;
84 baselen = strlen (basename);
85 if ( strncmp (p, basename, baselen-1) == 0 && *(p+baselen) == '-' )
87 p += baselen + 1;
88 if ( *p )
89 return p;
92 return NULL;
95 /*****************************************************************
96 ** getdefconfname (view)
97 ** returns a pointer to a dynamic string containing the
98 ** default configuration file name
99 *****************************************************************/
100 const char *getdefconfname (const char *view)
102 char *p;
103 char *file;
104 char *buf;
105 int size;
107 if ( (file = getenv ("ZKT_CONFFILE")) == NULL )
108 file = CONFIG_FILE;
109 dbg_val2 ("getdefconfname (%s) file = %s\n", view ? view : "NULL", file);
111 if ( view == NULL || *view == '\0' || (p = strrchr (file, '.')) == NULL )
112 return strdup (file);
114 size = strlen (file) + strlen (view) + 1 + 1;
115 if ( (buf = malloc (size)) == NULL )
116 return strdup (file);
118 dbg_val1 ("0123456789o123456789o123456789\tsize=%d\n", size);
119 dbg_val4 ("%.*s-%s%s\n", p - file, file, view, p);
121 snprintf (buf, size, "%.*s-%s%s", p - file, file, view, p);
122 return buf;
125 /*****************************************************************
126 ** domain_canonicdup (s)
127 ** returns NULL or a pointer to a dynamic string containing the
128 ** canonic (all lower case letters and ending with a '.')
129 ** domain name
130 *****************************************************************/
131 char *domain_canonicdup (const char *s)
133 char *new;
134 char *p;
135 int len;
136 int add_dot;
138 if ( s == NULL )
139 return NULL;
141 add_dot = 0;
142 len = strlen (s);
143 if ( len > 0 && s[len-1] != '.' )
144 add_dot = len++;
146 if ( (new = p = malloc (len + 1)) == NULL )
147 return NULL;
149 while ( *s )
150 *p++ = tolower (*s++);
151 if ( add_dot )
152 *p++ = '.';
153 *p = '\0';
155 return new;
157 #if 0 /* replaced by domain_canonicdup */
158 /*****************************************************************
159 ** str_tolowerdup (s)
160 *****************************************************************/
161 char *str_tolowerdup (const char *s)
163 char *new;
164 char *p;
166 if ( s == NULL || (new = p = malloc (strlen (s) + 1)) == NULL )
167 return NULL;
169 while ( *s )
170 *p++ = tolower (*s++);
171 *p = '\0';
173 return new;
175 #endif
177 /*****************************************************************
178 ** str_delspace (s)
179 ** Remove in string 's' all white space char
180 *****************************************************************/
181 char *str_delspace (char *s)
183 char *start;
184 char *p;
186 if ( !s ) /* no string present ? */
187 return NULL;
189 start = s;
190 for ( p = s; *p; p++ )
191 if ( !isspace (*p) )
192 *s++ = *p; /* copy each nonspace */
194 *s = '\0'; /* terminate string */
196 return start;
199 /*****************************************************************
200 ** in_strarr (str, arr, cnt)
201 ** check if string array 'arr' contains the string 'str'
202 ** return 1 if true or 'arr' or 'str' is empty, otherwise 0
203 *****************************************************************/
204 int in_strarr (const char *str, char *const arr[], int cnt)
206 if ( arr == NULL || cnt <= 0 )
207 return 1;
209 if ( str == NULL || *str == '\0' )
210 return 0;
212 while ( --cnt >= 0 )
213 if ( strcmp (str, arr[cnt]) == 0 )
214 return 1;
216 return 0;
219 /*****************************************************************
220 ** str_untaint (s)
221 ** Remove in string 's' all TAINTED chars
222 *****************************************************************/
223 char *str_untaint (char *str)
225 char *p;
227 assert (str != NULL);
229 for ( p = str; *p; p++ )
230 if ( strchr (TAINTEDCHARS, *p) )
231 *p = ' ';
232 return str;
235 /*****************************************************************
236 ** str_chop (str, c)
237 ** delete all occurrences of char 'c' at the end of string 's'
238 *****************************************************************/
239 char *str_chop (char *str, char c)
241 int len;
243 assert (str != NULL);
245 len = strlen (str) - 1;
246 while ( len >= 0 && str[len] == c )
247 str[len--] = '\0';
249 return str;
252 /*****************************************************************
253 ** parseurl (url, &proto, &host, &port, &para )
254 ** parses the given url (e.g. "proto://host.with.domain:port/para")
255 ** and set the pointer variables to the corresponding part of the string.
256 *****************************************************************/
257 void parseurl (char *url, char **proto, char **host, char **port, char **para)
259 char *start;
260 char *p;
262 assert ( url != NULL );
264 /* parse protocol */
265 if ( (p = strchr (url, ':')) == NULL ) /* no protocol string given ? */
266 p = url;
267 else /* looks like a protocol string */
268 if ( p[1] == '/' && p[2] == '/' ) /* protocol string ? */
270 *p = '\0';
271 p += 3;
272 if ( proto )
273 *proto = url;
275 else /* no protocol string found ! */
276 p = url;
278 /* parse host */
279 if ( *p == '[' ) /* ipv6 address as hostname ? */
281 for ( start = ++p; *p && *p != ']'; p++ )
283 if ( *p )
284 *p++ = '\0';
286 else
287 for ( start = p; *p && *p != ':' && *p != '/'; p++ )
289 if ( host )
290 *host = start;
292 /* parse port */
293 if ( *p == ':' )
295 *p++ = '\0';
296 for ( start = p; *p && isdigit (*p); p++ )
298 if ( *p )
299 *p++ = '\0';
300 if ( port )
301 *port = start;
304 if ( *p == '/' )
305 *p++ = '\0';
307 if ( *p && para )
308 *para = p;
311 /*****************************************************************
312 ** splitpath (path, pathsize, filename)
313 ** if filename is build of "path/file" then copy filename to path
314 ** and split of the filename part.
315 ** return pointer to filename part in path or NULL if path is too
316 ** small to hold "path+filename"
317 *****************************************************************/
318 const char *splitpath (char *path, size_t psize, const char *filename)
320 char *p;
322 if ( !path )
323 return NULL;
325 *path = '\0';
326 if ( !filename )
327 return filename;
329 if ( (p = strrchr (filename, '/')) ) /* file arg contains path ? */
331 if ( strlen (filename) + 1 > psize )
332 return filename;
334 strcpy (path, filename); /* copy whole filename to path */
335 path[p-filename] = '\0'; /* split of the file part */
336 filename = ++p;
338 return filename;
341 /*****************************************************************
342 ** pathname (path, size, dir, file, ext)
343 ** Concatenate 'dir', 'file' and 'ext' (if not null) to build
344 ** a pathname, and store the result in the character array
345 ** with length 'size' pointed to by 'path'.
346 *****************************************************************/
347 char *pathname (char *path, size_t size, const char *dir, const char *file, const char *ext)
349 int len;
351 if ( path == NULL || file == NULL )
352 return path;
354 len = strlen (file) + 1;
355 if ( dir )
356 len += strlen (dir);
357 if ( ext )
358 len += strlen (ext);
359 if ( len > size )
360 return path;
362 *path = '\0';
363 if ( dir && *dir )
365 len = sprintf (path, "%s", dir);
366 if ( path[len-1] != '/' )
368 path[len++] = '/';
369 path[len] = '\0';
372 strcat (path, file);
373 if ( ext )
374 strcat (path, ext);
375 return path;
378 /*****************************************************************
379 ** is_directory (name)
380 ** Check if the given pathname 'name' exists and is a directory.
381 ** returns 0 | 1
382 *****************************************************************/
383 int is_directory (const char *name)
385 struct stat st;
387 if ( !name || !*name )
388 return 0;
390 return ( stat (name, &st) == 0 && S_ISDIR (st.st_mode) );
393 /*****************************************************************
394 ** fileexist (name)
395 ** Check if a file with the given pathname 'name' exists.
396 ** returns 0 | 1
397 *****************************************************************/
398 int fileexist (const char *name)
400 struct stat st;
401 return ( stat (name, &st) == 0 && S_ISREG (st.st_mode) );
404 /*****************************************************************
405 ** filesize (name)
406 ** return the size of the file with the given pathname 'name'.
407 ** returns -1 if the file not exist
408 *****************************************************************/
409 size_t filesize (const char *name)
411 struct stat st;
412 if ( stat (name, &st) == -1 )
413 return -1L;
414 return ( st.st_size );
417 /*****************************************************************
418 ** is_keyfilename (name)
419 ** Check if the given name looks like a dnssec (public)
420 ** keyfile name. Returns 0 | 1
421 *****************************************************************/
422 int is_keyfilename (const char *name)
424 int len;
426 if ( name == NULL || *name != 'K' )
427 return 0;
429 len = strlen (name);
430 if ( len > 4 && strcmp (&name[len - 4], ".key") == 0 )
431 return 1;
433 return 0;
436 /*****************************************************************
437 ** is_dotfilename (name)
438 ** Check if the given pathname 'name' looks like "." or "..".
439 ** Returns 0 | 1
440 *****************************************************************/
441 int is_dotfilename (const char *name)
443 if ( name && (
444 (name[0] == '.' && name[1] == '\0') ||
445 (name[0] == '.' && name[1] == '.' && name[2] == '\0')) )
446 return 1;
448 return 0;
451 /*****************************************************************
452 ** touch (name, sec)
453 ** Set the modification time of the given pathname 'fname' to
454 ** 'sec'. Returns 0 on success.
455 *****************************************************************/
456 int touch (const char *fname, time_t sec)
458 struct utimbuf utb;
460 utb.actime = utb.modtime = sec;
461 return utime (fname, &utb);
464 /*****************************************************************
465 ** linkfile (fromfile, tofile)
466 *****************************************************************/
467 int linkfile (const char *fromfile, const char *tofile)
469 int ret;
471 /* fprintf (stderr, "linkfile (%s, %s)\n", fromfile, tofile); */
472 if ( (ret = link (fromfile, tofile)) == -1 && errno == EEXIST )
473 if ( unlink (tofile) == 0 )
474 ret = link (fromfile, tofile);
476 return ret;
479 /*****************************************************************
480 ** copyfile (fromfile, tofile, dnskeyfile)
481 *****************************************************************/
482 int copyfile (const char *fromfile, const char *tofile, const char *dnskeyfile)
484 FILE *infp;
485 FILE *outfp;
486 int c;
488 /* fprintf (stderr, "copyfile (%s, %s)\n", fromfile, tofile); */
489 if ( (infp = fopen (fromfile, "r")) == NULL )
490 return -1;
491 if ( (outfp = fopen (tofile, "w")) == NULL )
493 fclose (infp);
494 return -2;
496 while ( (c = getc (infp)) != EOF )
497 putc (c, outfp);
499 fclose (infp);
500 if ( dnskeyfile && *dnskeyfile && (infp = fopen (dnskeyfile, "r")) != NULL )
502 while ( (c = getc (infp)) != EOF )
503 putc (c, outfp);
504 fclose (infp);
506 fclose (outfp);
508 return 0;
511 /*****************************************************************
512 ** copyzonefile (fromfile, tofile, dnskeyfile)
513 ** copy a already signed zonefile and replace all zone DNSKEY
514 ** resource records by one "$INCLUDE dnskey.db" line
515 *****************************************************************/
516 int copyzonefile (const char *fromfile, const char *tofile, const char *dnskeyfile)
518 FILE *infp;
519 FILE *outfp;
520 int len;
521 int dnskeys;
522 int multi_line_dnskey;
523 int bufoverflow;
524 char buf[1024];
525 char *p;
527 if ( fromfile == NULL )
528 infp = stdin;
529 else
530 if ( (infp = fopen (fromfile, "r")) == NULL )
531 return -1;
532 if ( tofile == NULL )
533 outfp = stdout;
534 else
535 if ( (outfp = fopen (tofile, "w")) == NULL )
537 if ( fromfile )
538 fclose (infp);
539 return -2;
542 multi_line_dnskey = 0;
543 dnskeys = 0;
544 bufoverflow = 0;
545 while ( fgets (buf, sizeof buf, infp) != NULL )
547 p = buf;
548 if ( !bufoverflow && !multi_line_dnskey && (*p == '@' || isspace (*p)) ) /* check if DNSKEY RR */
551 p++;
552 while ( isspace (*p) ) ;
554 /* skip TTL */
555 while ( isdigit (*p) )
556 p++;
558 while ( isspace (*p) )
559 p++;
561 /* skip Class */
562 if ( strncasecmp (p, "IN", 2) == 0 )
564 p += 2;
565 while ( isspace (*p) )
566 p++;
569 if ( strncasecmp (p, "DNSKEY", 6) == 0 ) /* bingo! */
571 dnskeys++;
572 p += 6;
573 while ( *p )
575 if ( *p == '(' )
576 multi_line_dnskey = 1;
577 if ( *p == ')' )
578 multi_line_dnskey = 0;
579 p++;
581 if ( dnskeys == 1 )
582 fprintf (outfp, "$INCLUDE %s\n", dnskeyfile);
584 else
585 fputs (buf, outfp);
587 else
589 if ( bufoverflow )
590 fprintf (stderr, "!! buffer overflow in copyzonefile() !!\n");
591 if ( !multi_line_dnskey )
592 fputs (buf, outfp);
593 else
595 while ( *p && *p != ')' )
596 p++;
597 if ( *p == ')' )
598 multi_line_dnskey = 0;
602 len = strlen (buf);
603 bufoverflow = buf[len-1] != '\n'; /* line too long ? */
606 if ( fromfile )
607 fclose (infp);
608 if ( tofile )
609 fclose (outfp);
611 return 0;
614 /*****************************************************************
615 ** cmpfile (file1, file2)
616 ** returns -1 on error, 1 if the files differ and 0 if they
617 ** are identical.
618 *****************************************************************/
619 int cmpfile (const char *file1, const char *file2)
621 FILE *fp1;
622 FILE *fp2;
623 int c1;
624 int c2;
626 /* fprintf (stderr, "cmpfile (%s, %s)\n", file1, file2); */
627 if ( (fp1 = fopen (file1, "r")) == NULL )
628 return -1;
629 if ( (fp2 = fopen (file2, "r")) == NULL )
631 fclose (fp1);
632 return -1;
635 do {
636 c1 = getc (fp1);
637 c2 = getc (fp2);
638 } while ( c1 != EOF && c2 != EOF && c1 == c2 );
640 fclose (fp1);
641 fclose (fp2);
643 if ( c1 == c2 )
644 return 0;
645 return 1;
648 /*****************************************************************
649 ** file_age (fname)
650 *****************************************************************/
651 int file_age (const char *fname)
653 time_t curr = time (NULL);
654 time_t mtime = file_mtime (fname);
656 return curr - mtime;
659 /*****************************************************************
660 ** file_mtime (fname)
661 *****************************************************************/
662 time_t file_mtime (const char *fname)
664 struct stat st;
666 if ( stat (fname, &st) < 0 )
667 return 0;
668 return st.st_mtime;
671 /*****************************************************************
672 ** is_exec_ok (prog)
673 ** Check if we are running as root or if the file owner of
674 ** "prog" do not match the current user or the file permissions
675 ** allows file modification for others then the owner.
676 ** The same condition will be checked for the group ownership.
677 ** return 1 if the execution of the command "prog" will not
678 ** open a big security whole, 0 otherwise
679 *****************************************************************/
680 int is_exec_ok (const char *prog)
682 uid_t curr_uid;
683 struct stat st;
685 if ( stat (prog, &st) < 0 )
686 return 0;
688 curr_uid = getuid ();
689 if ( curr_uid == 0 ) /* don't run the cmd if we are root */
690 return 0;
692 /* if the file owner and the current user matches and */
693 /* the file mode is not writable except for the owner, we are save */
694 if ( curr_uid == st.st_uid && (st.st_mode & (S_IWGRP | S_IWOTH)) == 0 )
695 return 1;
697 /* if the file group and the current group matches and */
698 /* the file mode is not writable except for the group, we are also save */
699 if ( getgid() != st.st_gid && (st.st_mode & (S_IWUSR | S_IWOTH)) == 0 )
700 return 1;
702 return 0;
705 /*****************************************************************
706 ** fatal (fmt, ...)
707 *****************************************************************/
708 void fatal (char *fmt, ...)
710 va_list ap;
712 va_start(ap, fmt);
713 if ( progname )
714 fprintf (stderr, "%s: ", progname);
715 vfprintf (stderr, fmt, ap);
716 va_end(ap);
717 exit (127);
720 /*****************************************************************
721 ** error (fmt, ...)
722 *****************************************************************/
723 void error (char *fmt, ...)
725 va_list ap;
727 va_start(ap, fmt);
728 vfprintf (stderr, fmt, ap);
729 va_end(ap);
732 /*****************************************************************
733 ** logmesg (fmt, ...)
734 *****************************************************************/
735 void logmesg (char *fmt, ...)
737 va_list ap;
739 #if defined (LOG_WITH_PROGNAME) && LOG_WITH_PROGNAME
740 fprintf (stdout, "%s: ", progname);
741 #endif
742 va_start(ap, fmt);
743 vfprintf (stdout, fmt, ap);
744 va_end(ap);
747 /*****************************************************************
748 ** verbmesg (verblvl, conf, fmt, ...)
749 *****************************************************************/
750 void verbmesg (int verblvl, const zconf_t *conf, char *fmt, ...)
752 char str[511+1];
753 va_list ap;
755 str[0] = '\0';
756 va_start(ap, fmt);
757 vsnprintf (str, sizeof (str), fmt, ap);
758 va_end(ap);
760 //fprintf (stderr, "verbmesg (%d stdout=%d filelog=%d str = :%s:\n", verblvl, conf->verbosity, conf->verboselog, str);
761 if ( verblvl <= conf->verbosity ) /* check if we have to print this to stdout */
762 logmesg (str);
764 str_chop (str, '\n');
765 if ( verblvl <= conf->verboselog ) /* check logging to syslog and/or file */
766 lg_mesg (LG_DEBUG, str);
770 /*****************************************************************
771 ** logflush ()
772 *****************************************************************/
773 void logflush ()
775 fflush (stdout);
778 /*****************************************************************
779 ** timestr2time (timestr)
780 ** timestr should look like "20071211223901" for 12 dec 2007 22:39:01
781 *****************************************************************/
782 time_t timestr2time (const char *timestr)
784 struct tm t;
785 time_t sec;
787 // fprintf (stderr, "timestr = \"%s\"\n", timestr);
788 if ( sscanf (timestr, "%4d%2d%2d%2d%2d%2d",
789 &t.tm_year, &t.tm_mon, &t.tm_mday,
790 &t.tm_hour, &t.tm_min, &t.tm_sec) != 6 )
791 return 0L;
792 t.tm_year -= 1900;
793 t.tm_mon -= 1;
794 t.tm_isdst = 0;
796 #if defined(HAVE_TIMEGM) && HAVE_TIMEGM
797 sec = timegm (&t);
798 #else
800 char tzstr[31+1];
801 char *tz;
803 tz = getenv("TZ");
804 snprintf (tzstr, sizeof (tzstr), "TZ=%s", "UTC");
805 putenv (tzstr);
806 tzset();
807 sec = mktime(&t);
808 if (tz)
809 snprintf (tzstr, sizeof (tzstr), "TZ=%s", tz);
810 else
811 snprintf (tzstr, sizeof (tzstr), "TZ=%s", "");
812 putenv (tzstr);
813 tzset();
815 #endif
817 return sec < 0L ? 0L : sec;
820 /*****************************************************************
821 ** time2str (sec, precison)
822 ** sec is seconds since 1.1.1970
823 ** precison is currently either 's' (for seconds) or 'm' (minutes)
824 *****************************************************************/
825 char *time2str (time_t sec, int precision)
827 struct tm *t;
828 static char timestr[31+1]; /* 27+1 should be enough */
829 #if defined(HAVE_STRFTIME) && HAVE_STRFTIME
830 char tformat[127+1];
832 timestr[0] = '\0';
833 if ( sec <= 0L )
834 return timestr;
835 t = localtime (&sec);
836 if ( precision == 's' )
837 strcpy (tformat, "%b %d %Y %T");
838 else
839 strcpy (tformat, "%b %d %Y %R");
840 # if PRINT_TIMEZONE
841 strcat (tformat, " %z");
842 # endif
843 strftime (timestr, sizeof (timestr), tformat, t);
845 #else /* no strftime available */
846 static char *mstr[] = {
847 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
848 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
851 timestr[0] = '\0';
852 if ( sec <= 0L )
853 return timestr;
854 t = localtime (&sec);
855 # if PRINT_TIMEZONE
857 int h, s;
859 s = abs (t->tm_gmtoff);
860 h = t->tm_gmtoff / 3600;
861 s = t->tm_gmtoff % 3600;
862 if ( precision == 's' )
863 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d:%02d %c%02d%02d",
864 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
865 t->tm_hour, t->tm_min, t->tm_sec,
866 t->tm_gmtoff < 0 ? '-': '+',
867 h, s);
868 else
869 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d %c%02d%02d",
870 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
871 t->tm_hour, t->tm_min,
872 t->tm_gmtoff < 0 ? '-': '+',
873 h, s);
875 # else
876 if ( precision == 's' )
877 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d:%02d",
878 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
879 t->tm_hour, t->tm_min, t->tm_sec);
880 else
881 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d",
882 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
883 t->tm_hour, t->tm_min);
884 # endif
885 #endif
887 return timestr;
890 /*****************************************************************
891 ** time2isostr (sec, precison)
892 ** sec is seconds since 1.1.1970
893 ** precison is currently either 's' (for seconds) or 'm' (minutes)
894 *****************************************************************/
895 char *time2isostr (time_t sec, int precision)
897 struct tm *t;
898 static char timestr[31+1]; /* 27+1 should be enough */
900 timestr[0] = '\0';
901 if ( sec <= 0L )
902 return timestr;
904 t = gmtime (&sec);
905 if ( precision == 's' )
906 snprintf (timestr, sizeof (timestr), "%4d%02d%02d%02d%02d%02d",
907 t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
908 t->tm_hour, t->tm_min, t->tm_sec);
909 else
910 snprintf (timestr, sizeof (timestr), "%4d%02d%02d%02d%02d",
911 t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
912 t->tm_hour, t->tm_min);
914 return timestr;
917 /*****************************************************************
918 ** age2str (sec)
919 ** !!Attention: This function is not reentrant
920 *****************************************************************/
921 char *age2str (time_t sec)
923 static char str[20+1]; /* "2y51w6d23h50m55s" == 16+1 chars */
924 int len;
925 int strsize = sizeof (str);
927 len = 0;
928 # if PRINT_AGE_WITH_YEAR
929 if ( sec / (YEARSEC) > 0 )
931 len += snprintf (str+len, strsize - len, "%1luy", sec / YEARSEC );
932 sec %= (YEARSEC);
934 else
935 len += snprintf (str+len, strsize - len, " ");
936 # endif
937 if ( sec / WEEKSEC > 0 )
939 len += snprintf (str+len, strsize - len, "%2luw", (ulong) sec / WEEKSEC );
940 sec %= WEEKSEC;
942 else
943 len += snprintf (str+len, strsize - len, " ");
944 if ( sec / DAYSEC > 0 )
946 len += snprintf (str+len, strsize - len, "%2lud", sec / (ulong)DAYSEC);
947 sec %= DAYSEC;
949 else
950 len += snprintf (str+len, strsize - len, " ");
951 if ( sec / HOURSEC > 0 )
953 len += snprintf (str+len, strsize - len, "%2luh", sec / (ulong)HOURSEC);
954 sec %= HOURSEC;
956 else
957 len += snprintf (str+len, strsize - len, " ");
958 if ( sec / MINSEC > 0 )
960 len += snprintf (str+len, strsize - len, "%2lum", sec / (ulong)MINSEC);
961 sec %= MINSEC;
963 else
964 len += snprintf (str+len, strsize - len, " ");
965 if ( sec > 0 )
966 snprintf (str+len, strsize - len, "%2lus", (ulong) sec);
967 else
968 len += snprintf (str+len, strsize - len, " ");
970 return str;
973 /*****************************************************************
974 ** start_timer ()
975 *****************************************************************/
976 time_t start_timer ()
978 return (time(NULL));
981 /*****************************************************************
982 ** stop_timer ()
983 *****************************************************************/
984 time_t stop_timer (time_t start)
986 time_t stop = time (NULL);
988 return stop - start;
992 /****************************************************************
994 ** int gensalt (saltstr, sizeofstalstr, bits)
996 ** generate a random hexstring of 'bits' salt and store it
997 ** in saltstr. return 1 on success, otherwise 0.
999 *****************************************************************/
1000 int gensalt (char *salt, size_t saltsize, int saltbits)
1002 static char hexstr[] = "0123456789ABCDEF";
1003 static int seed = 0;
1004 int saltlen = 0; /* current length of salt in hex nibbles */
1005 int i;
1006 int hex;
1008 if ( seed == 0 )
1009 srandom (seed = (unsigned int)time (NULL));
1011 saltlen = saltbits / 4;
1012 if ( saltlen+1 > saltsize )
1013 return 0;
1015 for ( i = 0; i < saltlen; i++ )
1017 hex = random () % 16;
1018 assert ( hex >= 0 && hex < 16 );
1019 salt[i] = hexstr[hex];
1021 salt[i] = '\0';
1023 return 1;
1027 #ifdef COPYZONE_TEST
1028 const char *progname;
1029 main (int argc, char *argv[])
1031 progname = *argv;
1033 if ( copyzonefile (argv[1], NULL) < 0 )
1034 error ("can't copy zone file %s\n", argv[1]);
1036 #endif
1038 #ifdef URL_TEST
1039 const char *progname;
1040 main (int argc, char *argv[])
1042 char *proto;
1043 char *host;
1044 char *port;
1045 char *para;
1046 char url[1024];
1048 progname = *argv;
1050 proto = host = port = para = NULL;
1052 if ( --argc <= 0 )
1054 fprintf (stderr, "usage: url_test <url>\n");
1055 fprintf (stderr, "e.g.: url_test http://www.hznet.de:80/zkt\n");
1056 exit (1);
1059 strcpy (url, argv[1]);
1060 parseurl (url, &proto, &host, &port, &para);
1062 if ( proto )
1063 printf ("proto: \"%s\"\n", proto);
1064 if ( host )
1065 printf ("host: \"%s\"\n", host);
1066 if ( port )
1067 printf ("port: \"%s\"\n", port);
1068 if ( para )
1069 printf ("para: \"%s\"\n", para);
1072 #endif