Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 442 lines (370 sloc) 13.485 kb
38fb85e @klacke ""
authored
1 %%%----------------------------------------------------------------------
2 %%% File : yaws_ctl.erl
3 %%% Author : Claes Wikstrom <klacke@bluetail.com>
4 %%% Purpose :
5 %%% Created : 29 Apr 2002 by Claes Wikstrom <klacke@bluetail.com>
6 %%%----------------------------------------------------------------------
7
8
9 %% some code to remoteley control a running yaws server
10
11 -module(yaws_ctl).
12 -author('klacke@bluetail.com').
13
14 -include_lib("kernel/include/file.hrl").
6cf3ece @klacke ""
authored
15 -include("../include/yaws.hrl").
16 -include("../include/yaws_api.hrl").
28e4c73 @klacke first attempt to run properly under cygwin
authored
17 -include("yaws_debug.hrl").
2f51c68 @klacke -check arg
authored
18
9a74e5a @klacke Major general code cleanup, finally got rid of all the export_all sta…
authored
19 -export([start/2, actl_trace/1]).
20 -export([ls/1,hup/1,stop/1,status/1,load/1,
21 check/1,trace/1]).
22 %% internal
23 -export([run/1, aloop/3]).
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
24
25
26 %% assumes the appropriate file structures
27 %% are already created with the right perms
28
6dc4cca @klacke ""
authored
29 start(_GC, FirstTime) when FirstTime == false ->
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
30 ok;
31 start(GC, true) ->
d07115c @klacke Several cleanups due to dialyzer, also moved the control file into us…
authored
32 proc_lib:start_link(?MODULE, run, [GC]).
28e4c73 @klacke first attempt to run properly under cygwin
authored
33
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
34
35 run(GC) ->
36 %% First check if there is already a Yaws system running
37 %% with the same sid.
38 case connect(GC#gconf.id) of
0be3c7e @klacke untabified all of yaws
authored
39 {ok, Sock, _Key} ->
40 %% Not good, let's get some sys info
41 %% from that system so we can produce a good error
42 %% message
43 gen_tcp:close(Sock),
44 e("There is already a yaws system running with the same ~n"
d07115c @klacke Several cleanups due to dialyzer, also moved the control file into us…
authored
45 " id <~p> on this computer and this user, ~n"
0be3c7e @klacke untabified all of yaws
authored
46 " set another id in the yaws conf file ~n",
47 [GC#gconf.id]);
48 {error, eaccess} ->
49 %% We're not allowed to open the ctl file
d07115c @klacke Several cleanups due to dialyzer, also moved the control file into us…
authored
50 e("Error reading ~s, you don't have access rights to read it",
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
51 [yaws:ctl_file(GC#gconf.id)]);
0be3c7e @klacke untabified all of yaws
authored
52 {error, _} ->
53 %% Fine, this should be the case
54 run_listen(GC)
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
55 end.
56
57
58 ctl_args() ->
0be3c7e @klacke untabified all of yaws
authored
59 [{packet, 2},
60 {active, false},
61 binary,
62 {ip, {127,0,0,1}},
63 {reuseaddr, true}].
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
64
65 run_listen(GC) ->
66 case gen_tcp:listen(0, ctl_args()) of
0be3c7e @klacke untabified all of yaws
authored
67 {ok, L} ->
68 case inet:sockname(L) of
69 {ok, {_, Port}} ->
70 {A1, A2, A3}=now(),
71 random:seed(A1, A2, A3),
72 Key = random:uniform(1 bsl 64),
73 case w_ctl_file(GC#gconf.id, Port, Key) of
74 ok ->
75 proc_lib:init_ack(ok),
76 aloop(L, GC, Key);
77 error ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
78 e(
0be3c7e @klacke untabified all of yaws
authored
79 "Failed to create/manipulate the ctlfile ~n"
80 "called ~s~n"
81 "Either problems with permissions or "
82 " earlier runs of yaws ~nwith the same id "
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
83 " <~p> as this, check dir for perms~n",
84 [yaws:ctl_file(GC#gconf.id), GC#gconf.id])
0be3c7e @klacke untabified all of yaws
authored
85 end;
86 Err ->
87 e("Cannot get sockname for ctlsock: ~p",[Err] )
88 end;
89 Err ->
90 e("Cannot listen on ctl socket, fatal: ~p", [Err])
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
91 end.
92
0c9da97 @klacke added ability to run as different user than root
authored
93
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
94 e(Fmt, Args) ->
95 proc_lib:init_ack({error, io_lib:format(Fmt, Args)}),
96 exit(normal).
97
98
99
100 %% write the control file, set perms of the file
101 %% so that only this user can read the file
102 %% That way we're making sure different users
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
103 %% cannot manipulate each others webservers
f4e3e44 @klacke patch by Sergei Golovan which fixed a CGI bug and made yaws_ctl safe
authored
104 w_ctl_file(Sid, Port, Key) ->
105 case catch
0be3c7e @klacke untabified all of yaws
authored
106 begin
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
107 F = yaws:ctl_file(Sid),
108 error_logger:info_msg("Ctlfile : ~s~n", [F]),
0be3c7e @klacke untabified all of yaws
authored
109 file:write_file(F, io_lib:format("~w.", [{Port,Key}])),
110 {ok, FI} = file:read_file_info(F),
111 ok = file:write_file_info(F, FI#file_info{mode = 8#00600})
112 end of
113 {'EXIT', _} ->
114 error;
115 _ ->
116 ok
117 end.
38fb85e @klacke ""
authored
118
119
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
120
f4e3e44 @klacke patch by Sergei Golovan which fixed a CGI bug and made yaws_ctl safe
authored
121 aloop(L, GC, Key) ->
38fb85e @klacke ""
authored
122 case gen_tcp:accept(L) of
0be3c7e @klacke untabified all of yaws
authored
123 {ok, A} ->
124 handle_a(A, GC, Key);
125 Err ->
126 error_logger:format("yaws_ctl failed to accept: ~p~n",
127 [Err]),
128 timer:sleep(2000),
129 ignore
38fb85e @klacke ""
authored
130 end,
f4e3e44 @klacke patch by Sergei Golovan which fixed a CGI bug and made yaws_ctl safe
authored
131 ?MODULE:aloop(L, GC, Key).
38fb85e @klacke ""
authored
132
f4e3e44 @klacke patch by Sergei Golovan which fixed a CGI bug and made yaws_ctl safe
authored
133 handle_a(A, GC, Key) ->
38fb85e @klacke ""
authored
134 case gen_tcp:recv(A, 0) of
0be3c7e @klacke untabified all of yaws
authored
135 {ok, Data} ->
136 case catch binary_to_term(Data) of
137 {hup, Key} ->
138 Res = yaws:dohup(A),
139 Res;
140 {stop, Key} ->
141 gen_tcp:send(A, io_lib:format(
142 "stopping yaws with id=~p\n",
143 [GC#gconf.id])),
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
144 file:delete(yaws:ctl_file(GC#gconf.id)),
0be3c7e @klacke untabified all of yaws
authored
145 init:stop();
146 {{trace, What}, Key} ->
147 Res = actl_trace(What),
148 gen_tcp:send(A, Res),
149 gen_tcp:close(A);
150 {status, Key} ->
151 a_status(A),
152 gen_tcp:close(A);
153 {{load, Mods}, Key} ->
154 a_load(A, Mods),
155 gen_tcp:close(A);
156 {id, Key} ->
157 a_id(A),
158 gen_tcp:close(A);
159 {Other, Key} ->
160 gen_tcp:send(A, io_lib:format("Other: ~p~n", [Other])),
161 gen_tcp:close(A);
162 _Other ->
163 gen_tcp:close(A)
164
165 end;
166 {error, _} ->
d07115c @klacke Several cleanups due to dialyzer, also moved the control file into us…
authored
167 gen_tcp:close(A)
38fb85e @klacke ""
authored
168 end.
169
6377222 @klacke ""
authored
170
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
171 %% We implement this by reloading a patched config
172 actl_trace(What) ->
173 case lists:member(What, [traffic, http, off]) of
0be3c7e @klacke untabified all of yaws
authored
174 true ->
175 {ok, GC, SCs} = yaws_api:getconf(),
176 case GC#gconf.trace of
177 false when What /= off->
178 yaws_api:setconf(GC#gconf{trace = {true, What}},SCs),
179 io_lib:format(
180 "Turning on trace of ~p to file ~s~n",
181 [What,
182 filename:join([GC#gconf.logdir,
183 "trace." ++ atom_to_list(What)])]);
184 false when What == off ->
185 io_lib:format("Tracing is already turned off ~n",[]);
186 {true, _} when What == off ->
187 yaws_api:setconf(GC#gconf{trace = false},SCs),
188 "Turning trace off \n";
189 {true, What} ->
190 io_lib:format("Trace of ~p is already turned on, ose 'off' "
191 "to turn off~n", [What]);
192 {true, _Other} ->
193 yaws_api:setconf(GC#gconf{trace = {true, What}},SCs),
194 io_lib:format(
195 "Turning on trace of ~p to file ~s~n",
196 [What,
197 filename:join([GC#gconf.logdir,
198 "trace." ++ atom_to_list(What)])])
199 end;
200 false ->
201 "Need either http | traffic | off as argument\n"
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
202 end.
203
204
6377222 @klacke ""
authored
205
206 f(Fmt, As) ->
207 io_lib:format(Fmt, As).
208
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
209
210 a_id(Sock) ->
211 ID = gen_server:call(yaws_server, id, []),
212 gen_tcp:send(Sock, ID),
213 ok.
214
215
6377222 @klacke ""
authored
216 a_status(Sock) ->
217 {UpTime, L} = yaws_server:stats(),
a7ac905 @klacke introduced opaque data in sconf
authored
218 {Days, {Hours, Minutes, _Secs}} = UpTime,
6377222 @klacke ""
authored
219 H = f("~n Uptime: ~w Days, ~w Hours, ~w Minutes ~n",
0be3c7e @klacke untabified all of yaws
authored
220 [Days, Hours, Minutes]),
221
6377222 @klacke ""
authored
222 T =lists:map(
0be3c7e @klacke untabified all of yaws
authored
223 fun({Host,IP,Hits}) ->
224 L1= f("stats for ~p at ~p ~n",
225 [Host,IP]),
226 T = "\n"
6377222 @klacke ""
authored
227 "URL Number of hits\n",
0be3c7e @klacke untabified all of yaws
authored
228 L2=lists:map(
229 fun({Url, Hits2}) ->
230 f("~-30s ~-7w ~n",
231 [Url, Hits2])
232 end, Hits),
233 END = "\n",
234 [L1, T, L2, END]
235 end, L),
8722844 @klacke a file which has at least one compilation error shouldn't be cached i…
authored
236 gen_tcp:send(Sock, [H, T]),
0be3c7e @klacke untabified all of yaws
authored
237
8722844 @klacke a file which has at least one compilation error shouldn't be cached i…
authored
238 %% Now lets' figure out the status of loaded modules
239 ok.
6377222 @klacke ""
authored
240
caa1a72 @carsten3347 Added command `-load' to yaws script.
carsten3347 authored
241 a_load(A, Mods) ->
242 case purge(Mods) of
0be3c7e @klacke untabified all of yaws
authored
243 ok ->
244 gen_tcp:send(A, f("~p~n", [loadm(Mods)]));
245 Err ->
246 gen_tcp:send(A, f("~p~n", [Err]))
caa1a72 @carsten3347 Added command `-load' to yaws script.
carsten3347 authored
247 end.
248
249 loadm([]) ->
250 [];
251 loadm([M|Ms]) ->
252 [code:load_file(M)|loadm(Ms)].
253
254 purge(Ms) ->
255 case purge(Ms, []) of
0be3c7e @klacke untabified all of yaws
authored
256 [] -> ok;
257 L -> {cannot_purge, L}
caa1a72 @carsten3347 Added command `-load' to yaws script.
carsten3347 authored
258 end.
259
260 purge([], Ack) ->
261 Ack;
262 purge([M|Ms], Ack) ->
263 case code:soft_purge(M) of
0be3c7e @klacke untabified all of yaws
authored
264 true ->
265 purge(Ms, Ack);
266 false ->
267 purge(Ms, [M|Ack])
caa1a72 @carsten3347 Added command `-load' to yaws script.
carsten3347 authored
268 end.
269
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
270 connect(Sid) ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
271 connect_file(yaws:ctl_file(Sid)).
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
272
273
274 %% The ctl file contains the port number the yaws server
f4e3e44 @klacke patch by Sergei Golovan which fixed a CGI bug and made yaws_ctl safe
authored
275 %% is listening at and secret key string.
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
276
277 connect_file(CtlFile) ->
f4e3e44 @klacke patch by Sergei Golovan which fixed a CGI bug and made yaws_ctl safe
authored
278 case file:consult(CtlFile) of
0be3c7e @klacke untabified all of yaws
authored
279 {ok, [{Port, Key}]} ->
280 case gen_tcp:connect({127,0,0,1}, Port,
281 [{active, false},
282 {reuseaddr, true},
283 binary,
284 {packet, 2}], 2000) of
285 {ok, Socket} ->
286 {ok, Socket, Key};
287 Err ->
288 Err
289 end;
290 Err ->
291 Err
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
292 end.
293
294
295
296 actl(SID, Term) ->
297 case connect(SID) of
0be3c7e @klacke untabified all of yaws
authored
298 {error, eaccess} ->
299 io:format("Another user is using the yaws sid <~p>, ~n"
300 "You are not allowd to read the file <~s>, ~n"
301 "specify by <-I id> which yaws system you want "
302 " to control~n",
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
303 [SID, yaws:ctl_file(SID)]),
304 timer:sleep(10),
305 erlang:halt(1);
0be3c7e @klacke untabified all of yaws
authored
306 {error, econnrefused} ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
307 io:format("No yaws system responds~n",[]),
308 timer:sleep(10),
309 erlang:halt(2);
0be3c7e @klacke untabified all of yaws
authored
310 {error, Reason} ->
311 io:format("You failed to read the ctlfile ~s~n"
312 "error was: <~p>~n"
313 "specify by <-I id> which yaws system you want "
314 " to control~n",
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
315 [yaws:ctl_file(SID), Reason]),
316 timer:sleep(10),
317 erlang:halt(3);
0be3c7e @klacke untabified all of yaws
authored
318 {ok, Socket, Key} ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
319 {Ret, Str} = s_cmd(Socket, SID, Key, Term),
320 io:format("~s", [Str]),
321 timer:sleep(10),
322 case Ret of
323 ok ->
324 erlang:halt(0);
325 error ->
326 erlang:halt(4)
327 end
328 end.
38fb85e @klacke ""
authored
329
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
330
f4e3e44 @klacke patch by Sergei Golovan which fixed a CGI bug and made yaws_ctl safe
authored
331 s_cmd(Fd, SID, Key, Term) ->
332 gen_tcp:send(Fd, term_to_binary({Term, Key})),
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
333 Res = case gen_tcp:recv(Fd, 0) of
0be3c7e @klacke untabified all of yaws
authored
334 {ok, Bin} ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
335 {ok, binary_to_list(Bin)};
0be3c7e @klacke untabified all of yaws
authored
336 Err ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
337 {error, io_lib:format("yaws server for yaws id <~p> not "
338 "responding: ~p ~n", [SID, Err])}
0be3c7e @klacke untabified all of yaws
authored
339 end,
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
340 gen_tcp:close(Fd),
341 Res.
3dc56a7 @klacke javascript support in ehtml
authored
342
38fb85e @klacke ""
authored
343
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
344 %% List existing yaws nodes on this machine for this user
d659ba3 @klacke added a 'yaws -ls' command that lists all yaws servers on localhost
authored
345 ls(_) ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
346 Dir = filename:join([yaws:tmpdir(), "yaws"]),
347 case file:list_dir(Dir) of
0be3c7e @klacke untabified all of yaws
authored
348 {ok, List} ->
349 io:format("~-15s~-10s~-10s~n",
350 ["Id", "Status", "Owner"]),
351 io:format("-------------------------------------~n",[]),
352 lists:foreach(
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
353 fun(IdDir) ->
354 lls(IdDir)
0be3c7e @klacke untabified all of yaws
authored
355 end, List);
356 _ ->
357 ok
358
d659ba3 @klacke added a 'yaws -ls' command that lists all yaws servers on localhost
authored
359 end,
360 init:stop().
6dc4cca @klacke ""
authored
361
362
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
363 lls(IdDir) ->
364 CtlFile = yaws:ctl_file(IdDir),
c9778e0 @klacke added support for 2 additional configure
authored
365 case {file:read_file_info(CtlFile),
0be3c7e @klacke untabified all of yaws
authored
366 file:read_file(CtlFile)} of
367 {{ok, FI}, {error, eacces}} ->
368 User = yaws:uid_to_name(FI#file_info.uid),
369 io:format("~-15s~-10s~-10s~n",
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
370 [IdDir, "noaccess", User]);
0be3c7e @klacke untabified all of yaws
authored
371 {{ok, FI}, {ok, _Bin}} ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
372 Running = case connect(IdDir) of
0be3c7e @klacke untabified all of yaws
authored
373 {ok, Sock, _Key} ->
374 gen_tcp:close(Sock),
375 "running";
376 {error, timeout} ->
377 "hanging??";
378 {error, eacces} ->
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
379 "noaccess";
0be3c7e @klacke untabified all of yaws
authored
380 _Err ->
381 "stopped"
382 end,
383 User = yaws:uid_to_name(FI#file_info.uid),
384 io:format("~-15s~-10s~-10s~n",
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
385 [IdDir, Running, User]);
0be3c7e @klacke untabified all of yaws
authored
386 _ ->
387 ok
c105945 @klacke Redid the code which decides where the ctldir resides, now it always …
authored
388 end.
d659ba3 @klacke added a 'yaws -ls' command that lists all yaws servers on localhost
authored
389
0be3c7e @klacke untabified all of yaws
authored
390
6dc4cca @klacke ""
authored
391
38fb85e @klacke ""
authored
392 %% send a hup (kindof) to the yaws server to make it
393 %% reload its configuration and clear its caches
394
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
395 hup([SID]) ->
396 actl(SID, hup).
38fb85e @klacke ""
authored
397
3dc56a7 @klacke javascript support in ehtml
authored
398
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
399 %% stop a daemon
0be3c7e @klacke untabified all of yaws
authored
400 stop([SID]) ->
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
401 actl(SID, stop).
38fb85e @klacke ""
authored
402
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
403 %% query a daemon for status/stats
404 status([SID]) ->
405 actl(SID, status).
406
407 load(X) ->
408 [SID | Modules] = lists:reverse(X),
409 actl(SID, {load, Modules}).
caa1a72 @carsten3347 Added command `-load' to yaws script.
carsten3347 authored
410
6c84378 @klacke ""
authored
411 check([Id, File| IncludeDirs]) ->
92bafb4 @klacke removed the ability change userid, also stopped writing to /tmp/yaws …
authored
412 GC = yaws_config:make_default_gconf(false, undefined),
2f51c68 @klacke -check arg
authored
413 GC2 = GC#gconf{include_dir = lists:map(fun(X) -> atom_to_list(X) end,
0be3c7e @klacke untabified all of yaws
authored
414 IncludeDirs),
415 id = atom_to_list(Id)
416 },
745bb4a @klacke ""
authored
417 yaws_server:setup_dirs(GC2),
9ce9a25 @klacke ""
authored
418 put(sc, #sconf{}),
419 put(gc, GC2),
a7e93df @klacke patch from Magnus froberg to get better control over the files genera…
authored
420 put(use_yfile_name, true),
ef3a52a @klacke Removed the atoms in parse_post and parse query, backwards incompatib…
authored
421 case yaws_compile:compile_file(atom_to_list(File)) of
0be3c7e @klacke untabified all of yaws
authored
422 {ok, [{errors, 0}| _Spec]} ->
423 timer:sleep(100),erlang:halt(0);
424 % init:stop();
425 _Other ->
426 timer:sleep(100),erlang:halt(1)
427 % init:stop()
2f51c68 @klacke -check arg
authored
428 end.
429
dc00e52 @klacke postvar bug by hal snyder, added yaws_api:query_url/1 added the id su…
authored
430 %% control a daemon http/traffic tracer
431 trace([What, SID]) ->
432 actl(SID, {trace, What}).
433
38fb85e @klacke ""
authored
434
435
436
0be3c7e @klacke untabified all of yaws
authored
437
438
439
440
38fb85e @klacke ""
authored
441
Something went wrong with that request. Please try again.