tclUnixCompat.cGo to the documentation of this file.00001 /* 00002 * tclUnixCompat.c 00003 * 00004 * Written by: Zoran Vasiljevic (vasiljevic@users.sourceforge.net). 00005 * 00006 * See the file "license.terms" for information on usage and redistribution of 00007 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 00008 * 00009 * RCS: @(#) $Id: tclUnixCompat.c,v 1.13 2007/12/13 15:28:42 dgp Exp $ 00010 * 00011 */ 00012 00013 #include "tclInt.h" 00014 #include <pwd.h> 00015 #include <grp.h> 00016 #include <errno.h> 00017 #include <string.h> 00018 00019 /* 00020 * Used to pad structures at size'd boundaries 00021 * 00022 * This macro assumes that the pointer 'buffer' was created from an aligned 00023 * pointer by adding the 'length'. If this 'length' was not a multiple of the 00024 * 'size' the result is unaligned and PadBuffer corrects both the pointer, 00025 * _and_ the 'length'. The latter means that future increments of 'buffer' by 00026 * 'length' stay aligned. 00027 */ 00028 00029 #define PadBuffer(buffer, length, size) \ 00030 if (((length) % (size))) { \ 00031 (buffer) += ((size) - ((length) % (size))); \ 00032 (length) += ((size) - ((length) % (size))); \ 00033 } 00034 00035 /* 00036 * Per-thread private storage used to store values returned from MT-unsafe 00037 * library calls. 00038 */ 00039 00040 #ifdef TCL_THREADS 00041 00042 typedef struct ThreadSpecificData { 00043 struct passwd pwd; 00044 char pbuf[2048]; 00045 00046 struct group grp; 00047 char gbuf[2048]; 00048 00049 #if !defined(HAVE_MTSAFE_GETHOSTBYNAME) || !defined(HAVE_MTSAFE_GETHOSTBYADDR) 00050 struct hostent hent; 00051 char hbuf[2048]; 00052 #endif 00053 } ThreadSpecificData; 00054 static Tcl_ThreadDataKey dataKey; 00055 00056 #if ((!defined(HAVE_GETHOSTBYNAME_R) || !defined(HAVE_GETHOSTBYADDR_R)) && \ 00057 (!defined(HAVE_MTSAFE_GETHOSTBYNAME) || \ 00058 !defined(HAVE_MTSAFE_GETHOSTBYADDR))) || \ 00059 !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || \ 00060 !defined(HAVE_GETGRNAM_R) || !defined(HAVE_GETGRGID_R) 00061 /* 00062 * Mutex to lock access to MT-unsafe calls. This is just to protect our own 00063 * usage. It does not protect us from others calling the same functions 00064 * without (or using some different) lock. 00065 */ 00066 00067 static Tcl_Mutex compatLock; 00068 00069 /* 00070 * Helper function declarations. Note that these are only used if needed and 00071 * only defined if used (via the NEED_* macros). 00072 */ 00073 00074 #undef NEED_COPYARRAY 00075 #undef NEED_COPYGRP 00076 #undef NEED_COPYHOSTENT 00077 #undef NEED_COPYPWD 00078 #undef NEED_COPYSTRING 00079 00080 static int CopyArray(char **src, int elsize, char *buf, 00081 int buflen); 00082 static int CopyGrp(struct group *tgtPtr, char *buf, int buflen); 00083 static int CopyHostent(struct hostent *tgtPtr, char *buf, 00084 int buflen); 00085 static int CopyPwd(struct passwd *tgtPtr, char *buf, int buflen); 00086 static int CopyString(char *src, char *buf, int buflen); 00087 00088 #endif 00089 #endif /* TCL_THREADS */ 00090 00091 /* 00092 *--------------------------------------------------------------------------- 00093 * 00094 * TclpGetPwNam -- 00095 * 00096 * Thread-safe wrappers for getpwnam(). See "man getpwnam" for more 00097 * details. 00098 * 00099 * Results: 00100 * Pointer to struct passwd on success or NULL on error. 00101 * 00102 * Side effects: 00103 * None. 00104 * 00105 *--------------------------------------------------------------------------- 00106 */ 00107 00108 struct passwd * 00109 TclpGetPwNam( 00110 const char *name) 00111 { 00112 #if !defined(TCL_THREADS) 00113 return getpwnam(name); 00114 #else 00115 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 00116 00117 #if defined(HAVE_GETPWNAM_R_5) 00118 struct passwd *pwPtr = NULL; 00119 00120 return (getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf), 00121 &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL; 00122 00123 #elif defined(HAVE_GETPWNAM_R_4) 00124 return getpwnam_r(name, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)); 00125 00126 #else 00127 #define NEED_COPYPWD 1 00128 struct passwd *pwPtr; 00129 00130 Tcl_MutexLock(&compatLock); 00131 pwPtr = getpwnam(name); 00132 if (pwPtr != NULL) { 00133 tsdPtr->pwd = *pwPtr; 00134 pwPtr = &tsdPtr->pwd; 00135 if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) { 00136 pwPtr = NULL; 00137 } 00138 } 00139 Tcl_MutexUnlock(&compatLock); 00140 return pwPtr; 00141 #endif 00142 00143 return NULL; /* Not reached. */ 00144 #endif /* TCL_THREADS */ 00145 } 00146 00147 /* 00148 *--------------------------------------------------------------------------- 00149 * 00150 * TclpGetPwUid -- 00151 * 00152 * Thread-safe wrappers for getpwuid(). See "man getpwuid" for more 00153 * details. 00154 * 00155 * Results: 00156 * Pointer to struct passwd on success or NULL on error. 00157 * 00158 * Side effects: 00159 * None. 00160 * 00161 *--------------------------------------------------------------------------- 00162 */ 00163 00164 struct passwd * 00165 TclpGetPwUid( 00166 uid_t uid) 00167 { 00168 #if !defined(TCL_THREADS) 00169 return getpwuid(uid); 00170 #else 00171 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 00172 00173 #if defined(HAVE_GETPWUID_R_5) 00174 struct passwd *pwPtr = NULL; 00175 00176 return (getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf), 00177 &pwPtr) == 0 && pwPtr != NULL) ? &tsdPtr->pwd : NULL; 00178 00179 #elif defined(HAVE_GETPWUID_R_4) 00180 return getpwuid_r(uid, &tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)); 00181 00182 #else 00183 #define NEED_COPYPWD 1 00184 struct passwd *pwPtr; 00185 00186 Tcl_MutexLock(&compatLock); 00187 pwPtr = getpwuid(uid); 00188 if (pwPtr != NULL) { 00189 tsdPtr->pwd = *pwPtr; 00190 pwPtr = &tsdPtr->pwd; 00191 if (CopyPwd(&tsdPtr->pwd, tsdPtr->pbuf, sizeof(tsdPtr->pbuf)) == -1) { 00192 pwPtr = NULL; 00193 } 00194 } 00195 Tcl_MutexUnlock(&compatLock); 00196 return pwPtr; 00197 #endif 00198 00199 return NULL; /* Not reached. */ 00200 #endif /* TCL_THREADS */ 00201 } 00202 00203 /* 00204 *--------------------------------------------------------------------------- 00205 * 00206 * TclpGetGrNam -- 00207 * 00208 * Thread-safe wrappers for getgrnam(). See "man getgrnam" for more 00209 * details. 00210 * 00211 * Results: 00212 * Pointer to struct group on success or NULL on error. 00213 * 00214 * Side effects: 00215 * None. 00216 * 00217 *--------------------------------------------------------------------------- 00218 */ 00219 00220 struct group * 00221 TclpGetGrNam( 00222 const char *name) 00223 { 00224 #if !defined(TCL_THREADS) 00225 return getgrnam(name); 00226 #else 00227 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 00228 00229 #if defined(HAVE_GETGRNAM_R_5) 00230 struct group *grPtr = NULL; 00231 00232 return (getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf), 00233 &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL; 00234 00235 #elif defined(HAVE_GETGRNAM_R_4) 00236 return getgrnam_r(name, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)); 00237 00238 #else 00239 #define NEED_COPYGRP 1 00240 struct group *grPtr; 00241 00242 Tcl_MutexLock(&compatLock); 00243 grPtr = getgrnam(name); 00244 if (grPtr != NULL) { 00245 tsdPtr->grp = *grPtr; 00246 grPtr = &tsdPtr->grp; 00247 if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) { 00248 grPtr = NULL; 00249 } 00250 } 00251 Tcl_MutexUnlock(&compatLock); 00252 return grPtr; 00253 #endif 00254 00255 return NULL; /* Not reached. */ 00256 #endif /* TCL_THREADS */ 00257 } 00258 00259 /* 00260 *--------------------------------------------------------------------------- 00261 * 00262 * TclpGetGrGid -- 00263 * 00264 * Thread-safe wrappers for getgrgid(). See "man getgrgid" for more 00265 * details. 00266 * 00267 * Results: 00268 * Pointer to struct group on success or NULL on error. 00269 * 00270 * Side effects: 00271 * None. 00272 * 00273 *--------------------------------------------------------------------------- 00274 */ 00275 00276 struct group * 00277 TclpGetGrGid( 00278 gid_t gid) 00279 { 00280 #if !defined(TCL_THREADS) 00281 return getgrgid(gid); 00282 #else 00283 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 00284 00285 #if defined(HAVE_GETGRGID_R_5) 00286 struct group *grPtr = NULL; 00287 00288 return (getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf), 00289 &grPtr) == 0 && grPtr != NULL) ? &tsdPtr->grp : NULL; 00290 00291 #elif defined(HAVE_GETGRGID_R_4) 00292 return getgrgid_r(gid, &tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)); 00293 00294 #else 00295 #define NEED_COPYGRP 1 00296 struct group *grPtr; 00297 00298 Tcl_MutexLock(&compatLock); 00299 grPtr = getgrgid(gid); 00300 if (grPtr != NULL) { 00301 tsdPtr->grp = *grPtr; 00302 grPtr = &tsdPtr->grp; 00303 if (CopyGrp(&tsdPtr->grp, tsdPtr->gbuf, sizeof(tsdPtr->gbuf)) == -1) { 00304 grPtr = NULL; 00305 } 00306 } 00307 Tcl_MutexUnlock(&compatLock); 00308 return grPtr; 00309 #endif 00310 00311 return NULL; /* Not reached. */ 00312 #endif /* TCL_THREADS */ 00313 } 00314 00315 /* 00316 *--------------------------------------------------------------------------- 00317 * 00318 * TclpGetHostByName -- 00319 * 00320 * Thread-safe wrappers for gethostbyname(). See "man gethostbyname" for 00321 * more details. 00322 * 00323 * Results: 00324 * Pointer to struct hostent on success or NULL on error. 00325 * 00326 * Side effects: 00327 * None. 00328 * 00329 *--------------------------------------------------------------------------- 00330 */ 00331 00332 struct hostent * 00333 TclpGetHostByName( 00334 const char *name) 00335 { 00336 #if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYNAME) 00337 return gethostbyname(name); 00338 #else 00339 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 00340 00341 #if defined(HAVE_GETHOSTBYNAME_R_5) 00342 int h_errno; 00343 00344 return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf, 00345 sizeof(tsdPtr->hbuf), &h_errno); 00346 00347 #elif defined(HAVE_GETHOSTBYNAME_R_6) 00348 struct hostent *hePtr = NULL; 00349 int h_errno, result; 00350 00351 result = gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf, 00352 sizeof(tsdPtr->hbuf), &hePtr, &h_errno); 00353 return (result == 0) ? hePtr : NULL; 00354 00355 #elif defined(HAVE_GETHOSTBYNAME_R_3) 00356 struct hostent_data data; 00357 00358 return (gethostbyname_r(name, &tsdPtr->hent, &data) == 0) 00359 ? &tsdPtr->hent : NULL; 00360 00361 #else 00362 #define NEED_COPYHOSTENT 1 00363 struct hostent *hePtr; 00364 00365 Tcl_MutexLock(&compatLock); 00366 hePtr = gethostbyname(name); 00367 if (hePtr != NULL) { 00368 tsdPtr->hent = *hePtr; 00369 hePtr = &tsdPtr->hent; 00370 if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf, 00371 sizeof(tsdPtr->hbuf)) == -1) { 00372 hePtr = NULL; 00373 } 00374 } 00375 Tcl_MutexUnlock(&compatLock); 00376 return hePtr; 00377 #endif 00378 00379 return NULL; /* Not reached. */ 00380 #endif /* TCL_THREADS */ 00381 } 00382 00383 /* 00384 *--------------------------------------------------------------------------- 00385 * 00386 * TclpGetHostByAddr -- 00387 * 00388 * Thread-safe wrappers for gethostbyaddr(). See "man gethostbyaddr" for 00389 * more details. 00390 * 00391 * Results: 00392 * Pointer to struct hostent on success or NULL on error. 00393 * 00394 * Side effects: 00395 * None. 00396 * 00397 *--------------------------------------------------------------------------- 00398 */ 00399 00400 struct hostent * 00401 TclpGetHostByAddr( 00402 const char *addr, 00403 int length, 00404 int type) 00405 { 00406 #if !defined(TCL_THREADS) || defined(HAVE_MTSAFE_GETHOSTBYADDR) 00407 return gethostbyaddr(addr, length, type); 00408 #else 00409 ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); 00410 00411 #if defined(HAVE_GETHOSTBYADDR_R_7) 00412 int h_errno; 00413 00414 return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf, 00415 sizeof(tsdPtr->hbuf), &h_errno); 00416 00417 #elif defined(HAVE_GETHOSTBYADDR_R_8) 00418 struct hostent *hePtr; 00419 int h_errno; 00420 00421 return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf, 00422 sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0) 00423 ? &tsdPtr->hent : NULL; 00424 #else 00425 #define NEED_COPYHOSTENT 1 00426 struct hostent *hePtr; 00427 00428 Tcl_MutexLock(&compatLock); 00429 hePtr = gethostbyaddr(addr, length, type); 00430 if (hePtr != NULL) { 00431 tsdPtr->hent = *hePtr; 00432 hePtr = &tsdPtr->hent; 00433 if (CopyHostent(&tsdPtr->hent, tsdPtr->hbuf, 00434 sizeof(tsdPtr->hbuf)) == -1) { 00435 hePtr = NULL; 00436 } 00437 } 00438 Tcl_MutexUnlock(&compatLock); 00439 return hePtr; 00440 #endif 00441 00442 return NULL; /* Not reached. */ 00443 #endif /* TCL_THREADS */ 00444 } 00445 00446 /* 00447 *--------------------------------------------------------------------------- 00448 * 00449 * CopyGrp -- 00450 * 00451 * Copies string fields of the group structure to the private buffer, 00452 * honouring the size of the buffer. 00453 * 00454 * Results: 00455 * 0 on success or -1 on error (errno = ERANGE). 00456 * 00457 * Side effects: 00458 * None. 00459 * 00460 *--------------------------------------------------------------------------- 00461 */ 00462 00463 #ifdef NEED_COPYGRP 00464 #define NEED_COPYARRAY 1 00465 #define NEED_COPYSTRING 1 00466 00467 static int 00468 CopyGrp( 00469 struct group *tgtPtr, 00470 char *buf, 00471 int buflen) 00472 { 00473 register char *p = buf; 00474 register int copied, len = 0; 00475 00476 /* 00477 * Copy username. 00478 */ 00479 00480 copied = CopyString(tgtPtr->gr_name, p, buflen - len); 00481 if (copied == -1) { 00482 goto range; 00483 } 00484 tgtPtr->gr_name = (copied > 0) ? p : NULL; 00485 len += copied; 00486 p = buf + len; 00487 00488 /* 00489 * Copy password. 00490 */ 00491 00492 copied = CopyString(tgtPtr->gr_passwd, p, buflen - len); 00493 if (copied == -1) { 00494 goto range; 00495 } 00496 tgtPtr->gr_passwd = (copied > 0) ? p : NULL; 00497 len += copied; 00498 p = buf + len; 00499 00500 /* 00501 * Copy group members. 00502 */ 00503 00504 PadBuffer(p, len, sizeof(char *)); 00505 copied = CopyArray((char **)tgtPtr->gr_mem, -1, p, buflen - len); 00506 if (copied == -1) { 00507 goto range; 00508 } 00509 tgtPtr->gr_mem = (copied > 0) ? (char **)p : NULL; 00510 00511 return 0; 00512 00513 range: 00514 errno = ERANGE; 00515 return -1; 00516 } 00517 #endif /* NEED_COPYGRP */ 00518 00519 /* 00520 *--------------------------------------------------------------------------- 00521 * 00522 * CopyHostent -- 00523 * 00524 * Copies string fields of the hostnent structure to the private buffer, 00525 * honouring the size of the buffer. 00526 * 00527 * Results: 00528 * Number of bytes copied on success or -1 on error (errno = ERANGE) 00529 * 00530 * Side effects: 00531 * None 00532 * 00533 *--------------------------------------------------------------------------- 00534 */ 00535 00536 #ifdef NEED_COPYHOSTENT 00537 #define NEED_COPYSTRING 1 00538 #define NEED_COPYARRAY 1 00539 00540 static int 00541 CopyHostent( 00542 struct hostent *tgtPtr, 00543 char *buf, 00544 int buflen) 00545 { 00546 char *p = buf; 00547 int copied, len = 0; 00548 00549 copied = CopyString(tgtPtr->h_name, p, buflen - len); 00550 if (copied == -1) { 00551 goto range; 00552 } 00553 tgtPtr->h_name = (copied > 0) ? p : NULL; 00554 len += copied; 00555 p = buf + len; 00556 00557 PadBuffer(p, len, sizeof(char *)); 00558 copied = CopyArray(tgtPtr->h_aliases, -1, p, buflen - len); 00559 if (copied == -1) { 00560 goto range; 00561 } 00562 tgtPtr->h_aliases = (copied > 0) ? (char **)p : NULL; 00563 len += copied; 00564 p += len; 00565 00566 PadBuffer(p, len, sizeof(char *)); 00567 copied = CopyArray(tgtPtr->h_addr_list, tgtPtr->h_length, p, buflen-len); 00568 if (copied == -1) { 00569 goto range; 00570 } 00571 tgtPtr->h_addr_list = (copied > 0) ? (char **)p : NULL; 00572 00573 return 0; 00574 00575 range: 00576 errno = ERANGE; 00577 return -1; 00578 } 00579 #endif /* NEED_COPYHOSTENT */ 00580 00581 /* 00582 *--------------------------------------------------------------------------- 00583 * 00584 * CopyPwd -- 00585 * 00586 * Copies string fields of the passwd structure to the private buffer, 00587 * honouring the size of the buffer. 00588 * 00589 * Results: 00590 * 0 on success or -1 on error (errno = ERANGE). 00591 * 00592 * Side effects: 00593 * We are not copying the gecos field as it may not be supported on all 00594 * platforms. 00595 * 00596 *--------------------------------------------------------------------------- 00597 */ 00598 00599 #ifdef NEED_COPYPWD 00600 #define NEED_COPYSTRING 1 00601 00602 static int 00603 CopyPwd( 00604 struct passwd *tgtPtr, 00605 char *buf, 00606 int buflen) 00607 { 00608 char *p = buf; 00609 int copied, len = 0; 00610 00611 copied = CopyString(tgtPtr->pw_name, p, buflen - len); 00612 if (copied == -1) { 00613 range: 00614 errno = ERANGE; 00615 return -1; 00616 } 00617 tgtPtr->pw_name = (copied > 0) ? p : NULL; 00618 len += copied; 00619 p = buf + len; 00620 00621 copied = CopyString(tgtPtr->pw_passwd, p, buflen - len); 00622 if (copied == -1) { 00623 goto range; 00624 } 00625 tgtPtr->pw_passwd = (copied > 0) ? p : NULL; 00626 len += copied; 00627 p = buf + len; 00628 00629 copied = CopyString(tgtPtr->pw_dir, p, buflen - len); 00630 if (copied == -1) { 00631 goto range; 00632 } 00633 tgtPtr->pw_dir = (copied > 0) ? p : NULL; 00634 len += copied; 00635 p = buf + len; 00636 00637 copied = CopyString(tgtPtr->pw_shell, p, buflen - len); 00638 if (copied == -1) { 00639 goto range; 00640 } 00641 tgtPtr->pw_shell = (copied > 0) ? p : NULL; 00642 00643 return 0; 00644 } 00645 #endif /* NEED_COPYPWD */ 00646 00647 /* 00648 *--------------------------------------------------------------------------- 00649 * 00650 * CopyArray -- 00651 * 00652 * Copies array of NULL-terminated or fixed-length strings to the private 00653 * buffer, honouring the size of the buffer. 00654 * 00655 * Results: 00656 * Number of bytes copied on success or -1 on error (errno = ERANGE) 00657 * 00658 * Side effects: 00659 * None. 00660 * 00661 *--------------------------------------------------------------------------- 00662 */ 00663 00664 #ifdef NEED_COPYARRAY 00665 static int 00666 CopyArray( 00667 char **src, /* Array of elements to copy. */ 00668 int elsize, /* Size of each element, or -1 to indicate 00669 * that they are C strings of dynamic 00670 * length. */ 00671 char *buf, /* Buffer to copy into. */ 00672 int buflen) /* Size of buffer. */ 00673 { 00674 int i, j, len = 0; 00675 char *p, **new; 00676 00677 if (src == NULL) { 00678 return 0; 00679 } 00680 00681 for (i = 0; src[i] != NULL; i++) { 00682 /* 00683 * Empty loop to count how many. 00684 */ 00685 } 00686 len = sizeof(char *) * (i + 1); /* Leave place for the array. */ 00687 if (len > buflen) { 00688 return -1; 00689 } 00690 00691 new = (char **) buf; 00692 p = buf + len; 00693 00694 for (j = 0; j < i; j++) { 00695 int sz = (elsize<0 ? strlen(src[j])+1 : elsize); 00696 00697 len += sz; 00698 if (len > buflen) { 00699 return -1; 00700 } 00701 memcpy(p, src[j], sz); 00702 new[j] = p; 00703 p = buf + len; 00704 } 00705 new[j] = NULL; 00706 00707 return len; 00708 } 00709 #endif /* NEED_COPYARRAY */ 00710 00711 /* 00712 *--------------------------------------------------------------------------- 00713 * 00714 * CopyString -- 00715 * 00716 * Copies a NULL-terminated string to the private buffer, honouring the 00717 * size of the buffer 00718 * 00719 * Results: 00720 * 0 success or -1 on error (errno = ERANGE) 00721 * 00722 * Side effects: 00723 * None 00724 * 00725 *--------------------------------------------------------------------------- 00726 */ 00727 00728 #ifdef NEED_COPYSTRING 00729 static int 00730 CopyString( 00731 char *src, /* String to copy. */ 00732 char *buf, /* Buffer to copy into. */ 00733 int buflen) /* Size of buffer. */ 00734 { 00735 int len = 0; 00736 00737 if (src != NULL) { 00738 len = strlen(src) + 1; 00739 if (len > buflen) { 00740 return -1; 00741 } 00742 memcpy(buf, src, len); 00743 } 00744 00745 return len; 00746 } 00747 #endif /* NEED_COPYSTRING */ 00748 00749 /* 00750 * Local Variables: 00751 * mode: c 00752 * c-basic-offset: 4 00753 * fill-column: 78 00754 * End: 00755 */
Generated on Wed Mar 12 12:18:26 2008 by 1.5.1 |