Home | History | Annotate | Line # | Download | only in nameser
      1 /*	$NetBSD: ns_ttl.c,v 1.9 2026/04/08 14:12:06 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.9 2026/04/08 14:12:06 christos Exp $");
     26 #endif
     27 #endif
     28 
     29 /* Import. */
     30 
     31 #include "port_before.h"
     32 
     33 #include <arpa/nameser.h>
     34 
     35 #include <assert.h>
     36 #include <ctype.h>
     37 #include <errno.h>
     38 #include <stdio.h>
     39 #include <string.h>
     40 
     41 #include "port_after.h"
     42 
     43 /* Forward. */
     44 
     45 static int	fmt1(int t, char s, char **buf, size_t *buflen);
     46 
     47 /* Macros. */
     48 
     49 #define T(x) if ((x) < 0) return (-1)
     50 
     51 /* Public. */
     52 
     53 int
     54 ns_format_ttl(u_long src, char *dst, size_t dstlen) {
     55 	char *odst = dst;
     56 	int secs, mins, hours, days, weeks, x;
     57 	char *p;
     58 
     59 	secs = (int)(src % 60);   src /= 60;
     60 	mins = (int)(src % 60);   src /= 60;
     61 	hours = (int)(src % 24);  src /= 24;
     62 	days = (int)(src % 7);    src /= 7;
     63 	weeks = (int)src;       src = 0;
     64 
     65 	x = 0;
     66 	if (weeks) {
     67 		T(fmt1(weeks, 'W', &dst, &dstlen));
     68 		x++;
     69 	}
     70 	if (days) {
     71 		T(fmt1(days, 'D', &dst, &dstlen));
     72 		x++;
     73 	}
     74 	if (hours) {
     75 		T(fmt1(hours, 'H', &dst, &dstlen));
     76 		x++;
     77 	}
     78 	if (mins) {
     79 		T(fmt1(mins, 'M', &dst, &dstlen));
     80 		x++;
     81 	}
     82 	if (secs || !(weeks || days || hours || mins)) {
     83 		T(fmt1(secs, 'S', &dst, &dstlen));
     84 		x++;
     85 	}
     86 
     87 	if (x > 1) {
     88 		int ch;
     89 
     90 		for (p = odst; (ch = *p) != '\0'; p++)
     91 			if (isascii(ch) && isupper(ch))
     92 				*p = tolower(ch);
     93 	}
     94 
     95 	_DIAGASSERT(__type_fit(int, dst - odst));
     96 	return (int)(dst - odst);
     97 }
     98 
     99 #ifndef _LIBC
    100 int
    101 ns_parse_ttl(const char *src, u_long *dst) {
    102 	u_long ttl, tmp;
    103 	int ch, digits, dirty;
    104 
    105 	ttl = 0;
    106 	tmp = 0;
    107 	digits = 0;
    108 	dirty = 0;
    109 	while ((ch = *src++) != '\0') {
    110 		if (!isascii(ch) || !isprint(ch))
    111 			goto einval;
    112 		if (isdigit(ch)) {
    113 			tmp *= 10;
    114 			tmp += (ch - '0');
    115 			digits++;
    116 			continue;
    117 		}
    118 		if (digits == 0)
    119 			goto einval;
    120 		if (islower(ch))
    121 			ch = toupper(ch);
    122 		switch (ch) {
    123 		case 'W':  tmp *= 7;	/*FALLTHROUGH*/
    124 		case 'D':  tmp *= 24;	/*FALLTHROUGH*/
    125 		case 'H':  tmp *= 60;	/*FALLTHROUGH*/
    126 		case 'M':  tmp *= 60;	/*FALLTHROUGH*/
    127 		case 'S':  break;
    128 		default:   goto einval;
    129 		}
    130 		ttl += tmp;
    131 		tmp = 0;
    132 		digits = 0;
    133 		dirty = 1;
    134 	}
    135 	if (digits > 0) {
    136 		if (dirty)
    137 			goto einval;
    138 		else
    139 			ttl += tmp;
    140 	} else if (!dirty)
    141 		goto einval;
    142 	*dst = ttl;
    143 	return (0);
    144 
    145  einval:
    146 	errno = EINVAL;
    147 	return (-1);
    148 }
    149 #endif
    150 
    151 /* Private. */
    152 
    153 static int
    154 fmt1(int t, char s, char **buf, size_t *buflen) {
    155 	char tmp[50];
    156 	int len;
    157 
    158 	len = snprintf(tmp, sizeof(tmp), "%d%c", t, s);
    159 	if (len == -1 || (size_t)(len + 1) > *buflen)
    160 		return (-1);
    161 	strcpy(*buf, tmp);
    162 	*buf += len;
    163 	*buflen -= len;
    164 	return (0);
    165 }
    166 
    167 /*! \file */
    168