update devspec.en_US/1.0.general.md.
[devspec.git] / devspec.en_US / project / recutils / utils / recins.c
blob6fe1de701d0aa05c9924581ff4306d5e15ae883e
1 /* -*- mode: C -*-
3 * File: recins.c
4 * Date: Mon Dec 28 08:54:38 2009
6 * GNU recutils - recins
8 */
10 /* Copyright (C) 2009-2019 Jose E. Marchesi */
12 /* This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <config.h>
28 #include <getopt.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <xalloc.h>
32 #include <gettext.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <locale.h>
36 #define _(str) gettext (str)
37 #include <base64.h>
39 #include <rec.h>
40 #include <recutl.h>
42 /* Forward declarations. */
43 bool recins_insert_record (rec_db_t db, char *type, rec_record_t record);
44 void recins_parse_args (int argc, char **argv);
47 * Global variables
50 char *recutl_type = NULL;
51 rec_sex_t recutl_sex = NULL;
52 char *recutl_sex_str = NULL;
53 char *recutl_quick_str = NULL;
54 bool recutl_insensitive = false;
55 rec_record_t recins_record = NULL;
56 char *recins_file = NULL;
57 bool recins_force = false;
58 bool recins_verbose = false;
59 bool recins_external = true;
60 bool recins_auto = true;
61 char *recins_password = NULL;
62 size_t recutl_random = 0;
65 * Command line options management
68 enum
70 COMMON_ARGS,
71 RECORD_SELECTION_ARGS,
72 NAME_ARG,
73 VALUE_ARG,
74 FORCE_ARG,
75 VERBOSE_ARG,
76 NO_EXTERNAL_ARG,
77 RECORD_ARG,
78 #if defined REC_CRYPT_SUPPORT
79 PASSWORD_ARG,
80 #endif
81 NO_AUTO_ARG
84 static const struct option GNU_longOptions[] =
86 COMMON_LONG_ARGS,
87 RECORD_SELECTION_LONG_ARGS,
88 {"type", required_argument, NULL, TYPE_ARG},
89 {"name", required_argument, NULL, NAME_ARG},
90 {"value", required_argument, NULL, VALUE_ARG},
91 {"force", no_argument, NULL, FORCE_ARG},
92 {"verbose", no_argument, NULL, VERBOSE_ARG},
93 {"no-external", no_argument, NULL, NO_EXTERNAL_ARG},
94 {"record", required_argument, NULL, RECORD_ARG},
95 {"no-auto", no_argument, NULL, NO_AUTO_ARG},
96 #if defined REC_CRYPT_SUPPORT
97 {"password", required_argument, NULL, PASSWORD_ARG},
98 #endif
99 {NULL, 0, NULL, 0}
103 * Functions.
106 void
107 recutl_print_help (void)
109 /* TRANSLATORS: --help output, recins synopsis.
110 no-wrap */
111 printf (_("\
112 Usage: recins [OPTION]... [-t TYPE] [-n NUM | -e RECORD_EXPR | -q STR | -m NUM] [(-f NAME -v STR) | -r RECDATA]... [FILE]\n"));
114 /* TRANSLATORS: --help output, recins short description.
115 no-wrap */
116 fputs (_("\
117 Insert new records in a rec database.\n"), stdout);
119 puts ("");
120 /* TRANSLATORS: --help output, recins arguments.
121 no-wrap */
122 fputs (_("\
123 -f, --field=STR field name; should be followed by a -v.\n\
124 -v, --value=STR field value; should be preceded by an -f.\n\
125 -r, --record=STR record that will be inserted in the file.\n\
126 --force insert the record even if it is violating\n\
127 record restrictions.\n\
128 --no-external don't use external descriptors.\n\
129 --no-auto don't insert auto generated fields.\n\
130 --verbose give a detailed report if the integrity check\n\
131 fails.\n"), stdout);
133 #if defined REC_CRYPT_SUPPORT
134 /* TRANSLATORS: --help output, encryption related options.
135 no-wrap */
136 fputs (_("\
137 -s, --password=STR encrypt confidential fields with the given password.\n"),
138 stdout);
139 #endif
141 recutl_print_help_common ();
143 puts ("");
144 recutl_print_help_record_selection ();
146 puts ("");
147 /* TRANSLATORS: --help output, notes on recins.
148 no-wrap */
149 fputs (_("\
150 If no FILE is specified then the command acts like a filter, getting\n\
151 the data from standard input and writing the result to standard output.\n"), stdout);
153 puts ("");
154 recutl_print_help_footer ();
158 void recins_parse_args (int argc,
159 char **argv)
161 int ret;
162 char c;
163 rec_field_t field = NULL;
164 char *field_name = NULL;
165 rec_record_t provided_record;
167 while ((ret = getopt_long (argc,
168 argv,
169 RECORD_SELECTION_SHORT_ARGS
170 ENCRYPTION_SHORT_ARGS
171 "f:v:r:",
172 GNU_longOptions,
173 NULL)) != -1)
175 c = ret;
176 switch (c)
178 COMMON_ARGS_CASES
179 RECORD_SELECTION_ARGS_CASES
180 case FORCE_ARG:
182 recins_force = true;
183 break;
185 case VERBOSE_ARG:
187 recins_verbose = true;
188 break;
190 case NAME_ARG:
191 case 'f':
193 if (field != NULL)
195 recutl_fatal (_("a -f should be followed by a -v\n"));
196 exit (EXIT_FAILURE);
199 if (recins_record == NULL)
201 recins_record = rec_record_new ();
202 rec_record_set_source (recins_record, "cmdli");
203 rec_record_set_location (recins_record, 0);
206 if (!rec_field_name_p (optarg))
208 recutl_fatal (_("invalid field name %s.\n"), optarg);
211 field = rec_field_new (optarg, "foo");
212 break;
214 case VALUE_ARG:
215 case 'v':
217 if (field == NULL)
219 recutl_fatal (_("a -v should be preceded by a -f\n"));
222 rec_field_set_value (field, optarg);
223 rec_mset_append (rec_record_mset (recins_record), MSET_FIELD, (void *) field, MSET_ANY);
225 field = NULL;
226 break;
228 case NO_EXTERNAL_ARG:
230 recins_external = false;
231 break;
233 case NO_AUTO_ARG:
235 recins_auto = false;
236 break;
238 #if defined REC_CRYPT_SUPPORT
239 case PASSWORD_ARG:
240 case 's':
242 if (recins_password != NULL)
244 recutl_fatal (_("more than one password was specified\n"));
247 recins_password = xstrdup (optarg);
248 break;
250 #endif
251 case RECORD_ARG:
252 case 'r':
254 /* Parse the provided record and put it in recins_record. */
255 provided_record = rec_parse_record_str (optarg);
256 if (!provided_record)
258 recutl_fatal (_("error while parsing the record provided by -r\n"));
261 if (recins_record)
263 /* Append the fields in provided_record into
264 recins_record. */
266 rec_mset_iterator_t iter = rec_mset_iterator (rec_record_mset (provided_record));
267 while (rec_mset_iterator_next (&iter, MSET_FIELD, (const void **) &field, NULL))
269 rec_mset_append (rec_record_mset (recins_record), MSET_FIELD, (void *) rec_field_dup (field), MSET_ANY);
270 field = NULL;
272 rec_mset_iterator_free (&iter);
274 rec_record_destroy (provided_record);
275 provided_record = NULL;
277 else
279 recins_record = provided_record;
282 break;
284 default:
286 exit (EXIT_FAILURE);
291 if (field != NULL)
293 recutl_fatal (_("please provide a value for the field %s\n"), field_name);
296 /* Read the name of the file where to make the insertions. */
297 if (optind < argc)
300 if ((argc - optind) != 1)
302 recutl_print_help ();
303 exit (EXIT_FAILURE);
306 recins_file = argv[optind++];
310 void
311 recins_add_new_record (rec_db_t db)
313 int flags = 0;
315 #if defined REC_CRYPT_SUPPORT
317 /* Get the password interactively from the user if some field is
318 declared as confidential in the requested record set. */
321 rec_rset_t rset;
322 rec_fex_t confidential_fields;
324 if (recutl_type)
326 rset = rec_db_get_rset_by_type (db, recutl_type);
328 if (rset)
330 confidential_fields = rec_rset_confidential (rset);
331 if (!confidential_fields)
332 recutl_out_of_memory ();
334 if (rec_fex_size (confidential_fields) > 0)
336 if (!recins_password && recutl_interactive ())
338 recins_password = recutl_getpass (true);
339 if (!recins_password)
341 recutl_fatal ("not in an interactive terminal.\n");
345 /* Passwords can't be empty. */
347 if (recins_password && (strlen (recins_password) == 0))
349 free (recins_password);
350 recins_password = NULL;
357 #endif /* REC_CRYPT_SUPPORT */
359 /* Set flags flags and call the library to perform the
360 requested insertion/replacement operation. */
362 if (recutl_insensitive)
364 flags = flags | REC_F_ICASE;
367 if (!recins_auto)
369 flags = flags | REC_F_NOAUTO;
372 if (!rec_db_insert (db,
373 recutl_type,
374 recutl_index (),
375 recutl_sex,
376 recutl_quick_str,
377 recutl_random,
378 recins_password,
379 recins_record,
380 flags))
381 recutl_out_of_memory ();
383 /* Check for the integrity of the resulting database. */
385 if (!recins_force && db)
387 recutl_check_integrity (db, recins_verbose, recins_external);
392 main (int argc, char *argv[])
394 rec_db_t db;
396 recutl_init ("recins");
398 recins_parse_args (argc, argv);
400 db = recutl_read_db_from_file (recins_file);
401 if (!db)
403 /* Create an empty database. */
404 db = rec_db_new ();
406 recins_add_new_record (db);
408 if (!recutl_file_is_writable (recins_file))
410 recutl_error (_("file %s is not writable.\n"), recins_file);
411 return EXIT_FAILURE;
413 recutl_write_db_to_file (db, recins_file);
415 return EXIT_SUCCESS;
418 /* End of recins.c */