source: trunk/samba-3.0.25pre1/source/lib/replace/replace.c@ 1

Last change on this file since 1 was 1, checked in by Paul Smedley, 19 years ago

Initial code import

File size: 13.4 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 replacement routines for broken systems
4 Copyright (C) Andrew Tridgell 1992-1998
5
6 ** NOTE! The following LGPL license applies to the replace
7 ** library. This does NOT imply that all of Samba is released
8 ** under the LGPL
9
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
14
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23*/
24
25#include "replace.h"
26
27#include "system/filesys.h"
28#include "system/time.h"
29#include "system/passwd.h"
30#include "system/syslog.h"
31#include "system/network.h"
32#include "system/locale.h"
33#include "system/wait.h"
34
35void replace_dummy(void);
36void replace_dummy(void) {}
37
38#ifndef HAVE_FTRUNCATE
39 /*******************************************************************
40ftruncate for operating systems that don't have it
41********************************************************************/
42int rep_ftruncate(int f, off_t l)
43{
44#ifdef HAVE_CHSIZE
45 return chsize(f,l);
46#elif defined(F_FREESP)
47 struct flock fl;
48
49 fl.l_whence = 0;
50 fl.l_len = 0;
51 fl.l_start = l;
52 fl.l_type = F_WRLCK;
53 return fcntl(f, F_FREESP, &fl);
54#else
55#error "you must have a ftruncate function"
56#endif
57}
58#endif /* HAVE_FTRUNCATE */
59
60
61#ifndef HAVE_STRLCPY
62/* like strncpy but does not 0 fill the buffer and always null
63 terminates. bufsize is the size of the destination buffer */
64size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
65{
66 size_t len = strlen(s);
67 size_t ret = len;
68 if (bufsize <= 0) return 0;
69 if (len >= bufsize) len = bufsize-1;
70 memcpy(d, s, len);
71 d[len] = 0;
72 return ret;
73}
74#endif
75
76#ifndef HAVE_STRLCAT
77/* like strncat but does not 0 fill the buffer and always null
78 terminates. bufsize is the length of the buffer, which should
79 be one more than the maximum resulting string length */
80size_t rep_strlcat(char *d, const char *s, size_t bufsize)
81{
82 size_t len1 = strlen(d);
83 size_t len2 = strlen(s);
84 size_t ret = len1 + len2;
85
86 if (len1+len2 >= bufsize) {
87 len2 = bufsize - (len1+1);
88 }
89 if (len2 > 0) {
90 memcpy(d+len1, s, len2);
91 d[len1+len2] = 0;
92 }
93 return ret;
94}
95#endif
96
97#ifndef HAVE_MKTIME
98/*******************************************************************
99a mktime() replacement for those who don't have it - contributed by
100C.A. Lademann <[email protected]>
101Corrections by [email protected]
102********************************************************************/
103
104#define MINUTE 60
105#define HOUR 60*MINUTE
106#define DAY 24*HOUR
107#define YEAR 365*DAY
108time_t rep_mktime(struct tm *t)
109{
110 struct tm *u;
111 time_t epoch = 0;
112 int n;
113 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
114 y, m, i;
115
116 if(t->tm_year < 70)
117 return((time_t)-1);
118
119 n = t->tm_year + 1900 - 1;
120 epoch = (t->tm_year - 70) * YEAR +
121 ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
122
123 y = t->tm_year + 1900;
124 m = 0;
125
126 for(i = 0; i < t->tm_mon; i++) {
127 epoch += mon [m] * DAY;
128 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
129 epoch += DAY;
130
131 if(++m > 11) {
132 m = 0;
133 y++;
134 }
135 }
136
137 epoch += (t->tm_mday - 1) * DAY;
138 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
139
140 if((u = localtime(&epoch)) != NULL) {
141 t->tm_sec = u->tm_sec;
142 t->tm_min = u->tm_min;
143 t->tm_hour = u->tm_hour;
144 t->tm_mday = u->tm_mday;
145 t->tm_mon = u->tm_mon;
146 t->tm_year = u->tm_year;
147 t->tm_wday = u->tm_wday;
148 t->tm_yday = u->tm_yday;
149 t->tm_isdst = u->tm_isdst;
150 }
151
152 return(epoch);
153}
154#endif /* !HAVE_MKTIME */
155
156
157#ifndef HAVE_INNETGR
158#if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
159/*
160 * Search for a match in a netgroup. This replaces it on broken systems.
161 */
162int rep_innetgr(const char *group, const char *host, const char *user,
163 const char *dom)
164{
165 char *hst, *usr, *dm;
166
167 setnetgrent(group);
168 while (getnetgrent(&hst, &usr, &dm)) {
169 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
170 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
171 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
172 endnetgrent();
173 return (1);
174 }
175 }
176 endnetgrent();
177 return (0);
178}
179#endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
180#endif /* HAVE_INNETGR */
181
182
183
184#ifndef HAVE_INITGROUPS
185/****************************************************************************
186 some systems don't have an initgroups call
187****************************************************************************/
188int rep_initgroups(char *name, gid_t id)
189{
190#ifndef HAVE_SETGROUPS
191 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
192 errno = ENOSYS;
193 return -1;
194#else /* HAVE_SETGROUPS */
195
196#include <grp.h>
197
198 gid_t *grouplst = NULL;
199 int max_gr = 32;
200 int ret;
201 int i,j;
202 struct group *g;
203 char *gr;
204
205 if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
206 errno = ENOMEM;
207 return -1;
208 }
209
210 grouplst[0] = id;
211 i = 1;
212 while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
213 if (g->gr_gid == id)
214 continue;
215 j = 0;
216 gr = g->gr_mem[0];
217 while (gr && (*gr != (char)NULL)) {
218 if (strcmp(name,gr) == 0) {
219 grouplst[i] = g->gr_gid;
220 i++;
221 gr = (char *)NULL;
222 break;
223 }
224 gr = g->gr_mem[++j];
225 }
226 }
227 endgrent();
228 ret = setgroups(i, grouplst);
229 free(grouplst);
230 return ret;
231#endif /* HAVE_SETGROUPS */
232}
233#endif /* HAVE_INITGROUPS */
234
235
236#if (defined(SecureWare) && defined(SCO))
237/* This is needed due to needing the nap() function but we don't want
238 to include the Xenix libraries since that will break other things...
239 BTW: system call # 0x0c28 is the same as calling nap() */
240long nap(long milliseconds) {
241 return syscall(0x0c28, milliseconds);
242 }
243#endif
244
245
246#ifndef HAVE_MEMMOVE
247/*******************************************************************
248safely copies memory, ensuring no overlap problems.
249this is only used if the machine does not have it's own memmove().
250this is not the fastest algorithm in town, but it will do for our
251needs.
252********************************************************************/
253void *rep_memmove(void *dest,const void *src,int size)
254{
255 unsigned long d,s;
256 int i;
257 if (dest==src || !size) return(dest);
258
259 d = (unsigned long)dest;
260 s = (unsigned long)src;
261
262 if ((d >= (s+size)) || (s >= (d+size))) {
263 /* no overlap */
264 memcpy(dest,src,size);
265 return(dest);
266 }
267
268 if (d < s) {
269 /* we can forward copy */
270 if (s-d >= sizeof(int) &&
271 !(s%sizeof(int)) &&
272 !(d%sizeof(int)) &&
273 !(size%sizeof(int))) {
274 /* do it all as words */
275 int *idest = (int *)dest;
276 int *isrc = (int *)src;
277 size /= sizeof(int);
278 for (i=0;i<size;i++) idest[i] = isrc[i];
279 } else {
280 /* simplest */
281 char *cdest = (char *)dest;
282 char *csrc = (char *)src;
283 for (i=0;i<size;i++) cdest[i] = csrc[i];
284 }
285 } else {
286 /* must backward copy */
287 if (d-s >= sizeof(int) &&
288 !(s%sizeof(int)) &&
289 !(d%sizeof(int)) &&
290 !(size%sizeof(int))) {
291 /* do it all as words */
292 int *idest = (int *)dest;
293 int *isrc = (int *)src;
294 size /= sizeof(int);
295 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
296 } else {
297 /* simplest */
298 char *cdest = (char *)dest;
299 char *csrc = (char *)src;
300 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
301 }
302 }
303 return(dest);
304}
305#endif /* HAVE_MEMMOVE */
306
307#ifndef HAVE_STRDUP
308/****************************************************************************
309duplicate a string
310****************************************************************************/
311char *rep_strdup(const char *s)
312{
313 size_t len;
314 char *ret;
315
316 if (!s) return(NULL);
317
318 len = strlen(s)+1;
319 ret = (char *)malloc(len);
320 if (!ret) return(NULL);
321 memcpy(ret,s,len);
322 return(ret);
323}
324#endif /* HAVE_STRDUP */
325
326#ifndef WITH_PTHREADS
327/* REWRITE: not thread safe */
328#ifdef REPLACE_INET_NTOA
329char *rep_inet_ntoa(struct in_addr ip)
330{
331 uint8_t *p = (uint8_t *)&ip.s_addr;
332 static char buf[18];
333 slprintf(buf, 17, "%d.%d.%d.%d",
334 (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
335 return buf;
336}
337#endif /* REPLACE_INET_NTOA */
338#endif
339
340#ifndef HAVE_SETLINEBUF
341void rep_setlinebuf(FILE *stream)
342{
343 setvbuf(stream, (char *)NULL, _IOLBF, 0);
344}
345#endif /* HAVE_SETLINEBUF */
346
347#ifndef HAVE_VSYSLOG
348#ifdef HAVE_SYSLOG
349void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
350{
351 char *msg = NULL;
352 vasprintf(&msg, format, arglist);
353 if (!msg)
354 return;
355 syslog(facility_priority, "%s", msg);
356 free(msg);
357}
358#endif /* HAVE_SYSLOG */
359#endif /* HAVE_VSYSLOG */
360
361#ifndef HAVE_STRNLEN
362/**
363 Some platforms don't have strnlen
364**/
365 size_t rep_strnlen(const char *s, size_t max)
366{
367 size_t len;
368
369 for (len = 0; len < max; len++) {
370 if (s[len] == '\0') {
371 break;
372 }
373 }
374 return len;
375}
376#endif
377
378#ifndef HAVE_STRNDUP
379/**
380 Some platforms don't have strndup.
381**/
382char *rep_strndup(const char *s, size_t n)
383{
384 char *ret;
385
386 n = strnlen(s, n);
387 ret = malloc(n+1);
388 if (!ret)
389 return NULL;
390 memcpy(ret, s, n);
391 ret[n] = 0;
392
393 return ret;
394}
395#endif
396
397#ifndef HAVE_WAITPID
398int rep_waitpid(pid_t pid,int *status,int options)
399{
400 return wait4(pid, status, options, NULL);
401}
402#endif
403
404#ifndef HAVE_SETEUID
405int rep_seteuid(uid_t euid)
406{
407#ifdef HAVE_SETRESUID
408 return setresuid(-1, euid, -1);
409#else
410# error "You need a seteuid function"
411#endif
412}
413#endif
414
415#ifndef HAVE_SETEGID
416int rep_setegid(gid_t egid)
417{
418#ifdef HAVE_SETRESGID
419 return setresgid(-1, egid, -1);
420#else
421# error "You need a setegid function"
422#endif
423}
424#endif
425
426/*******************************************************************
427os/2 also doesn't have chroot
428********************************************************************/
429#ifndef HAVE_CHROOT
430int rep_chroot(const char *dname)
431{
432 errno = ENOSYS;
433 return -1;
434}
435#endif
436
437/*****************************************************************
438 Possibly replace mkstemp if it is broken.
439*****************************************************************/
440
441#ifndef HAVE_SECURE_MKSTEMP
442int rep_mkstemp(char *template)
443{
444 /* have a reasonable go at emulating it. Hope that
445 the system mktemp() isn't completly hopeless */
446 char *p = mktemp(template);
447 if (!p)
448 return -1;
449 return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
450}
451#endif
452
453#ifndef HAVE_MKDTEMP
454char *rep_mkdtemp(char *template)
455{
456 char *dname;
457
458 if ((dname = mktemp(template))) {
459 if (mkdir(dname, 0700) >= 0) {
460 return dname;
461 }
462 }
463
464 return NULL;
465}
466#endif
467
468#ifndef HAVE_PREAD
469ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
470{
471 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
472 return -1;
473 }
474 return read(__fd, __buf, __nbytes);
475}
476#endif
477
478#ifndef HAVE_PWRITE
479ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
480{
481 if (lseek(__fd, __offset, SEEK_SET) != __offset) {
482 return -1;
483 }
484 return write(__fd, __buf, __nbytes);
485}
486#endif
487
488#ifndef HAVE_STRCASESTR
489char *rep_strcasestr(const char *haystack, const char *needle)
490{
491 const char *s;
492 size_t nlen = strlen(needle);
493 for (s=haystack;*s;s++) {
494 if (toupper(*needle) == toupper(*s) &&
495 strncasecmp(s, needle, nlen) == 0) {
496 return (char *)((intptr_t)s);
497 }
498 }
499 return NULL;
500}
501#endif
502
503#ifndef HAVE_STRTOK_R
504/* based on GLIBC version, copyright Free Software Foundation */
505char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
506{
507 char *token;
508
509 if (s == NULL) s = *save_ptr;
510
511 s += strspn(s, delim);
512 if (*s == '\0') {
513 *save_ptr = s;
514 return NULL;
515 }
516
517 token = s;
518 s = strpbrk(token, delim);
519 if (s == NULL) {
520 *save_ptr = token + strlen(token);
521 } else {
522 *s = '\0';
523 *save_ptr = s + 1;
524 }
525
526 return token;
527}
528#endif
529
530#ifndef HAVE_STRTOLL
531long long int rep_strtoll(const char *str, char **endptr, int base)
532{
533#ifdef HAVE_STRTOQ
534 return strtoq(str, endptr, base);
535#elif defined(HAVE___STRTOLL)
536 return __strtoll(str, endptr, base);
537#elif SIZEOF_LONG == SIZEOF_LONG_LONG
538 return (long long int) strtol(str, endptr, base);
539#else
540# error "You need a strtoll function"
541#endif
542}
543#endif
544
545
546#ifndef HAVE_STRTOULL
547unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
548{
549#ifdef HAVE_STRTOUQ
550 return strtouq(str, endptr, base);
551#elif defined(HAVE___STRTOULL)
552 return __strtoull(str, endptr, base);
553#elif SIZEOF_LONG == SIZEOF_LONG_LONG
554 return (unsigned long long int) strtoul(str, endptr, base);
555#else
556# error "You need a strtoull function"
557#endif
558}
559#endif
560
561#ifndef HAVE_SETENV
562int rep_setenv(const char *name, const char *value, int overwrite)
563{
564 char *p;
565 size_t l1, l2;
566 int ret;
567
568 if (!overwrite && getenv(name)) {
569 return 0;
570 }
571
572 l1 = strlen(name);
573 l2 = strlen(value);
574
575 p = malloc(l1+l2+2);
576 if (p == NULL) {
577 return -1;
578 }
579 memcpy(p, name, l1);
580 p[l1] = '=';
581 memcpy(p+l1+1, value, l2);
582 p[l1+l2+1] = 0;
583
584 ret = putenv(p);
585 if (ret != 0) {
586 free(p);
587 }
588
589 return ret;
590}
591#endif
592
593#ifndef HAVE_SOCKETPAIR
594int rep_socketpair(int d, int type, int protocol, int sv[2])
595{
596 if (d != AF_UNIX) {
597 errno = EAFNOSUPPORT;
598 return -1;
599 }
600
601 if (protocol != 0) {
602 errno = EPROTONOSUPPORT;
603 return -1;
604 }
605
606 if (type != SOCK_STREAM) {
607 errno = EOPNOTSUPP;
608 return -1;
609 }
610
611 return pipe(sv);
612}
613#endif
Note: See TracBrowser for help on using the repository browser.