xref: /freebsd/contrib/sendmail/src/convtime.c (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1 /*
2  * Copyright (c) 1998-2001 Proofpoint, Inc. and its suppliers.
3  *	All rights reserved.
4  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5  * Copyright (c) 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * By using this file, you agree to the terms and conditions set
9  * forth in the LICENSE file which can be found at the top level of
10  * the sendmail distribution.
11  *
12  */
13 
14 #include <sendmail.h>
15 
16 SM_RCSID("@(#)$Id: convtime.c,v 8.40 2013-11-22 20:51:55 ca Exp $")
17 #include <sm/sendmail.h>
18 
19 /*
20 **  CONVTIME -- convert time
21 **
22 **	Takes a time as an ascii string with a trailing character
23 **	giving units:
24 **	  s -- seconds
25 **	  m -- minutes
26 **	  h -- hours
27 **	  d -- days (default)
28 **	  w -- weeks
29 **	For example, "3d12h" is three and a half days.
30 **
31 **	Parameters:
32 **		p -- pointer to ascii time.
33 **		units -- default units if none specified.
34 **
35 **	Returns:
36 **		time in seconds.
37 **
38 **	Side Effects:
39 **		none.
40 */
41 
42 time_t
43 convtime(p, units)
44 	char *p;
45 	int units;
46 {
47 	register time_t t, r;
48 	register char c;
49 	bool pos = true;
50 
51 	r = 0;
52 	if (SM_STRCASEEQ(p, "now"))
53 		return NOW;
54 	if (*p == '-')
55 	{
56 		pos = false;
57 		++p;
58 	}
59 	while (*p != '\0')
60 	{
61 		t = 0;
62 		while ((c = *p++) != '\0' && isascii(c) && isdigit(c))
63 			t = t * 10 + (c - '0');
64 		if (c == '\0')
65 		{
66 			c = units;
67 			p--;
68 		}
69 		else if (strchr("wdhms", c) == NULL)
70 		{
71 			usrerr("Invalid time unit `%c'", c);
72 			c = units;
73 		}
74 		switch (c)
75 		{
76 		  case 'w':		/* weeks */
77 			t *= 7;
78 			/* FALLTHROUGH */
79 
80 		  case 'd':		/* days */
81 			/* FALLTHROUGH */
82 		  default:
83 			t *= 24;
84 			/* FALLTHROUGH */
85 
86 		  case 'h':		/* hours */
87 			t *= 60;
88 			/* FALLTHROUGH */
89 
90 		  case 'm':		/* minutes */
91 			t *= 60;
92 			/* FALLTHROUGH */
93 
94 		  case 's':		/* seconds */
95 			break;
96 		}
97 		r += t;
98 	}
99 
100 	return pos ? r : -r;
101 }
102 /*
103 **  PINTVL -- produce printable version of a time interval
104 **
105 **	Parameters:
106 **		intvl -- the interval to be converted
107 **		brief -- if true, print this in an extremely compact form
108 **			(basically used for logging).
109 **
110 **	Returns:
111 **		A pointer to a string version of intvl suitable for
112 **			printing or framing.
113 **
114 **	Side Effects:
115 **		none.
116 **
117 **	Warning:
118 **		The string returned is in a static buffer.
119 */
120 
121 #define PLURAL(n)	((n) == 1 ? "" : "s")
122 
123 char *
124 pintvl(intvl, brief)
125 	time_t intvl;
126 	bool brief;
127 {
128 	static char buf[256];
129 	register char *p;
130 	int wk, dy, hr, mi, se;
131 
132 	if (intvl == 0 && !brief)
133 		return "zero seconds";
134 	if (intvl == NOW)
135 		return "too long";
136 
137 	/* decode the interval into weeks, days, hours, minutes, seconds */
138 	se = intvl % 60;
139 	intvl /= 60;
140 	mi = intvl % 60;
141 	intvl /= 60;
142 	hr = intvl % 24;
143 	intvl /= 24;
144 	if (brief)
145 	{
146 		dy = intvl;
147 		wk = 0;
148 	}
149 	else
150 	{
151 		dy = intvl % 7;
152 		intvl /= 7;
153 		wk = intvl;
154 	}
155 
156 	/* now turn it into a sexy form */
157 	p = buf;
158 	if (brief)
159 	{
160 		if (dy > 0)
161 		{
162 			(void) sm_snprintf(p, SPACELEFT(buf, p), "%d+", dy);
163 			p += strlen(p);
164 		}
165 		(void) sm_snprintf(p, SPACELEFT(buf, p), "%02d:%02d:%02d",
166 				   hr, mi, se);
167 		return buf;
168 	}
169 
170 	/* use the verbose form */
171 	if (wk > 0)
172 	{
173 		(void) sm_snprintf(p, SPACELEFT(buf, p), ", %d week%s", wk,
174 				   PLURAL(wk));
175 		p += strlen(p);
176 	}
177 	if (dy > 0)
178 	{
179 		(void) sm_snprintf(p, SPACELEFT(buf, p), ", %d day%s", dy,
180 				   PLURAL(dy));
181 		p += strlen(p);
182 	}
183 	if (hr > 0)
184 	{
185 		(void) sm_snprintf(p, SPACELEFT(buf, p), ", %d hour%s", hr,
186 				   PLURAL(hr));
187 		p += strlen(p);
188 	}
189 	if (mi > 0)
190 	{
191 		(void) sm_snprintf(p, SPACELEFT(buf, p), ", %d minute%s", mi,
192 				   PLURAL(mi));
193 		p += strlen(p);
194 	}
195 	if (se > 0)
196 	{
197 		(void) sm_snprintf(p, SPACELEFT(buf, p), ", %d second%s", se,
198 				   PLURAL(se));
199 		p += strlen(p);
200 	}
201 
202 	return (buf + 2);
203 }
204