2 Unix SMB/Netbios implementation.
4 replacement routines for broken systems
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern int DEBUGLEVEL
;
26 void replace_dummy(void);
27 void replace_dummy(void) {}
30 #ifndef HAVE_FTRUNCATE
31 /*******************************************************************
32 ftruncate for operating systems that don't have it
33 ********************************************************************/
34 int ftruncate(int f
,SMB_OFF_T l
)
42 return fcntl(f
, F_FREESP
, &fl
);
44 #endif /* HAVE_FTRUNCATE */
48 /*******************************************************************
49 a mktime() replacement for those who don't have it - contributed by
50 C.A. Lademann <cal@zls.com>
51 Corrections by richard.kettlewell@kewill.com
52 ********************************************************************/
55 #define HOUR 60*MINUTE
58 time_t mktime(struct tm
*t
)
63 int mon
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
69 n
= t
->tm_year
+ 1900 - 1;
70 epoch
= (t
->tm_year
- 70) * YEAR
+
71 ((n
/ 4 - n
/ 100 + n
/ 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY
;
73 y
= t
->tm_year
+ 1900;
76 for(i
= 0; i
< t
->tm_mon
; i
++) {
77 epoch
+= mon
[m
] * DAY
;
78 if(m
== 1 && y
% 4 == 0 && (y
% 100 != 0 || y
% 400 == 0))
87 epoch
+= (t
->tm_mday
- 1) * DAY
;
88 epoch
+= t
->tm_hour
* HOUR
+ t
->tm_min
* MINUTE
+ t
->tm_sec
;
90 if((u
= localtime(&epoch
)) != NULL
) {
91 t
->tm_sec
= u
->tm_sec
;
92 t
->tm_min
= u
->tm_min
;
93 t
->tm_hour
= u
->tm_hour
;
94 t
->tm_mday
= u
->tm_mday
;
95 t
->tm_mon
= u
->tm_mon
;
96 t
->tm_year
= u
->tm_year
;
97 t
->tm_wday
= u
->tm_wday
;
98 t
->tm_yday
= u
->tm_yday
;
99 t
->tm_isdst
= u
->tm_isdst
;
104 #endif /* !HAVE_MKTIME */
109 /* Rename a file. (from libiberty in GNU binutils) */
110 int rename(const char *zfrom
, const char *zto
)
112 if (link (zfrom
, zto
) < 0)
117 || link (zfrom
, zto
) < 0)
120 return unlink (zfrom
);
122 #endif /* HAVE_RENAME */
126 #if defined(HAVE_SETNETGRENT) && defined(HAVE_GETNETGRENT) && defined(HAVE_ENDNETGRENT)
128 * Search for a match in a netgroup. This replaces it on broken systems.
130 int innetgr(char *group
,char *host
,char *user
,char *dom
)
132 char *hst
, *usr
, *dm
;
135 while (getnetgrent(&hst
, &usr
, &dm
)) {
136 if (((host
== 0) || (hst
== 0) || !strcmp(host
, hst
)) &&
137 ((user
== 0) || (usr
== 0) || !strcmp(user
, usr
)) &&
138 ((dom
== 0) || (dm
== 0) || !strcmp(dom
, dm
))) {
146 #endif /* HAVE_SETNETGRENT HAVE_GETNETGRENT HAVE_ENDNETGRENT */
147 #endif /* HAVE_INNETGR */
151 #ifndef HAVE_INITGROUPS
152 /****************************************************************************
153 some systems don't have an initgroups call
154 ****************************************************************************/
155 int initgroups(char *name
,gid_t id
)
157 #ifndef HAVE_SETGROUPS
160 DEBUG(1,("WARNING: running without setgroups\n"));
163 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
165 #else /* HAVE_SETGROUPS */
166 gid_t
*grouplst
= NULL
;
167 int max_gr
= groups_max();
173 if((grouplst
= (gid_t
*)malloc(sizeof(gid_t
) * max_gr
)) == NULL
) {
174 DEBUG(0,("initgroups: malloc fail !\n"));
180 while (i
< max_gr
&& ((g
= (struct group
*)getgrent()) != (struct group
*)NULL
)) {
185 while (gr
&& (*gr
!= (char)NULL
)) {
186 if (strcmp(name
,gr
) == 0) {
187 grouplst
[i
] = g
->gr_gid
;
196 ret
= sys_setgroups(i
,grouplst
);
197 free((char *)grouplst
);
199 #endif /* HAVE_SETGROUPS */
201 #endif /* HAVE_INITGROUPS */
204 #if (defined(SecureWare) && defined(SCO))
205 /* This is needed due to needing the nap() function but we don't want
206 to include the Xenix libraries since that will break other things...
207 BTW: system call # 0x0c28 is the same as calling nap() */
208 long nap(long milliseconds
) {
209 return syscall(0x0c28, milliseconds
);
215 /*******************************************************************
216 safely copies memory, ensuring no overlap problems.
217 this is only used if the machine does not have it's own memmove().
218 this is not the fastest algorithm in town, but it will do for our
220 ********************************************************************/
221 void *memmove(void *dest
,const void *src
,int size
)
225 if (dest
==src
|| !size
) return(dest
);
227 d
= (unsigned long)dest
;
228 s
= (unsigned long)src
;
230 if ((d
>= (s
+size
)) || (s
>= (d
+size
))) {
232 memcpy(dest
,src
,size
);
237 /* we can forward copy */
238 if (s
-d
>= sizeof(int) &&
241 !(size
%sizeof(int))) {
242 /* do it all as words */
243 int *idest
= (int *)dest
;
244 int *isrc
= (int *)src
;
246 for (i
=0;i
<size
;i
++) idest
[i
] = isrc
[i
];
249 char *cdest
= (char *)dest
;
250 char *csrc
= (char *)src
;
251 for (i
=0;i
<size
;i
++) cdest
[i
] = csrc
[i
];
254 /* must backward copy */
255 if (d
-s
>= sizeof(int) &&
258 !(size
%sizeof(int))) {
259 /* do it all as words */
260 int *idest
= (int *)dest
;
261 int *isrc
= (int *)src
;
263 for (i
=size
-1;i
>=0;i
--) idest
[i
] = isrc
[i
];
266 char *cdest
= (char *)dest
;
267 char *csrc
= (char *)src
;
268 for (i
=size
-1;i
>=0;i
--) cdest
[i
] = csrc
[i
];
273 #endif /* HAVE_MEMMOVE */
276 /****************************************************************************
278 ****************************************************************************/
279 char *strdup(const char *s
)
284 if (!s
) return(NULL
);
287 ret
= (char *)malloc(len
);
288 if (!ret
) return(NULL
);
292 #endif /* HAVE_STRDUP */
294 #ifdef REPLACE_INET_NTOA
295 char *rep_inet_ntoa(struct in_addr ip
)
297 unsigned char *p
= (unsigned char *)&ip
.s_addr
;
300 slprintf(buf
, 17, "%d.%d.%d.%d",
301 (int)p
[0], (int)p
[1], (int)p
[2], (int)p
[3]);
302 #else /* WORDS_BIGENDIAN */
303 slprintf(buf
, 17, "%d.%d.%d.%d",
304 (int)p
[3], (int)p
[2], (int)p
[1], (int)p
[0]);
305 #endif /* WORDS_BIGENDIAN */
308 #endif /* REPLACE_INET_NTOA */
312 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
316 * Convert a string to an unsigned long integer.
317 * Taken from libg++ - libiberty code.
319 * Ignores `locale' stuff. Assumes that the upper and lower case
320 * alphabets and digits are each contiguous.
322 unsigned long strtoul(const char *nptr
, char **endptr
, int base
)
324 const char *s
= nptr
;
327 unsigned long cutoff
;
328 int neg
= 0, any
, cutlim
;
331 * See strtol for comments as to the logic used.
335 } while (isspace(c
));
341 if ((base
== 0 || base
== 16) &&
342 c
== '0' && (*s
== 'x' || *s
== 'X')) {
348 base
= c
== '0' ? 8 : 10;
349 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
350 cutlim
= (int)((unsigned long)ULONG_MAX
% (unsigned long)base
);
351 for (acc
= 0, any
= 0;; c
= *s
++) {
355 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
360 if (any
< 0 || acc
> cutoff
|| acc
== cutoff
&& c
> cutlim
)
374 *endptr
= (char *) (any
? s
- 1 : nptr
);
377 #endif /* HAVE_STRTOUL */
379 #ifndef HAVE_SETLINEBUF
380 int setlinebuf(FILE *stream
)
382 return setvbuf(stream
, (char *)NULL
, _IOLBF
, 0);
384 #endif /* HAVE_SETLINEBUF */