corner
Home

· About erlang.org
· Downloads
· Links
· FAQs + mailing lists
· Enhancements
· Getting started
· Documentation
· Examples
· Mirrors

Erlang Books









For comments or questions about this site, contact webmaster@erlang.org
     

Controlling Windows Vista from Linux

This is a simple "getting started guide" to show you how to control a Windows XP/Vista machine from Linux (or vice versa).

    Most of what follows is true for any platform to which Erlang has been ported - Linux and Windows XP/Vista are used in the examples because these operating systems are familiar to most people.

Below follows a program which manipulates the Windows Registry from Linux. This is an example of a program that could make a system administrators life a lot easier. In principle a single Linux machine could be used to remotely administer a large network of Windows machines.

Before you can do any of this you will have to install Erlang on both Windows and Linux.

To do this fetch the Linux and Windows versions of Erlang from www.erlang.org and follow the installation instructions.

Starting two Erlang nodes on the same LAN

This example shows how to start two machines (a Linux machine and a Windows XP/Vista machine) on the same LAN.

On the Linux machine start the system with the command:


erl -sname m1

You will see something like the following:


Erlang R13B (erts-5.7.1) [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]

Eshell V5.7.1  (abort with ^G)
(m1@mylinuxhost)1>

Here the prompt shows the Erlang node identifier m1 and the host name mylinuxhost (the combination m1@mylinuxhost we call the node name)

On the Windows machine give the command:


C:\Program Files\erl5.7.1\bin\werl -sname x

Assuming that you have installed Erlang in the directory "C:\Program Files\erl5.7.1" where erl5.7.1 is dependent on the version of Erlang you installed.

On the Windows machine a new window pops up containing:


Erlang R13B (erts-5.7.1) [smp:2:2] [rq:2] [async-threads:0]

Eshell V5.7.1  (abort with ^G)
(x@mywindowshost)1>

If you got this far then you now have two Erlang nodes on the same LAN but they will not necessarily be able to talk to each other.

Before the two nodes can talk to each other they have to be authenticated, Follow the instructions in the next section to set up the authentication system.

Once authenticated the nodes can "ping" each other, this can be used as a final test that everything works. To do this, start two nodes as described above make sure they have the same cookies and then try the command net_adm:ping/1 as follows:


(m1@mylinuxhost)> net_adm:ping(x@mywindowshost).
pong

It worked!

Authentication

Distributed Erlang authentication is based on the idea of shared secrets and challenge response algorithms. The shared secrets are called cookies. In order for two Erlang nodes to talk to each other they have to agree on the value of a cookie. The commands erlang:set_cookie/2 and erlang:get_cookie/0 can be used to set and read the the value of a cookie. For example:


1> erlang:set_cookie(node(), abcdef123XYZ).
true
2> erlang:get_cookie().
abcdef123XYZ

If two distributed node cannot ping each other (with the command net_adm:ping(NodeName)), then the first thing to do is to use the get_cookie command to see if both nodes have the same cookie.

The cookie can be permanently set up by editing the file HOME/.erlang.cookie where the value of HOME can be found out by evaluating init:get_argument(home)

Problems with distribution

A lot of things can go wrong when setting up distributed Erlang. Most often these are due to errors in the way DNS etc. have been set up. If you have problems in setting up distributed Erlang read the on-line documentation section "Getting Started" for help.

Manipulating the win32 registry from linux

The module win32reg can be used to manipulate the windows registry.

The program print_registry.erl is used to remotely access the windows registry. Read the comments in the code to see how this works. See also the output obtained when running this program:

Exercise: Extend the program so you can read and write files on the Windows machine that were sent from the Linux machine.


hint ...

{ok, Bin} = file:read_file(File),
rpc:call(WinMachine, file, write_file, [Bin])


Implement a complete remote management system for Windows machines, that is, a system that will allow an administrator to remotely add/remove files and tweak entries in the windows registry. Add security and authentication to your program. [Hint you'll find everything you need MD5 etc. in the Erlang distribution].

print_registry.erl

-module(print_registry).

%% to run this program
%%  > c(print_registry).
%%  > print_registry:install_code().
%%  > print_registry:run().

%%#doc maintainers(["joe@cslab.ericsson.se (Joe Armstrong)"]).
%%#doc title("Print the registry on a Window95/NT machine").
%%#doc keywords(["windows","registry"]).

-export([install_code/0, run/0, internal/0]).

-import(lists, [foreach/2, map/2]).
-import(win32reg, [open/1, current_key/1, sub_keys/1, close/1, 
		   change_key/2, values/1]).

%% install code installs this program on my
%% Windows-NT machine

install_code() -> install_code(?MODULE).

install_code(Mod) ->
    {ok, Bin} = file:read_file(atom_to_list(Mod) ++ ".jam"),
    rpc:call(x@yuck, code, load_binary,  [Mod, "print_registry.jam", Bin]).

%% run() runs print_registry:go() on the remote machine

run() -> rpc:call(x@yuck, print_registry, internal, []).

keys() ->
    ["\\hkey_classes_root", "\\hkey_current_user",
     "\\hkey_local_machine","\\hkey_users","\\hkey_performance_data",
     "\\hkey_current_config","\\hkey_dyn_data"].

internal() ->
    {ok, Reg} = open([read]),
    map(fun(I) ->
	       P = current_key(Reg),
	       case change_key(Reg, I) of
		   ok ->
		       case sub_keys(Reg) of
			   {ok, L1} ->
			       io:format("Key(~s) has ~p subkeys~n",
					 [I, length(L1)]);
			   Other ->
			       io:format("Oops ~p~n",[Other])
		       end;
		   {error, _} ->
		       io:format("No key ~p on this machine ~n",[I])
	       end
       end, keys()),
    Key = "\\hkey_current_user\\software",
    list_keys(0, Reg, Key),
    close(Reg).

list_keys(Tab, Reg, Key) ->
    tab(Tab),
    io:format("~p", [Key]),
    change_key(Reg, Key),
    case sub_keys(Reg) of
	{ok, Vals} ->
	    %% Remove the Microsoft key from the registry
	    %% because this gives *lots* of output and this is supposed
	    %% to be a *small* example
	    Vals1 = lists:delete("Microsoft", Vals),
	    foreach(fun(K) ->
			   io:nl(),
			   list_keys(Tab+2, Reg, K),
			   case values(Reg) of
			       {ok, []} ->
				   io:nl();
			       {ok, KVs} ->
				   io:nl(),
				   foreach(fun({KK,VV}) ->
						  tab(Tab+4),
						  io:format("~p = ~p~n",
							    [KK, VV])
					  end, KVs);
			       _ ->
				   true
			   end,
			   change_key(Reg, "..")
		   end, Vals1);
	{error, _} ->
	    true
    end.

tab(N) ->
    io:format("~s", [lists:duplicate(N, $ )]).


Appendix 1

The output obtained by running print_registry:


Erlang R13B (erts-5.7.1) [smp:4:4] [rq:4] [async-threads:0] [kernel-poll:false]

Eshell V5.7.1  (abort with ^G)
(m1@mylinuxhost)1> erlang:set_cookie(node(),fooy123).
true
(m1@mylinuxhost)2> c(print_registry).
{ok,print_registry}
(m1@mylinuxhost)3> print_registry:install_code().
{module,print_registry}
(m1@mylinuxhost)4> print_registry:run().         
No key "\\hkey_dyn_data" on this machine 
Key(\hkey_current_config) has 2 subkeys
No key "\\hkey_performance_data" on this machine 
Key(\hkey_users) has 2 subkeys
Key(\hkey_local_machine) has 5 subkeys
Key(\hkey_current_user) has 10 subkeys
Key(\hkey_classes_root) has 472 subkeys
"\\hkey_current_user\\software"
  "Cygnus Solutions"
    "CYGWIN.DLL setup"
      "b15.0"
        "mounts"
          "00"
            "native" = "\\\\.\\tape1:"
            "unix" = "/dev/st1"
            "fbinary" = 0
            "fsilent" = 1
 
     ... some lines omitted ...

  "Ericsson"
    "Erlang"
      "4.7.3"
        "Font" = #Bin
        "FgColor" = 0
        "BkColor" = 16777215

 
Last updated   2010-11-29 13:15 UTC