summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1995-04-21 10:05:46 +0000
committerjkh <jkh@FreeBSD.org>1995-04-21 10:05:46 +0000
commit1f6fa4c9ec95068d3ca4fcbea6bf82fa43431851 (patch)
tree20b76779594f5b70ab0711ff6fb02e2437d8ee27
parent63dadcab7d7b8eb9e20ea5abd48532b093e82632 (diff)
downloadFreeBSD-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/CHANGES7
-rw-r--r--usr.sbin/pkg_manage/Makefile14
-rw-r--r--usr.sbin/pkg_manage/TODO87
-rw-r--r--usr.sbin/pkg_manage/pkg_main.c49
-rw-r--r--usr.sbin/pkg_manage/pkg_manage.15
-rw-r--r--usr.sbin/pkg_manage/pkg_manage.c597
-rw-r--r--usr.sbin/pkg_manage/pkg_manage.h41
-rw-r--r--usr.sbin/pkg_manage/pkg_ui.c496
-rw-r--r--usr.sbin/pkg_manage/version.c1
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";
OpenPOWER on IntegriCloud