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>