freebsd-dev/usr.sbin/pkg_manage/pkg_manage.c

543 lines
12 KiB
C
Raw Normal View History

/***************************************************************
*
* Program: pkg_manage
* Author: Marc van Kempen
* Desc: Add, delete packages with the pkg_* binaries
* Get info about installed packages
* Review about to be installed packages
*
* 1. View installed packages
* 2. Delete installed packages
* 3. View package files
* 4. Install packages files.
*
* Installation and deletion of packages should be previewable
*
*
* 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 <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include "pkg_manage.h"
static PKG_info p_inf;
static int got_info;
/*
* Local prototypes
*/
void run_menu(void);
void get_pkginfo(void);
void FreeMnu(unsigned char **mnu, int n);
void FreeInfo(void);
/*
* Main
*/
void
main(void)
{
init_dialog();
get_pkginfo();
run_menu();
if (got_info)
FreeInfo();
clear();
dialog_update();
end_dialog();
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;
}
void
FreeMnu(unsigned char **mnu, int n)
/*
* Desc: free mnu array
*/
{
int i;
for (i=0; i<n; i++) {
free(mnu[i]);
}
free(mnu);
return;
} /* FreeMnu() */
int
file_exists(char *fname)
/*
* Desc: check if the file <fname> exists (and is readable)
*/
{
FILE *f;
if (strlen(fname) == 0) return(FALSE); /* apparently opening an empty */
/* file for reading succeeds always */
f = fopen(fname, "r");
if (f) {
fclose(f);
return(TRUE);
} else {
return(FALSE);
}
} /* file_exists() */
void
get_pkginfo(void)
{
FILE *f;
char *p;
char prog[512];
struct stat sb;
int i, j, n, lsize;
int newline;
int state;
char *tmp_file;
#define R_NAME 1
#define R_COMMENT 2
#define R_DESC 3
if (got_info)
FreeInfo();
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);
dialog_clear_norefresh();
f = fopen(tmp_file, "r");
if (!f) {
dialog_notify("Could not open temporary file");
goto err1;
}
if (stat(tmp_file, &sb)) { /* stat file to get filesize */
dialog_notify("Could not stat temporary file");
goto err2;
}
if (sb.st_size == 0) {
dialog_notify("No packages info available");
goto err2;
}
/* Allocate a buffer with sufficient space to hold the entire file */
p_inf.buf = (char *) malloc( sb.st_size );
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");
free(p_inf.buf);
err2:
fclose(f);
err1:
got_info = FALSE;
unlink(tmp_file);
free(tmp_file);
return;
}
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) {
n = 1;
} else {
n = 0;
}
while (i--) {
if (*p == '\n') {
if (strncmp(p+1, "Information for", 15) == 0) {
n++;
}
}
p++;
}
/* malloc space for PKG_info */
p_inf.name = (char **) malloc( n * sizeof(char *) );
p_inf.comment = (char **) malloc( n * sizeof(char *) );
p_inf.description = (char **) malloc( n * sizeof(char *) );
p_inf.Nitems = n;
/* parse pkg_info output */
/* use a finite state automate to parse the file */
i = 0;
p = p_inf.buf;
newline = TRUE;
state = R_NAME;
while (*p) {
if (newline) {
switch(state) {
case R_NAME:
if (strncmp(p, "Information for", 15) == 0) {
if (p>p_inf.buf) *(p-1) = '\0';
p_inf.name[i] = (char *) p+16;
while (*p && *p != ':') p++;
if (*p) *p = '\0';
state = R_COMMENT;
}
break;
case R_COMMENT:
if (strncmp(p, "Comment:", 8) == 0) {
while (*p && *p != '\n') p++;
if (*p) p_inf.comment[i] = (char *) p+1;
p++;
while (*p && *p != '\n') p++;
if (*p) *p = '\0';
p++;
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;
state = R_NAME;
i++;
}
break;
}
newline = FALSE;
}
if (*p == '\n') newline = TRUE;
p++;
}
/* build menu entries */
p_inf.mnu = (unsigned char **) malloc( 2 * p_inf.Nitems * sizeof(char *) );
lsize = COLS-30;
j=0;
for (i=0; i<p_inf.Nitems; i++) {
/* tag */
p_inf.mnu[j] = (char *) malloc( lsize );
strncpy(p_inf.mnu[j], p_inf.name[i], lsize-1);
p_inf.mnu[j++][lsize-1] = 0;
/* description */
p_inf.mnu[j] = (char *) malloc( lsize );
strncpy(p_inf.mnu[j], p_inf.comment[i], lsize-1);
p_inf.mnu[j++][lsize-1] = 0;
}
got_info = TRUE;
return;
} /* get_pkginfo() */
int
get_pkg_index(char *selection)
/*
* desc: get the index i, for which p_inf.name[i] == 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;
}
}
return(index);
} /* get_pkg_index() */
void
view_installed(void)
/*
* Desc: View the installed packages
*/
{
int i, quit_view, sc=0, ch=0;
char selection[1024];
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);
}
}
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], 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;
}
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;
} 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;
}
}
}
}
}
use_helpfile(NULL);
use_helpline(NULL);
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");
}
if (fname) free(fname);
use_helpfile(NULL);
use_helpline(NULL);
return;
} /* preview_pkg() */
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;
} 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;
}
}
}
if (fname) free(fname);
use_helpfile(NULL);
use_helpline(NULL);
return;
} /* install_new() */
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. 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;
}
}
return;
} /* run_menu() */