diff options
author | jkh <jkh@FreeBSD.org> | 1995-04-21 10:05:46 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1995-04-21 10:05:46 +0000 |
commit | 1f6fa4c9ec95068d3ca4fcbea6bf82fa43431851 (patch) | |
tree | 20b76779594f5b70ab0711ff6fb02e2437d8ee27 | |
parent | 63dadcab7d7b8eb9e20ea5abd48532b093e82632 (diff) | |
download | FreeBSD-src-1f6fa4c9ec95068d3ca4fcbea6bf82fa43431851.zip FreeBSD-src-1f6fa4c9ec95068d3ca4fcbea6bf82fa43431851.tar.gz |
Bring this up to date with Marc van Kempen's latest version (1.0) now
that the libdialog changes have gone in to support it.
Submitted by: Marc van Kempen <wmbfmk@urc.tue.nl>
-rw-r--r-- | usr.sbin/pkg_manage/CHANGES | 7 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/Makefile | 14 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/TODO | 87 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/pkg_main.c | 49 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/pkg_manage.1 | 5 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/pkg_manage.c | 597 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/pkg_manage.h | 41 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/pkg_ui.c | 496 | ||||
-rw-r--r-- | usr.sbin/pkg_manage/version.c | 1 |
9 files changed, 981 insertions, 316 deletions
diff --git a/usr.sbin/pkg_manage/CHANGES b/usr.sbin/pkg_manage/CHANGES new file mode 100644 index 0000000..25564b8 --- /dev/null +++ b/usr.sbin/pkg_manage/CHANGES @@ -0,0 +1,7 @@ +- fixed a bug with respect to the parsing of the pkg_info output +- implemented get_desc() which extracts +DESC and +COMMENT from the + packages. This is still done the stupid way (slow). +- install_batch(): two lists, one containing the to be installed + packages from the chosen directory, the other containing the + allready installed packages. + diff --git a/usr.sbin/pkg_manage/Makefile b/usr.sbin/pkg_manage/Makefile index 49691bf..c5f8940 100644 --- a/usr.sbin/pkg_manage/Makefile +++ b/usr.sbin/pkg_manage/Makefile @@ -1,11 +1,14 @@ -# $Id$ +# $Id: Makefile,v 1.1.1.1 1995/02/15 20:47:56 ache Exp $ PROG= pkg_manage -LDADD+= -ldialog -lncurses -lmytinfo -DPADD+= ${LIBDIALOG} ${LIBNCURSES} ${LIBMYTINFO} -CFLAGS+= -Wall -Wstrict-prototypes -DHELP_PATH=\"${HELPDIR}/\" +SRCS= pkg_main.c pkg_manage.c pkg_ui.c version.c +LDADD+= ../libdialog/libdialog.a ../libncurses/libncurses.a -lmytinfo +DPADD+= ${LIBDIALOG} ${LIBNCURSES} ${LIBMYTINFO} +CFLAGS+= -Wall -Wstrict-prototypes -DHELP_PATH=\"${HELPDIR}/\" \ + -I../libdialog -I../libncurses -g -HELPDIR = /usr/share/misc/pkg_manage +#HELPDIR = /usr/share/misc/pkg_manage +HELPDIR = /home/marc/src/dialog/pkg_manage HELPS= pkg_view-inst.hlp pkg_del-inst.hlp pkg_preview.hlp \ pkg_install.hlp pkg_main.hlp @@ -20,3 +23,4 @@ afterinstall: .include <bsd.prog.mk> +pkg_manage: ../libdialog/libdialog.a diff --git a/usr.sbin/pkg_manage/TODO b/usr.sbin/pkg_manage/TODO new file mode 100644 index 0000000..77552b0 --- /dev/null +++ b/usr.sbin/pkg_manage/TODO @@ -0,0 +1,87 @@ +TODO list for pkg_manage: + + +- check for expections, catch error output from pkg_* tools + check all i/o operations for error capture. +done 6Apr95 + +- implement better (faster) way of getting the +* out of the + tar files, or use an index file for this. +done 9Apr95, modified tar to stop after having extracted all + fnames listed on the commandline. + +- add extra option to have a user select a directory and then display + all packages in that directory with a descriptive line, one should be + able to select a whole bunch of packages and then select GO. + Maybe review the whole concept. Perhaps something like this: +done 5Apr95 + + NOTE: + Have two windows, one containing the installed packages, the other + containing the *to be* installed packages. Packages listed in this + last window depend upon the directory chosen. One can delete + packages in the left window, or move packages from the right window + to the left, that is install them. + Coupling deletion from the left window to inclusion in the right + window will be difficult, since one cannot be sure that the list + one sees in the right window are all the packages available. + Furthermore deleting a package does not give one a package file + to store in a central place. + This coupling should not be suggested. + +- when deleting the last package in the list, adjust the cursor-pointer +done 6Apr95 + +- check if a package is already installed when installing it. +done 7Apr95 + +- Read also +CONTENTS from pkg when scanning directory to extract + the package name from it. +done 7Apr95 + +- should I check for uid being root before installing anything? + + +- Make sure that the process can continue as a batch process. + Accumulate all error messages and show them after processing. + Before beginning with a batch install, check if any packages are + already installed, if so pop up message suggesting to delete + the package first before installing the new one. +done 7apr95 + +- make a dialog in which the comment information is printed, and + which has a button for displaying the description information. +done 6Apr95, no button, but key F2 for description + +- when selecting the directory to install multiple packages + print a helpline about what to do. +done 6Apr95 + +- limit the width of the info-popup when selecting multiple + packages. +done 6Apr95 + +- make sure that the popup's dont get too big. +done 6Apr95 + +- add progress indication when scanning packages and installing them. +done 6Apr95, added a dialog_gauge to libdialog. + +- check for delwin's whenever a newwin was called +done 6Apr95 + +- when an error occurs in get_desc, because it can't stat the temporary + file, then there is an seg-fault in draw_box in RefreshListObj() ????? + Low priority, because something fishy is going on then anyway + +- use $TMPDIR to create tmp directory into + +- make sure that when calling help, the helplines are disabled. +done 11Apr95, also implemented a different mechanism to save and +restore helplines + +- do a size calculation for the selected packages +done 11Apr95 + +- (next version?) implement exec_catch_errors with popen(), I think + this will speed up things quite a bit. diff --git a/usr.sbin/pkg_manage/pkg_main.c b/usr.sbin/pkg_manage/pkg_main.c new file mode 100644 index 0000000..c730311 --- /dev/null +++ b/usr.sbin/pkg_manage/pkg_main.c @@ -0,0 +1,49 @@ +/*************************************************************** + * + * Program: pkg_main.c + * Author: Marc van Kempen + * Desc: main routine for pkg_manage + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + ***************************************************************/ + +#include "pkg_manage.h" +#include "ui_objects.h" + +extern PKG_info p_inf; + +/* + * Main + */ + +void +main(void) +{ + init_dialog(); + + p_inf.Nitems = 0; /* Initialize p_inf */ + + get_pkginfo(); + run_menu(); + + if (p_inf.Nitems > 0) { + FreeInfo(); + } + + clear(); + dialog_update(); + end_dialog(); + + return; +} /* main() */ diff --git a/usr.sbin/pkg_manage/pkg_manage.1 b/usr.sbin/pkg_manage/pkg_manage.1 index 76f67fb..3df438e 100644 --- a/usr.sbin/pkg_manage/pkg_manage.1 +++ b/usr.sbin/pkg_manage/pkg_manage.1 @@ -11,7 +11,8 @@ delete and view packages. It is a front-end to the pkg_add(1), pkg_info(1) and pkg_delete(1) programs. Pressing F1 (or '?') at anytime during the program will bring up -online-help. (Pressing '?' will not work in character input fields) +online-help. (Pressing '?' will not invoke help when in character +input fields) .SH NAVIGATING THE MENU When starting pkg_manage you will be put in a menu with the following @@ -154,7 +155,7 @@ button and press enter. If you want to back out, move the cursor to the button and press enter. .SH SEE ALSO -pkg_add(1), pkg_info(1), pkg_delete(1), pkg_create. +pkg_add(1), pkg_info(1), pkg_delete(1), pkg_create(1). .SH BUGS Haven't met them yet. diff --git a/usr.sbin/pkg_manage/pkg_manage.c b/usr.sbin/pkg_manage/pkg_manage.c index eb0bab0..bac4fee 100644 --- a/usr.sbin/pkg_manage/pkg_manage.c +++ b/usr.sbin/pkg_manage/pkg_manage.c @@ -8,11 +8,7 @@ * * 1. View installed packages * 2. Delete installed packages - * 3. View package files - * 4. Install packages files. - * - * Installation and deletion of packages should be previewable - * + * 3. Install packages * * Copyright (c) 1995, Marc van Kempen * @@ -32,54 +28,38 @@ #include <string.h> #include <unistd.h> #include <sys/types.h> +#include <sys/param.h> #include <sys/stat.h> #include <stdio.h> #include "pkg_manage.h" +#include "ui_objects.h" +#include "dialog.priv.h" +#include "dir.h" -static PKG_info p_inf; -static int got_info; - -/* - * Local prototypes - */ +PKG_info p_inf = { 0, 0, NULL, NULL, NULL, NULL, NULL }; -void run_menu(void); -void get_pkginfo(void); -void FreeMnu(unsigned char **mnu, int n); -void FreeInfo(void); +/******************************************************************* + * + * Misc Functions + * + *******************************************************************/ +void +FreeInfo(void) /* - * Main + * Desc: free the space allocated to p_inf */ - -void -main(void) { - init_dialog(); - - get_pkginfo(); - run_menu(); - - if (got_info) - FreeInfo(); - - clear(); - dialog_update(); - end_dialog(); + free(p_inf.buf); + free(p_inf.name); + free(p_inf.comment); + free(p_inf.description); + p_inf.Nitems = 0; + FreeMnu(p_inf.mnu, 2*p_inf.Nitems); return; -} /* main() */ - -void FreeInfo(void) -{ - free(p_inf.buf); - free(p_inf.name); - free(p_inf.comment); - free(p_inf.description); - FreeMnu(p_inf.mnu, 2*p_inf.Nitems); - got_info = FALSE; -} +} /* FreeInfo() */ void FreeMnu(unsigned char **mnu, int n) @@ -91,7 +71,7 @@ FreeMnu(unsigned char **mnu, int n) for (i=0; i<n; i++) { free(mnu[i]); - } + } free(mnu); return; @@ -117,68 +97,135 @@ file_exists(char *fname) } /* file_exists() */ +int +exec_catch_errors(char *prog, char *arg, char *fout) +/* + * Desc: run the program <prog> with arguments <arg> and catch its output + * in <fout> and display it in case of an error. specify NULL, + * if you don't want output. + */ +{ + char *execstr, *tmp; + int ret, yesno, unlink_fout; + + execstr = (char *) malloc( strlen(prog) + strlen(arg) + 30 ); + if (!execstr) { + fprintf(stderr, "exec_catch_errors: Error while mallocing memory\n"); + exit(-1); + } + + /* when fout == NULL, allocate a temporary file name and unlink it */ + /* when done */ + if (!fout) { + fout = tempnam(NULL, "pkg."); + if (!fout) { + fprintf(stderr, "exec_catch_errors: Error allocating temp.name\n"); + exit(-1); + } + unlink_fout = TRUE; + } else { + unlink_fout = FALSE; + } + + sprintf(execstr, "%s %s > %s 2>&1", prog, arg, fout); + ret = system(execstr); + if (ret) { + + yesno = dialog_yesno("Error", "An error occured, view output?", 8, 40); + if (yesno == 0) { + /* disable helpline */ + tmp = get_helpline(); + use_helpline("use arrowkeys, PgUp, PgDn to move, press enter when done"); + dialog_textbox("Error output from pkg_add", fout, LINES-2, COLS-4); + restore_helpline(tmp); + } + } + + if (unlink_fout) { + unlink(fout); + free(fout); + } + free(execstr); + + return(ret); +} /* exec_catch_errors() */ + void get_pkginfo(void) +/* + * Desc: get info about installed packages + */ { FILE *f; char *p; - char prog[512]; struct stat sb; int i, j, n, lsize; - int newline; + int newline, ret; int state; char *tmp_file; #define R_NAME 1 #define R_COMMENT 2 #define R_DESC 3 - if (got_info) + if (p_inf.Nitems > 0) { FreeInfo(); + } + /* p_inf.Nitems == 0 */ dialog_msgbox("PKG INFO", "Reading info, please wait ...", 4, 35, FALSE); - tmp_file = tempnam(NULL, "pkg."); - - sprintf(prog, "%s -a > %s", PKG_INFO, tmp_file); - system(prog); + tmp_file = tempnam(NULL, "pkg."); + ret = exec_catch_errors(PKG_INFO, "-a", tmp_file); + if (ret) { + dialog_notify("Could not get package info\nexiting!"); + unlink(tmp_file); + free(tmp_file); + return; + } dialog_clear_norefresh(); - + f = fopen(tmp_file, "r"); if (!f) { dialog_notify("Could not open temporary file"); - goto err1; + unlink(tmp_file); + free(tmp_file); + return; } if (stat(tmp_file, &sb)) { /* stat file to get filesize */ dialog_notify("Could not stat temporary file"); - goto err2; + fclose(f); + unlink(tmp_file); + free(tmp_file); + return; } if (sb.st_size == 0) { - dialog_notify("No packages info available"); - goto err2; + dialog_notify("No packages installed or no info available"); + fclose(f); + unlink(tmp_file); + free(tmp_file); + return; } /* Allocate a buffer with sufficient space to hold the entire file */ - p_inf.buf = (char *) malloc( sb.st_size ); + p_inf.buf = (char *) malloc( sb.st_size + 1); p_inf.N = sb.st_size; if (fread(p_inf.buf, 1, p_inf.N, f) != p_inf.N) { - dialog_notify("Could not read from temporary file"); + dialog_notify("Could not read entire temporary file"); free(p_inf.buf); -err2: fclose(f); -err1: - got_info = FALSE; unlink(tmp_file); free(tmp_file); return; } + p_inf.buf[p_inf.N] = 0; fclose(f); unlink(tmp_file); free(tmp_file); + /* make one sweep through the buffer to determine the # of entries */ /* Look for "Information for" in the first column */ - i = p_inf.N - strlen("Information for") - 1; p = p_inf.buf; if (strncmp(p_inf.buf, "Information for", 15) == 0) { @@ -186,7 +233,7 @@ err1: } else { n = 0; } - while (i--) { + while (i-- > 0) { if (*p == '\n') { if (strncmp(p+1, "Information for", 15) == 0) { n++; @@ -210,6 +257,7 @@ err1: state = R_NAME; while (*p) { if (newline) { + newline = FALSE; switch(state) { case R_NAME: if (strncmp(p, "Information for", 15) == 0) { @@ -226,21 +274,25 @@ err1: if (*p) p_inf.comment[i] = (char *) p+1; p++; while (*p && *p != '\n') p++; - if (*p) *p = '\0'; - p++; + if (*p) { + *p = '\0'; + newline = TRUE; + } state = R_DESC; } break; case R_DESC: if (strncmp(p, "Description:", 12) == 0) { while (*p && *p != '\n') p++; - if (*p) p_inf.description[i] = (char *) p+1; + if (*p) { + p_inf.description[i] = (char *) p+1; + newline = TRUE; + } state = R_NAME; i++; } break; } - newline = FALSE; } if (*p == '\n') newline = TRUE; p++; @@ -262,8 +314,7 @@ err1: strncpy(p_inf.mnu[j], p_inf.comment[i], lsize-1); p_inf.mnu[j++][lsize-1] = 0; } - - got_info = TRUE; + return; } /* get_pkginfo() */ @@ -275,268 +326,220 @@ get_pkg_index(char *selection) { int i, found = FALSE, index = -1; - if (got_info) - for (i=0; i<p_inf.Nitems && !found; i++) { - if (strcmp(selection, p_inf.name[i]) == 0) { - found = TRUE; - index = i; - } + for (i=0; i<p_inf.Nitems && !found; i++) { + if (strcmp(selection, p_inf.name[i]) == 0) { + found = TRUE; + index = i; } + } return(index); } /* get_pkg_index() */ void -view_installed(void) -/* - * Desc: View the installed packages +install_package(char *fname) +/* + * Desc: install the package <fname> */ { - int i, quit_view, sc=0, ch=0; - char selection[1024]; + char *tmp_file; - if (!got_info) { - use_helpfile(NULL); - use_helpline(NULL); - dialog_notify("No packages info available"); - return; - } - use_helpfile(VIEW_INST_HLP); - quit_view = FALSE; - while (!quit_view) { - use_helpline("use arrow-keys or character to select option and press enter"); - if (dialog_menu("View installed packages", - "Press enter to see the package descriptions", - LINES, COLS, LINES-5, p_inf.Nitems, - p_inf.mnu, selection, &ch, &sc )) { - quit_view = TRUE; - } else { - i = get_pkg_index(selection); - use_helpline("use PgUp and PgDn and arrow-keys to move throught the text"); - dialog_mesgbox(p_inf.comment[i], p_inf.description[i], LINES, COLS); - } + tmp_file = tempnam(NULL, "pkg."); + if (!tmp_file) { + fprintf(stderr, "install_package(): Error malloc'ing tmp_file\n"); + exit(-1); } - use_helpfile(NULL); - use_helpline(NULL); + exec_catch_errors(PKG_ADD, fname, tmp_file); + + unlink(tmp_file); + free(tmp_file); return; -} /* view_installed() */ +} /* install_package() */ -void -delete_installed(void) + + +int +get_desc(char *fname, char **name, char **comment, + char **desc, long *size, char *tmp_dir) /* - * Desc: Delete an installed package + * Desc: get the description and comment from the files + * DESC, CONTENT and COMMENT from fname + * Pre: the current working directory is a temporary, + * empty directory. + * Post: name = the name of the package + * comment = the comment for the package + * desc = the description for the package */ { - unsigned char *mnu[] = { - "1. Simulate delete", "Display commands that are going to be executed", - "2. Delete", "Execute commands to delete the package", - "3. Cancel", "Do NOT delete the package" - }; - char tmp[512], selection[512], *tmp_file; - int quit_view, quit_del; - int i, sel, ch=0, sc=0, ch0=0, sc0=0; - - if (!got_info) { - use_helpfile(NULL); - use_helpline(NULL); - dialog_notify("No packages info available"); - return; + char msg[80], args[512], *buf, *p, tmp[MAXPATHLEN]; + FILE *f, *pf; + struct stat sb; + int i, N, ret, found; + + *comment = NULL; + *desc = NULL; + *name = NULL; + + sprintf(args, "--fast-read -zxvf %s -C %s %s %s %s", fname, + tmp_dir, CONTENTS, DESC, COMMENT); + ret = exec_catch_errors(TAR, args, NULL); + if (ret) { + sprintf(msg, "Could not get info for <%s>", fname); + dialog_notify(msg); + return(FALSE); } - quit_view = FALSE; - while (!quit_view) { - use_helpline("use arrow-keys or character to select option and press enter"); - use_helpfile(DEL_INST_HLP); - if (dialog_menu("DELETE an installed package", - "Press enter to select a package", - LINES, COLS, LINES-5, p_inf.Nitems, - p_inf.mnu, selection, &ch, &sc)) { - quit_view = TRUE; + /* Read CONTENTS */ + sprintf(tmp, "%s/%s", tmp_dir, CONTENTS); + f = fopen(tmp, "r"); + if (f == NULL) { + /* No contents file in package, propably not a package */ + return(FALSE); + } + if (stat(tmp, &sb)) { /* stat file to get filesize */ + dialog_notify("Could not stat CONTENTS file"); + fclose(f); + return(FALSE); + } + if (sb.st_size == 0) { + dialog_notify("CONTENTS file has zero length"); + fclose(f); + return(FALSE); + } + + /* Allocate a buffer with sufficient space to hold the entire file */ + buf = (char *) malloc( sb.st_size + 1); + N = sb.st_size; + if (fread(buf, 1, N, f) != N) { + sprintf(msg, "Could not read CONTENT file for <%s>", fname); + dialog_notify(msg); + free(buf); + fclose(f); + return(FALSE); + } + fclose(f); + buf[N] = 0; + + /* look for the name of the package */ + p = buf; + found = FALSE; + while (*p && !found) { + if (strncmp(p, "@name ", 6) == 0) { + i=0; + p += 6; + while (*p && p[i] != '\n' && p[i] != '\r') i++; + *name = (char *) malloc( i+1 ); + strncpy(*name, p, i); + (*name)[i] = 0; + found = TRUE; } else { - quit_del = FALSE; - i = get_pkg_index(selection); - while (!quit_del) { - sprintf(tmp, "Delete <%s>", p_inf.name[i]); - use_helpline("use arrow-keys or digit to select option and press enter"); - if (dialog_menu("Delete a package", tmp, 10, COLS-6, - 3, 3, mnu, selection, &ch0, &sc0)) { - quit_del = TRUE; - } else { - sel = atoi(selection); - switch(sel) { - case 1: - tmp_file = tempnam(NULL, "pkg."); - sprintf(tmp, "%s -n %s > %s", - PKG_DELETE, p_inf.name[i], tmp_file); - system(tmp); - dialog_textbox("Package deletion commands", - tmp_file, LINES, COLS); - unlink(tmp_file); - free(tmp_file); - break; - case 2: - sprintf(tmp, "%s %s", PKG_DELETE, p_inf.name[i]); - system(tmp); - get_pkginfo(); - quit_del = TRUE; - break; - case 3: - quit_del = TRUE; - break; - } - } - } + p++; } } - use_helpfile(NULL); - use_helpline(NULL); + unlink(tmp); - return; -} /* delete_installed() */ - -void -preview_pkg(void) -/* - * Desc: View the package description and comment before installation - */ -{ - char *fname; - char *tmp_file; - char prog[512], title[512]; - - use_helpfile(PREVIEW_HLP); - fname = dialog_fselect(".", "*.tgz"); - while (fname) { - use_helpfile(PREVIEW_HLP); - use_helpline("use PgUp and PgDn and arrow-keys to move through the text"); - tmp_file = tempnam(NULL, "pkg."); - sprintf(prog, "%s zxOf %s +COMMENT +DESC > %s", TAR, fname, tmp_file); - system(prog); - sprintf(title, "Preview package <%s>", fname); - dialog_textbox(title, tmp_file, LINES, COLS); - unlink(tmp_file); - free(fname); - free(tmp_file); - fname = dialog_fselect(".", "*.tgz"); + /* Read COMMENT file */ + sprintf(tmp, "%s/%s", tmp_dir, COMMENT); + f = fopen(tmp, "r"); + if (f == NULL) { + /* No comment file in package, propably not a package */ + return(FALSE); + } + if (stat(tmp, &sb)) { /* stat file to get filesize */ + dialog_notify("Could not stat COMMENT file"); + fclose(f); + return(FALSE); + } + if (sb.st_size == 0) { + dialog_notify("COMMENT file has zero length"); + fclose(f); + return(FALSE); } - if (fname) free(fname); - use_helpfile(NULL); - use_helpline(NULL); - return; -} /* preview_pkg() */ + /* Allocate a buffer with sufficient space to hold the entire file */ + *comment = (char *) malloc( sb.st_size + 1); + N = sb.st_size; + if (fread(*comment, 1, N, f) != N) { + sprintf(msg, "Could not read COMMENT file for <%s>", fname); + dialog_notify(msg); + free(*comment); + fclose(f); + return(FALSE); + } + fclose(f); + (*comment)[N] = 0; + unlink(tmp); + + /* Read DESC */ + sprintf(tmp, "%s/%s", tmp_dir, DESC); + f = fopen(tmp, "r"); + if (f == NULL) { + /* No description file in package, propably not a package */ + return(FALSE); + } + if (stat(tmp, &sb)) { /* stat file to get filesize */ + dialog_notify("Could not stat DESC file"); + fclose(f); + return(FALSE); + } + if (sb.st_size == 0) { + dialog_notify("DESC file has zero length"); + fclose(f); + return(FALSE); + } -void -install_new(void) -/* - * Desc: Install a new package - */ -{ - char *fname; - char *tmp_file; - char tmp[512], selection[40]; - unsigned char *mnu[] = { - "1. Simulate install", "Display commands that are going to be executed", - "2. Install", "Execute commands to install the package", - "3. Cancel", "Do NOT install the package" - }; - int sel, quit_inst, ch=0, sc=0; - - use_helpfile(INSTALL_HLP); - fname = dialog_fselect(".", "*.tgz"); - if (!fname) { - quit_inst = TRUE; + /* Allocate a buffer with sufficient space to hold the entire file */ + *desc = (char *) malloc( sb.st_size + 1); + N = sb.st_size; + if (fread(*desc, 1, N, f) != N) { + sprintf(msg, "Could not read CONTENT file for <%s>", fname); + dialog_notify(msg); + free(*desc); + fclose(f); + return(FALSE); + } + fclose(f); + (*desc)[N] = 0; + unlink(tmp); + + /* get the size from the uncompressed package */ + sprintf(tmp, "%s -l %s", GUNZIP, fname); + pf = popen(tmp, "r"); + if (!pf) { + dialog_notify("Could not popen gunzip to get package size"); + *size = 0; } else { - quit_inst = FALSE; - } - while (!quit_inst) { - use_helpfile(INSTALL_HLP); - use_helpline("use arrow-keys or digit to select option and press enter"); - sprintf(tmp, "Install package <%s>", fname); - if (dialog_menu("Install a package", tmp, 10, COLS-5, - 3, 3, mnu, selection, &ch, &sc)) { - quit_inst = TRUE; - } else { - sel = atoi(selection); - switch(sel) { - case 1: - tmp_file = tempnam(NULL, "*.pkg"); - sprintf(tmp, "%s -n %s 2>&1 | cat > %s", PKG_ADD, fname, tmp_file); - system(tmp); - dialog_textbox("Package installation commands", - tmp_file, LINES, COLS); - unlink(tmp_file); - free(tmp_file); - break; - case 2: - sprintf(tmp, "%s %s", PKG_ADD, fname); - system(tmp); - get_pkginfo(); - quit_inst = TRUE; - break; - case 3: - quit_inst = TRUE; - break; - } + while (!feof(pf)) { + fgets(tmp, 80, pf); } + sscanf(tmp, "%*s %ld", size); + pclose(pf); + } + + if (found) { + return(TRUE); + } else { + return(FALSE); } - if (fname) free(fname); - use_helpfile(NULL); - use_helpline(NULL); +} /* get_desc() */ - return; -} /* install_new() */ -void -run_menu(void) -/* - * Desc: display/choose from menu +int +already_installed(char *name) +/* + * Desc: check if <name> is already installed as a package */ { - int quit_pkg, sel, ch=0, sc=0; - char selection[30]; - unsigned char *pkg_menu[] = { - "1. View installed", "Overview of the installed packages", - "2. Delete installed", "Delete an installed package", - "3. View pkg files", "Preview about to be installed packages", - "4. Install pkg files", "Install new packages", - "5. Quit", "Leave the program", - }; - - quit_pkg = FALSE; - while (!quit_pkg) { - use_helpline("use arrow-keys or digit to select option and press enter"); - use_helpfile(MAIN_HLP); - if (dialog_menu("Package Manager", "Choose one of the options", - LINES, COLS, 5, 5, pkg_menu, selection, &ch, &sc)) { - sel = 0; - quit_pkg = TRUE; - } else { - sel = atoi(selection); - } - - switch(sel) { - case 0: /* Quit */ - break; - case 1: /* View installed packages */ - view_installed(); - break; - case 2: /* Delete installed package */ - delete_installed(); - break; - case 3: /* Preview new package file */ - preview_pkg(); - break; - case 4: /* Install new package */ - install_new(); - break; - case 5: /* Quit */ - quit_pkg = TRUE; - break; + int i, found; + + found = FALSE; + for (i=0; i<p_inf.Nitems && !found; i++) { + if (strcmp(name, p_inf.name[i]) == 0) { + found = TRUE; } } - return; -} /* run_menu() */ - + return(found); +} /* already_installed() */ + diff --git a/usr.sbin/pkg_manage/pkg_manage.h b/usr.sbin/pkg_manage/pkg_manage.h index da5bdfa..f17059b 100644 --- a/usr.sbin/pkg_manage/pkg_manage.h +++ b/usr.sbin/pkg_manage/pkg_manage.h @@ -1,5 +1,5 @@ /* - * include file for pkg.c + * include file for pkg_manage * * * Copyright (c) 1995, Marc van Kempen @@ -39,24 +39,41 @@ typedef struct { unsigned char **mnu; /* pointers to be used with dialog_menu() */ } PKG_info; -typedef struct DirList { /* structure to hold the directory entries */ - char filename[MAXNAMLEN]; /* together with the stat-info per file */ - struct stat filestatus; /* filename, or the name to which it points */ - int link; /* is it a link ? */ - char *linkname; /* the name of the file the link points to */ -} DirList; +/* Names of the description and comment files in the package */ +#define DESC "+DESC" +#define COMMENT "+COMMENT" +#define CONTENTS "+CONTENTS" +/* some programs */ #define PKG_DELETE "/usr/sbin/pkg_delete" #define PKG_INFO "/usr/sbin/pkg_info" #define PKG_ADD "/usr/sbin/pkg_add" -#define TAR "/usr/bin/tar" +#define TAR "/usr/bin/tar" +#define GUNZIP "/usr/bin/gunzip" /* HELP_PATH must have a trailing '/' */ #ifndef HELP_PATH -#define HELP_PATH "/home/marc/src/pkg_manage/" +#define HELP_PATH "/home/marc/src/dialog/pkg_manage/" #endif -#define VIEW_INST_HLP HELP_PATH##"pkg_view-inst.hlp" -#define DEL_INST_HLP HELP_PATH##"pkg_del-inst.hlp" -#define PREVIEW_HLP HELP_PATH##"pkg_preview.hlp" +#define VIEW_INST_HLP HELP_PATH##"pkg_view_inst.hlp" +#define DEL_INST_HLP HELP_PATH##"pkg_del_inst.hlp" #define INSTALL_HLP HELP_PATH##"pkg_install.hlp" #define MAIN_HLP HELP_PATH##"pkg_main.hlp" +#define DS_INSTALL_HLP HELP_PATH##"pkg_ds_install.hlp" + + +/* + * prototypes + */ + +void run_menu(void); +void get_pkginfo(void); +void FreeMnu(unsigned char **mnu, int n); +void FreeInfo(void); +void install_package(char *fname); +int get_pkg_index(char *selection); +void install_batch(void); +int get_desc(char *fname, char **name, char **comment, + char **desc, long *size, char *tmp_file); +int exec_catch_errors(char *prog, char *arg, char *fout); +int already_installed(char *name); diff --git a/usr.sbin/pkg_manage/pkg_ui.c b/usr.sbin/pkg_manage/pkg_ui.c new file mode 100644 index 0000000..a24452d --- /dev/null +++ b/usr.sbin/pkg_manage/pkg_ui.c @@ -0,0 +1,496 @@ +/*************************************************************** + * + * Program: pkg_ui.c + * Author: Marc van Kempen + * Desc: user interface parts of pkg_manage + * + * Copyright (c) 1995, Marc van Kempen + * + * All rights reserved. + * + * This software may be used, modified, copied, distributed, and + * sold, in both source and binary form provided that the above + * copyright and these terms are retained, verbatim, as the first + * lines of this file. Under no circumstances is the author + * responsible for the proper functioning of this software, nor does + * the author assume any responsibility for damages incurred with + * its use. + * + ***************************************************************/ + +#include <stdlib.h> +#include <unistd.h> +#include <sys/param.h> +#include "pkg_manage.h" +#include "dir.h" +#include "dialog.priv.h" +#include "ui_objects.h" + +extern PKG_info p_inf; + + +void +view_installed(void) +/* + * Desc: View the installed packages + */ +{ + int i, quit_view, sc=0, ch=0; + char selection[1024]; + + if (p_inf.Nitems == 0) { + use_helpfile(NULL); + use_helpline(NULL); + dialog_notify("No packages installed or no info available"); + return; + } + use_helpfile(VIEW_INST_HLP); + quit_view = FALSE; + while (!quit_view) { + use_helpline("F1=help, use arrow-keys or character to select option and press enter"); + if (dialog_menu("View installed packages", + "Press enter to see the package descriptions", + LINES, COLS, LINES-5, p_inf.Nitems, + p_inf.mnu, selection, &ch, &sc )) { + quit_view = TRUE; + } else { + i = get_pkg_index(selection); + use_helpline("F1=help, use PgUp and PgDn and arrow-keys to move through the text"); + dialog_mesgbox(p_inf.comment[i], p_inf.description[i], LINES, COLS); + } + } + + use_helpfile(NULL); + use_helpline(NULL); + + return; +} /* view_installed() */ + +void +delete_installed(void) +/* + * Desc: Delete an installed package + */ +{ + unsigned char *mnu[] = { + "1. Simulate delete", "Display commands that are going to be executed", + "2. Delete", "Execute commands to delete the package", + "3. Cancel", "Do NOT delete the package" + }; + char tmp[512], args[512], selection[512], *tmp_file; + int quit_view, quit_del; + int i, sel, ch=0, sc=0, ch0=0, sc0=0, ret; + + if (p_inf.Nitems == 0) { + use_helpfile(NULL); + use_helpline(NULL); + dialog_notify("No packages installed or no info available"); + return; + } + quit_view = FALSE; + while (!quit_view) { + use_helpline("F1=help, use arrow-keys or character to select option and press enter"); + use_helpfile(DEL_INST_HLP); + if (dialog_menu("DELETE an installed package", + "Press enter to select a package", + LINES, COLS, LINES-5, p_inf.Nitems, + p_inf.mnu, selection, &ch, &sc)) { + quit_view = TRUE; + } else { + quit_del = FALSE; + i = get_pkg_index(selection); + while (!quit_del) { + sprintf(tmp, "Delete <%s>", p_inf.name[i]); + use_helpline("F1=help, use arrow-keys or digit to select option and press enter"); + if (dialog_menu("Delete a package", tmp, 10, COLS-6, + 3, 3, mnu, selection, &ch0, &sc0)) { + quit_del = TRUE; + } else { + sel = atoi(selection); + switch(sel) { + case 1: + tmp_file = tempnam(NULL, "pkg."); + sprintf(args, "-n %s", p_inf.name[i]); + ret = exec_catch_errors(PKG_DELETE, args, tmp_file); + if (!ret) { + dialog_textbox("Package deletion commands", + tmp_file, LINES, COLS); + } + unlink(tmp_file); + free(tmp_file); + break; + case 2: + exec_catch_errors(PKG_DELETE, p_inf.name[i], NULL); + get_pkginfo(); + if (ch >= p_inf.Nitems) { /* adjust pointers */ + ch = p_inf.Nitems-1; + if (sc>ch) sc=ch; + } + quit_del = TRUE; + if (p_inf.Nitems == 0) { + /* Quit 'delete-installed' when no packages available */ + quit_view = TRUE; + } + break; + case 3: + quit_del = TRUE; + break; + } + } + } + } + } + use_helpfile(NULL); + use_helpline(NULL); + + return; +} /* delete_installed() */ + +void +install_batch(void) +/* + * Desc: install several packages. + */ +{ + WINDOW *pkg_win, *w; + DirList *d = NULL; + char **fnames, o_pkg[MAXPATHLEN], o_pkgi[MAXPATHLEN], + **comment, **desc, **names, msg[512]; + int n, nf, i, p, quit, j, *a, recalc; + struct ComposeObj *obj = NULL; + ListObj *pkg_obj, *pkgi_obj; + ButtonObj *installbut_obj, *cancelbut_obj; + int o_installbut, o_cancelbut, install; + long total_marked = 0, *sizes; + char *tmp_file, tmp_dir[MAXPATHLEN]; + + /* first go to the directory where the packages are installed, then + list all packages in that directory with a short description of + the package. Pressing enter should give more info about a specific + package. */ + + use_helpfile(DS_INSTALL_HLP); + use_helpline("Select the directory where the pkg's reside"); + if (dialog_dselect()) { + /* cancel button was pressed */ + return; + } + use_helpline(NULL); + + pkg_win = newwin(LINES-4, COLS-12, 2, 5); + if (pkg_win == NULL) { + endwin(); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", + LINES-4, COLS-10, 2, 5); + exit(1); + } + draw_box(pkg_win, 0, 0, LINES-4, COLS-12, dialog_attr, border_attr); + wattrset(pkg_win, dialog_attr); + mvwaddstr(pkg_win, 0, (COLS-12)/2 - 12, " Install multiple packages "); + draw_shadow(stdscr, 2, 5, LINES-4, COLS-12); + use_helpline("Enter,F2=info, Space=mark, *=mark all, -=unmark all, TAB=move"); + display_helpline(pkg_win, LINES-5, COLS-12); + wrefresh(pkg_win); + + /* now build a list of the packages in the chosen directory */ + /* and display them in a list */ + + get_dir(".", "*.tgz", &d, &n); + get_filenames(d, n, &fnames, &nf); + FreeDir(d, n); /* free the space allocated to d */ + + /* now get the description and comment and the name from the packages. */ + /* If there is no +COMMENT or +DESC in the package, then it's propably */ + /* not a package */ + + if (nf == 0) { + dialog_notify("No installable packages in this directory"); + return; + } + + names = (char **) malloc( sizeof(char *) * nf); + comment = (char **) malloc( sizeof(char *) * nf ); + desc = (char **) malloc( sizeof(char *) * nf ); + sizes = (long *) malloc( sizeof(long) * nf ); + + /* get_desc extracts the info from the file names[i] and puts the */ + /* comment in comment[i] and the description in desc[i], space is */ + /* malloc'ed as needed, and should be freed when done with it. */ + /* get_desc() returns FALSE when fnames[i] is not a package */ + /* the name of the package is extracted from CONTENT and put in */ + /* names */ + + /* create a tmp directory in which the files will be extracted */ + + tmp_file = tempnam("", "pkg."); + if (!tmp_file) { + fprintf(stderr, "install_batch(): Error malloc'ing space for tmpfile\n"); + exit(1); + } + sprintf(tmp_dir, "/tmp/%s", tmp_file); + free(tmp_file); + if (mkdir(tmp_dir, S_IRWXU)) { + dialog_notify("Could not create temporary directory in /tmp, exiting"); + free(names); + free(comment); + free(desc); + for (i=0; i<nf; i++) free(fnames[i]); + free(fnames); + delwin(pkg_win); + return; + } + + + w = dupwin(curscr); + a = (int *) malloc( nf * sizeof(int) ); + j = 0; + for (i=0; i<nf; i++) { + dialog_gauge("Scanning directory:", fnames[i], LINES/2-3, COLS/2-30, + 7, 60, (int) ((float) (i+1)/nf*100)); + if (get_desc(fnames[i], &(names[i]), &(comment[i]), + &(desc[i]), &(sizes[i]), tmp_dir) == FALSE) { + a[j] = i; + j++; + } + } + wrefresh(w); + delwin(w); + + /* remove the tmp directory and change to the previous directory */ + if (rmdir(tmp_dir)) { + dialog_notify("install_batch(): Error removing temporary directory"); + for (i=0; i<nf; i++) { + free(fnames[i]); + free(names[i]); + free(comment[i]); + free(desc[i]); + } + free(fnames); + free(names); + free(comment); + free(desc); + free(sizes); + delwin(pkg_win); + } + + /* Now we should have an array with indices of filenames that are not */ + /* packages, say a[0..k), 0<=k<=n, and the filenames itself */ + /* remove the non-packages from the array */ + + i=0; + p=0; + while (i+p < nf) { + if ((i+p == a[p]) && (p<j)) { + free(fnames[i+p]); + free(names[i+p]); + free(comment[i+p]); + free(desc[i+p]); + p++; + } else { + fnames[i] = fnames[i+p]; + names[i] = names[i+p]; + comment[i] = comment[i+p]; + desc[i] = desc[i+p]; + sizes[i] = sizes[i+p]; + i++; + } + } + nf = nf - j; + free(a); + + o_pkg[0] = '0'; + pkg_obj = NewListObj(pkg_win, "To be installed", names, o_pkg, + 1, 2, LINES-11, COLS-50, nf); + AddObj(&obj, LISTOBJ, (void *) pkg_obj); + + o_pkgi[0] = '0'; + pkgi_obj = NewListObj(pkg_win, "Already Installed", p_inf.name, o_pkgi, + 1, COLS-45, LINES-11, COLS-50, p_inf.Nitems); + AddObj(&obj, LISTOBJ, (void *) pkgi_obj); + + o_installbut = FALSE; + installbut_obj = NewButtonObj(pkg_win, "Install marked", &o_installbut, + LINES-8, (COLS-12)/2 - 22); + AddObj(&obj, BUTTONOBJ, (void *) installbut_obj); + + o_cancelbut = FALSE; + cancelbut_obj = NewButtonObj(pkg_win, "Cancel", &o_cancelbut, + LINES-8, (COLS-12)/2 + 2); + AddObj(&obj, BUTTONOBJ, (void *) cancelbut_obj); + + /* print total_marked in window */ + wmove(pkg_win, LINES-9, 2); + wattrset(pkg_win, dialog_attr); + waddstr(pkg_win, "Total marked = 0 kB"); + total_marked = 0; + + recalc = FALSE; + quit = FALSE; + install = FALSE; + while (!quit) { + use_helpfile(INSTALL_HLP); + switch(PollObj(&obj)) { + case SEL_CR: + /* first move back one list object */ + if (obj->prev) obj=obj->prev; + + if ((ListObj *) obj->obj == pkg_obj) { + dialog_notify(comment[pkg_obj->sel]); + } + if ((ListObj *) obj->obj == pkgi_obj) { + dialog_notify(p_inf.comment[pkgi_obj->sel]); + } + break; + case SEL_BUTTON: + if (o_installbut) { + install = TRUE; + quit = TRUE; + } + if (o_cancelbut) { + quit = TRUE; + } + break; + case SEL_ESC: + quit = TRUE; + break; + case ' ': + if ((ListObj *) obj->obj == pkg_obj) { + MarkCurrentListObj(pkg_obj); + } + recalc = TRUE; + wrefresh(pkg_win); + break; + case '*': + if ((ListObj *) obj->obj == pkg_obj) { + MarkAllListObj(pkg_obj); + } + recalc = TRUE; + break; + case '-': + if ((ListObj *) obj->obj == pkg_obj) { + UnMarkAllListObj(pkg_obj); + } + recalc = TRUE; + break; + case KEY_F(1): + display_helpfile(); + break; + case KEY_F(2): + if ((ListObj *) obj->obj == pkg_obj) { + dialog_notify(desc[pkg_obj->sel]); + } + if ((ListObj *) obj->obj == pkgi_obj) { + dialog_notify(p_inf.description[pkgi_obj->sel]); + } + break; + } + if (recalc) { + total_marked = 0; + for (i=0; i<nf; i++) { + if (pkg_obj->seld[i]) { + total_marked += sizes[i]; + } + } + recalc = FALSE; + /* print total_marked in window */ + wmove(pkg_win, LINES-9, 2); + wattrset(pkg_win, dialog_attr); + sprintf(msg, "Total marked = %6ld kB", (long) (total_marked / 1024)); + waddstr(pkg_win, msg); + wrefresh(pkg_win); + } + } + + if (install) { + /* check if any of the packages marked for installation are */ + /* already installed */ + i=0; + n=0; + while (i < nf) { + if ((pkg_obj->seld[i]) && (already_installed(names[i+p]))) { + /* popup a warning and remove the package from the */ + /* packages that are going to be installed */ + sprintf(msg, " The following package is already installed:\n %s (%s)\n", + names[i], fnames[i]); + strcat(msg, " This package will be skipped\n"); + strcat(msg, " If you want to install it anyway, remove it first"); + dialog_notify(msg); + pkg_obj->seld[i] = FALSE; + } + if (pkg_obj->seld[i]) n++; /* count selected packages */ + i++; + } + /* now install whatever is left */ + for (i=0; i<nf; i++) { + if (pkg_obj->seld[i]) { + dialog_gauge("Installing packages:", names[i], LINES/2-3, + COLS/2-30, 7, 60, (int) ((float) i/n*100)); + install_package(fnames[i]); + } + } + if (n>0) get_pkginfo(); + } + + /* clean up */ + for (i=0; i<nf; i++) { + free(fnames[i]); + free(names[i]); + free(comment[i]); + free(desc[i]); + } + free(fnames); + free(names); + free(comment); + free(desc); + free(sizes); + DelObj(obj); + use_helpfile(NULL); + use_helpline(NULL); + delwin(pkg_win); + + return; +} /* install_batch() */ + +void +run_menu(void) +/* + * Desc: display/choose from menu + */ +{ + int quit_pkg, sel, ch=0, sc=0; + char selection[30]; + unsigned char *pkg_menu[] = { + "1. View installed", "Overview of the installed packages", + "2. Delete installed", "Delete an installed package", + "3. Install packages", "Install one or more packages", + "4. Quit", "Leave the program", + }; + + quit_pkg = FALSE; + while (!quit_pkg) { + use_helpline("F1=help, use arrow-keys or digit to select option and press enter"); + use_helpfile(MAIN_HLP); + if (dialog_menu("Package Manager", "Choose one of the options", + LINES, COLS, 4, 4, pkg_menu, selection, &ch, &sc)) { + quit_pkg = TRUE; + } else { + sel = atoi(selection); + switch(sel) { + case 1: /* View installed packages */ + view_installed(); + break; + case 2: /* Delete installed package */ + delete_installed(); + break; + case 3: /* Install multiple packages */ + install_batch(); + break; + case 4: /* Quit */ + quit_pkg = TRUE; + break; + } + } + } + + return; +} /* run_menu() */ diff --git a/usr.sbin/pkg_manage/version.c b/usr.sbin/pkg_manage/version.c new file mode 100644 index 0000000..b738e81 --- /dev/null +++ b/usr.sbin/pkg_manage/version.c @@ -0,0 +1 @@ +char version[] = "pkg_manage version 1.0"; |