etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / contrib / zkt-1.1.3 / misc.c
bloba1c100a73c1769be92a0f99ad1343be421343a35
1 /* $NetBSD: misc.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
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", (int)(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 ** copy fromfile into tofile.
482 ** Add (optional) the content of dnskeyfile to tofile.
483 *****************************************************************/
484 int copyfile (const char *fromfile, const char *tofile, const char *dnskeyfile)
486 FILE *infp;
487 FILE *outfp;
488 int c;
490 /* fprintf (stderr, "copyfile (%s, %s)\n", fromfile, tofile); */
491 if ( (infp = fopen (fromfile, "r")) == NULL )
492 return -1;
493 if ( (outfp = fopen (tofile, "w")) == NULL )
495 fclose (infp);
496 return -2;
498 while ( (c = getc (infp)) != EOF )
499 putc (c, outfp);
501 fclose (infp);
502 if ( dnskeyfile && *dnskeyfile && (infp = fopen (dnskeyfile, "r")) != NULL )
504 while ( (c = getc (infp)) != EOF )
505 putc (c, outfp);
506 fclose (infp);
508 fclose (outfp);
510 return 0;
513 /*****************************************************************
514 ** copyzonefile (fromfile, tofile, dnskeyfile)
515 ** copy a already signed zonefile and replace all zone DNSKEY
516 ** resource records by one "$INCLUDE dnskey.db" line
517 *****************************************************************/
518 int copyzonefile (const char *fromfile, const char *tofile, const char *dnskeyfile)
520 FILE *infp;
521 FILE *outfp;
522 int len;
523 int dnskeys;
524 int multi_line_dnskey;
525 int bufoverflow;
526 char buf[1024];
527 char *p;
529 if ( fromfile == NULL )
530 infp = stdin;
531 else
532 if ( (infp = fopen (fromfile, "r")) == NULL )
533 return -1;
534 if ( tofile == NULL )
535 outfp = stdout;
536 else
537 if ( (outfp = fopen (tofile, "w")) == NULL )
539 if ( fromfile )
540 fclose (infp);
541 return -2;
544 multi_line_dnskey = 0;
545 dnskeys = 0;
546 bufoverflow = 0;
547 while ( fgets (buf, sizeof buf, infp) != NULL )
549 p = buf;
550 if ( !bufoverflow && !multi_line_dnskey && (*p == '@' || isspace (*p)) ) /* check if DNSKEY RR */
553 p++;
554 while ( isspace (*p) ) ;
556 /* skip TTL */
557 while ( isdigit (*p) )
558 p++;
560 while ( isspace (*p) )
561 p++;
563 /* skip Class */
564 if ( strncasecmp (p, "IN", 2) == 0 )
566 p += 2;
567 while ( isspace (*p) )
568 p++;
571 if ( strncasecmp (p, "DNSKEY", 6) == 0 ) /* bingo! */
573 dnskeys++;
574 p += 6;
575 while ( *p )
577 if ( *p == '(' )
578 multi_line_dnskey = 1;
579 if ( *p == ')' )
580 multi_line_dnskey = 0;
581 p++;
583 if ( dnskeys == 1 )
584 fprintf (outfp, "$INCLUDE %s\n", dnskeyfile);
586 else
587 fputs (buf, outfp);
589 else
591 if ( bufoverflow )
592 fprintf (stderr, "!! buffer overflow in copyzonefile() !!\n");
593 if ( !multi_line_dnskey )
594 fputs (buf, outfp);
595 else
597 while ( *p && *p != ')' )
598 p++;
599 if ( *p == ')' )
600 multi_line_dnskey = 0;
604 len = strlen (buf);
605 bufoverflow = buf[len-1] != '\n'; /* line too long ? */
608 if ( fromfile )
609 fclose (infp);
610 if ( tofile )
611 fclose (outfp);
613 return 0;
616 /*****************************************************************
617 ** cmpfile (file1, file2)
618 ** returns -1 on error, 1 if the files differ and 0 if they
619 ** are identical.
620 *****************************************************************/
621 int cmpfile (const char *file1, const char *file2)
623 FILE *fp1;
624 FILE *fp2;
625 int c1;
626 int c2;
628 /* fprintf (stderr, "cmpfile (%s, %s)\n", file1, file2); */
629 if ( (fp1 = fopen (file1, "r")) == NULL )
630 return -1;
631 if ( (fp2 = fopen (file2, "r")) == NULL )
633 fclose (fp1);
634 return -1;
637 do {
638 c1 = getc (fp1);
639 c2 = getc (fp2);
640 } while ( c1 != EOF && c2 != EOF && c1 == c2 );
642 fclose (fp1);
643 fclose (fp2);
645 if ( c1 == c2 )
646 return 0;
647 return 1;
650 /*****************************************************************
651 ** file_age (fname)
652 *****************************************************************/
653 int file_age (const char *fname)
655 time_t curr = time (NULL);
656 time_t mtime = file_mtime (fname);
658 return curr - mtime;
661 /*****************************************************************
662 ** file_mtime (fname)
663 *****************************************************************/
664 time_t file_mtime (const char *fname)
666 struct stat st;
668 if ( stat (fname, &st) < 0 )
669 return 0;
670 return st.st_mtime;
673 /*****************************************************************
674 ** is_exec_ok (prog)
675 ** Check if we are running as root or if the file owner of
676 ** "prog" do not match the current user or the file permissions
677 ** allows file modification for others then the owner.
678 ** The same condition will be checked for the group ownership.
679 ** return 1 if the execution of the command "prog" will not
680 ** open a big security whole, 0 otherwise
681 *****************************************************************/
682 int is_exec_ok (const char *prog)
684 uid_t curr_uid;
685 struct stat st;
687 if ( stat (prog, &st) < 0 )
688 return 0;
690 curr_uid = getuid ();
691 if ( curr_uid == 0 ) /* don't run the cmd if we are root */
692 return 0;
694 /* if the file owner and the current user matches and */
695 /* the file mode is not writable except for the owner, we are save */
696 if ( curr_uid == st.st_uid && (st.st_mode & (S_IWGRP | S_IWOTH)) == 0 )
697 return 1;
699 /* if the file group and the current group matches and */
700 /* the file mode is not writable except for the group, we are also save */
701 if ( getgid() != st.st_gid && (st.st_mode & (S_IWUSR | S_IWOTH)) == 0 )
702 return 1;
704 return 0;
707 /*****************************************************************
708 ** fatal (fmt, ...)
709 *****************************************************************/
710 void fatal (char *fmt, ...)
712 va_list ap;
714 va_start(ap, fmt);
715 if ( progname )
716 fprintf (stderr, "%s: ", progname);
717 vfprintf (stderr, fmt, ap);
718 va_end(ap);
719 exit (127);
722 /*****************************************************************
723 ** error (fmt, ...)
724 *****************************************************************/
725 void error (char *fmt, ...)
727 va_list ap;
729 va_start(ap, fmt);
730 vfprintf (stderr, fmt, ap);
731 va_end(ap);
734 /*****************************************************************
735 ** logmesg (fmt, ...)
736 *****************************************************************/
737 void logmesg (char *fmt, ...)
739 va_list ap;
741 #if defined (LOG_WITH_PROGNAME) && LOG_WITH_PROGNAME
742 fprintf (stdout, "%s: ", progname);
743 #endif
744 va_start(ap, fmt);
745 vfprintf (stdout, fmt, ap);
746 va_end(ap);
749 /*****************************************************************
750 ** verbmesg (verblvl, conf, fmt, ...)
751 *****************************************************************/
752 void verbmesg (int verblvl, const zconf_t *conf, char *fmt, ...)
754 char str[511+1];
755 va_list ap;
757 str[0] = '\0';
758 va_start(ap, fmt);
759 vsnprintf (str, sizeof (str), fmt, ap);
760 va_end(ap);
762 //fprintf (stderr, "verbmesg (%d stdout=%d filelog=%d str = :%s:\n", verblvl, conf->verbosity, conf->verboselog, str);
763 if ( verblvl <= conf->verbosity ) /* check if we have to print this to stdout */
764 logmesg (str);
766 str_chop (str, '\n');
767 if ( verblvl <= conf->verboselog ) /* check logging to syslog and/or file */
768 lg_mesg (LG_DEBUG, str);
772 /*****************************************************************
773 ** logflush ()
774 *****************************************************************/
775 void logflush ()
777 fflush (stdout);
780 /*****************************************************************
781 ** timestr2time (timestr)
782 ** timestr should look like "20071211223901" for 12 dec 2007 22:39:01
783 *****************************************************************/
784 time_t timestr2time (const char *timestr)
786 struct tm t;
787 time_t sec;
789 // fprintf (stderr, "timestr = \"%s\"\n", timestr);
790 if ( sscanf (timestr, "%4d%2d%2d%2d%2d%2d",
791 &t.tm_year, &t.tm_mon, &t.tm_mday,
792 &t.tm_hour, &t.tm_min, &t.tm_sec) != 6 )
793 return 0L;
794 t.tm_year -= 1900;
795 t.tm_mon -= 1;
796 t.tm_isdst = 0;
798 #if defined(HAVE_TIMEGM) && HAVE_TIMEGM
799 sec = timegm (&t);
800 #else
802 char tzstr[31+1];
803 char *tz;
805 tz = getenv("TZ");
806 snprintf (tzstr, sizeof (tzstr), "TZ=%s", "UTC");
807 putenv (tzstr);
808 tzset();
809 sec = mktime(&t);
810 if (tz)
811 snprintf (tzstr, sizeof (tzstr), "TZ=%s", tz);
812 else
813 snprintf (tzstr, sizeof (tzstr), "TZ=%s", "");
814 putenv (tzstr);
815 tzset();
817 #endif
819 return sec < 0L ? 0L : sec;
822 /*****************************************************************
823 ** time2str (sec, precison)
824 ** sec is seconds since 1.1.1970
825 ** precison is currently either 's' (for seconds) or 'm' (minutes)
826 *****************************************************************/
827 char *time2str (time_t sec, int precision)
829 struct tm *t;
830 static char timestr[31+1]; /* 27+1 should be enough */
831 #if defined(HAVE_STRFTIME) && HAVE_STRFTIME
832 char tformat[127+1];
834 timestr[0] = '\0';
835 if ( sec <= 0L )
836 return timestr;
837 t = localtime (&sec);
838 if ( precision == 's' )
839 strcpy (tformat, "%b %d %Y %T");
840 else
841 strcpy (tformat, "%b %d %Y %R");
842 # if PRINT_TIMEZONE
843 strcat (tformat, " %z");
844 # endif
845 strftime (timestr, sizeof (timestr), tformat, t);
847 #else /* no strftime available */
848 static char *mstr[] = {
849 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
850 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
853 timestr[0] = '\0';
854 if ( sec <= 0L )
855 return timestr;
856 t = localtime (&sec);
857 # if PRINT_TIMEZONE
859 int h, s;
861 s = abs (t->tm_gmtoff);
862 h = t->tm_gmtoff / 3600;
863 s = t->tm_gmtoff % 3600;
864 if ( precision == 's' )
865 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d:%02d %c%02d%02d",
866 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
867 t->tm_hour, t->tm_min, t->tm_sec,
868 t->tm_gmtoff < 0 ? '-': '+',
869 h, s);
870 else
871 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d %c%02d%02d",
872 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
873 t->tm_hour, t->tm_min,
874 t->tm_gmtoff < 0 ? '-': '+',
875 h, s);
877 # else
878 if ( precision == 's' )
879 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d:%02d",
880 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
881 t->tm_hour, t->tm_min, t->tm_sec);
882 else
883 snprintf (timestr, sizeof (timestr), "%s %2d %4d %02d:%02d",
884 mstr[t->tm_mon], t->tm_mday, t->tm_year + 1900,
885 t->tm_hour, t->tm_min);
886 # endif
887 #endif
889 return timestr;
892 /*****************************************************************
893 ** time2isostr (sec, precison)
894 ** sec is seconds since 1.1.1970
895 ** precison is currently either 's' (for seconds) or 'm' (minutes)
896 *****************************************************************/
897 char *time2isostr (time_t sec, int precision)
899 struct tm *t;
900 static char timestr[31+1]; /* 27+1 should be enough */
902 timestr[0] = '\0';
903 if ( sec <= 0L )
904 return timestr;
906 t = gmtime (&sec);
907 if ( precision == 's' )
908 snprintf (timestr, sizeof (timestr), "%4d%02d%02d%02d%02d%02d",
909 t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
910 t->tm_hour, t->tm_min, t->tm_sec);
911 else
912 snprintf (timestr, sizeof (timestr), "%4d%02d%02d%02d%02d",
913 t->tm_year + 1900, t->tm_mon+1, t->tm_mday,
914 t->tm_hour, t->tm_min);
916 return timestr;
919 /*****************************************************************
920 ** age2str (sec)
921 ** !!Attention: This function is not reentrant
922 *****************************************************************/
923 char *age2str (time_t sec)
925 static char str[20+1]; /* "2y51w6d23h50m55s" == 16+1 chars */
926 int len;
927 int strsize = sizeof (str);
929 len = 0;
930 # if PRINT_AGE_WITH_YEAR
931 if ( sec / (YEARSEC) > 0 )
933 len += snprintf (str+len, strsize - len, "%1luy", sec / YEARSEC );
934 sec %= (YEARSEC);
936 else
937 len += snprintf (str+len, strsize - len, " ");
938 # endif
939 if ( sec / WEEKSEC > 0 )
941 len += snprintf (str+len, strsize - len, "%2luw", (ulong) sec / WEEKSEC );
942 sec %= WEEKSEC;
944 else
945 len += snprintf (str+len, strsize - len, " ");
946 if ( sec / DAYSEC > 0 )
948 len += snprintf (str+len, strsize - len, "%2lud", sec / (ulong)DAYSEC);
949 sec %= DAYSEC;
951 else
952 len += snprintf (str+len, strsize - len, " ");
953 if ( sec / HOURSEC > 0 )
955 len += snprintf (str+len, strsize - len, "%2luh", sec / (ulong)HOURSEC);
956 sec %= HOURSEC;
958 else
959 len += snprintf (str+len, strsize - len, " ");
960 if ( sec / MINSEC > 0 )
962 len += snprintf (str+len, strsize - len, "%2lum", sec / (ulong)MINSEC);
963 sec %= MINSEC;
965 else
966 len += snprintf (str+len, strsize - len, " ");
967 if ( sec > 0 )
968 snprintf (str+len, strsize - len, "%2lus", (ulong) sec);
969 else
970 len += snprintf (str+len, strsize - len, " ");
972 return str;
975 /*****************************************************************
976 ** start_timer ()
977 *****************************************************************/
978 time_t start_timer ()
980 return (time(NULL));
983 /*****************************************************************
984 ** stop_timer ()
985 *****************************************************************/
986 time_t stop_timer (time_t start)
988 time_t stop = time (NULL);
990 return stop - start;
994 /****************************************************************
996 ** int gensalt (saltstr, sizeofsaltstr, bits)
998 ** generate a random hexstring of 'bits' salt and store it
999 ** in saltstr. return 1 on success, otherwise 0.
1001 *****************************************************************/
1002 int gensalt (char *salt, size_t saltsize, int saltbits, unsigned int seed)
1004 static char hexstr[] = "0123456789ABCDEF";
1005 int saltlen = 0; /* current length of salt in hex nibbles */
1006 int i;
1007 int hex;
1009 if ( seed == 0 )
1010 srandom (seed = (unsigned int)time (NULL));
1012 saltlen = saltbits / 4;
1013 if ( saltlen+1 > saltsize )
1014 return 0;
1016 for ( i = 0; i < saltlen; i++ )
1018 hex = random () % 16;
1019 assert ( hex >= 0 && hex < 16 );
1020 salt[i] = hexstr[hex];
1022 salt[i] = '\0';
1024 return 1;
1028 #ifdef COPYZONE_TEST
1029 const char *progname;
1030 main (int argc, char *argv[])
1032 progname = *argv;
1034 if ( copyzonefile (argv[1], NULL) < 0 )
1035 error ("can't copy zone file %s\n", argv[1]);
1037 #endif
1039 #ifdef URL_TEST
1040 const char *progname;
1041 main (int argc, char *argv[])
1043 char *proto;
1044 char *host;
1045 char *port;
1046 char *para;
1047 char url[1024];
1049 progname = *argv;
1051 proto = host = port = para = NULL;
1053 if ( --argc <= 0 )
1055 fprintf (stderr, "usage: url_test <url>\n");
1056 fprintf (stderr, "e.g.: url_test http://www.hznet.de:80/zkt\n");
1057 exit (1);
1060 strcpy (url, argv[1]);
1061 parseurl (url, &proto, &host, &port, &para);
1063 if ( proto )
1064 printf ("proto: \"%s\"\n", proto);
1065 if ( host )
1066 printf ("host: \"%s\"\n", host);
1067 if ( port )
1068 printf ("port: \"%s\"\n", port);
1069 if ( para )
1070 printf ("para: \"%s\"\n", para);
1073 #endif