The R Project SVN R

Rev

Rev 60370 | Rev 64237 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5223 ripley 1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
59039 ripley 4
 *  Copyright (C) 1997--2010  The R Core Team
5223 ripley 5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
42300 ripley 17
 *  along with this program; if not, a copy is available at
18
 *  http://www.r-project.org/Licenses/
5223 ripley 19
 */
20
 
45070 ripley 21
	 /* See ../unix/system.txt for a description of functions */
5223 ripley 22
 
45070 ripley 23
	/* Windows analogue of unix/sys-unix.c: often rather similar */
5223 ripley 24
 
25
#ifdef HAVE_CONFIG_H
7701 hornik 26
#include <config.h>
5223 ripley 27
#endif
28
 
51849 ripley 29
#include <Defn.h>
60667 ripley 30
#include <Internal.h>
51849 ripley 31
#include <Fileio.h>
32
#include <Startup.h>
5223 ripley 33
 
51849 ripley 34
#include <ctype.h> /* for isalpha */
35
 
11139 maechler 36
extern Rboolean LoadInitFile;
5223 ripley 37
extern UImode  CharacterMode;
38
 
39
/*
40
 *  4) INITIALIZATION AND TERMINATION ACTIONS
41
 */
42
 
43
FILE *R_OpenInitFile(void)
44
{
51229 ripley 45
    char  buf[PATH_MAX], *p = getenv("R_PROFILE_USER");
5223 ripley 46
    FILE *fp;
47
 
48
    fp = NULL;
49
    if (LoadInitFile) {
54654 ripley 50
	if(p) {
51
	    if(!*p) return NULL;  /* set to "" */
45059 ripley 52
	    return R_fopen(R_ExpandFileName(p), "r");
54654 ripley 53
	}
5223 ripley 54
	if ((fp = R_fopen(".Rprofile", "r")))
55
	    return fp;
51229 ripley 56
	snprintf(buf, PATH_MAX, "%s/.Rprofile", getenv("R_USER"));
5223 ripley 57
	if ((fp = R_fopen(buf, "r")))
58
	    return fp;
59
    }
60
    return fp;
61
}
62
/*
63
 *  5) FILESYSTEM INTERACTION
64
 */
65
 
66
 
67
static int HaveHOME=-1;
68
static char UserHOME[PATH_MAX];
69
static char newFileName[PATH_MAX];
41783 ripley 70
const char *R_ExpandFileName(const char *s)
5223 ripley 71
{
72
    char *p;
73
 
41778 ripley 74
    if(s[0] != '~') return s;
75
    if(isalpha(s[1])) return s;
5223 ripley 76
    if(HaveHOME < 0) {
77
	HaveHOME = 0;
45070 ripley 78
	p = getenv("R_USER"); /* should be set so the rest is a safety measure */
28888 ripley 79
	if(p && strlen(p) && strlen(p) < PATH_MAX) {
5223 ripley 80
	    strcpy(UserHOME, p);
45070 ripley 81
	    HaveHOME = 1;
5223 ripley 82
	} else {
41474 ripley 83
	    p = getenv("HOME");
84
	    if(p && strlen(p) && strlen(p) < PATH_MAX) {
5223 ripley 85
		strcpy(UserHOME, p);
41474 ripley 86
		HaveHOME = 1;
87
	    } else {
88
		p = getenv("HOMEDRIVE");
89
		if(p && strlen(p) < PATH_MAX) {
90
		    strcpy(UserHOME, p);
91
		    p = getenv("HOMEPATH");
92
		    if(p && strlen(UserHOME) + strlen(p) < PATH_MAX) {
93
			strcat(UserHOME, p);
94
			HaveHOME = 1;
95
		    }
5223 ripley 96
		}
97
	    }
98
	}
99
    }
28888 ripley 100
    if(HaveHOME > 0 && strlen(UserHOME) + strlen(s+1) < PATH_MAX) {
5223 ripley 101
	strcpy(newFileName, UserHOME);
102
	strcat(newFileName, s+1);
103
	return newFileName;
41778 ripley 104
    } else return s;
5223 ripley 105
}
106
 
107
/*
108
 *  7) PLATFORM DEPENDENT FUNCTIONS
109
 */
110
 
111
SEXP do_machine(SEXP call, SEXP op, SEXP args, SEXP env)
112
{
113
    return mkString("Win32");
114
}
115
 
36901 ripley 116
#define WIN32_LEAN_AND_MEAN 1
6121 ripley 117
#include <windows.h>
118
 
5223 ripley 119
static DWORD StartTime;
120
 
6098 pd 121
static FILETIME Create, Exit, Kernel, User;
122
 
7824 ripley 123
void R_setStartTime(void)
5223 ripley 124
{
125
    StartTime = GetTickCount();
126
}
127
 
10172 luke 128
void R_getProcTime(double *data)
5223 ripley 129
{
42253 ripley 130
    DWORD elapsed;
6098 pd 131
    double kernel, user;
45072 ripley 132
 
37670 ripley 133
    /* This is in msec, but to clock-tick accuracy,
134
       said to be 10ms on NT and 55ms on Win95 */
6098 pd 135
    elapsed = (GetTickCount() - StartTime) / 10;
5223 ripley 136
 
45072 ripley 137
    /* These are in units of 100ns, but with an accuracy only
138
       in clock ticks.  So we round to 0.01s */
139
    GetProcessTimes(GetCurrentProcess(), &Create, &Exit, &Kernel, &User);
140
    user = 1e-5 * ((double) User.dwLowDateTime +
141
		   (double) User.dwHighDateTime * 4294967296.0);
142
    user = floor(user)/100.0;
143
    kernel = 1e-5 * ((double) Kernel.dwLowDateTime +
144
		     (double) Kernel.dwHighDateTime * 4294967296.0);
145
    kernel = floor(kernel)/100.0;
10172 luke 146
    data[0] = user;
147
    data[1] = kernel;
148
    data[2] = (double) elapsed / 100.0;
149
    data[3] = R_NaReal;
150
    data[4] = R_NaReal;
151
}
152
 
57499 ripley 153
/* use in memory.c: increments for CPU times */
10172 luke 154
double R_getClockIncrement(void)
155
{
45070 ripley 156
    return 1.0 / 100.0;
10172 luke 157
}
5223 ripley 158
 
159
/*
160
 * flag =0 don't wait/ignore stdout
161
 * flag =1 wait/ignore stdout
162
 * flag =2 wait/copy stdout to the console
52802 ripley 163
 * flag =3 wait/return stdout (intern=TRUE)
5223 ripley 164
 * Add 10 to minimize application
165
 * Add 20 to make application "invisible"
166
*/
167
 
168
#include "run.h"
169
 
22229 ripley 170
#define INTERN_BUFSIZE 8096
5223 ripley 171
SEXP do_system(SEXP call, SEXP op, SEXP args, SEXP rho)
172
{
173
    rpipe *fp;
22229 ripley 174
    char  buf[INTERN_BUFSIZE];
52814 ripley 175
    const char *fout = "", *ferr = "";
176
    int   vis = 0, flag = 2, i = 0, j, ll;
177
    SEXP  cmd, fin, Stdout, Stderr, tlist = R_NilValue, tchar, rval;
5223 ripley 178
 
179
    checkArity(op, args);
52814 ripley 180
    cmd = CAR(args);
181
    if (!isString(cmd) || LENGTH(cmd) != 1)
32888 ripley 182
	errorcall(call, _("character string expected as first argument"));
52814 ripley 183
    args = CDR(args);
184
    flag = asInteger(CAR(args)); args = CDR(args);
185
    if (flag >= 20) {vis = -1; flag -= 20;}
186
    else if (flag >= 10) {vis = 0; flag -= 10;}
187
    else vis = 1;
188
 
189
    fin = CAR(args);
190
    if (!isString(fin))
32888 ripley 191
	errorcall(call, _("character string expected as third argument"));
52814 ripley 192
    args = CDR(args);
193
    Stdout = CAR(args);
194
    args = CDR(args);
195
    Stderr = CAR(args);
53612 ripley 196
 
5223 ripley 197
    if (CharacterMode == RGui) {
53348 ripley 198
	/* This is a rather conservative approach: if
199
	   Rgui is launched from a console window it does have
200
	   standard handles -- but users might well not expect that.
201
	*/
5223 ripley 202
	SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
203
	SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
204
	SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
52814 ripley 205
    } else {
206
	if (flag == 2) flag = 1; /* ignore std.output.on.console */
53348 ripley 207
	if (TYPEOF(Stdout) == STRSXP) fout = CHAR(STRING_ELT(Stdout, 0));
208
	else if (asLogical(Stdout) == 0) fout = NULL;
209
	if (TYPEOF(Stderr) == STRSXP) ferr = CHAR(STRING_ELT(Stderr, 0));
210
	else if (asLogical(Stderr) == 0) ferr = NULL;
5223 ripley 211
    }
52814 ripley 212
 
213
    if (flag < 2) { /* Neither intern = TRUE nor
52813 ripley 214
		       show.output.on.console for Rgui */
52814 ripley 215
	ll = runcmd(CHAR(STRING_ELT(cmd, 0)),
216
		    getCharCE(STRING_ELT(cmd, 0)),
217
		    flag, vis, CHAR(STRING_ELT(fin, 0)), fout, ferr);
5223 ripley 218
    } else {
52813 ripley 219
	/* read stdout +/- stderr from pipe */
40468 ripley 220
	int m = 0;
52814 ripley 221
	if(flag == 2 /* show on console */ || CharacterMode == RGui) m = 3;
222
	if(TYPEOF(Stderr) == LGLSXP)
223
	    m = asLogical(Stderr) ? 2 : 0;
224
	if(m  && TYPEOF(Stdout) == LGLSXP && asLogical(Stdout)) m = 3;
53595 ripley 225
	fp = rpipeOpen(CHAR(STRING_ELT(cmd, 0)), getCharCE(STRING_ELT(cmd, 0)),
226
		       vis, CHAR(STRING_ELT(fin, 0)), m, fout, ferr);
5223 ripley 227
	if (!fp) {
52813 ripley 228
	    /* If intern = TRUE generate an error */
52802 ripley 229
	    if (flag == 3) error(runerror());
5223 ripley 230
	    ll = NOLAUNCH;
231
	} else {
52813 ripley 232
	    /* FIXME: use REPROTECT */
53612 ripley 233
	    if (flag == 3) {
234
		PROTECT(tlist);
235
		/* honour intern = FALSE, ignore.stdout = TRUE */
236
		if (m > 0 ||
237
		    (!(TYPEOF(Stdout) == LGLSXP && !asLogical(Stdout))))
238
		    for (i = 0; rpipeGets(fp, buf, INTERN_BUFSIZE); i++) {
239
			ll = strlen(buf) - 1;
240
			if ((ll >= 0) && (buf[ll] == '\n')) buf[ll] = '\0';
241
			tchar = mkChar(buf);
242
			UNPROTECT(1); /* tlist */
243
			PROTECT(tlist = CONS(tchar, tlist));
244
		    }
245
 
246
	    } else {
247
		for (i = 0; rpipeGets(fp, buf, INTERN_BUFSIZE); i++)
5223 ripley 248
		    R_WriteConsole(buf, strlen(buf));
249
	    }
250
	    ll = rpipeClose(fp);
53348 ripley 251
	    if(ll) {
252
		warningcall(R_NilValue, 
253
			    _("running command '%s' had status %d"), 
254
			    CHAR(STRING_ELT(cmd, 0)), ll);
255
	    }
5223 ripley 256
	}
257
    }
52813 ripley 258
    if (flag == 3) { /* intern = TRUE: convert pairlist to list */
52802 ripley 259
	PROTECT(rval = allocVector(STRSXP, i));
5223 ripley 260
	for (j = (i - 1); j >= 0; j--) {
10172 luke 261
	    SET_STRING_ELT(rval, j, CAR(tlist));
5223 ripley 262
	    tlist = CDR(tlist);
263
	}
60370 urbaneks 264
	if(ll) {
265
	    SEXP lsym = install("status");
266
	    setAttrib(rval, lsym, ScalarInteger(ll));
267
	}
52802 ripley 268
	UNPROTECT(2);
269
	return rval;
5223 ripley 270
    } else {
52814 ripley 271
	rval = ScalarInteger(ll);
5223 ripley 272
	R_Visible = 0;
52814 ripley 273
	return rval;
5223 ripley 274
    }
275
}