1 /* distcache, Distributed Session Caching technology
2  * Copyright (C) 2000-2003  Geoff Thorpe, and Cryptographic Appliances, Inc.
3  * Copyright (C) 2004       The Distcache.org project
4  *
5  * This library is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License as published by the Free
7  * Software Foundation; using version 2.1 of the License. The copyright holders
8  * may elect to allow the application of later versions of the License to this
9  * software, please contact the author (geoff@distcache.org) if you wish us to
10  * review any later version released by the Free Software Foundation.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation, Inc.,
19  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21 #ifndef HEADER_LIBSYS_POST_H
22 #define HEADER_LIBSYS_POST_H
23 
24 #ifndef HEADER_LIBSYS_PRE_H
25 #error "must include libsys/pre.h before other headers"
26 #endif
27 
28 /**************************/
29 /* DEBUGGING DECLARATIONS */
30 /**************************/
31 
32 /* You can set this value to one of five settings; 0, 1, 2, 3, or 4. At
33  * run-time, logging can be turned off anyway - however this level controls the
34  * content that will be output if it is not disabled.
35  *
36  * 0 = output nothing (ie. silent operation)
37  * 1 = output what a normal release-build should output.
38  * 2 = output warnings too. Output interesting information that isn't otherwise
39  *     produced in a release build.
40  * 3 = output program flow information too, and minor warnings of more interest
41  *     to peer program debugging (ie. "no problem here, but maybe your other
42  *     program is not doing what you think it is?").
43  * 4 = output trace-level debugging information (verbose).
44  */
45 #ifndef SYS_DEBUG_LEVEL
46 #define SYS_DEBUG_LEVEL 1
47 #endif
48 
49 /*******************************/
50 /* OUTPUT CONTROL DECLARATIONS */
51 /*******************************/
52 
53 /* We use the system functions directly from our macros, but this permits more
54  * indirection later on. */
55 #define SYS_stdin	stdin
56 #define SYS_stdout	stdout
57 #define SYS_stderr	stderr
58 #define SYS_fprintf	fprintf
59 
60 #ifndef LEAVE_PROCESSES_ALONE
61 
62 #ifndef IN_SYS_C
63 #define daemon dont_use_daemon_but_use_SYS_daemon_instead
64 #endif
65 
66 #endif /* !LEAVE_PROCESSES_ALONE */
67 
68 /*********************/
69 /* TYPESAFE WRAPPERS */
70 /*********************/
71 
72 /* We use the system functions directly from our macros, but this permits more
73  * indirection later on. */
74 #define sys_malloc	malloc
75 #define sys_realloc	realloc
76 #define sys_free	free
77 #define sys_memset	memset
78 #define sys_memcpy	memcpy
79 #define sys_memmove	memmove
80 
81 /* We use our type-safe macro wrappers always for now, but if we notice any
82  * speed differences we can put these back. Note, a decent compiler should boil
83  * the type-safe wrappers down to these forms anyway after type-checking. */
84 #if 0
85 #define SYS_malloc(t,n)		(t *)malloc((n) * sizeof(t))
86 #define SYS_realloc(t,p,n)	(t *)realloc((p), (n) * sizeof(t))
87 #define SYS_free(t,p)		free((p))
88 #define SYS_cover(c,t,p)	memset((p), (c), sizeof(t))
89 #define SYS_cover_n(c,t,p,n)	memset((p), (c), (n) * sizeof(t))
90 #define SYS_memcpy(t,d,s)	memcpy((d), (s), sizeof(t))
91 #define SYS_memcpy_n(t,d,s,n)	memcpy((d), (s), (n) * sizeof(t))
92 #define SYS_memmove(t,d,s)	memmove((d), (s), sizeof(t))
93 #define SYS_memmove_n(t,d,s,n)	memmove((d), (s), (n) * sizeof(t))
94 #else
95 
96 /* Type-safe macro wrappers */
97 #define SYS_malloc(t,n)		(t *)sys_malloc((n) * sizeof(t))
98 #define SYS_realloc(t,p,n)	(t *)sys_realloc((p), (n) * sizeof(t))
99 #define SYS_free(t,p)		do { \
100 				t *tmp_sys_free_4765 = (p); \
101 				sys_free(tmp_sys_free_4765); \
102 				} while(0)
103 #define SYS_cover(c,t,p)	do { \
104 				t *temp_SYS_cover_ptr = (p); \
105 				sys_memset(temp_SYS_cover_ptr, (c), \
106 						sizeof(t)); \
107 				} while(0)
108 #define SYS_cover_n(c,t,p,n)	do { \
109 				t *temp_SYS_cover_n_ptr = (p); \
110 				sys_memset(temp_SYS_cover_n_ptr, (c), \
111 						(n) * sizeof(t)); \
112 				} while(0)
113 #define SYS_memcpy(t,d,s)	do { \
114 				t *temp_SYS_memcpy_ptr1 = (d); \
115 				const t *temp_SYS_memcpy_ptr2 = (s); \
116 				sys_memcpy(temp_SYS_memcpy_ptr1, \
117 					temp_SYS_memcpy_ptr2, \
118 					sizeof(t)); \
119 				} while(0)
120 #define SYS_memcpy_n(t,d,s,n)	do { \
121 				t *temp_SYS_memcpy_ptr1 = (d); \
122 				const t *temp_SYS_memcpy_ptr2 = (s); \
123 				sys_memcpy(temp_SYS_memcpy_ptr1, \
124 					temp_SYS_memcpy_ptr2, \
125 					(n) * sizeof(t)); \
126 				} while(0)
127 #define SYS_memmove(t,d,s)	do { \
128 				t *temp_SYS_memmove_ptr1 = (d); \
129 				const t *temp_SYS_memmove_ptr2 = (s); \
130 				sys_memmove(temp_SYS_memmove_ptr1, \
131 					temp_SYS_memmove_ptr2, \
132 					sizeof(t)); \
133 				} while(0)
134 #define SYS_memmove_n(t,d,s,n)	do { \
135 				t *temp_SYS_memmove_ptr1 = (d); \
136 				const t *temp_SYS_memmove_ptr2 = (s); \
137 				sys_memmove(temp_SYS_memmove_ptr1, \
138 					temp_SYS_memmove_ptr2, \
139 					(n) * sizeof(t)); \
140 				} while(0)
141 #endif
142 
143 #define SYS_zero(t,p)		SYS_cover(0,t,(p))
144 #define SYS_zero_n(t,p,n)	SYS_cover_n(0,t,(p),(n))
145 /* This wrapper always zero-terminates, unlike a normal strncpy which does not */
146 #define SYS_strncpy(d,s,n)	do { \
147 				char *tmp_SYS_strncpy1 = (d); \
148 				const char *tmp_SYS_strncpy2 = (s); \
149 				size_t tmp_SYS_strncpy3 = strlen(tmp_SYS_strncpy2), \
150 					tmp_SYS_strncpy4 = (n); \
151 				if(tmp_SYS_strncpy3 < tmp_SYS_strncpy4) \
152 					SYS_memcpy_n(char, (d), (s), tmp_SYS_strncpy3 + 1); \
153 				else { \
154 					SYS_memcpy_n(char, (d), (s), tmp_SYS_strncpy4); \
155 					tmp_SYS_strncpy1[tmp_SYS_strncpy4 - 1] = '\0'; \
156 				} \
157 				} while(0)
158 #define SYS_strdup(d,s)		do { \
159 				char **tmp_SYS_strdup1 = (d); \
160 				const char *tmp_SYS_strdup2 = (s); \
161 				size_t tmp_SYS_strdup3 = strlen(tmp_SYS_strdup2) + 1; \
162 				*tmp_SYS_strdup1 = SYS_malloc(char, tmp_SYS_strdup3); \
163 				if(*tmp_SYS_strdup1) \
164 					SYS_memcpy_n(char, *tmp_SYS_strdup1, \
165 						tmp_SYS_strdup2, tmp_SYS_strdup3); \
166 				} while(0)
167 
168 /* Now a structure version that is useful for example with fixed size char
169  * arrays ... eg. char v[20]; SYS_zero_s(v); Because you'd either need to use
170  * "20" inside SYS_zero_n, or risk strangeness with SYS_zero (do you pass "v" or
171  * "&v"? and what to pass for "t"??). */
172 #define SYS_cover_s(c,s)	memset(&(s), (c), sizeof(s))
173 #define SYS_zero_s(s)		SYS_cover_s(0,(s))
174 
175 /***************************/
176 /* SYSTEM HELPER FUNCTIONS */
177 /***************************/
178 
179 #define SYS_getpid	getpid
180 #define SYS_timecmp(a,b) \
181 		(((a)->tv_sec < (b)->tv_sec) ? -1 : \
182 			(((a)->tv_sec > (b)->tv_sec) ? 1 : \
183 			(((a)->tv_usec < (b)->tv_usec) ? -1 : \
184 			(((a)->tv_usec > (b)->tv_usec) ? 1 : 0))))
185 #define SYS_timecpy(d,s) SYS_memcpy(struct timeval, (d), (s))
186 #define SYS_timeadd(res,I,msecs) \
187 do { \
188 	struct timeval *_tmp_res = (res); \
189 	const struct timeval *_tmp_I = (I); \
190 	unsigned long _tmp_carry = _tmp_I->tv_usec + ((msecs) * 1000); \
191 	_tmp_res->tv_usec = _tmp_carry % 1000000; \
192 	_tmp_carry /= 1000000; \
193 	_tmp_res->tv_sec = _tmp_I->tv_sec + _tmp_carry; \
194 } while(0)
195 #ifdef WIN32
196 #define SYS_gettime(tv) \
197 do { \
198 	FILETIME decimillisecs; \
199 	unsigned __int64 crud; \
200 	GetSystemTimeAsFileTime(&decimillisecs); \
201 	crud = ((unsigned __int64)decimillisecs.dwHighDateTime << 32) + \
202 		(unsigned __int64)decimillisecs.dwLowDateTime; \
203 	crud /= 10; \
204 	crud -= (unsigned __int64)12614400000 * (unsigned __int64)1000000; \
205 	tv->tv_sec = (long)(crud / 1000000); \
206 	tv->tv_usec = (long)(crud % 1000000); \
207 } while(0)
208 #else
209 #define SYS_gettime(tv) \
210 do { \
211 	if(gettimeofday(tv, NULL) != 0)	abort(); \
212 } while(0)
213 #endif
214 
215 /* libsys functions shouldn't be exposed when generating library code, because
216  * they create linker dependencies on internal-only libsys. Those that we want to permit
217  * in library code must be declared inline instead. */
218 
219 #if defined(SYS_GENERATING_EXE) || defined(SYS_LOCAL)
220 
221 #ifdef WIN32
222 int SYS_sockets_init(void);
223 #else
224 int SYS_sigpipe_ignore(void);
225 int SYS_sigusr_interrupt(int *ptr);
226 int SYS_daemon(int nochdir);
227 int SYS_setuid(const char *username);
228 #endif
229 void SYS_timesub(struct timeval *res, const struct timeval *I,
230 		unsigned long msecs);
231 int SYS_expirycheck(const struct timeval *timeitem, unsigned long msec_expiry,
232 		const struct timeval *timenow);
233 unsigned long SYS_msecs_between(const struct timeval *a, const struct timeval *b);
234 
235 /* Redeclared as macros (for use in library code) */
236 #if 0
237 pid_t SYS_getpid(void);
238 void SYS_gettime(struct timeval *tv);
239 int SYS_timecmp(const struct timeval *a, const struct timeval *b);
240 void SYS_timecpy(struct timeval *dest, const struct timeval *src);
241 /* Arithmetic on timevals. 'res' can be the same as 'I' if desired. */
242 void SYS_timeadd(struct timeval *res, const struct timeval *I,
243 		unsigned long msecs);
244 #endif
245 
246 #endif /* defined(SYS_GENERATING_EXE) || defined(SYS_LOCAL) */
247 
248 #endif /* !defined(HEADER_LIBSYS_POST_H) */
249 
250