1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2003-2017. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 /*
21  * Some code just simply does not deserve functions :-)
22  * Dead simple installation program to set up init files etc after erlang is
23  * copied to its destination. Also to be used after a patch is applied.
24  */
25 
26 #include <windows.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include "init_file.h"
30 
wmain(int argc,wchar_t ** argv)31 int wmain(int argc, wchar_t **argv)
32 {
33     int silent = 0;
34     int start_sasl = 0;
35     wchar_t *root = NULL;
36     int i;
37     wchar_t buffer[MAX_PATH];
38     wchar_t erts_dir[MAX_PATH];
39     wchar_t release_dir[MAX_PATH];
40     wchar_t bin_dir[MAX_PATH];
41     char *tmp;
42     char tmp_utf8[MAX_PATH*4];
43     wchar_t my_ini_filename[MAX_PATH];
44     InitFile *my_ini_file;
45     InitSection *my_ini_section;
46     char erts_version[MAX_PATH];
47     InitFile *ini_file;
48     InitSection *ini_section;
49     HANDLE module = GetModuleHandle(NULL);
50     wchar_t *binaries[] = { L"erl.exe", L"werl.exe", L"erlc.exe", L"erl_call.exe",
51 			    L"dialyzer.exe",
52 			    L"typer.exe",
53 			    L"escript.exe", L"ct_run.exe", NULL };
54     wchar_t *scripts[] = { L"start_clean.boot", L"start_sasl.boot", L"no_dot_erlang.boot", NULL };
55     wchar_t fromname[MAX_PATH];
56     wchar_t toname[MAX_PATH];
57     size_t  converted;
58 
59     for (i = 1; i < argc; ++i) {
60 	switch(argv[i][0]) {
61 	case L'-' :
62 	    switch(argv[i][1]) {
63 	    case L's' :
64 		silent = 1;
65 		break;
66 	    default:
67 		fprintf(stderr, "Unknown command switch %S\n",
68 			argv[i]);
69 		exit(1);
70 	    }
71 	    break;
72 	default: {
73 	    if (root != NULL) {
74 		fprintf(stderr, "Only one root directory can be specified, "
75 			"parameter %S is illegal\n",
76 			argv[i]);
77 		exit(1);
78 	    }
79 	    root = argv[i];
80 	    }
81 	    break;
82 	}
83     }
84     if (root == NULL) {
85 	if (module == NULL) {
86 	    fprintf(stderr, "Cannot GetModuleHandle()\n");
87 	    exit(1);
88 	}
89 
90 	if (GetModuleFileNameW(module,buffer,MAX_PATH) == 0) {
91 	    fprintf(stderr,"Could not GetModuleFileName()\n");
92 	    exit(1);
93 	}
94 	i = wcslen(buffer) - 1;
95 	while ( i >= 0 && buffer[i] != L'\\') {
96 	    --i;
97 	}
98 	if (i < 0) {
99 	    fprintf(stderr,"GetModuleFileName returned broken path\n");
100 	    exit(1);
101 	}
102 	buffer[i] = L'\0';
103 	root = buffer;
104     }
105 
106     if (!silent) {
107 	char answer[100];
108 	char *eol;
109 	start_sasl = 1;
110 	printf("Do you want a minimal startup instead of sasl [No]: ");
111 	fflush(stdout);
112 	if (fgets(answer,100,stdin) == NULL) {
113 	    fprintf(stderr, "Could not read answer from user.\n");
114 	    exit(1);
115 	}
116 	eol = strchr(answer,'\n');
117 	if (eol == NULL) {
118 	    while (getchar() != '\n')
119 		;
120 	} else {
121 	    *eol = '\0';
122 	}
123 	if ((eol = strchr(answer, '\r')) != NULL) {
124 	    *eol = '\0';
125 	}
126 	if (_stricmp(answer,"yes") == 0 || _stricmp(answer,"y") == 0) {
127 	    start_sasl = 0;
128 	}
129     }
130     swprintf(my_ini_filename, MAX_PATH, L"%s\\Install.ini", root);
131     my_ini_file = load_init_file(my_ini_filename);
132     if (my_ini_file == NULL) {
133 	fprintf(stderr,"Cannot open init file %S\n",my_ini_filename);
134 	exit(1);
135     }
136 
137     if ((my_ini_section = lookup_init_section(my_ini_file,"Install"))
138 	== NULL) {
139 	fprintf(stderr,"No [Install] section in init file %S\n",
140 		my_ini_filename);
141 	exit(1);
142     }
143 
144     if ((tmp = lookup_init_entry(my_ini_section, "VSN")) == NULL) {
145 	fprintf(stderr,"No key VSN in init file %S\n",
146 		my_ini_filename);
147 	exit(1);
148     }
149     strcpy(erts_version,tmp);
150 
151     swprintf(erts_dir,MAX_PATH,L"%s\\erts-%S\\bin",root,erts_version);
152     if ((tmp = lookup_init_entry(my_ini_section, "SYSTEM_VSN")) == NULL) {
153 	fprintf(stderr,"No key SYSTEM_VSN in init file %S\n",
154 		 my_ini_filename);
155 	exit(1);
156     }
157     swprintf(release_dir,MAX_PATH,L"%s\\releases\\%S",root,tmp);
158 
159     swprintf(bin_dir,MAX_PATH,L"%s\\bin",root);
160     CreateDirectoryW(bin_dir,NULL);
161 
162     free_init_file(my_ini_file);
163 
164     for (i = 0; binaries[i] != NULL; ++i) {
165 	swprintf(fromname,MAX_PATH,L"%s\\%s",erts_dir,binaries[i]);
166 	swprintf(toname,MAX_PATH,L"%s\\%s",bin_dir,binaries[i]);
167 	if (GetFileAttributesW(fromname) == 0xFFFFFFFF) {
168 	    fprintf(stderr,"Could not find file %S\n",
169 		    fromname);
170 	    exit(1);
171 	}
172 	if (!CopyFileW(fromname,toname,FALSE)) {
173 	    fprintf(stderr,"Could not copy file %S to %S\n",
174 		    fromname,toname);
175 	    fprintf(stderr,"Continuing installation anyway...\n");
176 	}
177     }
178 
179     for (i = 0; scripts[i] != NULL; ++i) {
180 	swprintf(fromname,MAX_PATH,L"%s\\%s",release_dir,scripts[i]);
181 	swprintf(toname,MAX_PATH,L"%s\\%s",bin_dir,scripts[i]);
182 	if (GetFileAttributesW(fromname) == 0xFFFFFFFF) {
183 	    fprintf(stderr,"Could not find file %S\n",
184 		    fromname);
185 	    exit(1);
186 	}
187 	if (!CopyFileW(fromname,toname,FALSE)) {
188 	    fprintf(stderr,"Could not copy file %S to %S\n",
189 		    fromname,toname);
190 	    fprintf(stderr,"Cannot continue installation, bailing out.\n");
191 	    exit(1);
192 	}
193     }
194     if (start_sasl) {
195 	swprintf(fromname,MAX_PATH,L"%s\\start_sasl.boot",bin_dir);
196     } else {
197 	swprintf(fromname,MAX_PATH,L"%s\\start_clean.boot",bin_dir);
198     }
199     swprintf(toname,MAX_PATH,L"%s\\start.boot",bin_dir);
200     if (!CopyFileW(fromname,toname,FALSE)) {
201 	fprintf(stderr,"Could not copy file %S to %S\n",
202 		fromname,toname);
203 	fprintf(stderr,"Cannot continue installation, bailing out.\n");
204 	exit(1);
205     }
206 
207     /* OBS!!! If the format of the init file is changed, do not forget
208        to update release_handler:write_ini_file(...) */
209     ini_file = create_init_file();
210     ini_section = create_init_section("erlang");
211     add_init_section(ini_file,ini_section);
212     WideCharToMultiByte(CP_UTF8,0,erts_dir,-1,tmp_utf8,MAX_PATH*4,NULL,NULL);
213     add_init_entry(ini_section,"Bindir",tmp_utf8);
214     add_init_entry(ini_section,"Progname","erl");
215     WideCharToMultiByte(CP_UTF8,0,root,-1,tmp_utf8,MAX_PATH*4,NULL,NULL);
216     add_init_entry(ini_section,"Rootdir",tmp_utf8);
217     swprintf(fromname,MAX_PATH,L"%s\\erl.ini",erts_dir);
218     swprintf(toname,MAX_PATH,L"%s\\erl.ini",bin_dir);
219     if (store_init_file(ini_file,fromname) != 0) {
220 	fprintf(stderr,"Could not create file %S\n",
221 		fromname);
222 	fprintf(stderr,"Cannot continue installation, bailing out.\n");
223 	exit(1);
224     }
225     if (!CopyFileW(fromname,toname,FALSE)) {
226 	fprintf(stderr,"Could not copy file %S to %S\n",
227 		 fromname,toname);
228 	fprintf(stderr,"Cannot continue installation, bailing out.\n");
229 	exit(1);
230     }
231     if (!silent) {
232 	printf("Erlang %s installed successfully\n", erts_version);
233     }
234     return 0;
235 }
236 
237 
238 
239