r15086: Get defensive about creating user accounts when winbindd
[Samba.git] / source / lib / replace.c
blob120fd3a4688caf0120090183da60bcc583955ae2
1 /*
2 Unix SMB/CIFS implementation.
3 replacement routines for broken systems
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 void replace_dummy(void);
24 void replace_dummy(void) {}
26 #ifndef HAVE_FTRUNCATE
27 /*******************************************************************
28 ftruncate for operating systems that don't have it
29 ********************************************************************/
30 int ftruncate(int f,SMB_OFF_T l)
32 #ifdef HAVE_CHSIZE
33 return chsize(f,l);
34 #else
35 struct flock fl;
37 fl.l_whence = 0;
38 fl.l_len = 0;
39 fl.l_start = l;
40 fl.l_type = F_WRLCK;
41 return fcntl(f, F_FREESP, &fl);
42 #endif
44 #endif /* HAVE_FTRUNCATE */
46 #ifndef HAVE_STRLCPY
47 /* like strncpy but does not 0 fill the buffer and always null
48 terminates. bufsize is the size of the destination buffer */
49 size_t strlcpy(char *d, const char *s, size_t bufsize)
51 size_t len = strlen(s);
52 size_t ret = len;
53 if (bufsize <= 0) return 0;
54 if (len >= bufsize) len = bufsize-1;
55 memcpy(d, s, len);
56 d[len] = 0;
57 return ret;
59 #endif
61 #ifndef HAVE_STRLCAT
62 /* like strncat but does not 0 fill the buffer and always null
63 terminates. bufsize is the length of the buffer, which should
64 be one more than the maximum resulting string length */
65 size_t strlcat(char *d, const char *s, size_t bufsize)
67 size_t len1 = strlen(d);
68 size_t len2 = strlen(s);
69 size_t ret = len1 + len2;
71 if (len1 >= bufsize) {
72 return 0;
74 if (len1+len2 >= bufsize) {
75 len2 = bufsize - (len1+1);
77 if (len2 > 0) {
78 memcpy(d+len1, s, len2);
79 d[len1+len2] = 0;
81 return ret;
83 #endif
85 #ifndef HAVE_MKTIME
86 /*******************************************************************
87 a mktime() replacement for those who don't have it - contributed by
88 C.A. Lademann <cal@zls.com>
89 Corrections by richard.kettlewell@kewill.com
90 ********************************************************************/
92 #define MINUTE 60
93 #define HOUR 60*MINUTE
94 #define DAY 24*HOUR
95 #define YEAR 365*DAY
96 time_t mktime(struct tm *t)
98 struct tm *u;
99 time_t epoch = 0;
100 int n;
101 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
102 y, m, i;
104 if(t->tm_year < 70)
105 return((time_t)-1);
107 n = t->tm_year + 1900 - 1;
108 epoch = (t->tm_year - 70) * YEAR +
109 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
111 y = t->tm_year + 1900;
112 m = 0;
114 for(i = 0; i < t->tm_mon; i++) {
115 epoch += mon [m] * DAY;
116 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
117 epoch += DAY;
119 if(++m > 11) {
120 m = 0;
121 y++;
125 epoch += (t->tm_mday - 1) * DAY;
126 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
128 if((u = localtime(&epoch)) != NULL) {
129 t->tm_sec = u->tm_sec;
130 t->tm_min = u->tm_min;
131 t->tm_hour = u->tm_hour;
132 t->tm_mday = u->tm_mday;
133 t->tm_mon = u->tm_mon;
134 t->tm_year = u->tm_year;
135 t->tm_wday = u->tm_wday;
136 t->tm_yday = u->tm_yday;
137 t->tm_isdst = u->tm_isdst;
140 return(epoch);
142 #endif /* !HAVE_MKTIME */
146 #ifndef HAVE_RENAME
147 /* Rename a file. (from libiberty in GNU binutils) */
148 int rename(const char *zfrom, const char *zto)
150 if (link (zfrom, zto) < 0)
152 if (errno != EEXIST)
153 return -1;
154 if (unlink (zto) < 0
155 || link (zfrom, zto) < 0)
156 return -1;
158 return unlink (zfrom);
160 #endif /* HAVE_RENAME */
163 #ifndef HAVE_INNETGR
164 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
166 * Search for a match in a netgroup. This replaces it on broken systems.
168 int innetgr(const char *group,const char *host,const char *user,const char *dom)
170 char *hst, *usr, *dm;
172 setnetgrent(group);
173 while (getnetgrent(&hst, &usr, &dm)) {
174 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
175 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
176 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
177 endnetgrent();
178 return (1);
181 endnetgrent();
182 return (0);
184 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
185 #endif /* HAVE_INNETGR */
189 #ifndef HAVE_INITGROUPS
190 /****************************************************************************
191 some systems don't have an initgroups call
192 ****************************************************************************/
193 int initgroups(char *name,gid_t id)
195 #ifndef HAVE_SETGROUPS
196 static int done;
197 if (!done) {
198 DEBUG(1,("WARNING: running without setgroups\n"));
199 done=1;
201 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
202 return(0);
203 #else /* HAVE_SETGROUPS */
204 gid_t *grouplst = NULL;
205 int max_gr = groups_max();
206 int ret;
207 int i,j;
208 struct group *g;
209 char *gr;
211 if((grouplst = SMB_MALLOC_ARRAY(gid_t, max_gr)) == NULL) {
212 DEBUG(0,("initgroups: malloc fail !\n"));
213 return -1;
216 grouplst[0] = id;
217 i = 1;
218 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
219 if (g->gr_gid == id)
220 continue;
221 j = 0;
222 gr = g->gr_mem[0];
223 while (gr && (*gr != (char)NULL)) {
224 if (strcmp(name,gr) == 0) {
225 grouplst[i] = g->gr_gid;
226 i++;
227 gr = (char *)NULL;
228 break;
230 gr = g->gr_mem[++j];
233 endgrent();
234 ret = sys_setgroups(i,grouplst);
235 SAFE_FREE(grouplst);
236 return ret;
237 #endif /* HAVE_SETGROUPS */
239 #endif /* HAVE_INITGROUPS */
242 #if (defined(SecureWare) && defined(SCO))
243 /* This is needed due to needing the nap() function but we don't want
244 to include the Xenix libraries since that will break other things...
245 BTW: system call # 0x0c28 is the same as calling nap() */
246 long nap(long milliseconds) {
247 return syscall(0x0c28, milliseconds);
249 #endif
252 #ifndef HAVE_MEMMOVE
253 /*******************************************************************
254 safely copies memory, ensuring no overlap problems.
255 this is only used if the machine does not have it's own memmove().
256 this is not the fastest algorithm in town, but it will do for our
257 needs.
258 ********************************************************************/
259 void *memmove(void *dest,const void *src,int size)
261 unsigned long d,s;
262 int i;
263 if (dest==src || !size) return(dest);
265 d = (unsigned long)dest;
266 s = (unsigned long)src;
268 if ((d >= (s+size)) || (s >= (d+size))) {
269 /* no overlap */
270 memcpy(dest,src,size);
271 return(dest);
274 if (d < s) {
275 /* we can forward copy */
276 if (s-d >= sizeof(int) &&
277 !(s%sizeof(int)) &&
278 !(d%sizeof(int)) &&
279 !(size%sizeof(int))) {
280 /* do it all as words */
281 int *idest = (int *)dest;
282 int *isrc = (int *)src;
283 size /= sizeof(int);
284 for (i=0;i<size;i++) idest[i] = isrc[i];
285 } else {
286 /* simplest */
287 char *cdest = (char *)dest;
288 char *csrc = (char *)src;
289 for (i=0;i<size;i++) cdest[i] = csrc[i];
291 } else {
292 /* must backward copy */
293 if (d-s >= sizeof(int) &&
294 !(s%sizeof(int)) &&
295 !(d%sizeof(int)) &&
296 !(size%sizeof(int))) {
297 /* do it all as words */
298 int *idest = (int *)dest;
299 int *isrc = (int *)src;
300 size /= sizeof(int);
301 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
302 } else {
303 /* simplest */
304 char *cdest = (char *)dest;
305 char *csrc = (char *)src;
306 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
309 return(dest);
311 #endif /* HAVE_MEMMOVE */
313 #ifndef HAVE_STRDUP
314 /****************************************************************************
315 duplicate a string
316 ****************************************************************************/
318 #ifdef strdup
319 #undef strdup
320 #endif
322 char *strdup(const char *s)
324 size_t len;
325 char *ret;
327 if (!s) return(NULL);
329 len = strlen(s)+1;
330 ret = (char *)SMB_MALLOC(len);
331 if (!ret) return(NULL);
332 memcpy(ret,s,len);
333 return(ret);
335 #endif /* HAVE_STRDUP */
337 #ifdef REPLACE_INET_NTOA
338 char *rep_inet_ntoa(struct in_addr ip)
340 unsigned char *p = (unsigned char *)&ip.s_addr;
341 static char buf[18];
342 slprintf(buf, 17, "%d.%d.%d.%d",
343 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
344 return buf;
346 #endif /* REPLACE_INET_NTOA */
348 #ifndef HAVE_STRTOUL
349 #ifndef ULONG_MAX
350 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
351 #endif
354 * Convert a string to an unsigned long integer.
355 * Taken from libg++ - libiberty code.
357 * Ignores `locale' stuff. Assumes that the upper and lower case
358 * alphabets and digits are each contiguous.
360 unsigned long strtoul(const char *nptr, char **endptr, int base)
362 const char *s = nptr;
363 unsigned long acc;
364 int c;
365 unsigned long cutoff;
366 int neg = 0, any, cutlim;
369 * See strtol for comments as to the logic used.
371 do {
372 c = *s++;
373 } while (isspace(c));
374 if (c == '-') {
375 neg = 1;
376 c = *s++;
377 } else if (c == '+')
378 c = *s++;
379 if ((base == 0 || base == 16) &&
380 c == '0' && (*s == 'x' || *s == 'X')) {
381 c = s[1];
382 s += 2;
383 base = 16;
385 if (base == 0)
386 base = c == '0' ? 8 : 10;
387 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
388 cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
389 for (acc = 0, any = 0;; c = *s++) {
390 if (isdigit(c))
391 c -= '0';
392 else if (isalpha(c))
393 c -= isupper_ascii(c) ? 'A' - 10 : 'a' - 10;
394 else
395 break;
396 if (c >= base)
397 break;
398 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
399 any = -1;
400 else {
401 any = 1;
402 acc *= base;
403 acc += c;
406 if (any < 0) {
407 acc = ULONG_MAX;
408 errno = ERANGE;
409 } else if (neg)
410 acc = -acc;
411 if (endptr != 0)
412 *endptr = (char *) (any ? s - 1 : nptr);
413 return (acc);
415 #endif /* HAVE_STRTOUL */
417 #ifndef HAVE_SETLINEBUF
418 int setlinebuf(FILE *stream)
420 return setvbuf(stream, (char *)NULL, _IOLBF, 0);
422 #endif /* HAVE_SETLINEBUF */
424 #ifndef HAVE_VSYSLOG
425 #ifdef HAVE_SYSLOG
426 void vsyslog (int facility_priority, const char *format, va_list arglist)
428 char *msg = NULL;
429 vasprintf(&msg, format, arglist);
430 if (!msg)
431 return;
432 syslog(facility_priority, "%s", msg);
433 SAFE_FREE(msg);
435 #endif /* HAVE_SYSLOG */
436 #endif /* HAVE_VSYSLOG */
439 #ifndef HAVE_TIMEGM
441 yes, I know this looks insane, but its really needed. The function in the
442 Linux timegm() manpage does not work on solaris.
444 time_t timegm(struct tm *tm)
446 struct tm tm2, tm3;
447 time_t t;
449 tm2 = *tm;
451 t = mktime(&tm2);
452 tm3 = *localtime(&t);
453 tm2 = *tm;
454 tm2.tm_isdst = tm3.tm_isdst;
455 t = mktime(&tm2);
456 t -= get_time_zone(t);
458 return t;
460 #endif