tclUnixCompat.c

Go 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  doxygen 1.5.1