Annotation of othersrc/dist/cdk/demos/vinstall.c, revision 1.2
1.1 garbled 1: #include <cdk.h>
2:
3: #ifdef HAVE_XCURSES
4: char *XCursesProgramName="vinstall";
5: #endif
6:
7: /*
8: * Written by: Mike Glover
9: * Purpose:
10: * This is a fairly basic install interface.
11: */
12:
13: /* Declare global types and prototypes. */
14: char *FPUsage = "-f filename [-s source directory] [-d destination directory] [-t title] [-o Output file] [-q]";
15: typedef enum {vCanNotOpenSource,
16: vCanNotOpenDest,
17: vOK
18: } ECopyFile;
19: ECopyFile copyFile (CDKSCREEN *cdkScreen, char *src, char *dest);
20: int verifyDirectory (CDKSCREEN *screen, char *directory);
21:
22: int main (int argc, char **argv)
23: {
24: /* Declare variables. */
25: WINDOW *cursesWin = 0;
26: CDKSCREEN *cdkScreen = 0;
27: CDKSWINDOW *installOutput = 0;
28: CDKENTRY *sourceEntry = 0;
29: CDKENTRY *destEntry = 0;
30: CDKLABEL *titleWin = 0;
31: CDKHISTOGRAM *progressBar = 0;
32: char *sourcePath = 0;
33: char *destPath = 0;
34: char *sourceDir = 0;
35: char *destDir = 0;
36: char *filename = 0;
37: char *title = 0;
38: char *output = 0;
39: int quiet = FALSE;
40: int errors = 0;
41: int sWindowHeight = 0;
42: char *titleMessage[10], *fileList[2000], *mesg[20];
43: char oldPath[512], newPath[512], temp[2000];
44: char **files;
45: int count, chunks, ret, x;
46:
47: /* Parse up the command line. */
48: while (1)
49: {
50: ret = getopt (argc, argv, "d:s:f:t:o:q");
51: if (ret == -1)
52: {
53: break;
54: }
55: switch (ret)
56: {
57: case 's' :
58: sourcePath = strdup (optarg);
59: break;
60:
61: case 'd' :
62: destPath = strdup (optarg);
63: break;
64:
65: case 'f' :
66: filename = strdup (optarg);
67: break;
68:
69: case 't' :
70: title = strdup (optarg);
71: break;
72:
73: case 'o' :
74: output = strdup (optarg);
75: break;
76:
77: case 'q' :
78: quiet = TRUE;
79: break;
80: }
81: }
82:
83: /* Make sure have everything we need. */
84: if (filename == 0)
85: {
86: fprintf (stderr, "Usage: %s %s\n", argv[0], FPUsage);
1.2 ! wiz 87: exit (1);
1.1 garbled 88: }
89:
90: /* Open the file list file and read it in. */
91: count = readFile (filename, fileList, 2000);
92: if (count == 0)
93: {
94: fprintf (stderr, "%s: Input filename <%s> is empty.\n", argv[0], filename);
1.2 ! wiz 95: exit (1);
1.1 garbled 96: }
97:
98: /*
99: * Cycle through what was given to us and save it.
100: */
101: for (x=0; x < count; x++)
102: {
103: /* Strip white space from the line. */
104: stripWhiteSpace (vBOTH, fileList[x]);
105: }
106:
107: /* Set up CDK. */
108: cursesWin = initscr();
109: cdkScreen = initCDKScreen (cursesWin);
110:
111: /* Start color. */
112: initCDKColor();
113:
114: /* Create the title label. */
115: titleMessage[0] = "<C></32/B><#HL(30)>";
116: if (title == 0)
117: {
118: sprintf (temp, "<C></32/B>CDK Installer");
119: }
120: else
121: {
122: sprintf (temp, "<C></32/B>%s", title);
123: }
124: titleMessage[1] = copyChar (temp);
125: titleMessage[2] = "<C></32/B><#HL(30)>";
126: titleWin = newCDKLabel (cdkScreen, CENTER, TOP,
127: titleMessage, 3, FALSE, FALSE);
128: freeChar (titleMessage[1]);
129:
130: /* Allow them to change the install directory. */
131: if (sourcePath == 0)
132: {
133: sourceEntry = newCDKEntry (cdkScreen, CENTER, 8,
134: 0, "Source Directory: ",
135: A_NORMAL, '.', vMIXED,
136: 40, 0, 256, TRUE, FALSE);
137: }
138: if (destPath == 0)
139: {
140: destEntry = newCDKEntry (cdkScreen, CENTER, 11,
141: 0, "Destination Directory: ", A_NORMAL,
142: '.', vMIXED, 40, 0, 256, TRUE, FALSE);
143: }
144:
145: /* Get the source install path. */
146: if (sourceEntry != 0)
147: {
148: drawCDKScreen (cdkScreen);
149: sourceDir = copyChar (activateCDKEntry (sourceEntry, 0));
150: }
151: else
152: {
153: sourceDir = copyChar (sourcePath);
154: }
155:
156: /* Get the destination install path. */
157: if (destEntry != 0)
158: {
159: drawCDKScreen (cdkScreen);
160: destDir = copyChar (activateCDKEntry (destEntry, 0));
161: }
162: else
163: {
164: destDir = copyChar (destPath);
165: }
166:
167: /* Destroy the path entry fields. */
168: if (sourceEntry != 0)
169: {
170: destroyCDKEntry (sourceEntry);
171: }
172: if (destEntry != 0)
173: {
174: destroyCDKEntry (destEntry);
175: }
176:
177: /*
178: * Verify that the source directory is valid.
179: */
180: if (verifyDirectory (cdkScreen, sourceDir) != 0)
181: {
182: /* Clean up and leave. */
183: freeChar (destDir);
184: freeChar (sourceDir);
185: destroyCDKLabel (titleWin);
186: destroyCDKScreen (cdkScreen);
187: endCDK();
188:
189: /* Clean up the file list information. */
190: for (x=0; x < count; x++)
191: {
192: freeChar (fileList[x]);
193: }
1.2 ! wiz 194: exit (1);
1.1 garbled 195: }
196:
197: /*
198: * Verify that the source directory is valid.
199: */
200: if (verifyDirectory (cdkScreen, destDir) != 0)
201: {
202: /* Clean up and leave. */
203: freeChar (destDir);
204: freeChar (sourceDir);
205: destroyCDKLabel (titleWin);
206: destroyCDKScreen (cdkScreen);
207: endCDK();
208:
209: /* Clean up the file list information */
210: for (x=0; x < count; x++)
211: {
212: freeChar (fileList[x]);
213: }
1.2 ! wiz 214: exit (2);
1.1 garbled 215: }
216:
217: /* Create the histogram. */
218: progressBar = newCDKHistogram (cdkScreen, CENTER, 5,
219: 1, 0, HORIZONTAL,
220: "<C></56/B>Install Progress",
221: TRUE, FALSE);
222:
223: /* Set the top left/right characters of the histogram.*/
224: setCDKHistogramLLChar (progressBar, ACS_LTEE);
225: setCDKHistogramLRChar (progressBar, ACS_RTEE);
226:
227: /* Set the initial value of the histogram. */
228: setCDKHistogram (progressBar, vPERCENT, TOP, A_BOLD,
229: 1, count, 1,
230: COLOR_PAIR (24) | A_REVERSE | ' ',
231: TRUE);
232:
233: /* Determine the height of the scrolling window. */
234: if (LINES >= 16)
235: {
236: sWindowHeight = LINES - 8;
237: }
238: else
239: {
240: sWindowHeight = 3;
241: }
242:
243: /* Create the scrolling window. */
244: installOutput = newCDKSwindow (cdkScreen, CENTER, BOTTOM,
245: sWindowHeight, 0,
246: "<C></56/B>Install Results",
247: 2000, TRUE, FALSE);
248:
249: /* Set the top left/right characters of the scrolling window.*/
250: setCDKSwindowULChar (installOutput, ACS_LTEE);
251: setCDKSwindowURChar (installOutput, ACS_RTEE);
252:
253: /* Draw the screen. */
254: drawCDKScreen (cdkScreen);
255: wrefresh (progressBar->win);
256: wrefresh (installOutput->win);
257:
258: /* Start copying the files. */
259: for (x=0; x < count; x++)
260: {
261: /*
262: * If the 'file' list file has 2 columns, the first is
263: * the source filename, the second being the destination
264: * filename.
265: */
266: files = CDKsplitString (fileList[x], ' ');
267: chunks = CDKcountStrings (files);
268: if (chunks == 2)
269: {
270: /* Create the correct paths. */
271: sprintf (oldPath, "%s/%s", sourceDir, files[0]);
272: sprintf (newPath, "%s/%s", destDir, files[1]);
273: }
274: else
275: {
276: /* Create the correct paths. */
277: sprintf (oldPath, "%s/%s", sourceDir, fileList[x]);
278: sprintf (newPath, "%s/%s", destDir, fileList[x]);
279: }
280: CDKfreeStrings(files);
281:
282: /* Copy the file from the source to the destination. */
283: ret = copyFile (cdkScreen, oldPath, newPath);
284: if (ret == vCanNotOpenSource)
285: {
286: sprintf (temp, "</16>Error: Can not open source file %s<!16>", oldPath);
287: errors++;
288: }
289: else if (ret == vCanNotOpenDest)
290: {
291: sprintf (temp, "</16>Error: Can not open destination file %s<!16>", newPath);
292: errors++;
293: }
294: else
295: {
296: sprintf (temp, "</24>%s -> %s", oldPath, newPath);
297: }
298:
299: /* Add the message to the scrolling window. */
300: addCDKSwindow (installOutput, temp, BOTTOM);
301: drawCDKSwindow (installOutput, ObjOf(installOutput)->box);
302:
303: /* Update the histogram. */
304: setCDKHistogram (progressBar, vPERCENT, TOP, A_BOLD,
305: 1, count, x+1,
306: COLOR_PAIR (24) | A_REVERSE | ' ',
307: TRUE);
308:
309: /* Update the screen. */
310: drawCDKHistogram (progressBar, TRUE);
311:
312: wrefresh (progressBar->win);
313: wrefresh (installOutput->win);
314: }
315:
316: /*
317: * If there were errors, inform the user and allow them to look at the
318: * errors in the scrolling window.
319: */
320: if (errors != 0)
321: {
322: /* Create the information for the dialog box. */
323: char *buttons[] = {"Look At Errors Now", "Save Output To A File", "Ignore Errors"};
324: mesg[0] = "<C>There were errors in the installation.";
325: mesg[1] = "<C>If you want, you may scroll through the";
326: mesg[2] = "<C>messages of the scrolling window to see";
327: mesg[3] = "<C>what the errors were. If you want to save";
328: mesg[4] = "<C>the output of the window you may press </R>s<!R>";
329: mesg[5] = "<C>while in the window, or you may save the output";
330: mesg[6] = "<C>of the install now and look at the install";
331: mesg[7] = "<C>history at a later date.";
332:
333: /* Popup the dialog box. */
334: ret = popupDialog (cdkScreen, mesg, 8, buttons, 3);
335: if (ret == 0)
336: {
337: activateCDKSwindow (installOutput, 0);
338: }
339: else if (ret == 1)
340: {
341: injectCDKSwindow (installOutput, 's');
342: }
343: }
344: else
345: {
346: /*
347: * If they specified the name of an output file, then save the
348: * results of the installation to that file.
349: */
350: if (output != 0)
351: {
352: dumpCDKSwindow (installOutput, output);
353: }
354: else
355: {
356: /* Ask them if they want to save the output of the scrolling window. */
357: if (quiet == FALSE)
358: {
359: char *buttons[] = {"No", "Yes"};
360: mesg[0] = "<C>Do you want to save the output of the";
361: mesg[1] = "<C>scrolling window to a file?";
362:
363: if (popupDialog (cdkScreen, mesg, 2, buttons, 2) == 1)
364: {
365: injectCDKSwindow (installOutput, 's');
366: }
367: }
368: }
369: }
370:
371: /* Clean up. */
372: destroyCDKLabel (titleWin);
373: destroyCDKHistogram (progressBar);
374: destroyCDKSwindow (installOutput);
375: destroyCDKScreen (cdkScreen);
376: endCDK();
377:
378: /* Clean up the file list. */
379: for (x=0; x < count; x++)
380: {
381: freeChar (fileList[x]);
382: }
383: exit (0);
384: }
385:
386: /*
387: * This copies a file from one place to another. (tried rename
388: * library call, but it is equivalent to mv)
389: */
390: ECopyFile copyFile (CDKSCREEN *cdkScreen GCC_UNUSED, char *src, char *dest)
391: {
392: char command[2000];
393: FILE *fd;
394:
395: /* Make sure we can open the source file. */
396: if ((fd = fopen (src, "r")) == 0)
397: {
398: return vCanNotOpenSource;
399: }
400: fclose (fd);
401:
402: /*
403: * Remove the destination file first, just in case it already exists.
404: * This allows us to check if we can write to the desintation file.
405: */
406: remove (dest);
407:
408: /* Try to open the destination. */
409: if ((fd = fopen (dest, "w")) == 0)
410: {
411: return vCanNotOpenDest;
412: }
413: fclose (fd);
414:
415: /*
416: * Copy the file. There has to be a better way to do this. I
417: * tried rename and link but they both have the same limitation
418: * as the 'mv' command that you can not move across partitions.
419: * Quite limiting in an install binary.
420: */
421: sprintf (command, "rm -f %s; cp %s %s; chmod 444 %s", dest, src, dest, dest);
422: system (command);
423: return vOK;
424: }
425:
426: /*
427: * This makes sure that the directory given exists. If it
428: * doesn't then it will make it.
429: * THINK
430: */
431: int verifyDirectory (CDKSCREEN *cdkScreen, char *directory)
432: {
433: char *buttons[] = {"Yes", "No"};
434: int status = 0;
435: mode_t dirMode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH;
436: struct stat fileStat;
437: char *mesg[10];
438: char *error[10];
439: char temp[200];
440:
441: /* Stat the directory. */
442: if (lstat (directory, &fileStat) != 0)
443: {
444: /* The directory does not exist. */
445: if (errno == ENOENT)
446: {
447: /* Create the question. */
448: mesg[0] = "<C>The directory ";
449: sprintf (temp, "<C>%s", directory);
450: mesg[1] = copyChar (temp);
451: mesg[2] = "<C>Does not exist. Do you want to";
452: mesg[3] = "<C>create it?";
453:
454: /* Ask them if they want to create the directory. */
455: if (popupDialog (cdkScreen, mesg, 4, buttons, 2) == 0)
456: {
457: /* Create the directory. */
458: if (mkdir (directory, dirMode) != 0)
459: {
460: /* Create the error message. */
461: error[0] = "<C>Could not create the directory";
462: sprintf (temp, "<C>%s", directory);
463: error[1] = copyChar (temp);
464:
465: #ifdef HAVE_STRERROR
466: sprintf (temp, "<C>%s", strerror (errno));
467: #else
468: sprintf (temp, "<C>Check the permissions and try again.");
469: #endif
470: error[2] = copyChar (temp);
471:
472: /* Pop up the error message. */
473: popupLabel (cdkScreen, error, 3);
474:
475: /* Clean up and set the error status. */
476: freeChar (error[1]);
477: freeChar (error[2]);
478: status = -1;
479: }
480: }
481: else
482: {
483: /* Create the message. */
484: error[0] = "<C>Installation aborted.";
485:
486: /* Pop up the error message. */
487: popupLabel (cdkScreen, error, 1);
488:
489: /* Set the exit status. */
490: status = -1;
491: }
492:
493: /* Clean up. */
494: freeChar (mesg[1]);
495: }
496: }
497: return status;
498: }
CVSweb <webmaster@jp.NetBSD.org>