The R Project SVN R

Rev

Rev 62045 | Rev 64434 | 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
62580 ripley 3
 *  Copyright (C) 2006-13  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
17
 *  http://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
27
R --slave --no-restore --vanilla --file=foo [script_args]
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
 
53060 ripley 42
#ifdef WIN32
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
 
40361 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
{
40396 ripley 94
    fprintf(stderr, "Usage: /path/to/Rscript [--options] [-e expr] 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");
102
    fprintf(stderr, "or options to R, in addition to --slave --no-restore, such as\n");
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");
40361 ripley 111
}
112
 
113
 
114
int main(int argc, char *argv[])
115
{
116
#ifdef HAVE_EXECV
40601 ripley 117
    char cmd[PATH_MAX+1], buf[PATH_MAX+8], buf2[1100], *p;
40481 ripley 118
    int i, i0 = 0, ac = 0, res = 0, e_mode = 0, set_dp = 0;
40361 ripley 119
    char **av;
120
 
121
    if(argc <= 1) {
122
	usage();
123
	exit(1);
124
    }
55417 luke 125
    av = (char **) malloc((size_t) (argc+4)*sizeof(char *));
40361 ripley 126
    if(!av) {
127
	fprintf(stderr, "malloc failure\n");
128
	exit(1);
129
    }
130
 
131
    p = getenv("RHOME");
132
#ifdef WIN32
54654 ripley 133
    if(p && *p)
51072 ripley 134
	snprintf(cmd, PATH_MAX+1, "%s\\%s\\Rterm.exe",  p, BINDIR);
40361 ripley 135
    else {
136
	char rhome[MAX_PATH];
137
	GetModuleFileName(NULL, rhome, MAX_PATH);
138
	p = strrchr(rhome,'\\');
139
	if(!p) {fprintf(stderr, "installation problem\n"); exit(1);}
140
	*p = '\0';
141
	snprintf(cmd, PATH_MAX+1, "%s\\Rterm.exe",  rhome);
142
    }
143
#else
54654 ripley 144
    if(!(p && *p)) p = rhome;
145
    /* avoid snprintf here */
40601 ripley 146
    if(strlen(p) + 6 > PATH_MAX) {
147
	fprintf(stderr, "impossibly long path for RHOME\n");
148
	exit(1);
149
    }
62580 ripley 150
    snprintf(cmd, PATH_MAX+1, "%s/bin/R", p);
40361 ripley 151
#endif
152
    av[ac++] = cmd;
153
    av[ac++] = "--slave";
154
    av[ac++] = "--no-restore";
45475 ripley 155
 
40361 ripley 156
    if(argc == 2) {
157
	if(strcmp(argv[1], "--help") == 0) {
158
	    usage();
159
	    exit(0);
160
	}
161
	if(strcmp(argv[1], "--version") == 0) {
53300 ripley 162
	    if(strlen(R_STATUS) == 0)
163
		fprintf(stderr, "R scripting front-end version %s.%s (%s-%s-%s)\n", 
164
			R_MAJOR, R_MINOR, R_YEAR, R_MONTH, R_DAY);
165
	    else 
60975 ripley 166
		fprintf(stderr, "R scripting front-end version %s.%s %s (%s-%s-%s r%d)\n", 
53300 ripley 167
			R_MAJOR, R_MINOR, R_STATUS, R_YEAR, R_MONTH, R_DAY,
168
			R_SVN_REVISION);
40361 ripley 169
	    exit(0);
170
	}
171
    }
45475 ripley 172
 
40396 ripley 173
    /* first copy over any -e or --foo args */
174
    for(i = 1; i < argc; i++) {
175
	if(strcmp(argv[i], "-e") == 0) {
176
	    e_mode = 1;
177
	    av[ac++] = argv[i];
178
	    if(!argv[++i]) {
179
		fprintf(stderr, "-e not followed by an expression\n");
180
		exit(1);
40361 ripley 181
	    }
40396 ripley 182
	    av[ac++] = argv[i];
183
	    i0 = i;
184
	    continue;
185
	}
49838 falcon 186
	if(strncmp(argv[i], "--", 2) != 0) break;
40396 ripley 187
	if(strcmp(argv[i], "--verbose") == 0) {
188
	    verbose = 1;
189
	    i0 = i;
190
	    continue;
191
	}
192
	if(strncmp(argv[i], "--default-packages=", 18) == 0) {
40481 ripley 193
	    set_dp = 1;
40601 ripley 194
	    if(strlen(argv[i]) > 1000) {
195
		fprintf(stderr, "unable to set R_DEFAULT_PACKAGES\n");
196
		exit(1);
197
	    }
62580 ripley 198
	    snprintf(buf2, 1100, "R_DEFAULT_PACKAGES=%s", argv[i]+19);
40396 ripley 199
	    if(verbose)
200
		fprintf(stderr, "setting '%s'\n", buf2);
40361 ripley 201
#ifdef HAVE_PUTENV
45475 ripley 202
	    if(putenv(buf2))
40361 ripley 203
#endif
40396 ripley 204
	    {
205
		fprintf(stderr, "unable to set R_DEFAULT_PACKAGES\n");
206
		exit(1);
40361 ripley 207
	    }
208
	    i0 = i;
40396 ripley 209
	    continue;
40361 ripley 210
	}
40396 ripley 211
	av[ac++] = argv[i];
212
	i0 = i;
213
    }
214
 
215
    if(!e_mode) {
62580 ripley 216
	if(++i0 >= argc) {
217
	    fprintf(stderr, "file name is missing\n");
218
	    exit(1);
219
	}
220
	if(strlen(argv[i0]) > PATH_MAX) {
40601 ripley 221
	    fprintf(stderr, "file name is too long\n");
222
	    exit(1);
223
	}
62580 ripley 224
	snprintf(buf, PATH_MAX+8, "--file=%s", argv[i0]);
40396 ripley 225
	av[ac++] = buf;
226
    }
40361 ripley 227
    av[ac++] = "--args";
228
    for(i = i0+1; i < argc; i++) av[ac++] = argv[i];
229
    av[ac] = (char *) NULL;
40481 ripley 230
#ifdef HAVE_PUTENV
231
    if(!set_dp && !getenv("R_DEFAULT_PACKAGES"))
40562 ripley 232
	putenv("R_DEFAULT_PACKAGES=datasets,utils,grDevices,graphics,stats");
62045 urbaneks 233
 
234
#ifndef WIN32
235
    /* pass on r_arch from this binary to R as a default */
236
    if (!getenv("R_ARCH") && *rarch) {
237
	/* we have to prefix / so we may as well use putenv */
238
	if (strlen(rarch) + 9 > sizeof(buf2)) {
239
	    fprintf(stderr, "impossibly long string for R_ARCH\n");
240
	    exit(1);
241
	}
242
	strcpy(buf2, "R_ARCH=/");
243
	strcat(buf2, rarch);
244
	putenv(buf2);
245
    }
40481 ripley 246
#endif
62045 urbaneks 247
#endif
40361 ripley 248
    if(verbose) {
249
	fprintf(stderr, "running\n  '%s", cmd);
250
	for(i = 1; i < ac-1; i++) fprintf(stderr, " %s", av[i]);
251
	fprintf(stderr, "'\n\n");
252
    }
253
#ifndef WIN32
254
    res = execv(cmd, av); /* will not return if R is launched */
255
    perror("Rscript execution error");
256
#else
257
    AppMain(ac, av);
258
#endif
259
    return res;
46084 ripley 260
#else /* No execv*/
40361 ripley 261
    fprintf(stderr, "Rscript is not supported on this system");
262
    exit(1);
263
#endif
264
}