home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / install / printercfg.c < prev    next >
C/C++ Source or Header  |  1997-11-06  |  52KB  |  2,016 lines

  1. /* Text based printer configuration for the RHS install program */
  2. /* Michael Fulbright - 1997                                     */
  3. /*                                                              */
  4. /* Mon Apr 14 1997 - fixed up for inclusion into 4.2 install    */
  5. /* Mon Apr 14 1997 - Erik broke everything -- blame him        */
  6. /*                                                              */
  7. /* Last editted by msf - 11:10 Mon Apr 22 1997                  */
  8.  
  9. #include <alloca.h>
  10. #include <ctype.h>
  11. #include <errno.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <unistd.h>
  16. #include <ctype.h>
  17. #include <fcntl.h>
  18. #include <grp.h>
  19. #include <sys/types.h>
  20. #include <sys/wait.h>
  21. #include <sys/stat.h>
  22.  
  23. #include <newt.h>
  24.  
  25. #include "devices.h"
  26. #include "install.h"
  27. #include "log.h"
  28. #include "printercfg.h"
  29.  
  30. /* db of all entries in the printerdb file */
  31. /* we reallocate as we read entries, so we keep numread and numallocated */
  32. DBEntry **thedb;
  33. int numdb, numdb_alloc;
  34.  
  35. /* root_path is the base of any path we use. During install the actual */
  36. /* system is mounted under something like /mnt, so we have to take this */
  37. /* into account when creating system files for the final, installed sys */
  38. char *root_path;
  39.  
  40. /* keep up with whether we actually accomplished anything or not */
  41. int install_return_code;
  42.  
  43. #define NUM_PAPERSIZES 5
  44. static char *PaperSizes[NUM_PAPERSIZES] = {
  45.   "letter", "legal", "ledger", "a3", "a4" };
  46.  
  47. /* not sure what we're calling these yet */
  48. #define NEXT_LABEL "Next"
  49. #define PREV_LABEL "Previous"
  50.  
  51. /*******************************************/
  52. /* Some useful utility routines come first */
  53. /*******************************************/
  54.  
  55. /* convert the character sequence '\' \n' into a true '\n' */
  56. /* handy for treating a string which contains the continuation char '\' */
  57. static void insert_newlines( char *s ) {
  58.     char *p, *q;
  59.     char *tmp;
  60.     
  61.     if (strlen(s)<2)
  62.     return;
  63.     
  64.     tmp = strdup( s );
  65.     for (p=tmp, q=s; *(p+1); p++, q++)
  66.     if (*p == '\\' && *(p+1)=='n') {
  67.         *q = '\n';
  68.         p++;
  69.     } else
  70.         *q = *p;
  71.     
  72.     *q = '\000';
  73.     free(tmp);
  74. }
  75.     
  76.  
  77. /* clean up that string */
  78. static void trim_whitespace( char *s ) {
  79.     char *f, *l, *p, *q;
  80.  
  81.     if (!(*s))
  82.     return;
  83.     
  84.     for (f=s; *f && isspace(*f); f++) ;
  85.  
  86.     if (!*f) {
  87.     *s = '\0';
  88.     return;
  89.     }
  90.     
  91.     for (l=f+strlen(f)-1; isspace(*l) ; l--)
  92.     *l = '\0';
  93.     
  94.     q = s, p = f;
  95.     while (*p)
  96.     *q++ = *p++;
  97.     
  98.     *q = '\0';
  99. }
  100.  
  101.  
  102. /* set all values of a PCEntry to sane values */
  103. void initialize_PCEntry( PCEntry *pcentry ) {
  104.     pcentry->Queue=NULL;
  105.     pcentry->SpoolDir=NULL;
  106.     pcentry->Device=NULL;
  107.     pcentry->IF=NULL;
  108.     pcentry->AF=NULL;
  109.     pcentry->Type=NULL;
  110.     pcentry->db=NULL;
  111.     pcentry->Resolution=NULL;
  112.     pcentry->PaperSize=NULL;
  113.     pcentry->AutoEOF=NULL;
  114.     pcentry->BitsPerPixel=NULL;
  115.     pcentry->CRLF=NULL;
  116.     pcentry->RevPages=NULL;
  117.     pcentry->RemoteHost=NULL;
  118.     pcentry->RemoteQueue=NULL;
  119.     pcentry->SMBHost=NULL;
  120.     pcentry->SMBHostIP=NULL;
  121.     pcentry->SMBShare=NULL;
  122.     pcentry->SMBUser=NULL;
  123.     pcentry->SMBPasswd=NULL;
  124. }
  125.  
  126. /* allocate a new PrintCap Entry */
  127. static PCEntry *new_PCEntry() {
  128.     PCEntry *pcentry;
  129.     
  130.     pcentry = (PCEntry *) malloc(sizeof(PCEntry));
  131.     initialize_PCEntry( pcentry );
  132.     return pcentry;
  133. }
  134.  
  135. /* duplicate an existing PrintCap Entry */
  136. /* all strings are REALLOCATED, so new PCEntry is not dependent on original */
  137. static PCEntry *dup_PCEntry( PCEntry *orig ) {
  138.     PCEntry *pcentry;
  139.     
  140.     pcentry = new_PCEntry();
  141.     
  142.     if (orig->Queue)
  143.     pcentry->Queue=strdup(orig->Queue);
  144.     if (orig->SpoolDir)
  145.     pcentry->SpoolDir=strdup(orig->SpoolDir);
  146.     if (orig->Device)
  147.     pcentry->Device=strdup(orig->Device);
  148.     if (orig->IF)
  149.     pcentry->IF=strdup(orig->IF);
  150.     if (orig->AF)
  151.     pcentry->AF=strdup(orig->AF);
  152.     if (orig->Type)
  153.     pcentry->Type=strdup(orig->Type);
  154.     pcentry->db=orig->db;
  155.     if (orig->Resolution)
  156.     pcentry->Resolution=strdup(orig->Resolution);
  157.     if (orig->PaperSize)
  158.     pcentry->PaperSize=strdup(orig->PaperSize);
  159.     if (orig->AutoEOF)
  160.     pcentry->AutoEOF=strdup(orig->AutoEOF);
  161.     if (orig->BitsPerPixel)
  162.     pcentry->BitsPerPixel=strdup(orig->BitsPerPixel);
  163.     if (orig->CRLF)
  164.     pcentry->CRLF=strdup(orig->CRLF);
  165.     if (orig->RevPages)
  166.     pcentry->RevPages=strdup(orig->RevPages);
  167.     if (orig->RemoteHost)
  168.     pcentry->RemoteHost=strdup(orig->RemoteHost);
  169.     if (orig->RemoteQueue)
  170.     pcentry->RemoteQueue=strdup(orig->RemoteQueue);
  171.     if (orig->SMBHost)
  172.     pcentry->SMBHost=strdup(orig->SMBHost);
  173.     if (orig->SMBHostIP)
  174.     pcentry->SMBHostIP=strdup(orig->SMBHostIP);
  175.     if (orig->SMBShare)
  176.     pcentry->SMBShare=strdup(orig->SMBShare);
  177.     if (orig->SMBUser)
  178.     pcentry->SMBUser=strdup(orig->SMBUser);
  179.     if (orig->SMBPasswd)
  180.     pcentry->SMBPasswd=strdup(orig->SMBPasswd);
  181.     
  182.     return pcentry;
  183. }
  184.  
  185.  
  186.  
  187. /* Free an existing PrintCap Entry */
  188. static void free_PCEntry( PCEntry *pcentry) {
  189.     free(pcentry->Queue);
  190.     free(pcentry->SpoolDir);
  191.     free(pcentry->Device);
  192.     free(pcentry->IF);
  193.     free(pcentry->AF);
  194.     free(pcentry->Type);
  195.     free(pcentry->Resolution);
  196.     free(pcentry->PaperSize);
  197.     free(pcentry->AutoEOF);
  198.     free(pcentry->BitsPerPixel);
  199.     free(pcentry->CRLF);
  200.     free(pcentry->RevPages);
  201.     free(pcentry->RemoteHost);
  202.     free(pcentry->RemoteQueue);
  203.     free(pcentry->SMBHost);
  204.     free(pcentry->SMBHostIP);
  205.     free(pcentry->SMBShare);
  206.     free(pcentry->SMBUser);
  207.     free(pcentry->SMBPasswd);
  208.     free(pcentry);
  209. }
  210.  
  211.  
  212. /* Read lines from file, ignoring lines starting with a '#' and */
  213. /* observing continuation lines (lines which end with a '\')    */
  214. /* All leading and trailing spaces are removed, as well as \n   */
  215. /* Returns zero if no more input available                      */
  216. static char *pc_getline(FILE *file) {
  217.     int done;
  218.     char buf[256];
  219.     char *fresult;
  220.     char *line;
  221.     int len;
  222.     
  223.     line = NULL;
  224.     done=0;
  225.     while (!done) {
  226.     fresult=fgets( buf, 256, file );
  227.     if (!fresult)
  228.         return NULL;
  229.     
  230.     trim_whitespace( buf );
  231.     
  232.     if (! (*buf) )
  233.         continue;
  234.     
  235.     if (*buf == '#')
  236.         continue;
  237.     
  238.     len = strlen( buf );
  239.     if ( *(buf+len-1) != '\\' )
  240.         done = 1;
  241.     else {
  242.         /* silly rule - make sure line ends with a space */
  243.         if ( len > 2 && *(buf+len-2) != ' ' ) {
  244.         *(buf+len-1) = ' ';
  245.         *(buf+len) = '\000';
  246.         } else
  247.         *(buf+len-1) = '\000';
  248.     }
  249.  
  250.     if (!line)
  251.         line = strdup(buf);
  252.     else {
  253.         line = (char *) realloc( line, strlen(line) + strlen (buf) + 1 );
  254.         strcpy( line+strlen(line), buf );
  255.     }
  256.     }
  257.     
  258.     return line;
  259. }
  260.  
  261. /* strips out the value of a Parameter in the printer db file */
  262. static char *getfield( char *s ) {
  263.     char *f, *p;
  264.     
  265.     f = strchr(s, ':');
  266.     if (!f)
  267.     return NULL;
  268.     
  269.     p = strdup(f+1);
  270.     trim_whitespace(p);
  271.     
  272.     if (! (*p))
  273.     return NULL;
  274.     else
  275.     return p;
  276. }
  277.  
  278. /* looks for exactly flds fields, with each field enclosed in a {} pair. */
  279. static int parsefields( char *s, char **flds) {
  280.     char *f, *l;
  281.     char *p;
  282.     int n;
  283.     int i;
  284.     
  285.     flds[0] = NULL;
  286.     flds[1] = NULL;
  287.     flds[2] = NULL;
  288.     n = 0;
  289.     
  290.     p = s;
  291.     for (i=0; i<3; i++) {
  292.     f = strchr(p, '{');
  293.     if (!f)
  294.         return n;
  295.     
  296.     l = strchr(f, '}');
  297.     if (!l)
  298.         return n;
  299.     
  300.     flds[n] = (char *) malloc( l-f+2 );
  301.     strncpy( flds[n], f+1, l-f-1 );
  302.     *((flds[n])+(l-f)-1) = '\000';
  303.     
  304.     p = l+1;
  305.     n++;
  306.     }
  307.     return n;
  308. }
  309.  
  310. static int dbCompare(const void * a, const void * b) {
  311.     const DBEntry * const *first = a;
  312.     const DBEntry * const *second = b;
  313.  
  314.     return strcmp((*first)->Descr, (*second)->Descr);
  315. }
  316.  
  317. /* Read the printer database dbpath into memory */
  318. /* returns non-zero on error */
  319. static int read_printer_db( char *dbpath ) {
  320.     FILE *dbfile;
  321.     char *line;
  322.     char *tmpstr;
  323.     char *fields[3];
  324.     int nfield;
  325.     DBEntry *entry;
  326.     int nbpp, nres;
  327.     int nbpp_alloc, nres_alloc;
  328.     
  329.     tmpstr=malloc(strlen(dbpath)+strlen(root_path)+2);
  330.     strcpy(tmpstr,root_path);
  331.     strcat(tmpstr,dbpath);
  332.     if ((dbfile=fopen(tmpstr, "r")) == NULL) {
  333.     free(tmpstr);
  334.     return -1;
  335.     }
  336.     free(tmpstr);
  337.  
  338.     /* loop till we find the start of an entry */
  339.     /* we obviously want to ignore any comments on the way */
  340.     numdb = numdb_alloc = 0;
  341.     while ((line=pc_getline(dbfile))) {
  342.     if (!strncmp(line, "StartEntry:", 11)) {
  343.         entry = (DBEntry *) malloc( sizeof(DBEntry) );
  344.         entry->Entry = getfield(line);
  345.         entry->GSDriver = NULL;
  346.         entry->Descr = NULL;
  347.         entry->About = NULL;
  348.         entry->Resolution = NULL;
  349.         entry->ResDescr = NULL;
  350.         entry->BitsPerPixel = NULL;
  351.         entry->BppDescr = NULL;
  352.         
  353.         nres = nres_alloc = 0;
  354.         nbpp = nbpp_alloc = 0;
  355.         
  356.         free(line);
  357.         if (!entry->Entry) {
  358.         free(entry);
  359.         continue;
  360.         }
  361.  
  362.         numdb++;
  363.         if (numdb >= numdb_alloc ) {
  364.         numdb_alloc += 25;
  365.         thedb=(DBEntry **)realloc(thedb,
  366.                       sizeof(DBEntry *)*(numdb_alloc));
  367.         }
  368.  
  369.         thedb[numdb - 1] = entry;
  370.         
  371.         while ((line=pc_getline(dbfile))) {
  372.         if (!strncmp(line, "EndEntry", 8))
  373.             break;
  374.         
  375.         if (!strncmp(line, "GSDriver:", 9)) {
  376.             if (entry->GSDriver)
  377.             break;
  378.             
  379.             entry->GSDriver=getfield(line);
  380.         }
  381.  
  382.           if (!strncmp(line, "Description:", 12)) {
  383.           if (entry->Descr)
  384.               break;
  385.  
  386.           tmpstr=getfield(line);
  387.           nfield = parsefields(tmpstr, fields);
  388.           free(tmpstr);
  389.           
  390.           if (nfield == 1 )
  391.               entry->Descr=fields[0];
  392.           else
  393.               break;
  394.           }
  395.           
  396.           if (!strncmp(line, "About:", 6)) {
  397.           if (entry->About)
  398.               break;
  399.           
  400.           tmpstr=getfield(line);
  401.           nfield = parsefields(tmpstr, fields);
  402.           free(tmpstr);
  403.           if (nfield == 1) {
  404.               trim_whitespace(fields[0]);
  405.               insert_newlines(fields[0]);
  406.               entry->About=fields[0];
  407.           } else
  408.               break;
  409.           }
  410.  
  411.           if (!strncmp(line, "Resolution:", 11)) {
  412.           tmpstr=getfield(line);
  413.           nfield = parsefields(tmpstr, fields);
  414.           free(tmpstr);
  415.           if (nfield == 3) {
  416.               nres++;
  417.               
  418.               if (nres >= nres_alloc) {
  419.               nres_alloc += 10;
  420.               entry->Resolution=
  421.                 (char **)realloc(entry->Resolution,
  422.                          nres_alloc*sizeof(char*));
  423.               entry->ResDescr=
  424.                 (char **)realloc(entry->ResDescr,
  425.                          nres_alloc*sizeof(char*));
  426.               }
  427.  
  428.               entry->Resolution[nres-1]=
  429.             (char *)malloc(strlen(fields[0])+strlen(fields[1])+10);
  430.               sprintf(entry->Resolution[nres-1],
  431.                   "%sx%s", fields[0],fields[1]);
  432.  
  433.               if (fields[2])
  434.               entry->ResDescr[nres-1]=strdup(fields[2]);
  435.               else
  436.               entry->ResDescr[nres-1]=NULL;
  437.           } else
  438.               break;
  439.           }
  440.  
  441.           if (!strncmp(line, "BitsPerPixel:", 13)) {
  442.           tmpstr=getfield(line);
  443.           nfield = parsefields(tmpstr, fields);
  444.           free(tmpstr);
  445.           if (nfield == 2) {
  446.               nbpp++;
  447.               
  448.               if (nbpp >= nbpp_alloc) {
  449.               nbpp_alloc += 10;
  450.               entry->BitsPerPixel=
  451.                 (char **)realloc(entry->BitsPerPixel,
  452.                          nbpp_alloc*sizeof(char*));
  453.               entry->BppDescr=
  454.                 (char **)realloc(entry->BppDescr,
  455.                          nbpp_alloc*sizeof(char*));
  456.               }
  457.               
  458.               entry->BitsPerPixel[nbpp-1]=strdup(fields[0]);
  459.               
  460.               if (fields[1])
  461.               entry->BppDescr[nbpp-1]=strdup(fields[1]);
  462.               else
  463.               entry->BppDescr[nbpp-1]=NULL;
  464.           } else
  465.               break;
  466.           }
  467.           free(line);
  468.         }
  469.  
  470.         entry->NumRes = nres;
  471.         entry->NumBpp = nbpp;
  472.     } else    {
  473.         free(line);
  474.     }
  475.     }
  476.  
  477.     fclose(dbfile);
  478.  
  479.     qsort(thedb, numdb, sizeof(*thedb), dbCompare);
  480.  
  481.     return 0;
  482. }
  483.  
  484. #if 0
  485. /* used by below routines - assumes everything is malloc'd          */
  486. /* updates old to new if new is non-NULL                            */
  487. /* frees the old value and points it at the new                     */
  488. /* if new is NULL, means it wasnt updated and old remains unchanged */
  489. static void update_changed( void *new, void **old ) {
  490.     if (new) {
  491.     if (*old) 
  492.         free(*old);
  493.     *old = new;
  494.     }
  495. }
  496. #endif
  497.  
  498. /* display summary line given by char * arg */
  499. void show_printer_about( char *about ) {
  500.     newtComponent infoform, infook, infobox, answer;
  501.     
  502.     newtCenteredWindow(56, 15, "Printer Info");
  503.     infoform = newtForm(NULL, NULL, 0);
  504.     infobox=newtTextbox(3, 2, 50, 8, 
  505.             NEWT_TEXTBOX_WRAP|NEWT_TEXTBOX_SCROLL);
  506.     newtTextboxSetText( infobox, about );
  507.     infook = newtButton( 23, 11, "Ok");
  508.         
  509.     newtFormAddComponents(infoform, infobox, infook, NULL);
  510.     answer = newtRunForm( infoform );
  511.  
  512.     newtPopWindow();
  513.     newtFormDestroy(infoform);
  514. }
  515.  
  516. /* select the printer type you have */
  517. /* return < 0 if user aborted */
  518. /* returns index into thedb[] of the selected entry otherwise*/
  519. static int select_printer_type( PCEntry *changes) {
  520.     newtComponent ok, cancel, form, listbox, answer;
  521.     struct newtExitStruct event;
  522.     long i, sel;
  523.     int formdone;
  524.     char *origtype;
  525.  
  526.     if (changes->db && changes->db->Descr) {
  527.     origtype = alloca(strlen(changes->db->Descr)+2);
  528.     strcpy(origtype, changes->db->Descr);
  529.     } else
  530.     origtype = NULL;
  531.     
  532.     newtCenteredWindow(60, 18, "Configure Printer");
  533.     newtPushHelpLine("<F1> will give you information on a particular "
  534.              "printer type");
  535.     form = newtForm(NULL, NULL, 0);
  536.     newtFormAddComponent(form, newtLabel(3, 1, "What type of printer "
  537.                      "do you have?"));
  538.     listbox = newtListbox(6, 3, 10, NEWT_FLAG_RETURNEXIT);
  539.     for (i = 0; i < numdb; i++) {
  540.     newtListboxAddEntry(listbox, thedb[i]->Descr, (void *)i);
  541.     
  542.     if (changes->db && changes->db->Entry &&
  543.         !strcmp(changes->db->Entry,thedb[i]->Entry)) {
  544.         newtListboxSetCurrent(listbox, i);
  545.     }
  546.     }
  547.  
  548.     /* if no selection yet, default to PostScript if it exists */
  549.     if (changes->db==NULL || changes->db->Entry==NULL  ) {
  550.     /* set this just in case we find nothing that matches */
  551.     newtListboxSetCurrent(listbox, 0);
  552.     for (i = 0; i < numdb; i++)
  553.         if (!strcmp(thedb[i]->Descr,"PostScript printer")) {
  554.         newtListboxSetCurrent(listbox, i);
  555.         break;
  556.         }
  557.     }
  558.     
  559.     ok = newtButton( 15, 14, NEXT_LABEL);
  560.     cancel = newtButton( 31, 14, PREV_LABEL);
  561.     newtFormAddComponents( form, listbox, ok, cancel, NULL);
  562.     newtFormAddHotKey(form, NEWT_KEY_F1); 
  563.     
  564.     formdone = 0;
  565.     answer = NULL;
  566.     while (!formdone) {
  567.     newtFormRun(form, &event);
  568.     
  569.     if (event.reason == NEWT_EXIT_HOTKEY) {
  570.         if (event.u.key == NEWT_KEY_F12)
  571.         formdone = 1;
  572.         else if (event.u.key == NEWT_KEY_F1) {
  573.         show_printer_about(
  574.             thedb[(long)newtListboxGetCurrent(listbox)]->About);
  575.         }
  576.     } else if (event.reason == NEWT_EXIT_COMPONENT) {
  577.         formdone = 1;
  578.         if (event.u.co == cancel)
  579.         answer = cancel;
  580.     }
  581.     }
  582.     
  583.     sel = (long) newtListboxGetCurrent(listbox);
  584.     
  585.     newtPopWindow();
  586.     newtPopHelpLine();
  587.     newtFormDestroy(form);
  588.     
  589.     if ( answer == cancel )
  590.     return -1;
  591.  
  592.     /* store new values */
  593.     changes->db = thedb[sel];
  594.  
  595.     /* MAJOR HACK */
  596.     /* if the printer is an HP, lets do stairstep correction */
  597.     if (!strncmp(changes->db->Descr,"HP",2)) {
  598.     if (changes->CRLF)
  599.         free(changes->CRLF);
  600.     changes->CRLF=strdup("YES");
  601.     } else {
  602.     if (origtype) {
  603.         if (strcmp(origtype, changes->db->Descr)) {
  604.         if (changes->CRLF)
  605.             free(changes->CRLF);
  606.         changes->CRLF=strdup("NO");
  607.         }
  608.     } else  {
  609.         if (changes->CRLF)
  610.         free(changes->CRLF);
  611.         changes->CRLF=strdup("NO");
  612.     }
  613.     }
  614.  
  615.     return sel;
  616. }    
  617.     
  618.  
  619. /* select the paper size and printer resolution you want */
  620. /* return < 0 if user aborted */
  621. /* returns 0 otherwise */
  622. static int select_paper_size_and_res( PCEntry *changes ) {
  623.     newtComponent ok, cancel, form, text, papersz, res, answer, crlf;
  624.     struct newtExitStruct event;
  625.     long i;
  626.     int j;
  627.     int formdone;
  628.     int xpos;
  629.     int maxlen;
  630.  
  631.     char **reslines;
  632.     char crlfret;
  633.     
  634.     /* there has to be a current selection for this to work! */
  635.     if (changes->db == NULL)
  636.     return -1;
  637.     
  638.     newtCenteredWindow(54, 18, changes->db->Descr); 
  639.     newtPushHelpLine("<F1> will give you information on this "
  640.              "printer driver.");
  641.     form = newtForm(NULL, NULL, 0);
  642.     text = newtTextbox(1, 1, 52, 2, NEWT_TEXTBOX_WRAP);
  643.     newtTextboxSetText(text, 
  644.                "You may now configure the paper size and resolution "
  645.                "for this printer.");
  646.     newtFormAddComponent(form, text);
  647.  
  648.     /* Paper size listbox */
  649.     newtFormAddComponent(form, newtLabel(7, 4, "Paper Size"));
  650.     papersz = newtListbox( 8, 5, 5, NEWT_FLAG_NOSCROLL );
  651.     for (i=0; i < NUM_PAPERSIZES; i++) {
  652.     newtListboxAddEntry( papersz, PaperSizes[i], (void *)i );
  653.     if (changes->PaperSize &&
  654.         !strcmp(changes->PaperSize, PaperSizes[i]))
  655.         newtListboxSetCurrent(papersz, i);
  656.     }
  657.  
  658.     /* make sure something is picked */
  659.     if (changes->PaperSize==NULL)
  660.     newtListboxSetCurrent(papersz, 0);
  661.  
  662.     /* Resolution */
  663.     if ( changes->db->NumRes > 0) {
  664.     maxlen = 0;
  665.     reslines = (char **) alloca( changes->db->NumRes * sizeof(char *));
  666.     for (i=0; i < changes->db->NumRes; i++) {
  667.         if (changes->db->ResDescr && changes->db->ResDescr[i]) {
  668.         reslines[i]=alloca(strlen(changes->db->Resolution[i])+
  669.                    strlen(changes->db->ResDescr[i])+15);
  670.         /* we want the 'x' in the 5th column */
  671.         xpos = (strchr(changes->db->Resolution[i],'x')-
  672.             changes->db->Resolution[i]);
  673.         for (j=0; j<5-xpos; j++)
  674.             reslines[i][j]=' ';
  675.         reslines[i][j]='\000';
  676.         strcat(reslines[i],changes->db->Resolution[i]);
  677.         /* pad to 13 spaces */
  678.         for (j=strlen(reslines[i]); j < 13; j++)
  679.             strcat(reslines[i], " ");
  680.         strcat(reslines[i],changes->db->ResDescr[i]);
  681.         } else {
  682.         reslines[i]=alloca(strlen(changes->db->Resolution[i])+2);
  683.         strcat(reslines[i],changes->db->Resolution[i]);
  684.         }
  685.         if (strlen(reslines[i]) > maxlen)
  686.         maxlen = strlen(reslines[i]);
  687.         
  688.     }
  689.  
  690.     newtFormAddComponent(form, newtLabel(34, 4, "Resolution"));
  691.     res = newtListbox( 37-maxlen/2, 5, 5, 0 );
  692.  
  693.     for (i=0; i < changes->db->NumRes; i++) {
  694.         newtListboxAddEntry( res, reslines[i], (void *)i );
  695.         if (changes->Resolution &&
  696.         !strcmp(changes->Resolution, changes->db->Resolution[i]))
  697.         newtListboxSetCurrent(res, i);
  698.     }
  699.     } else {
  700.     newtFormAddComponent(form, newtLabel(34, 4, "Resolution"));
  701.     res = newtListbox( 32, 5, 4, 0 );
  702.     newtListboxAddEntry( res, "Default", (void *)0 );
  703.     newtListboxSetCurrent(res, 0);
  704.     reslines=NULL;
  705.     }
  706.     
  707.     /* make sure something is picked */
  708.     if (changes->Resolution==NULL)
  709.     newtListboxSetCurrent(res, 0);
  710.  
  711.     /* add stair-step correction toggle */
  712.     if (!strcmp("YES", changes->CRLF))
  713.         crlf = newtCheckbox(11, 11, "Fix stair-stepping of text?", '*', NULL,&crlfret);
  714.     else
  715.         crlf = newtCheckbox(11, 11, "Fix stair-stepping of text?", ' ', NULL,&crlfret);
  716.     
  717.     ok = newtButton( 11, 13, NEXT_LABEL);
  718.     cancel = newtButton( 31, 13, PREV_LABEL);
  719.     newtFormAddComponents(form,papersz,res,crlf,ok,cancel,NULL);
  720.     newtFormAddHotKey(form, NEWT_KEY_F1); 
  721.     
  722.     formdone = 0;
  723.     answer = NULL;
  724.     
  725.     while (!formdone) {
  726.     newtFormRun(form, &event);
  727.     
  728.     if (event.reason == NEWT_EXIT_HOTKEY) {
  729.         if (event.u.key == NEWT_KEY_F12)
  730.         formdone = 1;
  731.         else if (event.u.key == NEWT_KEY_F1) {
  732.         show_printer_about( changes->db->About );
  733.         }
  734.     } else if (event.reason == NEWT_EXIT_COMPONENT) {
  735.         formdone = 1;
  736.         if (event.u.co == cancel)
  737.         answer = cancel;
  738.     }
  739.     }
  740.  
  741.  
  742.     if ( answer == cancel ) {
  743.     newtPopHelpLine();
  744.     newtPopWindow();
  745.     newtFormDestroy(form);
  746.     return -1;
  747.     }
  748.  
  749.     i = (long) newtListboxGetCurrent(papersz);
  750.  
  751.     free(changes->PaperSize);
  752.     changes->PaperSize=strdup(PaperSizes[i]);
  753.  
  754.     free(changes->Resolution);
  755.     if (changes->db->NumRes > 0) {
  756.     i = (long) newtListboxGetCurrent(res);
  757.     changes->Resolution=strdup(changes->db->Resolution[i]);
  758.     } else
  759.     changes->Resolution=strdup("Default");
  760.  
  761.     if (changes->CRLF)
  762.     free(changes->CRLF);
  763.     
  764.     if (crlfret == ' ')
  765.     changes->CRLF=strdup("NO");
  766.     else
  767.     changes->CRLF=strdup("YES");
  768.     
  769.     newtPopHelpLine();
  770.     newtPopWindow();
  771.     newtFormDestroy(form);
  772.  
  773.     return 0;
  774. }
  775.  
  776. /* pick the color depth, returns < 0 on cancel, 0 otherwise */
  777. static int select_color_depth( PCEntry *changes ) {
  778.     newtComponent ok, cancel, form, bpp, answer, text;
  779.     struct newtExitStruct event;
  780.     long i;
  781.     int formdone, maxlen;
  782.  
  783.     char **bpplines;
  784.  
  785.     /* have to have a selection to work */
  786.     if (changes->db == NULL)
  787.     return -1;
  788.  
  789.     /* if only one color depth choice, do nothing */
  790.     if ( changes->db->NumBpp == 0) {
  791.     changes->BitsPerPixel=strdup("Default");
  792.     return 0;
  793.     }
  794.     
  795.     newtCenteredWindow(60, 15, "Configure Color Depth");
  796.     newtPushHelpLine("<F1> will give you information on this printer driver.");
  797.     form = newtForm(NULL, NULL, 0);
  798.  
  799.     text = newtTextbox(1, 1, 58, 2, NEWT_TEXTBOX_WRAP);
  800.     newtTextboxSetText(text, 
  801.                "You may now configure the color options "
  802.                "for this printer.");
  803.     newtFormAddComponent(form, text);
  804.  
  805.     newtFormAddComponent(form, newtLabel(22, 3, "Bits Per Pixel"));
  806.     if ( changes->db->NumBpp > 0) {
  807.     maxlen = 0;
  808.     bpplines = (char **) alloca(changes->db->NumBpp*sizeof(char *));
  809.     for (i=0; i < changes->db->NumBpp; i++) {
  810.         if (changes->db->BppDescr && changes->db->BppDescr[i]) {
  811.         bpplines[i]=alloca(strlen(changes->db->BitsPerPixel[i])+
  812.                    strlen(changes->db->BppDescr[i])+15);
  813.         bpplines[i][0]='\000';
  814.         strcat(bpplines[i],changes->db->BitsPerPixel[i]);
  815.         if (bpplines[i][1] == '\000') {
  816.             bpplines[i][1] = bpplines[i][0];
  817.             bpplines[i][0] = ' ';
  818.             bpplines[i][2] = '\000';
  819.         }
  820.         strcat(bpplines[i],"  ");
  821.         strcat(bpplines[i],changes->db->BppDescr[i]);
  822.         } else {
  823.         bpplines[i]=alloca(strlen(changes->db->BitsPerPixel[i])+2);
  824.         strcpy(bpplines[i], changes->db->BitsPerPixel[i]);
  825.         }
  826.         
  827.         /* limit the length of the line */
  828.         if (strlen(bpplines[i]) > 54)
  829.         bpplines[i][50] = '\000';
  830.  
  831.         if (strlen(bpplines[i]) > maxlen)
  832.         maxlen = strlen(bpplines[i]);
  833.     }
  834.     
  835.     bpp = newtListbox( 29-maxlen/2, 4, 5, NEWT_FLAG_RETURNEXIT );
  836.     for (i=0; i < changes->db->NumBpp; i++) {
  837.         newtListboxAddEntry(bpp,bpplines[i], (void *)i );
  838.         if (changes->BitsPerPixel &&
  839.         !strcmp(changes->BitsPerPixel,changes->db->BitsPerPixel[i]))
  840.         newtListboxSetCurrent(bpp, i);
  841.     }
  842.     
  843.     } else {
  844.     fprintf(stderr, "How did we get here, numbpp = 0!\n");
  845.     return -1;
  846. #if 0    
  847.     bpp = newtListbox( 29-strlen("Default")/2, 5, 4,NEWT_FLAG_RETURNEXIT );
  848.     newtListboxAddEntry( bpp, "Default", (void *)0 );
  849.     newtListboxSetCurrent(bpp, 0);
  850.     bpplines=NULL;
  851. #endif
  852.     }
  853.  
  854.     /* make sure something is set */
  855.     if (changes->BitsPerPixel==NULL)
  856.     newtListboxSetCurrent(bpp,0);
  857.  
  858.     ok = newtButton( 11, 10, NEXT_LABEL);
  859.     cancel = newtButton( 36, 10, PREV_LABEL);
  860.     newtFormAddComponents(form,bpp,ok,cancel,NULL);
  861.     newtFormAddHotKey(form, NEWT_KEY_F1); 
  862.     
  863.     formdone = 0;
  864.     answer = NULL;
  865.     while (!formdone) {
  866.     newtFormRun(form, &event);
  867.     
  868.     if (event.reason == NEWT_EXIT_HOTKEY) {
  869.         if (event.u.key == NEWT_KEY_F12)
  870.         formdone = 1;
  871.         else if (event.u.key == NEWT_KEY_F1) {
  872.         show_printer_about( changes->db->About );
  873.         }
  874.     } else if (event.reason == NEWT_EXIT_COMPONENT) {
  875.         formdone = 1;
  876.         if (event.u.co == cancel)
  877.         answer = cancel;
  878.     }
  879.     }
  880.  
  881.     if ( answer == cancel ) {
  882.     newtPopHelpLine();
  883.     newtPopWindow();
  884.     newtFormDestroy(form);
  885.     return -1;
  886.     }
  887.  
  888.     free(changes->BitsPerPixel);
  889.     if (changes->db->NumBpp > 0) {
  890.     i = (long) newtListboxGetCurrent(bpp);
  891.     changes->BitsPerPixel=strdup(changes->db->BitsPerPixel[i]);
  892.     } else {
  893.     fprintf(stderr, "How did we get here, numbpp = 0!\n");
  894.     return -1;
  895. #if 0    
  896.     changes->BitsPerPixel=strdup("Default");
  897. #endif
  898.     }
  899.  
  900.     newtPopHelpLine();
  901.     newtPopWindow();
  902.     newtFormDestroy(form);
  903.     
  904.     return 0;
  905. }
  906.  
  907. /* returns the full attribute of the selected printer filter */
  908. /* returns < 0 if user cancelled selected                    */
  909. static int select_filter( PCEntry *changes ) {
  910.     
  911.     int done;
  912.     int stage;
  913.     int abort;
  914.     
  915.     done = 0;
  916.     stage = 1;
  917.     abort = 0;
  918.     while (!done) {
  919.  
  920.     switch (stage) {
  921.  
  922.         /* select printer model/driver */
  923.       case 1:
  924.         if (select_printer_type(changes) < 0) {
  925.         done = 1;
  926.         abort = 1;
  927.         break;
  928.         } else
  929.         stage++;
  930.         break;
  931.  
  932.         /* select paper size and resolution */
  933.       case 2:
  934.         if (select_paper_size_and_res( changes ) < 0) {
  935.         stage--;
  936.         break;
  937.         } else
  938.         stage++;
  939.         break;
  940.  
  941.         /* select color depth */
  942.       case 3:
  943.         if (select_color_depth( changes ) < 0) {
  944.         stage--;
  945.         break;
  946.         } else
  947.         stage++;
  948.         break;
  949.  
  950.         /* we made it and we're done */
  951.       case 4:
  952.         done = 1;
  953.  
  954.     }
  955.     }
  956.  
  957.     if (abort)
  958.     return -1;
  959.  
  960.     return 0;
  961. }
  962.  
  963.  
  964. /* return < 0 for user cancel */
  965. static int get_local_info( PCEntry *changes ) {
  966.  
  967.     newtComponent answer, cancel, form, ok, device, text;
  968.     char *device_result;
  969.     char *devname;
  970.     int detected[3];
  971.     int i, result;
  972.     int npos;
  973.  
  974. #if defined(__i386__) && !defined(TESTING)
  975.     if (loadModule("lp", DRIVER_OTHER, DRIVER_MINOR_NONE, NULL)) 
  976.     return INST_ERROR;
  977.  
  978. #endif
  979.  
  980. #if 0
  981.     /* old way Erik did this */
  982.     devMakeInode("lp0", "/tmp/lp0");
  983.     devMakeInode("lp1", "/tmp/lp1");
  984.     devMakeInode("lp2", "/tmp/lp2");
  985.     
  986.     /* do auto-detect of lp ports */
  987.     detected[0] = ((result=open("/tmp/lp0", O_WRONLY|O_NONBLOCK)) != -1);
  988.     if (result >= 0) close(result);
  989.     detected[1] = ((result=open("/tmp/lp1", O_WRONLY|O_NONBLOCK)) != -1);
  990.     if (result >= 0) close(result);
  991.     detected[2] = ((result=open("/tmp/lp2", O_WRONLY|O_NONBLOCK)) != -1);
  992.     if (result >= 0) close(result);
  993.  
  994.     unlink("/tmp/lp0");
  995.     unlink("/tmp/lp1");
  996.     unlink("/tmp/lp2");
  997. #else
  998.     /* different approach */
  999.     /* do auto-detect of lp ports */
  1000.     devname=alloca(strlen(root_path)+strlen("/dev/lpX")+2);
  1001.     strcpy(devname,root_path);
  1002.     strcat(devname,"/dev/lpX");
  1003.     npos=strlen(devname)-1;
  1004.     devname[npos]='0';
  1005.     detected[0] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1);
  1006.     if (result >= 0) close(result);
  1007.     devname[npos]='1';
  1008.     detected[1] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1);
  1009.     if (result >= 0) close(result);
  1010.     devname[npos]='2';
  1011.     detected[2] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1);
  1012.     if (result >= 0) close(result);
  1013. #endif
  1014.     
  1015. #if defined(__i386__) && !defined(TESTING)
  1016.     removeModule("lp");
  1017. #endif
  1018.  
  1019.     newtCenteredWindow(44, 16, "Local Printer Device");
  1020.     form = newtForm(NULL, NULL, 0);
  1021.  
  1022.     text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP);
  1023.     newtTextboxSetText(text,
  1024.     "What device is your printer connected to (note that /dev/lp0 is "
  1025.     "equivalent to LPT1:)?");
  1026.  
  1027.     newtFormAddComponent(form, text);
  1028.     newtFormAddComponent(form, newtLabel(3, 7, "Auto-detected ports:"));
  1029.     newtFormAddComponent(form, newtLabel(6, 8, "/dev/lp0:"));
  1030.     newtFormAddComponent(form, newtLabel(6, 9, "/dev/lp1:"));
  1031.     newtFormAddComponent(form, newtLabel(6, 10, "/dev/lp2:"));
  1032.     
  1033.     for (i=0; i<3; i++) {
  1034.     if (detected[i])
  1035.         newtFormAddComponent(form, newtLabel(18,8+i, "Detected"));
  1036.     else
  1037.         newtFormAddComponent(form, newtLabel(18,8+i, "Not Detected"));
  1038.     }
  1039.  
  1040.     newtFormAddComponent(form, newtLabel(3, 5, "Printer Device:"));
  1041.     if (changes->Device)
  1042.     device=newtEntry(19, 5, changes->Device, 15, &device_result,
  1043.              NEWT_FLAG_RETURNEXIT);
  1044.     else
  1045.     device=newtEntry(19, 5, "/dev/lp1", 15, &device_result,
  1046.              NEWT_FLAG_RETURNEXIT);
  1047.     
  1048.     ok = newtButton( 7, 12, NEXT_LABEL);
  1049.     cancel = newtButton( 24, 12, PREV_LABEL);
  1050.     newtFormAddComponents( form, device, ok, cancel, NULL);
  1051.     answer = newtRunForm(form);
  1052.  
  1053.     if ( answer != cancel ) {
  1054.     free(changes->Device);
  1055.     changes->Device = strdup(device_result);
  1056.     result = 0;
  1057.     } else
  1058.     result = -1;
  1059.  
  1060.     newtPopWindow();
  1061.     newtFormDestroy(form);
  1062.     return result;
  1063. }
  1064.  
  1065.  
  1066. /* return < 0 for user cancel */
  1067. static int get_remote_info( PCEntry *changes ) {
  1068.     newtComponent answer, cancel, form, ok, rhost, rqueue, text;
  1069.     char *queue_result;
  1070.     char *host_result;
  1071.     int result;
  1072.     
  1073.     newtCenteredWindow(42, 14, "Remote lpd Printer Options");
  1074.     form = newtForm(NULL, NULL, 0);
  1075.  
  1076.     text = newtTextbox(1, 1, 40, 5, NEWT_TEXTBOX_WRAP);
  1077.     newtTextboxSetText(text, 
  1078.     "To use a remote lpd print queue, you need to supply the "
  1079.     "hostname of the printer server and the queue name on that "
  1080.     "server which jobs should be placed in.");
  1081.     
  1082.     newtFormAddComponent(form, text);
  1083.     newtFormAddComponent(form, newtLabel(2, 7, "Remote hostname:"));
  1084.     newtFormAddComponent(form, newtLabel(2, 8, "Remote queue:"));
  1085.  
  1086.     if (changes->RemoteHost)
  1087.     rhost =newtEntry(19, 7, changes->RemoteHost, 20, &host_result, 0);
  1088.     else
  1089.     rhost =newtEntry(19, 7, "", 20, &host_result, 0);
  1090.  
  1091.     if (changes->RemoteQueue)
  1092.     rqueue =newtEntry(19, 8, changes->RemoteQueue, 20, &queue_result, 0);
  1093.     else
  1094.     rqueue =newtEntry(19, 8, "lp", 20, &queue_result, 0);
  1095.  
  1096.     ok = newtButton( 7, 10, NEXT_LABEL);
  1097.     cancel = newtButton( 24, 10, PREV_LABEL);
  1098.     newtFormAddComponents( form, rhost, rqueue, ok, cancel, NULL);
  1099.     answer = newtRunForm(form);
  1100.  
  1101.     if ( answer != cancel ) {
  1102.     free(changes->RemoteHost);
  1103.     changes->RemoteHost = strdup(host_result);
  1104.     free(changes->RemoteQueue);
  1105.     changes->RemoteQueue = strdup(queue_result);
  1106.     result = 0;
  1107.     } else
  1108.     result = -1;
  1109.  
  1110.     newtPopWindow();
  1111.     newtFormDestroy(form);
  1112.     return result;
  1113. }
  1114.  
  1115.  
  1116. /* return < 0 for user cancel */
  1117. static int get_smb_info( PCEntry *changes ) {
  1118.     newtComponent answer, cancel, form, ok, text;
  1119.     newtComponent host, hostip, share, user, passwd;
  1120.     
  1121.     int result;
  1122.     char *host_result;
  1123.     char *hostip_result;
  1124.     char *share_result;
  1125.     char *user_result;
  1126.     char *passwd_result;
  1127.  
  1128.     newtCenteredWindow(60, 18, "LAN Manager Printer Options");
  1129.     form = newtForm(NULL, NULL, 0);
  1130.  
  1131.     text = newtTextbox(1, 1, 58, 6, NEWT_TEXTBOX_WRAP);
  1132.     newtTextboxSetText(text,
  1133.     "To print to a LAN manager printer, you need to provide the "
  1134.     "LAN manager host name (this is not always the same as the machines "
  1135.     "TCP/IP hostname) and possibly the IP address of the print server, as "
  1136.     "well as the share name for the printer you wish to access and any "
  1137.     "applicable user name and password.");    
  1138.  
  1139.     newtFormAddComponent(form, text);
  1140.     
  1141.     newtFormAddComponent(form, newtLabel(10, 8, "LAN Manager Host:"));
  1142.     newtFormAddComponent(form, newtLabel(10, 9, "LAN Manager IP:"));
  1143.     newtFormAddComponent(form, newtLabel(10, 10, "Share Name:"));
  1144.     newtFormAddComponent(form, newtLabel(10, 11, "Username:"));
  1145.     newtFormAddComponent(form, newtLabel(10, 12, "Password:"));
  1146.  
  1147.     if (changes->SMBHost)
  1148.     host   = newtEntry(28, 8, changes->SMBHost, 15, &host_result, 0);
  1149.     else
  1150.     host   = newtEntry(28, 8, "", 15, &host_result, 0);
  1151.     if (changes->SMBHostIP)
  1152.     hostip = newtEntry(28, 9, changes->SMBHostIP, 15, &hostip_result, 0);
  1153.     else
  1154.     hostip = newtEntry(28, 9, "", 15, &hostip_result, 0);
  1155.     if (changes->SMBShare)
  1156.     share  = newtEntry(28, 10, changes->SMBShare, 15, &share_result, 0);
  1157.     else
  1158.     share  = newtEntry(28, 10, "", 15, &share_result, 0);
  1159.     if (changes->SMBUser)
  1160.     user   = newtEntry(28, 11, changes->SMBUser, 15, &user_result, 0);
  1161.     else
  1162.     user   = newtEntry(28, 11, "", 15, &user_result, 0);
  1163.     if (changes->SMBPasswd)
  1164.     passwd = newtEntry(28, 12, changes->SMBPasswd, 15, 
  1165.                &passwd_result, NEWT_ENTRY_HIDDEN);
  1166.     else
  1167.     passwd = newtEntry(28, 12, "", 15, &passwd_result, NEWT_ENTRY_HIDDEN);
  1168.  
  1169.     ok = newtButton( 15, 14, NEXT_LABEL);
  1170.     cancel = newtButton( 35, 14, PREV_LABEL);
  1171.     newtFormAddComponents( form, host, hostip, 
  1172.              share, user, passwd, ok, cancel, NULL);
  1173.     answer = newtRunForm(form);
  1174.  
  1175.     if ( answer != cancel ) {
  1176.     free(changes->SMBHost);
  1177.     changes->SMBHost = strdup(host_result);
  1178.     free(changes->SMBHostIP);
  1179.     changes->SMBHostIP = strdup(hostip_result);
  1180.     free(changes->SMBShare);
  1181.     changes->SMBShare = strdup(share_result);
  1182.     free(changes->SMBUser);
  1183.     changes->SMBUser = strdup(user_result);
  1184.     free(changes->SMBPasswd);
  1185.     changes->SMBPasswd = strdup(passwd_result);
  1186.     
  1187.     result = 0;
  1188.     } else
  1189.     result = -1;
  1190.  
  1191.     newtPopWindow();
  1192.     newtFormDestroy(form);
  1193.     return result;
  1194. }
  1195.  
  1196. /* return < 0 for user cancel */
  1197. static int get_std_info( PCEntry *changes ) {
  1198.     newtComponent answer, cancel, form, ok, queue, spool, text;
  1199.     char *queue_result;
  1200.     char *spool_result;
  1201.     int result;
  1202.  
  1203.     newtCenteredWindow(52, 14, "Standard Printer Options");
  1204.     form = newtForm(NULL, NULL, 0);
  1205.  
  1206.     text = newtTextbox(1, 1, 50, 5, NEWT_TEXTBOX_WRAP);
  1207.     newtTextboxSetText(text, 
  1208.     "Every print queue (which print jobs are directed to) needs a "
  1209.     "name (often lp) and a spool directory associated with it. What "
  1210.     "name and directory should be used for this queue? ");
  1211.     
  1212.     newtFormAddComponent(form, newtLabel(2, 7, "Name of queue:"));
  1213.     newtFormAddComponent(form, newtLabel(2, 8, "Spool directory:"));
  1214.     if (changes->Queue)
  1215.     queue =newtEntry(20, 7, changes->Queue, 30, &queue_result, 0);
  1216.     else
  1217.     queue =newtEntry(20, 7, "lp", 30, &queue_result, 0);
  1218.  
  1219.     if (changes->SpoolDir)
  1220.     spool =newtEntry(20, 8, changes->SpoolDir, 30, &spool_result, 0);
  1221.     else
  1222.     spool =newtEntry(20, 8, "/var/spool/lpd/lp", 30, &spool_result, 0);
  1223.  
  1224.     ok = newtButton( 11, 10, NEXT_LABEL);
  1225.     cancel = newtButton( 27, 10, PREV_LABEL);
  1226.     newtFormAddComponents(form, text, queue, spool, ok, cancel, NULL);
  1227.     answer = newtRunForm(form);
  1228.  
  1229.     if ( answer != cancel ) {
  1230.     free(changes->Queue);
  1231.     changes->Queue = strdup(queue_result);
  1232.     free(changes->SpoolDir);
  1233.     changes->SpoolDir = strdup(spool_result);
  1234.     result = 0;
  1235.     } else {
  1236.     result = -1;
  1237.     }
  1238.  
  1239.     newtPopWindow();
  1240.     newtFormDestroy(form);
  1241.     return result;
  1242. }
  1243.  
  1244.  
  1245. static int query_config(void) {
  1246.     int result;
  1247.  
  1248.     result = newtWinChoice("Configure Printer", "Yes", "No", 
  1249.                    "Would you like to configure a printer?");
  1250.     
  1251.     if (result == 1) 
  1252.     return -1;
  1253.     return 0;
  1254. }
  1255.  
  1256. #if 0
  1257. static int query_add_more() {
  1258.     int result;
  1259.  
  1260.     result = newtWinChoice("Add Printer", "Yes", "No", 
  1261.                    "Would you like to add another printer?");
  1262.  
  1263.     if (result == 1) 
  1264.     return -1;
  1265.     return 0;
  1266. }
  1267. #endif
  1268.  
  1269. /* returns 1 if they want to quit, 0 otherwise */
  1270. static int you_are_sure(void) {
  1271.     int result;
  1272.  
  1273.     result = newtWinChoice("Confirm Termination", "Exit", "Continue", 
  1274.                "If you choose 'Exit', you will return to the main "
  1275.                "installation without a printer being configured.\n\n"
  1276.                 "Choose 'Continue' to return to configuring "
  1277.                "your printer.");
  1278.  
  1279.     if (result == 1) return 0;
  1280.     return 1;
  1281. }
  1282.  
  1283.  
  1284. /* returns < 0 for user cancel, otherwise uses #defines in printercfg.h */
  1285. static int get_prn_connx( char *Type ) {
  1286.     newtComponent answer, cancel, form, ok, listbox;
  1287.     int sel;
  1288.  
  1289.     newtCenteredWindow(33, 12, "Select Printer Connection");
  1290.     form = newtForm(NULL, NULL, 0);
  1291.     newtFormAddComponent(form,
  1292.              newtLabel(1, 1, "How is this printer connected?"));
  1293.     
  1294.     listbox = newtListbox(9, 3, 0, NEWT_FLAG_NOSCROLL | NEWT_FLAG_RETURNEXIT);
  1295.     newtListboxAddEntry(listbox, "Local", (void *)LOCAL_CONNX);
  1296.     newtListboxAddEntry(listbox, "Remote lpd", (void *)REMOTE_LPD_CONNX);
  1297.     newtListboxAddEntry(listbox, "LAN Manager", (void *)SMB_CONNX);
  1298.  
  1299.     if (Type)
  1300.     if (!strcmp(Type,"LOCAL"))
  1301.         newtListboxSetCurrent(listbox, 0);
  1302.     else if (!strcmp(Type,"REMOTE"))
  1303.         newtListboxSetCurrent(listbox, 1);
  1304.     else if (!strcmp(Type,"SMB"))
  1305.         newtListboxSetCurrent(listbox, 2);
  1306.     
  1307.     ok = newtButton( 4, 7, NEXT_LABEL);
  1308.     cancel = newtButton( 17, 7, "Cancel");
  1309.     newtFormAddComponents(form, listbox, ok, cancel, NULL);
  1310.  
  1311.     answer = newtRunForm(form);
  1312.  
  1313.     if ( answer == cancel ) {
  1314.     newtPopWindow();
  1315.     newtFormDestroy(form);
  1316.     return -1;
  1317.     } else {
  1318.     sel = (long) newtListboxGetCurrent(listbox);
  1319.     newtPopWindow();
  1320.     newtFormDestroy(form);
  1321.     return sel;
  1322.     }
  1323. }
  1324.  
  1325. /* edit the PrintCap Entry pcentry */
  1326. /* return < 0 if user aborts or error occurs */
  1327. static int edit_pcentry( PCEntry **pcentry ) {
  1328.  
  1329.     int result;
  1330.     int stage;
  1331.     int done;
  1332.     int abort;
  1333.     PCEntry *changes;
  1334.  
  1335.     /* copy current into temporary */
  1336.     changes = dup_PCEntry( *pcentry );
  1337.  
  1338.     done = 0;
  1339.     abort = 0;
  1340.     stage = 0;
  1341.  
  1342.     while (!done) {
  1343.  
  1344.     switch (stage) {
  1345.       case 0:
  1346.         switch (get_prn_connx(changes->Type)) {
  1347.           case -1:
  1348.         if (you_are_sure()) {
  1349.             done = 1;
  1350.             abort = 1;
  1351.         }
  1352.         break;
  1353.         
  1354.           case LOCAL_CONNX:
  1355.         free(changes->Type);
  1356.         changes->Type = strdup("LOCAL");
  1357.         stage++;
  1358.         break;
  1359.       
  1360.           case REMOTE_LPD_CONNX:
  1361.         free(changes->Type);
  1362.         changes->Type = strdup("REMOTE");
  1363.         stage++;
  1364.         break;
  1365.         
  1366.           case SMB_CONNX:
  1367.         free(changes->Type);
  1368.         changes->Type = strdup("SMB");
  1369.         stage++;
  1370.         break;
  1371.       
  1372.           default:
  1373.         break;
  1374.         }
  1375.         break;
  1376.       
  1377.       case 1:
  1378.             result=get_std_info(changes);
  1379.         if (result < 0)
  1380.         stage--;
  1381.         else 
  1382.         stage++;
  1383.         break;
  1384.  
  1385.       case 2:
  1386.         if (!strcmp(changes->Type, "SMB"))
  1387.         result=get_smb_info(changes);
  1388.         else if (!strcmp(changes->Type, "REMOTE"))
  1389.         result=get_remote_info(changes);
  1390.         else if (!strcmp(changes->Type, "LOCAL"))
  1391.         result=get_local_info(changes);
  1392.         else
  1393.         return -1;
  1394.  
  1395.         if (result < 0)
  1396.         stage--;
  1397.         else
  1398.         stage++;
  1399.         break;
  1400.  
  1401.       case 3:
  1402.         result=select_filter(changes);
  1403.         if (result < 0)
  1404.         stage--;
  1405.         else
  1406.         stage++;
  1407.         break;
  1408.  
  1409.       case 4:
  1410.         done = 1;
  1411.         break;
  1412.     }
  1413.     }
  1414.  
  1415.     if (!abort) {
  1416.     free_PCEntry(*pcentry);
  1417.     *pcentry = changes;
  1418.     return 0;
  1419.     } else {
  1420.     free_PCEntry(changes);
  1421.     return -1;
  1422.     }
  1423. }
  1424.  
  1425. /* returns 0 on success, -1 on abort, and -2 if user wishes to re-edit */
  1426. static int verify_pcentry( PCEntry *pcentry ) {
  1427.  
  1428.     newtComponent form, ok, edit, cancel, answer;
  1429.     char tmpstr[256];
  1430.     int row;
  1431.     int done;
  1432.     int result;
  1433.  
  1434.     newtCenteredWindow(60, 18, "Verify Printer Configuration");
  1435.     form = newtForm(NULL, NULL, 0);
  1436.  
  1437.     newtFormAddComponent(form, newtLabel(3, 1, 
  1438.         "Please verify that this printer information is correct:"));
  1439.  
  1440.     row=3;
  1441.     sprintf(tmpstr, "Printer Type    : %s\n",pcentry->Type);
  1442.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1443.  
  1444.     sprintf(tmpstr, "Queue           : %s\n",pcentry->Queue);
  1445.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1446.  
  1447.     sprintf(tmpstr, "Spool directory : %s\n",pcentry->SpoolDir);
  1448.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1449.  
  1450.     if (!strcmp(pcentry->Type, "LOCAL")) {
  1451.     sprintf(tmpstr, "Printer device  : %s\n",pcentry->Device);
  1452.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1453.     } else if (!strcmp(pcentry->Type, "REMOTE")) {
  1454.     sprintf(tmpstr, "Remote Host     : %s\n",pcentry->RemoteHost);
  1455.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1456.     sprintf(tmpstr, "Remote Queue    : %s\n",pcentry->RemoteQueue);
  1457.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1458.     } else if (!strcmp(pcentry->Type, "SMB")) {
  1459.     if (pcentry->SMBHostIP && pcentry->SMBHostIP[0])
  1460.         sprintf(tmpstr, "Server          : %s [%s]\n",
  1461.             pcentry->SMBHost, pcentry->SMBHostIP);
  1462.     else
  1463.         sprintf(tmpstr, "Server          : %s\n",pcentry->SMBHost);
  1464.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1465.     sprintf(tmpstr, "Share           : %s\n",pcentry->SMBShare);
  1466.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1467.     sprintf(tmpstr, "User            : %s  <Password hidden>\n",
  1468.         pcentry->SMBUser);
  1469.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1470.     }
  1471.  
  1472.     sprintf(tmpstr, "Printer Driver  : %s\n",pcentry->db->Descr);
  1473.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1474.  
  1475.     sprintf(tmpstr, "Paper Size      : %s\n",pcentry->PaperSize);
  1476.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1477.  
  1478.     sprintf(tmpstr, "Resolution      : %s\n",pcentry->Resolution);
  1479.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1480.  
  1481.     sprintf(tmpstr, "Bits Per Pixel  : %s\n",pcentry->BitsPerPixel);
  1482.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1483.  
  1484.  
  1485.     ok = newtButton( 11, 14,   "Done");
  1486.     edit = newtButton( 26, 14, "Edit");
  1487.     cancel = newtButton( 41, 14, "Cancel");
  1488.     newtFormAddComponents( form, ok, edit, cancel, NULL);
  1489.  
  1490.     done = 0;
  1491.     result = 0;
  1492.     while (!done) {
  1493.     answer = newtRunForm(form);
  1494.  
  1495.     if ( answer == cancel ) {
  1496.         if (you_are_sure()) {
  1497.         done = 1;
  1498.         result = -1;
  1499.         }
  1500.     } else if (answer == edit) {
  1501.         done = 1;
  1502.         result = -2;
  1503.     } else {
  1504.         done = 1;
  1505.         result = 0;
  1506.     }
  1507.     }
  1508.  
  1509.     newtPopWindow();
  1510.     newtFormDestroy(form);
  1511.  
  1512.     return result;
  1513. }
  1514.  
  1515. /* given the path queue_path, we create all the required spool directory */
  1516. static int create_spool_dir( char *queue_path ) {
  1517.     int result, done;
  1518.     int oldmask;
  1519.     
  1520.     struct group *grent;
  1521.     gid_t lpgid = 0;
  1522.     
  1523.     FILE *groupfile;
  1524.     char groupfilename[80];
  1525.     
  1526.  
  1527.     oldmask=umask(0);
  1528.     result=mkdir(queue_path, 0755);
  1529.     if ( result < 0)
  1530.     if (errno != EEXIST)
  1531.         return -1;
  1532.     umask(oldmask);
  1533.   
  1534.     strcpy(groupfilename, root_path);
  1535.     strcat(groupfilename, "/etc/group");
  1536.     if ((groupfile=fopen(groupfilename, "r"))==NULL)
  1537.     return -1;
  1538.     
  1539.     done=0;
  1540.     while (!done) {
  1541.     grent=fgetgrent(groupfile);
  1542.     if (grent==NULL)
  1543.         return -1;
  1544.       
  1545.     if (!strcmp(grent->gr_name, "lp")) {
  1546.         lpgid=grent->gr_gid;
  1547.         done |= 2;
  1548.     }
  1549.     }
  1550.  
  1551.     fclose(groupfile);
  1552.   
  1553.     if (!done)
  1554.     return -1;
  1555.   
  1556.     result=chown(queue_path, 0, lpgid );
  1557.     if ( result < 0)
  1558.     return -1;
  1559.  
  1560.     return 0;
  1561. }
  1562.  
  1563.  
  1564. /* given the input spec file 'input', and the target output file 'output' */
  1565. /* we set the fields specified by fieldname to the values in fieldval     */
  1566. /* nval  is the number of fields to set                                   */
  1567. /* Doesnt currently catch error exec'ing sed yet                          */
  1568. static int create_config_file( char *input, char *output, 
  1569.             char **fieldname, char **fieldval, 
  1570.             int nval ) {
  1571.     int status;
  1572.     int infd, outfd;
  1573.     int childpid;
  1574.     int i, j;
  1575.     
  1576.     int oldmask;
  1577.  
  1578.     char **sedargs;
  1579.     char *sedcmd;
  1580.     
  1581.     oldmask = umask(0);
  1582.     
  1583.     outfd=creat(output, 0755 );
  1584.     umask(oldmask);
  1585.     if (outfd == -1)
  1586.     return -1;
  1587.   
  1588.     infd=open(input, O_RDONLY);
  1589.     if (infd == -1)
  1590.     return -1;
  1591.  
  1592.     /* we have to setup the args to sed */
  1593.     /* need the name to exec, plus 2 args per field, plus NULL at end */
  1594.     sedargs = (char **) malloc( (nval + 2) * sizeof( char * ) );
  1595.     if (!sedargs)
  1596.     return -1;
  1597.  
  1598.     sedargs[0] = "/bin/sed";
  1599.     sedargs[nval+1] = NULL;
  1600.     for (i=0; i<nval; i++) {
  1601.     sedargs[i+1] = (char *) malloc(25 + strlen(fieldname[i]) +
  1602.                        strlen(fieldval[i]));
  1603.     /* if we get an error, try to cleanup */
  1604.     if (!sedargs[i+1]) {
  1605.         for (j=0; j<i; j++)
  1606.         if (sedargs[j+1])
  1607.             free(sedargs[j+1]);
  1608.         
  1609.         if (sedargs)
  1610.         free(sedargs);
  1611.         
  1612.         return -1;
  1613.     }
  1614.     sprintf(sedargs[i+1], "-e s/@@@%s@@@/%s/g", fieldname[i], fieldval[i]);
  1615.     }
  1616.  
  1617.     sedcmd = malloc(strlen(root_path)+15);
  1618.     if (!sedcmd)
  1619.     return -1;
  1620.     
  1621.     strcpy(sedcmd, root_path);
  1622.     strcat(sedcmd, "/bin/sed");
  1623.     
  1624.     if (!(childpid = fork())) {
  1625.     close(0);
  1626.     close(1);
  1627.     dup2(infd, 0);
  1628.     dup2(outfd, 1);
  1629.     close(infd);
  1630.     close(outfd);
  1631.     execv(sedcmd, sedargs);
  1632.     exit(-1);
  1633.     }
  1634.  
  1635.     close(infd);
  1636.     close(outfd);
  1637.  
  1638.     waitpid(childpid, &status, 0);
  1639.  
  1640.     if (sedcmd)
  1641.     free(sedcmd);
  1642.  
  1643.     for (i=0; i<nval; i++)
  1644.     if (sedargs[i+1])
  1645.         free(sedargs[i+1]);
  1646.  
  1647.     if (sedargs)
  1648.     free(sedargs);
  1649.  
  1650.     return 0;
  1651. }
  1652.  
  1653. /* copy master filter to the spool dir */
  1654. static int copy_master_filter( char *queue_path ) {
  1655.     int childpid, status;
  1656.     char *masterfilter, *cpcmd, *dest;
  1657.     
  1658.     masterfilter=malloc(strlen(PRINTER_FILTER_DIR)+strlen(root_path)+20);
  1659.     strcpy(masterfilter,root_path);
  1660.     strcat(masterfilter,PRINTER_FILTER_DIR);
  1661.     strcat(masterfilter,"master-filter");
  1662.     
  1663.     dest=malloc(strlen(queue_path)+20);
  1664.     strcpy(dest,queue_path);
  1665.     strcat(dest,"filter");
  1666.     
  1667.     cpcmd = malloc(strlen(root_path)+15);
  1668.     if (!cpcmd)
  1669.     return -1;
  1670.     
  1671.     strcpy(cpcmd, root_path);
  1672.     strcat(cpcmd, "/bin/cp");
  1673.     
  1674.     if (!(childpid = fork())) 
  1675.     execl(cpcmd, cpcmd, masterfilter, dest, NULL);
  1676.  
  1677.     waitpid(childpid, &status, 0);
  1678.     
  1679.     free(masterfilter);
  1680.     free(cpcmd);
  1681.     free(dest);
  1682.     return 0;
  1683. }
  1684.  
  1685. /* given a PrintCap Entry, create the spool dir and special */
  1686. /* rhs-printfilters related config files which are required */
  1687. static int configure_queue( PCEntry *pcentry ) {
  1688.     char *queue_path;
  1689.     char *output;
  1690.     char *input;
  1691.     char colorstr[80]; /* holds the '-dBitsPerPixel=nn' */
  1692.     
  1693.     char **fieldname;
  1694.     char **fieldval;
  1695.     int  nfield;
  1696.  
  1697.     FILE *printcap, *smbconfig;
  1698.  
  1699.     if (testing) return 0;
  1700.     
  1701.     if (pcentry->SpoolDir) {
  1702.     /* create the spooldir and set to root.lp ownership */
  1703.     queue_path=malloc(strlen(root_path)+strlen(pcentry->SpoolDir)+5);
  1704.     strcpy(queue_path, root_path);
  1705.     strcat(queue_path, pcentry->SpoolDir);
  1706.     strcat(queue_path, "/");
  1707.     if (create_spool_dir(queue_path) < 0)
  1708.         return -1;
  1709.     
  1710.     /* make the cfg files we need */
  1711.     output=malloc(strlen(queue_path)+strlen("general.cfg")+2);
  1712.     strcpy(output,queue_path);
  1713.     strcat(output,"general.cfg");
  1714.     input=malloc(strlen(root_path)+strlen(PRINTER_FILTER_DIR)+
  1715.              strlen("general.cfg.in")+2);
  1716.     strcpy(input,root_path);
  1717.     strcat(input,PRINTER_FILTER_DIR);
  1718.     strcat(input,"general.cfg.in");
  1719.  
  1720.     /* setup the field arrays */
  1721.     nfield = 4;
  1722.     fieldname = (char **) malloc( nfield * sizeof(char *) );
  1723.     fieldname[0] = "desiredto";
  1724.     fieldname[1] = "papersize";
  1725.     fieldname[2] = "printertype";
  1726.     fieldname[3] = "ascps_trans";
  1727.     
  1728.     fieldval = (char **) malloc( nfield * sizeof(char *) );
  1729.  
  1730.     if (strcmp(pcentry->db->GSDriver, "TEXT"))
  1731.         fieldval[0] = "ps";
  1732.     else
  1733.         fieldval[0] = "asc";
  1734.  
  1735.     if (!pcentry->PaperSize)
  1736.         fieldval[1] = "letter";
  1737.     else
  1738.         fieldval[1] = pcentry->PaperSize;
  1739.  
  1740.     fieldval[2] = pcentry->Type;
  1741.     
  1742.     if (strcmp(pcentry->db->GSDriver, "POSTSCRIPT"))
  1743.         fieldval[3] = "NO";
  1744.     else
  1745.         fieldval[3] = "YES";
  1746.  
  1747.     if (create_config_file(input, output, fieldname, fieldval, nfield) < 0)
  1748.         return -1;
  1749.  
  1750.     /* successfully created general.cfg, now do postscript.cfg */
  1751.     free(fieldname);
  1752.     free(fieldval);
  1753.     free(output);
  1754.     free(input);
  1755.  
  1756.     output=malloc(strlen(queue_path)+strlen("postscript.cfg")+2);
  1757.     strcpy(output,queue_path);
  1758.     strcat(output,"postscript.cfg");
  1759.     input=malloc(strlen(root_path)+strlen(PRINTER_FILTER_DIR)+
  1760.              strlen("postscript.cfg.in")+2);
  1761.     strcpy(input,root_path);
  1762.     strcat(input,PRINTER_FILTER_DIR);
  1763.     strcat(input,"postscript.cfg.in");
  1764.  
  1765.     /* setup the field arrays */
  1766.     nfield = 10;
  1767.     fieldname = (char **) malloc( nfield * sizeof(char *) );
  1768.     fieldname[0] = "gsdevice";
  1769.     fieldname[1] = "papersize";
  1770.     fieldname[2] = "resolution";
  1771.     fieldname[3] = "color";
  1772.     fieldname[4] = "reversepages";
  1773.     fieldname[5] = "extragsoptions";
  1774.     fieldname[6] = "pssendeof";
  1775.     fieldname[7] = "nup";
  1776.     fieldname[8] = "rtlftmar";
  1777.     fieldname[9] = "topbotmar";
  1778.     
  1779.     fieldval = (char **) malloc( nfield * sizeof(char *) );
  1780.     
  1781.     /* gsdriver */
  1782.     fieldval[0] = pcentry->db->GSDriver;
  1783.     
  1784.     /* papersize */
  1785.     if (!pcentry->PaperSize)
  1786.         fieldval[1] = "letter";
  1787.     else
  1788.         fieldval[1] = pcentry->PaperSize;
  1789.     
  1790.     /* resolution */
  1791.     if (!pcentry->Resolution)
  1792.         fieldval[2] = "";
  1793.     else
  1794.         if (strcmp(pcentry->Resolution,"Default"))
  1795.         fieldval[2] = pcentry->Resolution;
  1796.         else
  1797.         fieldval[2] = "";
  1798.  
  1799.     /* color depth */
  1800.     if (!pcentry->BitsPerPixel)
  1801.         fieldval[3] = "";
  1802.     else
  1803.         if (strcmp(pcentry->BitsPerPixel,"Default")) {
  1804.         strcpy(colorstr,"-dBitsPerPixel=");
  1805.         strcat(colorstr,pcentry->BitsPerPixel);
  1806.         fieldval[3] = colorstr;
  1807.         } else
  1808.         fieldval[3] = "";
  1809.     
  1810.     /* reverse pages? */
  1811.     if (!pcentry->RevPages)
  1812.         fieldval[4] = "";
  1813.     else
  1814.         fieldval[4] = pcentry->RevPages;
  1815.  
  1816.     /* extra gs options */
  1817.     fieldval[5] = "";
  1818.  
  1819.     /* ps send eof */
  1820.     if (strcmp(pcentry->db->GSDriver, "POSTSCRIPT"))
  1821.         fieldval[6] = "NO";
  1822.     else
  1823.         fieldval[6] = "YES";
  1824.  
  1825.     /* nup */
  1826.     fieldval[7] = "1";
  1827.     
  1828.     /* rtlftmar */
  1829.     fieldval[8] = "18";
  1830.     
  1831.     /* topbotmar */
  1832.     fieldval[9] = "18";
  1833.     
  1834.     if (create_config_file(input, output, fieldname, fieldval, nfield) < 0)
  1835.         return -1;
  1836.     
  1837.     /* finally, make textonly.cfg */
  1838.     free(fieldval);
  1839.     free(fieldname);
  1840.     free(output);
  1841.     free(input);
  1842.     
  1843.     output=malloc(strlen(queue_path)+strlen("textonly.cfg")+2);
  1844.     strcpy(output,queue_path);
  1845.     strcat(output,"textonly.cfg");
  1846.     input=malloc(strlen(root_path)+strlen(PRINTER_FILTER_DIR)+
  1847.              strlen("textonly.cfg.in")+2);
  1848.     strcpy(input,root_path);
  1849.     strcat(input,PRINTER_FILTER_DIR);
  1850.     strcat(input,"textonly.cfg.in");
  1851.     
  1852.     /* setup the field arrays */
  1853.     nfield = 3;
  1854.     fieldname = (char **) malloc( nfield * sizeof(char *) );
  1855.     fieldname[0] = "textonlyoptions";
  1856.     fieldname[1] = "crlftrans";
  1857.     fieldname[2] = "textsendeof";
  1858.     
  1859.     fieldval = (char **) malloc( nfield * sizeof(char *) );
  1860.     fieldval[0] = "";
  1861.     if (!pcentry->CRLF)
  1862.         fieldval[1] = "";
  1863.     else
  1864.         fieldval[1] = pcentry->CRLF;
  1865.     fieldval[2] = "YES";
  1866.     
  1867.     if (create_config_file(input, output, fieldname, fieldval, nfield) < 0)
  1868.         return -1;
  1869.     
  1870.     /* simple config file required if SMB printer */
  1871.     if (!strcmp(pcentry->Type, "SMB")) {
  1872.         output=malloc(strlen(queue_path)+15);
  1873.         strcpy(output,queue_path);
  1874.         strcat(output,".config");
  1875.         smbconfig = fopen(output, "w");
  1876.         
  1877.         fprintf(smbconfig,"share='\\\\%s\\%s'\n",
  1878.             pcentry->SMBHost, pcentry->SMBShare);
  1879.         fprintf(smbconfig,"hostip=%s\n",pcentry->SMBHostIP);
  1880.         fprintf(smbconfig,"user=%s\n",pcentry->SMBUser);
  1881.         fprintf(smbconfig,"password=%s\n",pcentry->SMBPasswd);
  1882.  
  1883.         fclose(smbconfig);
  1884.     }
  1885.  
  1886.     /* we're done with config files - need to copy filter over now  */
  1887.     free(fieldval);
  1888.     free(fieldname);
  1889.     free(output);
  1890.     free(input);
  1891.     
  1892.     if ( copy_master_filter(queue_path) < 0 )
  1893.         return -1;
  1894.     } else
  1895.     return -1; /* we have to have a spool dir! */
  1896.  
  1897.     /* assume that spool dir got setup ok, now add printcap entry */
  1898.     output=alloca(strlen("/etc/printcap")+strlen(root_path)+2);
  1899.     strcpy(output,root_path);
  1900.     strcat(output,"/etc/printcap");
  1901.     if (access(output, F_OK)) {
  1902.     printcap=fopen(output, "w");
  1903.     if (printcap == NULL)
  1904.         return -1;
  1905.     
  1906.     fputs("#\n", printcap);
  1907.     fputs("# Please don't edit this file directly unless you know what "
  1908.         "you are doing!\n", printcap);
  1909.     fputs("# Be warned that the control-panel printtool requires a very "
  1910.         "strict format!\n", printcap);
  1911.     fputs("# Look at the printcap(5) man page for more info.\n", printcap);
  1912.     fputs("#\n", printcap);
  1913.     fputs("# This file can be edited with the printtool in the "
  1914.         "control-panel.\n", printcap);
  1915.     fputs("\n", printcap);
  1916.  
  1917.     fclose(printcap);
  1918.     }
  1919.  
  1920.     printcap = fopen(output, "a");
  1921.     
  1922.     fputs("\n",printcap);
  1923.     fprintf(printcap, "##PRINTTOOL3## %s %s %s %s %s %s %s %s \n",
  1924.         pcentry->Type,
  1925.         pcentry->db->GSDriver,
  1926.         pcentry->Resolution,
  1927.         pcentry->PaperSize,
  1928.         "{}",
  1929.         pcentry->db->Entry,
  1930.         pcentry->BitsPerPixel,
  1931.         "{}");
  1932.     fprintf(printcap, "%s:\\\n",pcentry->Queue);
  1933.     fprintf(printcap, "\t:sd=%s:\\\n",pcentry->SpoolDir);
  1934.     fprintf(printcap, "\t:mx#0:\\\n\t:sh:\\\n");
  1935.     
  1936.     if (!strcmp(pcentry->Type, "LOCAL")) {
  1937.     fprintf(printcap,"\t:lp=%s:\\\n",pcentry->Device);
  1938.     } else if (!strcmp(pcentry->Type, "REMOTE")) {
  1939.     fprintf(printcap,"\t:rm=%s:\\\n",pcentry->RemoteHost);
  1940.     fprintf(printcap,"\t:rp=%s:\\\n",pcentry->RemoteQueue);
  1941.     } else if (!strcmp(pcentry->Type, "SMB")) {
  1942.     fprintf(printcap,"\t:lp=/dev/null:\\\n");
  1943.     fprintf(printcap,"\t:af=%s/%s\\\n",pcentry->SpoolDir,"acct");
  1944.     }
  1945.  
  1946.     /* cheating to get the input filter! */
  1947.     fprintf(printcap,"\t:if=%s/%s:\n",pcentry->SpoolDir,"filter");
  1948.     fclose(printcap);
  1949.     return 0;
  1950. }
  1951.  
  1952.  
  1953. int doConfigurePrinters (char *theroot) {
  1954.  
  1955.   int done, result;
  1956.   PCEntry *pcentry = NULL;
  1957.  
  1958.   /* root under which the installed system lives */
  1959.   root_path = theroot;
  1960.  
  1961.   /* read the printer database into memory -- ignore these errors as they
  1962.      probably indicate missing packages */
  1963.   if (read_printer_db(PRINTER_DB_FILE)) return INST_NOP;
  1964.  
  1965.   install_return_code = 0;
  1966.   done = 0;
  1967.  
  1968.   if (!query_config()) {
  1969.       pcentry = new_PCEntry();
  1970.  
  1971.       /* setup some defaults needed for all printer types */
  1972.       pcentry->AutoEOF = strdup("NO");
  1973.       pcentry->CRLF = strdup("NO");
  1974.       pcentry->RevPages = strdup("NO");
  1975.  
  1976.       result = edit_pcentry( &pcentry );
  1977.       
  1978.       while ((result != -1) && (result=verify_pcentry( pcentry ))==-2) 
  1979.       result = edit_pcentry( &pcentry );
  1980.       
  1981.       if (result == -1)
  1982.       free_PCEntry( pcentry );
  1983.       else {
  1984.       configure_queue( pcentry );
  1985.       free_PCEntry( pcentry );
  1986.       install_return_code=0;
  1987.       }
  1988.   }
  1989.  
  1990.   return install_return_code;
  1991. }
  1992.  
  1993.  
  1994. #ifdef TESTING
  1995. int testing = 1;
  1996.  
  1997. int main() {
  1998.     int result;
  1999.  
  2000.     /* get the type of connection we want */
  2001.     newtInit();
  2002.     newtCls();
  2003.     newtPushHelpLine(NULL);
  2004.     newtDrawRootText(0, 0, "Printer Config - (C) 1997 Red Hat Software");
  2005.  
  2006.     result = doConfigurePrinters( "/" );
  2007.  
  2008.     newtFinished();
  2009.  
  2010.     printf("The result code is %d\n",result);
  2011.  
  2012.     return result;
  2013. }
  2014. #endif
  2015.      
  2016.