~ubuntu-branches/ubuntu/saucy/openvpn/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/jjo-ipv6-support.patch/buffer.c

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2013-05-24 17:42:45 UTC
  • mfrom: (1.1.19) (10.2.22 sid)
  • Revision ID: package-import@ubuntu.com-20130524174245-g9y6wlforycufqy5
Tags: 2.3.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  - debian/openvpn.init.d:
    + Do not use start-stop-daemon and </dev/null to avoid blocking boot.
    + Show per-VPN result messages.
    + Add "--script-security 2" by default for backwards compatabliity.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  OpenVPN -- An application to securely tunnel IP networks
3
 
 *             over a single UDP port, with support for SSL/TLS-based
4
 
 *             session authentication and key exchange,
5
 
 *             packet encryption, packet authentication, and
6
 
 *             packet compression.
7
 
 *
8
 
 *  Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
9
 
 *
10
 
 *  This program is free software; you can redistribute it and/or modify
11
 
 *  it under the terms of the GNU General Public License version 2
12
 
 *  as published by the Free Software Foundation.
13
 
 *
14
 
 *  This program is distributed in the hope that it will be useful,
15
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 *  GNU General Public License for more details.
18
 
 *
19
 
 *  You should have received a copy of the GNU General Public License
20
 
 *  along with this program (see the file COPYING included with this
21
 
 *  distribution); if not, write to the Free Software Foundation, Inc.,
22
 
 *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 
 */
24
 
 
25
 
#include "syshead.h"
26
 
 
27
 
#include "common.h"
28
 
#include "buffer.h"
29
 
#include "error.h"
30
 
#include "mtu.h"
31
 
 
32
 
#include "memdbg.h"
33
 
 
34
 
size_t
35
 
array_mult_safe (const size_t m1, const size_t m2, const size_t extra)
36
 
{
37
 
  const size_t limit = 0xFFFFFFFF;
38
 
  unsigned long long res = (unsigned long long)m1 * (unsigned long long)m2 + (unsigned long long)extra;
39
 
  if (unlikely(m1 > limit) || unlikely(m2 > limit) || unlikely(extra > limit) || unlikely(res > (unsigned long long)limit))
40
 
    msg (M_FATAL, "attemped allocation of excessively large array");
41
 
  return (size_t) res;
42
 
}
43
 
 
44
 
void
45
 
buf_size_error (const size_t size)
46
 
{
47
 
  msg (M_FATAL, "fatal buffer size error, size=%lu", (unsigned long)size);
48
 
}
49
 
 
50
 
struct buffer
51
 
#ifdef DMALLOC
52
 
alloc_buf_debug (size_t size, const char *file, int line)
53
 
#else
54
 
alloc_buf (size_t size)
55
 
#endif
56
 
{
57
 
#ifdef DMALLOC
58
 
  return alloc_buf_gc_debug (size, NULL, file, line);
59
 
#else
60
 
  return alloc_buf_gc (size, NULL);
61
 
#endif
62
 
}
63
 
 
64
 
struct buffer
65
 
#ifdef DMALLOC
66
 
alloc_buf_gc_debug (size_t size, struct gc_arena *gc, const char *file, int line)
67
 
#else
68
 
alloc_buf_gc (size_t size, struct gc_arena *gc)
69
 
#endif
70
 
{
71
 
  struct buffer buf;
72
 
  if (!buf_size_valid (size))
73
 
    buf_size_error (size);
74
 
  buf.capacity = (int)size;
75
 
  buf.offset = 0;
76
 
  buf.len = 0;
77
 
#ifdef DMALLOC
78
 
  buf.data = (uint8_t *) gc_malloc_debug (size, false, gc, file, line);
79
 
#else
80
 
  buf.data = (uint8_t *) gc_malloc (size, false, gc);
81
 
#endif
82
 
  if (size)
83
 
    *buf.data = 0;
84
 
  return buf;
85
 
}
86
 
 
87
 
struct buffer
88
 
#ifdef DMALLOC
89
 
clone_buf_debug (const struct buffer* buf, const char *file, int line)
90
 
#else
91
 
clone_buf (const struct buffer* buf)
92
 
#endif
93
 
{
94
 
  struct buffer ret;
95
 
  ret.capacity = buf->capacity;
96
 
  ret.offset = buf->offset;
97
 
  ret.len = buf->len;
98
 
#ifdef DMALLOC
99
 
  ret.data = (uint8_t *) openvpn_dmalloc (file, line, buf->capacity);
100
 
#else
101
 
  ret.data = (uint8_t *) malloc (buf->capacity);
102
 
#endif
103
 
  check_malloc_return (ret.data);
104
 
  memcpy (BPTR (&ret), BPTR (buf), BLEN (buf));
105
 
  return ret;
106
 
}
107
 
 
108
 
#ifdef BUF_INIT_TRACKING
109
 
 
110
 
bool
111
 
buf_init_debug (struct buffer *buf, int offset, const char *file, int line)
112
 
{
113
 
  buf->debug_file = file;
114
 
  buf->debug_line = line;
115
 
  return buf_init_dowork (buf, offset);
116
 
}
117
 
 
118
 
static inline int
119
 
buf_debug_line (const struct buffer *buf)
120
 
{
121
 
  return buf->debug_line;
122
 
}
123
 
 
124
 
static const char *
125
 
buf_debug_file (const struct buffer *buf)
126
 
{
127
 
  return buf->debug_file;
128
 
}
129
 
 
130
 
#else
131
 
 
132
 
#define buf_debug_line(buf) 0
133
 
#define buf_debug_file(buf) "[UNDEF]"
134
 
 
135
 
#endif
136
 
 
137
 
void
138
 
buf_clear (struct buffer *buf)
139
 
{
140
 
  if (buf->capacity > 0)
141
 
    memset (buf->data, 0, buf->capacity);
142
 
  buf->len = 0;
143
 
  buf->offset = 0;
144
 
}
145
 
 
146
 
bool
147
 
buf_assign (struct buffer *dest, const struct buffer *src)
148
 
{
149
 
  if (!buf_init (dest, src->offset))
150
 
    return false;
151
 
  return buf_write (dest, BPTR (src), BLEN (src));
152
 
}
153
 
 
154
 
struct buffer
155
 
clear_buf ()
156
 
{
157
 
  struct buffer buf;
158
 
  CLEAR (buf);
159
 
  return buf;
160
 
}
161
 
 
162
 
void
163
 
free_buf (struct buffer *buf)
164
 
{
165
 
  if (buf->data)
166
 
    free (buf->data);
167
 
  CLEAR (*buf);
168
 
}
169
 
 
170
 
/*
171
 
 * Return a buffer for write that is a subset of another buffer
172
 
 */
173
 
struct buffer
174
 
buf_sub (struct buffer *buf, int size, bool prepend)
175
 
{
176
 
  struct buffer ret;
177
 
  uint8_t *data;
178
 
 
179
 
  CLEAR (ret);
180
 
  data = prepend ? buf_prepend (buf, size) : buf_write_alloc (buf, size);
181
 
  if (data)
182
 
    {
183
 
      ret.capacity = size;
184
 
      ret.data = data;
185
 
    }
186
 
  return ret;
187
 
}
188
 
 
189
 
/*
190
 
 * printf append to a buffer with overflow check
191
 
 */
192
 
bool
193
 
buf_printf (struct buffer *buf, const char *format, ...)
194
 
{
195
 
  int ret = false;
196
 
  if (buf_defined (buf))
197
 
    {
198
 
      va_list arglist;
199
 
      uint8_t *ptr = BEND (buf);
200
 
      int cap = buf_forward_capacity (buf);
201
 
 
202
 
      if (cap > 0)
203
 
        {
204
 
          int stat;
205
 
          va_start (arglist, format);
206
 
          stat = vsnprintf ((char *)ptr, cap, format, arglist);
207
 
          va_end (arglist);
208
 
          *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */
209
 
          buf->len += (int) strlen ((char *)ptr);
210
 
          if (stat >= 0 && stat < cap)
211
 
            ret = true;
212
 
        }
213
 
    }
214
 
  return ret;
215
 
}
216
 
 
217
 
/*
218
 
 * This is necessary due to certain buggy implementations of snprintf,
219
 
 * that don't guarantee null termination for size > 0.
220
 
 *
221
 
 * This function is duplicated into service-win32/openvpnserv.c
222
 
 * Any modifications here should be done to the other place as well.
223
 
 */
224
 
 
225
 
int openvpn_snprintf(char *str, size_t size, const char *format, ...)
226
 
{
227
 
  va_list arglist;
228
 
  int ret = 0;
229
 
  if (size > 0)
230
 
    {
231
 
      va_start (arglist, format);
232
 
      ret = vsnprintf (str, size, format, arglist);
233
 
      va_end (arglist);
234
 
      str[size - 1] = 0;
235
 
    }
236
 
  return ret;
237
 
}
238
 
 
239
 
/*
240
 
 * write a string to the end of a buffer that was
241
 
 * truncated by buf_printf
242
 
 */
243
 
void
244
 
buf_catrunc (struct buffer *buf, const char *str)
245
 
{
246
 
  if (buf_forward_capacity (buf) <= 1)
247
 
    {
248
 
      int len = (int) strlen (str) + 1;
249
 
      if (len < buf_forward_capacity_total (buf))
250
 
        {
251
 
          strncpynt ((char *)(buf->data + buf->capacity - len), str, len);
252
 
        }
253
 
    }
254
 
}
255
 
 
256
 
/*
257
 
 * convert a multi-line output to one line
258
 
 */
259
 
void
260
 
convert_to_one_line (struct buffer *buf)
261
 
{
262
 
  uint8_t *cp = BPTR(buf);
263
 
  int len = BLEN(buf);
264
 
  while (len--)
265
 
    {
266
 
      if (*cp == '\n')
267
 
        *cp = '|';
268
 
      ++cp;
269
 
    }
270
 
}
271
 
 
272
 
/* NOTE: requires that string be null terminated */
273
 
void
274
 
buf_write_string_file (const struct buffer *buf, const char *filename, int fd)
275
 
{
276
 
  const int len = strlen ((char *) BPTR (buf));
277
 
  const int size = write (fd, BPTR (buf), len);
278
 
  if (size != len)
279
 
    msg (M_ERR, "Write error on file '%s'", filename);
280
 
}
281
 
 
282
 
/*
283
 
 * Garbage collection
284
 
 */
285
 
 
286
 
void *
287
 
#ifdef DMALLOC
288
 
gc_malloc_debug (size_t size, bool clear, struct gc_arena *a, const char *file, int line)
289
 
#else
290
 
gc_malloc (size_t size, bool clear, struct gc_arena *a)
291
 
#endif
292
 
{
293
 
  void *ret;
294
 
  if (a)
295
 
    {
296
 
      struct gc_entry *e;
297
 
#ifdef DMALLOC
298
 
      e = (struct gc_entry *) openvpn_dmalloc (file, line, size + sizeof (struct gc_entry));
299
 
#else
300
 
      e = (struct gc_entry *) malloc (size + sizeof (struct gc_entry));
301
 
#endif
302
 
      check_malloc_return (e);
303
 
      ret = (char *) e + sizeof (struct gc_entry);
304
 
      e->next = a->list;
305
 
      a->list = e;
306
 
    }
307
 
  else
308
 
    {
309
 
#ifdef DMALLOC
310
 
      ret = openvpn_dmalloc (file, line, size);
311
 
#else
312
 
      ret = malloc (size);
313
 
#endif
314
 
      check_malloc_return (ret);
315
 
    }
316
 
#ifndef ZERO_BUFFER_ON_ALLOC
317
 
  if (clear)
318
 
#endif
319
 
    memset (ret, 0, size);
320
 
  return ret;
321
 
}
322
 
 
323
 
void
324
 
x_gc_free (struct gc_arena *a)
325
 
{
326
 
  struct gc_entry *e;
327
 
  e = a->list;
328
 
  a->list = NULL;
329
 
  
330
 
  while (e != NULL)
331
 
    {
332
 
      struct gc_entry *next = e->next;
333
 
      free (e);
334
 
      e = next;
335
 
    }
336
 
}
337
 
 
338
 
/*
339
 
 * Transfer src arena to dest, resetting src to an empty arena.
340
 
 */
341
 
void
342
 
gc_transfer (struct gc_arena *dest, struct gc_arena *src)
343
 
{
344
 
  if (dest && src)
345
 
    {
346
 
      struct gc_entry *e = src->list;
347
 
      if (e)
348
 
        {
349
 
          while (e->next != NULL)
350
 
            e = e->next;
351
 
          e->next = dest->list;
352
 
          dest->list = src->list;
353
 
          src->list = NULL;
354
 
        }
355
 
    }
356
 
}
357
 
 
358
 
/*
359
 
 * Hex dump -- Output a binary buffer to a hex string and return it.
360
 
 */
361
 
 
362
 
char *
363
 
format_hex_ex (const uint8_t *data, int size, int maxoutput,
364
 
               int space_break, const char* separator,
365
 
               struct gc_arena *gc)
366
 
{
367
 
  struct buffer out = alloc_buf_gc (maxoutput ? maxoutput :
368
 
                                    ((size * 2) + (size / space_break) * (int) strlen (separator) + 2),
369
 
                                    gc);
370
 
  int i;
371
 
  for (i = 0; i < size; ++i)
372
 
    {
373
 
      if (separator && i && !(i % space_break))
374
 
        buf_printf (&out, "%s", separator);
375
 
      buf_printf (&out, "%02x", data[i]);
376
 
    }
377
 
  buf_catrunc (&out, "[more...]");
378
 
  return (char *)out.data;
379
 
}
380
 
 
381
 
/*
382
 
 * remove specific trailing character
383
 
 */
384
 
 
385
 
void
386
 
buf_rmtail (struct buffer *buf, uint8_t remove)
387
 
{
388
 
  uint8_t *cp = BLAST(buf);
389
 
  if (cp && *cp == remove)
390
 
    {
391
 
      *cp = '\0';
392
 
      --buf->len;
393
 
    }
394
 
}
395
 
 
396
 
/*
397
 
 * force a null termination even it requires
398
 
 * truncation of the last char.
399
 
 */
400
 
void
401
 
buf_null_terminate (struct buffer *buf)
402
 
{
403
 
  char *last = (char *) BLAST (buf);
404
 
  if (last && *last == '\0') /* already terminated? */
405
 
    return;
406
 
 
407
 
  if (!buf_safe (buf, 1))    /* make space for trailing null */
408
 
    buf_inc_len (buf, -1);
409
 
 
410
 
  buf_write_u8 (buf, 0);
411
 
}
412
 
 
413
 
/*
414
 
 * Remove trailing \r and \n chars and ensure
415
 
 * null termination.
416
 
 */
417
 
void
418
 
buf_chomp (struct buffer *buf)
419
 
{
420
 
  while (true)
421
 
    {
422
 
      char *last = (char *) BLAST (buf);
423
 
      if (!last)
424
 
        break;
425
 
      if (char_class (*last, CC_CRLF|CC_NULL))
426
 
        {
427
 
          if (!buf_inc_len (buf, -1))
428
 
            break;
429
 
        }
430
 
      else
431
 
        break;
432
 
    }
433
 
  buf_null_terminate (buf);
434
 
}
435
 
 
436
 
const char *
437
 
skip_leading_whitespace (const char *str)
438
 
{
439
 
  while (*str)
440
 
    {
441
 
      const char c = *str;
442
 
      if (!(c == ' ' || c == '\t'))
443
 
        break;
444
 
      ++str;
445
 
    }
446
 
  return str;
447
 
}
448
 
 
449
 
/*
450
 
 * like buf_null_terminate, but operate on strings
451
 
 */
452
 
void
453
 
string_null_terminate (char *str, int len, int capacity)
454
 
{
455
 
  ASSERT (len >= 0 && len <= capacity && capacity > 0);
456
 
  if (len < capacity)
457
 
    *(str + len) = '\0';
458
 
  else if (len == capacity)
459
 
    *(str + len - 1) = '\0';
460
 
}
461
 
 
462
 
/*
463
 
 * Remove trailing \r and \n chars.
464
 
 */
465
 
void
466
 
chomp (char *str)
467
 
{
468
 
  rm_trailing_chars (str, "\r\n");
469
 
}
470
 
 
471
 
/*
472
 
 * Remove trailing chars
473
 
 */
474
 
void
475
 
rm_trailing_chars (char *str, const char *what_to_delete)
476
 
{
477
 
  bool modified;
478
 
  do {
479
 
    const int len = strlen (str);
480
 
    modified = false;
481
 
    if (len > 0)
482
 
      {
483
 
        char *cp = str + (len - 1);
484
 
        if (strchr (what_to_delete, *cp) != NULL)
485
 
          {
486
 
            *cp = '\0';
487
 
            modified = true;
488
 
          }
489
 
      }
490
 
  } while (modified);
491
 
}
492
 
 
493
 
/*
494
 
 * Allocate a string
495
 
 */
496
 
char *
497
 
#ifdef DMALLOC
498
 
string_alloc_debug (const char *str, struct gc_arena *gc, const char *file, int line)
499
 
#else
500
 
string_alloc (const char *str, struct gc_arena *gc)
501
 
#endif
502
 
{
503
 
  if (str)
504
 
    {
505
 
      const int n = strlen (str) + 1;
506
 
      char *ret;
507
 
 
508
 
#ifdef DMALLOC
509
 
      ret = (char *) gc_malloc_debug (n, false, gc, file, line);
510
 
#else
511
 
      ret = (char *) gc_malloc (n, false, gc);
512
 
#endif
513
 
      memcpy (ret, str, n);
514
 
      return ret;
515
 
    }
516
 
  else
517
 
    return NULL;
518
 
}
519
 
 
520
 
/*
521
 
 * Erase all characters in a string
522
 
 */
523
 
void
524
 
string_clear (char *str)
525
 
{
526
 
  if (str)
527
 
    {
528
 
      const int len = strlen (str);
529
 
      if (len > 0)
530
 
        memset (str, 0, len);
531
 
    }
532
 
}
533
 
 
534
 
/*
535
 
 * Return the length of a string array
536
 
 */
537
 
int
538
 
string_array_len (const char **array)
539
 
{
540
 
  int i = 0;
541
 
  if (array)
542
 
    {
543
 
      while (array[i])
544
 
        ++i;
545
 
    }
546
 
  return i;
547
 
}
548
 
 
549
 
char *
550
 
print_argv (const char **p, struct gc_arena *gc, const unsigned int flags)
551
 
{
552
 
  struct buffer out = alloc_buf_gc (256, gc);
553
 
  int i = 0;
554
 
  for (;;)
555
 
    {
556
 
      const char *cp = *p++;
557
 
      if (!cp)
558
 
        break;
559
 
      if (i)
560
 
        buf_printf (&out, " ");
561
 
      if (flags & PA_BRACKET)
562
 
        buf_printf (&out, "[%s]", cp);
563
 
      else
564
 
        buf_printf (&out, "%s", cp);
565
 
      ++i;
566
 
    }
567
 
  return BSTR (&out);
568
 
}
569
 
 
570
 
/*
571
 
 * Allocate a string inside a buffer
572
 
 */
573
 
struct buffer
574
 
#ifdef DMALLOC
575
 
string_alloc_buf_debug (const char *str, struct gc_arena *gc, const char *file, int line)
576
 
#else
577
 
string_alloc_buf (const char *str, struct gc_arena *gc)
578
 
#endif
579
 
{
580
 
  struct buffer buf;
581
 
 
582
 
  ASSERT (str);
583
 
 
584
 
#ifdef DMALLOC
585
 
  buf_set_read (&buf, (uint8_t*) string_alloc_debug (str, gc, file, line), strlen (str) + 1);
586
 
#else
587
 
  buf_set_read (&buf, (uint8_t*) string_alloc (str, gc), strlen (str) + 1);
588
 
#endif
589
 
 
590
 
  if (buf.len > 0) /* Don't count trailing '\0' as part of length */
591
 
    --buf.len;
592
 
 
593
 
  return buf;
594
 
}
595
 
 
596
 
/*
597
 
 * String comparison
598
 
 */
599
 
 
600
 
bool
601
 
buf_string_match_head_str (const struct buffer *src, const char *match)
602
 
{
603
 
  const int size = strlen (match);
604
 
  if (size < 0 || size > src->len)
605
 
    return false;
606
 
  return memcmp (BPTR (src), match, size) == 0;
607
 
}
608
 
 
609
 
bool
610
 
buf_string_compare_advance (struct buffer *src, const char *match)
611
 
{
612
 
  if (buf_string_match_head_str (src, match))
613
 
    {
614
 
      buf_advance (src, strlen (match));
615
 
      return true;
616
 
    }
617
 
  else
618
 
    return false;
619
 
}
620
 
 
621
 
int
622
 
buf_substring_len (const struct buffer *buf, int delim)
623
 
{
624
 
  int i = 0;
625
 
  struct buffer tmp = *buf;
626
 
  int c;
627
 
 
628
 
  while ((c = buf_read_u8 (&tmp)) >= 0)
629
 
    {
630
 
      ++i;
631
 
      if (c == delim)
632
 
        return i;
633
 
    }
634
 
  return -1;
635
 
}
636
 
 
637
 
/*
638
 
 * String parsing
639
 
 */
640
 
 
641
 
bool
642
 
buf_parse (struct buffer *buf, const int delim, char *line, const int size)
643
 
{
644
 
  bool eol = false;
645
 
  int n = 0;
646
 
  int c;
647
 
 
648
 
  ASSERT (size > 0);
649
 
 
650
 
  do
651
 
    {
652
 
      c = buf_read_u8 (buf);
653
 
      if (c < 0)
654
 
        eol = true;
655
 
      if (c <= 0 || c == delim)
656
 
        c = 0;
657
 
      if (n >= size)
658
 
        break;
659
 
      line[n++] = c;
660
 
    }
661
 
  while (c);
662
 
 
663
 
  line[size-1] = '\0';
664
 
  return !(eol && !strlen (line));
665
 
}
666
 
 
667
 
/*
668
 
 * Print a string which might be NULL
669
 
 */
670
 
const char *
671
 
np (const char *str)
672
 
{
673
 
  if (str)
674
 
    return str;
675
 
  else
676
 
    return "[NULL]";
677
 
}
678
 
 
679
 
/*
680
 
 * Classify and mutate strings based on character types.
681
 
 */
682
 
 
683
 
bool
684
 
char_class (const unsigned char c, const unsigned int flags)
685
 
{
686
 
  if (!flags)
687
 
    return false;
688
 
  if (flags & CC_ANY)
689
 
    return true;
690
 
 
691
 
  if ((flags & CC_NULL) && c == '\0')
692
 
    return true;
693
 
 
694
 
  if ((flags & CC_ALNUM) && isalnum (c))
695
 
    return true;
696
 
  if ((flags & CC_ALPHA) && isalpha (c))
697
 
    return true;
698
 
  if ((flags & CC_ASCII) && isascii (c))
699
 
    return true;
700
 
  if ((flags & CC_CNTRL) && iscntrl (c))
701
 
    return true;
702
 
  if ((flags & CC_DIGIT) && isdigit (c))
703
 
    return true;
704
 
  if ((flags & CC_PRINT) && isprint (c))
705
 
    return true;
706
 
  if ((flags & CC_PUNCT) && ispunct (c))
707
 
    return true;    
708
 
  if ((flags & CC_SPACE) && isspace (c))
709
 
    return true;
710
 
  if ((flags & CC_XDIGIT) && isxdigit (c))
711
 
    return true;
712
 
 
713
 
  if ((flags & CC_BLANK) && (c == ' ' || c == '\t'))
714
 
    return true;
715
 
  if ((flags & CC_NEWLINE) && c == '\n')
716
 
    return true;
717
 
  if ((flags & CC_CR) && c == '\r')
718
 
    return true;
719
 
 
720
 
  if ((flags & CC_BACKSLASH) && c == '\\')
721
 
    return true;
722
 
  if ((flags & CC_UNDERBAR) && c == '_')
723
 
    return true;
724
 
  if ((flags & CC_DASH) && c == '-')
725
 
    return true;
726
 
  if ((flags & CC_DOT) && c == '.')
727
 
    return true;
728
 
  if ((flags & CC_COMMA) && c == ',')
729
 
    return true;
730
 
  if ((flags & CC_COLON) && c == ':')
731
 
    return true;
732
 
  if ((flags & CC_SLASH) && c == '/')
733
 
    return true;
734
 
  if ((flags & CC_SINGLE_QUOTE) && c == '\'')
735
 
    return true;
736
 
  if ((flags & CC_DOUBLE_QUOTE) && c == '\"')
737
 
    return true;
738
 
  if ((flags & CC_REVERSE_QUOTE) && c == '`')
739
 
    return true;
740
 
  if ((flags & CC_AT) && c == '@')
741
 
    return true;
742
 
  if ((flags & CC_EQUAL) && c == '=')
743
 
    return true;
744
 
 
745
 
  return false;
746
 
}
747
 
 
748
 
static inline bool
749
 
char_inc_exc (const char c, const unsigned int inclusive, const unsigned int exclusive)
750
 
{
751
 
  return char_class (c, inclusive) && !char_class (c, exclusive);
752
 
}
753
 
 
754
 
bool
755
 
string_class (const char *str, const unsigned int inclusive, const unsigned int exclusive)
756
 
{
757
 
  char c;
758
 
  ASSERT (str);
759
 
  while ((c = *str++))
760
 
    {
761
 
      if (!char_inc_exc (c, inclusive, exclusive))
762
 
        return false;
763
 
    }
764
 
  return true;
765
 
}
766
 
 
767
 
/*
768
 
 * Modify string in place.
769
 
 * Guaranteed to not increase string length.
770
 
 */
771
 
bool
772
 
string_mod (char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
773
 
{
774
 
  const char *in = str;
775
 
  bool ret = true;
776
 
 
777
 
  ASSERT (str);
778
 
 
779
 
  while (true)
780
 
    {
781
 
      char c = *in++;
782
 
      if (c)
783
 
        {
784
 
          if (!char_inc_exc (c, inclusive, exclusive))
785
 
            {
786
 
              c = replace;
787
 
              ret = false;
788
 
            }
789
 
          if (c)
790
 
            *str++ = c;
791
 
        }
792
 
      else
793
 
        {
794
 
          *str = '\0';
795
 
          break;
796
 
        }
797
 
    }
798
 
  return ret;
799
 
}
800
 
 
801
 
const char *
802
 
string_mod_const (const char *str,
803
 
                  const unsigned int inclusive,
804
 
                  const unsigned int exclusive,
805
 
                  const char replace,
806
 
                  struct gc_arena *gc)
807
 
{
808
 
  if (str)
809
 
    {
810
 
      char *buf = string_alloc (str, gc);
811
 
      string_mod (buf, inclusive, exclusive, replace);
812
 
      return buf;
813
 
    }
814
 
  else
815
 
    return NULL;
816
 
}
817
 
 
818
 
void
819
 
string_replace_leading (char *str, const char match, const char replace)
820
 
{
821
 
  ASSERT (match != '\0');
822
 
  while (*str)
823
 
    {
824
 
      if (*str == match)
825
 
        *str = replace;
826
 
      else
827
 
        break;
828
 
      ++str;
829
 
    }
830
 
}
831
 
 
832
 
#ifdef CHARACTER_CLASS_DEBUG
833
 
 
834
 
#define CC_INCLUDE    (CC_PRINT)
835
 
#define CC_EXCLUDE    (0)
836
 
#define CC_REPLACE    ('.')
837
 
 
838
 
void
839
 
character_class_debug (void)
840
 
{
841
 
  char buf[256];
842
 
 
843
 
  while (fgets (buf, sizeof (buf), stdin) != NULL)
844
 
    {
845
 
      string_mod (buf, CC_INCLUDE, CC_EXCLUDE, CC_REPLACE);
846
 
      printf ("%s", buf);
847
 
    }
848
 
}
849
 
 
850
 
#endif
851
 
 
852
 
#ifdef VERIFY_ALIGNMENT
853
 
void
854
 
valign4 (const struct buffer *buf, const char *file, const int line)
855
 
{
856
 
  if (buf && buf->len)
857
 
    {
858
 
      int msglevel = D_ALIGN_DEBUG;
859
 
      const unsigned int u = (unsigned int) BPTR (buf);
860
 
 
861
 
      if (u & (PAYLOAD_ALIGN-1))
862
 
        msglevel = D_ALIGN_ERRORS;
863
 
 
864
 
      msg (msglevel, "%sAlignment at %s/%d ptr=" ptr_format " OLC=%d/%d/%d I=%s/%d",
865
 
           (msglevel == D_ALIGN_ERRORS) ? "ERROR: " : "",
866
 
           file,
867
 
           line,
868
 
           (ptr_type)buf->data,
869
 
           buf->offset,
870
 
           buf->len,
871
 
           buf->capacity,
872
 
           buf_debug_file (buf),
873
 
           buf_debug_line (buf));
874
 
    }
875
 
}
876
 
#endif
877
 
 
878
 
/*
879
 
 * struct buffer_list
880
 
 */
881
 
 
882
 
#ifdef ENABLE_BUFFER_LIST
883
 
 
884
 
struct buffer_list *
885
 
buffer_list_new (const int max_size)
886
 
{
887
 
  struct buffer_list *ret;
888
 
  ALLOC_OBJ_CLEAR (ret, struct buffer_list);
889
 
  ret->max_size = max_size;
890
 
  ret->size = 0;
891
 
  return ret;
892
 
}
893
 
 
894
 
void
895
 
buffer_list_free (struct buffer_list *ol)
896
 
{
897
 
  if (ol)
898
 
    {
899
 
      buffer_list_reset (ol);
900
 
      free (ol);
901
 
    }
902
 
}
903
 
 
904
 
bool
905
 
buffer_list_defined (const struct buffer_list *ol)
906
 
{
907
 
  return ol->head != NULL;
908
 
}
909
 
 
910
 
void
911
 
buffer_list_reset (struct buffer_list *ol)
912
 
{
913
 
  struct buffer_entry *e = ol->head;
914
 
  while (e)
915
 
    {
916
 
      struct buffer_entry *next = e->next;
917
 
      free_buf (&e->buf);
918
 
      free (e);
919
 
      e = next;
920
 
    }
921
 
  ol->head = ol->tail = NULL;
922
 
  ol->size = 0;
923
 
}
924
 
 
925
 
void
926
 
buffer_list_push (struct buffer_list *ol, const unsigned char *str)
927
 
{
928
 
  if (str)
929
 
    {
930
 
      const size_t len = strlen ((const char *)str);
931
 
      struct buffer_entry *e = buffer_list_push_data (ol, str, len+1);
932
 
      if (e)
933
 
        e->buf.len = len; /* Don't count trailing '\0' as part of length */
934
 
    }
935
 
}
936
 
 
937
 
struct buffer_entry *
938
 
buffer_list_push_data (struct buffer_list *ol, const uint8_t *data, size_t size)
939
 
{
940
 
  struct buffer_entry *e = NULL;
941
 
  if (data && (!ol->max_size || ol->size < ol->max_size))
942
 
    {
943
 
      ALLOC_OBJ_CLEAR (e, struct buffer_entry);
944
 
 
945
 
      ++ol->size;
946
 
      if (ol->tail)
947
 
        {
948
 
          ASSERT (ol->head);
949
 
          ol->tail->next = e;
950
 
        }
951
 
      else
952
 
        {
953
 
          ASSERT (!ol->head);
954
 
          ol->head = e;
955
 
        }
956
 
      e->buf = alloc_buf (size);
957
 
      memcpy (e->buf.data, data, size);
958
 
      e->buf.len = (int)size;
959
 
      ol->tail = e;
960
 
    }
961
 
  return e;
962
 
}
963
 
 
964
 
struct buffer *
965
 
buffer_list_peek (struct buffer_list *ol)
966
 
{
967
 
  if (ol && ol->head)
968
 
    return &ol->head->buf;
969
 
  else
970
 
    return NULL;
971
 
}
972
 
 
973
 
void
974
 
buffer_list_aggregate (struct buffer_list *bl, const size_t max)
975
 
{
976
 
  if (bl->head)
977
 
    {
978
 
      struct buffer_entry *more = bl->head;
979
 
      size_t size = 0;
980
 
      int count = 0;
981
 
      for (count = 0; more && size <= max; ++count)
982
 
        {
983
 
          size += BLEN(&more->buf);
984
 
          more = more->next;
985
 
        }
986
 
 
987
 
      if (count >= 2)
988
 
        {
989
 
          int i;
990
 
          struct buffer_entry *e = bl->head, *f;
991
 
 
992
 
          ALLOC_OBJ_CLEAR (f, struct buffer_entry);
993
 
          f->buf.data = malloc (size);
994
 
          check_malloc_return (f->buf.data);
995
 
          f->buf.capacity = size;
996
 
          for (i = 0; e && i < count; ++i)
997
 
            {
998
 
              struct buffer_entry *next = e->next;
999
 
              buf_copy (&f->buf, &e->buf);
1000
 
              free_buf (&e->buf);
1001
 
              free (e);
1002
 
              e = next;
1003
 
            }
1004
 
          bl->head = f;
1005
 
          f->next = more;
1006
 
          if (!more)
1007
 
            bl->tail = f;
1008
 
        }
1009
 
    }
1010
 
}
1011
 
 
1012
 
void
1013
 
buffer_list_pop (struct buffer_list *ol)
1014
 
{
1015
 
  if (ol && ol->head)
1016
 
    {
1017
 
      struct buffer_entry *e = ol->head->next;
1018
 
      free_buf (&ol->head->buf);
1019
 
      free (ol->head);
1020
 
      ol->head = e;
1021
 
      --ol->size;
1022
 
      if (!e)
1023
 
        ol->tail = NULL;
1024
 
    }
1025
 
}
1026
 
 
1027
 
void
1028
 
buffer_list_advance (struct buffer_list *ol, int n)
1029
 
{
1030
 
  if (ol->head)
1031
 
    {
1032
 
      struct buffer *buf = &ol->head->buf;
1033
 
      ASSERT (buf_advance (buf, n));
1034
 
      if (!BLEN (buf))
1035
 
        buffer_list_pop (ol);
1036
 
    }
1037
 
}
1038
 
 
1039
 
struct buffer_list *
1040
 
buffer_list_file (const char *fn, int max_line_len)
1041
 
{
1042
 
  FILE *fp = fopen (fn, "r");
1043
 
  struct buffer_list *bl = NULL;
1044
 
 
1045
 
  if (fp)
1046
 
    {
1047
 
      char *line = (char *) malloc (max_line_len);
1048
 
      if (line)
1049
 
        {
1050
 
          bl = buffer_list_new (0);
1051
 
          while (fgets (line, max_line_len, fp) != NULL)
1052
 
            buffer_list_push (bl, (unsigned char *)line);
1053
 
          free (line);
1054
 
        }
1055
 
      fclose (fp);
1056
 
    }
1057
 
  return bl;
1058
 
}
1059
 
 
1060
 
#endif