The R Project SVN R

Rev

Rev 83901 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
40361 ripley 1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
83819 kalibera 3
 *  Copyright (C) 2006-2023  The R Core Team
40361 ripley 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
42309 ripley 16
 *  along with this program; if not, a copy is available at
68947 ripley 17
 *  https://www.R-project.org/Licenses/
40361 ripley 18
 */
19
 
20
/* This is intended to be used in scripts like
21
 
22
#! /path/to/Rscript --vanilla
40428 ripley 23
commandArgs(TRUE)
40361 ripley 24
q(status=7)
25
 
26
This invokes R with a command line like
77228 maechler 27
R --no-echo --no-restore --vanilla --file=foo [script_args]
40361 ripley 28
 
29
*/
30
 
31
/* execv exists and can be used on Windows, but it returns immediately
32
   and so the exit status is lost.  HAVE_EXECV is defined under Windows.
33
 
45475 ripley 34
   The main reason for using execv rather than system is to avoid
40361 ripley 35
   argument quoting hell.
36
*/
37
 
38
#ifdef HAVE_CONFIG_H
39
# include <config.h>
40
#endif
41
 
65805 ripley 42
#ifdef _WIN32
53060 ripley 43
#include <psignal.h>
44
/* on some systems needs to be included before <sys/types.h> */
45
#endif
46
 
40361 ripley 47
#include <stdio.h>
48
#include <limits.h> /* for PATH_MAX */
49
#include <string.h>
50
#include <stdlib.h>
51
#include <unistd.h> /* for execv */
52
 
53300 ripley 53
#include <Rversion.h>
40601 ripley 54
 
83819 kalibera 55
/* See comments in Defn.h and keep in step. */
40601 ripley 56
/* Maximal length of an entire file name */
57
#if !defined(PATH_MAX)
58
# if defined(HAVE_SYS_PARAM_H)
59
#  include <sys/param.h>
60
# endif
61
# if !defined(PATH_MAX)
62
#  if defined(MAXPATHLEN)
63
#    define PATH_MAX MAXPATHLEN
64
#  elif defined(Win32)
65
#    define PATH_MAX 260
66
#  else
67
/* quite possibly unlimited, so we make this large, and test when used */
68
#    define PATH_MAX 5000
69
#  endif
70
# endif
71
#endif
72
 
83901 kalibera 73
#ifdef Unix
74
# define R_PATH_MAX PATH_MAX
75
#else
76
  /* On Windows, 260 is too limiting */
77
# define R_PATH_MAX 5000
78
#endif
79
 
65805 ripley 80
#ifndef _WIN32
62045 urbaneks 81
#ifndef R_ARCH /* R_ARCH should be always defined, but for safety ... */
82
#define R_ARCH ""
83
#endif
84
 
40361 ripley 85
static char rhome[] = R_HOME;
62045 urbaneks 86
static char rarch[] = R_ARCH;
40361 ripley 87
#else
51072 ripley 88
# ifndef BINDIR
89
#  define BINDIR "bin"
90
# endif
50910 ripley 91
# define FOR_Rscript
40361 ripley 92
# include "rterm.c"
93
#endif
94
 
95
#ifdef HAVE_EXECV
96
static int verbose = 0;
97
#endif
98
 
83819 kalibera 99
void R_putenv_cpy(char *varname, char *value)
100
{
101
#ifdef HAVE_PUTENV
102
    size_t needed = strlen(varname) + 1 + strlen(value) + 1;
103
    char *buf = (char *)malloc(needed);
104
    if (!buf) {
105
	fprintf(stderr, "malloc failure\n");
106
	exit(1);
107
    }
108
    snprintf(buf, needed, "%s=%s", varname, value);
109
    if (putenv(buf)) {
110
	fprintf(stderr, "unable to set %s\n", varname);
111
	exit(1);
112
    }
113
    /* no free here: storage remains in use */
114
#else
115
    fprintf(stderr, "unable to set %s\n", varname);
116
    exit(1);
117
#endif
118
}
119
 
44199 ripley 120
void usage(void)
40361 ripley 121
{
81943 smeyer 122
    fprintf(stdout, "Usage: Rscript [options] file [args]\n");
123
    fprintf(stdout, "   or: Rscript [options] -e expr [-e expr2 ...] [args]\n");
124
    fprintf(stdout, "A binary front-end to R, for use in scripting applications.\n\n");
125
    fprintf(stdout, "Options:\n");
126
    fprintf(stdout, "  --help              Print usage and exit\n");
127
    fprintf(stdout, "  --version           Print version and exit\n");
128
    fprintf(stdout, "  --verbose           Print information on progress\n");
129
    fprintf(stdout, "  --default-packages=LIST  Attach these packages on startup;\n");
130
    fprintf(stdout, "                        a comma-separated LIST of package names, or 'NULL'\n");
131
    fprintf(stdout, "and options to R (in addition to --no-echo --no-restore), for example:\n");
132
    fprintf(stdout, "  --save              Do save workspace at the end of the session\n");
133
    fprintf(stdout, "  --no-environ        Don't read the site and user environment files\n");
134
    fprintf(stdout, "  --no-site-file      Don't read the site-wide Rprofile\n");
135
    fprintf(stdout, "  --no-init-file      Don't read the user R profile\n");
136
    fprintf(stdout, "  --restore           Do restore previously saved objects at startup\n");
137
    fprintf(stdout, "  --vanilla           Combine --no-save, --no-restore, --no-site-file,\n");
138
    fprintf(stdout, "                        --no-init-file and --no-environ\n");
139
    /* fprintf(stdout, "\n'file' may contain spaces but not shell metacharacters.\n"); */
140
    fprintf(stdout, "\nExpressions (one or more '-e <expr>') may be used *instead* of 'file'.\n");
141
    fprintf(stdout, "Any additional 'args' can be accessed from R via 'commandArgs(TRUE)'.\n");
142
    fprintf(stdout, "See also  ?Rscript  from within R.\n");
40361 ripley 143
}
144
 
145
 
72503 kalibera 146
int main(int argc_, char *argv_[])
40361 ripley 147
{
148
#ifdef HAVE_EXECV
83901 kalibera 149
    char *cmd = NULL, buf[R_PATH_MAX+8], *p;
40481 ripley 150
    int i, i0 = 0, ac = 0, res = 0, e_mode = 0, set_dp = 0;
40361 ripley 151
    char **av;
74084 luke 152
    int have_cmdarg_default_packages = 0;
40361 ripley 153
 
72503 kalibera 154
    if(argc_ <= 1) {
40361 ripley 155
	usage();
156
	exit(1);
157
    }
72503 kalibera 158
 
159
    /* When executed via '#!' on most systems, argv_[1] will include multiple
160
       arguments. These arguments will be those provided directly on the line
161
       starting with '#!'.
162
 
163
       argv_[1] is split here into individual arguments assuming any space or
164
       tab is a separator - no quoting is supported
74643 kalibera 165
 
166
       This code is, however, also used with explicit invocation of Rscript
167
       where arguments are not joined and the first argument may be a file
168
       name, which is explicitly allowed to contain space. Thus, only split the
169
       first argument if it starts with "--"  (a file name for Rscript cannot
170
       start with "--"; it can start with "-", but the only short option is "-e"
171
       and that is not usable with '#!' invocation).
72503 kalibera 172
    */
173
 
174
    /* compute number of arguments included in argv_[1] */
175
    char *s = argv_[1];
176
    int njoined = 0;
177
    size_t j;
74643 kalibera 178
    if (strncmp(s, "--", 2) == 0)
179
	for(j = 0; s[j] != 0; j++)
180
	    if (s[j] != ' ' && s[j] != '\t' &&
181
		    (j == 0 || s[j-1] == ' ' || s[j-1] == '\t'))
182
		/* first character of an argument */
183
		njoined++;
72503 kalibera 184
 
185
    int argc;
186
    char **argv;
187
 
188
    if (njoined > 1) { /* need to split argv_[1] */
189
	argc = argc_ - 1 + njoined;
74643 kalibera 190
	argv = (char **) malloc((size_t) (argc+1)*sizeof(char *));
72503 kalibera 191
	if (!argv) {
192
	    fprintf(stderr, "malloc failure\n");
193
	    exit(1);
194
	}
195
	argv[0] = argv_[0];
196
 
197
	size_t len = strlen(s);
84684 kalibera 198
	char *buf = (char *)malloc((size_t) (len+1)*sizeof(char));
72503 kalibera 199
	if (!buf) {
200
	    fprintf(stderr, "malloc failure\n");
201
	    exit(1);
202
	}
203
	strcpy(buf, s);
204
 
205
	i = 1;
206
	for(j = 0; s[j] != 0; j++)
207
	    if (s[j] == ' ' || s[j] == '\t')
208
		/* turn space into end-of-string */
209
		buf[j] = 0;
210
	    else if (j == 0 || s[j-1] == ' ' || s[j-1] == '\t')
211
		/* first character of an argument */
212
		argv[i++] = buf + j;
213
	/* assert i - 1 == njoined */
214
 
215
	for(i = 2; i < argc_; i++)
216
	    argv[i-1+njoined] = argv_[i];
217
	argv[argc] = 0;
218
 
219
    } else {
220
	argc = argc_;
221
	argv = argv_;
222
    }
223
 
55417 luke 224
    av = (char **) malloc((size_t) (argc+4)*sizeof(char *));
40361 ripley 225
    if(!av) {
226
	fprintf(stderr, "malloc failure\n");
227
	exit(1);
228
    }
229
 
230
    p = getenv("RHOME");
65805 ripley 231
#ifdef _WIN32
83819 kalibera 232
    size_t rterm_len = strlen("\\Rterm.exe");
233
    if(p && *p) {
234
	size_t len = strlen(p) + 1 + strlen(BINDIR) + rterm_len + 1;
235
	cmd = (char *)malloc(len);
236
	if (!cmd) {
237
	    fprintf(stderr, "malloc failure\n");
238
	    exit(1);
239
	}
240
	snprintf(cmd, len, "%s\\%s\\Rterm.exe",  p, BINDIR);
241
    } else {
242
	DWORD size = 1;
243
	/* GetModuleFileName doesn't return the needed buffer size. */
244
	for(;;) {
245
	    cmd = (char *)malloc(size + rterm_len);
246
	    if (!cmd) {
247
		fprintf(stderr, "malloc failure\n");
248
		exit(1);
249
	    }
250
	    DWORD res = GetModuleFileName(NULL, cmd, size);
251
	    if (res > 0 && res < size) /* success */
252
		break;
253
	    free(cmd);
254
	    cmd = NULL;
255
	    if (res != size) { /* error */
256
		fprintf(stderr, "installation problem\n");
257
		exit(1);
258
	    }
259
	    size *= 2; /* try again with 2x larger buffer */
260
	}
261
 
262
	p = strrchr(cmd,'\\');
40361 ripley 263
	if(!p) {fprintf(stderr, "installation problem\n"); exit(1);}
264
	*p = '\0';
83819 kalibera 265
	strcat(cmd, "\\Rterm.exe");
40361 ripley 266
    }
267
#else
83901 kalibera 268
    cmd = (char *)malloc(R_PATH_MAX + 1);
83819 kalibera 269
    if (!cmd) {
270
	fprintf(stderr, "malloc failure\n");
271
	exit(1);
272
    }
54654 ripley 273
    if(!(p && *p)) p = rhome;
274
    /* avoid snprintf here */
83901 kalibera 275
    if(strlen(p) + 6 > R_PATH_MAX) {
40601 ripley 276
	fprintf(stderr, "impossibly long path for RHOME\n");
277
	exit(1);
278
    }
83901 kalibera 279
    snprintf(cmd, R_PATH_MAX+1, "%s/bin/R", p);
40361 ripley 280
#endif
281
    av[ac++] = cmd;
77228 maechler 282
    av[ac++] = "--no-echo";
40361 ripley 283
    av[ac++] = "--no-restore";
45475 ripley 284
 
40361 ripley 285
    if(argc == 2) {
286
	if(strcmp(argv[1], "--help") == 0) {
287
	    usage();
288
	    exit(0);
289
	}
290
	if(strcmp(argv[1], "--version") == 0) {
53300 ripley 291
	    if(strlen(R_STATUS) == 0)
81943 smeyer 292
		fprintf(stdout, "Rscript (R) version %s.%s (%s-%s-%s)\n",
53300 ripley 293
			R_MAJOR, R_MINOR, R_YEAR, R_MONTH, R_DAY);
66644 maechler 294
	    else
81943 smeyer 295
		fprintf(stdout, "Rscript (R) version %s.%s %s (%s-%s-%s r%d)\n",
53300 ripley 296
			R_MAJOR, R_MINOR, R_STATUS, R_YEAR, R_MONTH, R_DAY,
297
			R_SVN_REVISION);
40361 ripley 298
	    exit(0);
299
	}
300
    }
45475 ripley 301
 
40396 ripley 302
    /* first copy over any -e or --foo args */
303
    for(i = 1; i < argc; i++) {
304
	if(strcmp(argv[i], "-e") == 0) {
305
	    e_mode = 1;
306
	    av[ac++] = argv[i];
307
	    if(!argv[++i]) {
308
		fprintf(stderr, "-e not followed by an expression\n");
309
		exit(1);
40361 ripley 310
	    }
40396 ripley 311
	    av[ac++] = argv[i];
312
	    i0 = i;
313
	    continue;
314
	}
80666 kalibera 315
	if (e_mode) break;
316
	    /* Once in e_mode, only additional -e options are to be processed.
317
	       Any remaining --options belong to the expressions (PR#18102). */ 
49838 falcon 318
	if(strncmp(argv[i], "--", 2) != 0) break;
40396 ripley 319
	if(strcmp(argv[i], "--verbose") == 0) {
320
	    verbose = 1;
321
	    i0 = i;
322
	    continue;
323
	}
324
	if(strncmp(argv[i], "--default-packages=", 18) == 0) {
40481 ripley 325
	    set_dp = 1;
83819 kalibera 326
	    R_putenv_cpy("R_DEFAULT_PACKAGES", argv[i]+19);
40396 ripley 327
	    if(verbose)
83819 kalibera 328
		fprintf(stderr, "setting '%s=%s'\n", "R_DEFAULT_PACKAGES", argv[i]+19);
329
	    have_cmdarg_default_packages = 1;
40361 ripley 330
	    i0 = i;
40396 ripley 331
	    continue;
40361 ripley 332
	}
40396 ripley 333
	av[ac++] = argv[i];
334
	i0 = i;
335
    }
336
 
337
    if(!e_mode) {
62580 ripley 338
	if(++i0 >= argc) {
339
	    fprintf(stderr, "file name is missing\n");
340
	    exit(1);
341
	}
83901 kalibera 342
	if(strlen(argv[i0]) > R_PATH_MAX) {
40601 ripley 343
	    fprintf(stderr, "file name is too long\n");
344
	    exit(1);
345
	}
83901 kalibera 346
	snprintf(buf, R_PATH_MAX+8, "--file=%s", argv[i0]);
40396 ripley 347
	av[ac++] = buf;
348
    }
66674 maechler 349
    // copy any user arguments, preceded by "--args"
350
    i = i0+1;
351
    if (i < argc) {
352
	av[ac++] = "--args";
353
	for(; i < argc; i++)
354
	    av[ac++] = argv[i];
355
    }
40361 ripley 356
    av[ac] = (char *) NULL;
74084 luke 357
    /* If provided, and default packages are not specified on the
358
       command line, then R_SCRIPT_DEFAULT_PACKAGES takes precedence
73995 luke 359
       over R_DEFAULT_PACKAGES. */
74084 luke 360
    if (! have_cmdarg_default_packages) {
361
	char *rsdp = getenv("R_SCRIPT_DEFAULT_PACKAGES");
83819 kalibera 362
	if (rsdp)
363
	    R_putenv_cpy("R_DEFAULT_PACKAGES", rsdp);
73995 luke 364
    }
365
 
73996 luke 366
    p = getenv("R_SCRIPT_LEGACY");
74084 luke 367
    int legacy = (p && (strcmp(p, "yes") == 0)) ? 1 : 0;
368
    //int legacy = (p && (strcmp(p, "no") == 0)) ? 0 : 1;
73996 luke 369
    if(legacy && !set_dp && !getenv("R_DEFAULT_PACKAGES"))
83819 kalibera 370
	/* R_putenv_cpy to get error handling */
371
	R_putenv_cpy("R_DEFAULT_PACKAGES",
372
	             "datasets,utils,grDevices,graphics,stats");
62045 urbaneks 373
 
65805 ripley 374
#ifndef _WIN32
62045 urbaneks 375
    /* pass on r_arch from this binary to R as a default */
376
    if (!getenv("R_ARCH") && *rarch) {
83819 kalibera 377
	char *slrarch = (char *)malloc(1 + strlen(rarch) + 1);
378
	if (!slrarch) {
379
	    fprintf(stderr, "malloc failure\n");
62045 urbaneks 380
	    exit(1);
381
	}
83819 kalibera 382
	strcpy(slrarch, "/");
383
	strcat(slrarch, rarch);
384
	R_putenv_cpy("R_ARCH", slrarch);
385
	free(slrarch);
62045 urbaneks 386
    }
40481 ripley 387
#endif
40361 ripley 388
    if(verbose) {
389
	fprintf(stderr, "running\n  '%s", cmd);
66644 maechler 390
	for(i = 1; i < ac; i++) fprintf(stderr, " %s", av[i]);
40361 ripley 391
	fprintf(stderr, "'\n\n");
392
    }
65805 ripley 393
#ifndef _WIN32
40361 ripley 394
    res = execv(cmd, av); /* will not return if R is launched */
395
    perror("Rscript execution error");
396
#else
397
    AppMain(ac, av);
398
#endif
399
    return res;
46084 ripley 400
#else /* No execv*/
40361 ripley 401
    fprintf(stderr, "Rscript is not supported on this system");
402
    exit(1);
403
#endif
404
}
83819 kalibera 405