"Fossies" - the Fresh Open Source Software Archive

Member "xombrero-1.6.4/linux/linux.c" (17 Feb 2015, 21039 Bytes) of package /linux/www/old/xombrero-1.6.4.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "linux.c" see the Fossies "Dox" file reference documentation.

    1 #include <sys/types.h>
    2 #include <sys/cdefs.h>
    3 #include <sys/socket.h>
    4 
    5 #include <errno.h>
    6 #include <errno.h>
    7 #include <limits.h>
    8 #include <stdio.h>
    9 #include <stdlib.h>
   10 #include <string.h>
   11 
   12 #include "util.h"
   13 
   14 /*
   15  * All the workarounds for glibc stupidity are piled into this file...
   16  */
   17 
   18 /* --------------------------------------------------------------------------- */
   19 /*  $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $  */
   20 
   21 /*
   22  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
   23  *
   24  * Permission to use, copy, modify, and distribute this software for any
   25  * purpose with or without fee is hereby granted, provided that the above
   26  * copyright notice and this permission notice appear in all copies.
   27  *
   28  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   29  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   30  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   31  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   32  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   33  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   34  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   35  */
   36 
   37 /*
   38  * Copy src to string dst of size siz.  At most siz-1 characters
   39  * will be copied.  Always NUL terminates (unless siz == 0).
   40  * Returns strlen(src); if retval >= siz, truncation occurred.
   41  */
   42 size_t
   43 strlcpy(char *dst, const char *src, size_t siz)
   44 {
   45     char *d = dst;
   46     const char *s = src;
   47     size_t n = siz;
   48 
   49     /* Copy as many bytes as will fit */
   50     if (n != 0 && --n != 0) {
   51         do {
   52             if ((*d++ = *s++) == 0)
   53                 break;
   54         } while (--n != 0);
   55     }
   56 
   57     /* Not enough room in dst, add NUL and traverse rest of src */
   58     if (n == 0) {
   59         if (siz != 0)
   60             *d = '\0';      /* NUL-terminate dst */
   61         while (*s++)
   62             ;
   63     }
   64 
   65     return(s - src - 1);    /* count does not include NUL */
   66 }
   67 
   68 /* --------------------------------------------------------------------------- */
   69 /*  $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $  */
   70 
   71 /*
   72  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
   73  *
   74  * Permission to use, copy, modify, and distribute this software for any
   75  * purpose with or without fee is hereby granted, provided that the above
   76  * copyright notice and this permission notice appear in all copies.
   77  *
   78  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   79  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   80  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   81  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   82  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   83  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   84  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   85  */
   86 
   87 /*
   88  * Appends src to string dst of size siz (unlike strncat, siz is the
   89  * full size of dst, not space left).  At most siz-1 characters
   90  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
   91  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
   92  * If retval >= siz, truncation occurred.
   93  */
   94 size_t
   95 strlcat(char *dst, const char *src, size_t siz)
   96 {
   97     char *d = dst;
   98     const char *s = src;
   99     size_t n = siz;
  100     size_t dlen;
  101 
  102     /* Find the end of dst and adjust bytes left but don't go past end */
  103     while (n-- != 0 && *d != '\0')
  104         d++;
  105     dlen = d - dst;
  106     n = siz - dlen;
  107 
  108     if (n == 0)
  109         return(dlen + strlen(s));
  110     while (*s != '\0') {
  111         if (n != 1) {
  112             *d++ = *s;
  113             n--;
  114         }
  115         s++;
  116     }
  117     *d = '\0';
  118 
  119     return(dlen + (s - src));   /* count does not include NUL */
  120 }
  121 
  122 /* --------------------------------------------------------------------------- */
  123 /*  $NetBSD: fgetln.c,v 1.3 2007/08/07 02:06:58 lukem Exp $ */
  124 
  125 /*-
  126  * Copyright (c) 1998 The NetBSD Foundation, Inc.
  127  * All rights reserved.
  128  *
  129  * This code is derived from software contributed to The NetBSD Foundation
  130  * by Christos Zoulas.
  131  *
  132  * Redistribution and use in source and binary forms, with or without
  133  * modification, are permitted provided that the following conditions
  134  * are met:
  135  * 1. Redistributions of source code must retain the above copyright
  136  *    notice, this list of conditions and the following disclaimer.
  137  * 2. Redistributions in binary form must reproduce the above copyright
  138  *    notice, this list of conditions and the following disclaimer in the
  139  *    documentation and/or other materials provided with the distribution.
  140  * 3. Neither the name of The NetBSD Foundation nor the names of its
  141  *    contributors may be used to endorse or promote products derived
  142  *    from this software without specific prior written permission.
  143  *
  144  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  145  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  146  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  147  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  148  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  149  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  150  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  151  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  152  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  153  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  154  * POSSIBILITY OF SUCH DAMAGE.
  155  */
  156 
  157 char *
  158 fgetln(fp, len)
  159     FILE *fp;
  160     size_t *len;
  161 {
  162     static char *buf = NULL;
  163     static size_t bufsiz = 0;
  164     char *ptr;
  165 
  166 
  167     if (buf == NULL) {
  168         bufsiz = BUFSIZ;
  169         if ((buf = malloc(bufsiz)) == NULL)
  170             return NULL;
  171     }
  172 
  173     if (fgets(buf, bufsiz, fp) == NULL)
  174         return NULL;
  175 
  176     *len = 0;
  177     while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
  178         size_t nbufsiz = bufsiz + BUFSIZ;
  179         char *nbuf = realloc(buf, nbufsiz);
  180 
  181         if (nbuf == NULL) {
  182             int oerrno = errno;
  183             free(buf);
  184             errno = oerrno;
  185             buf = NULL;
  186             return NULL;
  187         } else
  188             buf = nbuf;
  189 
  190         *len = bufsiz;
  191         if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL)
  192             return buf;
  193 
  194         bufsiz = nbufsiz;
  195     }
  196 
  197     *len = (ptr - buf) + 1;
  198     return buf;
  199 }
  200 
  201 /* --------------------------------------------------------------------------- */
  202 /*  $OpenBSD: fparseln.c,v 1.6 2005/08/02 21:46:23 espie Exp $  */
  203 /*  $NetBSD: fparseln.c,v 1.7 1999/07/02 15:49:12 simonb Exp $  */
  204 
  205 /*
  206  * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
  207  *
  208  * Redistribution and use in source and binary forms, with or without
  209  * modification, are permitted provided that the following conditions
  210  * are met:
  211  * 1. Redistributions of source code must retain the above copyright
  212  *    notice, this list of conditions and the following disclaimer.
  213  * 2. Redistributions in binary form must reproduce the above copyright
  214  *    notice, this list of conditions and the following disclaimer in the
  215  *    documentation and/or other materials provided with the distribution.
  216  * 3. All advertising materials mentioning features or use of this software
  217  *    must display the following acknowledgement:
  218  *  This product includes software developed by Christos Zoulas.
  219  * 4. The name of the author may not be used to endorse or promote products
  220  *    derived from this software without specific prior written permission.
  221  *
  222  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  223  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  224  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  225  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  226  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  227  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  228  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  229  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  230  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  231  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  232  */
  233 
  234 #define FPARSELN_UNESCESC   0x01
  235 #define FPARSELN_UNESCCONT  0x02
  236 #define FPARSELN_UNESCCOMM  0x04
  237 #define FPARSELN_UNESCREST  0x08
  238 #define FPARSELN_UNESCALL   0x0f
  239 
  240 static int isescaped(const char *, const char *, int);
  241 
  242 /* isescaped():
  243  *  Return true if the character in *p that belongs to a string
  244  *  that starts in *sp, is escaped by the escape character esc.
  245  */
  246 static int
  247 isescaped(const char *sp, const char *p, int esc)
  248 {
  249     const char     *cp;
  250     size_t      ne;
  251 
  252     /* No escape character */
  253     if (esc == '\0')
  254         return 1;
  255 
  256     /* Count the number of escape characters that precede ours */
  257     for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)
  258         continue;
  259 
  260     /* Return true if odd number of escape characters */
  261     return (ne & 1) != 0;
  262 }
  263 
  264 
  265 /* fparseln():
  266  *  Read a line from a file parsing continuations ending in \
  267  *  and eliminating trailing newlines, or comments starting with
  268  *  the comment char.
  269  */
  270 char *
  271 fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3],
  272     int flags)
  273 {
  274     static const char dstr[3] = { '\\', '\\', '#' };
  275     char    *buf = NULL, *ptr, *cp, esc, con, nl, com;
  276     size_t  s, len = 0;
  277     int cnt = 1;
  278 
  279     if (str == NULL)
  280         str = dstr;
  281 
  282     esc = str[0];
  283     con = str[1];
  284     com = str[2];
  285 
  286     /*
  287      * XXX: it would be cool to be able to specify the newline character,
  288      * but unfortunately, fgetln does not let us
  289      */
  290     nl  = '\n';
  291 
  292     while (cnt) {
  293         cnt = 0;
  294 
  295         if (lineno)
  296             (*lineno)++;
  297 
  298         if ((ptr = fgetln(fp, &s)) == NULL)
  299             break;
  300 
  301         if (s && com) {     /* Check and eliminate comments */
  302             for (cp = ptr; cp < ptr + s; cp++)
  303                 if (*cp == com && !isescaped(ptr, cp, esc)) {
  304                     s = cp - ptr;
  305                     cnt = s == 0 && buf == NULL;
  306                     break;
  307                 }
  308         }
  309 
  310         if (s && nl) {      /* Check and eliminate newlines */
  311             cp = &ptr[s - 1];
  312 
  313             if (*cp == nl)
  314                 s--;    /* forget newline */
  315         }
  316 
  317         if (s && con) {     /* Check and eliminate continuations */
  318             cp = &ptr[s - 1];
  319 
  320             if (*cp == con && !isescaped(ptr, cp, esc)) {
  321                 s--;    /* forget escape */
  322                 cnt = 1;
  323             }
  324         }
  325 
  326         if (s == 0 && buf != NULL)
  327             continue;
  328 
  329         if ((cp = realloc(buf, len + s + 1)) == NULL) {
  330             free(buf);
  331             return NULL;
  332         }
  333         buf = cp;
  334 
  335         (void) memcpy(buf + len, ptr, s);
  336         len += s;
  337         buf[len] = '\0';
  338     }
  339 
  340     if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&
  341         strchr(buf, esc) != NULL) {
  342         ptr = cp = buf;
  343         while (cp[0] != '\0') {
  344             int skipesc;
  345 
  346             while (cp[0] != '\0' && cp[0] != esc)
  347                 *ptr++ = *cp++;
  348             if (cp[0] == '\0' || cp[1] == '\0')
  349                 break;
  350 
  351             skipesc = 0;
  352             if (cp[1] == com)
  353                 skipesc += (flags & FPARSELN_UNESCCOMM);
  354             if (cp[1] == con)
  355                 skipesc += (flags & FPARSELN_UNESCCONT);
  356             if (cp[1] == esc)
  357                 skipesc += (flags & FPARSELN_UNESCESC);
  358             if (cp[1] != com && cp[1] != con && cp[1] != esc)
  359                 skipesc = (flags & FPARSELN_UNESCREST);
  360 
  361             if (skipesc)
  362                 cp++;
  363             else
  364                 *ptr++ = *cp++;
  365             *ptr++ = *cp++;
  366         }
  367         *ptr = '\0';
  368         len = strlen(buf);
  369     }
  370 
  371     if (size)
  372         *size = len;
  373     return buf;
  374 }
  375 
  376 /* --------------------------------------------------------------------------- */
  377 /*  $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $    */
  378 
  379 /*
  380  * Copyright (c) 2004 Ted Unangst and Todd Miller
  381  * All rights reserved.
  382  *
  383  * Permission to use, copy, modify, and distribute this software for any
  384  * purpose with or without fee is hereby granted, provided that the above
  385  * copyright notice and this permission notice appear in all copies.
  386  *
  387  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  388  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  389  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  390  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  391  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  392  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  393  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  394  */
  395 
  396 #define INVALID     1
  397 #define TOOSMALL    2
  398 #define TOOLARGE    3
  399 
  400 long long
  401 strtonum(const char *numstr, long long minval, long long maxval,
  402     const char **errstrp)
  403 {
  404     long long ll = 0;
  405     char *ep;
  406     int error = 0;
  407     struct errval {
  408         const char *errstr;
  409         int err;
  410     } ev[4] = {
  411         { NULL,     0 },
  412         { "invalid",    EINVAL },
  413         { "too small",  ERANGE },
  414         { "too large",  ERANGE },
  415     };
  416 
  417     ev[0].err = errno;
  418     errno = 0;
  419     if (minval > maxval)
  420         error = INVALID;
  421     else {
  422         ll = strtoll(numstr, &ep, 10);
  423         if (numstr == ep || *ep != '\0')
  424             error = INVALID;
  425         else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
  426             error = TOOSMALL;
  427         else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
  428             error = TOOLARGE;
  429     }
  430     if (errstrp != NULL)
  431         *errstrp = ev[error].errstr;
  432     errno = ev[error].err;
  433     if (error)
  434         ll = 0;
  435 
  436     return (ll);
  437 }
  438 
  439 /*  $OpenBSD: fmt_scaled.c,v 1.10 2009/06/20 15:00:04 martynas Exp $    */
  440 
  441 /*
  442  * Copyright (c) 2001, 2002, 2003 Ian F. Darwin.  All rights reserved.
  443  *
  444  * Redistribution and use in source and binary forms, with or without
  445  * modification, are permitted provided that the following conditions
  446  * are met:
  447  * 1. Redistributions of source code must retain the above copyright
  448  *    notice, this list of conditions and the following disclaimer.
  449  * 2. Redistributions in binary form must reproduce the above copyright
  450  *    notice, this list of conditions and the following disclaimer in the
  451  *    documentation and/or other materials provided with the distribution.
  452  * 3. The name of the author may not be used to endorse or promote products
  453  *    derived from this software without specific prior written permission.
  454  *
  455  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  456  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  457  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  458  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  459  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  460  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  461  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  462  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  463  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  464  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  465  */
  466 
  467 /*
  468  * fmt_scaled: Format numbers scaled for human comprehension
  469  * scan_scaled: Scan numbers in this format.
  470  *
  471  * "Human-readable" output uses 4 digits max, and puts a unit suffix at
  472  * the end.  Makes output compact and easy-to-read esp. on huge disks.
  473  * Formatting code was originally in OpenBSD "df", converted to library routine.
  474  * Scanning code written for OpenBSD libutil.
  475  */
  476 
  477 #include <stdio.h>
  478 #include <stdlib.h>
  479 #include <errno.h>
  480 #include <string.h>
  481 #include <ctype.h>
  482 #include <limits.h>
  483 
  484 #include "util.h"
  485 
  486 typedef enum {
  487     NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6
  488 } unit_type;
  489 
  490 /* These three arrays MUST be in sync!  XXX make a struct */
  491 static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA };
  492 static char scale_chars[] = "BKMGTPE";
  493 static long long scale_factors[] = {
  494     1LL,
  495     1024LL,
  496     1024LL*1024,
  497     1024LL*1024*1024,
  498     1024LL*1024*1024*1024,
  499     1024LL*1024*1024*1024*1024,
  500     1024LL*1024*1024*1024*1024*1024,
  501 };
  502 #define SCALE_LENGTH (sizeof(units)/sizeof(units[0]))
  503 
  504 #define MAX_DIGITS (SCALE_LENGTH * 3)   /* XXX strlen(sprintf("%lld", -1)? */
  505 
  506 /* Convert the given input string "scaled" into numeric in "result".
  507  * Return 0 on success, -1 and errno set on error.
  508  */
  509 int
  510 scan_scaled(char *scaled, long long *result)
  511 {
  512     char *p = scaled;
  513     int sign = 0;
  514     unsigned int i, ndigits = 0, fract_digits = 0;
  515     long long scale_fact = 1, whole = 0, fpart = 0;
  516 
  517     /* Skip leading whitespace */
  518     while (isascii(*p) && isspace(*p))
  519         ++p;
  520 
  521     /* Then at most one leading + or - */
  522     while (*p == '-' || *p == '+') {
  523         if (*p == '-') {
  524             if (sign) {
  525                 errno = EINVAL;
  526                 return -1;
  527             }
  528             sign = -1;
  529             ++p;
  530         } else if (*p == '+') {
  531             if (sign) {
  532                 errno = EINVAL;
  533                 return -1;
  534             }
  535             sign = +1;
  536             ++p;
  537         }
  538     }
  539 
  540     /* Main loop: Scan digits, find decimal point, if present.
  541      * We don't allow exponentials, so no scientific notation
  542      * (but note that E for Exa might look like e to some!).
  543      * Advance 'p' to end, to get scale factor.
  544      */
  545     for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) {
  546         if (*p == '.') {
  547             if (fract_digits > 0) { /* oops, more than one '.' */
  548                 errno = EINVAL;
  549                 return -1;
  550             }
  551             fract_digits = 1;
  552             continue;
  553         }
  554 
  555         i = (*p) - '0';         /* whew! finally a digit we can use */
  556         if (fract_digits > 0) {
  557             if (fract_digits >= MAX_DIGITS-1)
  558                 /* ignore extra fractional digits */
  559                 continue;
  560             fract_digits++;     /* for later scaling */
  561             fpart *= 10;
  562             fpart += i;
  563         } else {                /* normal digit */
  564             if (++ndigits >= MAX_DIGITS) {
  565                 errno = ERANGE;
  566                 return -1;
  567             }
  568             whole *= 10;
  569             whole += i;
  570         }
  571     }
  572 
  573     if (sign) {
  574         whole *= sign;
  575         fpart *= sign;
  576     }
  577 
  578     /* If no scale factor given, we're done. fraction is discarded. */
  579     if (!*p) {
  580         *result = whole;
  581         return 0;
  582     }
  583 
  584     /* Validate scale factor, and scale whole and fraction by it. */
  585     for (i = 0; i < SCALE_LENGTH; i++) {
  586 
  587         /* Are we there yet? */
  588         if (*p == scale_chars[i] ||
  589             *p == tolower(scale_chars[i])) {
  590 
  591             /* If it ends with alphanumerics after the scale char, bad. */
  592             if (isalnum(*(p+1))) {
  593                 errno = EINVAL;
  594                 return -1;
  595             }
  596             scale_fact = scale_factors[i];
  597 
  598             /* scale whole part */
  599             whole *= scale_fact;
  600 
  601             /* truncate fpart so it does't overflow.
  602              * then scale fractional part.
  603              */
  604             while (fpart >= LLONG_MAX / scale_fact) {
  605                 fpart /= 10;
  606                 fract_digits--;
  607             }
  608             fpart *= scale_fact;
  609             if (fract_digits > 0) {
  610                 for (i = 0; i < fract_digits -1; i++)
  611                     fpart /= 10;
  612             }
  613             whole += fpart;
  614             *result = whole;
  615             return 0;
  616         }
  617     }
  618     errno = ERANGE;
  619     return -1;
  620 }
  621 
  622 /* Format the given "number" into human-readable form in "result".
  623  * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE.
  624  * Return 0 on success, -1 and errno set if error.
  625  */
  626 int
  627 fmt_scaled(long long number, char *result)
  628 {
  629     long long abval, fract = 0;
  630     unsigned int i;
  631     unit_type unit = NONE;
  632 
  633     abval = llabs(number);
  634 
  635     /* Not every negative long long has a positive representation.
  636      * Also check for numbers that are just too darned big to format
  637      */
  638     if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) {
  639         errno = ERANGE;
  640         return -1;
  641     }
  642 
  643     /* scale whole part; get unscaled fraction */
  644     for (i = 0; i < SCALE_LENGTH; i++) {
  645         if (abval/1024 < scale_factors[i]) {
  646             unit = units[i];
  647             fract = (i == 0) ? 0 : abval % scale_factors[i];
  648             number /= scale_factors[i];
  649             if (i > 0)
  650                 fract /= scale_factors[i - 1];
  651             break;
  652         }
  653     }
  654 
  655     fract = (10 * fract + 512) / 1024;
  656     /* if the result would be >= 10, round main number */
  657     if (fract == 10) {
  658         if (number >= 0)
  659             number++;
  660         else
  661             number--;
  662         fract = 0;
  663     }
  664 
  665     if (number == 0)
  666         strlcpy(result, "0B", FMT_SCALED_STRSIZE);
  667     else if (unit == NONE || number >= 100 || number <= -100) {
  668         if (fract >= 5) {
  669             if (number >= 0)
  670                 number++;
  671             else
  672                 number--;
  673         }
  674         (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c",
  675             number, scale_chars[unit]);
  676     } else
  677         (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c",
  678             number, fract, scale_chars[unit]);
  679 
  680     return 0;
  681 }
  682 
  683 /* --------------------------------------------------------------------------- */
  684 
  685 /*
  686  * Copyright (c) 2002,2004 Damien Miller <djm@mindrot.org>
  687  *
  688  * Permission to use, copy, modify, and distribute this software for any
  689  * purpose with or without fee is hereby granted, provided that the above
  690  * copyright notice and this permission notice appear in all copies.
  691  *
  692  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  693  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  694  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  695  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  696  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  697  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  698  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  699  */
  700 
  701 /* Get effective user and group identification of locally-connected
  702  * peer.
  703  */
  704 int
  705 getpeereid(int s, uid_t *euid, gid_t *gid)
  706 {
  707     struct ucred cred;
  708     socklen_t len = sizeof(cred);
  709 
  710     if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0)
  711         return (-1);
  712     *euid = cred.uid;
  713     *gid = cred.gid;
  714 
  715     return (0);
  716 }
  717 
  718 #ifdef  MAIN
  719 /*
  720  * This is the original version of the program in the man page.
  721  * Copy-and-paste whatever you need from it.
  722  */
  723 int
  724 main(int argc, char **argv)
  725 {
  726     char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE];
  727     long long ninput = 10483892, result;
  728 
  729     if (scan_scaled(cinput, &result) == 0)
  730         printf("\"%s\" -> %lld\n", cinput, result);
  731     else
  732         perror(cinput);
  733 
  734     if (fmt_scaled(ninput, buf) == 0)
  735         printf("%lld -> \"%s\"\n", ninput, buf);
  736     else
  737         fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno));
  738 
  739     return 0;
  740 }
  741 #endif