This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/cdk-5.0-20161210/demos/vinstall.c
2017-03-20 21:40:32 +10:00

509 lines
12 KiB
C

/* $Id: vinstall.c,v 1.21 2016/12/04 15:22:16 tom Exp $ */
#include <cdk_test.h>
#ifdef HAVE_XCURSES
char *XCursesProgramName = "vinstall";
#endif
/*
* Written by: Mike Glover
* Purpose:
* This is a fairly basic install interface.
*/
/* Declare global types and prototypes. */
static const char *FPUsage = "-f filename [-s source directory] [-d destination directory] [-t title] [-o Output file] [-q]";
typedef enum
{
vCanNotOpenSource,
vCanNotOpenDest,
vOK
}
ECopyFile;
static ECopyFile copyFile (CDKSCREEN *cdkScreen, char *src, char *dest);
static int verifyDirectory (CDKSCREEN *screen, char *directory);
int main (int argc, char **argv)
{
/* *INDENT-EQLS* */
CDKSCREEN *cdkScreen = 0;
CDKSWINDOW *installOutput = 0;
CDKENTRY *sourceEntry = 0;
CDKENTRY *destEntry = 0;
CDKLABEL *titleWin = 0;
CDKHISTOGRAM *progressBar = 0;
char *sourcePath = 0;
char *destPath = 0;
char *sourceDir = 0;
char *destDir = 0;
char *filename = 0;
char *title = 0;
char *output = 0;
int quiet = FALSE;
int errors = 0;
int sWindowHeight = 0;
char *titleMessage[10];
char **fileList = 0;
const char *mesg[20];
char oldPath[512], newPath[512], temp[2000];
int count, ret, x;
/* Parse up the command line. */
while (1)
{
ret = getopt (argc, argv, "d:s:f:t:o:q");
if (ret == -1)
{
break;
}
switch (ret)
{
case 's':
sourcePath = strdup (optarg);
break;
case 'd':
destPath = strdup (optarg);
break;
case 'f':
filename = strdup (optarg);
break;
case 't':
title = strdup (optarg);
break;
case 'o':
output = strdup (optarg);
break;
case 'q':
quiet = TRUE;
break;
}
}
/* Make sure have everything we need. */
if (filename == 0)
{
fprintf (stderr, "Usage: %s %s\n", argv[0], FPUsage);
ExitProgram (EXIT_FAILURE);
}
/* Open the file list file and read it in. */
count = CDKreadFile (filename, &fileList);
if (count == 0)
{
fprintf (stderr, "%s: Input filename <%s> is empty.\n", argv[0], filename);
ExitProgram (EXIT_FAILURE);
}
/*
* Cycle through what was given to us and save it.
*/
for (x = 0; x < count; x++)
{
/* Strip white space from the line. */
stripWhiteSpace (vBOTH, fileList[x]);
}
cdkScreen = initCDKScreen (NULL);
/* Start color. */
initCDKColor ();
/* Create the title label. */
titleMessage[0] = copyChar ("<C></32/B><#HL(30)>");
if (title == 0)
{
sprintf (temp, "<C></32/B>CDK Installer");
}
else
{
sprintf (temp, "<C></32/B>%.256s", title);
}
titleMessage[1] = copyChar (temp);
titleMessage[2] = copyChar ("<C></32/B><#HL(30)>");
titleWin = newCDKLabel (cdkScreen, CENTER, TOP,
(CDK_CSTRING2)titleMessage, 3,
FALSE, FALSE);
freeCharList (titleMessage, 3);
/* Allow them to change the install directory. */
if (sourcePath == 0)
{
sourceEntry = newCDKEntry (cdkScreen, CENTER, 8,
0, "Source Directory :",
A_NORMAL, '.', vMIXED,
40, 0, 256, TRUE, FALSE);
}
if (destPath == 0)
{
destEntry = newCDKEntry (cdkScreen, CENTER, 11,
0, "Destination Directory:", A_NORMAL,
'.', vMIXED, 40, 0, 256, TRUE, FALSE);
}
/* Get the source install path. */
if (sourceEntry != 0)
{
drawCDKScreen (cdkScreen);
sourceDir = copyChar (activateCDKEntry (sourceEntry, 0));
}
else
{
sourceDir = copyChar (sourcePath);
}
/* Get the destination install path. */
if (destEntry != 0)
{
drawCDKScreen (cdkScreen);
destDir = copyChar (activateCDKEntry (destEntry, 0));
}
else
{
destDir = copyChar (destPath);
}
/* Destroy the path entry fields. */
if (sourceEntry != 0)
{
destroyCDKEntry (sourceEntry);
}
if (destEntry != 0)
{
destroyCDKEntry (destEntry);
}
/*
* Verify that the source directory is valid.
*/
if (verifyDirectory (cdkScreen, sourceDir) != 0)
{
/* Clean up and leave. */
freeChar (destDir);
freeChar (sourceDir);
destroyCDKLabel (titleWin);
destroyCDKScreen (cdkScreen);
endCDK ();
ExitProgram (EXIT_FAILURE);
}
/*
* Verify that the source directory is valid.
*/
if (verifyDirectory (cdkScreen, destDir) != 0)
{
/* Clean up and leave. */
freeChar (destDir);
freeChar (sourceDir);
destroyCDKLabel (titleWin);
destroyCDKScreen (cdkScreen);
endCDK ();
ExitProgram (EXIT_FAILURE);
}
/* Create the histogram. */
progressBar = newCDKHistogram (cdkScreen, CENTER, 5,
3, 0, HORIZONTAL,
"<C></56/B>Install Progress",
TRUE, FALSE);
/* Set the top left/right characters of the histogram. */
setCDKHistogramLLChar (progressBar, ACS_LTEE);
setCDKHistogramLRChar (progressBar, ACS_RTEE);
/* Set the initial value of the histogram. */
setCDKHistogram (progressBar, vPERCENT, TOP, A_BOLD,
1, count, 1,
COLOR_PAIR (24) | A_REVERSE | ' ',
TRUE);
/* Determine the height of the scrolling window. */
if (LINES >= 16)
{
sWindowHeight = LINES - 13;
}
else
{
sWindowHeight = 3;
}
/* Create the scrolling window. */
installOutput = newCDKSwindow (cdkScreen, CENTER, BOTTOM,
sWindowHeight, 0,
"<C></56/B>Install Results",
2000, TRUE, FALSE);
/* Set the top left/right characters of the scrolling window. */
setCDKSwindowULChar (installOutput, ACS_LTEE);
setCDKSwindowURChar (installOutput, ACS_RTEE);
/* Draw the screen. */
drawCDKScreen (cdkScreen);
/* Start copying the files. */
for (x = 0; x < count; x++)
{
char **files;
int chunks;
/*
* If the 'file' list file has 2 columns, the first is
* the source filename, the second being the destination
* filename.
*/
files = CDKsplitString (fileList[x], ' ');
chunks = (int)CDKcountStrings ((CDK_CSTRING2)files);
if (chunks == 2)
{
/* Create the correct paths. */
sprintf (oldPath, "%s/%s", sourceDir, files[0]);
sprintf (newPath, "%s/%s", destDir, files[1]);
}
else
{
/* Create the correct paths. */
sprintf (oldPath, "%s/%s", sourceDir, fileList[x]);
sprintf (newPath, "%s/%s", destDir, fileList[x]);
}
CDKfreeStrings (files);
/* Copy the file from the source to the destination. */
ret = copyFile (cdkScreen, oldPath, newPath);
if (ret == vCanNotOpenSource)
{
sprintf (temp,
"</16>Error: Can not open source file \"%.256s\"<!16>", oldPath);
errors++;
}
else if (ret == vCanNotOpenDest)
{
sprintf (temp,
"</16>Error: Can not open destination file \"%.256s\"<!16>", newPath);
errors++;
}
else
{
sprintf (temp, "</24>%.256s -> %.256s", oldPath, newPath);
}
/* Add the message to the scrolling window. */
addCDKSwindow (installOutput, temp, BOTTOM);
drawCDKSwindow (installOutput, ObjOf (installOutput)->box);
/* Update the histogram. */
setCDKHistogram (progressBar, vPERCENT, TOP, A_BOLD,
1, count, x + 1,
COLOR_PAIR (24) | A_REVERSE | ' ',
TRUE);
/* Update the screen. */
drawCDKHistogram (progressBar, TRUE);
}
/*
* If there were errors, inform the user and allow them to look at the
* errors in the scrolling window.
*/
if (errors != 0)
{
/* Create the information for the dialog box. */
const char *buttons[] =
{
"Look At Errors Now",
"Save Output To A File",
"Ignore Errors"
};
mesg[0] = "<C>There were errors in the installation.";
mesg[1] = "<C>If you want, you may scroll through the";
mesg[2] = "<C>messages of the scrolling window to see";
mesg[3] = "<C>what the errors were. If you want to save";
mesg[4] = "<C>the output of the window you may press </R>s<!R>";
mesg[5] = "<C>while in the window, or you may save the output";
mesg[6] = "<C>of the install now and look at the install";
mesg[7] = "<C>history at a later date.";
/* Popup the dialog box. */
ret = popupDialog (cdkScreen,
(CDK_CSTRING2)mesg, 8,
(CDK_CSTRING2)buttons, 3);
if (ret == 0)
{
activateCDKSwindow (installOutput, 0);
}
else if (ret == 1)
{
(void)injectCDKSwindow (installOutput, 's');
}
}
else
{
/*
* If they specified the name of an output file, then save the
* results of the installation to that file.
*/
if (output != 0)
{
dumpCDKSwindow (installOutput, output);
}
else
{
/* Ask them if they want to save the output of the scrolling window. */
if (quiet == FALSE)
{
const char *buttons[] =
{
"No",
"Yes"
};
mesg[0] = "<C>Do you want to save the output of the";
mesg[1] = "<C>scrolling window to a file?";
if (popupDialog (cdkScreen,
(CDK_CSTRING2)mesg, 2,
(CDK_CSTRING2)buttons, 2) == 1)
{
(void)injectCDKSwindow (installOutput, 's');
}
}
}
}
/* Clean up. */
destroyCDKLabel (titleWin);
destroyCDKHistogram (progressBar);
destroyCDKSwindow (installOutput);
destroyCDKScreen (cdkScreen);
endCDK ();
ExitProgram (EXIT_SUCCESS);
}
/*
* This copies a file from one place to another. (tried rename
* library call, but it is equivalent to mv)
*/
static ECopyFile copyFile (CDKSCREEN *cdkScreen GCC_UNUSED, char *src, char *dest)
{
char command[2000];
FILE *fd;
/* Make sure we can open the source file. */
if ((fd = fopen (src, "r")) == 0)
{
return vCanNotOpenSource;
}
fclose (fd);
/*
* Remove the destination file first, just in case it already exists.
* This allows us to check if we can write to the desintation file.
*/
sprintf (command, "rm -f %s", dest);
system (command);
/* Try to open the destination. */
if ((fd = fopen (dest, "w")) == 0)
{
return vCanNotOpenDest;
}
fclose (fd);
/*
* Copy the file. There has to be a better way to do this. I
* tried rename and link but they both have the same limitation
* as the 'mv' command that you can not move across partitions.
* Quite limiting in an install binary.
*/
sprintf (command, "rm -f %s; cp %s %s; chmod 444 %s", dest, src, dest, dest);
system (command);
return vOK;
}
/*
* This makes sure that the directory given exists. If it
* doesn't then it will make it.
* THINK
*/
static int verifyDirectory (CDKSCREEN *cdkScreen, char *directory)
{
int status = 0;
#if !defined (__MINGW32__)
mode_t dirMode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH;
#endif
struct stat fileStat;
char temp[512];
/* Stat the directory. */
if (lstat (directory, &fileStat) != 0)
{
/* The directory does not exist. */
if (errno == ENOENT)
{
const char *buttons[] =
{
"Yes",
"No"
};
const char *mesg[10];
char *error[10];
/* Create the question. */
mesg[0] = "<C>The directory ";
sprintf (temp, "<C>%.256s", directory);
mesg[1] = temp;
mesg[2] = "<C>Does not exist. Do you want to";
mesg[3] = "<C>create it?";
/* Ask them if they want to create the directory. */
if (popupDialog (cdkScreen,
(CDK_CSTRING2)mesg, 4,
(CDK_CSTRING2)buttons, 2) == 0)
{
/* Create the directory. */
#if defined (__MINGW32__)
if (mkdir (directory) != 0)
#else
if (mkdir (directory, dirMode) != 0)
#endif
{
/* Create the error message. */
error[0] = copyChar ("<C>Could not create the directory");
sprintf (temp, "<C>%.256s", directory);
error[1] = copyChar (temp);
#ifdef HAVE_STRERROR
sprintf (temp, "<C>%.256s", strerror (errno));
#else
sprintf (temp, "<C>Check the permissions and try again.");
#endif
error[2] = copyChar (temp);
/* Pop up the error message. */
popupLabel (cdkScreen, (CDK_CSTRING2)error, 3);
freeCharList (error, 3);
status = -1;
}
}
else
{
/* Create the message. */
error[0] = copyChar ("<C>Installation aborted.");
/* Pop up the error message. */
popupLabel (cdkScreen, (CDK_CSTRING2)error, 1);
freeCharList (error, 1);
status = -1;
}
}
}
return status;
}