preparing for release of alpha-2.6
[Samba/gbeck.git] / source / lib / replace.c
blob8d91c2d785c6df5d23f17f75e59e4738ea231b90
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 replacement routines for broken systems
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 extern int DEBUGLEVEL;
26 void replace_dummy(void);
27 void replace_dummy(void) {}
30 #ifndef HAVE_FTRUNCATE
31 /*******************************************************************
32 ftruncate for operating systems that don't have it
33 ********************************************************************/
34 int ftruncate(int f,SMB_OFF_T l)
36 struct flock fl;
38 fl.l_whence = 0;
39 fl.l_len = 0;
40 fl.l_start = l;
41 fl.l_type = F_WRLCK;
42 return fcntl(f, F_FREESP, &fl);
44 #endif /* HAVE_FTRUNCATE */
47 #ifndef HAVE_MKTIME
48 /*******************************************************************
49 a mktime() replacement for those who don't have it - contributed by
50 C.A. Lademann <cal@zls.com>
51 Corrections by richard.kettlewell@kewill.com
52 ********************************************************************/
54 #define MINUTE 60
55 #define HOUR 60*MINUTE
56 #define DAY 24*HOUR
57 #define YEAR 365*DAY
58 time_t mktime(struct tm *t)
60 struct tm *u;
61 time_t epoch = 0;
62 int n;
63 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
64 y, m, i;
66 if(t->tm_year < 70)
67 return((time_t)-1);
69 n = t->tm_year + 1900 - 1;
70 epoch = (t->tm_year - 70) * YEAR +
71 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
73 y = t->tm_year + 1900;
74 m = 0;
76 for(i = 0; i < t->tm_mon; i++) {
77 epoch += mon [m] * DAY;
78 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
79 epoch += DAY;
81 if(++m > 11) {
82 m = 0;
83 y++;
87 epoch += (t->tm_mday - 1) * DAY;
88 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
90 if((u = localtime(&epoch)) != NULL) {
91 t->tm_sec = u->tm_sec;
92 t->tm_min = u->tm_min;
93 t->tm_hour = u->tm_hour;
94 t->tm_mday = u->tm_mday;
95 t->tm_mon = u->tm_mon;
96 t->tm_year = u->tm_year;
97 t->tm_wday = u->tm_wday;
98 t->tm_yday = u->tm_yday;
99 t->tm_isdst = u->tm_isdst;
102 return(epoch);
104 #endif /* !HAVE_MKTIME */
108 #ifndef HAVE_RENAME
109 /* Rename a file. (from libiberty in GNU binutils) */
110 int rename(const char *zfrom, const char *zto)
112 if (link (zfrom, zto) < 0)
114 if (errno != EEXIST)
115 return -1;
116 if (unlink (zto) < 0
117 || link (zfrom, zto) < 0)
118 return -1;
120 return unlink (zfrom);
122 #endif /* HAVE_RENAME */
125 #ifndef HAVE_INNETGR
126 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
128 * Search for a match in a netgroup. This replaces it on broken systems.
130 int innetgr(char *group,char *host,char *user,char *dom)
132 char *hst, *usr, *dm;
134 setnetgrent(group);
135 while (getnetgrent(&hst, &usr, &dm)) {
136 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
137 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
138 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
139 endnetgrent();
140 return (1);
143 endnetgrent();
144 return (0);
146 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
147 #endif /* HAVE_INNETGR */
151 #ifndef HAVE_INITGROUPS
152 /****************************************************************************
153 some systems don't have an initgroups call
154 ****************************************************************************/
155 int initgroups(char *name,gid_t id)
157 #ifndef HAVE_SETGROUPS
158 static int done;
159 if (!done) {
160 DEBUG(1,("WARNING: running without setgroups\n"));
161 done=1;
163 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
164 return(0);
165 #else /* HAVE_SETGROUPS */
166 gid_t *grouplst = NULL;
167 int max_gr = groups_max();
168 int ret;
169 int i,j;
170 struct group *g;
171 char *gr;
173 if((grouplst = (gid_t *)malloc(sizeof(gid_t) * max_gr)) == NULL) {
174 DEBUG(0,("initgroups: malloc fail !\n");
175 return -1;
178 grouplst[0] = id;
179 i = 1;
180 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
181 if (g->gr_gid == id)
182 continue;
183 j = 0;
184 gr = g->gr_mem[0];
185 while (gr && (*gr != (char)NULL)) {
186 if (strcmp(name,gr) == 0) {
187 grouplst[i] = g->gr_gid;
188 i++;
189 gr = (char *)NULL;
190 break;
192 gr = g->gr_mem[++j];
195 endgrent();
196 ret = sys_setgroups(i,grouplst);
197 free((char *)grouplst);
198 return ret;
199 #endif /* HAVE_SETGROUPS */
201 #endif /* HAVE_INITGROUPS */
204 #if (defined(SecureWare) && defined(SCO))
205 /* This is needed due to needing the nap() function but we don't want
206 to include the Xenix libraries since that will break other things...
207 BTW: system call # 0x0c28 is the same as calling nap() */
208 long nap(long milliseconds) {
209 return syscall(0x0c28, milliseconds);
211 #endif
214 #ifndef HAVE_MEMMOVE
215 /*******************************************************************
216 safely copies memory, ensuring no overlap problems.
217 this is only used if the machine does not have it's own memmove().
218 this is not the fastest algorithm in town, but it will do for our
219 needs.
220 ********************************************************************/
221 void *memmove(void *dest,const void *src,int size)
223 unsigned long d,s;
224 int i;
225 if (dest==src || !size) return(dest);
227 d = (unsigned long)dest;
228 s = (unsigned long)src;
230 if ((d >= (s+size)) || (s >= (d+size))) {
231 /* no overlap */
232 memcpy(dest,src,size);
233 return(dest);
236 if (d < s) {
237 /* we can forward copy */
238 if (s-d >= sizeof(int) &&
239 !(s%sizeof(int)) &&
240 !(d%sizeof(int)) &&
241 !(size%sizeof(int))) {
242 /* do it all as words */
243 int *idest = (int *)dest;
244 int *isrc = (int *)src;
245 size /= sizeof(int);
246 for (i=0;i<size;i++) idest[i] = isrc[i];
247 } else {
248 /* simplest */
249 char *cdest = (char *)dest;
250 char *csrc = (char *)src;
251 for (i=0;i<size;i++) cdest[i] = csrc[i];
253 } else {
254 /* must backward copy */
255 if (d-s >= sizeof(int) &&
256 !(s%sizeof(int)) &&
257 !(d%sizeof(int)) &&
258 !(size%sizeof(int))) {
259 /* do it all as words */
260 int *idest = (int *)dest;
261 int *isrc = (int *)src;
262 size /= sizeof(int);
263 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
264 } else {
265 /* simplest */
266 char *cdest = (char *)dest;
267 char *csrc = (char *)src;
268 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
271 return(dest);
273 #endif /* HAVE_MEMMOVE */
275 #ifndef HAVE_STRDUP
276 /****************************************************************************
277 duplicate a string
278 ****************************************************************************/
279 char *strdup(const char *s)
281 size_t len;
282 char *ret;
284 if (!s) return(NULL);
286 len = strlen(s)+1;
287 ret = (char *)malloc(len);
288 if (!ret) return(NULL);
289 memcpy(ret,s,len);
290 return(ret);
292 #endif /* HAVE_STRDUP */
294 #ifdef REPLACE_INET_NTOA
295 char *rep_inet_ntoa(struct in_addr ip)
297 unsigned char *p = (unsigned char *)&ip.s_addr;
298 static char buf[18];
299 #if WORDS_BIGENDIAN
300 slprintf(buf, 17, "%d.%d.%d.%d",
301 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
302 #else /* WORDS_BIGENDIAN */
303 slprintf(buf, 17, "%d.%d.%d.%d",
304 (int)p[3], (int)p[2], (int)p[1], (int)p[0]);
305 #endif /* WORDS_BIGENDIAN */
306 return buf;
308 #endif /* REPLACE_INET_NTOA */
310 #ifndef HAVE_STRTOUL
311 #ifndef ULONG_MAX
312 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
313 #endif
316 * Convert a string to an unsigned long integer.
317 * Taken from libg++ - libiberty code.
319 * Ignores `locale' stuff. Assumes that the upper and lower case
320 * alphabets and digits are each contiguous.
322 unsigned long strtoul(const char *nptr, char **endptr, int base)
324 const char *s = nptr;
325 unsigned long acc;
326 int c;
327 unsigned long cutoff;
328 int neg = 0, any, cutlim;
331 * See strtol for comments as to the logic used.
333 do {
334 c = *s++;
335 } while (isspace(c));
336 if (c == '-') {
337 neg = 1;
338 c = *s++;
339 } else if (c == '+')
340 c = *s++;
341 if ((base == 0 || base == 16) &&
342 c == '0' && (*s == 'x' || *s == 'X')) {
343 c = s[1];
344 s += 2;
345 base = 16;
347 if (base == 0)
348 base = c == '0' ? 8 : 10;
349 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
350 cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
351 for (acc = 0, any = 0;; c = *s++) {
352 if (isdigit(c))
353 c -= '0';
354 else if (isalpha(c))
355 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
356 else
357 break;
358 if (c >= base)
359 break;
360 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
361 any = -1;
362 else {
363 any = 1;
364 acc *= base;
365 acc += c;
368 if (any < 0) {
369 acc = ULONG_MAX;
370 errno = ERANGE;
371 } else if (neg)
372 acc = -acc;
373 if (endptr != 0)
374 *endptr = (char *) (any ? s - 1 : nptr);
375 return (acc);
377 #endif /* HAVE_STRTOUL */