The R Project SVN R

Rev

Rev 74643 | Rev 81170 | Go to most recent revision | 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
74643 kalibera 3
 *  Copyright (C) 2006-2018  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
 
53300 ripley 55
 
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
 
65805 ripley 73
#ifndef _WIN32
62045 urbaneks 74
#ifndef R_ARCH /* R_ARCH should be always defined, but for safety ... */
75
#define R_ARCH ""
76
#endif
77
 
40361 ripley 78
static char rhome[] = R_HOME;
62045 urbaneks 79
static char rarch[] = R_ARCH;
40361 ripley 80
#else
51072 ripley 81
# ifndef BINDIR
82
#  define BINDIR "bin"
83
# endif
50910 ripley 84
# define FOR_Rscript
40361 ripley 85
# include "rterm.c"
86
#endif
87
 
88
#ifdef HAVE_EXECV
89
static int verbose = 0;
90
#endif
91
 
44199 ripley 92
void usage(void)
40361 ripley 93
{
64434 maechler 94
    fprintf(stderr, "Usage: /path/to/Rscript [--options] [-e expr [-e expr2 ...] | file] [args]\n\n");
40361 ripley 95
    fprintf(stderr, "--options accepted are\n");
96
    fprintf(stderr, "  --help              Print usage and exit\n");
97
    fprintf(stderr, "  --version           Print version and exit\n");
98
    fprintf(stderr, "  --verbose           Print information on progress\n");
99
    fprintf(stderr, "  --default-packages=list\n");
100
    fprintf(stderr, "                      Where 'list' is a comma-separated set\n");
101
    fprintf(stderr, "                        of package names, or 'NULL'\n");
77228 maechler 102
    fprintf(stderr, "or options to R, in addition to --no-echo --no-restore, such as\n");
40361 ripley 103
    fprintf(stderr, "  --save              Do save workspace at the end of the session\n");
104
    fprintf(stderr, "  --no-environ        Don't read the site and user environment files\n");
105
    fprintf(stderr, "  --no-site-file      Don't read the site-wide Rprofile\n");
45053 hornik 106
    fprintf(stderr, "  --no-init-file      Don't read the user R profile\n");
40361 ripley 107
    fprintf(stderr, "  --restore           Do restore previously saved objects at startup\n");
108
    fprintf(stderr, "  --vanilla           Combine --no-save, --no-restore, --no-site-file\n");
109
    fprintf(stderr, "                        --no-init-file and --no-environ\n");
55931 ripley 110
    fprintf(stderr, "\n'file' may contain spaces but not shell metacharacters\n");
64423 maechler 111
    fprintf(stderr, "Expressions (one or more '-e <expr>') may be used *instead* of 'file'\n");
112
    fprintf(stderr, "See also  ?Rscript  from within R\n");
40361 ripley 113
}
114
 
115
 
72503 kalibera 116
int main(int argc_, char *argv_[])
40361 ripley 117
{
118
#ifdef HAVE_EXECV
40601 ripley 119
    char cmd[PATH_MAX+1], buf[PATH_MAX+8], buf2[1100], *p;
40481 ripley 120
    int i, i0 = 0, ac = 0, res = 0, e_mode = 0, set_dp = 0;
40361 ripley 121
    char **av;
74084 luke 122
    int have_cmdarg_default_packages = 0;
40361 ripley 123
 
72503 kalibera 124
    if(argc_ <= 1) {
40361 ripley 125
	usage();
126
	exit(1);
127
    }
72503 kalibera 128
 
129
    /* When executed via '#!' on most systems, argv_[1] will include multiple
130
       arguments. These arguments will be those provided directly on the line
131
       starting with '#!'.
132
 
133
       argv_[1] is split here into individual arguments assuming any space or
134
       tab is a separator - no quoting is supported
74643 kalibera 135
 
136
       This code is, however, also used with explicit invocation of Rscript
137
       where arguments are not joined and the first argument may be a file
138
       name, which is explicitly allowed to contain space. Thus, only split the
139
       first argument if it starts with "--"  (a file name for Rscript cannot
140
       start with "--"; it can start with "-", but the only short option is "-e"
141
       and that is not usable with '#!' invocation).
72503 kalibera 142
    */
143
 
144
    /* compute number of arguments included in argv_[1] */
145
    char *s = argv_[1];
146
    int njoined = 0;
147
    size_t j;
74643 kalibera 148
    if (strncmp(s, "--", 2) == 0)
149
	for(j = 0; s[j] != 0; j++)
150
	    if (s[j] != ' ' && s[j] != '\t' &&
151
		    (j == 0 || s[j-1] == ' ' || s[j-1] == '\t'))
152
		/* first character of an argument */
153
		njoined++;
72503 kalibera 154
 
155
    int argc;
156
    char **argv;
157
 
158
    if (njoined > 1) { /* need to split argv_[1] */
159
	argc = argc_ - 1 + njoined;
74643 kalibera 160
	argv = (char **) malloc((size_t) (argc+1)*sizeof(char *));
72503 kalibera 161
	if (!argv) {
162
	    fprintf(stderr, "malloc failure\n");
163
	    exit(1);
164
	}
165
	argv[0] = argv_[0];
166
 
167
	size_t len = strlen(s);
168
	char *buf = (char *)malloc((size_t) (len+1)*sizeof(char *));
169
	if (!buf) {
170
	    fprintf(stderr, "malloc failure\n");
171
	    exit(1);
172
	}
173
	strcpy(buf, s);
174
 
175
	i = 1;
176
	for(j = 0; s[j] != 0; j++)
177
	    if (s[j] == ' ' || s[j] == '\t')
178
		/* turn space into end-of-string */
179
		buf[j] = 0;
180
	    else if (j == 0 || s[j-1] == ' ' || s[j-1] == '\t')
181
		/* first character of an argument */
182
		argv[i++] = buf + j;
183
	/* assert i - 1 == njoined */
184
 
185
	for(i = 2; i < argc_; i++)
186
	    argv[i-1+njoined] = argv_[i];
187
	argv[argc] = 0;
188
 
189
    } else {
190
	argc = argc_;
191
	argv = argv_;
192
    }
193
 
55417 luke 194
    av = (char **) malloc((size_t) (argc+4)*sizeof(char *));
40361 ripley 195
    if(!av) {
196
	fprintf(stderr, "malloc failure\n");
197
	exit(1);
198
    }
199
 
200
    p = getenv("RHOME");
65805 ripley 201
#ifdef _WIN32
54654 ripley 202
    if(p && *p)
51072 ripley 203
	snprintf(cmd, PATH_MAX+1, "%s\\%s\\Rterm.exe",  p, BINDIR);
40361 ripley 204
    else {
205
	char rhome[MAX_PATH];
206
	GetModuleFileName(NULL, rhome, MAX_PATH);
207
	p = strrchr(rhome,'\\');
208
	if(!p) {fprintf(stderr, "installation problem\n"); exit(1);}
209
	*p = '\0';
210
	snprintf(cmd, PATH_MAX+1, "%s\\Rterm.exe",  rhome);
211
    }
212
#else
54654 ripley 213
    if(!(p && *p)) p = rhome;
214
    /* avoid snprintf here */
40601 ripley 215
    if(strlen(p) + 6 > PATH_MAX) {
216
	fprintf(stderr, "impossibly long path for RHOME\n");
217
	exit(1);
218
    }
62580 ripley 219
    snprintf(cmd, PATH_MAX+1, "%s/bin/R", p);
40361 ripley 220
#endif
221
    av[ac++] = cmd;
77228 maechler 222
    av[ac++] = "--no-echo";
40361 ripley 223
    av[ac++] = "--no-restore";
45475 ripley 224
 
40361 ripley 225
    if(argc == 2) {
226
	if(strcmp(argv[1], "--help") == 0) {
227
	    usage();
228
	    exit(0);
229
	}
230
	if(strcmp(argv[1], "--version") == 0) {
53300 ripley 231
	    if(strlen(R_STATUS) == 0)
66644 maechler 232
		fprintf(stderr, "R scripting front-end version %s.%s (%s-%s-%s)\n",
53300 ripley 233
			R_MAJOR, R_MINOR, R_YEAR, R_MONTH, R_DAY);
66644 maechler 234
	    else
235
		fprintf(stderr, "R scripting front-end version %s.%s %s (%s-%s-%s r%d)\n",
53300 ripley 236
			R_MAJOR, R_MINOR, R_STATUS, R_YEAR, R_MONTH, R_DAY,
237
			R_SVN_REVISION);
40361 ripley 238
	    exit(0);
239
	}
240
    }
45475 ripley 241
 
40396 ripley 242
    /* first copy over any -e or --foo args */
243
    for(i = 1; i < argc; i++) {
244
	if(strcmp(argv[i], "-e") == 0) {
245
	    e_mode = 1;
246
	    av[ac++] = argv[i];
247
	    if(!argv[++i]) {
248
		fprintf(stderr, "-e not followed by an expression\n");
249
		exit(1);
40361 ripley 250
	    }
40396 ripley 251
	    av[ac++] = argv[i];
252
	    i0 = i;
253
	    continue;
254
	}
49838 falcon 255
	if(strncmp(argv[i], "--", 2) != 0) break;
40396 ripley 256
	if(strcmp(argv[i], "--verbose") == 0) {
257
	    verbose = 1;
258
	    i0 = i;
259
	    continue;
260
	}
261
	if(strncmp(argv[i], "--default-packages=", 18) == 0) {
40481 ripley 262
	    set_dp = 1;
40601 ripley 263
	    if(strlen(argv[i]) > 1000) {
264
		fprintf(stderr, "unable to set R_DEFAULT_PACKAGES\n");
265
		exit(1);
266
	    }
62580 ripley 267
	    snprintf(buf2, 1100, "R_DEFAULT_PACKAGES=%s", argv[i]+19);
40396 ripley 268
	    if(verbose)
269
		fprintf(stderr, "setting '%s'\n", buf2);
40361 ripley 270
#ifdef HAVE_PUTENV
45475 ripley 271
	    if(putenv(buf2))
40361 ripley 272
#endif
40396 ripley 273
	    {
274
		fprintf(stderr, "unable to set R_DEFAULT_PACKAGES\n");
275
		exit(1);
40361 ripley 276
	    }
74084 luke 277
	    else have_cmdarg_default_packages = 1;
40361 ripley 278
	    i0 = i;
40396 ripley 279
	    continue;
40361 ripley 280
	}
40396 ripley 281
	av[ac++] = argv[i];
282
	i0 = i;
283
    }
284
 
285
    if(!e_mode) {
62580 ripley 286
	if(++i0 >= argc) {
287
	    fprintf(stderr, "file name is missing\n");
288
	    exit(1);
289
	}
290
	if(strlen(argv[i0]) > PATH_MAX) {
40601 ripley 291
	    fprintf(stderr, "file name is too long\n");
292
	    exit(1);
293
	}
62580 ripley 294
	snprintf(buf, PATH_MAX+8, "--file=%s", argv[i0]);
40396 ripley 295
	av[ac++] = buf;
296
    }
66674 maechler 297
    // copy any user arguments, preceded by "--args"
298
    i = i0+1;
299
    if (i < argc) {
300
	av[ac++] = "--args";
301
	for(; i < argc; i++)
302
	    av[ac++] = argv[i];
303
    }
40361 ripley 304
    av[ac] = (char *) NULL;
40481 ripley 305
#ifdef HAVE_PUTENV
74084 luke 306
    /* If provided, and default packages are not specified on the
307
       command line, then R_SCRIPT_DEFAULT_PACKAGES takes precedence
73995 luke 308
       over R_DEFAULT_PACKAGES. */
74084 luke 309
    if (! have_cmdarg_default_packages) {
310
	char *rdpvar = "R_DEFAULT_PACKAGES";
311
	char *rsdp = getenv("R_SCRIPT_DEFAULT_PACKAGES");
312
	if (rsdp && strlen(rdpvar) + strlen(rsdp) + 1 < sizeof(buf2)) {
313
	    snprintf(buf2, sizeof(buf2), "%s=%s", rdpvar, rsdp);
314
	    putenv(buf2);
315
	}
73995 luke 316
    }
317
 
73996 luke 318
    p = getenv("R_SCRIPT_LEGACY");
74084 luke 319
    int legacy = (p && (strcmp(p, "yes") == 0)) ? 1 : 0;
320
    //int legacy = (p && (strcmp(p, "no") == 0)) ? 0 : 1;
73996 luke 321
    if(legacy && !set_dp && !getenv("R_DEFAULT_PACKAGES"))
40562 ripley 322
	putenv("R_DEFAULT_PACKAGES=datasets,utils,grDevices,graphics,stats");
62045 urbaneks 323
 
65805 ripley 324
#ifndef _WIN32
62045 urbaneks 325
    /* pass on r_arch from this binary to R as a default */
326
    if (!getenv("R_ARCH") && *rarch) {
327
	/* we have to prefix / so we may as well use putenv */
328
	if (strlen(rarch) + 9 > sizeof(buf2)) {
329
	    fprintf(stderr, "impossibly long string for R_ARCH\n");
330
	    exit(1);
331
	}
332
	strcpy(buf2, "R_ARCH=/");
333
	strcat(buf2, rarch);
334
	putenv(buf2);
335
    }
40481 ripley 336
#endif
62045 urbaneks 337
#endif
40361 ripley 338
    if(verbose) {
339
	fprintf(stderr, "running\n  '%s", cmd);
66644 maechler 340
	for(i = 1; i < ac; i++) fprintf(stderr, " %s", av[i]);
40361 ripley 341
	fprintf(stderr, "'\n\n");
342
    }
65805 ripley 343
#ifndef _WIN32
40361 ripley 344
    res = execv(cmd, av); /* will not return if R is launched */
345
    perror("Rscript execution error");
346
#else
347
    AppMain(ac, av);
348
#endif
349
    return res;
46084 ripley 350
#else /* No execv*/
40361 ripley 351
    fprintf(stderr, "Rscript is not supported on this system");
352
    exit(1);
353
#endif
354
}