home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / install / .#printercfg.c.1.12 < prev    next >
Text File  |  1997-10-09  |  52KB  |  2,013 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 <unistd.h>
  15. #include <strings.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. /* used by below routines - assumes everything is malloc'd          */
  485. /* updates old to new if new is non-NULL                            */
  486. /* frees the old value and points it at the new                     */
  487. /* if new is NULL, means it wasnt updated and old remains unchanged */
  488. static void update_changed( void *new, void **old ) {
  489.     if (new) {
  490.     if (*old) 
  491.         free(*old);
  492.     *old = new;
  493.     }
  494. }
  495.  
  496. /* display summary line given by char * arg */
  497. void show_printer_about( char *about ) {
  498.     newtComponent infoform, infook, infobox, answer;
  499.     
  500.     newtCenteredWindow(56, 15, "Printer Info");
  501.     infoform = newtForm(NULL, NULL, 0);
  502.     infobox=newtTextbox(3, 2, 50, 8, 
  503.             NEWT_TEXTBOX_WRAP|NEWT_TEXTBOX_SCROLL);
  504.     newtTextboxSetText( infobox, about );
  505.     infook = newtButton( 23, 11, "Ok");
  506.         
  507.     newtFormAddComponents(infoform, infobox, infook, NULL);
  508.     answer = newtRunForm( infoform );
  509.  
  510.     newtPopWindow();
  511.     newtFormDestroy(infoform);
  512. }
  513.  
  514. /* select the printer type you have */
  515. /* return < 0 if user aborted */
  516. /* returns index into thedb[] of the selected entry otherwise*/
  517. static int select_printer_type( PCEntry *changes) {
  518.     newtComponent ok, cancel, form, listbox, answer;
  519.     struct newtExitStruct event;
  520.     long i, sel;
  521.     int formdone;
  522.     char *origtype;
  523.  
  524.     if (changes->db && changes->db->Descr) {
  525.     origtype = alloca(strlen(changes->db->Descr)+2);
  526.     strcpy(origtype, changes->db->Descr);
  527.     } else
  528.     origtype = NULL;
  529.     
  530.     newtCenteredWindow(60, 18, "Configure Printer");
  531.     newtPushHelpLine("<F1> will give you information on a particular "
  532.              "printer type");
  533.     form = newtForm(NULL, NULL, 0);
  534.     newtFormAddComponent(form, newtLabel(3, 1, "What type of printer "
  535.                      "do you have?"));
  536.     listbox = newtListbox(6, 3, 10, NEWT_FLAG_RETURNEXIT);
  537.     for (i = 0; i < numdb; i++) {
  538.     newtListboxAddEntry(listbox, thedb[i]->Descr, (void *)i);
  539.     
  540.     if (changes->db && changes->db->Entry &&
  541.         !strcmp(changes->db->Entry,thedb[i]->Entry)) {
  542.         newtListboxSetCurrent(listbox, i);
  543.     }
  544.     }
  545.  
  546.     /* if no selection yet, default to PostScript if it exists */
  547.     if (changes->db==NULL || changes->db->Entry==NULL  ) {
  548.     /* set this just in case we find nothing that matches */
  549.     newtListboxSetCurrent(listbox, 0);
  550.     for (i = 0; i < numdb; i++)
  551.         if (!strcmp(thedb[i]->Descr,"PostScript printer")) {
  552.         newtListboxSetCurrent(listbox, i);
  553.         break;
  554.         }
  555.     }
  556.     
  557.     ok = newtButton( 15, 14, NEXT_LABEL);
  558.     cancel = newtButton( 31, 14, PREV_LABEL);
  559.     newtFormAddComponents( form, listbox, ok, cancel, NULL);
  560.     newtFormAddHotKey(form, NEWT_KEY_F1); 
  561.     
  562.     formdone = 0;
  563.     answer = NULL;
  564.     while (!formdone) {
  565.     newtFormRun(form, &event);
  566.     
  567.     if (event.reason == NEWT_EXIT_HOTKEY) {
  568.         if (event.u.key == NEWT_KEY_F12)
  569.         formdone = 1;
  570.         else if (event.u.key == NEWT_KEY_F1) {
  571.         show_printer_about(
  572.             thedb[(long)newtListboxGetCurrent(listbox)]->About);
  573.         }
  574.     } else if (event.reason == NEWT_EXIT_COMPONENT) {
  575.         formdone = 1;
  576.         if (event.u.co == cancel)
  577.         answer = cancel;
  578.     }
  579.     }
  580.     
  581.     sel = (long) newtListboxGetCurrent(listbox);
  582.     
  583.     newtPopWindow();
  584.     newtPopHelpLine();
  585.     newtFormDestroy(form);
  586.     
  587.     if ( answer == cancel )
  588.     return -1;
  589.  
  590.     /* store new values */
  591.     changes->db = thedb[sel];
  592.  
  593.     /* MAJOR HACK */
  594.     /* if the printer is an HP, lets do stairstep correction */
  595.     if (!strncmp(changes->db->Descr,"HP",2)) {
  596.     if (changes->CRLF)
  597.         free(changes->CRLF);
  598.     changes->CRLF=strdup("YES");
  599.     } else {
  600.     if (origtype) {
  601.         if (strcmp(origtype, changes->db->Descr)) {
  602.         if (changes->CRLF)
  603.             free(changes->CRLF);
  604.         changes->CRLF=strdup("NO");
  605.         }
  606.     } else  {
  607.         if (changes->CRLF)
  608.         free(changes->CRLF);
  609.         changes->CRLF=strdup("NO");
  610.     }
  611.     }
  612.  
  613.     return sel;
  614. }    
  615.     
  616.  
  617. /* select the paper size and printer resolution you want */
  618. /* return < 0 if user aborted */
  619. /* returns 0 otherwise */
  620. static int select_paper_size_and_res( PCEntry *changes ) {
  621.     newtComponent ok, cancel, form, text, papersz, res, answer, crlf;
  622.     struct newtExitStruct event;
  623.     long i;
  624.     int j;
  625.     int formdone;
  626.     int xpos;
  627.     int maxlen;
  628.  
  629.     char **reslines;
  630.     char crlfret;
  631.     
  632.     /* there has to be a current selection for this to work! */
  633.     if (changes->db == NULL)
  634.     return -1;
  635.     
  636.     newtCenteredWindow(54, 18, changes->db->Descr); 
  637.     newtPushHelpLine("<F1> will give you information on this "
  638.              "printer driver.");
  639.     form = newtForm(NULL, NULL, 0);
  640.     text = newtTextbox(1, 1, 52, 2, NEWT_TEXTBOX_WRAP);
  641.     newtTextboxSetText(text, 
  642.                "You may now configure the paper size and resolution "
  643.                "for this printer.");
  644.     newtFormAddComponent(form, text);
  645.  
  646.     /* Paper size listbox */
  647.     newtFormAddComponent(form, newtLabel(7, 4, "Paper Size"));
  648.     papersz = newtListbox( 8, 5, 5, NEWT_FLAG_NOSCROLL );
  649.     for (i=0; i < NUM_PAPERSIZES; i++) {
  650.     newtListboxAddEntry( papersz, PaperSizes[i], (void *)i );
  651.     if (changes->PaperSize &&
  652.         !strcmp(changes->PaperSize, PaperSizes[i]))
  653.         newtListboxSetCurrent(papersz, i);
  654.     }
  655.  
  656.     /* make sure something is picked */
  657.     if (changes->PaperSize==NULL)
  658.     newtListboxSetCurrent(papersz, 0);
  659.  
  660.     /* Resolution */
  661.     if ( changes->db->NumRes > 0) {
  662.     maxlen = 0;
  663.     reslines = (char **) alloca( changes->db->NumRes * sizeof(char *));
  664.     for (i=0; i < changes->db->NumRes; i++) {
  665.         if (changes->db->ResDescr && changes->db->ResDescr[i]) {
  666.         reslines[i]=alloca(strlen(changes->db->Resolution[i])+
  667.                    strlen(changes->db->ResDescr[i])+15);
  668.         /* we want the 'x' in the 5th column */
  669.         xpos = (strchr(changes->db->Resolution[i],'x')-
  670.             changes->db->Resolution[i]);
  671.         for (j=0; j<5-xpos; j++)
  672.             reslines[i][j]=' ';
  673.         reslines[i][j]='\000';
  674.         strcat(reslines[i],changes->db->Resolution[i]);
  675.         /* pad to 13 spaces */
  676.         for (j=strlen(reslines[i]); j < 13; j++)
  677.             strcat(reslines[i], " ");
  678.         strcat(reslines[i],changes->db->ResDescr[i]);
  679.         } else {
  680.         reslines[i]=alloca(strlen(changes->db->Resolution[i])+2);
  681.         strcat(reslines[i],changes->db->Resolution[i]);
  682.         }
  683.         if (strlen(reslines[i]) > maxlen)
  684.         maxlen = strlen(reslines[i]);
  685.         
  686.     }
  687.  
  688.     newtFormAddComponent(form, newtLabel(34, 4, "Resolution"));
  689.     res = newtListbox( 37-maxlen/2, 5, 5, 0 );
  690.  
  691.     for (i=0; i < changes->db->NumRes; i++) {
  692.         newtListboxAddEntry( res, reslines[i], (void *)i );
  693.         if (changes->Resolution &&
  694.         !strcmp(changes->Resolution, changes->db->Resolution[i]))
  695.         newtListboxSetCurrent(res, i);
  696.     }
  697.     } else {
  698.     newtFormAddComponent(form, newtLabel(34, 4, "Resolution"));
  699.     res = newtListbox( 32, 5, 4, 0 );
  700.     newtListboxAddEntry( res, "Default", (void *)0 );
  701.     newtListboxSetCurrent(res, 0);
  702.     reslines=NULL;
  703.     }
  704.     
  705.     /* make sure something is picked */
  706.     if (changes->Resolution==NULL)
  707.     newtListboxSetCurrent(res, 0);
  708.  
  709.     /* add stair-step correction toggle */
  710.     if (!strcmp("YES", changes->CRLF))
  711.         crlf = newtCheckbox(11, 11, "Fix stair-stepping of text?", '*', NULL,&crlfret);
  712.     else
  713.         crlf = newtCheckbox(11, 11, "Fix stair-stepping of text?", ' ', NULL,&crlfret);
  714.     
  715.     ok = newtButton( 11, 13, NEXT_LABEL);
  716.     cancel = newtButton( 31, 13, PREV_LABEL);
  717.     newtFormAddComponents(form,papersz,res,crlf,ok,cancel,NULL);
  718.     newtFormAddHotKey(form, NEWT_KEY_F1); 
  719.     
  720.     formdone = 0;
  721.     answer = NULL;
  722.     
  723.     while (!formdone) {
  724.     newtFormRun(form, &event);
  725.     
  726.     if (event.reason == NEWT_EXIT_HOTKEY) {
  727.         if (event.u.key == NEWT_KEY_F12)
  728.         formdone = 1;
  729.         else if (event.u.key == NEWT_KEY_F1) {
  730.         show_printer_about( changes->db->About );
  731.         }
  732.     } else if (event.reason == NEWT_EXIT_COMPONENT) {
  733.         formdone = 1;
  734.         if (event.u.co == cancel)
  735.         answer = cancel;
  736.     }
  737.     }
  738.  
  739.  
  740.     if ( answer == cancel ) {
  741.     newtPopHelpLine();
  742.     newtPopWindow();
  743.     newtFormDestroy(form);
  744.     return -1;
  745.     }
  746.  
  747.     i = (long) newtListboxGetCurrent(papersz);
  748.  
  749.     free(changes->PaperSize);
  750.     changes->PaperSize=strdup(PaperSizes[i]);
  751.  
  752.     free(changes->Resolution);
  753.     if (changes->db->NumRes > 0) {
  754.     i = (long) newtListboxGetCurrent(res);
  755.     changes->Resolution=strdup(changes->db->Resolution[i]);
  756.     } else
  757.     changes->Resolution=strdup("Default");
  758.  
  759.     if (changes->CRLF)
  760.     free(changes->CRLF);
  761.     
  762.     if (crlfret == ' ')
  763.     changes->CRLF=strdup("NO");
  764.     else
  765.     changes->CRLF=strdup("YES");
  766.     
  767.     newtPopHelpLine();
  768.     newtPopWindow();
  769.     newtFormDestroy(form);
  770.  
  771.     return 0;
  772. }
  773.  
  774. /* pick the color depth, returns < 0 on cancel, 0 otherwise */
  775. static int select_color_depth( PCEntry *changes ) {
  776.     newtComponent ok, cancel, form, bpp, answer, text;
  777.     struct newtExitStruct event;
  778.     long i;
  779.     int formdone, maxlen;
  780.  
  781.     char **bpplines;
  782.  
  783.     /* have to have a selection to work */
  784.     if (changes->db == NULL)
  785.     return -1;
  786.  
  787.     /* if only one color depth choice, do nothing */
  788.     if ( changes->db->NumBpp == 0) {
  789.     changes->BitsPerPixel=strdup("Default");
  790.     return 0;
  791.     }
  792.     
  793.     newtCenteredWindow(60, 15, "Configure Color Depth");
  794.     newtPushHelpLine("<F1> will give you information on this printer driver.");
  795.     form = newtForm(NULL, NULL, 0);
  796.  
  797.     text = newtTextbox(1, 1, 58, 2, NEWT_TEXTBOX_WRAP);
  798.     newtTextboxSetText(text, 
  799.                "You may now configure the color options "
  800.                "for this printer.");
  801.     newtFormAddComponent(form, text);
  802.  
  803.     newtFormAddComponent(form, newtLabel(22, 3, "Bits Per Pixel"));
  804.     if ( changes->db->NumBpp > 0) {
  805.     maxlen = 0;
  806.     bpplines = (char **) alloca(changes->db->NumBpp*sizeof(char *));
  807.     for (i=0; i < changes->db->NumBpp; i++) {
  808.         if (changes->db->BppDescr && changes->db->BppDescr[i]) {
  809.         bpplines[i]=alloca(strlen(changes->db->BitsPerPixel[i])+
  810.                    strlen(changes->db->BppDescr[i])+15);
  811.         bpplines[i][0]='\000';
  812.         strcat(bpplines[i],changes->db->BitsPerPixel[i]);
  813.         if (bpplines[i][1] == '\000') {
  814.             bpplines[i][1] = bpplines[i][0];
  815.             bpplines[i][0] = ' ';
  816.             bpplines[i][2] = '\000';
  817.         }
  818.         strcat(bpplines[i],"  ");
  819.         strcat(bpplines[i],changes->db->BppDescr[i]);
  820.         } else {
  821.         bpplines[i]=alloca(strlen(changes->db->BitsPerPixel[i])+2);
  822.         strcpy(bpplines[i], changes->db->BitsPerPixel[i]);
  823.         }
  824.         
  825.         /* limit the length of the line */
  826.         if (strlen(bpplines[i]) > 54)
  827.         bpplines[i][50] = '\000';
  828.  
  829.         if (strlen(bpplines[i]) > maxlen)
  830.         maxlen = strlen(bpplines[i]);
  831.     }
  832.     
  833.     bpp = newtListbox( 29-maxlen/2, 4, 5, NEWT_FLAG_RETURNEXIT );
  834.     for (i=0; i < changes->db->NumBpp; i++) {
  835.         newtListboxAddEntry(bpp,bpplines[i], (void *)i );
  836.         if (changes->BitsPerPixel &&
  837.         !strcmp(changes->BitsPerPixel,changes->db->BitsPerPixel[i]))
  838.         newtListboxSetCurrent(bpp, i);
  839.     }
  840.     
  841.     } else {
  842.     fprintf(stderr, "How did we get here, numbpp = 0!\n");
  843.     return -1;
  844. #if 0    
  845.     bpp = newtListbox( 29-strlen("Default")/2, 5, 4,NEWT_FLAG_RETURNEXIT );
  846.     newtListboxAddEntry( bpp, "Default", (void *)0 );
  847.     newtListboxSetCurrent(bpp, 0);
  848.     bpplines=NULL;
  849. #endif
  850.     }
  851.  
  852.     /* make sure something is set */
  853.     if (changes->BitsPerPixel==NULL)
  854.     newtListboxSetCurrent(bpp,0);
  855.  
  856.     ok = newtButton( 11, 10, NEXT_LABEL);
  857.     cancel = newtButton( 36, 10, PREV_LABEL);
  858.     newtFormAddComponents(form,bpp,ok,cancel,NULL);
  859.     newtFormAddHotKey(form, NEWT_KEY_F1); 
  860.     
  861.     formdone = 0;
  862.     answer = NULL;
  863.     while (!formdone) {
  864.     newtFormRun(form, &event);
  865.     
  866.     if (event.reason == NEWT_EXIT_HOTKEY) {
  867.         if (event.u.key == NEWT_KEY_F12)
  868.         formdone = 1;
  869.         else if (event.u.key == NEWT_KEY_F1) {
  870.         show_printer_about( changes->db->About );
  871.         }
  872.     } else if (event.reason == NEWT_EXIT_COMPONENT) {
  873.         formdone = 1;
  874.         if (event.u.co == cancel)
  875.         answer = cancel;
  876.     }
  877.     }
  878.  
  879.     if ( answer == cancel ) {
  880.     newtPopHelpLine();
  881.     newtPopWindow();
  882.     newtFormDestroy(form);
  883.     return -1;
  884.     }
  885.  
  886.     free(changes->BitsPerPixel);
  887.     if (changes->db->NumBpp > 0) {
  888.     i = (long) newtListboxGetCurrent(bpp);
  889.     changes->BitsPerPixel=strdup(changes->db->BitsPerPixel[i]);
  890.     } else {
  891.     fprintf(stderr, "How did we get here, numbpp = 0!\n");
  892.     return -1;
  893. #if 0    
  894.     changes->BitsPerPixel=strdup("Default");
  895. #endif
  896.     }
  897.  
  898.     newtPopHelpLine();
  899.     newtPopWindow();
  900.     newtFormDestroy(form);
  901.     
  902.     return 0;
  903. }
  904.  
  905. /* returns the full attribute of the selected printer filter */
  906. /* returns < 0 if user cancelled selected                    */
  907. static int select_filter( PCEntry *changes ) {
  908.     
  909.     int done;
  910.     int stage;
  911.     int abort;
  912.     
  913.     done = 0;
  914.     stage = 1;
  915.     abort = 0;
  916.     while (!done) {
  917.  
  918.     switch (stage) {
  919.  
  920.         /* select printer model/driver */
  921.       case 1:
  922.         if (select_printer_type(changes) < 0) {
  923.         done = 1;
  924.         abort = 1;
  925.         break;
  926.         } else
  927.         stage++;
  928.         break;
  929.  
  930.         /* select paper size and resolution */
  931.       case 2:
  932.         if (select_paper_size_and_res( changes ) < 0) {
  933.         stage--;
  934.         break;
  935.         } else
  936.         stage++;
  937.         break;
  938.  
  939.         /* select color depth */
  940.       case 3:
  941.         if (select_color_depth( changes ) < 0) {
  942.         stage--;
  943.         break;
  944.         } else
  945.         stage++;
  946.         break;
  947.  
  948.         /* we made it and we're done */
  949.       case 4:
  950.         done = 1;
  951.  
  952.     }
  953.     }
  954.  
  955.     if (abort)
  956.     return -1;
  957.  
  958.     return 0;
  959. }
  960.  
  961.  
  962. /* return < 0 for user cancel */
  963. static int get_local_info( PCEntry *changes ) {
  964.  
  965.     newtComponent answer, cancel, form, ok, device, text;
  966.     char *device_result;
  967.     char *devname;
  968.     int detected[3];
  969.     int i, result;
  970.     int npos;
  971.  
  972. #if defined(__i386__) && !defined(TESTING)
  973.     if (loadModule("lp", DRIVER_OTHER, DRIVER_MINOR_NONE, NULL)) 
  974.     return INST_ERROR;
  975.  
  976. #endif
  977.  
  978. #if 0
  979.     /* old way Erik did this */
  980.     devMakeInode("lp0", "/tmp/lp0");
  981.     devMakeInode("lp1", "/tmp/lp1");
  982.     devMakeInode("lp2", "/tmp/lp2");
  983.     
  984.     /* do auto-detect of lp ports */
  985.     detected[0] = ((result=open("/tmp/lp0", O_WRONLY|O_NONBLOCK)) != -1);
  986.     if (result >= 0) close(result);
  987.     detected[1] = ((result=open("/tmp/lp1", O_WRONLY|O_NONBLOCK)) != -1);
  988.     if (result >= 0) close(result);
  989.     detected[2] = ((result=open("/tmp/lp2", O_WRONLY|O_NONBLOCK)) != -1);
  990.     if (result >= 0) close(result);
  991.  
  992.     unlink("/tmp/lp0");
  993.     unlink("/tmp/lp1");
  994.     unlink("/tmp/lp2");
  995. #else
  996.     /* different approach */
  997.     /* do auto-detect of lp ports */
  998.     devname=alloca(strlen(root_path)+strlen("/dev/lpX")+2);
  999.     strcpy(devname,root_path);
  1000.     strcat(devname,"/dev/lpX");
  1001.     npos=strlen(devname)-1;
  1002.     devname[npos]='0';
  1003.     detected[0] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1);
  1004.     if (result >= 0) close(result);
  1005.     devname[npos]='1';
  1006.     detected[1] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1);
  1007.     if (result >= 0) close(result);
  1008.     devname[npos]='2';
  1009.     detected[2] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1);
  1010.     if (result >= 0) close(result);
  1011. #endif
  1012.     
  1013. #if defined(__i386__) && !defined(TESTING)
  1014.     removeModule("lp");
  1015. #endif
  1016.  
  1017.     newtCenteredWindow(44, 16, "Local Printer Device");
  1018.     form = newtForm(NULL, NULL, 0);
  1019.  
  1020.     text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP);
  1021.     newtTextboxSetText(text,
  1022.     "What device is your printer connected to (note that /dev/lp0 is "
  1023.     "equivalent to LPT1:)?");
  1024.  
  1025.     newtFormAddComponent(form, text);
  1026.     newtFormAddComponent(form, newtLabel(3, 7, "Auto-detected ports:"));
  1027.     newtFormAddComponent(form, newtLabel(6, 8, "/dev/lp0:"));
  1028.     newtFormAddComponent(form, newtLabel(6, 9, "/dev/lp1:"));
  1029.     newtFormAddComponent(form, newtLabel(6, 10, "/dev/lp2:"));
  1030.     
  1031.     for (i=0; i<3; i++) {
  1032.     if (detected[i])
  1033.         newtFormAddComponent(form, newtLabel(18,8+i, "Detected"));
  1034.     else
  1035.         newtFormAddComponent(form, newtLabel(18,8+i, "Not Detected"));
  1036.     }
  1037.  
  1038.     newtFormAddComponent(form, newtLabel(3, 5, "Printer Device:"));
  1039.     if (changes->Device)
  1040.     device=newtEntry(19, 5, changes->Device, 15, &device_result,
  1041.              NEWT_FLAG_RETURNEXIT);
  1042.     else
  1043.     device=newtEntry(19, 5, "/dev/lp1", 15, &device_result,
  1044.              NEWT_FLAG_RETURNEXIT);
  1045.     
  1046.     ok = newtButton( 7, 12, NEXT_LABEL);
  1047.     cancel = newtButton( 24, 12, PREV_LABEL);
  1048.     newtFormAddComponents( form, device, ok, cancel, NULL);
  1049.     answer = newtRunForm(form);
  1050.  
  1051.     if ( answer != cancel ) {
  1052.     free(changes->Device);
  1053.     changes->Device = strdup(device_result);
  1054.     result = 0;
  1055.     } else
  1056.     result = -1;
  1057.  
  1058.     newtPopWindow();
  1059.     newtFormDestroy(form);
  1060.     return result;
  1061. }
  1062.  
  1063.  
  1064. /* return < 0 for user cancel */
  1065. static int get_remote_info( PCEntry *changes ) {
  1066.     newtComponent answer, cancel, form, ok, rhost, rqueue, text;
  1067.     char *queue_result;
  1068.     char *host_result;
  1069.     int result;
  1070.     
  1071.     newtCenteredWindow(42, 14, "Remote lpd Printer Options");
  1072.     form = newtForm(NULL, NULL, 0);
  1073.  
  1074.     text = newtTextbox(1, 1, 40, 5, NEWT_TEXTBOX_WRAP);
  1075.     newtTextboxSetText(text, 
  1076.     "To use a remote lpd print queue, you need to supply the "
  1077.     "hostname of the printer server and the queue name on that "
  1078.     "server which jobs should be placed in.");
  1079.     
  1080.     newtFormAddComponent(form, text);
  1081.     newtFormAddComponent(form, newtLabel(2, 7, "Remote hostname:"));
  1082.     newtFormAddComponent(form, newtLabel(2, 8, "Remote queue:"));
  1083.  
  1084.     if (changes->RemoteHost)
  1085.     rhost =newtEntry(19, 7, changes->RemoteHost, 20, &host_result, 0);
  1086.     else
  1087.     rhost =newtEntry(19, 7, "", 20, &host_result, 0);
  1088.  
  1089.     if (changes->RemoteQueue)
  1090.     rqueue =newtEntry(19, 8, changes->RemoteQueue, 20, &queue_result, 0);
  1091.     else
  1092.     rqueue =newtEntry(19, 8, "lp", 20, &queue_result, 0);
  1093.  
  1094.     ok = newtButton( 7, 10, NEXT_LABEL);
  1095.     cancel = newtButton( 24, 10, PREV_LABEL);
  1096.     newtFormAddComponents( form, rhost, rqueue, ok, cancel, NULL);
  1097.     answer = newtRunForm(form);
  1098.  
  1099.     if ( answer != cancel ) {
  1100.     free(changes->RemoteHost);
  1101.     changes->RemoteHost = strdup(host_result);
  1102.     free(changes->RemoteQueue);
  1103.     changes->RemoteQueue = strdup(queue_result);
  1104.     result = 0;
  1105.     } else
  1106.     result = -1;
  1107.  
  1108.     newtPopWindow();
  1109.     newtFormDestroy(form);
  1110.     return result;
  1111. }
  1112.  
  1113.  
  1114. /* return < 0 for user cancel */
  1115. static int get_smb_info( PCEntry *changes ) {
  1116.     newtComponent answer, cancel, form, ok, text;
  1117.     newtComponent host, hostip, share, user, passwd;
  1118.     
  1119.     int result;
  1120.     char *host_result;
  1121.     char *hostip_result;
  1122.     char *share_result;
  1123.     char *user_result;
  1124.     char *passwd_result;
  1125.  
  1126.     newtCenteredWindow(60, 18, "LAN Manager Printer Options");
  1127.     form = newtForm(NULL, NULL, 0);
  1128.  
  1129.     text = newtTextbox(1, 1, 58, 6, NEWT_TEXTBOX_WRAP);
  1130.     newtTextboxSetText(text,
  1131.     "To print to a LAN manager printer, you need to provide the "
  1132.     "LAN manager host name (this is not always the same as the machines "
  1133.     "TCP/IP hostname) and possibly the IP address of the print server, as "
  1134.     "well as the share name for the printer you wish to access and any "
  1135.     "applicable user name and password.");    
  1136.  
  1137.     newtFormAddComponent(form, text);
  1138.     
  1139.     newtFormAddComponent(form, newtLabel(10, 8, "LAN Manager Host:"));
  1140.     newtFormAddComponent(form, newtLabel(10, 9, "LAN Manager IP:"));
  1141.     newtFormAddComponent(form, newtLabel(10, 10, "Share Name:"));
  1142.     newtFormAddComponent(form, newtLabel(10, 11, "Username:"));
  1143.     newtFormAddComponent(form, newtLabel(10, 12, "Password:"));
  1144.  
  1145.     if (changes->SMBHost)
  1146.     host   = newtEntry(28, 8, changes->SMBHost, 15, &host_result, 0);
  1147.     else
  1148.     host   = newtEntry(28, 8, "", 15, &host_result, 0);
  1149.     if (changes->SMBHostIP)
  1150.     hostip = newtEntry(28, 9, changes->SMBHostIP, 15, &hostip_result, 0);
  1151.     else
  1152.     hostip = newtEntry(28, 9, "", 15, &hostip_result, 0);
  1153.     if (changes->SMBShare)
  1154.     share  = newtEntry(28, 10, changes->SMBShare, 15, &share_result, 0);
  1155.     else
  1156.     share  = newtEntry(28, 10, "", 15, &share_result, 0);
  1157.     if (changes->SMBUser)
  1158.     user   = newtEntry(28, 11, changes->SMBUser, 15, &user_result, 0);
  1159.     else
  1160.     user   = newtEntry(28, 11, "", 15, &user_result, 0);
  1161.     if (changes->SMBPasswd)
  1162.     passwd = newtEntry(28, 12, changes->SMBPasswd, 15, 
  1163.                &passwd_result, NEWT_ENTRY_HIDDEN);
  1164.     else
  1165.     passwd = newtEntry(28, 12, "", 15, &passwd_result, NEWT_ENTRY_HIDDEN);
  1166.  
  1167.     ok = newtButton( 15, 14, NEXT_LABEL);
  1168.     cancel = newtButton( 35, 14, PREV_LABEL);
  1169.     newtFormAddComponents( form, host, hostip, 
  1170.              share, user, passwd, ok, cancel, NULL);
  1171.     answer = newtRunForm(form);
  1172.  
  1173.     if ( answer != cancel ) {
  1174.     free(changes->SMBHost);
  1175.     changes->SMBHost = strdup(host_result);
  1176.     free(changes->SMBHostIP);
  1177.     changes->SMBHostIP = strdup(hostip_result);
  1178.     free(changes->SMBShare);
  1179.     changes->SMBShare = strdup(share_result);
  1180.     free(changes->SMBUser);
  1181.     changes->SMBUser = strdup(user_result);
  1182.     free(changes->SMBPasswd);
  1183.     changes->SMBPasswd = strdup(passwd_result);
  1184.     
  1185.     result = 0;
  1186.     } else
  1187.     result = -1;
  1188.  
  1189.     newtPopWindow();
  1190.     newtFormDestroy(form);
  1191.     return result;
  1192. }
  1193.  
  1194. /* return < 0 for user cancel */
  1195. static int get_std_info( PCEntry *changes ) {
  1196.     newtComponent answer, cancel, form, ok, queue, spool, text;
  1197.     char *queue_result;
  1198.     char *spool_result;
  1199.     int result;
  1200.  
  1201.     newtCenteredWindow(52, 14, "Standard Printer Options");
  1202.     form = newtForm(NULL, NULL, 0);
  1203.  
  1204.     text = newtTextbox(1, 1, 50, 5, NEWT_TEXTBOX_WRAP);
  1205.     newtTextboxSetText(text, 
  1206.     "Every print queue (which print jobs are directed to) needs a "
  1207.     "name (often lp) and a spool directory associated with it. What "
  1208.     "name and directory should be used for this queue? ");
  1209.     
  1210.     newtFormAddComponent(form, newtLabel(2, 7, "Name of queue:"));
  1211.     newtFormAddComponent(form, newtLabel(2, 8, "Spool directory:"));
  1212.     if (changes->Queue)
  1213.     queue =newtEntry(20, 7, changes->Queue, 30, &queue_result, 0);
  1214.     else
  1215.     queue =newtEntry(20, 7, "lp", 30, &queue_result, 0);
  1216.  
  1217.     if (changes->SpoolDir)
  1218.     spool =newtEntry(20, 8, changes->SpoolDir, 30, &spool_result, 0);
  1219.     else
  1220.     spool =newtEntry(20, 8, "/var/spool/lpd/lp", 30, &spool_result, 0);
  1221.  
  1222.     ok = newtButton( 11, 10, NEXT_LABEL);
  1223.     cancel = newtButton( 27, 10, PREV_LABEL);
  1224.     newtFormAddComponents(form, text, queue, spool, ok, cancel, NULL);
  1225.     answer = newtRunForm(form);
  1226.  
  1227.     if ( answer != cancel ) {
  1228.     free(changes->Queue);
  1229.     changes->Queue = strdup(queue_result);
  1230.     free(changes->SpoolDir);
  1231.     changes->SpoolDir = strdup(spool_result);
  1232.     result = 0;
  1233.     } else {
  1234.     result = -1;
  1235.     }
  1236.  
  1237.     newtPopWindow();
  1238.     newtFormDestroy(form);
  1239.     return result;
  1240. }
  1241.  
  1242.  
  1243. static int query_config(void) {
  1244.     int result;
  1245.  
  1246.     result = newtWinChoice("Configure Printer", "Yes", "No", 
  1247.                    "Would you like to configure a printer?");
  1248.     
  1249.     if (result == 1) 
  1250.     return -1;
  1251.     return 0;
  1252. }
  1253.  
  1254. static int query_add_more() {
  1255.     int result;
  1256.  
  1257.     result = newtWinChoice("Add Printer", "Yes", "No", 
  1258.                    "Would you like to add another printer?");
  1259.  
  1260.     if (result == 1) 
  1261.     return -1;
  1262.     return 0;
  1263. }
  1264.  
  1265.  
  1266. /* returns 1 if they want to quit, 0 otherwise */
  1267. static int you_are_sure(void) {
  1268.     int result;
  1269.  
  1270.     result = newtWinChoice("Confirm Termination", "Exit", "Continue", 
  1271.                "If you choose 'Exit', you will return to the main "
  1272.                "installation without a printer being configured.\n\n"
  1273.                 "Choose 'Continue' to return to configuring "
  1274.                "your printer.");
  1275.  
  1276.     if (result == 1) return 0;
  1277.     return 1;
  1278. }
  1279.  
  1280.  
  1281. /* returns < 0 for user cancel, otherwise uses #defines in printercfg.h */
  1282. static int get_prn_connx( char *Type ) {
  1283.     newtComponent answer, cancel, form, ok, listbox;
  1284.     int sel;
  1285.  
  1286.     newtCenteredWindow(33, 12, "Select Printer Connection");
  1287.     form = newtForm(NULL, NULL, 0);
  1288.     newtFormAddComponent(form,
  1289.              newtLabel(1, 1, "How is this printer connected?"));
  1290.     
  1291.     listbox = newtListbox(9, 3, 0, NEWT_FLAG_NOSCROLL | NEWT_FLAG_RETURNEXIT);
  1292.     newtListboxAddEntry(listbox, "Local", (void *)LOCAL_CONNX);
  1293.     newtListboxAddEntry(listbox, "Remote lpd", (void *)REMOTE_LPD_CONNX);
  1294.     newtListboxAddEntry(listbox, "LAN Manager", (void *)SMB_CONNX);
  1295.  
  1296.     if (Type)
  1297.     if (!strcmp(Type,"LOCAL"))
  1298.         newtListboxSetCurrent(listbox, 0);
  1299.     else if (!strcmp(Type,"REMOTE"))
  1300.         newtListboxSetCurrent(listbox, 1);
  1301.     else if (!strcmp(Type,"SMB"))
  1302.         newtListboxSetCurrent(listbox, 2);
  1303.     
  1304.     ok = newtButton( 4, 7, NEXT_LABEL);
  1305.     cancel = newtButton( 17, 7, "Cancel");
  1306.     newtFormAddComponents(form, listbox, ok, cancel, NULL);
  1307.  
  1308.     answer = newtRunForm(form);
  1309.  
  1310.     if ( answer == cancel ) {
  1311.     newtPopWindow();
  1312.     newtFormDestroy(form);
  1313.     return -1;
  1314.     } else {
  1315.     sel = (long) newtListboxGetCurrent(listbox);
  1316.     newtPopWindow();
  1317.     newtFormDestroy(form);
  1318.     return sel;
  1319.     }
  1320. }
  1321.  
  1322. /* edit the PrintCap Entry pcentry */
  1323. /* return < 0 if user aborts or error occurs */
  1324. static int edit_pcentry( PCEntry **pcentry ) {
  1325.  
  1326.     int result;
  1327.     int stage;
  1328.     int done;
  1329.     int abort;
  1330.     PCEntry *changes;
  1331.  
  1332.     /* copy current into temporary */
  1333.     changes = dup_PCEntry( *pcentry );
  1334.  
  1335.     done = 0;
  1336.     abort = 0;
  1337.     stage = 0;
  1338.  
  1339.     while (!done) {
  1340.  
  1341.     switch (stage) {
  1342.       case 0:
  1343.         switch (get_prn_connx(changes->Type)) {
  1344.           case -1:
  1345.         if (you_are_sure()) {
  1346.             done = 1;
  1347.             abort = 1;
  1348.         }
  1349.         break;
  1350.         
  1351.           case LOCAL_CONNX:
  1352.         free(changes->Type);
  1353.         changes->Type = strdup("LOCAL");
  1354.         stage++;
  1355.         break;
  1356.       
  1357.           case REMOTE_LPD_CONNX:
  1358.         free(changes->Type);
  1359.         changes->Type = strdup("REMOTE");
  1360.         stage++;
  1361.         break;
  1362.         
  1363.           case SMB_CONNX:
  1364.         free(changes->Type);
  1365.         changes->Type = strdup("SMB");
  1366.         stage++;
  1367.         break;
  1368.       
  1369.           default:
  1370.         break;
  1371.         }
  1372.         break;
  1373.       
  1374.       case 1:
  1375.             result=get_std_info(changes);
  1376.         if (result < 0)
  1377.         stage--;
  1378.         else 
  1379.         stage++;
  1380.         break;
  1381.  
  1382.       case 2:
  1383.         if (!strcmp(changes->Type, "SMB"))
  1384.         result=get_smb_info(changes);
  1385.         else if (!strcmp(changes->Type, "REMOTE"))
  1386.         result=get_remote_info(changes);
  1387.         else if (!strcmp(changes->Type, "LOCAL"))
  1388.         result=get_local_info(changes);
  1389.         else
  1390.         return -1;
  1391.  
  1392.         if (result < 0)
  1393.         stage--;
  1394.         else
  1395.         stage++;
  1396.         break;
  1397.  
  1398.       case 3:
  1399.         result=select_filter(changes);
  1400.         if (result < 0)
  1401.         stage--;
  1402.         else
  1403.         stage++;
  1404.         break;
  1405.  
  1406.       case 4:
  1407.         done = 1;
  1408.         break;
  1409.     }
  1410.     }
  1411.  
  1412.     if (!abort) {
  1413.     free_PCEntry(*pcentry);
  1414.     *pcentry = changes;
  1415.     return 0;
  1416.     } else {
  1417.     free_PCEntry(changes);
  1418.     return -1;
  1419.     }
  1420. }
  1421.  
  1422. /* returns 0 on success, -1 on abort, and -2 if user wishes to re-edit */
  1423. static int verify_pcentry( PCEntry *pcentry ) {
  1424.  
  1425.     newtComponent form, ok, edit, cancel, answer;
  1426.     char tmpstr[256];
  1427.     int row;
  1428.     int done;
  1429.     int result;
  1430.  
  1431.     newtCenteredWindow(60, 18, "Verify Printer Configuration");
  1432.     form = newtForm(NULL, NULL, 0);
  1433.  
  1434.     newtFormAddComponent(form, newtLabel(3, 1, 
  1435.         "Please verify that this printer information is correct:"));
  1436.  
  1437.     row=3;
  1438.     sprintf(tmpstr, "Printer Type    : %s\n",pcentry->Type);
  1439.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1440.  
  1441.     sprintf(tmpstr, "Queue           : %s\n",pcentry->Queue);
  1442.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1443.  
  1444.     sprintf(tmpstr, "Spool directory : %s\n",pcentry->SpoolDir);
  1445.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1446.  
  1447.     if (!strcmp(pcentry->Type, "LOCAL")) {
  1448.     sprintf(tmpstr, "Printer device  : %s\n",pcentry->Device);
  1449.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1450.     } else if (!strcmp(pcentry->Type, "REMOTE")) {
  1451.     sprintf(tmpstr, "Remote Host     : %s\n",pcentry->RemoteHost);
  1452.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1453.     sprintf(tmpstr, "Remote Queue    : %s\n",pcentry->RemoteQueue);
  1454.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1455.     } else if (!strcmp(pcentry->Type, "SMB")) {
  1456.     if (pcentry->SMBHostIP && pcentry->SMBHostIP[0])
  1457.         sprintf(tmpstr, "Server          : %s [%s]\n",
  1458.             pcentry->SMBHost, pcentry->SMBHostIP);
  1459.     else
  1460.         sprintf(tmpstr, "Server          : %s\n",pcentry->SMBHost);
  1461.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1462.     sprintf(tmpstr, "Share           : %s\n",pcentry->SMBShare);
  1463.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1464.     sprintf(tmpstr, "User            : %s  <Password hidden>\n",
  1465.         pcentry->SMBUser);
  1466.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1467.     }
  1468.  
  1469.     sprintf(tmpstr, "Printer Driver  : %s\n",pcentry->db->Descr);
  1470.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1471.  
  1472.     sprintf(tmpstr, "Paper Size      : %s\n",pcentry->PaperSize);
  1473.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1474.  
  1475.     sprintf(tmpstr, "Resolution      : %s\n",pcentry->Resolution);
  1476.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1477.  
  1478.     sprintf(tmpstr, "Bits Per Pixel  : %s\n",pcentry->BitsPerPixel);
  1479.     newtFormAddComponent(form, newtLabel(5, row++, tmpstr));
  1480.  
  1481.  
  1482.     ok = newtButton( 11, 14,   "Done");
  1483.     edit = newtButton( 26, 14, "Edit");
  1484.     cancel = newtButton( 41, 14, "Cancel");
  1485.     newtFormAddComponents( form, ok, edit, cancel, NULL);
  1486.  
  1487.     done = 0;
  1488.     result = 0;
  1489.     while (!done) {
  1490.     answer = newtRunForm(form);
  1491.  
  1492.     if ( answer == cancel ) {
  1493.         if (you_are_sure()) {
  1494.         done = 1;
  1495.         result = -1;
  1496.         }
  1497.     } else if (answer == edit) {
  1498.         done = 1;
  1499.         result = -2;
  1500.     } else {
  1501.         done = 1;
  1502.         result = 0;
  1503.     }
  1504.     }
  1505.  
  1506.     newtPopWindow();
  1507.     newtFormDestroy(form);
  1508.  
  1509.     return result;
  1510. }
  1511.  
  1512. /* given the path queue_path, we create all the required spool directory */
  1513. static int create_spool_dir( char *queue_path ) {
  1514.     int result, done;
  1515.     int oldmask;
  1516.     
  1517.     struct group *grent;
  1518.     gid_t lpgid = 0;
  1519.     
  1520.     FILE *groupfile;
  1521.     char groupfilename[80];
  1522.     
  1523.  
  1524.     oldmask=umask(0);
  1525.     result=mkdir(queue_path, 0755);
  1526.     if ( result < 0)
  1527.     if (errno != EEXIST)
  1528.         return -1;
  1529.     umask(oldmask);
  1530.   
  1531.     strcpy(groupfilename, root_path);
  1532.     strcat(groupfilename, "/etc/group");
  1533.     if ((groupfile=fopen(groupfilename, "r"))==NULL)
  1534.     return -1;
  1535.     
  1536.     done=0;
  1537.     while (!done) {
  1538.     grent=fgetgrent(groupfile);
  1539.     if (grent==NULL)
  1540.         return -1;
  1541.       
  1542.     if (!strcmp(grent->gr_name, "lp")) {
  1543.         lpgid=grent->gr_gid;
  1544.         done |= 2;
  1545.     }
  1546.     }
  1547.  
  1548.     fclose(groupfile);
  1549.   
  1550.     if (!done)
  1551.     return -1;
  1552.   
  1553.     result=chown(queue_path, 0, lpgid );
  1554.     if ( result < 0)
  1555.     return -1;
  1556.  
  1557.     return 0;
  1558. }
  1559.  
  1560.  
  1561. /* given the input spec file 'input', and the target output file 'output' */
  1562. /* we set the fields specified by fieldname to the values in fieldval     */
  1563. /* nval  is the number of fields to set                                   */
  1564. /* Doesnt currently catch error exec'ing sed yet                          */
  1565. static int create_config_file( char *input, char *output, 
  1566.             char **fieldname, char **fieldval, 
  1567.             int nval ) {
  1568.     int status;
  1569.     int infd, outfd;
  1570.     int childpid;
  1571.     int i, j;
  1572.     
  1573.     int oldmask;
  1574.  
  1575.     char **sedargs;
  1576.     char *sedcmd;
  1577.     
  1578.     oldmask = umask(0);
  1579.     
  1580.     outfd=creat(output, 0755 );
  1581.     umask(oldmask);
  1582.     if (outfd == -1)
  1583.     return -1;
  1584.   
  1585.     infd=open(input, O_RDONLY);
  1586.     if (infd == -1)
  1587.     return -1;
  1588.  
  1589.     /* we have to setup the args to sed */
  1590.     /* need the name to exec, plus 2 args per field, plus NULL at end */
  1591.     sedargs = (char **) malloc( (nval + 2) * sizeof( char * ) );
  1592.     if (!sedargs)
  1593.     return -1;
  1594.  
  1595.     sedargs[0] = "/bin/sed";
  1596.     sedargs[nval+1] = NULL;
  1597.     for (i=0; i<nval; i++) {
  1598.     sedargs[i+1] = (char *) malloc(25 + strlen(fieldname[i]) +
  1599.                        strlen(fieldval[i]));
  1600.     /* if we get an error, try to cleanup */
  1601.     if (!sedargs[i+1]) {
  1602.         for (j=0; j<i; j++)
  1603.         if (sedargs[j+1])
  1604.             free(sedargs[j+1]);
  1605.         
  1606.         if (sedargs)
  1607.         free(sedargs);
  1608.         
  1609.         return -1;
  1610.     }
  1611.     sprintf(sedargs[i+1], "-e s/@@@%s@@@/%s/g", fieldname[i], fieldval[i]);
  1612.     }
  1613.  
  1614.     sedcmd = malloc(strlen(root_path)+15);
  1615.     if (!sedcmd)
  1616.     return -1;
  1617.     
  1618.     strcpy(sedcmd, root_path);
  1619.     strcat(sedcmd, "/bin/sed");
  1620.     
  1621.     if (!(childpid = fork())) {
  1622.     close(0);
  1623.     close(1);
  1624.     dup2(infd, 0);
  1625.     dup2(outfd, 1);
  1626.     close(infd);
  1627.     close(outfd);
  1628.     execv(sedcmd, sedargs);
  1629.     exit(-1);
  1630.     }
  1631.  
  1632.     close(infd);
  1633.     close(outfd);
  1634.  
  1635.     waitpid(childpid, &status, 0);
  1636.  
  1637.     if (sedcmd)
  1638.     free(sedcmd);
  1639.  
  1640.     for (i=0; i<nval; i++)
  1641.     if (sedargs[i+1])
  1642.         free(sedargs[i+1]);
  1643.  
  1644.     if (sedargs)
  1645.     free(sedargs);
  1646.  
  1647.     return 0;
  1648. }
  1649.  
  1650. /* copy master filter to the spool dir */
  1651. static int copy_master_filter( char *queue_path ) {
  1652.     int childpid, status;
  1653.     char *masterfilter, *cpcmd, *dest;
  1654.     
  1655.     masterfilter=malloc(strlen(PRINTER_FILTER_DIR)+strlen(root_path)+20);
  1656.     strcpy(masterfilter,root_path);
  1657.     strcat(masterfilter,PRINTER_FILTER_DIR);
  1658.     strcat(masterfilter,"master-filter");
  1659.     
  1660.     dest=malloc(strlen(queue_path)+20);
  1661.     strcpy(dest,queue_path);
  1662.     strcat(dest,"filter");
  1663.     
  1664.     cpcmd = malloc(strlen(root_path)+15);
  1665.     if (!cpcmd)
  1666.     return -1;
  1667.     
  1668.     strcpy(cpcmd, root_path);
  1669.     strcat(cpcmd, "/bin/cp");
  1670.     
  1671.     if (!(childpid = fork())) 
  1672.     execl(cpcmd, cpcmd, masterfilter, dest, NULL);
  1673.  
  1674.     waitpid(childpid, &status, 0);
  1675.     
  1676.     free(masterfilter);
  1677.     free(cpcmd);
  1678.     free(dest);
  1679.     return 0;
  1680. }
  1681.  
  1682. /* given a PrintCap Entry, create the spool dir and special */
  1683. /* rhs-printfilters related config files which are required */
  1684. static int configure_queue( PCEntry *pcentry ) {
  1685.     char *queue_path;
  1686.     char *output;
  1687.     char *input;
  1688.     char colorstr[80]; /* holds the '-dBitsPerPixel=nn' */
  1689.     
  1690.     char **fieldname;
  1691.     char **fieldval;
  1692.     int  nfield;
  1693.  
  1694.     FILE *printcap, *smbconfig;
  1695.  
  1696.     if (testing) return 0;
  1697.     
  1698.     if (pcentry->SpoolDir) {
  1699.     /* create the spooldir and set to root.lp ownership */
  1700.     queue_path=malloc(strlen(root_path)+strlen(pcentry->SpoolDir)+5);
  1701.     strcpy(queue_path, root_path);
  1702.     strcat(queue_path, pcentry->SpoolDir);
  1703.     strcat(queue_path, "/");
  1704.     if (create_spool_dir(queue_path) < 0)
  1705.         return -1;
  1706.     
  1707.     /* make the cfg files we need */
  1708.     output=malloc(strlen(queue_path)+strlen("general.cfg")+2);
  1709.     strcpy(output,queue_path);
  1710.     strcat(output,"general.cfg");
  1711.     input=malloc(strlen(root_path)+strlen(PRINTER_FILTER_DIR)+
  1712.              strlen("general.cfg.in")+2);
  1713.     strcpy(input,root_path);
  1714.     strcat(input,PRINTER_FILTER_DIR);
  1715.     strcat(input,"general.cfg.in");
  1716.  
  1717.     /* setup the field arrays */
  1718.     nfield = 4;
  1719.     fieldname = (char **) malloc( nfield * sizeof(char *) );
  1720.     fieldname[0] = "desiredto";
  1721.     fieldname[1] = "papersize";
  1722.     fieldname[2] = "printertype";
  1723.     fieldname[3] = "ascps_trans";
  1724.     
  1725.     fieldval = (char **) malloc( nfield * sizeof(char *) );
  1726.  
  1727.     if (strcmp(pcentry->db->GSDriver, "TEXT"))
  1728.         fieldval[0] = "ps";
  1729.     else
  1730.         fieldval[0] = "asc";
  1731.  
  1732.     if (!pcentry->PaperSize)
  1733.         fieldval[1] = "letter";
  1734.     else
  1735.         fieldval[1] = pcentry->PaperSize;
  1736.  
  1737.     fieldval[2] = pcentry->Type;
  1738.     
  1739.     if (strcmp(pcentry->db->GSDriver, "POSTSCRIPT"))
  1740.         fieldval[3] = "NO";
  1741.     else
  1742.         fieldval[3] = "YES";
  1743.  
  1744.     if (create_config_file(input, output, fieldname, fieldval, nfield) < 0)
  1745.         return -1;
  1746.  
  1747.     /* successfully created general.cfg, now do postscript.cfg */
  1748.     free(fieldname);
  1749.     free(fieldval);
  1750.     free(output);
  1751.     free(input);
  1752.  
  1753.     output=malloc(strlen(queue_path)+strlen("postscript.cfg")+2);
  1754.     strcpy(output,queue_path);
  1755.     strcat(output,"postscript.cfg");
  1756.     input=malloc(strlen(root_path)+strlen(PRINTER_FILTER_DIR)+
  1757.              strlen("postscript.cfg.in")+2);
  1758.     strcpy(input,root_path);
  1759.     strcat(input,PRINTER_FILTER_DIR);
  1760.     strcat(input,"postscript.cfg.in");
  1761.  
  1762.     /* setup the field arrays */
  1763.     nfield = 10;
  1764.     fieldname = (char **) malloc( nfield * sizeof(char *) );
  1765.     fieldname[0] = "gsdevice";
  1766.     fieldname[1] = "papersize";
  1767.     fieldname[2] = "resolution";
  1768.     fieldname[3] = "color";
  1769.     fieldname[4] = "reversepages";
  1770.     fieldname[5] = "extragsoptions";
  1771.     fieldname[6] = "pssendeof";
  1772.     fieldname[7] = "nup";
  1773.     fieldname[8] = "rtlftmar";
  1774.     fieldname[9] = "topbotmar";
  1775.     
  1776.     fieldval = (char **) malloc( nfield * sizeof(char *) );
  1777.     
  1778.     /* gsdriver */
  1779.     fieldval[0] = pcentry->db->GSDriver;
  1780.     
  1781.     /* papersize */
  1782.     if (!pcentry->PaperSize)
  1783.         fieldval[1] = "letter";
  1784.     else
  1785.         fieldval[1] = pcentry->PaperSize;
  1786.     
  1787.     /* resolution */
  1788.     if (!pcentry->Resolution)
  1789.         fieldval[2] = "";
  1790.     else
  1791.         if (strcmp(pcentry->Resolution,"Default"))
  1792.         fieldval[2] = pcentry->Resolution;
  1793.         else
  1794.         fieldval[2] = "";
  1795.  
  1796.     /* color depth */
  1797.     if (!pcentry->BitsPerPixel)
  1798.         fieldval[3] = "";
  1799.     else
  1800.         if (strcmp(pcentry->BitsPerPixel,"Default")) {
  1801.         strcpy(colorstr,"-dBitsPerPixel=");
  1802.         strcat(colorstr,pcentry->BitsPerPixel);
  1803.         fieldval[3] = colorstr;
  1804.         } else
  1805.         fieldval[3] = "";
  1806.     
  1807.     /* reverse pages? */
  1808.     if (!pcentry->RevPages)
  1809.         fieldval[4] = "";
  1810.     else
  1811.         fieldval[4] = pcentry->RevPages;
  1812.  
  1813.     /* extra gs options */
  1814.     fieldval[5] = "";
  1815.  
  1816.     /* ps send eof */
  1817.     if (strcmp(pcentry->db->GSDriver, "POSTSCRIPT"))
  1818.         fieldval[6] = "NO";
  1819.     else
  1820.         fieldval[6] = "YES";
  1821.  
  1822.     /* nup */
  1823.     fieldval[7] = "1";
  1824.     
  1825.     /* rtlftmar */
  1826.     fieldval[8] = "18";
  1827.     
  1828.     /* topbotmar */
  1829.     fieldval[9] = "18";
  1830.     
  1831.     if (create_config_file(input, output, fieldname, fieldval, nfield) < 0)
  1832.         return -1;
  1833.     
  1834.     /* finally, make textonly.cfg */
  1835.     free(fieldval);
  1836.     free(fieldname);
  1837.     free(output);
  1838.     free(input);
  1839.     
  1840.     output=malloc(strlen(queue_path)+strlen("textonly.cfg")+2);
  1841.     strcpy(output,queue_path);
  1842.     strcat(output,"textonly.cfg");
  1843.     input=malloc(strlen(root_path)+strlen(PRINTER_FILTER_DIR)+
  1844.              strlen("textonly.cfg.in")+2);
  1845.     strcpy(input,root_path);
  1846.     strcat(input,PRINTER_FILTER_DIR);
  1847.     strcat(input,"textonly.cfg.in");
  1848.     
  1849.     /* setup the field arrays */
  1850.     nfield = 3;
  1851.     fieldname = (char **) malloc( nfield * sizeof(char *) );
  1852.     fieldname[0] = "textonlyoptions";
  1853.     fieldname[1] = "crlftrans";
  1854.     fieldname[2] = "textsendeof";
  1855.     
  1856.     fieldval = (char **) malloc( nfield * sizeof(char *) );
  1857.     fieldval[0] = "";
  1858.     if (!pcentry->CRLF)
  1859.         fieldval[1] = "";
  1860.     else
  1861.         fieldval[1] = pcentry->CRLF;
  1862.     fieldval[2] = "YES";
  1863.     
  1864.     if (create_config_file(input, output, fieldname, fieldval, nfield) < 0)
  1865.         return -1;
  1866.     
  1867.     /* simple config file required if SMB printer */
  1868.     if (!strcmp(pcentry->Type, "SMB")) {
  1869.         output=malloc(strlen(queue_path)+15);
  1870.         strcpy(output,queue_path);
  1871.         strcat(output,".config");
  1872.         smbconfig = fopen(output, "w");
  1873.         
  1874.         fprintf(smbconfig,"share='\\\\%s\\%s'\n",
  1875.             pcentry->SMBHost, pcentry->SMBShare);
  1876.         fprintf(smbconfig,"hostip=%s\n",pcentry->SMBHostIP);
  1877.         fprintf(smbconfig,"user=%s\n",pcentry->SMBUser);
  1878.         fprintf(smbconfig,"password=%s\n",pcentry->SMBPasswd);
  1879.  
  1880.         fclose(smbconfig);
  1881.     }
  1882.  
  1883.     /* we're done with config files - need to copy filter over now  */
  1884.     free(fieldval);
  1885.     free(fieldname);
  1886.     free(output);
  1887.     free(input);
  1888.     
  1889.     if ( copy_master_filter(queue_path) < 0 )
  1890.         return -1;
  1891.     } else
  1892.     return -1; /* we have to have a spool dir! */
  1893.  
  1894.     /* assume that spool dir got setup ok, now add printcap entry */
  1895.     output=alloca(strlen("/etc/printcap")+strlen(root_path)+2);
  1896.     strcpy(output,root_path);
  1897.     strcat(output,"/etc/printcap");
  1898.     if (access(output, F_OK)) {
  1899.     printcap=fopen(output, "w");
  1900.     if (printcap == NULL)
  1901.         return -1;
  1902.     
  1903.     fputs("#\n", printcap);
  1904.     fputs("# Please don't edit this file directly unless you know what "
  1905.         "you are doing!\n", printcap);
  1906.     fputs("# Be warned that the control-panel printtool requires a very "
  1907.         "strict format!\n", printcap);
  1908.     fputs("# Look at the printcap(5) man page for more info.\n", printcap);
  1909.     fputs("#\n", printcap);
  1910.     fputs("# This file can be edited with the printtool in the "
  1911.         "control-panel.\n", printcap);
  1912.     fputs("\n", printcap);
  1913.  
  1914.     fclose(printcap);
  1915.     }
  1916.  
  1917.     printcap = fopen(output, "a");
  1918.     
  1919.     fputs("\n",printcap);
  1920.     fprintf(printcap, "##PRINTTOOL3## %s %s %s %s %s %s %s %s \n",
  1921.         pcentry->Type,
  1922.         pcentry->db->GSDriver,
  1923.         pcentry->Resolution,
  1924.         pcentry->PaperSize,
  1925.         "{}",
  1926.         pcentry->db->Entry,
  1927.         pcentry->BitsPerPixel,
  1928.         "{}");
  1929.     fprintf(printcap, "%s:\\\n",pcentry->Queue);
  1930.     fprintf(printcap, "\t:sd=%s:\\\n",pcentry->SpoolDir);
  1931.     fprintf(printcap, "\t:mx#0:\\\n\t:sh:\\\n");
  1932.     
  1933.     if (!strcmp(pcentry->Type, "LOCAL")) {
  1934.     fprintf(printcap,"\t:lp=%s:\\\n",pcentry->Device);
  1935.     } else if (!strcmp(pcentry->Type, "REMOTE")) {
  1936.     fprintf(printcap,"\t:rm=%s:\\\n",pcentry->RemoteHost);
  1937.     fprintf(printcap,"\t:rp=%s:\\\n",pcentry->RemoteQueue);
  1938.     } else if (!strcmp(pcentry->Type, "SMB")) {
  1939.     fprintf(printcap,"\t:lp=/dev/null:\\\n");
  1940.     fprintf(printcap,"\t:af=%s/%s\\\n",pcentry->SpoolDir,"acct");
  1941.     }
  1942.  
  1943.     /* cheating to get the input filter! */
  1944.     fprintf(printcap,"\t:if=%s/%s:\n",pcentry->SpoolDir,"filter");
  1945.     fclose(printcap);
  1946.     return 0;
  1947. }
  1948.  
  1949.  
  1950. int doConfigurePrinters (char *theroot) {
  1951.  
  1952.   int done, result;
  1953.   PCEntry *pcentry = NULL;
  1954.  
  1955.   /* root under which the installed system lives */
  1956.   root_path = theroot;
  1957.  
  1958.   /* read the printer database into memory -- ignore these errors as they
  1959.      probably indicate missing packages */
  1960.   if (read_printer_db(PRINTER_DB_FILE)) return INST_NOP;
  1961.  
  1962.   install_return_code = 0;
  1963.   done = 0;
  1964.  
  1965.   if (!query_config()) {
  1966.       pcentry = new_PCEntry();
  1967.  
  1968.       /* setup some defaults needed for all printer types */
  1969.       pcentry->AutoEOF = strdup("NO");
  1970.       pcentry->CRLF = strdup("NO");
  1971.       pcentry->RevPages = strdup("NO");
  1972.  
  1973.       result = edit_pcentry( &pcentry );
  1974.       
  1975.       while ((result != -1) && (result=verify_pcentry( pcentry ))==-2) 
  1976.       result = edit_pcentry( &pcentry );
  1977.       
  1978.       if (result == -1)
  1979.       free_PCEntry( pcentry );
  1980.       else {
  1981.       configure_queue( pcentry );
  1982.       free_PCEntry( pcentry );
  1983.       install_return_code=0;
  1984.       }
  1985.   }
  1986.  
  1987.   return install_return_code;
  1988. }
  1989.  
  1990.  
  1991. #ifdef TESTING
  1992. int testing = 1;
  1993.  
  1994. int main() {
  1995.     int result;
  1996.  
  1997.     /* get the type of connection we want */
  1998.     newtInit();
  1999.     newtCls();
  2000.     newtPushHelpLine(NULL);
  2001.     newtDrawRootText(0, 0, "Printer Config - (C) 1997 Red Hat Software");
  2002.  
  2003.     result = doConfigurePrinters( "/" );
  2004.  
  2005.     newtFinished();
  2006.  
  2007.     printf("The result code is %d\n",result);
  2008.  
  2009.     return result;
  2010. }
  2011. #endif
  2012.      
  2013.