~ubuntu-branches/ubuntu/intrepid/haproxy/intrepid

« back to all changes in this revision

Viewing changes to src/standard.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2008-03-09 21:30:29 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080309213029-8oupnrc607mg5uqw
Tags: 1.3.14.3-1
* New Upstream Version
* Add status argument support to init-script to conform to LSB.
* Cleanup pidfile after stop in init script. Init script return code fixups.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 *
11
11
 */
12
12
 
 
13
#include <ctype.h>
13
14
#include <netdb.h>
14
15
#include <stdlib.h>
15
16
#include <string.h>
 
17
#include <sys/socket.h>
 
18
#include <sys/un.h>
16
19
#include <netinet/in.h>
17
20
#include <arpa/inet.h>
18
21
 
20
23
#include <common/standard.h>
21
24
#include <proto/log.h>
22
25
 
23
 
/* enough to store 2^64-1 = 18446744073709551615 */
24
 
static char itoa_str[21];
 
26
/* enough to store 10 integers of :
 
27
 *   2^64-1 = 18446744073709551615 or
 
28
 *    -2^63 = -9223372036854775808
 
29
 */
 
30
char itoa_str[10][21];
25
31
 
26
32
/*
27
33
 * copies at most <size-1> chars from <src> to <dst>. Last char is always
43
49
}
44
50
 
45
51
/*
46
 
 * This function simply returns a statically allocated string containing
 
52
 * This function simply returns a locally allocated string containing
47
53
 * the ascii representation for number 'n' in decimal.
48
54
 */
49
 
char *ultoa(unsigned long n)
 
55
const char *ultoa_r(unsigned long n, char *buffer, int size)
50
56
{
51
57
        char *pos;
52
58
        
53
 
        pos = itoa_str + sizeof(itoa_str) - 1;
 
59
        pos = buffer + size - 1;
54
60
        *pos-- = '\0';
55
61
        
56
62
        do {
57
63
                *pos-- = '0' + n % 10;
58
64
                n /= 10;
59
 
        } while (n && pos >= itoa_str);
 
65
        } while (n && pos >= buffer);
60
66
        return pos + 1;
61
67
}
62
68
 
 
69
/*
 
70
 * This function simply returns a locally allocated string containing the ascii
 
71
 * representation for number 'n' in decimal, unless n is 0 in which case it
 
72
 * returns the alternate string (or an empty string if the alternate string is
 
73
 * NULL). It use is intended for limits reported in reports, where it's
 
74
 * desirable not to display anything if there is no limit. Warning! it shares
 
75
 * the same vector as ultoa_r().
 
76
 */
 
77
const char *limit_r(unsigned long n, char *buffer, int size, const char *alt)
 
78
{
 
79
        return (n) ? ultoa_r(n, buffer, size) : (alt ? alt : "");
 
80
}
 
81
 
 
82
/*
 
83
 * converts <str> to a struct sockaddr_un* which is locally allocated.
 
84
 * The format is "/path", where "/path" is a path to a UNIX domain socket.
 
85
 */
 
86
struct sockaddr_un *str2sun(const char *str)
 
87
{
 
88
        static struct sockaddr_un su;
 
89
        int strsz;      /* length included null */
 
90
 
 
91
        memset(&su, 0, sizeof(su));
 
92
        strsz = strlen(str) + 1;
 
93
        if (strsz > sizeof(su.sun_path)) {
 
94
                Alert("Socket path '%s' too long (max %d)\n",
 
95
                        str, sizeof(su.sun_path) - 1);
 
96
        } else {
 
97
                su.sun_family = AF_UNIX;
 
98
                memcpy(su.sun_path, str, strsz);
 
99
        }
 
100
        return &su;
 
101
}
63
102
 
64
103
/*
65
104
 * Returns non-zero if character <s> is a hex digit (0-9, a-f, A-F), else zero.
82
121
        return 0;
83
122
}
84
123
 
 
124
/*
 
125
 * Checks <name> for invalid characters. Valid chars are [A-Za-z0-9_:.-]. If an
 
126
 * invalid character is found, a pointer to it is returned. If everything is
 
127
 * fine, NULL is returned.
 
128
 */
 
129
const char *invalid_char(const char *name)
 
130
{
 
131
        if (!*name)
 
132
                return name;
 
133
 
 
134
        while (*name) {
 
135
                if (!isalnum((int)*name) && *name != '.' && *name != ':' &&
 
136
                    *name != '_' && *name != '-')
 
137
                        return name;
 
138
                name++;
 
139
        }
 
140
        return NULL;
 
141
}
85
142
 
86
143
/*
87
144
 * converts <str> to a struct sockaddr_in* which is locally allocated.
186
243
        goto out_free;
187
244
}
188
245
 
 
246
 
 
247
/*
 
248
 * Parse IP address found in url.
 
249
 */
 
250
static int url2ip(const char *addr, struct in_addr *dst)
 
251
{
 
252
        int saw_digit, octets, ch;
 
253
        u_char tmp[4], *tp;
 
254
        const char *cp = addr;
 
255
 
 
256
        saw_digit = 0;
 
257
        octets = 0;
 
258
        *(tp = tmp) = 0;
 
259
 
 
260
        while (*addr) {
 
261
                unsigned char digit = (ch = *addr++) - '0';
 
262
                if (digit > 9 && ch != '.')
 
263
                        break;
 
264
                if (digit <= 9) {
 
265
                        u_int new = *tp * 10 + digit;
 
266
                        if (new > 255)
 
267
                                return 0;
 
268
                        *tp = new;
 
269
                        if (!saw_digit) {
 
270
                                if (++octets > 4)
 
271
                                        return 0;
 
272
                                saw_digit = 1;
 
273
                        }
 
274
                } else if (ch == '.' && saw_digit) {
 
275
                        if (octets == 4)
 
276
                                return 0;
 
277
                        *++tp = 0;
 
278
                        saw_digit = 0;
 
279
                } else
 
280
                        return 0;
 
281
        }
 
282
 
 
283
        if (octets < 4)
 
284
                return 0;
 
285
 
 
286
        memcpy(&dst->s_addr, tmp, 4);
 
287
        return addr-cp-1;
 
288
}
 
289
 
 
290
/*
 
291
 * Resolve destination server from URL. Convert <str> to a sockaddr_in*.
 
292
 */
 
293
int url2sa(const char *url, int ulen, struct sockaddr_in *addr)
 
294
{
 
295
        const char *curr = url, *cp = url;
 
296
        int ret, url_code = 0;
 
297
        unsigned int http_code = 0;
 
298
 
 
299
        /* Cleanup the room */
 
300
        addr->sin_family = AF_INET;
 
301
        addr->sin_addr.s_addr = 0;
 
302
        addr->sin_port = 0;
 
303
 
 
304
        /* Firstly, try to find :// pattern */
 
305
        while (curr < url+ulen && url_code != 0x3a2f2f) {
 
306
                url_code = ((url_code & 0xffff) << 8);
 
307
                url_code += (unsigned char)*curr++;
 
308
        }
 
309
 
 
310
        /* Secondly, if :// pattern is found, verify parsed stuff
 
311
         * before pattern is matching our http pattern.
 
312
         * If so parse ip address and port in uri.
 
313
         * 
 
314
         * WARNING: Current code doesn't support dynamic async dns resolver.
 
315
         */
 
316
        if (url_code == 0x3a2f2f) {
 
317
                while (cp < curr - 3)
 
318
                        http_code = (http_code << 8) + *cp++;
 
319
                http_code |= 0x20202020;                        /* Turn everything to lower case */
 
320
                
 
321
                /* HTTP url matching */
 
322
                if (http_code == 0x68747470) {
 
323
                        /* We are looking for IP address. If you want to parse and
 
324
                         * resolve hostname found in url, you can use str2sa(), but
 
325
                         * be warned this can slow down global daemon performances
 
326
                         * while handling lagging dns responses.
 
327
                         */
 
328
                        ret = url2ip(curr, &addr->sin_addr);
 
329
                        if (!ret)
 
330
                                return -1;
 
331
                        curr += ret;
 
332
                        addr->sin_port = (*curr == ':') ? str2uic(++curr) : 80;
 
333
                        addr->sin_port = htons(addr->sin_port);
 
334
                }
 
335
                return 0;
 
336
        }
 
337
 
 
338
        return -1;
 
339
}
 
340
 
189
341
/* will try to encode the string <string> replacing all characters tagged in
190
342
 * <map> with the hexadecimal representation of their ASCII-code (2 digits)
191
343
 * prefixed by <escape>, and will store the result between <start> (included)
248
400
int strl2ic(const char *s, int len)
249
401
{
250
402
        int i = 0;
251
 
        int j;
 
403
        int j, k;
252
404
 
253
405
        if (len > 0) {
254
406
                if (*s != '-') {
255
407
                        /* positive number */
256
408
                        while (len-- > 0) {
257
409
                                j = (*s++) - '0';
258
 
                                i = i * 10;
 
410
                                k = i * 10;
259
411
                                if (j > 9)
260
412
                                        break;
261
 
                                i += j;
 
413
                                i = k + j;
262
414
                        }
263
415
                } else {
264
416
                        /* negative number */
265
417
                        s++;
266
418
                        while (--len > 0) {
267
419
                                j = (*s++) - '0';
268
 
                                i = i * 10;
 
420
                                k = i * 10;
269
421
                                if (j > 9)
270
422
                                        break;
271
 
                                i -= j;
 
423
                                i = k - j;
272
424
                        }
273
425
                }
274
426
        }
366
518
        return 0;
367
519
}
368
520
 
 
521
/* This function parses a time value optionally followed by a unit suffix among
 
522
 * "d", "h", "m", "s", "ms" or "us". It converts the value into the unit
 
523
 * expected by the caller. The computation does its best to avoid overflows.
 
524
 * The value is returned in <ret> if everything is fine, and a NULL is returned
 
525
 * by the function. In case of error, a pointer to the error is returned and
 
526
 * <ret> is left untouched. Values are automatically rounded up when needed.
 
527
 */
 
528
const char *parse_time_err(const char *text, unsigned *ret, unsigned unit_flags)
 
529
{
 
530
        unsigned imult, idiv;
 
531
        unsigned omult, odiv;
 
532
        unsigned value;
 
533
 
 
534
        omult = odiv = 1;
 
535
 
 
536
        switch (unit_flags & TIME_UNIT_MASK) {
 
537
        case TIME_UNIT_US:   omult = 1000000; break;
 
538
        case TIME_UNIT_MS:   omult = 1000; break;
 
539
        case TIME_UNIT_S:    break;
 
540
        case TIME_UNIT_MIN:  odiv = 60; break;
 
541
        case TIME_UNIT_HOUR: odiv = 3600; break;
 
542
        case TIME_UNIT_DAY:  odiv = 86400; break;
 
543
        default: break;
 
544
        }
 
545
 
 
546
        value = 0;
 
547
 
 
548
        while (1) {
 
549
                unsigned int j;
 
550
 
 
551
                j = *text - '0';
 
552
                if (j > 9)
 
553
                        break;
 
554
                text++;
 
555
                value *= 10;
 
556
                value += j;
 
557
        }
 
558
 
 
559
        imult = idiv = 1;
 
560
        switch (*text) {
 
561
        case '\0': /* no unit = default unit */
 
562
                imult = omult = idiv = odiv = 1;
 
563
                break;
 
564
        case 's': /* second = unscaled unit */
 
565
                break;
 
566
        case 'u': /* microsecond : "us" */
 
567
                if (text[1] == 's') {
 
568
                        idiv = 1000000;
 
569
                        text++;
 
570
                }
 
571
                break;
 
572
        case 'm': /* millisecond : "ms" or minute: "m" */
 
573
                if (text[1] == 's') {
 
574
                        idiv = 1000;
 
575
                        text++;
 
576
                } else
 
577
                        imult = 60;
 
578
                break;
 
579
        case 'h': /* hour : "h" */
 
580
                imult = 3600;
 
581
                break;
 
582
        case 'd': /* day : "d" */
 
583
                imult = 86400;
 
584
                break;
 
585
        default:
 
586
                return text;
 
587
                break;
 
588
        }
 
589
 
 
590
        if (omult % idiv == 0) { omult /= idiv; idiv = 1; }
 
591
        if (idiv % omult == 0) { idiv /= omult; omult = 1; }
 
592
        if (imult % odiv == 0) { imult /= odiv; odiv = 1; }
 
593
        if (odiv % imult == 0) { odiv /= imult; imult = 1; }
 
594
 
 
595
        value = (value * (imult * omult) + (idiv * odiv - 1)) / (idiv * odiv);
 
596
        *ret = value;
 
597
        return NULL;
 
598
}
369
599
 
370
600
/*
371
601
 * Local variables: