/* Text based printer configuration for the RHS install program */ /* Michael Fulbright - 1997 */ /* */ /* Heavily hacked by ewt for post-Red Hat 5.0 releases */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "devices.h" #include "install.h" #include "intl.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 ) { memset(pcentry, 0, sizeof(*pcentry)); } /* allocate a new PrintCap Entry */ static PCEntry *new_PCEntry() { PCEntry *pcentry; pcentry = malloc(sizeof(PCEntry)); initialize_PCEntry( pcentry ); return pcentry; } static char * safestrdup(char * item) { return item ? strdup(item) : NULL; } /* 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(); pcentry->Queue = safestrdup(orig->Queue); pcentry->SpoolDir = safestrdup(orig->SpoolDir); pcentry->Device = safestrdup(orig->Device); pcentry->IF = safestrdup(orig->IF); pcentry->AF = safestrdup(orig->AF); pcentry->Type = orig->Type; pcentry->db = orig->db; pcentry->Resolution = safestrdup(orig->Resolution); pcentry->PaperSize = safestrdup(orig->PaperSize); pcentry->BitsPerPixel = safestrdup(orig->BitsPerPixel); pcentry->CRLF = orig->CRLF; pcentry->RemoteHost = safestrdup(orig->RemoteHost); pcentry->RemoteQueue = safestrdup(orig->RemoteQueue); pcentry->SMBHost = safestrdup(orig->SMBHost); pcentry->SMBHostIP = safestrdup(orig->SMBHostIP); pcentry->SMBShare = safestrdup(orig->SMBShare); pcentry->SMBUser = safestrdup(orig->SMBUser); pcentry->SMBPasswd = safestrdup(orig->SMBPasswd); pcentry->SMBWorkgroup = safestrdup(orig->SMBWorkgroup); pcentry->NCPHost = safestrdup(orig->NCPHost); pcentry->NCPQueue = safestrdup(orig->NCPQueue); pcentry->NCPUser = safestrdup(orig->NCPUser); pcentry->NCPPasswd = safestrdup(orig->NCPPasswd); 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->Resolution); free(pcentry->PaperSize); free(pcentry->BitsPerPixel); free(pcentry->RemoteHost); free(pcentry->RemoteQueue); free(pcentry->SMBHost); free(pcentry->SMBHostIP); free(pcentry->SMBShare); free(pcentry->SMBUser); free(pcentry->SMBPasswd); free(pcentry->SMBWorkgroup); free(pcentry->NCPHost); free(pcentry->NCPQueue); free(pcentry->NCPUser); free(pcentry->NCPPasswd); 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 ) { newtWinMessage(_("Printer Information"), _("Ok"), about); } /* 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 okay, cancel, form, listbox, answer; struct newtExitStruct event; long i, sel; int formdone; char *origtype; newtGrid grid, buttons; if (changes->db && changes->db->Descr) { origtype = alloca(strlen(changes->db->Descr)+2); strcpy(origtype, changes->db->Descr); } else origtype = NULL; newtPushHelpLine(_(" will give you information on a particular " "printer type")); grid = newtCreateGrid(1, 3); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("What type of printer do you have?")), 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); listbox = newtListbox(-1, -1, 10, NEWT_FLAG_RETURNEXIT | NEWT_FLAG_SCROLL); 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); } } newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox, 2, 1, 2, 0, 0, 0); /* 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; } } buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL); newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); form = newtForm(NULL, NULL, 0); newtFormAddHotKey(form, NEWT_KEY_F1); newtGridAddComponentsToForm(grid, form, 1); newtGridWrappedWindow(grid, _("Configure Printer")); newtGridFree(grid, 1); 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, let's do stairstep correction */ if (!strncmp(changes->db->Descr,"HP",2)) { changes->CRLF = 1; } else { if (origtype) { if (strcmp(origtype, changes->db->Descr)) { changes->CRLF = 0; } } else { changes->CRLF = 0; } } 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 okay, cancel, form, text, papersz, res, answer, crlf; struct newtExitStruct event; long i; int formdone; char * xpos; newtGrid grid, subgrid, buttons, leftgrid, rightgrid; char crlfret; char buf[200]; /* there has to be a current selection for this to work! */ if (changes->db == NULL) return -1; newtPushHelpLine(_(" will give you information on this " "printer driver.")); text = newtTextboxReflowed(-1, -1, _("You may now configure the paper size and resolution " "for this printer."), 52, 5, 5, 0); subgrid = newtCreateGrid(2, 1); leftgrid = newtCreateGrid(1, 2); rightgrid = newtCreateGrid(1, 2); /* Paper size listbox */ newtGridSetField(leftgrid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("Paper Size")), 0, 0, 0, 0, 0, 0); papersz = newtListbox( 8, 5, 5, 0); for (i=0; i < NUM_PAPERSIZES; i++) { newtListboxAddEntry( papersz, PaperSizes[i], (void *)i ); if (changes->PaperSize && !strcmp(changes->PaperSize, PaperSizes[i])) newtListboxSetCurrent(papersz, i); } newtGridSetField(leftgrid, 0, 1, NEWT_GRID_COMPONENT, papersz, 0, 0, 0, 0, 0, 0); newtGridSetField(subgrid, 0, 0, NEWT_GRID_SUBGRID, leftgrid, 0, 0, 0, 0, 0, 0); /* make sure something is picked */ if (changes->PaperSize==NULL) newtListboxSetCurrent(papersz, 0); /* Resolution */ newtGridSetField(rightgrid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(-1, -1, _("Resolution")), 0, 0, 0, 0, 0, 0); res = newtListbox(-1, -1, 5, changes->db->NumRes < 5 ? 0 : NEWT_FLAG_SCROLL); if ( changes->db->NumRes > 0) { for (i=0; i < changes->db->NumRes; i++) { xpos = strchr(changes->db->Resolution[i],'x'); *xpos = '\0'; sprintf(buf, "%4sx%4s %s", changes->db->Resolution[i], xpos + 1, changes->db->ResDescr[i] ? changes->db->ResDescr[i] : ""); *xpos = 'x'; newtListboxAddEntry(res, buf, (void *) i); if (changes->Resolution && !strcmp(changes->Resolution, changes->db->Resolution[i])) newtListboxSetCurrent(res, i); } } else { newtListboxAddEntry( res, _("Default"), (void *)0 ); newtListboxSetCurrent(res, 0); } /* make sure something is picked */ if (changes->Resolution==NULL) newtListboxSetCurrent(res, 0); newtGridSetField(rightgrid, 0, 1, NEWT_GRID_COMPONENT, res, 0, 0, 0, 0, 0, 0); newtGridSetField(subgrid, 1, 0, NEWT_GRID_SUBGRID, rightgrid, 0, 0, 0, 0, 0, 0); crlf = newtCheckbox(-1, -1, _("Fix stair-stepping of text?"), changes->CRLF ? '*' : ' ', NULL,&crlfret); buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL); grid = newtCreateGrid(1, 4); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, subgrid, 4, 1, 4, 0, 0, NEWT_GRID_FLAG_GROWX); newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, crlf, 0, 1, 0, 0, 0, 0); newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons, 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); form = newtForm(NULL, NULL, 0); newtGridWrappedWindow(grid, changes->db->Descr); newtGridAddComponentsToForm(grid, form, 1); newtGridFree(grid, 1); 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 (crlfret == ' ') changes->CRLF = 0; else changes->CRLF = 1; newtPopHelpLine(); newtPopWindow(); newtFormDestroy(form); return 0; } /* pick the color depth, returns < 0 on cancel, 0 otherwise */ static int select_color_depth( PCEntry *changes, int direction ) { newtComponent okay, cancel, form, bpp, answer, text; struct newtExitStruct event; int i, width, height; int formdone, maxlen; newtGrid grid, buttons; char buf[200]; char * reflowedText; /* 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 direction > 0 ? 0 : -1; } /* we know that changes->db->NumBpp > 0 */ newtPushHelpLine(_(" will give you information on this " "printer driver.")); bpp = newtListbox(-1, -1, (changes->db->NumBpp < 8) ? changes->db->NumBpp : 8, NEWT_FLAG_RETURNEXIT | NEWT_FLAG_SCROLL); maxlen = 0; for (i=0; i < changes->db->NumBpp; i++) { sprintf(buf, "%2s %s", changes->db->BitsPerPixel[i], changes->db->BppDescr[i] ? changes->db->BppDescr[i] : ""); /* limit the length of the line */ if (strlen(buf) > 70) buf[70] = '\000'; newtListboxAddEntry(bpp, buf, (void *)i ); if (changes->BitsPerPixel && !strcmp(changes->BitsPerPixel, changes->db->BitsPerPixel[i])) newtListboxSetCurrent(bpp, i); if (strlen(buf) > maxlen) maxlen = strlen(buf); } /* make sure something is set */ if (changes->BitsPerPixel==NULL) newtListboxSetCurrent(bpp,0); if (strcmp(changes->db->GSDriver,"uniprint")) reflowedText = newtReflowText(_("You may now configure the color " "options for this printer."), maxlen + 5, 5, 3, &width, &height); else reflowedText = newtReflowText(_("You may now configure the uniprint " "options for this printer."), maxlen + 5, 5, 3, &width, &height); text = newtTextbox(1, 1, width, height, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, reflowedText); free(reflowedText); buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL); form = newtForm(NULL, NULL, 0); newtFormAddHotKey(form, NEWT_KEY_F1); grid = newtGridSimpleWindow(text, bpp, buttons); if (strcmp(changes->db->GSDriver,"uniprint")) newtGridWrappedWindow(grid, _("Configure Color Depth")); else newtGridWrappedWindow(grid, _("Configure Uniprint Driver")); newtGridAddComponentsToForm(grid, form, 1); newtGridFree(grid, 1); 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 ) { free(changes->BitsPerPixel); i = (long) newtListboxGetCurrent(bpp); changes->BitsPerPixel=strdup(changes->db->BitsPerPixel[i]); } newtPopHelpLine(); newtPopWindow(); newtFormDestroy(form); return (answer == cancel) ? -1 : 0; } /* returns the full attribute of the selected printer filter */ /* returns < 0 if user cancelled selected */ static int select_filter( PCEntry *changes, int direction ) { int done; int stage; int abort; done = 0; stage = direction > 0 ? 1 : 3; 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++; direction = 1; } break; /* select paper size and resolution */ case 2: if (select_paper_size_and_res( changes ) < 0) { direction = -1; } else direction = 1; stage += direction; break; /* select color depth */ case 3: if (select_color_depth( changes, direction ) < 0) direction = -1; else direction = 1; stage += direction; 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, okay, device, text, detectedW; char buf[2000]; char *device_result; char *devname; char * reflowedText; int width, height; int detected[3]; int i, result; int npos; newtGrid grid, subgrid, buttons; #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 reflowedText = newtReflowText(_("What device is your printer connected to " "(note that /dev/lp0 is equivalent to LPT1:)?"), 40, 5, 5, &width, &height); text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, reflowedText); free(reflowedText); strcpy(buf, _("Auto-detected ports:\n\n")); for (i=0; i<3; i++) { strcat(buf, " /dev/lp"); buf[strlen(buf) + 1] = '\0'; buf[strlen(buf)] = i + '0'; strcat(buf, ": "); if (!detected[i]) strcat(buf, _("Not ")); strcat(buf, _("Detected\n")); } reflowedText = newtReflowText(buf, 40, 5, 5, &width, &height); detectedW = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP); newtTextboxSetText(detectedW, reflowedText); free(reflowedText); subgrid = newtCreateGrid(2, 1); newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT, newtLabel(3, 5, _("Printer Device:")), 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); device = newtEntry(19, 5, changes->Device ? changes->Device : "/dev/lp0", 15, &device_result, NEWT_FLAG_RETURNEXIT); newtGridSetField(subgrid, 1, 0, NEWT_GRID_COMPONENT, device, 1, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL); grid = newtCreateGrid(1, 4); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, 0, 0, 0, 0, 0, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, subgrid, 2, 1, 0, 0, 0, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, detectedW, 2, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons, 0, 1, 0, 0, 0, NEWT_GRID_FLAG_GROWX); form = newtForm(NULL, NULL, 0); newtGridAddComponentsToForm(grid, form, 1); newtGridWrappedWindow(grid, _("Local Printer Device")); newtGridFree(grid, 1); 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 ) { char *queue_result = changes->RemoteQueue; char *host_result = changes->RemoteHost; int result; struct newtWinEntry entries[3] = { { NULL, &host_result, NEWT_ENTRY_SCROLL }, { NULL, &queue_result, NEWT_ENTRY_SCROLL }, { NULL, NULL, 0 } }; entries[0].text = _("Remote hostname:"); entries[1].text = _("Remote queue:"); result = newtWinEntries(_("Remote lpd Printer Options"), _("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."), 50, 5, 5, 20, entries, _("Ok"), _("Back"), NULL); if (result != 2) { free(changes->RemoteHost); changes->RemoteHost = host_result; free(changes->RemoteQueue); changes->RemoteQueue = queue_result; result = 0; } else { result = -1; free(host_result); free(queue_result); } return result; } static int get_ncp_info( PCEntry *changes ) { int result; char *host_result = changes->NCPHost; char *queue_result = changes->NCPQueue; char *user_result = changes->NCPUser; char *passwd_result = changes->NCPPasswd; struct newtWinEntry entries[] = { { NULL, &host_result, NEWT_ENTRY_SCROLL }, { NULL, &queue_result, NEWT_ENTRY_SCROLL }, { NULL, &user_result, NEWT_ENTRY_SCROLL }, { NULL, &passwd_result, NEWT_ENTRY_SCROLL | NEWT_ENTRY_HIDDEN }, { NULL, NULL, 0 } }; entries[0].text = _("Printer Server:"); entries[1].text = _("Print Queue Name:"); entries[2].text = _("User name:"); entries[3].text = _("Password:"); result = newtWinEntries(_("NetWare Printer Options"), _("To print to a NetWare printer, you need to provide the " "NetWare print server name (this is not always the same as the machines " "TCP/IP hostname) " "as well as the print queue name for the printer you wish to access and any " "applicable user name and password."), 50, 4, 4, 20, entries, _("Ok"), _("Back"), NULL); if ( result != 2 ) { free(changes->NCPHost); changes->NCPHost = host_result; free(changes->NCPQueue); changes->NCPQueue = queue_result; free(changes->NCPUser); changes->NCPUser = user_result; free(changes->NCPPasswd); changes->NCPPasswd = passwd_result; result = 0; } else { result = -1; free(host_result); free(queue_result); free(user_result); free(passwd_result); } return result; } /* return < 0 for user cancel */ static int get_smb_info( PCEntry *changes ) { int result; char *host_result = changes->SMBHost; char *hostip_result = changes->SMBHostIP; char *share_result = changes->SMBShare; char *user_result = changes->SMBUser; char *passwd_result = changes->SMBPasswd; char *workgroup_result = changes->SMBWorkgroup; struct newtWinEntry entries[] = { { NULL, &host_result, NEWT_ENTRY_SCROLL }, { NULL, &hostip_result, NEWT_ENTRY_SCROLL }, { NULL, &share_result, NEWT_ENTRY_SCROLL }, { NULL, &user_result, NEWT_ENTRY_SCROLL }, { NULL, &passwd_result, NEWT_ENTRY_SCROLL | NEWT_ENTRY_HIDDEN }, { NULL, &workgroup_result, NEWT_ENTRY_SCROLL }, { NULL, NULL, 0 } }; entries[0].text = _("SMB server host:"); entries[1].text = _("SMB server IP:"); entries[2].text = _("Share name:"); entries[3].text = _("User name:"); entries[4].text = _("Password:"); entries[5].text = _("Workgroup:"); result = newtWinEntries(_("SMB/Windows 95/NT Printer Options"), _("To print to a SMB printer, you need to provide the " "SMB 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, password, and workgroup information."), 50, 5, 5, 20, entries, _("Ok"), _("Back"), NULL); if ( result != 2 ) { free(changes->SMBHost); changes->SMBHost = host_result; free(changes->SMBHostIP); changes->SMBHostIP = hostip_result; free(changes->SMBShare); changes->SMBShare = share_result; free(changes->SMBUser); changes->SMBUser = user_result; free(changes->SMBPasswd); changes->SMBPasswd = passwd_result; free(changes->SMBWorkgroup); changes->SMBWorkgroup = workgroup_result; result = 0; } else { result = -1; free(host_result); free(hostip_result); free(share_result); free(user_result); free(passwd_result); free(workgroup_result); } return result; } /* return < 0 for user cancel */ static int get_std_info( PCEntry *changes ) { char *queue_result = changes->Queue ? changes->Queue : "lp"; char *spool_result = changes->SpoolDir ? changes->SpoolDir : "/var/spool/lpd/lp"; int result; struct newtWinEntry entries[3] = { { NULL, &queue_result, NEWT_ENTRY_SCROLL }, { NULL, &spool_result, NEWT_ENTRY_SCROLL }, { NULL, NULL, 0 } }; entries[0].text = _("Name of queue:"); entries[1].text = _("Spool directory:"); result = newtWinEntries(_("Standard Printer Options"), _("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?"), 50, 5, 5, 20, entries, _("Ok"), _("Back"), NULL); if (result != 2) { free(changes->Queue); changes->Queue = queue_result; free(changes->SpoolDir); changes->SpoolDir = spool_result; result = 0; } else { free(queue_result); free(spool_result); result = -1; } return result; } #define QUERY_YES 0 #define QUERY_NO 1 #define QUERY_BACK 2 static int queryConfig(void) { int result; result = newtWinTernary(_("Configure Printer"), _("Yes"), _("No"), _("Back"), _("Would you like to configure a printer?")); if (result == 2) return QUERY_NO; else if (result == 3) return QUERY_BACK; return QUERY_YES; } #if 0 static int query_add_more() { int result; result = newtWinChoice(_("Add Printer"), _("Yes"), _("No"), _("Would you like to add another printer?")); if (result == 2) return -1; return 0; } #endif static char * connToString(int connType) { switch (connType) { case PRINTER_LOCAL: return "LOCAL"; case PRINTER_LPRREM: return "REMOTE"; case PRINTER_SMB: default: return "SMB"; case PRINTER_NCP: return "NCP"; } } /* returns < 0 for user cancel, otherwise uses #defines in printercfg.h */ static int get_prn_connx(int connType) { int sel = connType, rc; char * connectionTypes[5]; connectionTypes[0] = _("Local"); connectionTypes[1] = _("Remote lpd"); connectionTypes[2] = _("SMB/Windows 95/NT"); connectionTypes[3] = _("NetWare"); connectionTypes[4] = NULL; sel--; rc = newtWinMenu(_("Select Printer Connection"), _("How is this printer connected?"), 40, 5, 5, 5, connectionTypes, &sel, _("Ok"), _("Back"), NULL); if (rc == 2) return -1; return sel + 1; } /* returns 0 on success, -1 on cancel */ static int verify_pcentry( PCEntry *pcentry ) { char tmpstr[500]; int done; int result; int i, max; char info[2000]; int lens[15]; lens[0] = strlen(_("Printer type:")); lens[1] = strlen(_("Queue:")); lens[2] = strlen(_("Spool directory:")); lens[3] = strlen(_("Printer device:")); lens[4] = strlen(_("Remote host:")); lens[5] = strlen(_("Remote queue:")); lens[6] = strlen(_("Server:")); lens[7] = strlen(_("Share:")); lens[8] = strlen(_("User:")); lens[9] = strlen(_("Printer driver:")); lens[10] = strlen(_("Paper size:")); lens[11] = strlen(_("Resolution:")); if (strcmp(pcentry->db->GSDriver,"uniprint")) { lens[12] = strlen(_("Bits per pixel:")); } else { lens[12] = strlen(_("Uniprint driver:")); } max = 0; for (i = 0; i <= 12; i++) if (lens[i] > max) max = lens[i]; strcpy(info, _("Please verify that this printer information is " "correct:\n\n")); sprintf(tmpstr, " %-*s %s\n %-*s %s\n %-*s %s\n", max, _("Printer type:"), connToString(pcentry->Type), max, _("Queue:"), pcentry->Queue, max, _("Spool directory:"), pcentry->SpoolDir); strcat(info, tmpstr); if (pcentry->Type == PRINTER_LOCAL) { sprintf(tmpstr, " %-*s %s\n", max, _("Printer device"), pcentry->Device); } else if (pcentry->Type == PRINTER_LPRREM) { sprintf(tmpstr, " %-*s %s\n %-*s %s\n", max, _("Remote host:"), pcentry->RemoteHost, max, _("Remote queue:"), pcentry->RemoteQueue); } else if (pcentry->Type == PRINTER_NCP) { sprintf(tmpstr, " %-*s %s\n %-*s %s\n %-*s %s