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/locale.h"
23 #include "system/wait.h"
24 #include "system/time.h"
25 #include "system/network.h"
26 #include "system/filesys.h"
27 #include "system/syslog.h"
29 void replace_dummy(void);
30 void replace_dummy(void) {}
32 #ifndef HAVE_FTRUNCATE
33 /*******************************************************************
34 ftruncate for operating systems that don't have it
35 ********************************************************************/
36 int ftruncate(int f,off_t l)
47 return fcntl(f, F_FREESP, &fl);
50 #endif /* HAVE_FTRUNCATE */
54 /* like strncpy but does not 0 fill the buffer and always null
55 terminates. bufsize is the size of the destination buffer */
56 size_t strlcpy(char *d, const char *s, size_t bufsize)
58 size_t len = strlen(s);
60 if (bufsize <= 0) return 0;
61 if (len >= bufsize) len = bufsize-1;
69 /* like strncat but does not 0 fill the buffer and always null
70 terminates. bufsize is the length of the buffer, which should
71 be one more than the maximum resulting string length */
72 size_t strlcat(char *d, const char *s, size_t bufsize)
74 size_t len1 = strlen(d);
75 size_t len2 = strlen(s);
76 size_t ret = len1 + len2;
78 if (len1+len2 >= bufsize) {
79 len2 = bufsize - (len1+1);
82 memcpy(d+len1, s, len2);
90 /*******************************************************************
91 a mktime() replacement for those who don't have it - contributed by
92 C.A. Lademann <cal@zls.com>
93 Corrections by richard.kettlewell@kewill.com
94 ********************************************************************/
97 #define HOUR 60*MINUTE
100 time_t mktime(struct tm *t)
105 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
111 n = t->tm_year + 1900 - 1;
112 epoch = (t->tm_year - 70) * YEAR +
113 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
115 y = t->tm_year + 1900;
118 for(i = 0; i < t->tm_mon; i++) {
119 epoch += mon [m] * DAY;
120 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
129 epoch += (t->tm_mday - 1) * DAY;
130 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
132 if((u = localtime(&epoch)) != NULL) {
133 t->tm_sec = u->tm_sec;
134 t->tm_min = u->tm_min;
135 t->tm_hour = u->tm_hour;
136 t->tm_mday = u->tm_mday;
137 t->tm_mon = u->tm_mon;
138 t->tm_year = u->tm_year;
139 t->tm_wday = u->tm_wday;
140 t->tm_yday = u->tm_yday;
141 t->tm_isdst = u->tm_isdst;
146 #endif /* !HAVE_MKTIME */
151 /* Rename a file. (from libiberty in GNU binutils) */
152 int rename(const char *zfrom, const char *zto)
154 if (link (zfrom, zto) < 0)
159 || link (zfrom, zto) < 0)
162 return unlink (zfrom);
164 #endif /* HAVE_RENAME */
168 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
170 * Search for a match in a netgroup. This replaces it on broken systems.
172 int innetgr(const char *group,const char *host,const char *user,const char *dom)
174 char *hst, *usr, *dm;
177 while (getnetgrent(&hst, &usr, &dm)) {
178 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
179 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
180 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
188 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
189 #endif /* HAVE_INNETGR */
193 #ifndef HAVE_INITGROUPS
194 /****************************************************************************
195 some systems don't have an initgroups call
196 ****************************************************************************/
197 int initgroups(char *name, gid_t id)
199 #ifndef HAVE_SETGROUPS
200 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
203 #else /* HAVE_SETGROUPS */
207 gid_t *grouplst = NULL;
208 int max_gr = groups_max();
214 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
221 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
226 while (gr && (*gr != (char)NULL)) {
227 if (strcmp(name,gr) == 0) {
228 grouplst[i] = g->gr_gid;
237 ret = setgroups(i, grouplst);
240 #endif /* HAVE_SETGROUPS */
242 #endif /* HAVE_INITGROUPS */
245 #if (defined(SecureWare) && defined(SCO))
246 /* This is needed due to needing the nap() function but we don't want
247 to include the Xenix libraries since that will break other things...
248 BTW: system call # 0x0c28 is the same as calling nap() */
249 long nap(long milliseconds) {
250 return syscall(0x0c28, milliseconds);
256 /*******************************************************************
257 safely copies memory, ensuring no overlap problems.
258 this is only used if the machine does not have it's own memmove().
259 this is not the fastest algorithm in town, but it will do for our
261 ********************************************************************/
262 void *memmove(void *dest,const void *src,int size)
266 if (dest==src || !size) return(dest);
268 d = (unsigned long)dest;
269 s = (unsigned long)src;
271 if ((d >= (s+size)) || (s >= (d+size))) {
273 memcpy(dest,src,size);
278 /* we can forward copy */
279 if (s-d >= sizeof(int) &&
282 !(size%sizeof(int))) {
283 /* do it all as words */
284 int *idest = (int *)dest;
285 int *isrc = (int *)src;
287 for (i=0;i<size;i++) idest[i] = isrc[i];
290 char *cdest = (char *)dest;
291 char *csrc = (char *)src;
292 for (i=0;i<size;i++) cdest[i] = csrc[i];
295 /* must backward copy */
296 if (d-s >= sizeof(int) &&
299 !(size%sizeof(int))) {
300 /* do it all as words */
301 int *idest = (int *)dest;
302 int *isrc = (int *)src;
304 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
307 char *cdest = (char *)dest;
308 char *csrc = (char *)src;
309 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
314 #endif /* HAVE_MEMMOVE */
317 /****************************************************************************
319 ****************************************************************************/
320 char *strdup(const char *s)
325 if (!s) return(NULL);
328 ret = (char *)malloc(len);
329 if (!ret) return(NULL);
333 #endif /* HAVE_STRDUP */
335 #ifndef WITH_PTHREADS
336 /* REWRITE: not thread safe */
337 #ifdef REPLACE_INET_NTOA
338 char *rep_inet_ntoa(struct in_addr ip)
340 uint8_t *p = (uint8_t *)&ip.s_addr;
342 slprintf(buf, 17, "%d.%d.%d.%d",
343 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
346 #endif /* REPLACE_INET_NTOA */
349 #ifndef HAVE_SETLINEBUF
350 int setlinebuf(FILE *stream)
352 return setvbuf(stream, (char *)NULL, _IOLBF, 0);
354 #endif /* HAVE_SETLINEBUF */
358 void vsyslog (int facility_priority, char *format, va_list arglist)
361 vasprintf(&msg, format, arglist);
364 syslog(facility_priority, "%s", msg);
367 #endif /* HAVE_SYSLOG */
368 #endif /* HAVE_VSYSLOG */
373 yes, I know this looks insane, but its really needed. The function in the
374 Linux timegm() manpage does not work on solaris.
376 time_t timegm(struct tm *tm)
378 time_t t = mktime(tm);
379 t -= mktime(gmtime(&t)) - (int)mktime(localtime(&t));
385 int setenv(const char *name, const char *value, int overwrite)
390 asprintf(&p, "%s=%s", name, value);
392 if (overwrite || getenv(name)) {
393 if (p) ret = putenv(p);
403 #ifndef HAVE_STRTOULL
404 unsigned long long int strtoull(const char *str, char **endptr, int base)
407 return strtouq(str, endptr, base);
408 #elif defined(HAVE___STRTOULL)
409 return __strtoull(str, endptr, base);
411 # error "You need a strtoull function"
417 long long int strtoll(const char *str, char **endptr, int base)
420 return strtoq(str, endptr, base);
421 #elif defined(HAVE___STRTOLL)
422 return __strtoll(str, endptr, base);
424 # error "You need a strtoll function"
432 Some platforms don't have strndup.
434 char *strndup(const char *s, size_t n)
451 Some platforms don't have strnlen
453 size_t strnlen(const char *s, size_t n)
456 for (i=0; s[i] && i<n; i++)
463 int waitpid(pid_t pid,int *status,int options)
465 return wait4(pid, status, options, NULL);
470 int seteuid(uid_t euid)
472 #ifdef HAVE_SETRESUID
473 return setresuid(-1, euid, -1);
475 # error "You need a seteuid function"
481 int setegid(gid_t egid)
483 #ifdef HAVE_SETRESGID
484 return setresgid(-1, egid, -1);
486 # error "You need a setegid function"
491 /*******************************************************************
492 os/2 also doesn't have chroot
493 ********************************************************************/
495 int chroot(const char *dname)
502 /*****************************************************************
503 Possibly replace mkstemp if it is broken.
504 *****************************************************************/
506 #ifndef HAVE_SECURE_MKSTEMP
507 int rep_mkstemp(char *template)
509 /* have a reasonable go at emulating it. Hope that
510 the system mktemp() isn't completly hopeless */
511 char *p = mktemp(template);
514 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
519 static ssize_t pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
521 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
524 return read(__fd, __buf, __nbytes);
529 static ssize_t pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
531 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
534 return write(__fd, __buf, __nbytes);
538 #ifndef HAVE_STRCASESTR
539 char *strcasestr(const char *haystack, const char *needle)
542 size_t nlen = strlen(needle);
543 for (s=haystack;*s;s++) {
544 if (toupper(*needle) == toupper(*s) &&
545 strncasecmp(s, needle, nlen) == 0) {
546 return discard_const_p(char, s);
553 #ifndef HAVE_STRTOK_R
554 /* based on GLIBC version, copyright Free Software Foundation */
555 char *strtok_r(char *s, const char *delim, char **save_ptr)
559 if (s == NULL) s = *save_ptr;
561 s += strspn(s, delim);
568 s = strpbrk(token, delim);
570 *save_ptr = token + strlen(token);