16
16
* along with this program; if not, write to the Free Software
17
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* $Id: spm.in,v 1.7 2005/03/26 15:14:11 mbaehr Exp $
19
* $Id: spm.in,v 1.13 2006/10/09 21:59:49 exodusd Exp $
22
constant cvs_version="$Id: spm.in,v 1.7 2005/03/26 15:14:11 mbaehr Exp $";
22
constant cvs_version="$Id: spm.in,v 1.13 2006/10/09 21:59:49 exodusd Exp $";
24
24
//! steam package manager main script
25
25
//! Installs packages into the main server
26
26
//! Uploads files by coal and runs pike scripts for preinst and postinst
27
27
inherit "../config";
29
#include "../server/include/classes.h"
30
#include "../server/include/attributes.h"
29
32
string tmp_dir = "/tmp";
31
37
static object oInstall;
39
static int debug_output = 0;
33
42
object find_object(int id)
35
44
if ( objectp(oInstall) )
40
void list_packages(mapping options)
49
void list_packages( void|string name )
51
if ( stringp(name) && sizeof(name) < 1 ) name = UNDEFINED;
42
52
object conn = ((program)"connection.pike")();
44
conn->start("www.open-steam.org", 1900, "guest", "guest");
45
conn->list_packages();
53
conn->set_debug( debug_output );
55
conn->start( "steam.open-steam.org", 1900, "guest", "guest" );
57
object _filepath = conn->send_cmd( 0, "get_module", "filepath:tree" );
58
object _packages = conn->send_cmd( _filepath, "path_to_object",
59
"/home/admin/packages" );
60
array package_objs = conn->send_cmd( _packages, "get_inventory" );
61
mapping packages = ([ ]);
62
foreach ( package_objs, object pck ) {
63
string desc = conn->send_cmd( pck, "query_attribute", OBJ_DESC );
64
if ( !stringp(desc) ) desc = "";
65
packages[pck->get_identifier()] = desc;
68
werror("List of packages " + (stringp(name) ? "containing '"+name+"' " : "") + "on sTeam server:\n");
69
foreach( sort(indices(packages)), string package ) {
70
if ( stringp(name) && (search(package, name) < 0) ) continue;
71
werror(" " + package + " : \t" + (string)packages[package] + "\n");
48
75
int get_package(string pck_name, string filename)
50
77
object conn = ((program)"connection.pike")();
78
conn->set_debug( debug_output );
52
conn->start("www.open-steam.org", 1900, "guest", "guest");
80
conn->start("steam.open-steam.org", 1900, "guest", "guest");
53
81
string content = conn->get_package(pck_name);
54
82
if ( !stringp(content) )
100
//! Generate a random valid filename for a new file
101
//! Returns the string of a valid filename in the given directory and with the
102
//! given prefix and suffix. The filename will thus be dir+prefix+random+suffix.
103
//! At the time of calling, no file with this name existed.
104
string make_tmp_filename ( string dir, string prefix, string suffix ) {
128
/** Generate a random valid name for a new directory
129
* Returns the string of a valid directory name in the given directory and
130
* with the given prefix and suffix. The name will thus be
131
* dir+prefix+random+suffix.
132
* At the time of calling, no file with this name existed. The directory
133
* will be created and the path returned.
135
string make_tmp_dirname ( string dir, string prefix, string suffix ) {
136
if ( stringp(tmp_dir_name) && sizeof(tmp_dir_name)>0 )
105
138
string full_prefix = dir;
106
139
if ( ! has_suffix( full_prefix, "/" ) ) full_prefix += "/";
107
140
full_prefix += prefix;
108
string random_fname = "";
141
string random_name = "";
109
142
Stdio.File tmp_file;
112
random_fname = full_prefix + replace(MIME.encode_base64(random_string(20),1) + suffix,"/","X");
113
} while ( Stdio.exist(random_fname) );
145
random_name = full_prefix + replace(MIME.encode_base64(random_string(20),1) + suffix,"/","X");
146
} while ( Stdio.exist(random_name) );
147
if ( !Stdio.mkdirhier( random_name ) ) {
148
werror( "Could not create tmp directory: %s\n", random_name );
151
tmp_dir_name = random_name;
156
static void cleanup ()
158
// delete the temporary dir:
159
if ( stringp(tmp_dir_name) && sizeof(tmp_dir_name)>0 ) {
160
if ( Stdio.exist(tmp_dir_name) ) {
161
write( "Deleting temporary directory ...\n", tmp_dir_name );
162
if ( !Stdio.recursive_rm( tmp_dir_name ) )
163
werror( "Could not delete temporary directory: %s\n", tmp_dir_name );
166
//if ( search(pck_name,tmp_dir) == 0 )
167
// Filesystem.System()->rm( pck_name );
170
int check_spm(string pname, object spmModule, object connection, void|int force)
172
object tfs = Filesystem.Tar(pname);
173
if ( !objectp(tfs) ) {
174
werror(pname + " not a valid SPM !\n");
177
mixed xml = tfs->open("package.xml", "r");
178
string packageXML = xml->read();
180
mapping config =spmModule->spm_check_configuration(packageXML);
181
mapping pmod = connection->send_cmd(0, "get_module", config->name);
182
if ( !objectp(pmod) )
183
pmod = connection->send_cmd(0, "get_module", "package:"+config->name);
184
if ( objectp(pmod) ) {
185
if ( spmModule->spm_version_value(config->version) <= spmModule->spm_version_value(pmod->get_version()) ) {
187
write("Found installed module with version %O, forcing installation anyway.\n", pmod->get_version());
190
werror("Found installed module with version %O, skipping installation !\n", pmod->get_version());
195
werror("Found installed module - updating to %O (previous version %O)\n",
196
config->version, pmod->get_version());
134
219
write("SPM: sTeam package manager.\n"+
135
220
"This utility connects to a running local sTeam server and\n"+
136
221
"installs new packages. Usage is spm <options>:\n"+
137
" -i --install <package-name>: Installs a new package.\n"+
222
" -i --install <package-name>: Installs ar updates a package.\n"+
138
223
" The package is either retrieved from the main sTeam server\n"+
139
224
" or located on the local disk (package-name can be a path name).\n"+
140
" -l --list: Lists all packages available for installation on the\n"+
141
" main sTeam server (www.open-steam.org).\n"+
142
" -d --dest: Install the package to the destination directory.\n"+
143
" -c --configure: Just configure a package (if already installed).\n");
225
" -o --old-install <package-name>: Installs or updates a package\n"+
226
" using the old installation mechanism. This is deprecated and\n"+
227
" you should only use this method when instructed to.\n"+
228
" -f --force : Forces installation of a package, even if the\n"+
229
" package is already installed with that version.\n"+
230
" -l --list [name] : Lists all packages available for installation\n"+
231
" on the main sTeam server (www.open-steam.org). If an argument\n"+
232
" is given, only packages which contain that text are listed.\n"+
233
" -d --dest <directory> : Install the package to the destination"+
235
" -s --server <hostname> : Install on a given server.\n"+
236
" -p --port <port> : use another port for installation\n"+
237
" (default is 1900).\n"+
238
" -c --configure <package-name> : Just configure a package\n"+
239
" (if already installed).\n");
147
mapping values = ([ "i":"install",
153
mapping options = handle_options(argv[1..], values);
245
// get all command line options:
246
array tmp_options = Getopt.find_all_options( argv, ({
247
({ "install", Getopt.HAS_ARG, ({ "-i", "--install" }) }),
248
({ "old-install", Getopt.HAS_ARG, ({ "-o", "--old-install" }) }),
249
({ "list", Getopt.MAY_HAVE_ARG, ({ "-l", "--list" }), ({ }), "" }),
250
({ "dest", Getopt.HAS_ARG, ({ "-d", "--dest" }) }),
251
({ "configure", Getopt.HAS_ARG, ({ "-c", "--configure" }) }),
252
({ "server", Getopt.HAS_ARG, ({ "-s", "--server" }) }),
253
({ "port", Getopt.HAS_ARG, ({ "-p", "--port" }) }),
254
({ "debug", Getopt.NO_ARG, ({ "--debug" }) }),
255
({ "force", Getopt.NO_ARG, ({ "-f", "--force" }) }),
257
// make a mapping out of the options:
258
mapping options = ([ ]);
259
foreach ( tmp_options, array option ) options[ option[0] ] = option[1];
260
if ( options["debug"] ) debug_output = 1;
261
if ( options["force"] ) force = 1;
155
263
master()->add_include_path(server_path+"/server/include");
156
264
master()->add_program_path(server_path+"/server/");
158
266
master()->add_module_path(server_path+"/server/libraries");
159
267
master()->add_program_path(server_path+"/server/net/coal");
160
268
add_constant("find_object", find_object);
161
read_configs(config_path+"/steam.cnf");
269
read_configs(config_path+"/steam.cfg");
163
271
if ( options["list"] ) {
164
list_packages(options);
272
list_packages( options["list"] );
168
werror("OPTIONS\n"+sprintf("%O\n", options));
169
if ( sizeof(options->options) < 1 ) {
170
werror("Missing filename or URL for installation...\n");
276
pck_name = options["install"];
277
if ( !stringp(pck_name) ) pck_name = options["old-install"];
278
if ( !stringp(pck_name) ) pck_name = options["configure"];
280
if ( !stringp(pck_name) ) {
281
werror("Missing filename or URL for installation / configuration...\n");
175
string url, pck_name;
176
pck_name = options->options[0];
284
string spm_filename = basename( pck_name );
285
sscanf( spm_filename, "%s.gz", spm_filename );
177
288
mkdir(dirname(tmp_dir));
179
290
if ( sscanf(pck_name, "http://%s", url) > 0 ) {
182
293
mapping headers = ([ ]);
183
294
string user, pass;
184
295
if ( sscanf(url, "%s:%s@%s", user, pass, url) == 3 ) {
185
werror("User: "+ user + "\n");
296
write("User: "+ user + "\n");
186
297
headers = ([ "authorization": "Basic " +
187
298
MIME.encode_base64(user+":"+pass), ]);
189
werror("Connecting to http://" + url+"\n");
300
write("Connecting to http://" + url+"\n");
190
301
object query = Protocols.HTTP.get_url("http://"+url, ([ ]), headers);
191
302
mapping d = query->cast("mapping");
192
werror("RESULT=\n"+sprintf("%O\n",indices(d)));
303
//werror("RESULT=\n"+sprintf("%O\n",indices(d)));
193
304
string data = d->data;
195
306
sscanf(url, "%*s/%s", fname);
196
werror("Transfered " + strlen(data) + " bytes...\n");
197
pck_name = make_tmp_filename(tmp_dir,"spm_",basename(fname));
307
write("Transfered " + strlen(data) + " bytes...\n");
308
tmp_dir_name = make_tmp_dirname(tmp_dir,"spm_","");
309
pck_name = tmp_dir_name + "/" + fname;
198
310
object f = Stdio.File(pck_name, "wct",0600);
202
werror("Package received...\n");
314
write("Package received...\n");
205
317
if ( !Stdio.exist(pck_name) ) {
206
werror("Getting file from package server...\n");
207
string tmp_filename = make_tmp_filename(tmp_dir,"spm_",basename(pck_name));
318
write("Getting file from package server...\n");
319
tmp_dir_name = make_tmp_dirname(tmp_dir,"spm_","");
320
string tmp_filename = tmp_dir_name + "/" + pck_name;
208
321
if ( !get_package(pck_name, tmp_filename) ) {
209
322
werror("Package not found on server ... Try -l to list packages.\n");
214
327
master()->add_program_path("../spm");
216
if ( sscanf(pck_name, "%s.gz", pck_name) >= 0 ) {
217
werror("Unzipping...\n");
218
string destname = pck_name;
219
if ( search(destname,tmp_dir) != 0 )
220
destname = make_tmp_filename(tmp_dir,"spm_",basename(destname));
221
object f = Stdio.File(destname, "wct");
222
int ret = Process.create_process(
223
({ "gunzip", "-c", "-f", pck_name+".gz" }), ([ "stdout" : f ]))->wait();
225
if ( search(pck_name,tmp_dir) == 0 )
226
Filesystem.System()->rm( pck_name+".gz" );
329
if ( sscanf(pck_name, "%s.gz", pck_name) >= 1 ) {
330
write("Unzipping...\n");
331
string destname = pck_name;
332
if ( search(destname,tmp_dir) != 0 ) {
333
tmp_dir_name = make_tmp_dirname(tmp_dir,"spm_","");
334
destname = tmp_dir_name + "/" + destname;
336
object f = Stdio.File(destname, "wct");
337
int ret = Process.create_process( ({ "gunzip", "-c", "-f",
338
pck_name+".gz" }), ([ "stdout" : f ]))->wait();
340
if ( search(pck_name,tmp_dir) == 0 )
341
Filesystem.System()->rm( pck_name+".gz" );
230
werror("Opening Tar Filesystem...");
345
write("Opening spm archive ...");
231
346
object fsystem = Filesystem.Tar(pck_name);
234
object conn = ((program)"connection.pike")();
235
string server = "localhost";
236
int port = (int)vars->port;
238
if ( options->server )
239
server = options->server;
241
port = (int)options->port;
349
// check for package.xml
350
if ( !objectp(fsystem) ) {
351
werror("Not a valid spm package (not a tar archive): %s\n", spm_filename);
354
if ( options["install"] && search( fsystem->get_dir(), "/package.xml" )<0 ) {
355
werror("The package %s is deprecated (it doesn't contain a /package.xml"
356
+" file).\nYou need to install it with the -o or --old-install "
357
+"command instead:\n spm -o %s\n", spm_filename, spm_filename);
360
if ( options["old-install"]
361
&& search( fsystem->get_dir(), "/package.xml" ) >= 0 ) {
362
werror("The package %s is not deprecated (it contains a /package.xml"
363
+" file).\nYou need to install it with the -i or --install "
364
+"command instead:\n spm -i %s\n", spm_filename, spm_filename);
369
string server = options["server"];
370
int port = (int)(vars["port"]);
371
if ( stringp(server) ) port = 1900;
372
else if ( stringp(vars["ip"]) && sizeof(vars["ip"]) )
375
server = "localhost";
376
if ( stringp(options["port"]) )
377
sscanf( options["port"], "%d", port );
242
379
write("Connecting sTeam on "+server+":"+port+"\n");
244
string pw = read_input("Root Password for server", "steam");
380
object conn = ((program)"connection.pike")();
381
conn->set_debug( debug_output );
382
string pw = read_password("Root Password for server", "steam");
247
385
if ( sscanf(pck_name, "%s.spm", pname) != 1 ) {
258
396
conn->set_fsystem(fsystem, vars);
259
397
conn->start(server, port, "root", pw);
260
398
if ( options->configure ) {
399
//TODO: this is hardcoded to configure only the web package!?
261
400
conn->configure_web();
262
werror("CONFIGURATION of package completed !");
401
werror("Configuration of package completed !");
405
// connect to the server and register the new package module
406
if ( options["old-install"] ) {
407
conn->upload_package(vars);
408
werror("\nInstallation successfull ("+conn->iInstall + " new Files, "+
409
conn->iUpdate + " updated).\n\n");
411
} else if ( options["install"] ) {
412
object package_file = Stdio.File( pck_name, "r" );
413
object _filepath = conn->send_cmd( 0, "get_module", "filepath:tree" );
414
if ( !objectp(_filepath) ) {
415
werror( "Unable to find filepath module on server!\n" );
418
object _spm = conn->send_cmd( 0, "get_module", "SPM" );
419
if ( !objectp(_spm) ) {
420
werror( "Unable to find spm module on server!\n" );
423
object dir = conn->send_cmd( _filepath, "path_to_object", "/packages" );
424
object root_dir = conn->send_cmd( _filepath, "path_to_object", "/" );
425
if ( !objectp(dir) || !objectp(root_dir) ) {
426
werror( "Unable to find package or root directory on server!" );
429
if ( !check_spm(pck_name, _spm, conn, force) )
431
object new_obj = conn->send_cmd( dir, "get_object_byname", spm_filename );
432
if ( !objectp(new_obj) ) {
433
object _docfactory = conn->send_cmd( 0, "get_factory", CLASS_DOCUMENT );
434
if ( !objectp(_docfactory) ) {
435
werror( "Unable to find document factory on server!\n" );
438
new_obj = conn->send_cmd( _docfactory, "execute", ([ "name": spm_filename, ]) );
439
if ( !objectp(new_obj) ) {
440
werror( "Could not create temporary package file on server!\n" );
443
conn->send_cmd( new_obj, "move", dir );
445
conn->send_cmd( new_obj, "set_content", package_file->read() );
446
package_file->close();
447
write( "Uploaded package %s ...\n", spm_filename );
449
conn->send_cmd( _spm, "install_spm", ({ new_obj, root_dir }) );
450
write( "Installed package %s ...\n", spm_filename );
451
// delete temporary package on server
452
conn->send_cmd( new_obj, "delete" );
453
write( "Deleted temporary package file on server\n" );
266
* connect to the server and register the new package module
268
conn->upload_package(vars);
269
werror("\nINSTALLATION Successfull, "+conn->iInstall + " new Files, "+
270
conn->iUpdate + " updated.\n\n");
272
// delete the temporary file:
273
if ( search(pck_name,tmp_dir) == 0 )
274
Filesystem.System()->rm( pck_name );