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