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 *
pintvl(intvl,brief)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