/* Text based printer configuration for the RHS install program */ /* Michael Fulbright - 1997 */ /* */ /* Mon Apr 14 1997 - fixed up for inclusion into 4.2 install */ /* Mon Apr 14 1997 - Erik broke everything -- blame him */ /* */ /* Last editted by msf - 11:10 Mon Apr 22 1997 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "devices.h" #include "install.h" #include "log.h" #include "printercfg.h" /* db of all entries in the printerdb file */ /* we reallocate as we read entries, so we keep numread and numallocated */ DBEntry **thedb; int numdb, numdb_alloc; /* root_path is the base of any path we use. During install the actual */ /* system is mounted under something like /mnt, so we have to take this */ /* into account when creating system files for the final, installed sys */ char *root_path; /* keep up with whether we actually accomplished anything or not */ int install_return_code; #define NUM_PAPERSIZES 5 static char *PaperSizes[NUM_PAPERSIZES] = { "letter", "legal", "ledger", "a3", "a4" }; /* not sure what we're calling these yet */ #define NEXT_LABEL "Next" #define PREV_LABEL "Previous" /*******************************************/ /* Some useful utility routines come first */ /*******************************************/ /* convert the character sequence '\' \n' into a true '\n' */ /* handy for treating a string which contains the continuation char '\' */ static void insert_newlines( char *s ) { char *p, *q; char *tmp; if (strlen(s)<2) return; tmp = strdup( s ); for (p=tmp, q=s; *(p+1); p++, q++) if (*p == '\\' && *(p+1)=='n') { *q = '\n'; p++; } else *q = *p; *q = '\000'; free(tmp); } /* clean up that string */ static void trim_whitespace( char *s ) { char *f, *l, *p, *q; if (!(*s)) return; for (f=s; *f && isspace(*f); f++) ; if (!*f) { *s = '\0'; return; } for (l=f+strlen(f)-1; isspace(*l) ; l--) *l = '\0'; q = s, p = f; while (*p) *q++ = *p++; *q = '\0'; } /* set all values of a PCEntry to sane values */ void initialize_PCEntry( PCEntry *pcentry ) { pcentry->Queue=NULL; pcentry->SpoolDir=NULL; pcentry->Device=NULL; pcentry->IF=NULL; pcentry->AF=NULL; pcentry->Type=NULL; pcentry->db=NULL; pcentry->Resolution=NULL; pcentry->PaperSize=NULL; pcentry->AutoEOF=NULL; pcentry->BitsPerPixel=NULL; pcentry->CRLF=NULL; pcentry->RevPages=NULL; pcentry->RemoteHost=NULL; pcentry->RemoteQueue=NULL; pcentry->SMBHost=NULL; pcentry->SMBHostIP=NULL; pcentry->SMBShare=NULL; pcentry->SMBUser=NULL; pcentry->SMBPasswd=NULL; } /* allocate a new PrintCap Entry */ static PCEntry *new_PCEntry() { PCEntry *pcentry; pcentry = (PCEntry *) malloc(sizeof(PCEntry)); initialize_PCEntry( pcentry ); return pcentry; } /* duplicate an existing PrintCap Entry */ /* all strings are REALLOCATED, so new PCEntry is not dependent on original */ static PCEntry *dup_PCEntry( PCEntry *orig ) { PCEntry *pcentry; pcentry = new_PCEntry(); if (orig->Queue) pcentry->Queue=strdup(orig->Queue); if (orig->SpoolDir) pcentry->SpoolDir=strdup(orig->SpoolDir); if (orig->Device) pcentry->Device=strdup(orig->Device); if (orig->IF) pcentry->IF=strdup(orig->IF); if (orig->AF) pcentry->AF=strdup(orig->AF); if (orig->Type) pcentry->Type=strdup(orig->Type); pcentry->db=orig->db; if (orig->Resolution) pcentry->Resolution=strdup(orig->Resolution); if (orig->PaperSize) pcentry->PaperSize=strdup(orig->PaperSize); if (orig->AutoEOF) pcentry->AutoEOF=strdup(orig->AutoEOF); if (orig->BitsPerPixel) pcentry->BitsPerPixel=strdup(orig->BitsPerPixel); if (orig->CRLF) pcentry->CRLF=strdup(orig->CRLF); if (orig->RevPages) pcentry->RevPages=strdup(orig->RevPages); if (orig->RemoteHost) pcentry->RemoteHost=strdup(orig->RemoteHost); if (orig->RemoteQueue) pcentry->RemoteQueue=strdup(orig->RemoteQueue); if (orig->SMBHost) pcentry->SMBHost=strdup(orig->SMBHost); if (orig->SMBHostIP) pcentry->SMBHostIP=strdup(orig->SMBHostIP); if (orig->SMBShare) pcentry->SMBShare=strdup(orig->SMBShare); if (orig->SMBUser) pcentry->SMBUser=strdup(orig->SMBUser); if (orig->SMBPasswd) pcentry->SMBPasswd=strdup(orig->SMBPasswd); return pcentry; } /* Free an existing PrintCap Entry */ static void free_PCEntry( PCEntry *pcentry) { free(pcentry->Queue); free(pcentry->SpoolDir); free(pcentry->Device); free(pcentry->IF); free(pcentry->AF); free(pcentry->Type); free(pcentry->Resolution); free(pcentry->PaperSize); free(pcentry->AutoEOF); free(pcentry->BitsPerPixel); free(pcentry->CRLF); free(pcentry->RevPages); free(pcentry->RemoteHost); free(pcentry->RemoteQueue); free(pcentry->SMBHost); free(pcentry->SMBHostIP); free(pcentry->SMBShare); free(pcentry->SMBUser); free(pcentry->SMBPasswd); free(pcentry); } /* Read lines from file, ignoring lines starting with a '#' and */ /* observing continuation lines (lines which end with a '\') */ /* All leading and trailing spaces are removed, as well as \n */ /* Returns zero if no more input available */ static char *pc_getline(FILE *file) { int done; char buf[256]; char *fresult; char *line; int len; line = NULL; done=0; while (!done) { fresult=fgets( buf, 256, file ); if (!fresult) return NULL; trim_whitespace( buf ); if (! (*buf) ) continue; if (*buf == '#') continue; len = strlen( buf ); if ( *(buf+len-1) != '\\' ) done = 1; else { /* silly rule - make sure line ends with a space */ if ( len > 2 && *(buf+len-2) != ' ' ) { *(buf+len-1) = ' '; *(buf+len) = '\000'; } else *(buf+len-1) = '\000'; } if (!line) line = strdup(buf); else { line = (char *) realloc( line, strlen(line) + strlen (buf) + 1 ); strcpy( line+strlen(line), buf ); } } return line; } /* strips out the value of a Parameter in the printer db file */ static char *getfield( char *s ) { char *f, *p; f = strchr(s, ':'); if (!f) return NULL; p = strdup(f+1); trim_whitespace(p); if (! (*p)) return NULL; else return p; } /* looks for exactly flds fields, with each field enclosed in a {} pair. */ static int parsefields( char *s, char **flds) { char *f, *l; char *p; int n; int i; flds[0] = NULL; flds[1] = NULL; flds[2] = NULL; n = 0; p = s; for (i=0; i<3; i++) { f = strchr(p, '{'); if (!f) return n; l = strchr(f, '}'); if (!l) return n; flds[n] = (char *) malloc( l-f+2 ); strncpy( flds[n], f+1, l-f-1 ); *((flds[n])+(l-f)-1) = '\000'; p = l+1; n++; } return n; } static int dbCompare(const void * a, const void * b) { const DBEntry * const *first = a; const DBEntry * const *second = b; return strcmp((*first)->Descr, (*second)->Descr); } /* Read the printer database dbpath into memory */ /* returns non-zero on error */ static int read_printer_db( char *dbpath ) { FILE *dbfile; char *line; char *tmpstr; char *fields[3]; int nfield; DBEntry *entry; int nbpp, nres; int nbpp_alloc, nres_alloc; tmpstr=malloc(strlen(dbpath)+strlen(root_path)+2); strcpy(tmpstr,root_path); strcat(tmpstr,dbpath); if ((dbfile=fopen(tmpstr, "r")) == NULL) { free(tmpstr); return -1; } free(tmpstr); /* loop till we find the start of an entry */ /* we obviously want to ignore any comments on the way */ numdb = numdb_alloc = 0; while ((line=pc_getline(dbfile))) { if (!strncmp(line, "StartEntry:", 11)) { entry = (DBEntry *) malloc( sizeof(DBEntry) ); entry->Entry = getfield(line); entry->GSDriver = NULL; entry->Descr = NULL; entry->About = NULL; entry->Resolution = NULL; entry->ResDescr = NULL; entry->BitsPerPixel = NULL; entry->BppDescr = NULL; nres = nres_alloc = 0; nbpp = nbpp_alloc = 0; free(line); if (!entry->Entry) { free(entry); continue; } numdb++; if (numdb >= numdb_alloc ) { numdb_alloc += 25; thedb=(DBEntry **)realloc(thedb, sizeof(DBEntry *)*(numdb_alloc)); } thedb[numdb - 1] = entry; while ((line=pc_getline(dbfile))) { if (!strncmp(line, "EndEntry", 8)) break; if (!strncmp(line, "GSDriver:", 9)) { if (entry->GSDriver) break; entry->GSDriver=getfield(line); } if (!strncmp(line, "Description:", 12)) { if (entry->Descr) break; tmpstr=getfield(line); nfield = parsefields(tmpstr, fields); free(tmpstr); if (nfield == 1 ) entry->Descr=fields[0]; else break; } if (!strncmp(line, "About:", 6)) { if (entry->About) break; tmpstr=getfield(line); nfield = parsefields(tmpstr, fields); free(tmpstr); if (nfield == 1) { trim_whitespace(fields[0]); insert_newlines(fields[0]); entry->About=fields[0]; } else break; } if (!strncmp(line, "Resolution:", 11)) { tmpstr=getfield(line); nfield = parsefields(tmpstr, fields); free(tmpstr); if (nfield == 3) { nres++; if (nres >= nres_alloc) { nres_alloc += 10; entry->Resolution= (char **)realloc(entry->Resolution, nres_alloc*sizeof(char*)); entry->ResDescr= (char **)realloc(entry->ResDescr, nres_alloc*sizeof(char*)); } entry->Resolution[nres-1]= (char *)malloc(strlen(fields[0])+strlen(fields[1])+10); sprintf(entry->Resolution[nres-1], "%sx%s", fields[0],fields[1]); if (fields[2]) entry->ResDescr[nres-1]=strdup(fields[2]); else entry->ResDescr[nres-1]=NULL; } else break; } if (!strncmp(line, "BitsPerPixel:", 13)) { tmpstr=getfield(line); nfield = parsefields(tmpstr, fields); free(tmpstr); if (nfield == 2) { nbpp++; if (nbpp >= nbpp_alloc) { nbpp_alloc += 10; entry->BitsPerPixel= (char **)realloc(entry->BitsPerPixel, nbpp_alloc*sizeof(char*)); entry->BppDescr= (char **)realloc(entry->BppDescr, nbpp_alloc*sizeof(char*)); } entry->BitsPerPixel[nbpp-1]=strdup(fields[0]); if (fields[1]) entry->BppDescr[nbpp-1]=strdup(fields[1]); else entry->BppDescr[nbpp-1]=NULL; } else break; } free(line); } entry->NumRes = nres; entry->NumBpp = nbpp; } else { free(line); } } fclose(dbfile); qsort(thedb, numdb, sizeof(*thedb), dbCompare); return 0; } #if 0 /* used by below routines - assumes everything is malloc'd */ /* updates old to new if new is non-NULL */ /* frees the old value and points it at the new */ /* if new is NULL, means it wasnt updated and old remains unchanged */ static void update_changed( void *new, void **old ) { if (new) { if (*old) free(*old); *old = new; } } #endif /* display summary line given by char * arg */ void show_printer_about( char *about ) { newtComponent infoform, infook, infobox, answer; newtCenteredWindow(56, 15, "Printer Info"); infoform = newtForm(NULL, NULL, 0); infobox=newtTextbox(3, 2, 50, 8, NEWT_TEXTBOX_WRAP|NEWT_TEXTBOX_SCROLL); newtTextboxSetText( infobox, about ); infook = newtButton( 23, 11, "Ok"); newtFormAddComponents(infoform, infobox, infook, NULL); answer = newtRunForm( infoform ); newtPopWindow(); newtFormDestroy(infoform); } /* select the printer type you have */ /* return < 0 if user aborted */ /* returns index into thedb[] of the selected entry otherwise*/ static int select_printer_type( PCEntry *changes) { newtComponent ok, cancel, form, listbox, answer; struct newtExitStruct event; long i, sel; int formdone; char *origtype; if (changes->db && changes->db->Descr) { origtype = alloca(strlen(changes->db->Descr)+2); strcpy(origtype, changes->db->Descr); } else origtype = NULL; newtCenteredWindow(60, 18, "Configure Printer"); newtPushHelpLine(" will give you information on a particular " "printer type"); form = newtForm(NULL, NULL, 0); newtFormAddComponent(form, newtLabel(3, 1, "What type of printer " "do you have?")); listbox = newtListbox(6, 3, 10, NEWT_FLAG_RETURNEXIT); for (i = 0; i < numdb; i++) { newtListboxAddEntry(listbox, thedb[i]->Descr, (void *)i); if (changes->db && changes->db->Entry && !strcmp(changes->db->Entry,thedb[i]->Entry)) { newtListboxSetCurrent(listbox, i); } } /* if no selection yet, default to PostScript if it exists */ if (changes->db==NULL || changes->db->Entry==NULL ) { /* set this just in case we find nothing that matches */ newtListboxSetCurrent(listbox, 0); for (i = 0; i < numdb; i++) if (!strcmp(thedb[i]->Descr,"PostScript printer")) { newtListboxSetCurrent(listbox, i); break; } } ok = newtButton( 15, 14, NEXT_LABEL); cancel = newtButton( 31, 14, PREV_LABEL); newtFormAddComponents( form, listbox, ok, cancel, NULL); newtFormAddHotKey(form, NEWT_KEY_F1); formdone = 0; answer = NULL; while (!formdone) { newtFormRun(form, &event); if (event.reason == NEWT_EXIT_HOTKEY) { if (event.u.key == NEWT_KEY_F12) formdone = 1; else if (event.u.key == NEWT_KEY_F1) { show_printer_about( thedb[(long)newtListboxGetCurrent(listbox)]->About); } } else if (event.reason == NEWT_EXIT_COMPONENT) { formdone = 1; if (event.u.co == cancel) answer = cancel; } } sel = (long) newtListboxGetCurrent(listbox); newtPopWindow(); newtPopHelpLine(); newtFormDestroy(form); if ( answer == cancel ) return -1; /* store new values */ changes->db = thedb[sel]; /* MAJOR HACK */ /* if the printer is an HP, lets do stairstep correction */ if (!strncmp(changes->db->Descr,"HP",2)) { if (changes->CRLF) free(changes->CRLF); changes->CRLF=strdup("YES"); } else { if (origtype) { if (strcmp(origtype, changes->db->Descr)) { if (changes->CRLF) free(changes->CRLF); changes->CRLF=strdup("NO"); } } else { if (changes->CRLF) free(changes->CRLF); changes->CRLF=strdup("NO"); } } return sel; } /* select the paper size and printer resolution you want */ /* return < 0 if user aborted */ /* returns 0 otherwise */ static int select_paper_size_and_res( PCEntry *changes ) { newtComponent ok, cancel, form, text, papersz, res, answer, crlf; struct newtExitStruct event; long i; int j; int formdone; int xpos; int maxlen; char **reslines; char crlfret; /* there has to be a current selection for this to work! */ if (changes->db == NULL) return -1; newtCenteredWindow(54, 18, changes->db->Descr); newtPushHelpLine(" will give you information on this " "printer driver."); form = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 52, 2, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "You may now configure the paper size and resolution " "for this printer."); newtFormAddComponent(form, text); /* Paper size listbox */ newtFormAddComponent(form, newtLabel(7, 4, "Paper Size")); papersz = newtListbox( 8, 5, 5, NEWT_FLAG_NOSCROLL ); for (i=0; i < NUM_PAPERSIZES; i++) { newtListboxAddEntry( papersz, PaperSizes[i], (void *)i ); if (changes->PaperSize && !strcmp(changes->PaperSize, PaperSizes[i])) newtListboxSetCurrent(papersz, i); } /* make sure something is picked */ if (changes->PaperSize==NULL) newtListboxSetCurrent(papersz, 0); /* Resolution */ if ( changes->db->NumRes > 0) { maxlen = 0; reslines = (char **) alloca( changes->db->NumRes * sizeof(char *)); for (i=0; i < changes->db->NumRes; i++) { if (changes->db->ResDescr && changes->db->ResDescr[i]) { reslines[i]=alloca(strlen(changes->db->Resolution[i])+ strlen(changes->db->ResDescr[i])+15); /* we want the 'x' in the 5th column */ xpos = (strchr(changes->db->Resolution[i],'x')- changes->db->Resolution[i]); for (j=0; j<5-xpos; j++) reslines[i][j]=' '; reslines[i][j]='\000'; strcat(reslines[i],changes->db->Resolution[i]); /* pad to 13 spaces */ for (j=strlen(reslines[i]); j < 13; j++) strcat(reslines[i], " "); strcat(reslines[i],changes->db->ResDescr[i]); } else { reslines[i]=alloca(strlen(changes->db->Resolution[i])+2); strcat(reslines[i],changes->db->Resolution[i]); } if (strlen(reslines[i]) > maxlen) maxlen = strlen(reslines[i]); } newtFormAddComponent(form, newtLabel(34, 4, "Resolution")); res = newtListbox( 37-maxlen/2, 5, 5, 0 ); for (i=0; i < changes->db->NumRes; i++) { newtListboxAddEntry( res, reslines[i], (void *)i ); if (changes->Resolution && !strcmp(changes->Resolution, changes->db->Resolution[i])) newtListboxSetCurrent(res, i); } } else { newtFormAddComponent(form, newtLabel(34, 4, "Resolution")); res = newtListbox( 32, 5, 4, 0 ); newtListboxAddEntry( res, "Default", (void *)0 ); newtListboxSetCurrent(res, 0); reslines=NULL; } /* make sure something is picked */ if (changes->Resolution==NULL) newtListboxSetCurrent(res, 0); /* add stair-step correction toggle */ if (!strcmp("YES", changes->CRLF)) crlf = newtCheckbox(11, 11, "Fix stair-stepping of text?", '*', NULL,&crlfret); else crlf = newtCheckbox(11, 11, "Fix stair-stepping of text?", ' ', NULL,&crlfret); ok = newtButton( 11, 13, NEXT_LABEL); cancel = newtButton( 31, 13, PREV_LABEL); newtFormAddComponents(form,papersz,res,crlf,ok,cancel,NULL); newtFormAddHotKey(form, NEWT_KEY_F1); formdone = 0; answer = NULL; while (!formdone) { newtFormRun(form, &event); if (event.reason == NEWT_EXIT_HOTKEY) { if (event.u.key == NEWT_KEY_F12) formdone = 1; else if (event.u.key == NEWT_KEY_F1) { show_printer_about( changes->db->About ); } } else if (event.reason == NEWT_EXIT_COMPONENT) { formdone = 1; if (event.u.co == cancel) answer = cancel; } } if ( answer == cancel ) { newtPopHelpLine(); newtPopWindow(); newtFormDestroy(form); return -1; } i = (long) newtListboxGetCurrent(papersz); free(changes->PaperSize); changes->PaperSize=strdup(PaperSizes[i]); free(changes->Resolution); if (changes->db->NumRes > 0) { i = (long) newtListboxGetCurrent(res); changes->Resolution=strdup(changes->db->Resolution[i]); } else changes->Resolution=strdup("Default"); if (changes->CRLF) free(changes->CRLF); if (crlfret == ' ') changes->CRLF=strdup("NO"); else changes->CRLF=strdup("YES"); newtPopHelpLine(); newtPopWindow(); newtFormDestroy(form); return 0; } /* pick the color depth, returns < 0 on cancel, 0 otherwise */ static int select_color_depth( PCEntry *changes ) { newtComponent ok, cancel, form, bpp, answer, text; struct newtExitStruct event; long i; int formdone, maxlen; char **bpplines; /* have to have a selection to work */ if (changes->db == NULL) return -1; /* if only one color depth choice, do nothing */ if ( changes->db->NumBpp == 0) { changes->BitsPerPixel=strdup("Default"); return 0; } newtCenteredWindow(60, 15, "Configure Color Depth"); newtPushHelpLine(" will give you information on this printer driver."); form = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 58, 2, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "You may now configure the color options " "for this printer."); newtFormAddComponent(form, text); newtFormAddComponent(form, newtLabel(22, 3, "Bits Per Pixel")); if ( changes->db->NumBpp > 0) { maxlen = 0; bpplines = (char **) alloca(changes->db->NumBpp*sizeof(char *)); for (i=0; i < changes->db->NumBpp; i++) { if (changes->db->BppDescr && changes->db->BppDescr[i]) { bpplines[i]=alloca(strlen(changes->db->BitsPerPixel[i])+ strlen(changes->db->BppDescr[i])+15); bpplines[i][0]='\000'; strcat(bpplines[i],changes->db->BitsPerPixel[i]); if (bpplines[i][1] == '\000') { bpplines[i][1] = bpplines[i][0]; bpplines[i][0] = ' '; bpplines[i][2] = '\000'; } strcat(bpplines[i]," "); strcat(bpplines[i],changes->db->BppDescr[i]); } else { bpplines[i]=alloca(strlen(changes->db->BitsPerPixel[i])+2); strcpy(bpplines[i], changes->db->BitsPerPixel[i]); } /* limit the length of the line */ if (strlen(bpplines[i]) > 54) bpplines[i][50] = '\000'; if (strlen(bpplines[i]) > maxlen) maxlen = strlen(bpplines[i]); } bpp = newtListbox( 29-maxlen/2, 4, 5, NEWT_FLAG_RETURNEXIT ); for (i=0; i < changes->db->NumBpp; i++) { newtListboxAddEntry(bpp,bpplines[i], (void *)i ); if (changes->BitsPerPixel && !strcmp(changes->BitsPerPixel,changes->db->BitsPerPixel[i])) newtListboxSetCurrent(bpp, i); } } else { fprintf(stderr, "How did we get here, numbpp = 0!\n"); return -1; #if 0 bpp = newtListbox( 29-strlen("Default")/2, 5, 4,NEWT_FLAG_RETURNEXIT ); newtListboxAddEntry( bpp, "Default", (void *)0 ); newtListboxSetCurrent(bpp, 0); bpplines=NULL; #endif } /* make sure something is set */ if (changes->BitsPerPixel==NULL) newtListboxSetCurrent(bpp,0); ok = newtButton( 11, 10, NEXT_LABEL); cancel = newtButton( 36, 10, PREV_LABEL); newtFormAddComponents(form,bpp,ok,cancel,NULL); newtFormAddHotKey(form, NEWT_KEY_F1); formdone = 0; answer = NULL; while (!formdone) { newtFormRun(form, &event); if (event.reason == NEWT_EXIT_HOTKEY) { if (event.u.key == NEWT_KEY_F12) formdone = 1; else if (event.u.key == NEWT_KEY_F1) { show_printer_about( changes->db->About ); } } else if (event.reason == NEWT_EXIT_COMPONENT) { formdone = 1; if (event.u.co == cancel) answer = cancel; } } if ( answer == cancel ) { newtPopHelpLine(); newtPopWindow(); newtFormDestroy(form); return -1; } free(changes->BitsPerPixel); if (changes->db->NumBpp > 0) { i = (long) newtListboxGetCurrent(bpp); changes->BitsPerPixel=strdup(changes->db->BitsPerPixel[i]); } else { fprintf(stderr, "How did we get here, numbpp = 0!\n"); return -1; #if 0 changes->BitsPerPixel=strdup("Default"); #endif } newtPopHelpLine(); newtPopWindow(); newtFormDestroy(form); return 0; } /* returns the full attribute of the selected printer filter */ /* returns < 0 if user cancelled selected */ static int select_filter( PCEntry *changes ) { int done; int stage; int abort; done = 0; stage = 1; abort = 0; while (!done) { switch (stage) { /* select printer model/driver */ case 1: if (select_printer_type(changes) < 0) { done = 1; abort = 1; break; } else stage++; break; /* select paper size and resolution */ case 2: if (select_paper_size_and_res( changes ) < 0) { stage--; break; } else stage++; break; /* select color depth */ case 3: if (select_color_depth( changes ) < 0) { stage--; break; } else stage++; break; /* we made it and we're done */ case 4: done = 1; } } if (abort) return -1; return 0; } /* return < 0 for user cancel */ static int get_local_info( PCEntry *changes ) { newtComponent answer, cancel, form, ok, device, text; char *device_result; char *devname; int detected[3]; int i, result; int npos; #if defined(__i386__) && !defined(TESTING) if (loadModule("lp", DRIVER_OTHER, DRIVER_MINOR_NONE, NULL)) return INST_ERROR; #endif #if 0 /* old way Erik did this */ devMakeInode("lp0", "/tmp/lp0"); devMakeInode("lp1", "/tmp/lp1"); devMakeInode("lp2", "/tmp/lp2"); /* do auto-detect of lp ports */ detected[0] = ((result=open("/tmp/lp0", O_WRONLY|O_NONBLOCK)) != -1); if (result >= 0) close(result); detected[1] = ((result=open("/tmp/lp1", O_WRONLY|O_NONBLOCK)) != -1); if (result >= 0) close(result); detected[2] = ((result=open("/tmp/lp2", O_WRONLY|O_NONBLOCK)) != -1); if (result >= 0) close(result); unlink("/tmp/lp0"); unlink("/tmp/lp1"); unlink("/tmp/lp2"); #else /* different approach */ /* do auto-detect of lp ports */ devname=alloca(strlen(root_path)+strlen("/dev/lpX")+2); strcpy(devname,root_path); strcat(devname,"/dev/lpX"); npos=strlen(devname)-1; devname[npos]='0'; detected[0] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1); if (result >= 0) close(result); devname[npos]='1'; detected[1] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1); if (result >= 0) close(result); devname[npos]='2'; detected[2] = ((result=open(devname, O_WRONLY|O_NONBLOCK)) != -1); if (result >= 0) close(result); #endif #if defined(__i386__) && !defined(TESTING) removeModule("lp"); #endif newtCenteredWindow(44, 16, "Local Printer Device"); form = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "What device is your printer connected to (note that /dev/lp0 is " "equivalent to LPT1:)?"); newtFormAddComponent(form, text); newtFormAddComponent(form, newtLabel(3, 7, "Auto-detected ports:")); newtFormAddComponent(form, newtLabel(6, 8, "/dev/lp0:")); newtFormAddComponent(form, newtLabel(6, 9, "/dev/lp1:")); newtFormAddComponent(form, newtLabel(6, 10, "/dev/lp2:")); for (i=0; i<3; i++) { if (detected[i]) newtFormAddComponent(form, newtLabel(18,8+i, "Detected")); else newtFormAddComponent(form, newtLabel(18,8+i, "Not Detected")); } newtFormAddComponent(form, newtLabel(3, 5, "Printer Device:")); if (changes->Device) device=newtEntry(19, 5, changes->Device, 15, &device_result, NEWT_FLAG_RETURNEXIT); else device=newtEntry(19, 5, "/dev/lp1", 15, &device_result, NEWT_FLAG_RETURNEXIT); ok = newtButton( 7, 12, NEXT_LABEL); cancel = newtButton( 24, 12, PREV_LABEL); newtFormAddComponents( form, device, ok, cancel, NULL); answer = newtRunForm(form); if ( answer != cancel ) { free(changes->Device); changes->Device = strdup(device_result); result = 0; } else result = -1; newtPopWindow(); newtFormDestroy(form); return result; } /* return < 0 for user cancel */ static int get_remote_info( PCEntry *changes ) { newtComponent answer, cancel, form, ok, rhost, rqueue, text; char *queue_result; char *host_result; int result; newtCenteredWindow(42, 14, "Remote lpd Printer Options"); form = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 40, 5, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "To use a remote lpd print queue, you need to supply the " "hostname of the printer server and the queue name on that " "server which jobs should be placed in."); newtFormAddComponent(form, text); newtFormAddComponent(form, newtLabel(2, 7, "Remote hostname:")); newtFormAddComponent(form, newtLabel(2, 8, "Remote queue:")); if (changes->RemoteHost) rhost =newtEntry(19, 7, changes->RemoteHost, 20, &host_result, 0); else rhost =newtEntry(19, 7, "", 20, &host_result, 0); if (changes->RemoteQueue) rqueue =newtEntry(19, 8, changes->RemoteQueue, 20, &queue_result, 0); else rqueue =newtEntry(19, 8, "lp", 20, &queue_result, 0); ok = newtButton( 7, 10, NEXT_LABEL); cancel = newtButton( 24, 10, PREV_LABEL); newtFormAddComponents( form, rhost, rqueue, ok, cancel, NULL); answer = newtRunForm(form); if ( answer != cancel ) { free(changes->RemoteHost); changes->RemoteHost = strdup(host_result); free(changes->RemoteQueue); changes->RemoteQueue = strdup(queue_result); result = 0; } else result = -1; newtPopWindow(); newtFormDestroy(form); return result; } /* return < 0 for user cancel */ static int get_smb_info( PCEntry *changes ) { newtComponent answer, cancel, form, ok, text; newtComponent host, hostip, share, user, passwd; int result; char *host_result; char *hostip_result; char *share_result; char *user_result; char *passwd_result; newtCenteredWindow(60, 18, "LAN Manager Printer Options"); form = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 58, 6, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "To print to a LAN manager printer, you need to provide the " "LAN manager host name (this is not always the same as the machines " "TCP/IP hostname) and possibly the IP address of the print server, as " "well as the share name for the printer you wish to access and any " "applicable user name and password."); newtFormAddComponent(form, text); newtFormAddComponent(form, newtLabel(10, 8, "LAN Manager Host:")); newtFormAddComponent(form, newtLabel(10, 9, "LAN Manager IP:")); newtFormAddComponent(form, newtLabel(10, 10, "Share Name:")); newtFormAddComponent(form, newtLabel(10, 11, "Username:")); newtFormAddComponent(form, newtLabel(10, 12, "Password:")); if (changes->SMBHost) host = newtEntry(28, 8, changes->SMBHost, 15, &host_result, 0); else host = newtEntry(28, 8, "", 15, &host_result, 0); if (changes->SMBHostIP) hostip = newtEntry(28, 9, changes->SMBHostIP, 15, &hostip_result, 0); else hostip = newtEntry(28, 9, "", 15, &hostip_result, 0); if (changes->SMBShare) share = newtEntry(28, 10, changes->SMBShare, 15, &share_result, 0); else share = newtEntry(28, 10, "", 15, &share_result, 0); if (changes->SMBUser) user = newtEntry(28, 11, changes->SMBUser, 15, &user_result, 0); else user = newtEntry(28, 11, "", 15, &user_result, 0); if (changes->SMBPasswd) passwd = newtEntry(28, 12, changes->SMBPasswd, 15, &passwd_result, NEWT_ENTRY_HIDDEN); else passwd = newtEntry(28, 12, "", 15, &passwd_result, NEWT_ENTRY_HIDDEN); ok = newtButton( 15, 14, NEXT_LABEL); cancel = newtButton( 35, 14, PREV_LABEL); newtFormAddComponents( form, host, hostip, share, user, passwd, ok, cancel, NULL); answer = newtRunForm(form); if ( answer != cancel ) { free(changes->SMBHost); changes->SMBHost = strdup(host_result); free(changes->SMBHostIP); changes->SMBHostIP = strdup(hostip_result); free(changes->SMBShare); changes->SMBShare = strdup(share_result); free(changes->SMBUser); changes->SMBUser = strdup(user_result); free(changes->SMBPasswd); changes->SMBPasswd = strdup(passwd_result); result = 0; } else result = -1; newtPopWindow(); newtFormDestroy(form); return result; } /* return < 0 for user cancel */ static int get_std_info( PCEntry *changes ) { newtComponent answer, cancel, form, ok, queue, spool, text; char *queue_result; char *spool_result; int result; newtCenteredWindow(52, 14, "Standard Printer Options"); form = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 50, 5, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "Every print queue (which print jobs are directed to) needs a " "name (often lp) and a spool directory associated with it. What " "name and directory should be used for this queue? "); newtFormAddComponent(form, newtLabel(2, 7, "Name of queue:")); newtFormAddComponent(form, newtLabel(2, 8, "Spool directory:")); if (changes->Queue) queue =newtEntry(20, 7, changes->Queue, 30, &queue_result, 0); else queue =newtEntry(20, 7, "lp", 30, &queue_result, 0); if (changes->SpoolDir) spool =newtEntry(20, 8, changes->SpoolDir, 30, &spool_result, 0); else spool =newtEntry(20, 8, "/var/spool/lpd/lp", 30, &spool_result, 0); ok = newtButton( 11, 10, NEXT_LABEL); cancel = newtButton( 27, 10, PREV_LABEL); newtFormAddComponents(form, text, queue, spool, ok, cancel, NULL); answer = newtRunForm(form); if ( answer != cancel ) { free(changes->Queue); changes->Queue = strdup(queue_result); free(changes->SpoolDir); changes->SpoolDir = strdup(spool_result); result = 0; } else { result = -1; } newtPopWindow(); newtFormDestroy(form); return result; } static int query_config(void) { int result; result = newtWinChoice("Configure Printer", "Yes", "No", "Would you like to configure a printer?"); if (result == 1) return -1; return 0; } #if 0 static int query_add_more() { int result; result = newtWinChoice("Add Printer", "Yes", "No", "Would you like to add another printer?"); if (result == 1) return -1; return 0; } #endif /* returns 1 if they want to quit, 0 otherwise */ static int you_are_sure(void) { int result; result = newtWinChoice("Confirm Termination", "Exit", "Continue", "If you choose 'Exit', you will return to the main " "installation without a printer being configured.\n\n" "Choose 'Continue' to return to configuring " "your printer."); if (result == 1) return 0; return 1; } /* returns < 0 for user cancel, otherwise uses #defines in printercfg.h */ static int get_prn_connx( char *Type ) { newtComponent answer, cancel, form, ok, listbox; int sel; newtCenteredWindow(33, 12, "Select Printer Connection"); form = newtForm(NULL, NULL, 0); newtFormAddComponent(form, newtLabel(1, 1, "How is this printer connected?")); listbox = newtListbox(9, 3, 0, NEWT_FLAG_NOSCROLL | NEWT_FLAG_RETURNEXIT); newtListboxAddEntry(listbox, "Local", (void *)LOCAL_CONNX); newtListboxAddEntry(listbox, "Remote lpd", (void *)REMOTE_LPD_CONNX); newtListboxAddEntry(listbox, "LAN Manager", (void *)SMB_CONNX); if (Type) if (!strcmp(Type,"LOCAL")) newtListboxSetCurrent(listbox, 0); else if (!strcmp(Type,"REMOTE")) newtListboxSetCurrent(listbox, 1); else if (!strcmp(Type,"SMB")) newtListboxSetCurrent(listbox, 2); ok = newtButton( 4, 7, NEXT_LABEL); cancel = newtButton( 17, 7, "Cancel"); newtFormAddComponents(form, listbox, ok, cancel, NULL); answer = newtRunForm(form); if ( answer == cancel ) { newtPopWindow(); newtFormDestroy(form); return -1; } else { sel = (long) newtListboxGetCurrent(listbox); newtPopWindow(); newtFormDestroy(form); return sel; } } /* edit the PrintCap Entry pcentry */ /* return < 0 if user aborts or error occurs */ static int edit_pcentry( PCEntry **pcentry ) { int result; int stage; int done; int abort; PCEntry *changes; /* copy current into temporary */ changes = dup_PCEntry( *pcentry ); done = 0; abort = 0; stage = 0; while (!done) { switch (stage) { case 0: switch (get_prn_connx(changes->Type)) { case -1: if (you_are_sure()) { done = 1; abort = 1; } break; case LOCAL_CONNX: free(changes->Type); changes->Type = strdup("LOCAL"); stage++; break; case REMOTE_LPD_CONNX: free(changes->Type); changes->Type = strdup("REMOTE"); stage++; break; case SMB_CONNX: free(changes->Type); changes->Type = strdup("SMB"); stage++; break; default: break; } break; case 1: result=get_std_info(changes); if (result < 0) stage--; else stage++; break; case 2: if (!strcmp(changes->Type, "SMB")) result=get_smb_info(changes); else if (!strcmp(changes->Type, "REMOTE")) result=get_remote_info(changes); else if (!strcmp(changes->Type, "LOCAL")) result=get_local_info(changes); else return -1; if (result < 0) stage--; else stage++; break; case 3: result=select_filter(changes); if (result < 0) stage--; else stage++; break; case 4: done = 1; break; } } if (!abort) { free_PCEntry(*pcentry); *pcentry = changes; return 0; } else { free_PCEntry(changes); return -1; } } /* returns 0 on success, -1 on abort, and -2 if user wishes to re-edit */ static int verify_pcentry( PCEntry *pcentry ) { newtComponent form, ok, edit, cancel, answer; char tmpstr[256]; int row; int done; int result; newtCenteredWindow(60, 18, "Verify Printer Configuration"); form = newtForm(NULL, NULL, 0); newtFormAddComponent(form, newtLabel(3, 1, "Please verify that this printer information is correct:")); row=3; sprintf(tmpstr, "Printer Type : %s\n",pcentry->Type); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); sprintf(tmpstr, "Queue : %s\n",pcentry->Queue); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); sprintf(tmpstr, "Spool directory : %s\n",pcentry->SpoolDir); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); if (!strcmp(pcentry->Type, "LOCAL")) { sprintf(tmpstr, "Printer device : %s\n",pcentry->Device); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); } else if (!strcmp(pcentry->Type, "REMOTE")) { sprintf(tmpstr, "Remote Host : %s\n",pcentry->RemoteHost); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); sprintf(tmpstr, "Remote Queue : %s\n",pcentry->RemoteQueue); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); } else if (!strcmp(pcentry->Type, "SMB")) { if (pcentry->SMBHostIP && pcentry->SMBHostIP[0]) sprintf(tmpstr, "Server : %s [%s]\n", pcentry->SMBHost, pcentry->SMBHostIP); else sprintf(tmpstr, "Server : %s\n",pcentry->SMBHost); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); sprintf(tmpstr, "Share : %s\n",pcentry->SMBShare); newtFormAddComponent(form, newtLabel(5, row++, tmpstr)); sprintf(tmpstr, "User : %s