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