~ubuntu-branches/ubuntu/vivid/sed/vivid

« back to all changes in this revision

Viewing changes to .pc/debian-changes/sed/utils.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2014-02-13 11:32:23 UTC
  • mfrom: (19.1.4 sid)
  • Revision ID: package-import@ubuntu.com-20140213113223-7wbjzudiiwnipc7s
Tags: 4.2.2-4ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Mark sed Multi-Arch: foreign.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  Functions from hack's utils library.
 
2
    Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003, 2008, 2009, 2011
 
3
    Free Software Foundation, Inc.
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 3, or (at your option)
 
8
    any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program; if not, write to the Free Software
 
17
    Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#include <stdio.h>
 
22
#include <stdarg.h>
 
23
#include <errno.h>
 
24
#include <string.h>
 
25
#include <stdlib.h>
 
26
#include <sys/types.h>
 
27
#include <sys/stat.h>
 
28
#include <unistd.h>
 
29
#include <limits.h>
 
30
 
 
31
#include "utils.h"
 
32
#include "pathmax.h"
 
33
#include "fwriting.h"
 
34
 
 
35
const char *myname;
 
36
 
 
37
/* Store information about files opened with ck_fopen
 
38
   so that error messages from ck_fread, ck_fwrite, etc. can print the
 
39
   name of the file that had the error */
 
40
 
 
41
struct open_file
 
42
  {
 
43
    FILE *fp;
 
44
    char *name;
 
45
    struct open_file *link;
 
46
    unsigned temp : 1;
 
47
  };
 
48
 
 
49
static struct open_file *open_files = NULL;
 
50
static void do_ck_fclose (FILE *fp);
 
51
 
 
52
/* Print an error message and exit */
 
53
 
 
54
void
 
55
panic(const char *str, ...)
 
56
{
 
57
  va_list ap;
 
58
 
 
59
  fprintf(stderr, "%s: ", myname);
 
60
  va_start(ap, str);
 
61
  vfprintf(stderr, str, ap);
 
62
  va_end(ap);
 
63
  putc('\n', stderr);
 
64
 
 
65
  /* Unlink the temporary files.  */
 
66
  while (open_files)
 
67
    {
 
68
      if (open_files->temp)
 
69
        {
 
70
          fclose (open_files->fp);
 
71
          errno = 0;
 
72
          unlink (open_files->name);
 
73
          if (errno != 0)
 
74
            fprintf (stderr, _("cannot remove %s: %s"), open_files->name, strerror (errno));
 
75
        }
 
76
 
 
77
      open_files = open_files->link;
 
78
    }
 
79
 
 
80
  exit(4);
 
81
}
 
82
 
 
83
 
 
84
/* Internal routine to get a filename from open_files */
 
85
static const char *utils_fp_name (FILE *fp);
 
86
static const char *
 
87
utils_fp_name(fp)
 
88
  FILE *fp;
 
89
{
 
90
  struct open_file *p;
 
91
 
 
92
  for (p=open_files; p; p=p->link)
 
93
    if (p->fp == fp)
 
94
      return p->name;
 
95
  if (fp == stdin)
 
96
    return "stdin";
 
97
  else if (fp == stdout)
 
98
    return "stdout";
 
99
  else if (fp == stderr)
 
100
    return "stderr";
 
101
 
 
102
  return "<unknown>";
 
103
}
 
104
 
 
105
static void
 
106
register_open_file (fp, name, temp)
 
107
  FILE *fp;
 
108
  const char *name;
 
109
  int temp;
 
110
{
 
111
  struct open_file *p;
 
112
  for (p=open_files; p; p=p->link)
 
113
    {
 
114
      if (fp == p->fp)
 
115
        {
 
116
          free(p->name);
 
117
          break;
 
118
        }
 
119
    }
 
120
  if (!p)
 
121
    {
 
122
      p = MALLOC(1, struct open_file);
 
123
      p->link = open_files;
 
124
      open_files = p;
 
125
    }
 
126
  p->name = ck_strdup(name);
 
127
  p->fp = fp;
 
128
  p->temp = false;
 
129
}
 
130
 
 
131
/* Panic on failing fopen */
 
132
FILE *
 
133
ck_fopen(name, mode, fail)
 
134
  const char *name;
 
135
  const char *mode;
 
136
  int fail;
 
137
{
 
138
  FILE *fp;
 
139
 
 
140
  fp = fopen (name, mode);
 
141
  if (!fp)
 
142
    {
 
143
      if (fail)
 
144
        panic(_("couldn't open file %s: %s"), name, strerror(errno));
 
145
 
 
146
      return NULL;
 
147
    }
 
148
 
 
149
  register_open_file (fp, name, false);
 
150
  return fp;
 
151
}
 
152
 
 
153
/* Panic on failing fdopen */
 
154
FILE *
 
155
ck_fdopen(fd, name, mode, fail)
 
156
  int fd;
 
157
  const char *name;
 
158
  const char *mode;
 
159
  int fail;
 
160
{
 
161
  FILE *fp;
 
162
 
 
163
  fp = fdopen (fd, mode);
 
164
  if (!fp)
 
165
    {
 
166
      if (fail)
 
167
        panic(_("couldn't attach to %s: %s"), name, strerror(errno));
 
168
 
 
169
      return NULL;
 
170
    }
 
171
 
 
172
  register_open_file (fp, name, false);
 
173
  return fp;
 
174
}
 
175
 
 
176
FILE *
 
177
ck_mkstemp (p_filename, tmpdir, base, mode)
 
178
  char **p_filename;
 
179
  const char *base, *tmpdir;
 
180
  const char *mode;
 
181
{
 
182
  char *template;
 
183
  FILE *fp;
 
184
  int fd;
 
185
  int save_umask;
 
186
 
 
187
  if (tmpdir == NULL)
 
188
    tmpdir = getenv("TMPDIR");
 
189
  if (tmpdir == NULL)
 
190
    {
 
191
      tmpdir = getenv("TMP");
 
192
      if (tmpdir == NULL)
 
193
#ifdef P_tmpdir
 
194
        tmpdir = P_tmpdir;
 
195
#else
 
196
        tmpdir = "/tmp";
 
197
#endif
 
198
    }
 
199
 
 
200
  template = xmalloc (strlen (tmpdir) + strlen (base) + 8);
 
201
  sprintf (template, "%s/%sXXXXXX", tmpdir, base);
 
202
 
 
203
   /* The ownership might change, so omit some permissions at first
 
204
      so unauthorized users cannot nip in before the file is ready.
 
205
    
 
206
      mkstemp forces O_BINARY on cygwin, so use mkostemp instead.  */
 
207
  save_umask = umask (0700);
 
208
  fd = mkostemp (template, 0);
 
209
  umask (save_umask);
 
210
  if (fd == -1)
 
211
    panic(_("couldn't open temporary file %s: %s"), template, strerror(errno));
 
212
 
 
213
  *p_filename = template;
 
214
  fp = fdopen (fd, mode);
 
215
  register_open_file (fp, template, true);
 
216
  return fp;
 
217
}
 
218
 
 
219
/* Panic on failing fwrite */
 
220
void
 
221
ck_fwrite(ptr, size, nmemb, stream)
 
222
  const void *ptr;
 
223
  size_t size;
 
224
  size_t nmemb;
 
225
  FILE *stream;
 
226
{
 
227
  clearerr(stream);
 
228
  if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
 
229
    panic(ngettext("couldn't write %d item to %s: %s",
 
230
                   "couldn't write %d items to %s: %s", nmemb), 
 
231
                nmemb, utils_fp_name(stream), strerror(errno));
 
232
}
 
233
 
 
234
/* Panic on failing fread */
 
235
size_t
 
236
ck_fread(ptr, size, nmemb, stream)
 
237
  void *ptr;
 
238
  size_t size;
 
239
  size_t nmemb;
 
240
  FILE *stream;
 
241
{
 
242
  clearerr(stream);
 
243
  if (size && (nmemb=fread(ptr, size, nmemb, stream)) <= 0 && ferror(stream))
 
244
    panic(_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
 
245
 
 
246
  return nmemb;
 
247
}
 
248
 
 
249
size_t
 
250
ck_getdelim(text, buflen, buffer_delimiter, stream)
 
251
  char **text;
 
252
  size_t *buflen;
 
253
  char buffer_delimiter;
 
254
  FILE *stream;
 
255
{
 
256
  ssize_t result;
 
257
  bool error;
 
258
 
 
259
  error = ferror (stream);
 
260
  if (!error)
 
261
    {
 
262
      result = getdelim (text, buflen, buffer_delimiter, stream);
 
263
      error = ferror (stream);
 
264
    }
 
265
 
 
266
  if (error)
 
267
    panic (_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
 
268
 
 
269
  return result;
 
270
}
 
271
 
 
272
/* Panic on failing fflush */
 
273
void
 
274
ck_fflush(stream)
 
275
  FILE *stream;
 
276
{
 
277
  if (!fwriting(stream))
 
278
    return;
 
279
 
 
280
  clearerr(stream);
 
281
  if (fflush(stream) == EOF && errno != EBADF)
 
282
    panic("couldn't flush %s: %s", utils_fp_name(stream), strerror(errno));
 
283
}
 
284
 
 
285
/* Panic on failing fclose */
 
286
void
 
287
ck_fclose(stream)
 
288
  FILE *stream;
 
289
{
 
290
  struct open_file r;
 
291
  struct open_file *prev;
 
292
  struct open_file *cur;
 
293
 
 
294
  /* a NULL stream means to close all files */
 
295
  r.link = open_files;
 
296
  prev = &r;
 
297
  while ( (cur = prev->link) )
 
298
    {
 
299
      if (!stream || stream == cur->fp)
 
300
        {
 
301
          do_ck_fclose (cur->fp);
 
302
          prev->link = cur->link;
 
303
          free(cur->name);
 
304
          free(cur);
 
305
        }
 
306
      else
 
307
        prev = cur;
 
308
    }
 
309
 
 
310
  open_files = r.link;
 
311
 
 
312
  /* Also care about stdout, because if it is redirected the
 
313
     last output operations might fail and it is important
 
314
     to signal this as an error (perhaps to make). */
 
315
  if (!stream)
 
316
    {
 
317
      do_ck_fclose (stdout);
 
318
      do_ck_fclose (stderr);
 
319
    }
 
320
}
 
321
 
 
322
/* Close a single file. */
 
323
void
 
324
do_ck_fclose(fp)
 
325
  FILE *fp;
 
326
{
 
327
  ck_fflush(fp);
 
328
  clearerr(fp);
 
329
 
 
330
  if (fclose(fp) == EOF)
 
331
    panic("couldn't close %s: %s", utils_fp_name(fp), strerror(errno));
 
332
}
 
333
 
 
334
 
 
335
/* Follow symlink and panic if something fails.  Return the ultimate
 
336
   symlink target, stored in a temporary buffer that the caller should
 
337
   not free.  */
 
338
const char *
 
339
follow_symlink(const char *fname)
 
340
{
 
341
#ifdef ENABLE_FOLLOW_SYMLINKS
 
342
  static char *buf1, *buf2;
 
343
  static int buf_size;
 
344
 
 
345
  struct stat statbuf;
 
346
  const char *buf = fname, *c;
 
347
  int rc;
 
348
 
 
349
  if (buf_size == 0)
 
350
    {
 
351
      buf1 = ck_malloc (PATH_MAX + 1);
 
352
      buf2 = ck_malloc (PATH_MAX + 1);
 
353
      buf_size = PATH_MAX + 1;
 
354
    }
 
355
 
 
356
  while ((rc = lstat (buf, &statbuf)) == 0
 
357
         && (statbuf.st_mode & S_IFLNK) == S_IFLNK)
 
358
    {
 
359
      if (buf == buf2)
 
360
        {
 
361
          strcpy (buf1, buf2);
 
362
          buf = buf1;
 
363
        }
 
364
 
 
365
      while ((rc = readlink (buf, buf2, buf_size)) == buf_size)
 
366
        {
 
367
          buf_size *= 2;
 
368
          buf1 = ck_realloc (buf1, buf_size);
 
369
          buf2 = ck_realloc (buf2, buf_size);
 
370
        }
 
371
      if (rc < 0)
 
372
        panic (_("couldn't follow symlink %s: %s"), buf, strerror(errno));
 
373
      else
 
374
        buf2 [rc] = '\0';
 
375
 
 
376
      if (buf2[0] != '/' && (c = strrchr (buf, '/')) != NULL)
 
377
        {
 
378
          /* Need to handle relative paths with care.  Reallocate buf1 and
 
379
             buf2 to be big enough.  */
 
380
          int len = c - buf + 1;
 
381
          if (len + rc + 1 > buf_size)
 
382
            {
 
383
              buf_size = len + rc + 1;
 
384
              buf1 = ck_realloc (buf1, buf_size);
 
385
              buf2 = ck_realloc (buf2, buf_size);
 
386
            }
 
387
 
 
388
          /* Always store the new path in buf1.  */
 
389
          if (buf != buf1)
 
390
            memcpy (buf1, buf, len);
 
391
 
 
392
          /* Tack the relative symlink at the end of buf1.  */
 
393
          memcpy (buf1 + len, buf2, rc + 1);
 
394
          buf = buf1;
 
395
        }
 
396
      else
 
397
        {
 
398
          /* Use buf2 as the buffer, it saves a strcpy if it is not pointing to
 
399
             another link.  It works for absolute symlinks, and as long as
 
400
             symlinks do not leave the current directory.  */
 
401
           buf = buf2;
 
402
        }
 
403
    }
 
404
 
 
405
  if (rc < 0)
 
406
    panic (_("cannot stat %s: %s"), buf, strerror(errno));
 
407
 
 
408
  return buf;
 
409
#else
 
410
  return fname;
 
411
#endif /* ENABLE_FOLLOW_SYMLINKS */
 
412
}
 
413
 
 
414
/* Panic on failing rename */
 
415
void
 
416
ck_rename (from, to, unlink_if_fail)
 
417
  const char *from, *to;
 
418
  const char *unlink_if_fail;
 
419
{
 
420
  int rd = rename (from, to);
 
421
  if (rd != -1)
 
422
    return;
 
423
 
 
424
  if (unlink_if_fail)
 
425
    {
 
426
      int save_errno = errno;
 
427
      errno = 0;
 
428
      unlink (unlink_if_fail);
 
429
 
 
430
      /* Failure to remove the temporary file is more severe, so trigger it first.  */
 
431
      if (errno != 0)
 
432
        panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno));
 
433
 
 
434
      errno = save_errno;
 
435
    }
 
436
 
 
437
  panic (_("cannot rename %s: %s"), from, strerror (errno));
 
438
}
 
439
 
 
440
 
 
441
 
 
442
 
 
443
/* Panic on failing malloc */
 
444
void *
 
445
ck_malloc(size)
 
446
  size_t size;
 
447
{
 
448
  void *ret = calloc(1, size ? size : 1);
 
449
  if (!ret)
 
450
    panic("couldn't allocate memory");
 
451
  return ret;
 
452
}
 
453
 
 
454
/* Panic on failing realloc */
 
455
void *
 
456
ck_realloc(ptr, size)
 
457
  void *ptr;
 
458
  size_t size;
 
459
{
 
460
  void *ret;
 
461
 
 
462
  if (size == 0)
 
463
    {
 
464
      free(ptr);
 
465
      return NULL;
 
466
    }
 
467
  if (!ptr)
 
468
    return ck_malloc(size);
 
469
  ret = realloc(ptr, size);
 
470
  if (!ret)
 
471
    panic("couldn't re-allocate memory");
 
472
  return ret;
 
473
}
 
474
 
 
475
/* Return a malloc()'d copy of a string */
 
476
char *
 
477
ck_strdup(str)
 
478
  const char *str;
 
479
{
 
480
  char *ret = MALLOC(strlen(str)+1, char);
 
481
  return strcpy(ret, str);
 
482
}
 
483
 
 
484
/* Return a malloc()'d copy of a block of memory */
 
485
void *
 
486
ck_memdup(buf, len)
 
487
  const void *buf;
 
488
  size_t len;
 
489
{
 
490
  void *ret = ck_malloc(len);
 
491
  return memcpy(ret, buf, len);
 
492
}
 
493
 
 
494
 
 
495
/* Implement a variable sized buffer of `stuff'.  We don't know what it is,
 
496
nor do we care, as long as it doesn't mind being aligned by malloc. */
 
497
 
 
498
struct buffer
 
499
  {
 
500
    size_t allocated;
 
501
    size_t length;
 
502
    char *b;
 
503
  };
 
504
 
 
505
#define MIN_ALLOCATE 50
 
506
 
 
507
struct buffer *
 
508
init_buffer()
 
509
{
 
510
  struct buffer *b = MALLOC(1, struct buffer);
 
511
  b->b = MALLOC(MIN_ALLOCATE, char);
 
512
  b->allocated = MIN_ALLOCATE;
 
513
  b->length = 0;
 
514
  return b;
 
515
}
 
516
 
 
517
char *
 
518
get_buffer(b)
 
519
  struct buffer *b;
 
520
{
 
521
  return b->b;
 
522
}
 
523
 
 
524
size_t
 
525
size_buffer(b)
 
526
  struct buffer *b;
 
527
{
 
528
  return b->length;
 
529
}
 
530
 
 
531
static void resize_buffer (struct buffer *b, size_t newlen);
 
532
static void
 
533
resize_buffer(b, newlen)
 
534
  struct buffer *b;
 
535
  size_t newlen;
 
536
{
 
537
  char *try = NULL;
 
538
  size_t alen = b->allocated;
 
539
 
 
540
  if (newlen <= alen)
 
541
    return;
 
542
  alen *= 2;
 
543
  if (newlen < alen)
 
544
    try = realloc(b->b, alen);  /* Note: *not* the REALLOC() macro! */
 
545
  if (!try)
 
546
    {
 
547
      alen = newlen;
 
548
      try = REALLOC(b->b, alen, char);
 
549
    }
 
550
  b->allocated = alen;
 
551
  b->b = try;
 
552
}
 
553
 
 
554
char *
 
555
add_buffer(b, p, n)
 
556
  struct buffer *b;
 
557
  const char *p;
 
558
  size_t n;
 
559
{
 
560
  char *result;
 
561
  if (b->allocated - b->length < n)
 
562
    resize_buffer(b, b->length+n);
 
563
  result = memcpy(b->b + b->length, p, n);
 
564
  b->length += n;
 
565
  return result;
 
566
}
 
567
 
 
568
char *
 
569
add1_buffer(b, c)
 
570
  struct buffer *b;
 
571
  int c;
 
572
{
 
573
  /* This special case should be kept cheap;
 
574
   *  don't make it just a mere convenience
 
575
   *  wrapper for add_buffer() -- even "builtin"
 
576
   *  versions of memcpy(a, b, 1) can become
 
577
   *  expensive when called too often.
 
578
   */
 
579
  if (c != EOF)
 
580
    {
 
581
      char *result;
 
582
      if (b->allocated - b->length < 1)
 
583
        resize_buffer(b, b->length+1);
 
584
      result = b->b + b->length++;
 
585
      *result = c;
 
586
      return result;
 
587
    }
 
588
 
 
589
  return NULL;
 
590
}
 
591
 
 
592
void
 
593
free_buffer(b)
 
594
  struct buffer *b;
 
595
{
 
596
  if (b)
 
597
    free(b->b);
 
598
  free(b);
 
599
}