/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 | } |