1 /*
2 ** Copyright (C) 2006-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8 
9 /*
10 **  sku-compat.c
11 **
12 **    Function
13 **
14 */
15 
16 
17 #include <silk/silk.h>
18 
19 RCSIDENT("$SiLK: sku-compat.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
20 
21 #include <silk/utils.h>
22 
23 
24 /* Compute quotient and remainder in one structure like div(), but
25  * with intmax_t's instead of int's. */
26 sk_imaxdiv_t
sk_imaxdiv(sk_intmax_t numer,sk_intmax_t denom)27 sk_imaxdiv(
28     sk_intmax_t         numer,
29     sk_intmax_t         denom)
30 {
31     sk_imaxdiv_t res;
32     res.quot = numer / denom;
33     res.rem = numer % denom;
34     return res;
35 }
36 
37 
38 /* Copy data from 'src' to 'dst' stopping at value 'c' or when 'len'
39  * octets have been copied.  If 'c' was not found, NULL is returned;
40  * else return value points to character after 'c' in 'dst'. */
41 void *
sk_memccpy(void * dst,const void * src,int c,size_t len)42 sk_memccpy(
43     void               *dst,
44     const void         *src,
45     int                 c,
46     size_t              len)
47 {
48     uint8_t *c_dst = (uint8_t*)dst;
49     const uint8_t *c_src = (const uint8_t*)src;
50 
51     for ( ; len > 0; --len) {
52         *c_dst = *c_src;
53         ++c_dst;
54         if (*c_src == c) {
55             return c_dst;
56         }
57         ++c_src;
58     }
59     return NULL;
60 }
61 
62 
63 /* Set environment variable 'name' to 'value', unless 'name' already
64  * exists in the environment and 'overwrite' is 0. */
65 int
sk_setenv(const char * name,const char * value,int overwrite)66 sk_setenv(
67     const char         *name,
68     const char         *value,
69     int                 overwrite)
70 {
71     /* This function allocates new memory on every call.  This will be
72      * reported as a memory leak in valgrind, but that is hard to
73      * avoid.  We could reduce memory usage by overwriting the current
74      * value for 'name' when 'name' exists in the environment and
75      * strlen(value) is not greater than strlen(getenv(name)). */
76 
77     char *buf;
78 
79     if (strchr(name, '=')) {
80         errno = EINVAL;
81         return -1;
82     }
83 
84     if (overwrite || !getenv(name)) {
85         buf = (char*)malloc(2 + strlen(name) + strlen(value));
86         if (NULL == buf) {
87             return -1;
88         }
89         strcpy(buf, name);
90         strcat(buf, "=");
91         strcat(buf, value);
92         return putenv(buf);
93     }
94 
95     return 0;
96 }
97 
98 
99 /* Return next 'delim'-delimited token from *stringp; move *stringp to
100  * start of next token. */
101 char *
sk_strsep(char ** stringp,const char * delim)102 sk_strsep(
103     char              **stringp,
104     const char         *delim)
105 {
106     char *cp = *stringp;
107     size_t sz;
108 
109     if (NULL == cp) {
110         return NULL;
111     }
112 
113     sz = strcspn(cp, delim);
114     if (cp[sz] == '\0') {
115         /* reached end of string */
116         *stringp = NULL;
117     } else {
118         cp[sz] = '\0';
119         *stringp += (sz + 1);
120     }
121 
122     return cp;
123 }
124 
125 
126 /* Inverse of gmtime(); convert a struct tm to time_t. */
127 time_t
sk_timegm(struct tm * tm)128 sk_timegm(
129     struct tm          *tm)
130 {
131     time_t t_offset, t_2offset;
132     struct tm tm_offset;
133 
134     /* compute time_t with the timezone offset */
135     t_offset = mktime(tm);
136     if (t_offset == -1) {
137         /* see if adjusting the hour allows mktime() to work */
138         tm->tm_hour--;
139         t_offset = mktime(tm);
140         if (t_offset == -1) {
141             return -1;
142         }
143         /* adjusting hour worked; add back that time */
144         t_offset += 3600;
145     }
146 
147     /* compute a second value with another timezone offset */
148     gmtime_r(&t_offset, &tm_offset);
149     tm_offset.tm_isdst = 0;
150     t_2offset = mktime(&tm_offset);
151     if (t_2offset == -1) {
152         tm_offset.tm_hour--;
153         t_2offset = mktime(&tm_offset);
154         if (t_2offset == -1) {
155             return -1;
156         }
157         t_2offset += 3600;
158     }
159 
160     /* difference in the two time_t's is one TZ offset */
161     return (t_offset - (t_2offset - t_offset));
162 }
163 
164 
165 #if 0
166 /* just like snprintf(), but always NUL terminates */
167 int
168 sk_snprintf(
169     char               *str,
170     size_t              size,
171     const char         *format,
172     ...)
173 {
174     va_list args;
175     int rv;
176 
177     va_start(args, format);
178     rv = sk_vsnprintf(str, size, format, args);
179     va_end(args);
180     return rv;
181 }
182 
183 
184 /* just like vsnprintf(), but always NUL terminates */
185 int
186 sk_vsnprintf(
187     char               *str,
188     size_t              size,
189     const char         *format,
190     va_list             args)
191 {
192 #undef vsnprintf
193     int rv = vsnprintf(str, size, format, args);
194     str[size-1] = '\0';
195     return rv;
196 }
197 #endif
198 
199 
200 /*
201 ** Local Variables:
202 ** mode:c
203 ** indent-tabs-mode:nil
204 ** c-basic-offset:4
205 ** End:
206 */
207