source: rtems/c/src/libnetworking/rtems_webserver/misc.c @ a6b4c0df

4.104.114.84.95
Last change on this file since a6b4c0df was a6b4c0df, checked in by Joel Sherrill <joel.sherrill@…>, on 09/01/00 at 10:57:21

2000-08-30 Joel Sherrill <joel@…>

  • Merged version 2.1 of GoAhead? webserver. This update was submitted by Antti P Miettinen <antti.p.miettinen@…>.
  • NOTES, base64.c, ejIntrn.h, emfdb.c, emfdb.h, md5.h, md5c.c, um.c, um.h: New files.
  • wbase64.c: Removed.
  • Makefile.am, asp.c, balloc.c, default.c, ej.h, ejlex.c, ejparse.c, form.c, h.c, handler.c, mime.c, misc.c, ringq.c, rom.c, security.c, socket.c, sym.c, uemf.c, uemf.h, url.c, value.c, webcomp.c, webmain.c, webpage.c, webrom.c, webs.c, webs.h, websuemf.c, wsIntrn.h: Modified.
  • Property mode set to 100644
File size: 15.3 KB
RevLine 
[c1cdaa0]1/*
2 * misc.c -- Miscellaneous routines.
3 *
[a6b4c0df]4 * Copyright (c) GoAhead Software Inc., 1995-2000. All Rights Reserved.
[c1cdaa0]5 *
6 * See the file "license.txt" for usage and redistribution license requirements
7 */
8
9/********************************* Includes ***********************************/
10
11#if UEMF
12        #include        "uemf.h"
13#else
14        #include        "basic/basicInternal.h"
15#endif
16
17/********************************* Defines ************************************/
18/*
[a6b4c0df]19 *      Sprintf buffer structure. Make the increment 64 so that
[c1cdaa0]20 *      a balloc can use a 64 byte block.
21 */
22
23#define STR_REALLOC             0x1                             /* Reallocate the buffer as required */
[a6b4c0df]24#define STR_INC                 64                              /* Growth increment */
[c1cdaa0]25
26typedef struct {
27        char_t  *s;                                                     /* Pointer to buffer */
28        int             size;                                           /* Current buffer size */
29        int             max;                                            /* Maximum buffer size */
30        int             count;                                          /* Buffer count */
31        int             flags;                                          /* Allocation flags */
32} strbuf_t;
33
34/*
35 *      Sprintf formatting flags
36 */
37enum flag {
38        flag_none = 0,
39        flag_minus = 1,
40        flag_plus = 2,
41        flag_space = 4,
42        flag_hash = 8,
43        flag_zero = 16,
44        flag_short = 32,
45        flag_long = 64
46};
47
48/************************** Forward Declarations ******************************/
49
50static int      dsnprintf(char_t **s, int size, char_t *fmt, va_list arg,
51                                int msize);
52static int      strnlen(char_t *s, unsigned int n);
53static void     put_char(strbuf_t *buf, char_t c);
54static void     put_string(strbuf_t *buf, char_t *s, int len,
55                                int width, int prec, enum flag f);
56static void     put_ulong(strbuf_t *buf, unsigned long int value, int base,
57                                int upper, char_t *prefix, int width, int prec, enum flag f);
58
59/************************************ Code ************************************/
60/*
61 *      "basename" returns a pointer to the last component of a pathname
[a6b4c0df]62 *  LINUX and LynxOS have their own basename function
[c1cdaa0]63 */
64
[a6b4c0df]65#if ! LINUX && ! LYNX && ! __rtems__
66char_t *basename(char_t *name)
[c1cdaa0]67{
68        char_t  *cp;
69
70#if NW || WIN
71        if (((cp = gstrrchr(name, '\\')) == NULL) &&
72                        ((cp = gstrrchr(name, '/')) == NULL)) {
73                return name;
74#else
75        if ((cp = gstrrchr(name, '/')) == NULL) {
76                return name;
77#endif
78        } else if (*(cp + 1) == '\0' && cp == name) {
79                return name;
80        } else if (*(cp + 1) == '\0' && cp != name) {
81                return T("");
82        } else {
83                return ++cp;
84        }
85}
[a6b4c0df]86#endif /* ! LINUX & ! LYNX */
[c1cdaa0]87
88/******************************************************************************/
89/*
90 *      Returns a pointer to the directory component of a pathname. bufsize is
91 *      the size of the buffer in BYTES!
92 */
93
[a6b4c0df]94char_t *dirname(char_t *buf, char_t *name, int bufsize)
[c1cdaa0]95{
[a6b4c0df]96        char_t *cp;
[c1cdaa0]97        int             len;
98
99        a_assert(name);
100        a_assert(buf);
101        a_assert(bufsize > 0);
102
103#if WIN || NW
104        if ((cp = gstrrchr(name, '/')) == NULL &&
105                (cp = gstrrchr(name, '\\')) == NULL)
106#else
107        if ((cp = gstrrchr(name, '/')) == NULL)
108#endif
109        {
110                gstrcpy(buf, T("."));
111                return buf;
112        }
113
114        if ((*(cp + 1) == '\0' && cp == name)) {
115                gstrncpy(buf, T("."), TSZ(bufsize));
116                gstrcpy(buf, T("."));
117                return buf;
118        }
119
120        len = cp - name;
121
122        if (len < bufsize) {
123                gstrncpy(buf, name, len);
124                buf[len] = '\0';
125        } else {
126                gstrncpy(buf, name, TSZ(bufsize));
127                buf[bufsize - 1] = '\0';
128        }
129
130        return buf;
131}
132
[a6b4c0df]133
[c1cdaa0]134/******************************************************************************/
135/*
136 *      sprintf and vsprintf are bad, ok. You can easily clobber memory. Use
[a6b4c0df]137 *      fmtAlloc and fmtValloc instead! These functions do _not_ support floating
[c1cdaa0]138 *      point, like %e, %f, %g...
139 */
140
[a6b4c0df]141int fmtAlloc(char_t **s, int n, char_t *fmt, ...)
[c1cdaa0]142{
143        va_list ap;
144        int             result;
145
146        a_assert(s);
147        a_assert(fmt);
148
149        *s = NULL;
150        va_start(ap, fmt);
[a6b4c0df]151        result = dsnprintf(s, n, fmt, ap, 0);
152        va_end(ap);
153        return result;
154}
155
156/******************************************************************************/
157/*
158 *      Support a static buffer version for small buffers only!
159 */
160
161int fmtStatic(char_t *s, int n, char_t *fmt, ...)
162{
163        va_list ap;
164        int             result;
165
166        a_assert(s);
167        a_assert(fmt);
168        a_assert(n <= 256);
169
170        if (n <= 0) {
171                return -1;
172        }
173        va_start(ap, fmt);
174        result = dsnprintf(&s, n, fmt, ap, 0);
[c1cdaa0]175        va_end(ap);
176        return result;
177}
178
179/******************************************************************************/
180/*
181 *      This function appends the formatted string to the supplied string,
182 *      reallocing if required.
183 */
184
[a6b4c0df]185int fmtRealloc(char_t **s, int n, int msize, char_t *fmt, ...)
[c1cdaa0]186{
187        va_list ap;
188        int             result;
189
190        a_assert(s);
191        a_assert(fmt);
192
193        if (msize == -1) {
194                *s = NULL;
195        }
196        va_start(ap, fmt);
197        result = dsnprintf(s, n, fmt, ap, msize);
198        va_end(ap);
199        return result;
200}
201
202/******************************************************************************/
203/*
204 *      A vsprintf replacement.
205 */
206
[a6b4c0df]207int fmtValloc(char_t **s, int n, char_t *fmt, va_list arg)
[c1cdaa0]208{
209        a_assert(s);
210        a_assert(fmt);
211
[a6b4c0df]212        *s = NULL;
[c1cdaa0]213        return dsnprintf(s, n, fmt, arg, 0);
214}
215
216/******************************************************************************/
217/*
[a6b4c0df]218 *      Dynamic sprintf implementation. Supports dynamic buffer allocation.
[c1cdaa0]219 *      This function can be called multiple times to grow an existing allocated
220 *      buffer. In this case, msize is set to the size of the previously allocated
221 *      buffer. The buffer will be realloced, as required. If msize is set, we
222 *      return the size of the allocated buffer for use with the next call. For
223 *      the first call, msize can be set to -1.
224 */
225
226static int dsnprintf(char_t **s, int size, char_t *fmt, va_list arg, int msize)
227{
228        strbuf_t        buf;
229        char_t          c;
230
231        a_assert(s);
232        a_assert(fmt);
233
234        memset(&buf, 0, sizeof(buf));
235        buf.s = *s;
236
237        if (*s == NULL || msize != 0) {
238                buf.max = size;
239                buf.flags |= STR_REALLOC;
240                if (msize != 0) {
241                        buf.size = max(msize, 0);
242                }
243                if (*s != NULL && msize != 0) {
244                        buf.count = gstrlen(*s);
245                }
246        } else {
247                buf.size = size;
248        }
249
250        while ((c = *fmt++) != '\0') {
251                if (c != '%' || (c = *fmt++) == '%') {
252                        put_char(&buf, c);
253                } else {
254                        enum flag f = flag_none;
255                        int width = 0;
256                        int prec = -1;
257                        for ( ; c != '\0'; c = *fmt++) {
258                                if (c == '-') {
259                                        f |= flag_minus;
260                                } else if (c == '+') {
261                                        f |= flag_plus;
262                                } else if (c == ' ') {
263                                        f |= flag_space;
264                                } else if (c == '#') {
265                                        f |= flag_hash;
266                                } else if (c == '0') {
267                                        f |= flag_zero;
268                                } else {
269                                        break;
270                                }
271                        }
272                        if (c == '*') {
273                                width = va_arg(arg, int);
274                                if (width < 0) {
275                                        f |= flag_minus;
276                                        width = -width;
277                                }
278                                c = *fmt++;
279                        } else {
[a6b4c0df]280                                for ( ; gisdigit((int)c); c = *fmt++) {
[c1cdaa0]281                                        width = width * 10 + (c - '0');
282                                }
283                        }
284                        if (c == '.') {
285                                f &= ~flag_zero;
286                                c = *fmt++;
287                                if (c == '*') {
288                                        prec = va_arg(arg, int);
289                                        c = *fmt++;
290                                } else {
[a6b4c0df]291                                        for (prec = 0; gisdigit((int)c); c = *fmt++) {
[c1cdaa0]292                                                prec = prec * 10 + (c - '0');
293                                        }
294                                }
295                        }
296                        if (c == 'h' || c == 'l') {
297                                f |= (c == 'h' ? flag_short : flag_long);
298                                c = *fmt++;
299                        }
300                        if (c == 'd' || c == 'i') {
301                                long int value;
302                                if (f & flag_short) {
303                                        value = (short int) va_arg(arg, int);
304                                } else if (f & flag_long) {
305                                        value = va_arg(arg, long int);
306                                } else {
307                                        value = va_arg(arg, int);
308                                }
309                                if (value >= 0) {
310                                        if (f & flag_plus) {
311                                                put_ulong(&buf, value, 10, 0, T("+"), width, prec, f);
312                                        } else if (f & flag_space) {
313                                                put_ulong(&buf, value, 10, 0, T(" "), width, prec, f);
314                                        } else {
315                                                put_ulong(&buf, value, 10, 0, NULL, width, prec, f);
316                                        }
317                                } else {
318                                        put_ulong(&buf, -value, 10, 0, T("-"), width, prec, f);
319                                }
320                        } else if (c == 'o' || c == 'u' || c == 'x' || c == 'X') {
321                                unsigned long int value;
322                                if (f & flag_short) {
323                                        value = (unsigned short int) va_arg(arg, unsigned int);
324                                } else if (f & flag_long) {
325                                        value = va_arg(arg, unsigned long int);
326                                } else {
327                                        value = va_arg(arg, unsigned int);
328                                }
329                                if (c == 'o') {
330                                        if (f & flag_hash && value != 0) {
331                                                put_ulong(&buf, value, 8, 0, T("0"), width, prec, f);
332                                        } else {
333                                                put_ulong(&buf, value, 8, 0, NULL, width, prec, f);
334                                        }
335                                } else if (c == 'u') {
336                                        put_ulong(&buf, value, 10, 0, NULL, width, prec, f);
337                                } else {
338                                        if (f & flag_hash && value != 0) {
339                                                if (c == 'x') {
340                                                        put_ulong(&buf, value, 16, 0, T("0x"), width,
341                                                                prec, f);
342                                                } else {
343                                                        put_ulong(&buf, value, 16, 1, T("0X"), width,
344                                                                prec, f);
345                                                }
346                                        } else {
347                                                put_ulong(&buf, value, 16, 0, NULL, width, prec, f);
348                                        }
349                                }
350
351                        } else if (c == 'c') {
352                                char_t value = va_arg(arg, int);
353                                put_char(&buf, value);
354
355                        } else if (c == 's' || c == 'S') {
356                                char_t *value = va_arg(arg, char_t *);
357                                if (value == NULL) {
358                                        put_string(&buf, T("(null)"), -1, width, prec, f);
359                                } else if (f & flag_hash) {
360                                        put_string(&buf,
361                                                value + 1, (char_t) *value, width, prec, f);
362                                } else {
363                                        put_string(&buf, value, -1, width, prec, f);
364                                }
365                        } else if (c == 'p') {
366                                void *value = va_arg(arg, void *);
367                                put_ulong(&buf,
368                                        (unsigned long int) value, 16, 0, T("0x"), width, prec, f);
369                        } else if (c == 'n') {
370                                if (f & flag_short) {
371                                        short int *value = va_arg(arg, short int *);
372                                        *value = buf.count;
373                                } else if (f & flag_long) {
374                                        long int *value = va_arg(arg, long int *);
375                                        *value = buf.count;
376                                } else {
377                                        int *value = va_arg(arg, int *);
378                                        *value = buf.count;
379                                }
380                        } else {
381                                put_char(&buf, c);
382                        }
383                }
384        }
385        if (buf.s == NULL) {
386                put_char(&buf, '\0');
387        }
388
389/*
390 *      If the user requested a dynamic buffer (*s == NULL), ensure it is returned.
391 */
392        if (*s == NULL || msize != 0) {
393                *s = buf.s;
394        }
395
396        if (*s != NULL && size > 0) {
397                if (buf.count < size) {
398                        (*s)[buf.count] = '\0';
399                } else {
400                        (*s)[buf.size - 1] = '\0';
401                }
402        }
403
404        if (msize != 0) {
405                return buf.size;
406        }
407        return buf.count;
408}
409
410/******************************************************************************/
411/*
412 *      Return the length of a string limited by a given length
413 */
414
415static int strnlen(char_t *s, unsigned int n)
416{
417        unsigned int    len;
418
419        len = gstrlen(s);
420        return min(len, n);
421}
422
423/******************************************************************************/
424/*
425 *      Add a character to a string buffer
426 */
427
428static void put_char(strbuf_t *buf, char_t c)
429{
[a6b4c0df]430        if (buf->count >= (buf->size - 1)) {
[c1cdaa0]431                if (! (buf->flags & STR_REALLOC)) {
432                        return;
433                }
434                buf->size += STR_INC;
435                if (buf->size > buf->max && buf->size > STR_INC) {
[a6b4c0df]436/*
437 *                      Caller should increase the size of the calling buffer
438 */
[c1cdaa0]439                        buf->size -= STR_INC;
440                        return;
441                }
442                if (buf->s == NULL) {
[a6b4c0df]443                        buf->s = balloc(B_L, buf->size * sizeof(char_t));
[c1cdaa0]444                } else {
[a6b4c0df]445                        buf->s = brealloc(B_L, buf->s, buf->size * sizeof(char_t));
[c1cdaa0]446                }
447        }
448        buf->s[buf->count] = c;
[a6b4c0df]449        if (c != '\0') {
450                ++buf->count;
451        }
[c1cdaa0]452}
453
454/******************************************************************************/
455/*
456 *      Add a string to a string buffer
457 */
458
459static void put_string(strbuf_t *buf, char_t *s, int len, int width,
[a6b4c0df]460                int prec, enum flag f)
[c1cdaa0]461{
462        int             i;
463
464        if (len < 0) {
465                len = strnlen(s, prec >= 0 ? prec : ULONG_MAX);
466        } else if (prec >= 0 && prec < len) {
467                len = prec;
468        }
469        if (width > len && !(f & flag_minus)) {
470                for (i = len; i < width; ++i) {
471                        put_char(buf, ' ');
472                }
473        }
474        for (i = 0; i < len; ++i) {
475                put_char(buf, s[i]);
476        }
477        if (width > len && f & flag_minus) {
478                for (i = len; i < width; ++i) {
479                        put_char(buf, ' ');
480                }
481        }
482}
483
484/******************************************************************************/
485/*
486 *      Add a long to a string buffer
487 */
488
489static void put_ulong(strbuf_t *buf, unsigned long int value, int base,
[a6b4c0df]490                int upper, char_t *prefix, int width, int prec, enum flag f)
[c1cdaa0]491{
492        unsigned long   x, x2;
493        int                             len, zeros, i;
494
495        for (len = 1, x = 1; x < ULONG_MAX / base; ++len, x = x2) {
496                x2 = x * base;
497                if (x2 > value) {
498                        break;
499                }
500        }
501        zeros = (prec > len) ? prec - len : 0;
502        width -= zeros + len;
503        if (prefix != NULL) {
504                width -= strnlen(prefix, ULONG_MAX);
505        }
506        if (!(f & flag_minus)) {
[a6b4c0df]507                if (f & flag_zero) {
508                        for (i = 0; i < width; ++i) {
509                                put_char(buf, '0');
510                        }
511                } else {
512                        for (i = 0; i < width; ++i) {
513                                put_char(buf, ' ');
514                        }
[c1cdaa0]515                }
516        }
517        if (prefix != NULL) {
518                put_string(buf, prefix, -1, 0, -1, flag_none);
519        }
520        for (i = 0; i < zeros; ++i) {
521                put_char(buf, '0');
522        }
523        for ( ; x > 0; x /= base) {
524                int digit = (value / x) % base;
525                put_char(buf, (char) ((digit < 10 ? '0' : (upper ? 'A' : 'a') - 10) +
526                        digit));
527        }
528        if (f & flag_minus) {
529                for (i = 0; i < width; ++i) {
530                        put_char(buf, ' ');
531                }
532        }
533}
534
535/******************************************************************************/
536/*
537 *      Convert an ansi string to a unicode string. On an error, we return the
538 *      original ansi string which is better than returning NULL. nBytes is the
539 *      size of the destination buffer (ubuf) in _bytes_.
540 */
541
542char_t *ascToUni(char_t *ubuf, char *str, int nBytes)
543{
544#if UNICODE
545        if (MultiByteToWideChar(CP_ACP, 0, str, nBytes / sizeof(char_t), ubuf,
546                        nBytes / sizeof(char_t)) < 0) {
547                return (char_t*) str;
548        }
549#else
550        memcpy(ubuf, str, nBytes);
551#endif
552        return ubuf;
553}
554
555/******************************************************************************/
556/*
557 *      Convert a unicode string to an ansi string. On an error, return the
558 *      original unicode string which is better than returning NULL.
559 *      N.B. nBytes is the number of _bytes_ in the destination buffer, buf.
560 */
561
[a6b4c0df]562char *uniToAsc(char *buf, char_t *ustr, int nBytes)
[c1cdaa0]563{
564#if UNICODE
565        if (WideCharToMultiByte(CP_ACP, 0, ustr, nBytes, buf, nBytes, NULL,
566                        NULL) < 0) {
567                return (char*) ustr;
568        }
569#else
570        memcpy(buf, ustr, nBytes);
571#endif
572        return (char*) buf;
573}
574
575/******************************************************************************/
576/*
577 *      allocate (balloc) a buffer and do ascii to unicode conversion into it.
[a6b4c0df]578 *      cp points to the ascii buffer.  alen is the length of the buffer to be
579 *      converted not including a terminating NULL.  Return a pointer to the
580 *      unicode buffer which must be bfree'd later.  Return NULL on failure to
581 *      get buffer.  The buffer returned is NULL terminated.
[c1cdaa0]582 */
[a6b4c0df]583
584char_t *ballocAscToUni(char *cp, int alen)
[c1cdaa0]585{
[a6b4c0df]586        char_t *unip;
[c1cdaa0]587        int ulen;
588
[a6b4c0df]589        ulen = (alen + 1) * sizeof(char_t);
[c1cdaa0]590        if ((unip = balloc(B_L, ulen)) == NULL) {
591                return NULL;
592        }
593        ascToUni(unip, cp, ulen);
[a6b4c0df]594        unip[alen] = 0;
[c1cdaa0]595        return unip;
596}
597
598/******************************************************************************/
599/*
600 *      allocate (balloc) a buffer and do unicode to ascii conversion into it.
601 *      unip points to the unicoded string. ulen is the number of characters
[a6b4c0df]602 *      in the unicode string not including a teminating null.  Return a pointer
603 *      to the ascii buffer which must be bfree'd later.  Return NULL on failure
604 *      to get buffer.  The buffer returned is NULL terminated.
[c1cdaa0]605 */
[a6b4c0df]606
607char *ballocUniToAsc(char_t *unip, int ulen)
[c1cdaa0]608{
609        char * cp;
610
[a6b4c0df]611        if ((cp = balloc(B_L, ulen+1)) == NULL) {
[c1cdaa0]612                return NULL;
613        }
614        uniToAsc(cp, unip, ulen);
[a6b4c0df]615        cp[ulen] = '\0';
[c1cdaa0]616        return cp;
617}
618
619/******************************************************************************/
[a6b4c0df]620/*
621 *      convert a hex string to an integer. The end of the string or a non-hex
622 *      character will indicate the end of the hex specification.
623 */
624
625unsigned int hextoi(char_t *hexstring)
626{
627        register char_t                 *h;
628        register unsigned int   c, v;
629
630        v = 0;
631        h = hexstring;
632        if (*h == '0' && (*(h+1) == 'x' || *(h+1) == 'X')) {
633                h += 2;
634        }
635        while ((c = (unsigned int)*h++) != 0) {
636                if (c >= '0' && c <= '9') {
637                        c -= '0';
638                } else if (c >= 'a' && c <= 'f') {
639                        c = (c - 'a') + 10;
640                } else if (c >=  'A' && c <= 'F') {
641                        c = (c - 'A') + 10;
642                } else {
643                        break;
644                }
645                v = (v * 0x10) + c;
646        }
647        return v;
648}
649
650/******************************************************************************/
651/*
652 *      convert a string to an integer. If the string starts with "0x" or "0X"
653 *      a hexidecimal conversion is done.
654 */
655
656unsigned int gstrtoi(char_t *s)
657{
658        if (*s == '0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
659                s += 2;
660                return hextoi(s);
661        }
662        return gatoi(s);
663}
664
665/******************************************************************************/
[c1cdaa0]666
Note: See TracBrowser for help on using the repository browser.