~ubuntu-branches/ubuntu/dapper/ecasound2.2/dapper

« back to all changes in this revision

Viewing changes to readline-4.0/histfile.c

  • Committer: Bazaar Package Importer
  • Author(s): Junichi Uekawa
  • Date: 2005-04-14 09:15:48 UTC
  • Revision ID: james.westby@ubuntu.com-20050414091548-o7kgb47z0tcunh0s
Tags: upstream-2.4.1
ImportĀ upstreamĀ versionĀ 2.4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* histfile.c - functions to manipulate the history file. */
 
2
 
 
3
/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
 
4
 
 
5
   This file contains the GNU History Library (the Library), a set of
 
6
   routines for managing the text of previously typed lines.
 
7
 
 
8
   The Library is free software; you can redistribute it and/or modify
 
9
   it under the terms of the GNU General Public License as published by
 
10
   the Free Software Foundation; either version 1, or (at your option)
 
11
   any later version.
 
12
 
 
13
   The Library is distributed in the hope that it will be useful, but
 
14
   WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
   General Public License for more details.
 
17
 
 
18
   The GNU General Public License is often shipped with GNU software, and
 
19
   is generally kept in a file called COPYING or LICENSE.  If you do not
 
20
   have a copy of the license, write to the Free Software Foundation,
 
21
   675 Mass Ave, Cambridge, MA 02139, USA. */
 
22
 
 
23
/* The goal is to make the implementation transparent, so that you
 
24
   don't have to know what data types are used, just what functions
 
25
   you can call.  I think I have done that. */
 
26
#define READLINE_LIBRARY
 
27
 
 
28
#if defined (HAVE_CONFIG_H)
 
29
#  include <config.h>
 
30
#endif
 
31
 
 
32
#include <stdio.h>
 
33
 
 
34
#include <sys/types.h>
 
35
#ifndef _MINIX
 
36
#  include <sys/file.h>
 
37
#endif
 
38
#include <sys/stat.h>
 
39
#include <fcntl.h>
 
40
 
 
41
#if defined (HAVE_STDLIB_H)
 
42
#  include <stdlib.h>
 
43
#else
 
44
#  include "ansi_stdlib.h"
 
45
#endif /* HAVE_STDLIB_H */
 
46
 
 
47
#if defined (HAVE_UNISTD_H)
 
48
#  include <unistd.h>
 
49
#endif
 
50
 
 
51
#if defined (HAVE_STRING_H)
 
52
#  include <string.h>
 
53
#else
 
54
#  include <strings.h>
 
55
#endif /* !HAVE_STRING_H */
 
56
 
 
57
#if defined (__EMX__)
 
58
#  ifndef O_BINARY
 
59
#    define O_BINARY 0
 
60
#  endif
 
61
#else /* !__EMX__ */
 
62
   /* If we're not compiling for __EMX__, we don't want this at all.  Ever. */
 
63
#  undef O_BINARY
 
64
#  define O_BINARY 0
 
65
#endif /* !__EMX__ */
 
66
 
 
67
#include <errno.h>
 
68
#if !defined (errno)
 
69
extern int errno;
 
70
#endif /* !errno */
 
71
 
 
72
#include "history.h"
 
73
#include "histlib.h"
 
74
 
 
75
/* Functions imported from shell.c */
 
76
extern char *get_env_value ();
 
77
 
 
78
extern char *xmalloc (), *xrealloc ();
 
79
 
 
80
/* Return the string that should be used in the place of this
 
81
   filename.  This only matters when you don't specify the
 
82
   filename to read_history (), or write_history (). */
 
83
static char *
 
84
history_filename (filename)
 
85
     char *filename;
 
86
{
 
87
  char *return_val, *home;
 
88
  int home_len;
 
89
 
 
90
  return_val = filename ? savestring (filename) : (char *)NULL;
 
91
 
 
92
  if (return_val)
 
93
    return (return_val);
 
94
  
 
95
  home = get_env_value ("HOME");
 
96
 
 
97
  if (home == 0)
 
98
    {
 
99
      home = ".";
 
100
      home_len = 1;
 
101
    }
 
102
  else
 
103
    home_len = strlen (home);
 
104
 
 
105
  return_val = xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
 
106
  strcpy (return_val, home);
 
107
  return_val[home_len] = '/';
 
108
  strcpy (return_val + home_len + 1, ".history");
 
109
 
 
110
  return (return_val);
 
111
}
 
112
 
 
113
/* Add the contents of FILENAME to the history list, a line at a time.
 
114
   If FILENAME is NULL, then read from ~/.history.  Returns 0 if
 
115
   successful, or errno if not. */
 
116
int
 
117
read_history (filename)
 
118
     char *filename;
 
119
{
 
120
  return (read_history_range (filename, 0, -1));
 
121
}
 
122
 
 
123
/* Read a range of lines from FILENAME, adding them to the history list.
 
124
   Start reading at the FROM'th line and end at the TO'th.  If FROM
 
125
   is zero, start at the beginning.  If TO is less than FROM, read
 
126
   until the end of the file.  If FILENAME is NULL, then read from
 
127
   ~/.history.  Returns 0 if successful, or errno if not. */
 
128
int
 
129
read_history_range (filename, from, to)
 
130
     char *filename;
 
131
     int from, to;
 
132
{
 
133
  register int line_start, line_end;
 
134
  char *input, *buffer;
 
135
  int file, current_line;
 
136
  struct stat finfo;
 
137
  size_t file_size;
 
138
 
 
139
  buffer = (char *)NULL;
 
140
  input = history_filename (filename);
 
141
  file = open (input, O_RDONLY|O_BINARY, 0666);
 
142
 
 
143
  if ((file < 0) || (fstat (file, &finfo) == -1))
 
144
    goto error_and_exit;
 
145
 
 
146
  file_size = (size_t)finfo.st_size;
 
147
 
 
148
  /* check for overflow on very large files */
 
149
  if (file_size != finfo.st_size || file_size + 1 < file_size)
 
150
    {
 
151
#if defined (EFBIG)
 
152
      errno = EFBIG;
 
153
#endif
 
154
      goto error_and_exit;
 
155
    }
 
156
 
 
157
  buffer = xmalloc (file_size + 1);
 
158
#if 0
 
159
  if (read (file, buffer, file_size) != file_size)
 
160
#else
 
161
  if (read (file, buffer, file_size) < 0)
 
162
#endif
 
163
    {
 
164
  error_and_exit:
 
165
      if (file >= 0)
 
166
        close (file);
 
167
 
 
168
      FREE (input);
 
169
      FREE (buffer);
 
170
 
 
171
      return (errno);
 
172
    }
 
173
 
 
174
  close (file);
 
175
 
 
176
  /* Set TO to larger than end of file if negative. */
 
177
  if (to < 0)
 
178
    to = file_size;
 
179
 
 
180
  /* Start at beginning of file, work to end. */
 
181
  line_start = line_end = current_line = 0;
 
182
 
 
183
  /* Skip lines until we are at FROM. */
 
184
  while (line_start < file_size && current_line < from)
 
185
    {
 
186
      for (line_end = line_start; line_end < file_size; line_end++)
 
187
        if (buffer[line_end] == '\n')
 
188
          {
 
189
            current_line++;
 
190
            line_start = line_end + 1;
 
191
            if (current_line == from)
 
192
              break;
 
193
          }
 
194
    }
 
195
 
 
196
  /* If there are lines left to gobble, then gobble them now. */
 
197
  for (line_end = line_start; line_end < file_size; line_end++)
 
198
    if (buffer[line_end] == '\n')
 
199
      {
 
200
        buffer[line_end] = '\0';
 
201
 
 
202
        if (buffer[line_start])
 
203
          add_history (buffer + line_start);
 
204
 
 
205
        current_line++;
 
206
 
 
207
        if (current_line >= to)
 
208
          break;
 
209
 
 
210
        line_start = line_end + 1;
 
211
      }
 
212
 
 
213
  FREE (input);
 
214
  FREE (buffer);
 
215
 
 
216
  return (0);
 
217
}
 
218
 
 
219
/* Truncate the history file FNAME, leaving only LINES trailing lines.
 
220
   If FNAME is NULL, then use ~/.history. */
 
221
int
 
222
history_truncate_file (fname, lines)
 
223
     char *fname;
 
224
     int lines;
 
225
{
 
226
  register int i;
 
227
  int file, chars_read;
 
228
  char *buffer, *filename;
 
229
  struct stat finfo;
 
230
  size_t file_size;
 
231
 
 
232
  buffer = (char *)NULL;
 
233
  filename = history_filename (fname);
 
234
  file = open (filename, O_RDONLY|O_BINARY, 0666);
 
235
 
 
236
  if (file == -1 || fstat (file, &finfo) == -1)
 
237
    goto truncate_exit;
 
238
 
 
239
  file_size = (size_t)finfo.st_size;
 
240
 
 
241
  /* check for overflow on very large files */
 
242
  if (file_size != finfo.st_size || file_size + 1 < file_size)
 
243
    {
 
244
      close (file);
 
245
#if defined (EFBIG)
 
246
      errno = EFBIG;
 
247
#endif
 
248
      goto truncate_exit;
 
249
    }
 
250
 
 
251
  buffer = xmalloc (file_size + 1);
 
252
  chars_read = read (file, buffer, file_size);
 
253
  close (file);
 
254
 
 
255
  if (chars_read <= 0)
 
256
    goto truncate_exit;
 
257
 
 
258
  /* Count backwards from the end of buffer until we have passed
 
259
     LINES lines. */
 
260
  for (i = chars_read - 1; lines && i; i--)
 
261
    {
 
262
      if (buffer[i] == '\n')
 
263
        lines--;
 
264
    }
 
265
 
 
266
  /* If this is the first line, then the file contains exactly the
 
267
     number of lines we want to truncate to, so we don't need to do
 
268
     anything.  It's the first line if we don't find a newline between
 
269
     the current value of i and 0.  Otherwise, write from the start of
 
270
     this line until the end of the buffer. */
 
271
  for ( ; i; i--)
 
272
    if (buffer[i] == '\n')
 
273
      {
 
274
        i++;
 
275
        break;
 
276
      }
 
277
 
 
278
  /* Write only if there are more lines in the file than we want to
 
279
     truncate to. */
 
280
  if (i && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
 
281
    {
 
282
      write (file, buffer + i, file_size - i);
 
283
 
 
284
#if defined (__BEOS__)
 
285
      /* BeOS ignores O_TRUNC. */
 
286
      ftruncate (file, file_size - i);
 
287
#endif
 
288
 
 
289
      close (file);
 
290
    }
 
291
 
 
292
 truncate_exit:
 
293
 
 
294
  FREE (buffer);
 
295
 
 
296
  free (filename);
 
297
  return 0;
 
298
}
 
299
 
 
300
/* Workhorse function for writing history.  Writes NELEMENT entries
 
301
   from the history list to FILENAME.  OVERWRITE is non-zero if you
 
302
   wish to replace FILENAME with the entries. */
 
303
static int
 
304
history_do_write (filename, nelements, overwrite)
 
305
     char *filename;
 
306
     int nelements, overwrite;
 
307
{
 
308
  register int i;
 
309
  char *output;
 
310
  int file, mode;
 
311
 
 
312
  mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
 
313
  output = history_filename (filename);
 
314
 
 
315
  if ((file = open (output, mode, 0600)) == -1)
 
316
    {
 
317
      FREE (output);
 
318
      return (errno);
 
319
    }
 
320
 
 
321
  if (nelements > history_length)
 
322
    nelements = history_length;
 
323
 
 
324
  /* Build a buffer of all the lines to write, and write them in one syscall.
 
325
     Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
 
326
  {
 
327
    HIST_ENTRY **the_history;   /* local */
 
328
    register int j;
 
329
    int buffer_size;
 
330
    char *buffer;
 
331
 
 
332
    the_history = history_list ();
 
333
    /* Calculate the total number of bytes to write. */
 
334
    for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
 
335
      buffer_size += 1 + strlen (the_history[i]->line);
 
336
 
 
337
    /* Allocate the buffer, and fill it. */
 
338
    buffer = xmalloc (buffer_size);
 
339
 
 
340
    for (j = 0, i = history_length - nelements; i < history_length; i++)
 
341
      {
 
342
        strcpy (buffer + j, the_history[i]->line);
 
343
        j += strlen (the_history[i]->line);
 
344
        buffer[j++] = '\n';
 
345
      }
 
346
 
 
347
    write (file, buffer, buffer_size);
 
348
    free (buffer);
 
349
  }
 
350
 
 
351
  close (file);
 
352
 
 
353
  FREE (output);
 
354
 
 
355
  return (0);
 
356
}
 
357
 
 
358
/* Append NELEMENT entries to FILENAME.  The entries appended are from
 
359
   the end of the list minus NELEMENTs up to the end of the list. */
 
360
int
 
361
append_history (nelements, filename)
 
362
     int nelements;
 
363
     char *filename;
 
364
{
 
365
  return (history_do_write (filename, nelements, HISTORY_APPEND));
 
366
}
 
367
 
 
368
/* Overwrite FILENAME with the current history.  If FILENAME is NULL,
 
369
   then write the history list to ~/.history.  Values returned
 
370
   are as in read_history ().*/
 
371
int
 
372
write_history (filename)
 
373
     char *filename;
 
374
{
 
375
  return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
 
376
}