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