r11176 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r11175‎ | r11176 | r11177 >
Date:08:53, 2 October 2005
Author:kateturner
Status:old
Tags:
Comment:
solaris apt-get type thing
Modified paths:
  • /trunk/tools/rosary (added) (history)
  • /trunk/tools/rosary/Makefile (added) (history)
  • /trunk/tools/rosary/README (added) (history)
  • /trunk/tools/rosary/rosary.c (added) (history)

Diff [purge]

Index: trunk/tools/rosary/rosary.c
@@ -0,0 +1,609 @@
 2+/*
 3+ * Rosary: SVr4/Solaris package manager.
 4+ */
 5+
 6+#include <sys/types.h>
 7+#include <sys/wait.h>
 8+
 9+#include <stdio.h>
 10+#include <string.h>
 11+#include <errno.h>
 12+#include <unistd.h>
 13+#include <stdlib.h>
 14+#include <dirent.h>
 15+#include <curses.h>
 16+#include <term.h>
 17+#include <fnmatch.h>
 18+#include <libtecla.h>
 19+
 20+#include <glib.h>
 21+
 22+#define CFGFILE "/etc/opt/rosary/rosary.conf"
 23+#define PKGFILE "/etc/opt/rosary/db.pkg"
 24+#define FILEFILE "/etc/opt/rosary/db.file"
 25+
 26+struct package;
 27+int initroot (void);
 28+int read_pkg_info (struct package *pkg, const char *dir);
 29+void pkgdb_write (gpointer, gpointer, gpointer);
 30+void pkgdb_writedep (gpointer, gpointer);
 31+void pkgsearch (gpointer, gpointer, gpointer);
 32+void print_pkghash (GHashTable *);
 33+void print_pkghash_one (gpointer, gpointer, gpointer);
 34+gboolean is_installable (gpointer, gpointer, gpointer);
 35+void print_package (struct package *);
 36+int is_installed (const char *pkg);
 37+int add_depends (struct package *pkg);
 38+void install_all (void);
 39+int install_one (struct package *pkg);
 40+int is_candidate (const char *);
 41+struct package *next_installable (void);
 42+int run_cmd (char **);
 43+int install_cmd (char **);
 44+int search_cmd (char **);
 45+int shell_cmd (char **);
 46+
 47+GHashTable *pkgs_byname;
 48+GHashTable *files_byname;
 49+GHashTable *inst_pkgs;
 50+
 51+GHashTable *to_install;
 52+GHashTable *toins_deps;
 53+char *pkgroot;
 54+
 55+struct package {
 56+ char *name;
 57+ char *desc;
 58+ GSList *depends;
 59+};
 60+
 61+char *progname;
 62+const char *commands =
 63+ "commands:\n"
 64+ " install <pkgs> install one or more packages\n"
 65+ " search <term> search package names and descriptions\n"
 66+ " shell enter interactive shell\n";
 67+const char *icommands =
 68+ " quit exit command shell\n";
 69+int
 70+main(ac, av)
 71+int ac;
 72+char *av[];
 73+{
 74+int c;
 75+int Iflag = 0;
 76+struct package *pkg;
 77+GIOChannel *f;
 78+GError *err = NULL;
 79+char *ln;
 80+DIR *dp;
 81+struct dirent *de;
 82+static const char *usage =
 83+ "usage: %s [-I -m <media location>] <command>\n"
 84+ " -m\tspecify location of Solaris DVD/CD media\n"
 85+ " -I\tinitialise configuration\n";
 86+
 87+ progname = av[0];
 88+
 89+ while ((c = getopt(ac, av, "Im:")) != -1) {
 90+ switch (c) {
 91+ case 'I':
 92+ Iflag++;
 93+ break;
 94+ case 'm':
 95+ pkgroot = optarg;
 96+ break;
 97+ default:
 98+ fprintf(stderr, usage, av[0]);
 99+ fprintf(stderr, "\n%s", commands);
 100+ exit(1);
 101+ }
 102+ }
 103+ ac -= optind;
 104+ av += optind;
 105+
 106+ if (Iflag) {
 107+ return initroot();
 108+ }
 109+
 110+ if (access(CFGFILE, F_OK) == 0) {
 111+ fprintf(stderr, "Loading configuration from %s: ", CFGFILE);
 112+ if ((f = g_io_channel_new_file(CFGFILE, "r", &err)) == NULL) {
 113+ fprintf(stderr, "%s\n", err->message);
 114+ return 1;
 115+ }
 116+ while (g_io_channel_read_line(f, &ln, NULL, NULL, &err) == G_IO_STATUS_NORMAL) {
 117+ char *v, *o = ln;
 118+ ln[strlen(ln) - 1] = '\0';
 119+ if ((v = strchr(o, '=')) == NULL) {
 120+ fprintf(stderr, "format error\n");
 121+ return 1;
 122+ }
 123+ *v++ = '\0';
 124+ if (!strcmp(o, "pkgroot"))
 125+ pkgroot = strdup(v);
 126+ g_free(ln);
 127+ }
 128+ g_io_channel_unref(f);
 129+ fprintf(stderr, "OK\n");
 130+ } else {
 131+ fprintf(stderr, "No configuration exists; use -I to create.\n");
 132+ return 0;
 133+ }
 134+
 135+ fprintf(stderr, "package root: %s\n", pkgroot);
 136+ pkgs_byname = g_hash_table_new(g_str_hash, g_str_equal);
 137+ fprintf(stderr, "Reading package database from %s: ", PKGFILE);
 138+ if ((f = g_io_channel_new_file(PKGFILE, "r", &err)) == NULL) {
 139+ fprintf(stderr, "%s\n", err->message);
 140+ return 1;
 141+ }
 142+ while (g_io_channel_read_line(f, &ln, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) {
 143+ char *v, *o = ln;
 144+ ln[strlen(ln) - 1] = '\0';
 145+ if ((v = strchr(o, ' ')) == NULL) {
 146+ fprintf(stderr, "format error\n");
 147+ return 1;
 148+ }
 149+ *v++ = '\0';
 150+ if (!strcmp(o, "p")) {
 151+ pkg = calloc(1, sizeof(struct package));
 152+ pkg->name = strdup(v);
 153+ g_hash_table_insert(pkgs_byname, strdup(v), pkg);
 154+ } else if (!strcmp(o, "desc")) {
 155+ if (!pkg) {
 156+ fprintf(stderr, "format error\n");
 157+ exit(1);
 158+ }
 159+ pkg->desc = strdup(v);
 160+ } else if (!strcmp(o, "dep")) {
 161+ if (!pkg) {
 162+ fprintf(stderr, "format error\n");
 163+ exit(1);
 164+ }
 165+ pkg->depends = g_slist_prepend(pkg->depends, strdup(v));
 166+ }
 167+ }
 168+ fprintf(stderr, "OK, %d packages\n", g_hash_table_size(pkgs_byname));
 169+ g_io_channel_unref(f);
 170+
 171+ fprintf(stderr, "Reading list of installed packages: ");
 172+ inst_pkgs = g_hash_table_new(g_str_hash, g_str_equal);
 173+ if ((dp = opendir("/var/sadm/pkg")) == NULL) {
 174+ perror("/var/sadm/pkg");
 175+ return 1;
 176+ }
 177+ while (de = readdir(dp)) {
 178+ struct package *ipkg;
 179+ ipkg = calloc(1, sizeof(struct package));
 180+ ipkg->name = strdup(de->d_name);
 181+ g_hash_table_insert(inst_pkgs, strdup(de->d_name), ipkg);
 182+ }
 183+ closedir(dp);
 184+ fprintf(stderr, "OK, %d packages\n", g_hash_table_size(inst_pkgs));
 185+
 186+ fprintf(stderr, "\n");
 187+ if (!*av) {
 188+ fprintf(stderr, usage, progname);
 189+ fprintf(stderr, "\n%s", commands);
 190+ return 1;
 191+ }
 192+
 193+ if (run_cmd(av) == -1)
 194+ return 1;
 195+ return 0;
 196+}
 197+
 198+int
 199+search_cmd(av)
 200+char **av;
 201+{
 202+char *term;
 203+ if (!*av) {
 204+ printf("search: not enough arguments\n");
 205+ return -1;
 206+ }
 207+ printf("Packages matching \"%s\":\n", av[0]);
 208+ term = g_strdup_printf("*%s*", av[0]);
 209+ g_hash_table_foreach(pkgs_byname, pkgsearch, term);
 210+ g_free(term);
 211+ fprintf(stderr, "a = available, i = installed\n");
 212+}
 213+
 214+int
 215+run_cmd(av)
 216+char **av;
 217+{
 218+static int slev;
 219+ if (!strcmp(av[0], "install"))
 220+ return install_cmd(av + 1);
 221+ if (!strcmp(av[0], "search"))
 222+ return search_cmd(av + 1);
 223+ if (!slev++ && !strcmp(av[0], "shell"))
 224+ return shell_cmd(av + 1);
 225+ if (!strcmp(av[0], "quit"))
 226+ exit(0);
 227+ if (!strcmp(av[0], "help")) {
 228+ fprintf(stderr, "%s", commands);
 229+ fprintf(stderr, "%s", icommands);
 230+ return 0;
 231+ }
 232+
 233+ fprintf(stderr, "Unknown command '%s'\n", av[0]);
 234+ return -1;
 235+}
 236+
 237+int
 238+shell_cmd(av)
 239+char **av;
 240+{
 241+GetLine *gl;
 242+ gl = new_GetLine(4096, 256);
 243+ for (;;) {
 244+ char *in;
 245+ char **args;
 246+ in = gl_get_line(gl, "rosary> ", "", 0);
 247+ if (!in)
 248+ return 0;
 249+ in[strlen(in) - 1] = '\0';
 250+ args = g_strsplit(in, " ", 0);
 251+ if (!args[0]) {
 252+ g_strfreev(args);
 253+ free(in);
 254+ continue;
 255+ }
 256+ run_cmd(args);
 257+ g_strfreev(args);
 258+ }
 259+ del_GetLine(gl);
 260+}
 261+
 262+int
 263+install_cmd(av)
 264+char **av;
 265+{
 266+int c;
 267+ to_install = g_hash_table_new(g_str_hash, g_str_equal);
 268+ toins_deps = g_hash_table_new(g_str_hash, g_str_equal);
 269+ while (*av) {
 270+ struct package *pkg;
 271+ GSList *dep;
 272+ if ((pkg = g_hash_table_lookup(pkgs_byname, *av)) == NULL) {
 273+ fprintf(stderr, "Nothing known about package '%s'\n", *av);
 274+ return 1;
 275+ }
 276+ if (is_installed(pkg->name)) {
 277+ fprintf(stderr, "%s is already installed\n", pkg->name);
 278+ av++;
 279+ continue;
 280+ }
 281+ g_hash_table_insert(to_install, strdup(*av), pkg);
 282+ if (add_depends(pkg) == -1) {
 283+ fprintf(stderr, "Cannot resolve dependencies.\n");
 284+ return 1;
 285+ }
 286+ av++;
 287+ }
 288+
 289+ if (g_hash_table_size(to_install) == 0) {
 290+ printf("Nothing to do.\n");
 291+ return 0;
 292+ }
 293+
 294+ printf("The following packages will be installed:\n");
 295+ print_pkghash(to_install);
 296+ if (g_hash_table_size(toins_deps)) {
 297+ printf("The following packages will be installed to satisfy dependencies:\n");
 298+ print_pkghash(toins_deps);
 299+ }
 300+
 301+ printf("\nContinue? [y/N] ");
 302+ c = getc(stdin);
 303+ if (c != 'y') {
 304+ printf("Okay, exiting\n");
 305+ return 0;
 306+ }
 307+ install_all();
 308+ return 0;
 309+}
 310+
 311+void
 312+install_all(void)
 313+{
 314+struct package *next;
 315+ while (next = next_installable()) {
 316+ install_one(next);
 317+ }
 318+ if (g_hash_table_size(to_install) || g_hash_table_size(toins_deps))
 319+ fprintf(stderr, "No installable packages; possible dependency loop?\n");
 320+}
 321+
 322+struct package *
 323+next_installable(void)
 324+{
 325+struct package *next;
 326+ next = g_hash_table_find(toins_deps, is_installable, NULL);
 327+ if (next) {
 328+ g_hash_table_remove(toins_deps, next->name);
 329+ return next;
 330+ }
 331+ next = g_hash_table_find(to_install, is_installable, NULL);
 332+ if (next)
 333+ g_hash_table_remove(to_install, next->name);
 334+ return next;
 335+}
 336+
 337+gboolean
 338+is_installable(key, value, ud)
 339+gpointer key, value, ud;
 340+{
 341+struct package *pkg = value;
 342+GSList *dep;
 343+ for (dep = pkg->depends; dep; dep = g_slist_next(dep)) {
 344+ if (!is_installed(dep->data)) {
 345+ return FALSE;
 346+ }
 347+ }
 348+ return TRUE;
 349+}
 350+
 351+int
 352+install_one(pkg)
 353+struct package *pkg;
 354+{
 355+pid_t pid;
 356+int res;
 357+ fprintf(stderr, "Installing %s...\n", pkg->name);
 358+ switch (pid = fork()) {
 359+ case -1:
 360+ fprintf(stderr, "fork: %s\n", strerror(errno));
 361+ exit(1);
 362+ case 0:
 363+ execl("/usr/sbin/pkgadd", "pkgadd", "-d", pkgroot, "--", pkg->name, NULL);
 364+ fprintf(stderr, "execl: %s\n", strerror(errno));
 365+ _exit(1);
 366+ }
 367+ if (waitpid(pid, &res, 0) < 0) {
 368+ fprintf(stderr, "waitpid: %s\n", strerror(errno));
 369+ exit(1);
 370+ }
 371+ if (WEXITSTATUS(res)) {
 372+ fprintf(stderr, "pkgadd exited with return code %d\n", WEXITSTATUS(res));
 373+ exit(1);
 374+ }
 375+ fprintf(stderr, "%s installed okay\n", pkg->name);
 376+ g_hash_table_insert(inst_pkgs, pkg->name, pkg);
 377+}
 378+
 379+int
 380+add_depends(pkg)
 381+struct package *pkg;
 382+{
 383+GSList *dep;
 384+int n = 0;
 385+ for (dep = pkg->depends; dep; dep = g_slist_next(dep)) {
 386+ struct package *dpkg;
 387+ if ((dpkg = g_hash_table_lookup(pkgs_byname, dep->data)) == NULL) {
 388+ fprintf(stderr, "Package %s depends on unknown package %s\n",
 389+ pkg->name, dep->data);
 390+ return -1;
 391+ }
 392+ if (!is_installed(dpkg->name) && !is_candidate(dpkg->name)) {
 393+ g_hash_table_insert(toins_deps, dpkg->name, dpkg);
 394+ if (add_depends(dpkg) == -1)
 395+ return -1;
 396+ n++;
 397+ }
 398+ }
 399+ return n;
 400+}
 401+
 402+void
 403+print_pkghash(hash)
 404+GHashTable *hash;
 405+{
 406+ g_hash_table_foreach(hash, print_pkghash_one, NULL);
 407+}
 408+
 409+void
 410+print_pkghash_one(key, value, ud)
 411+gpointer key, value, ud;
 412+{
 413+ print_package(value);
 414+}
 415+
 416+void
 417+print_package(pkg)
 418+struct package *pkg;
 419+{
 420+ printf("%c %-30s %s\n", is_installed(pkg->name) ? 'i' : 'a',
 421+ pkg->name, pkg->desc ? pkg->desc : "<no description>");
 422+}
 423+
 424+int
 425+is_installed(name)
 426+const char *name;
 427+{
 428+ return g_hash_table_lookup(inst_pkgs, name) != NULL;
 429+}
 430+
 431+int
 432+is_candidate(name)
 433+const char *name;
 434+{
 435+ return g_hash_table_lookup(to_install, name)
 436+ || g_hash_table_lookup(toins_deps, name);
 437+}
 438+
 439+void
 440+pkgsearch(key, value, data)
 441+gpointer key, value, data;
 442+{
 443+const char *term = data;
 444+struct package *pkg = value;
 445+char *lterm, *lname, *ldesc;
 446+ lname = g_ascii_strdown(pkg->name, -1);
 447+ ldesc = g_ascii_strdown(pkg->desc, -1);
 448+ lterm = g_ascii_strdown(term, -1);
 449+ if (fnmatch(lterm, ldesc, 0) == 0 || fnmatch(lterm, lname, 0) == 0)
 450+ print_package(pkg);
 451+ g_free(lname);
 452+ g_free(ldesc);
 453+ g_free(lterm);
 454+}
 455+
 456+int
 457+initroot(void)
 458+{
 459+int npkg = 0, nign = 0;
 460+char *tieol;
 461+GHashTable *pkgs;
 462+DIR *pd;
 463+struct dirent *de;
 464+FILE *f;
 465+ if (!pkgroot) {
 466+ fprintf(stderr, "Package root not specified (use -m <root>)\n");
 467+ return 1;
 468+ }
 469+
 470+ if ((pd = opendir(pkgroot)) == NULL) {
 471+ fprintf(stderr, "Cannot open package root %s: %s\n", pkgroot, strerror(errno));
 472+ return 1;
 473+ }
 474+
 475+ fprintf(stderr, "Initialising package database from %s...\n", pkgroot);
 476+ setupterm(NULL, 1, NULL);
 477+ tieol = tigetstr("el");
 478+ pkgs_byname = g_hash_table_new(g_str_hash, g_str_equal);
 479+ pkgs = g_hash_table_new(g_str_hash, g_str_equal);
 480+ chdir(pkgroot);
 481+ while (de = readdir(pd)) {
 482+ struct package *pkg;
 483+ if (de->d_name[0] == '.')
 484+ continue;
 485+ if (chdir(de->d_name) == -1) {
 486+ nign++;
 487+ continue;
 488+ }
 489+ if (access("pkgmap", F_OK) != 0) {
 490+ nign++;
 491+ continue;
 492+ }
 493+ fprintf(stderr, "\r%s%s", tieol, de->d_name);
 494+ npkg++;
 495+ pkg = calloc(1, sizeof(struct package));
 496+ if (read_pkg_info(pkg, ".") == -1) {
 497+ fprintf(stderr, "%s: cannot read package information\n", de->d_name);
 498+ return 1;
 499+ }
 500+ g_hash_table_insert(pkgs_byname, pkg->name, pkg);
 501+ if (chdir(pkgroot) == -1) {
 502+ fprintf(stderr, "chdir(%s): %s\n", pkgroot, strerror(errno));
 503+ return 1;
 504+ }
 505+ }
 506+ closedir(pd);
 507+ fprintf(stderr, "\r%sFound %d packages (%d ignored)\n", tieol, npkg, nign);
 508+
 509+ fprintf(stderr, "Writing configuration file %s: ", CFGFILE);
 510+ if ((f = fopen(CFGFILE, "w")) == NULL) {
 511+ fprintf(stderr, "%s\n", strerror(errno));
 512+ return 1;
 513+ }
 514+ fprintf(f, "pkgroot=%s\n", pkgroot);
 515+ fclose(f);
 516+ fprintf(stderr, "OK\n");
 517+
 518+ fprintf(stderr, "Writing package database %s: ", PKGFILE);
 519+ if ((f = fopen(PKGFILE, "w")) == NULL) {
 520+ fprintf(stderr, "%s\n", strerror(errno));
 521+ return 1;
 522+ }
 523+ g_hash_table_foreach(pkgs_byname, pkgdb_write, f);
 524+ fclose(f);
 525+ fprintf(stderr, "OK\n");
 526+ return 0;
 527+}
 528+
 529+void
 530+pkgdb_write(key, value, ud)
 531+gpointer key, value, ud;
 532+{
 533+FILE *f = ud;
 534+const char *name = key;
 535+struct package *pkg = value;
 536+ fprintf(f, "p %s\n", name);
 537+ fprintf(f, "desc %s\n", pkg->desc);
 538+ g_slist_foreach(pkg->depends, pkgdb_writedep, f);
 539+}
 540+
 541+void
 542+pkgdb_writedep(data, ud)
 543+gpointer data, ud;
 544+{
 545+const char *dep = data;
 546+FILE *f = ud;
 547+ fprintf(f, "dep %s\n", dep);
 548+}
 549+
 550+int
 551+read_pkg_info(pkg, dir)
 552+struct package *pkg;
 553+const char *dir;
 554+{
 555+GIOChannel *f;
 556+GError *err = NULL;
 557+char *ln;
 558+ if ((f = g_io_channel_new_file("pkginfo", "r", &err)) == NULL) {
 559+ fprintf(stderr, "\rpkginfo: %s\n", err->message);
 560+ return -1;
 561+ }
 562+ while (g_io_channel_read_line(f, &ln, NULL, NULL, &err) == G_IO_STATUS_NORMAL) {
 563+ char *o, *v, *p;
 564+ ln[strlen(ln) - 1] = '\0';
 565+ if (*ln == '#') {
 566+ g_free(ln);
 567+ continue;
 568+ }
 569+ if ((v = strchr(ln, '=')) == NULL) {
 570+ g_free(ln);
 571+ continue;
 572+ }
 573+ o = ln;
 574+ *v++ = '\0';
 575+ if (!strcmp(o, "NAME"))
 576+ pkg->desc = strdup(v);
 577+ else if (!strcmp(o, "PKG")) {
 578+ if (p = strpbrk(v, " \t"))
 579+ *p = '\0';
 580+ pkg->name = strdup(v);
 581+ }
 582+ g_free(ln);
 583+ }
 584+ g_io_channel_unref(f);
 585+ if (!pkg->name) {
 586+ fprintf(stderr, "\rpkginfo: no package name\n");
 587+ return -1;
 588+ }
 589+ if ((f = g_io_channel_new_file("install/depend", "r", &err)) == NULL)
 590+ return 0;
 591+ while (g_io_channel_read_line(f, &ln, NULL, NULL, &err) == G_IO_STATUS_NORMAL) {
 592+ char *v, *p;
 593+ ln[strlen(ln) - 1] = '\0';
 594+ if (*ln != 'P' || strlen(ln) < 3) {
 595+ g_free(ln);
 596+ continue;
 597+ }
 598+ ln += 2;
 599+ if (v = strpbrk(ln, " \t"))
 600+ *v = '\0';
 601+ if (p = strpbrk(v, " \t"))
 602+ *p = '\0';
 603+ pkg->depends = g_slist_prepend(pkg->depends, strdup(ln));
 604+ g_free(ln);
 605+ }
 606+ g_io_channel_unref(f);
 607+
 608+ return 0;
 609+}
 610+
Property changes on: trunk/tools/rosary/rosary.c
___________________________________________________________________
Added: svn:keywords
1611 + Author Date Id Revision
Added: svn:eol-style
2612 + native
Index: trunk/tools/rosary/Makefile
@@ -0,0 +1,10 @@
 2+default: all
 3+all: rosary
 4+rosary.o: rosary.c
 5+ cc `pkg-config --cflags glib-2.0` -g -c rosary.c -o $@
 6+rosary: rosary.o
 7+ cc -g rosary.o -o rosary `pkg-config --libs glib-2.0` -lcurses -ltecla
 8+clean:
 9+ rm -f rosary rosary.o
 10+
 11+.KEEP_STATE:
Property changes on: trunk/tools/rosary/Makefile
___________________________________________________________________
Added: svn:keywords
112 + Author Date Id Revision
Added: svn:eol-style
213 + native
Index: trunk/tools/rosary/README
@@ -0,0 +1,12 @@
 2+To use:
 3+
 4+ 1) make
 5+ 2) cp rosary /usr/local/sbin
 6+ 3) rosary -I -m /path/to/Solaris_10/Product
 7+
 8+To search for a package:
 9+ rosary search <glob>
 10+To install a package:
 11+ rosary install <name> [<name> <name>...]
 12+To open a command shell:
 13+ rosary shell
Property changes on: trunk/tools/rosary/README
___________________________________________________________________
Added: svn:keywords
114 + Author Date Id Revision
Added: svn:eol-style
215 + native

Status & tagging log