00001
00002
00003
00004
00005 #include <u/libu_conf.h>
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <stdio.h>
00011 #include <time.h>
00012 #include <errno.h>
00013 #include <signal.h>
00014 #include <ctype.h>
00015 #include <fcntl.h>
00016 #include <unistd.h>
00017 #include <sys/types.h>
00018
00019 #include <toolbox/misc.h>
00020 #include <toolbox/carpal.h>
00021 #include <toolbox/memory.h>
00022
00041 inline int u_isblank (int c)
00042 {
00043 return c == ' ' || c == '\t';
00044 }
00045
00056 inline int u_isblank_str (const char *s)
00057 {
00058 for ( ; *s; ++s)
00059 {
00060 if (!u_isblank(*s))
00061 return 0;
00062 }
00063
00064 return 1;
00065 }
00066
00078 inline int u_isnl (int c)
00079 {
00080 return c == '\n' || c == '\r';
00081 }
00082
00095 int u_data_is_bin (char *data, size_t sz)
00096 {
00097 size_t i;
00098
00099 for (i = 0; i < sz; i++)
00100 {
00101 if (!isascii(data[i]))
00102 return 1;
00103 }
00104
00105 return 0;
00106 }
00107
00118 void u_trim (char *s)
00119 {
00120 char *p;
00121
00122 nop_return_if (s == NULL, );
00123
00124
00125 p = s + strlen(s) - 1;
00126 while (s < p && u_isblank(*p))
00127 --p;
00128 p[1] = '\0';
00129
00130
00131 p = s;
00132 while (*p && u_isblank(*p))
00133 ++p;
00134
00135 if (p > s)
00136 memmove(s, p, 1 + strlen(p));
00137
00138 return;
00139 }
00140
00154 char *u_strndup (const char *s, size_t len)
00155 {
00156 char *cp;
00157
00158
00159 dbg_return_if (len > strlen(s), NULL);
00160
00161
00162 dbg_return_sif ((cp = u_malloc(len + 1)) == NULL, NULL);
00163
00164 memcpy(cp, s, len);
00165 cp[len] = '\0';
00166
00167 return cp;
00168 }
00169
00183 char *u_strdup (const char *s)
00184 {
00185 return u_strndup(s, strlen(s));
00186 }
00187
00203 inline int u_strlcpy(char *dst, const char *src, size_t size)
00204 {
00205 return (strlcpy(dst, src, size) >= size ? ~0 : 0);
00206 }
00207
00223 inline int u_strlcat(char *dst, const char *src, size_t size)
00224 {
00225 return (strlcat(dst, src, size) >= size ? ~0 : 0);
00226 }
00227
00266 int u_strtok (const char *s, const char *delim, char ***ptv, size_t *pnelems)
00267 {
00268 enum { TV_NSLOTS_DFLT = 10, TV_NSLOTS_INCR = 10 };
00269 char **ap, **tv = NULL, **ntv = NULL;
00270 size_t nelems, tv_slots = TV_NSLOTS_DFLT;
00271 char *p, *sdup = NULL;
00272
00273 dbg_return_if (s == NULL, ~0);
00274 dbg_return_if (delim == NULL, ~0);
00275 dbg_return_if (ptv == NULL, ~0);
00276 dbg_return_if (pnelems == NULL, ~0);
00277
00278 sdup = u_strdup(s);
00279 dbg_err_if (sdup == NULL);
00280
00281 p = sdup;
00282 ap = tv;
00283 nelems = 0;
00284
00285 expand:
00286 ntv = u_realloc(tv, tv_slots * sizeof(char *));
00287 dbg_err_sif (ntv == NULL);
00288
00289
00290 if (ntv != tv)
00291 ap = ntv + (ap - tv);
00292
00293 tv = ntv;
00294
00295 for (; (*ap = strsep(&p, delim)) != NULL; )
00296 {
00297
00298 if (**ap == '\0')
00299 continue;
00300
00301 ++nelems;
00302
00303
00304 if (++ap == &tv[tv_slots - 1])
00305 {
00306 tv_slots += TV_NSLOTS_INCR;
00307 goto expand;
00308 }
00309 }
00310
00311
00312 *ap = sdup;
00313
00314
00315 *ptv = tv;
00316 *pnelems = nelems;
00317
00318 return 0;
00319 err:
00320 U_FREE(sdup);
00321 U_FREE(tv);
00322 return ~0;
00323 }
00324
00335 void u_strtok_cleanup (char **tv, size_t nelems)
00336 {
00337 if (tv)
00338 {
00339 U_FREE(tv[nelems]);
00340 u_free(tv);
00341 }
00342
00343 return;
00344 }
00345
00359 int u_snprintf (char *str, size_t size, const char *fmt, ...)
00360 {
00361 int wr;
00362 va_list ap;
00363
00364 va_start(ap, fmt);
00365 wr = vsnprintf(str, size, fmt, ap);
00366 va_end(ap);
00367
00368 dbg_err_sif (wr < 0);
00369 dbg_err_if (size <= (size_t) wr);
00370
00371
00372
00373 return 0;
00374 err:
00375 return ~0;
00376 }
00377
00392 int u_path_snprintf (char *buf, size_t sz, char sep, const char *fmt, ...)
00393 {
00394 va_list ap;
00395 int wr, i, len;
00396
00397 va_start(ap, fmt);
00398 wr = vsnprintf(buf, sz, fmt, ap);
00399 va_end(ap);
00400
00401 dbg_err_sif (wr < 0);
00402 dbg_err_if (sz <= (size_t) wr);
00403
00404
00405 for (len = i = strlen(buf); i > 0; --i)
00406 {
00407 if (buf[i] == sep && buf[i - 1] == sep)
00408 {
00409 memmove(buf + i, buf + i + 1, len - i);
00410 len--;
00411 }
00412 }
00413
00414 return 0;
00415 err:
00416 return ~0;
00417 }
00418
00430 int u_savepid (const char *pf)
00431 {
00432 FILE *pfp = NULL;
00433
00434 dbg_return_if (pf == NULL, ~0);
00435
00436 dbg_err_sif ((pfp = fopen(pf, "w")) == NULL);
00437 dbg_err_sif (fprintf(pfp, "%ld\n", (long) getpid()) == 0);
00438 fclose(pfp);
00439
00440 return 0;
00441 err:
00442 U_FCLOSE(pfp);
00443 return ~0;
00444 }
00445
00457 void *u_memdup (const void *src, size_t size)
00458 {
00459 void *p;
00460
00461 dbg_return_sif ((p = u_malloc(size)) == NULL, NULL);
00462
00463 memcpy(p, src, size);
00464
00465 return p;
00466 }
00467
00480 inline void u_use_unused_args (char *dummy, ...)
00481 {
00482 dummy = 0;
00483 return;
00484 }
00485
00486
00500 int u_data_dump (char *data, size_t sz, const char *file)
00501 {
00502 FILE *fp = NULL;
00503
00504 dbg_err_sif ((fp = fopen(file, "w")) == NULL);
00505 dbg_err_sif (fwrite(data, sz, 1, fp) < 1);
00506 fclose(fp);
00507
00508 return 0;
00509 err:
00510 U_FCLOSE(fp);
00511 return ~0;
00512 }
00513
00526 int u_load_file (const char *path, size_t sz_max, char **pbuf, size_t *psz)
00527 {
00528 FILE *fp = NULL;
00529 char *buf = NULL;
00530 size_t sz;
00531 struct stat sb;
00532
00533 dbg_return_if (path == NULL, ~0);
00534 dbg_return_if (pbuf == NULL, ~0);
00535 dbg_return_if (psz == NULL, ~0);
00536
00537 dbg_err_sifm ((fp = fopen(path, "r")) == NULL, "%s", path);
00538 dbg_err_sifm (fstat(fileno(fp), &sb) == -1, "%s", path);
00539 sz = sb.st_size;
00540 dbg_err_ifm (sz_max > 0 && sz > sz_max,
00541 "file too big (%zu vs %zu bytes)", sz, sz_max);
00542 dbg_err_sif ((buf = u_zalloc(sz)) == NULL);
00543 dbg_err_sifm (fread(buf, sz, 1, fp) != 1, "%s", path);
00544
00545 U_FCLOSE(fp);
00546
00547 *pbuf = buf;
00548 *psz = sz;
00549
00550 return 0;
00551 err:
00552 U_FCLOSE(fp);
00553 U_FREE(buf);
00554 return ~0;
00555 }
00556
00581 int u_io (iof_t f, int sd, void *buf, size_t l, ssize_t *n, int *eof)
00582 {
00583 #define SET_PPTR(pptr, val) do {if ((pptr)) *(pptr) = (val);} while (0);
00584 ssize_t nret;
00585 size_t nleft = l;
00586 char *p = buf;
00587
00588 SET_PPTR(n, 0);
00589 SET_PPTR(eof, 0);
00590
00591 while (nleft > 0)
00592 {
00593 if ((nret = (f) (sd, p, nleft)) == -1)
00594 {
00595 if (errno == EINTR)
00596 continue;
00597 else
00598 {
00599 dbg_strerror(errno);
00600 goto end;
00601 }
00602 }
00603
00604
00605 if (nret == 0)
00606 {
00607 SET_PPTR(eof, 1);
00608 goto end;
00609 }
00610
00611 nleft -= nret;
00612 p += nret;
00613 }
00614
00615 end:
00616 SET_PPTR(n, l - nleft);
00617 return nleft ? ~0 : 0;
00618 #undef SET_PPTR
00619 }
00620
00635 ssize_t u_read (int fd, void *buf, size_t size)
00636 {
00637 int eof = 0;
00638 ssize_t nw = 0;
00639
00640 if (u_io((iof_t) read, fd, buf, size, &nw, &eof))
00641 {
00642 if (eof)
00643 return nw;
00644 else
00645 return -1;
00646 }
00647
00648 return nw;
00649 }
00650
00665 ssize_t u_write (int fd, void *buf, size_t size)
00666 {
00667 if (u_io((iof_t) write, fd, buf, size, NULL, NULL))
00668 return -1;
00669
00670 return size;
00671 }
00672
00683 int u_sleep(unsigned int secs)
00684 {
00685 #ifdef OS_WIN
00686 Sleep(secs * 1000);
00687 #else
00688 int sleep_for, c;
00689
00690 for (sleep_for = secs; sleep_for > 0; sleep_for = c)
00691 {
00692 if ((c = sleep(sleep_for)) == 0)
00693 break;
00694 else if (errno != EINTR)
00695 return -1;
00696 }
00697 #endif
00698 return 0;
00699 }
00700
00716 int u_atol (const char *nptr, long *pl)
00717 {
00718 char *endptr;
00719 long tmp, saved_errno = errno;
00720
00721 dbg_return_if (nptr == NULL, ~0);
00722 dbg_return_if (pl == NULL, ~0);
00723
00724 tmp = strtol(nptr, &endptr, 10);
00725
00726 dbg_err_sif (tmp == 0 && errno == EINVAL);
00727 dbg_err_sif ((tmp == LONG_MIN || tmp == LONG_MAX) && errno == ERANGE);
00728
00729
00730
00731
00732 dbg_err_ifm (nptr == endptr, "invalid base10 string: %s", nptr);
00733
00734 *pl = tmp;
00735
00736 errno = saved_errno;
00737 return 0;
00738 err:
00739 errno = saved_errno;
00740 return ~0;
00741 }
00742
00758 int u_atoi (const char *nptr, int *pi)
00759 {
00760 long int tmp;
00761
00762 dbg_err_if (u_atol(nptr, &tmp));
00763
00764
00765 #if (INT_MAX < LONG_MAX)
00766 dbg_err_if (tmp > INT_MAX);
00767 #endif
00768 #if (INT_MIN > LONG_MIN)
00769 dbg_err_if (tmp < INT_MIN);
00770 #endif
00771
00772 *pi = (int) tmp;
00773
00774 return 0;
00775 err:
00776 return ~0;
00777 }
00778
00779 #ifdef HAVE_STRTOUMAX
00780
00795 int u_atoumax (const char *nptr, uintmax_t *pumax)
00796 {
00797 uintmax_t tmp;
00798 int saved_errno = errno;
00799
00800 dbg_return_if (nptr == NULL, ~0);
00801 dbg_return_if (pumax == NULL, ~0);
00802
00803 tmp = strtoumax(nptr, (char **) NULL, 10);
00804
00805 dbg_err_if (tmp == 0 && errno == EINVAL);
00806 dbg_err_if (tmp == UINTMAX_MAX && errno == ERANGE);
00807
00808 *pumax = tmp;
00809
00810 errno = saved_errno;
00811 return 0;
00812 err:
00813 errno = saved_errno;
00814 return ~0;
00815 }
00816 #endif
00817
00836 int u_atof (const char *nptr, double *pd)
00837 {
00838 #ifdef HAVE_STRTOD
00839 double tmp;
00840 char *endptr;
00841 int saved_errno = errno;
00842
00843 dbg_return_if (nptr == NULL, ~0);
00844 dbg_return_if (pd == NULL, ~0);
00845
00846
00847 errno = 0;
00848
00849
00850 tmp = strtod(nptr, &endptr);
00851
00852
00853 dbg_err_if (tmp == 0 && nptr == endptr);
00854
00855
00856
00857
00858 dbg_err_sif (errno == ERANGE);
00859
00860 *pd = tmp;
00861
00862 errno = saved_errno;
00863 return 0;
00864 err:
00865 errno = saved_errno;
00866 return ~0;
00867 #else
00868
00869 dbg_return_if (nptr == NULL, ~0);
00870 dbg_return_if (pd == NULL, ~0);
00871
00872 *pd = atof(nptr);
00873
00874 return 0;
00875 #endif
00876 }
00877
00895 int u_tokenize (char *wlist, const char *delim, char **tokv, size_t tokv_sz)
00896 {
00897 char **ap;
00898
00899 dbg_return_if (wlist == NULL, ~0);
00900 dbg_return_if (delim == NULL, ~0);
00901 dbg_return_if (tokv == NULL, ~0);
00902 dbg_return_if (tokv_sz == 0, ~0);
00903
00904 ap = tokv;
00905
00906 for ( ; (*ap = strsep(&wlist, delim)) != NULL; )
00907 {
00908
00909 if (**ap == '\0')
00910 continue;
00911
00912
00913 if (++ap >= &tokv[tokv_sz - 1])
00914 break;
00915 }
00916
00917
00918 *ap = NULL;
00919
00920 return 0;
00921 }
00922
00937 char *u_sstrncpy (char *dst, const char *src, size_t size)
00938 {
00939 dst[size] = '\0';
00940 return strncpy(dst, src, size);
00941 }
00942