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.
22 #include "system/wait.h"
23 #include "system/time.h"
24 #include "system/network.h"
26 void replace_dummy(void);
27 void replace_dummy(void) {}
29 #ifndef HAVE_FTRUNCATE
30 /*******************************************************************
31 ftruncate for operating systems that don't have it
32 ********************************************************************/
33 int ftruncate(int f,off_t l)
44 return fcntl(f, F_FREESP, &fl);
47 #endif /* HAVE_FTRUNCATE */
51 /* like strncpy but does not 0 fill the buffer and always null
52 terminates. bufsize is the size of the destination buffer */
53 size_t strlcpy(char *d, const char *s, size_t bufsize)
55 size_t len = strlen(s);
57 if (bufsize <= 0) return 0;
58 if (len >= bufsize) len = bufsize-1;
66 /* like strncat but does not 0 fill the buffer and always null
67 terminates. bufsize is the length of the buffer, which should
68 be one more than the maximum resulting string length */
69 size_t strlcat(char *d, const char *s, size_t bufsize)
71 size_t len1 = strlen(d);
72 size_t len2 = strlen(s);
73 size_t ret = len1 + len2;
75 if (len1+len2 >= bufsize) {
76 len2 = bufsize - (len1+1);
79 memcpy(d+len1, s, len2);
87 /*******************************************************************
88 a mktime() replacement for those who don't have it - contributed by
89 C.A. Lademann <cal@zls.com>
90 Corrections by richard.kettlewell@kewill.com
91 ********************************************************************/
94 #define HOUR 60*MINUTE
97 time_t mktime(struct tm *t)
102 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
108 n = t->tm_year + 1900 - 1;
109 epoch = (t->tm_year - 70) * YEAR +
110 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
112 y = t->tm_year + 1900;
115 for(i = 0; i < t->tm_mon; i++) {
116 epoch += mon [m] * DAY;
117 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
126 epoch += (t->tm_mday - 1) * DAY;
127 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
129 if((u = localtime(&epoch)) != NULL) {
130 t->tm_sec = u->tm_sec;
131 t->tm_min = u->tm_min;
132 t->tm_hour = u->tm_hour;
133 t->tm_mday = u->tm_mday;
134 t->tm_mon = u->tm_mon;
135 t->tm_year = u->tm_year;
136 t->tm_wday = u->tm_wday;
137 t->tm_yday = u->tm_yday;
138 t->tm_isdst = u->tm_isdst;
143 #endif /* !HAVE_MKTIME */
148 /* Rename a file. (from libiberty in GNU binutils) */
149 int rename(const char *zfrom, const char *zto)
151 if (link (zfrom, zto) < 0)
156 || link (zfrom, zto) < 0)
159 return unlink (zfrom);
161 #endif /* HAVE_RENAME */
165 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
167 * Search for a match in a netgroup. This replaces it on broken systems.
169 int innetgr(const char *group,const char *host,const char *user,const char *dom)
171 char *hst, *usr, *dm;
174 while (getnetgrent(&hst, &usr, &dm)) {
175 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
176 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
177 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
185 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
186 #endif /* HAVE_INNETGR */
190 #ifndef HAVE_INITGROUPS
191 /****************************************************************************
192 some systems don't have an initgroups call
193 ****************************************************************************/
194 int initgroups(char *name, gid_t id)
196 #ifndef HAVE_SETGROUPS
197 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
200 #else /* HAVE_SETGROUPS */
201 gid_t *grouplst = NULL;
202 int max_gr = groups_max();
208 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
215 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
220 while (gr && (*gr != (char)NULL)) {
221 if (strcmp(name,gr) == 0) {
222 grouplst[i] = g->gr_gid;
231 ret = setgroups(i, grouplst);
234 #endif /* HAVE_SETGROUPS */
236 #endif /* HAVE_INITGROUPS */
239 #if (defined(SecureWare) && defined(SCO))
240 /* This is needed due to needing the nap() function but we don't want
241 to include the Xenix libraries since that will break other things...
242 BTW: system call # 0x0c28 is the same as calling nap() */
243 long nap(long milliseconds) {
244 return syscall(0x0c28, milliseconds);
250 /*******************************************************************
251 safely copies memory, ensuring no overlap problems.
252 this is only used if the machine does not have it's own memmove().
253 this is not the fastest algorithm in town, but it will do for our
255 ********************************************************************/
256 void *memmove(void *dest,const void *src,int size)
260 if (dest==src || !size) return(dest);
262 d = (unsigned long)dest;
263 s = (unsigned long)src;
265 if ((d >= (s+size)) || (s >= (d+size))) {
267 memcpy(dest,src,size);
272 /* we can forward copy */
273 if (s-d >= sizeof(int) &&
276 !(size%sizeof(int))) {
277 /* do it all as words */
278 int *idest = (int *)dest;
279 int *isrc = (int *)src;
281 for (i=0;i<size;i++) idest[i] = isrc[i];
284 char *cdest = (char *)dest;
285 char *csrc = (char *)src;
286 for (i=0;i<size;i++) cdest[i] = csrc[i];
289 /* must backward copy */
290 if (d-s >= sizeof(int) &&
293 !(size%sizeof(int))) {
294 /* do it all as words */
295 int *idest = (int *)dest;
296 int *isrc = (int *)src;
298 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
301 char *cdest = (char *)dest;
302 char *csrc = (char *)src;
303 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
308 #endif /* HAVE_MEMMOVE */
311 /****************************************************************************
313 ****************************************************************************/
314 char *strdup(const char *s)
319 if (!s) return(NULL);
322 ret = (char *)malloc(len);
323 if (!ret) return(NULL);
327 #endif /* HAVE_STRDUP */
329 #ifndef WITH_PTHREADS
330 /* REWRITE: not thread safe */
331 #ifdef REPLACE_INET_NTOA
332 char *rep_inet_ntoa(struct in_addr ip)
334 uint8_t *p = (uint8_t *)&ip.s_addr;
336 slprintf(buf, 17, "%d.%d.%d.%d",
337 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
340 #endif /* REPLACE_INET_NTOA */
345 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
349 * Convert a string to an unsigned long integer.
350 * Taken from libg++ - libiberty code.
352 * Ignores `locale' stuff. Assumes that the upper and lower case
353 * alphabets and digits are each contiguous.
355 unsigned long strtoul(const char *nptr, char **endptr, int base)
357 const char *s = nptr;
360 unsigned long cutoff;
361 int neg = 0, any, cutlim;
364 * See strtol for comments as to the logic used.
368 } while (isspace(c));
374 if ((base == 0 || base == 16) &&
375 c == '0' && (*s == 'x' || *s == 'X')) {
381 base = c == '0' ? 8 : 10;
382 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
383 cutlim = (int)((unsigned long)ULONG_MAX % (unsigned long)base);
384 for (acc = 0, any = 0;; c = *s++) {
388 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
393 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
407 *endptr = (char *) (any ? s - 1 : nptr);
410 #endif /* HAVE_STRTOUL */
412 #ifndef HAVE_SETLINEBUF
413 int setlinebuf(FILE *stream)
415 return setvbuf(stream, (char *)NULL, _IOLBF, 0);
417 #endif /* HAVE_SETLINEBUF */
421 void vsyslog (int facility_priority, char *format, va_list arglist)
424 vasprintf(&msg, format, arglist);
427 syslog(facility_priority, "%s", msg);
430 #endif /* HAVE_SYSLOG */
431 #endif /* HAVE_VSYSLOG */
433 /*******************************************************************
434 yield the difference between *A and *B, in seconds, ignoring leap seconds
435 ********************************************************************/
436 static int tm_diff(struct tm *a, struct tm *b)
438 int ay = a->tm_year + (1900 - 1);
439 int by = b->tm_year + (1900 - 1);
440 int intervening_leap_days =
441 (ay/4 - by/4) - (ay/100 - by/100) + (ay/400 - by/400);
443 int days = 365*years + intervening_leap_days + (a->tm_yday - b->tm_yday);
444 int hours = 24*days + (a->tm_hour - b->tm_hour);
445 int minutes = 60*hours + (a->tm_min - b->tm_min);
446 int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
451 /*******************************************************************
452 return the UTC offset in seconds west of UTC, or 0 if it cannot be determined
453 ******************************************************************/
454 int get_time_zone(time_t t)
456 struct tm *tm = gmtime(&t);
464 return tm_diff(&tm_utc,tm);
469 yes, I know this looks insane, but its really needed. The function in the
470 Linux timegm() manpage does not work on solaris.
472 time_t timegm(struct tm *tm)
480 tm3 = *localtime(&t);
482 tm2.tm_isdst = tm3.tm_isdst;
484 t -= get_time_zone(t);
491 int setenv(const char *name, const char *value, int overwrite)
496 asprintf(&p, "%s=%s", name, value);
498 if (overwrite || getenv(name)) {
499 if (p) ret = putenv(p);
509 #ifndef HAVE_STRTOULL
510 unsigned long long int strtoull(const char *str, char **endptr, int base)
513 return strtouq(str, endptr, base);
515 unsigned long long int v;
516 if (sscanf(str, "%lli", &v) != 1) {
517 smb_panic("system does not support %lli in sscanf");
520 /* try to get endptr right - uggh */
521 strtoul(str, endptr, base);
531 Some platforms don't have strndup.
533 char *strndup(const char *s, size_t n)
550 Some platforms don't have strnlen
552 size_t strnlen(const char *s, size_t n)
555 for (i=0; s[i] && i<n; i++)
561 int sys_waitpid(pid_t pid,int *status,int options)
564 return waitpid(pid,status,options);
565 #else /* USE_WAITPID */
566 return wait4(pid, status, options, NULL);
567 #endif /* USE_WAITPID */