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