Bash-4.3 distribution sources and documentation
[platform/upstream/bash.git] / builtins / mapfile.def
1 This file is mapfile.def, from which is created mapfile.c.
2 It implements the builtin "mapfile" in Bash.
3
4 Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc.
5 Copyright (C) 2008-2012 Free Software Foundation, Inc.
6
7 This file is part of GNU Bash, the Bourne Again SHell.
8
9 Bash is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Bash 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 Bash.  If not, see <http://www.gnu.org/licenses/>.
21
22 $PRODUCES mapfile.c
23
24 $BUILTIN mapfile
25 $FUNCTION mapfile_builtin
26 $SHORT_DOC mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
27 Read lines from the standard input into an indexed array variable.
28
29 Read lines from the standard input into the indexed array variable ARRAY, or
30 from file descriptor FD if the -u option is supplied.  The variable MAPFILE
31 is the default ARRAY.
32
33 Options:
34   -n count      Copy at most COUNT lines.  If COUNT is 0, all lines are copied.
35   -O origin     Begin assigning to ARRAY at index ORIGIN.  The default index is 0.
36   -s count      Discard the first COUNT lines read.
37   -t            Remove a trailing newline from each line read.
38   -u fd         Read lines from file descriptor FD instead of the standard input.
39   -C callback   Evaluate CALLBACK each time QUANTUM lines are read.
40   -c quantum    Specify the number of lines read between each call to CALLBACK.
41
42 Arguments:
43   ARRAY         Array variable name to use for file data.
44
45 If -C is supplied without -c, the default quantum is 5000.  When
46 CALLBACK is evaluated, it is supplied the index of the next array
47 element to be assigned and the line to be assigned to that element
48 as additional arguments.
49
50 If not supplied with an explicit origin, mapfile will clear ARRAY before
51 assigning to it.
52
53 Exit Status:
54 Returns success unless an invalid option is given or ARRAY is readonly or
55 not an indexed array.
56 $END
57
58 $BUILTIN readarray
59 $FUNCTION mapfile_builtin
60 $SHORT_DOC readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
61 Read lines from a file into an array variable.
62
63 A synonym for `mapfile'.
64 $END
65
66 #include <config.h>
67
68 #include "builtins.h"
69 #include "posixstat.h"
70
71 #if defined (HAVE_UNISTD_H)
72 #  include <unistd.h>
73 #endif
74
75 #include "bashansi.h"
76 #include "bashintl.h"
77
78 #include <stdio.h>
79 #include <errno.h>
80
81 #include "../bashintl.h"
82 #include "../shell.h"
83 #include "common.h"
84 #include "bashgetopt.h"
85
86 #if !defined (errno)
87 extern int errno;
88 #endif
89
90 #if defined (ARRAY_VARS)
91
92 static int run_callback __P((const char *, unsigned int, const char *));
93
94 #define DEFAULT_ARRAY_NAME      "MAPFILE"
95 #define DEFAULT_VARIABLE_NAME   "MAPLINE"       /* not used right now */
96
97 /* The value specifying how frequently `mapfile'  calls the callback. */
98 #define DEFAULT_QUANTUM 5000
99
100 /* Values for FLAGS */
101 #define MAPF_CLEARARRAY 0x01
102 #define MAPF_CHOP       0x02
103
104 static int
105 run_callback (callback, curindex, curline)
106      const char *callback;
107      unsigned int curindex;
108      const char *curline;
109 {
110   unsigned int execlen;
111   char  *execstr, *qline;
112   int flags;
113
114   qline = sh_single_quote (curline);
115   execlen = strlen (callback) + strlen (qline) + 10;
116   /* 1 for each space between %s and %d,
117      another 1 for the last nul char for C string. */
118   execlen += 3;
119   execstr = xmalloc (execlen);
120
121   flags = SEVAL_NOHIST;
122 #if 0
123   if (interactive)
124     flags |= SEVAL_INTERACT;
125 #endif
126   snprintf (execstr, execlen, "%s %d %s", callback, curindex, qline);
127   free (qline);
128   return evalstring (execstr, NULL, flags);
129 }
130
131 static void
132 do_chop(line)
133      char * line;
134 {
135   int length;
136
137   length = strlen (line);
138   if (length && line[length-1] == '\n') 
139     line[length-1] = '\0';
140 }
141
142 static int
143 mapfile (fd, line_count_goal, origin, nskip, callback_quantum, callback, array_name, flags)
144      int fd;
145      long line_count_goal, origin, nskip, callback_quantum;
146      char *callback, *array_name;
147      int flags;
148 {
149   char *line;
150   size_t line_length;
151   unsigned int array_index, line_count;
152   SHELL_VAR *entry;
153   int unbuffered_read;
154   
155   line = NULL;
156   line_length = 0;
157   unbuffered_read = 0;
158
159   /* The following check should be done before reading any lines.  Doing it
160      here allows us to call bind_array_element instead of bind_array_variable
161      and skip the variable lookup on every call. */
162   entry = find_or_make_array_variable (array_name, 1);
163   if (entry == 0 || readonly_p (entry) || noassign_p (entry))
164     {
165       if (entry && readonly_p (entry))
166         err_readonly (array_name);
167         
168       return (EXECUTION_FAILURE);
169     }
170   else if (array_p (entry) == 0)
171     {
172       builtin_error (_("%s: not an indexed array"), array_name);
173       return (EXECUTION_FAILURE);
174     }
175   else if (invisible_p (entry))
176     VUNSETATTR (entry, att_invisible);  /* no longer invisible */
177       
178   if (flags & MAPF_CLEARARRAY)
179     array_flush (array_cell (entry));
180
181 #ifndef __CYGWIN__
182   unbuffered_read = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
183 #else
184   unbuffered_read = 1;
185 #endif
186
187   zreset ();
188
189   /* Skip any lines at beginning of file? */
190   for (line_count = 0; line_count < nskip; line_count++)
191     if (zgetline (fd, &line, &line_length, unbuffered_read) < 0)
192       break;
193
194   line = 0;
195   line_length = 0;    
196
197   /* Reset the buffer for bash own stream */
198   for (array_index = origin, line_count = 1; 
199         zgetline (fd, &line, &line_length, unbuffered_read) != -1;
200         array_index++) 
201     {
202       /* Remove trailing newlines? */
203       if (flags & MAPF_CHOP)
204         do_chop (line);
205           
206       /* Has a callback been registered and if so is it time to call it? */
207       if (callback && line_count && (line_count % callback_quantum) == 0) 
208         {
209           run_callback (callback, array_index, line);
210
211           /* Reset the buffer for bash own stream. */
212           if (unbuffered_read == 0)
213             zsyncfd (fd);
214         }
215
216       /* XXX - bad things can happen if the callback modifies ENTRY, e.g.,
217          unsetting it or changing it to a non-indexed-array type. */
218       bind_array_element (entry, array_index, line, 0);
219
220       /* Have we exceeded # of lines to store? */
221       line_count++;
222       if (line_count_goal != 0 && line_count > line_count_goal) 
223         break;
224     }
225
226   xfree (line);
227
228   if (unbuffered_read == 0)
229     zsyncfd (fd);
230
231   return EXECUTION_SUCCESS;
232 }
233
234 int
235 mapfile_builtin (list)
236      WORD_LIST *list;
237 {
238   int opt, code, fd, clear_array, flags;
239   intmax_t intval;
240   long lines, origin, nskip, callback_quantum;
241   char *array_name, *callback;
242
243   clear_array = 1;
244   fd = 0;
245   lines = origin = nskip = 0;
246   flags = MAPF_CLEARARRAY;
247   callback_quantum = DEFAULT_QUANTUM;
248   callback = 0;
249
250   reset_internal_getopt ();
251   while ((opt = internal_getopt (list, "u:n:O:tC:c:s:")) != -1)
252     {
253       switch (opt)
254         {
255         case 'u':
256           code = legal_number (list_optarg, &intval);
257           if (code == 0 || intval < 0 || intval != (int)intval)
258             {
259               builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
260               return (EXECUTION_FAILURE);
261             }
262           else
263             fd = intval;
264
265           if (sh_validfd (fd) == 0)
266             {
267               builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
268               return (EXECUTION_FAILURE);
269             }
270           break;          
271
272         case 'n':
273           code = legal_number (list_optarg, &intval);
274           if (code == 0 || intval < 0 || intval != (unsigned)intval)
275             {
276               builtin_error (_("%s: invalid line count"), list_optarg);
277               return (EXECUTION_FAILURE);
278             }
279           else
280             lines = intval;
281           break;
282
283         case 'O':
284           code = legal_number (list_optarg, &intval);
285           if (code == 0 || intval < 0 || intval != (unsigned)intval)
286             {
287               builtin_error (_("%s: invalid array origin"), list_optarg);
288               return (EXECUTION_FAILURE);
289             }
290           else
291             origin = intval;
292           flags &= ~MAPF_CLEARARRAY;
293           break;
294         case 't':
295           flags |= MAPF_CHOP;
296           break;
297         case 'C':
298           callback = list_optarg;
299           break;
300         case 'c':
301           code = legal_number (list_optarg, &intval);
302           if (code == 0 || intval <= 0 || intval != (unsigned)intval)
303             {
304               builtin_error (_("%s: invalid callback quantum"), list_optarg);
305               return (EXECUTION_FAILURE);
306             }
307           else
308             callback_quantum = intval;
309           break;
310         case 's':
311           code = legal_number (list_optarg, &intval);
312           if (code == 0 || intval < 0 || intval != (unsigned)intval)
313             {
314               builtin_error (_("%s: invalid line count"), list_optarg);
315               return (EXECUTION_FAILURE);
316             }
317           else
318             nskip = intval;
319           break;
320         default:
321           builtin_usage ();
322           return (EX_USAGE);
323         }
324     }
325   list = loptend;
326
327   if (list == 0) 
328     array_name = DEFAULT_ARRAY_NAME;
329   else if (list->word == 0 || list->word->word == 0)
330     {
331       builtin_error ("internal error: getting variable name");
332       return (EXECUTION_FAILURE);
333     }
334   else if (list->word->word[0] == '\0')
335     {
336       builtin_error (_("empty array variable name"));
337       return (EX_USAGE);
338     } 
339   else
340     array_name = list->word->word;
341   
342   if (legal_identifier (array_name) == 0 && valid_array_reference (array_name) == 0)
343     {
344       sh_invalidid (array_name);
345       return (EXECUTION_FAILURE);
346     }
347
348   return mapfile (fd, lines, origin, nskip, callback_quantum, callback, array_name, flags);
349 }
350
351 #else
352
353 int
354 mapfile_builtin (list)
355      WORD_LIST *list;
356 {
357   builtin_error (_("array variable support required"));
358   return (EXECUTION_FAILURE);
359 }
360
361 #endif  /* ARRAY_VARS */