Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/r-source/src/main/CommandLineArgs.c
Line
Count
Source
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1997-2023   The R Core Team
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 2 of the License, or
8
 *  (at your option) 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, a copy is available at
17
 *  https://www.R-project.org/Licenses/
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
#include <config.h>
22
#endif
23
24
#include <string.h>
25
26
#include <Defn.h>
27
#include <R_ext/RStartup.h>
28
29
30
/* Remove and process common command-line arguments
31
 *  Formally part of ../unix/sys-common.c.
32
 */
33
34
/*
35
  This copies the command line arguments to the Rstart
36
  structure. The memory is obtained from calloc, etc.
37
  since these are permanent and it is not intended that
38
  they be modified. This is why they are copied before
39
  being processed and removed from the list.
40
41
  We might store these as a SEXP. I have no strong opinion
42
  about this.
43
 */
44
45
/* Permanent copy of the command line arguments and the number
46
   of them passed to the application.
47
   These are populated via the routine R_set_command_line_arguments().
48
*/
49
static int    NumCommandLineArgs = 0;
50
static char **CommandLineArgs = NULL; // this does not get freed
51
52
53
void
54
R_set_command_line_arguments(int argc, char **argv)
55
38
{
56
    // nothing here is ever freed.
57
38
    NumCommandLineArgs = argc;
58
38
    CommandLineArgs = (char**) calloc((size_t) argc, sizeof(char*));
59
38
    if(CommandLineArgs == NULL)
60
0
  R_Suicide("allocation failure in R_set_command_line_arguments");
61
62
190
    for(int i = 0; i < argc; i++) {
63
152
  CommandLineArgs[i] = strdup(argv[i]);
64
152
  if(CommandLineArgs[i] == NULL)
65
0
      R_Suicide("allocation failure in R_set_command_line_arguments");
66
152
    }
67
38
}
68
69
70
/*
71
  The .Internal which returns the command line arguments that are stored
72
  in global variables.
73
 */
74
attribute_hidden
75
SEXP do_commandArgs(SEXP call, SEXP op, SEXP args, SEXP env)
76
0
{
77
0
    int i;
78
0
    SEXP vals;
79
80
0
    checkArity(op, args);
81
    /* need protection as mkChar allocates */
82
0
    vals = PROTECT(allocVector(STRSXP, NumCommandLineArgs));
83
0
    for(i = 0; i < NumCommandLineArgs; i++)
84
0
  SET_STRING_ELT(vals, i, mkChar(CommandLineArgs[i]));
85
0
    UNPROTECT(1);
86
0
    return vals;
87
0
}
88
89
#ifdef Win32
90
extern Rboolean R_LoadRconsole;
91
#endif
92
93
void
94
R_common_command_line(int *pac, char **argv, Rstart Rp)
95
38
{
96
38
    int ac = *pac, newac = 1; /* argv[0] is process name */
97
38
    long lval; /* this is used for ppval, so 32-bit long is fine */
98
38
    char *p, **av = argv, msg[1024];
99
38
    Rboolean processing = TRUE;
100
101
38
    R_RestoreHistory = 1;
102
152
    while(--ac) {
103
114
  if(processing && **++av == '-') {
104
114
      if (!strcmp(*av, "--version")) {
105
0
    PrintVersion(msg, 1024);
106
0
    R_ShowMessage(msg);
107
0
    exit(0);
108
0
      }
109
114
      else if(!strcmp(*av, "--args")) {
110
    /* copy this through for further processing */
111
0
    argv[newac++] = *av;
112
0
    processing = FALSE;
113
0
      }
114
114
      else if(!strcmp(*av, "--save")) {
115
0
    Rp->SaveAction = SA_SAVE;
116
0
      }
117
114
      else if(!strcmp(*av, "--no-save")) {
118
0
    Rp->SaveAction = SA_NOSAVE;
119
0
      }
120
114
      else if(!strcmp(*av, "--restore")) {
121
0
    Rp->RestoreAction = SA_RESTORE;
122
0
      }
123
114
      else if(!strcmp(*av, "--no-restore")) {
124
38
    Rp->RestoreAction = SA_NORESTORE;
125
38
    R_RestoreHistory = 0;
126
38
      }
127
76
      else if(!strcmp(*av, "--no-restore-data")) {
128
0
    Rp->RestoreAction = SA_NORESTORE;
129
0
      }
130
76
      else if(!strcmp(*av, "--no-restore-history")) {
131
0
    R_RestoreHistory = 0;
132
0
      }
133
76
      else if (!strcmp(*av, "--silent") ||
134
76
         !strcmp(*av, "--quiet") ||
135
76
         !strcmp(*av, "-q")) {
136
0
    Rp->R_Quiet = TRUE;
137
0
      }
138
76
      else if (!strcmp(*av, "--vanilla")) {
139
38
    Rp->SaveAction = SA_NOSAVE; /* --no-save */
140
38
    Rp->RestoreAction = SA_NORESTORE; /* --no-restore */
141
38
    R_RestoreHistory = 0;     // --no-restore-history (= part of --no-restore)
142
38
    Rp->LoadSiteFile = FALSE; /* --no-site-file */
143
38
    Rp->LoadInitFile = FALSE; /* --no-init-file */
144
38
    Rp->NoRenviron = TRUE;    // --no-environ
145
#ifdef Win32
146
    R_LoadRconsole = FALSE;
147
#endif
148
38
      }
149
38
      else if (!strcmp(*av, "--no-environ")) {
150
0
    Rp->NoRenviron = TRUE;
151
0
      }
152
38
      else if (!strcmp(*av, "--verbose")) {
153
0
    Rp->R_Verbose = TRUE;
154
0
      }
155
38
      else if (!strcmp(*av, "--no-echo") ||
156
0
         !strcmp(*av, "--slave") || // "deprecated" from R 4.0.0 (spring 2020)
157
38
         !strcmp(*av, "-s")) {
158
38
    Rp->R_Quiet = TRUE;
159
38
    Rp->R_NoEcho = TRUE;
160
38
    Rp->SaveAction = SA_NOSAVE;
161
38
      }
162
0
      else if (!strcmp(*av, "--no-site-file")) {
163
0
    Rp->LoadSiteFile = FALSE;
164
0
      }
165
0
      else if (!strcmp(*av, "--no-init-file")) {
166
0
    Rp->LoadInitFile = FALSE;
167
0
      }
168
      /* Undocumented and unused.
169
       else if (!strcmp(*av, "--debug-init")) {
170
        Rp->DebugInitFile = TRUE;
171
       */
172
0
      else if (!strncmp(*av, "--encoding", 10)) {
173
0
    if(strlen(*av) < 12) {
174
0
        if(ac > 1) {ac--; av++; p = *av;} else p = NULL;
175
0
    } else p = &(*av)[11];
176
0
    if (p == NULL) {
177
0
        R_ShowMessage(_("WARNING: no value given for --encoding"));
178
0
    } else {
179
0
        strncpy(R_StdinEnc, p, 30);
180
0
        R_StdinEnc[30] = '\0';
181
0
    }
182
0
      }
183
#ifdef Win32
184
      else if (!strcmp(*av, "--no-Rconsole")) {
185
    R_LoadRconsole = 0;
186
      }
187
#endif
188
0
      else if (!strcmp(*av, "-save") ||
189
0
         !strcmp(*av, "-nosave") ||
190
0
         !strcmp(*av, "-restore") ||
191
0
         !strcmp(*av, "-norestore") ||
192
0
         !strcmp(*av, "-noreadline") ||
193
0
         !strcmp(*av, "-quiet") ||
194
0
         !strcmp(*av, "-nsize") ||
195
0
         !strcmp(*av, "-vsize") ||
196
0
         !strncmp(*av, "--max-nsize", 11) ||
197
0
         !strncmp(*av, "--max-vsize", 11) ||
198
0
         !strcmp(*av, "-V") ||
199
0
         !strcmp(*av, "-n") ||
200
0
         !strcmp(*av, "-v")) {
201
0
    snprintf(msg, 1024,
202
0
       _("WARNING: option '%s' no longer supported"), *av);
203
0
    R_ShowMessage(msg);
204
0
      }
205
      /* mop up --min-[nv]size */
206
0
      else if( !strncmp(*av, "--min-nsize", 11) ||
207
0
         !strncmp(*av, "--min-vsize", 11) ) {
208
0
    if(strlen(*av) < 13) {
209
0
        if(ac > 1) {ac--; av++; p = *av;} else p = NULL;
210
0
    } else p = &(*av)[12];
211
0
    if (p == NULL) {
212
0
        snprintf(msg, 1024,
213
0
           _("WARNING: no value given for '%s'"), *av);
214
0
        R_ShowMessage(msg);
215
0
        break;
216
0
    }
217
0
    int ierr;
218
0
    R_size_t value;
219
0
    value = R_Decode2Long(p, &ierr);
220
0
    if(ierr) {
221
0
        if(ierr < 0)
222
0
      snprintf(msg, 1024,
223
0
         _("WARNING: '%s' value is invalid: ignored"),
224
0
         *av);
225
0
        else
226
0
      snprintf(msg, 1024,
227
0
         _("WARNING: %s: too large and ignored"),
228
0
         *av);
229
0
        R_ShowMessage(msg);
230
231
0
    } else {
232
0
        if(!strncmp(*av, "--min-nsize", 11)) Rp->nsize = value;
233
0
        if(!strncmp(*av, "--min-vsize", 11)) Rp->vsize = value;
234
0
    }
235
0
      }
236
0
      else if(strncmp(*av, "--max-ppsize", 12) == 0) {
237
0
    if(strlen(*av) < 14) {
238
0
        if(ac > 1) {ac--; av++; p = *av;} else p = NULL;
239
0
    } else p = &(*av)[13];
240
0
    if (p == NULL) {
241
0
        R_ShowMessage(_("WARNING: no value given for '--max-ppsize'"));
242
0
        break;
243
0
    }
244
0
    lval = strtol(p, &p, 10);
245
0
    if (lval < 0)
246
0
        R_ShowMessage(_("WARNING: '--max-ppsize' value is negative: ignored"));
247
0
    else if (lval < 10000)
248
0
        R_ShowMessage(_("WARNING: '--max-ppsize' value is too small: ignored"));
249
0
    else if (lval > 500000)
250
0
        R_ShowMessage(_("WARNING: '--max-ppsize' value is too large: ignored"));
251
0
    else Rp->ppsize = (size_t) lval;
252
0
      }
253
0
      else if(strncmp(*av, "--max-connections", 17) == 0) {
254
0
    if(strlen(*av) < 19) {
255
0
        if(ac > 1) {ac--; av++; p = *av;} else p = NULL;
256
0
    } else p = &(*av)[18];
257
0
    if (p == NULL) {
258
0
        R_ShowMessage(_("WARNING: no value given for '--max-connections'"));
259
0
        break;
260
0
    }
261
0
    lval = strtol(p, &p, 10);
262
0
    if (lval < 0)
263
0
        R_ShowMessage(_("WARNING: '--max-connections' value is negative: ignored"));
264
0
    else if (lval < 128)
265
0
        R_ShowMessage(_("WARNING: '--max-connections' value is too small: ignored"));
266
0
    else if (lval > 4096)
267
0
        R_ShowMessage(_("WARNING: '--max-connections' value is too large: ignored"));
268
0
    else Rp->nconnections = (int) lval;
269
0
      }
270
0
      else { /* unknown -option */
271
0
    argv[newac++] = *av;
272
0
      }
273
114
  }
274
0
  else {
275
0
      argv[newac++] = *av;
276
0
  }
277
114
    }
278
38
    *pac = newac;
279
38
    return;
280
38
}