Implemented force install
[spkg.git] / src / main.c
blobfe8db38d536abc261bcc7314cb2ec4c9e9738531
1 /*----------------------------------------------------------------------*\
2 |* spkg - The Unofficial Slackware Linux Package Manager *|
3 |* designed by Ondøej Jirman, 2005 *|
4 |*----------------------------------------------------------------------*|
5 |* No copy/usage restrictions are imposed on anybody. *|
6 \*----------------------------------------------------------------------*/
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
12 #include <popt.h>
14 #include "config.h"
16 #include "commands.h"
17 #include "pkgdb.h"
18 #include "sigtrap.h"
19 #include "message.h"
20 #include "misc.h"
22 /* commands
23 ************************************************************************/
25 static guint command = 0;
26 #define CMD_INSTALL (1<<0)
27 #define CMD_UPGRADE (1<<1)
28 #define CMD_REMOVE (1<<2)
29 #define CMD_LIST (1<<3)
31 static struct poptOption optsCommands[] = {
33 "install", 'i', POPT_ARG_NONE|POPT_BIT_SET, &command, CMD_INSTALL,
34 "Install packages.", NULL
37 "upgrade", 'u', POPT_ARG_NONE|POPT_BIT_SET, &command, CMD_UPGRADE,
38 "Upgrade packages", NULL
41 "remove", 'd', POPT_ARG_NONE|POPT_BIT_SET, &command, CMD_REMOVE,
42 "Remove packages.", NULL
45 "list", 'l', POPT_ARG_NONE|POPT_BIT_SET, &command, CMD_LIST,
46 "List all packages. You can add package names to the command line "
47 "to limit listed packages. This command supports glob matching.", NULL
49 POPT_TABLEEND
52 /* options
53 ************************************************************************/
55 static gchar* default_bl_symopts[] = {
56 "aaa_base", "bin", "glibc-solibs", "glibc", NULL
59 static gchar* default_bl_upgrade[] = {
60 "aaa_base", "aaa_elflibs", NULL
63 static struct cmd_options cmd_opts = {
64 .root = "/",
65 .dryrun = 0,
66 .verbosity = 2,
67 .safe = 0,
68 .no_optsyms = 0,
69 .no_scripts = 0,
70 .no_ldconfig = 0,
71 .reinstall = 0,
72 .bl_symopts = default_bl_symopts,
73 .bl_upgrade = default_bl_upgrade
76 static gint verbose = 0;
77 static gint quiet = 0;
78 static gint install_new = 0;
80 static struct poptOption optsOptions[] = {
82 "root", 0, POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &cmd_opts.root, 0,
83 "Set alternate root directory for package operations. You can also use "
84 "ROOT environment variable.", "ROOT"
87 "safe", 's', 0, &cmd_opts.safe, 0,
88 "Play it safe. Don't replace existing files during --install or --upgrade. "
89 "Don't run post-installation scripts. Don't remove changed files on "
90 "--remove.", NULL
93 "force", 'f', 0, &cmd_opts.force, 0,
94 "Force installation even if package is already installed.",
95 NULL
98 "dry-run", 'n', 0, &cmd_opts.dryrun, 0,
99 "Don't modify filesystem or database. This may be useful when used along "
100 "with -v option to check what exactly would given command do.", NULL
103 "verbose", 'v', 0, 0, 1,
104 "Increase verbosity level. When used once, files and directories "
105 "that are affected by particular operation will be shown. When used "
106 "twice, everything that is done will be reported.", NULL
109 "quiet", 'q', 0, 0, 2,
110 "Decrease verbosity level. Default is to show info messages and warnings. "
111 "This option disables warnings when used once. When used twice it will "
112 "completely disable output except for error messages.", NULL
115 "reinstall", 0, 0, &cmd_opts.reinstall, 0,
116 "When upgrading package and package already exists in the database, "
117 "force reinstall.", NULL
120 "install-new", 0, 0, &install_new, 0,
121 "When upgrading package that does not yet exist in the database, "
122 "install it instead.", NULL
125 "no-fast-symlinks", 0, 0, &cmd_opts.no_optsyms, 0,
126 "Spkg by default parses doinst.sh for symlink creation code and removes "
127 "it from the script. This improves execution times of doinst.sh. Use "
128 "this option to disable such optimizations.", NULL
131 "no-scripts", 0, 0, &cmd_opts.no_scripts, 0,
132 "Disable postinstallation script.", NULL
135 "no-ldconfig", 0, 0, &cmd_opts.no_ldconfig, 0,
136 "Don't execute ldconfig after installation and upgrade.", NULL
138 POPT_TABLEEND
141 /* help
142 ************************************************************************/
144 static gint help = 0;
145 static gint usage = 0;
146 static gint version = 0;
148 static struct poptOption optsHelp[] = {
150 "usage", '\0', POPT_ARG_NONE, &usage, 0,
151 "Display brief usage message.", NULL
154 "help", 'h', POPT_ARG_NONE, &help, 0,
155 "Show this help message.", NULL
158 "version", 'V', POPT_ARG_NONE, &version, 0,
159 "Display spkg version.", NULL
161 POPT_TABLEEND
164 /* main table
165 ************************************************************************/
167 static struct poptOption opts[] = {
168 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, &optsCommands, 0, "Commands:", NULL },
169 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, &optsOptions, 0, "Options:", NULL },
170 { NULL, '\0', POPT_ARG_INCLUDE_TABLE, &optsHelp, 0, "Help options:", NULL },
171 POPT_TABLEEND
174 /* main
175 ************************************************************************/
177 gboolean is_root()
179 #ifndef __WIN32__
180 return getuid() == 0;
181 #else
182 return 1;
183 #endif
186 int main(const int ac, const char* av[])
188 poptContext optCon=0;
189 gint rc;
190 gint status = 0;
191 const gchar* arg;
192 struct error* err;
194 #ifdef __DEBUG
195 g_mem_set_vtable(glib_mem_profiler_table);
196 #endif
198 err = e_new();
199 /* check if we have enough privileges */
200 #ifndef __WIN32__
201 unsetenv("LD_LIBRARY_PATH");
202 #else
203 putenv("LD_LIBRARY_PATH");
204 putenv("LD_LIBRARY_PATH=");
205 #endif
207 /* load blacklists from SPKG_CONFDIR */
208 gchar** bl_symopts = load_blacklist(SPKG_CONFDIR "/symopts_blacklist");
209 if (bl_symopts)
210 cmd_opts.bl_symopts = bl_symopts;
212 gchar** bl_upgrade = load_blacklist(SPKG_CONFDIR "/upgrade_blacklist");
213 if (bl_upgrade)
214 cmd_opts.bl_upgrade = bl_upgrade;
216 /* preset ROOT */
217 cmd_opts.root = getenv("ROOT");
219 /* initialize popt context */
220 optCon = poptGetContext("spkg", ac, av, opts, 0);
221 poptSetOtherOptionHelp(optCon, "<command> [options] [packages...]");
223 /* parse options */
224 while ((rc = poptGetNextOpt(optCon)) != -1)
226 if (rc == 1)
227 verbose++;
228 else if (rc == 2)
229 quiet++;
230 if (rc < -1)
232 fprintf(stderr, "ERROR: Invalid argument: %s (%s)\n",
233 poptStrerror(rc),
234 poptBadOption(optCon, POPT_BADOPTION_NOALIAS));
235 goto err_1;
239 /* these are help handlers */
240 if (help)
242 printf(
243 PACKAGE_STRING "\n"
244 "\n"
245 "Written by Ondrej Jirman, 2005-2006.\n"
246 "\n"
247 "This is free software. Not like a beer or like in a \"freedom\",\n"
248 "but like in \"I don't care what you are going to do with it.\"\n"
249 "\n"
251 poptPrintHelp(optCon, stdout, 0);
252 printf(
253 "\n"
254 "Examples:\n"
255 " spkg -i <packages> [--install]\n"
256 " spkg -u <packages> [--upgrade]\n"
257 " spkg -vd <packages> [--verbose --remove]\n"
258 " spkg -l kde* [--list]\n"
259 " spkg -vnu <packages> [--upgrade --verbose --dry-run]\n"
260 "\n"
261 "Official website: http://spkg.megous.com\n"
262 "Bug reports can be sent to <megous@megous.com>.\n"
264 goto out;
266 if (usage)
268 printf("Usage: spkg [-i|-u|-d|-l] [--root=ROOT] [-n] [-s] [-q] [-v] [packages...]\n");
269 goto out;
271 if (version)
273 printf("%s\n", PACKAGE_STRING);
274 goto out;
277 /* check verbosity options */
278 if (verbose && quiet)
280 fprintf(stderr, "ERROR: Verbose or quiet?\n");
281 goto err_1;
283 cmd_opts.verbosity += verbose;
284 cmd_opts.verbosity -= quiet;
286 /* check command options */
287 switch (command)
289 case CMD_INSTALL:
290 if (!cmd_opts.dryrun && !is_root())
291 goto err_noroot;
292 if (poptPeekArg(optCon) == 0)
293 goto err_nopackages;
294 break;
295 case CMD_UPGRADE:
296 if (!cmd_opts.dryrun && !is_root())
297 goto err_noroot;
298 if (poptPeekArg(optCon) == 0)
299 goto err_nopackages;
300 break;
301 case CMD_REMOVE:
302 if (!cmd_opts.dryrun && !is_root())
303 goto err_noroot;
304 if (poptPeekArg(optCon) == 0)
305 goto err_nopackages;
306 break;
307 case CMD_LIST:
308 break;
309 case 0:
310 if (poptPeekArg(optCon) == 0)
312 printf("Usage: spkg [-i|-u|-d|-l] [--root=ROOT] [-n] [-s] [-q] [-v] [packages...]\n");
313 goto out;
315 if (!cmd_opts.dryrun && !is_root())
316 goto err_noroot;
317 command = CMD_UPGRADE;
318 install_new = TRUE;
319 break;
320 default:
321 fprintf(stderr, "ERROR: Schizofrenic command usage.\n");
322 goto err_1;
325 /* init signal trap */
326 if (sig_trap(err))
327 goto err_2;
329 /* open db */
330 gboolean readonly = cmd_opts.dryrun || !is_root();
331 if (db_open(cmd_opts.root, readonly, err))
332 goto err_2;
334 switch (command)
336 case CMD_INSTALL:
338 while ((arg = poptGetArg(optCon)) != 0 && !sig_break)
340 if (cmd_install(arg, &cmd_opts, err))
342 if (e_errno(err) & CMD_EXIST)
344 gchar* pkgname = parse_pkgname(arg, 5);
345 _inform("Skipping package %s (package with same base name is already installed)...", pkgname ? pkgname : arg);
346 g_free(pkgname);
347 e_clean(err);
349 else
351 e_print(err);
352 e_clean(err);
353 status = 2;
358 break;
359 case CMD_UPGRADE:
361 while ((arg = poptGetArg(optCon)) != 0 && !sig_break)
363 if (cmd_upgrade(arg, &cmd_opts, err))
365 if (install_new && (e_errno(err) & CMD_NOTEX))
367 e_clean(err);
368 if (cmd_install(arg, &cmd_opts, err))
370 e_print(err);
371 e_clean(err);
372 status = 2;
375 else if (e_errno(err) & CMD_NOTEX)
377 gchar* pkgname = parse_pkgname(arg, 5);
378 _inform("Skipping package %s (package with same base name is NOT installed)...", pkgname ? pkgname : arg);
379 g_free(pkgname);
380 e_clean(err);
382 else if (e_errno(err) & CMD_BLACK)
384 gchar* pkgname = parse_pkgname(arg, 5);
385 _inform("Skipping package %s (package is blacklisted)...", pkgname ? pkgname : arg);
386 g_free(pkgname);
387 e_clean(err);
389 else if (e_errno(err) & CMD_EXIST)
391 gchar* pkgname = parse_pkgname(arg, 5);
392 _inform("Skipping package %s (already uptodate)...", pkgname ? pkgname : arg);
393 g_free(pkgname);
394 e_clean(err);
396 else
398 e_print(err);
399 e_clean(err);
400 status = 2;
405 break;
406 case CMD_REMOVE:
408 while ((arg = poptGetArg(optCon)) != 0 && !sig_break)
410 if (cmd_remove(arg, &cmd_opts, err))
412 e_print(err);
413 e_clean(err);
414 status = 2;
418 break;
419 case CMD_LIST:
421 GSList* arglist = NULL;
422 while ((arg = poptGetArg(optCon)) != 0)
423 arglist = g_slist_append(arglist, g_strdup(arg));
424 if (cmd_list(arglist, &cmd_opts, err))
426 e_print(err);
427 e_clean(err);
428 status = 2;
430 g_slist_foreach(arglist, (GFunc)g_free, 0);
431 g_slist_free(arglist);
433 break;
436 db_close();
438 out:
439 poptFreeContext(optCon);
440 e_free(err);
442 #ifdef __DEBUG
443 g_mem_profile();
444 #endif
446 /* 0 = all ok
447 * 1 = command line error
448 * 2 = package manager error
450 return status;
451 err_1:
452 status = 1;
453 goto out;
454 err_2:
455 status = 2;
456 e_print(err);
457 goto out;
458 err_nopackages:
459 fprintf(stderr, "ERROR: No packages specified.\n");
460 goto err_1;
461 err_noroot:
462 fprintf(stderr, "ERROR: You need root privileges to run this command. Try using --dry-run.\n");
463 goto err_1;