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