Home | History | Annotate | Download | only in nameser
      1 /*	$NetBSD: ns_ttl.c,v 1.8 2012/03/13 21:13:39 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
      5  * Copyright (c) 1996,1999 by Internet Software Consortium.
      6  *
      7  * Permission to use, copy, modify, and distribute this software for any
      8  * purpose with or without fee is hereby granted, provided that the above
      9  * copyright notice and this permission notice appear in all copies.
     10  *
     11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  */
     19 
     20 #include <sys/cdefs.h>
     21 #ifndef lint
     22 #ifdef notdef
     23 static const char rcsid[] = "Id: ns_ttl.c,v 1.4 2005/07/28 06:51:49 marka Exp";
     24 #else
     25 __RCSID("$NetBSD: ns_ttl.c,v 1.8 2012/03/13 21:13:39 christos Exp $");
     26 #endif
     27 #endif
     28 
     29 /* Import. */
     30 
     31 #include <arpa/nameser.h>
     32 
     33 #include <assert.h>
     34 #include <ctype.h>
     35 #include <errno.h>
     36 #include <stdio.h>
     37 #include <string.h>
     38 
     39 #ifdef SPRINTF_CHAR
     40 # define SPRINTF(x) strlen(sprintf/**/x)
     41 #else
     42 # define SPRINTF(x) ((size_t)sprintf x)
     43 #endif
     44 
     45 /* Forward. */
     46 
     47 static int	fmt1(int t, char s, char **buf, size_t *buflen);
     48 
     49 /* Macros. */
     50 
     51 #define T(x) do { if ((x) < 0) return (-1); } while(0)
     52 
     53 /* Public. */
     54 
     55 int
     56 ns_format_ttl(u_long src, char *dst, size_t dstlen) {
     57 	char *odst = dst;
     58 	int secs, mins, hours, days, weeks, x;
     59 	char *p;
     60 
     61 	secs = (int)(src % 60);   src /= 60;
     62 	mins = (int)(src % 60);   src /= 60;
     63 	hours = (int)(src % 24);  src /= 24;
     64 	days = (int)(src % 7);    src /= 7;
     65 	weeks = (int)src;       src = 0;
     66 
     67 	x = 0;
     68 	if (weeks) {
     69 		T(fmt1(weeks, 'W', &dst, &dstlen));
     70 		x++;
     71 	}
     72 	if (days) {
     73 		T(fmt1(days, 'D', &dst, &dstlen));
     74 		x++;
     75 	}
     76 	if (hours) {
     77 		T(fmt1(hours, 'H', &dst, &dstlen));
     78 		x++;
     79 	}
     80 	if (mins) {
     81 		T(fmt1(mins, 'M', &dst, &dstlen));
     82 		x++;
     83 	}
     84 	if (secs || !(weeks || days || hours || mins)) {
     85 		T(fmt1(secs, 'S', &dst, &dstlen));
     86 		x++;
     87 	}
     88 
     89 	if (x > 1) {
     90 		int ch;
     91 
     92 		for (p = odst; (ch = *p) != '\0'; p++)
     93 			if (isascii(ch) && isupper(ch))
     94 				*p = tolower(ch);
     95 	}
     96 
     97 	_DIAGASSERT(__type_fit(int, dst - odst));
     98 	return (int)(dst - odst);
     99 }
    100 
    101 #ifndef _LIBC
    102 int
    103 ns_parse_ttl(const char *src, u_long *dst) {
    104 	u_long ttl, tmp;
    105 	int ch, digits, dirty;
    106 
    107 	ttl = 0;
    108 	tmp = 0;
    109 	digits = 0;
    110 	dirty = 0;
    111 	while ((ch = *src++) != '\0') {
    112 		if (!isascii(ch) || !isprint(ch))
    113 			goto einval;
    114 		if (isdigit(ch)) {
    115 			tmp *= 10;
    116 			tmp += (ch - '0');
    117 			digits++;
    118 			continue;
    119 		}
    120 		if (digits == 0)
    121 			goto einval;
    122 		if (islower(ch))
    123 			ch = toupper(ch);
    124 		switch (ch) {
    125 		case 'W':  tmp *= 7;	/*FALLTHROUGH*/
    126 		case 'D':  tmp *= 24;	/*FALLTHROUGH*/
    127 		case 'H':  tmp *= 60;	/*FALLTHROUGH*/
    128 		case 'M':  tmp *= 60;	/*FALLTHROUGH*/
    129 		case 'S':  break;
    130 		default:   goto einval;
    131 		}
    132 		ttl += tmp;
    133 		tmp = 0;
    134 		digits = 0;
    135 		dirty = 1;
    136 	}
    137 	if (digits > 0) {
    138 		if (dirty)
    139 			goto einval;
    140 		else
    141 			ttl += tmp;
    142 	} else if (!dirty)
    143 		goto einval;
    144 	*dst = ttl;
    145 	return (0);
    146 
    147  einval:
    148 	errno = EINVAL;
    149 	return (-1);
    150 }
    151 #endif
    152 
    153 /* Private. */
    154 
    155 static int
    156 fmt1(int t, char s, char **buf, size_t *buflen) {
    157 	char tmp[50];
    158 	size_t len;
    159 
    160 	len = SPRINTF((tmp, "%d%c", t, s));
    161 	if (len + 1 > *buflen)
    162 		return (-1);
    163 	strcpy(*buf, tmp);
    164 	*buf += len;
    165 	*buflen -= len;
    166 	return (0);
    167 }
    168