Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* cmdarg.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS-Portierung                                                             */
6
/*                                                                           */
7
/* Verarbeitung Kommandozeilenparameter                                      */
8
/*                                                                           */
9
/* Historie:  4. 5.1996 Grundsteinlegung                                     */
10
/*            1. 6.1996 Empty-Funktion                                       */
11
/*           17. 4.1999 Key-Files in Kommandozeile                           */
12
/*            3. 8.2000 added command line args as slashes                   */
13
/*                                                                           */
14
/*****************************************************************************/
15
 
16
#include "stdinc.h"
17
#include <string.h>
18
#include <ctype.h>
19
 
20
#include "strutil.h"
21
#include "stringlists.h"
22
#include "nls.h"
23
#include "nlmessages.h"
24
#include "cmdarg.rsc"
25
#ifdef _USE_MSH
26
# include "cmdarg.msh"
27
#endif
28
#include "cmdarg.h"
29
 
30
/* --------------------------------------------------------------- */
31
 
32
TMsgCat MsgCat;
33
 
34
static as_cmd_rec_t *sum_cmd_recs = NULL;
35
static size_t sum_cmd_rec_cnt = 0;
36
 
37
/* --------------------------------------------------------------- */
38
 
39
static as_cmd_result_t ProcessFile(const char *Name_O,
40
                                   const as_cmd_rec_t *p_cmd_recs, size_t cmd_rec_cnt,
41
                                   as_cmd_results_t *p_results);
42
 
43
static as_cmd_result_t cmd_write_help(Boolean negate, const char *p_arg, as_cmd_results_t *p_results)
44
{
45
  UNUSED(p_arg);
46
 
47
  if (negate)
48
    return e_cmd_err;
49
 
50
  p_results->write_help_exit = True;
51
  return e_cmd_ok;
52
}
53
 
54
static as_cmd_result_t cmd_write_version(Boolean negate, const char *p_arg, as_cmd_results_t *p_results)
55
{
56
  UNUSED(p_arg);
57
 
58
  if (negate)
59
    return e_cmd_err;
60
 
61
  p_results->write_version_exit = True;
62
  return e_cmd_ok;
63
}
64
 
65
static Boolean is_arg_leadin(char p)
66
{
67
  return (p == '-')
68
#ifdef SLASHARGS
69
      || (p == '/')
70
#endif
71
      || (p == '+');
72
}
73
 
74
static as_cmd_result_t ProcessParam(const as_cmd_rec_t *p_cmd_recs, size_t cmd_rec_cnt, const char *p_param,
75
                                    const char *p_next, Boolean AllowLink,
76
                                    as_cmd_results_t *p_results)
77
{
78
  Boolean Negate;
79
  as_cmd_result_t TempRes;
80
  const char *p_act_next;
81
 
82
  if (as_strcasecmp(p_param, "-intsyntax"))
83
    p_act_next = (is_arg_leadin(*p_next) || (*p_next == '@')) ? "" : p_next;
84
  else
85
    p_act_next = p_next;
86
  if (*p_param == '@')
87
  {
88
    if (AllowLink)
89
    {
90
      return ProcessFile(p_param + 1, p_cmd_recs, cmd_rec_cnt, p_results);
91
    }
92
    else
93
    {
94
      fprintf(stderr, "%s\n", catgetmessage(&MsgCat, Num_ErrMsgNoKeyInFile));
95
      strmaxcpy(p_results->error_arg, p_param, sizeof(p_results->error_arg));
96
      return e_cmd_err;
97
    }
98
  }
99
  if (is_arg_leadin(*p_param))
100
  {
101
    size_t Search;
102
    int cnv_up_lo = 0;
103
 
104
    Negate = (*p_param == '+');
105
    p_param++;
106
    if (*p_param == '#')
107
    {
108
      cnv_up_lo = 1;
109
      p_param++;
110
    }
111
    else if (*p_param == '~')
112
    {
113
      cnv_up_lo = -1;
114
      p_param++;
115
    }
116
 
117
    for (Search = 0; Search < cmd_rec_cnt; Search++)
118
      if ((strlen(p_cmd_recs[Search].p_ident) > 1) && (!as_strcasecmp(p_param, p_cmd_recs[Search].p_ident)))
119
        break;
120
    if (Search < cmd_rec_cnt)
121
      TempRes = p_cmd_recs[Search].callback(Negate, p_act_next);
122
    else if (!as_strcasecmp(p_param, "help"))
123
      TempRes = cmd_write_help(Negate, p_act_next, p_results);
124
    else if (!as_strcasecmp(p_param, "version"))
125
      TempRes = cmd_write_version(Negate, p_act_next, p_results);
126
 
127
    else
128
    {
129
      TempRes = e_cmd_ok;
130
      for (; *p_param; p_param++)
131
      {
132
        char p = *p_param;
133
 
134
        if (cnv_up_lo)
135
          p = (cnv_up_lo > 0) ? as_toupper(p) : as_tolower(p);
136
        Search = 0;
137
        for (Search = 0; Search < cmd_rec_cnt; Search++)
138
          if ((strlen(p_cmd_recs[Search].p_ident) == 1) && (p_cmd_recs[Search].p_ident[0] == p))
139
            break;
140
        if (Search >= cmd_rec_cnt)
141
          TempRes = e_cmd_err;
142
        else
143
          switch (p_cmd_recs[Search].callback(Negate, p_act_next))
144
          {
145
            case e_cmd_err:
146
              TempRes = e_cmd_err;
147
              break;
148
            case e_cmd_arg:
149
              TempRes = e_cmd_arg;
150
              p_act_next = "";
151
              break;
152
            case e_cmd_ok:
153
              break;
154
            case e_cmd_file:
155
              break; /** **/
156
          }
157
        if (TempRes == e_cmd_err)
158
          break;
159
      }
160
    }
161
    if (TempRes == e_cmd_err)
162
      strmaxcpy(p_results->error_arg, p_param, sizeof(p_results->error_arg));
163
    return TempRes;
164
  }
165
  else
166
    return e_cmd_file;
167
}
168
 
169
static as_cmd_result_t DecodeLine(const as_cmd_rec_t *p_cmd_recs, int cmd_rec_cnt, char *OneLine,
170
                                  as_cmd_results_t *p_results)
171
{
172
  int z;
173
  char *EnvStr[256], *start, *p;
174
  int EnvCnt = 0;
175
 
176
  KillPrefBlanks(OneLine);
177
  if ((*OneLine != '\0') && (*OneLine != ';'))
178
  {
179
    start = OneLine;
180
    while (*start != '\0')
181
    {
182
      EnvStr[EnvCnt++] = start;
183
      p = strchr(start, ' ');
184
      if (!p)
185
        p = strchr(start, '\t');
186
      if (p)
187
      {
188
        *p = '\0';
189
        start = p + 1;
190
        while (as_isspace(*start))
191
           start++;
192
      }
193
      else
194
        start += strlen(start);
195
    }
196
    EnvStr[EnvCnt] = start;
197
 
198
    for (z = 0; z < EnvCnt; z++)
199
    {
200
      switch (ProcessParam(p_cmd_recs, cmd_rec_cnt, EnvStr[z], EnvStr[z + 1], False, p_results))
201
      {
202
        case e_cmd_file:
203
          AddStringListLast(&p_results->file_arg_list, EnvStr[z]);
204
          break;
205
        case e_cmd_err:
206
          strmaxcpy(p_results->error_arg, EnvStr[z], sizeof(p_results->error_arg));
207
          p_results->error_arg_in_env = True;
208
          return e_cmd_err;
209
        case e_cmd_arg:
210
          z++;
211
          break;
212
        case e_cmd_ok:
213
          break;
214
      }
215
    }
216
  }
217
  return e_cmd_ok;
218
}
219
 
220
/*!------------------------------------------------------------------------
221
 * \fn     ProcessFile(const char *Name_O,
222
                       const as_cmd_rec_t *p_cmd_recs, size_t cmd_rec_cnt,
223
                       as_cmd_results_t *p_results)
224
 * \brief  process arguments from file
225
 * \param  Name_O file's name
226
 * \param  p_cmd_recs, cmd_rec_cnt argument defintions
227
 * \param  p_results result buffer
228
 * \return e_cmd_ok or e_cmd_err
229
 * ------------------------------------------------------------------------ */
230
 
231
static as_cmd_result_t ProcessFile(const char *Name_O,
232
                                   const as_cmd_rec_t *p_cmd_recs, size_t cmd_rec_cnt,
233
                                   as_cmd_results_t *p_results)
234
{
235
  FILE *KeyFile;
236
  String Name, OneLine;
237
  as_cmd_result_t ret = e_cmd_ok;
238
 
239
  strmaxcpy(Name, Name_O, STRINGSIZE);
240
  KillPrefBlanks(OneLine);
241
 
242
  KeyFile = fopen(Name, "r");
243
  if (!KeyFile)
244
  {
245
    strmaxcpy(p_results->error_arg, catgetmessage(&MsgCat, Num_ErrMsgKeyFileNotFound), sizeof(p_results->error_arg));
246
    ret = e_cmd_err;
247
  }
248
  while (!feof(KeyFile) && (ret == e_cmd_ok))
249
  {
250
    errno = 0;
251
    ReadLn(KeyFile, OneLine);
252
    if ((errno != 0) && !feof(KeyFile))
253
    {
254
      strmaxcpy(p_results->error_arg, catgetmessage(&MsgCat, Num_ErrMsgKeyFileError), sizeof(p_results->error_arg));
255
      ret = e_cmd_err;
256
    }
257
    ret = DecodeLine(p_cmd_recs, cmd_rec_cnt, OneLine, p_results);
258
  }
259
  fclose(KeyFile);
260
  return ret;
261
}
262
 
263
static int cmd_compare(const void *p1, const void *p2)
264
{
265
  const as_cmd_rec_t *p_rec1 = (const as_cmd_rec_t*)p1,
266
                     *p_rec2 = (const as_cmd_rec_t*)p2;
267
  int cmp_res = strcmp(p_rec1->p_ident, p_rec2->p_ident);
268
 
269
  if (!cmp_res && (p_rec1 != p_rec2))
270
    fprintf(stderr, "cmd_arg: option '%s' present twice\n", p_rec1->p_ident);
271
  return cmp_res;
272
}
273
 
274
/*!------------------------------------------------------------------------
275
 * \fn     as_cmd_register(const as_cmd_rec_t *p_add_recs, size_t add_rec_cnt)
276
 * \brief  extend command record list
277
 * \param  p_add_recs, add_rec_cnt records to add
278
 * ------------------------------------------------------------------------ */
279
 
280
void as_cmd_register(const as_cmd_rec_t *p_add_recs, size_t add_rec_cnt)
281
{
282
  as_cmd_rec_t *p_new_sum_recs;
283
 
284
  if (sum_cmd_recs)
285
    p_new_sum_recs = (as_cmd_rec_t*)realloc(sum_cmd_recs, sizeof(*p_new_sum_recs) * (sum_cmd_rec_cnt + add_rec_cnt));
286
  else
287
    p_new_sum_recs = (as_cmd_rec_t*)malloc(sizeof(*p_new_sum_recs) * (sum_cmd_rec_cnt + add_rec_cnt));
288
  if (p_new_sum_recs)
289
  {
290
    memcpy(&p_new_sum_recs[sum_cmd_rec_cnt], p_add_recs, sizeof(*p_new_sum_recs) * add_rec_cnt);
291
    sum_cmd_rec_cnt += add_rec_cnt;
292
    sum_cmd_recs = p_new_sum_recs;
293
    qsort(p_new_sum_recs, sum_cmd_rec_cnt, sizeof(*p_new_sum_recs), cmd_compare);
294
  }
295
}
296
 
297
/*!------------------------------------------------------------------------
298
 * \fn     as_cmd_process(int argc, char **argv,
299
                          const char *p_env_name, as_cmd_results_t *p_results)
300
 * \brief  arguments from command line and environment
301
 * \param  argc command line arg count as handed to main()
302
 * \param  argv command line args as handed to main()
303
 * \param  p_env_name environment variable to draw additional args from
304
 * \param  p_file_arg_list gets populated with file arguments
305
 * \return e_cmd_ok, or e_cmd_err on faulty arg
306
 * ------------------------------------------------------------------------ */
307
 
308
const char *argv0;
309
 
310
as_cmd_result_t as_cmd_process(int argc, char **argv,
311
                               const char *p_env_name, as_cmd_results_t *p_results)
312
{
313
  int z;
314
  String EnvLine;
315
  char *pEnv;
316
  Boolean skip_next;
317
 
318
  p_results->file_arg_list = NULL;
319
  p_results->write_help_exit =
320
  p_results->write_version_exit = False;
321
  p_results->error_arg_in_env = False;
322
  p_results->error_arg[0] = '\0';
323
 
324
  pEnv = getenv(p_env_name);
325
  strmaxcpy(EnvLine, pEnv ? pEnv : "", STRINGSIZE);
326
 
327
  if (EnvLine[0] == '@')
328
  {
329
    if (e_cmd_err == ProcessFile(EnvLine + 1, sum_cmd_recs, sum_cmd_rec_cnt, p_results))
330
      return e_cmd_err;
331
  }
332
  else
333
  {
334
    if (e_cmd_err == DecodeLine(sum_cmd_recs, sum_cmd_rec_cnt, EnvLine, p_results))
335
      return e_cmd_err;
336
  }
337
 
338
  argv0 = argv[0];
339
 
340
  skip_next = False;
341
  for (z = 1; z < argc; z++)
342
  {
343
    if (skip_next)
344
    {
345
      skip_next = False;
346
      continue;
347
    }
348
    switch (ProcessParam(sum_cmd_recs, sum_cmd_rec_cnt, argv[z], (z + 1 < argc) ? argv[z + 1] : "",
349
                         True, p_results))
350
    {
351
      case e_cmd_err:
352
        p_results->error_arg_in_env = False;
353
        strmaxcpy(p_results->error_arg, argv[z], sizeof(p_results->error_arg));
354
        return e_cmd_err;
355
      case e_cmd_ok:
356
        break;
357
      case e_cmd_arg:
358
        skip_next = True;
359
        break;
360
      case e_cmd_file:
361
        AddStringListLast(&p_results->file_arg_list, argv[z]);
362
        break;
363
    }
364
  }
365
  return e_cmd_ok;
366
}
367
 
368
const char *as_cmdarg_get_executable_name(void)
369
{
370
  const char *pos;
371
 
372
  pos = strrchr(argv0, '/');
373
  return (pos) ? pos + 1 : argv0;
374
}
375
 
376
void as_cmdarg_init(char *ProgPath)
377
{
378
#ifdef _USE_MSH
379
  msg_catalog_open_buffer(&MsgCat, cmdarg_msh_data, sizeof(cmdarg_msh_data), MsgId1, MsgId2);
380
  UNUSED(ProgPath);
381
#else
382
  msg_catalog_open_file(&MsgCat, "cmdarg.msg", ProgPath, MsgId1, MsgId2);
383
#endif
384
}
385