void lsmatch(char *cp) { char *save = smalloc(LBSIZE); register char *sp = save; register char *scurs = cursor; wcursor = cp; lcpy(sp, linebuf, LBSIZE); *wcursor = 0; strcpy(cursor, genbuf); cursor = strend(linebuf) - 1; if (lmatchp(dot - vcline)) { register int i = insmode; register int c = outcol; register int l = outline; if (!MI) endim(); vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1); flush(); sleep(1); vgoto(l, c); if (i) goim(); } else { strcLIN(sp); strcpy(scurs, genbuf); if (!lmatchp((line *) 0)) beep(); } strcLIN(sp); wdot = 0; wcursor = 0; cursor = scurs; free(save); }
/* ** Set the DefFiltOpts: line for a group. */ int group_deffiltopts_internal(const char *group) { if(grpopen(group, TRUE, FALSE)) { fprintf(errors, "The group \"%s\" does not exist.\n", group); return EXIT_BADDEST; } { void *qobj = NULL; const char *p; gu_Try { qobj = queueinfo_new(QUEUEINFO_GROUP, group); queueinfo_set_warnings_file(qobj, errors); queueinfo_set_debug_level(qobj, debug_level); /* Modify the group's configuration file. */ while(confread()) { if(lmatch(confline, "DefFiltOpts:")) continue; if((p = lmatchp(confline, "Printer:"))) queueinfo_add_printer(qobj, p); conf_printf("%s\n", confline); } if((p = queueinfo_computedDefaultFilterOptions(qobj))) conf_printf("DefFiltOpts: %s\n", p); confclose(); } gu_Final { if(qobj) queueinfo_free(qobj); } gu_Catch { confabort(); fprintf(errors, "%s: %s\n", myname, gu_exception); return exception_to_exitcode(gu_exception_code); } } return EXIT_OK; } /* end of group_deffiltopts_internal() */
void operate(int c, int cnt) { register int i; void (*moveop)(), (*deleteop)(); void (*opf)(); bool subop = 0; char *oglobp, *ocurs; register line *addr; static char lastFKND, lastFCHR; char d; moveop = vmove, deleteop = vdelete; wcursor = cursor; wdot = NOLINE; notecnt = 0; dir = 1; switch (c) { /* * d delete operator. */ case 'd': moveop = vdelete; deleteop = beep; break; /* * s substitute characters, like c\040, i.e. change space. */ case 's': ungetkey(' '); subop++; /* fall into ... */ /* * c Change operator. */ case 'c': if ((c == 'c' && workcmd[0] == 'C') || workcmd[0] == 'S') subop++; moveop = vchange; deleteop = beep; break; /* * ! Filter through a UNIX command. */ case '!': moveop = vfilter; deleteop = beep; break; /* * y Yank operator. Place specified text so that it * can be put back with p/P. Also yanks to named buffers. */ case 'y': moveop = vyankit; deleteop = beep; break; /* * = Reformat operator (for LISP). */ #ifdef LISP case '=': forbid(!value(LISP)); /* fall into ... */ #endif /* * > Right shift operator. * < Left shift operator. */ case '<': case '>': moveop = vshftop; deleteop = beep; break; /* * r Replace character under cursor with single following * character. */ case 'r': vrep(cnt); return; default: goto nocount; } /* * Had an operator, so accept another count. * Multiply counts together. */ if (isdigit(peekkey()) && peekkey() != '0') { cnt *= vgetcnt(); Xcnt = cnt; forbid (cnt <= 0); } /* * Get next character, mapping it and saving as * part of command for repeat. */ c = map(getesc()); if (c == 0) return; if (!subop) *lastcp++ = c; nocount: opf = moveop; switch (c) { /* * b Back up a word. * B Back up a word, liberal definition. */ case 'b': case 'B': dir = -1; /* fall into ... */ /* * w Forward a word. * W Forward a word, liberal definition. */ case 'W': case 'w': wdkind = c & ' '; if (edge()) { forbid (opf == vmove); wcursor = dir == -1 ? linebuf : strend(linebuf); } else while (cnt > 0 && !edge()) word(opf, cnt), cnt--; vmoving = 0; break; /* * E to end of following blank/nonblank word */ case 'E': wdkind = 0; goto ein; /* * e To end of following word. */ case 'e': wdkind = 1; ein: if (edge()) { forbid(opf == vmove); wcursor = dir == -1 ? linebuf : strend(linebuf); } else { while (cnt > 1 && !edge()) { word(opf, cnt); cnt--; } eend(opf, cnt); } vmoving = 0; break; /* * ( Back an s-expression. */ case '(': dir = -1; /* fall into... */ /* * ) Forward an s-expression. */ case ')': forbid(lfind(0, cnt, opf, (line *) 0) < 0); if (wdot) markpr(wdot); break; /* * { Back an s-expression, but don't stop on atoms. * In text mode, a paragraph. For C, a balanced set * of {}'s. */ case '{': dir = -1; /* fall into... */ /* * } Forward an s-expression, but don't stop on atoms. * In text mode, back paragraph. For C, back a balanced * set of {}'s. */ case '}': forbid(lfind(1, cnt, opf, (line *) 0) < 0); if (wdot) markpr(wdot); break; /* * % To matching () or {}. If not at ( or { scan for * first such after cursor on this line. */ case '%': vsave(); i = lmatchp((line *) 0); getDOT(); forbid(!i); if (opf != vmove) if (dir > 0) wcursor++; else cursor++; else if (wdot) markpr(wdot); break; /* * [ Back to beginning of defun, i.e. an ( in column 1. * For text, back to a section macro. * For C, back to a { in column 1 (~~ beg of function.) */ case '[': dir = -1; /* fall into ... */ /* * ] Forward to next defun, i.e. a ( in column 1. * For text, forward section. * For C, forward to a } in column 1 (if delete or such) * or if a move to a { in column 1. */ case ']': if (!vglobp) forbid(getkey() != c); if (Xhadcnt) vsetsiz(Xcnt); vsave(); i = lbrack(c, opf); getDOT(); forbid(!i); if (wdot) markpr(wdot); if (ex_ospeed > B300) hold |= HOLDWIG; break; /* * , Invert last find with f F t or T, like inverse * of ;. */ case ',': forbid (lastFKND == 0); c = isupper((int)lastFKND) ? tolower((int)lastFKND) : toupper((int)lastFKND); ungetkey(lastFCHR); if (vglobp == 0) vglobp = ""; subop++; goto nocount; /* * 0 To beginning of real line. */ case '0': wcursor = linebuf; vmoving = 0; break; /* * ; Repeat last find with f F t or T. */ case ';': forbid (lastFKND == 0); c = lastFKND; ungetkey(lastFCHR); subop++; goto nocount; /* * F Find single character before cursor in current line. * T Like F, but stops before character. */ case 'F': /* inverted find */ case 'T': dir = -1; /* fall into ... */ /* * f Find single character following cursor in current line. * t Like f, but stope before character. */ case 'f': /* find */ case 't': i = getesc(); if (i == 0) return; if (!subop) *lastcp++ = i; if (vglobp == 0) lastFKND = c, lastFCHR = i; for (; cnt > 0; cnt--) forbid (find(i) == 0); switch (c) { case 'T': wcursor++; break; case 't': wcursor--; case 'f': fixup: if (moveop != vmove) wcursor++; break; } vmoving = 0; break; /* * | Find specified print column in current line. */ case '|': if (Pline == numbline) cnt += 8; vmovcol = cnt; vmoving = 1; wcursor = vfindcol(cnt); break; /* * ^ To beginning of non-white space on line. */ case '^': wcursor = vskipwh(linebuf); vmoving = 0; break; /* * $ To end of line. */ case '$': if (cnt > 1) { if (opf == vmove) { wcursor = 0; vmoving = 1; vmovcol = 20000; cnt--; } else wcursor = linebuf; wdot = dot + cnt; break; } if (linebuf[0]) { wcursor = strend(linebuf) - 1; goto fixup; } wcursor = linebuf; vmoving = 0; break; /* * h Back a character. * ^H Back a character. */ case 'h': case CTRL('h'): dir = -1; /* fall into ... */ /* * space Forward a character. */ case ' ': forbid (margin() || (opf == vmove && edge())); while (cnt > 0 && !margin()) wcursor += dir, cnt--; if ((margin() && opf == vmove) || wcursor < linebuf) wcursor -= dir; vmoving = 0; break; /* * D Delete to end of line, short for d$. */ case 'D': cnt = INF; goto deleteit; /* * X Delete character before cursor. */ case 'X': dir = -1; /* fall into ... */ deleteit: /* * x Delete character at cursor, leaving cursor where it is. */ case 'x': if (margin()) goto errlab; while (cnt > 0 && !margin()) wcursor += dir, cnt--; opf = deleteop; vmoving = 0; break; default: /* * Stuttered operators are equivalent to the operator on * a line, thus turn dd into d_. */ if (opf == vmove || c != workcmd[0]) { errlab: beep(); return; } /* fall into ... */ /* * _ Target for a line or group of lines. * Stuttering is more convenient; this is mostly * for aesthetics. */ case '_': wdot = dot + cnt - 1; vmoving = 0; wcursor = 0; break; /* * H To first, home line on screen. * Count is for count'th line rather than first. */ case 'H': wdot = (dot - vcline) + cnt - 1; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * - Backwards lines, to first non-white character. */ case '-': wdot = dot - cnt; vmoving = 0; wcursor = 0; break; /* * ^P To previous line same column. Ridiculous on the * console of the VAX since it puts console in LSI mode. */ case CTRL('p'): wdot = dot - cnt; if (vmoving == 0) vmoving = 1, vmovcol = column(cursor); wcursor = 0; break; /* * L To last line on screen, or count'th line from the * bottom. */ case 'L': wdot = dot + vcnt - vcline - cnt; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * M To the middle of the screen. */ case 'M': wdot = dot + ((vcnt + 1) / 2) - vcline - 1; if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * + Forward line, to first non-white. * * CR Convenient synonym for +. */ case '+': case CR: wdot = dot + cnt; vmoving = 0; wcursor = 0; break; /* * ^N To next line, same column if possible. * * LF Linefeed is a convenient synonym for ^N. */ case CTRL('n'): case NL: wdot = dot + cnt; if (vmoving == 0) vmoving = 1, vmovcol = column(cursor); wcursor = 0; break; /* * n Search to next match of current pattern. */ case 'n': vglobp = vscandir; c = *vglobp++; goto nocount; /* * N Like n but in reverse direction. */ case 'N': vglobp = vscandir[0] == '/' ? "?" : "/"; c = *vglobp++; goto nocount; /* * ' Return to line specified by following mark, * first white position on line. * * ` Return to marked line at remembered column. */ case '\'': case '`': d = c; c = getesc(); if (c == 0) return; c = markreg(c); forbid (c == 0); wdot = getmark(c); forbid (wdot == NOLINE); if (Xhadcnt) vsetsiz(Xcnt); if (opf == vmove) markit(wdot); vmoving = 0; wcursor = d == '`' ? ncols[c - 'a'] : 0; if (wcursor) { vsave(); ex_getline(*wdot); if (wcursor > strend(linebuf)) wcursor = 0; getDOT(); } if (ex_ospeed > B300) hold |= HOLDWIG; break; /* * G Goto count'th line, or last line if no count * given. */ case 'G': if (!Xhadcnt) cnt = lineDOL(); wdot = zero + cnt; forbid (wdot < one || wdot > dol); if (opf == vmove) markit(wdot); vmoving = 0; wcursor = 0; break; /* * / Scan forward for following re. * ? Scan backward for following re. */ case '/': case '?': if (Xhadcnt) vsetsiz(Xcnt); vsave(); ocurs = cursor; wcursor = 0; if (readecho(c)) return; if (!vglobp) vscandir[0] = genbuf[0]; oglobp = globp; CP(vutmp, genbuf); globp = vutmp; d = peekc; ungetchar(0); fixech(); CATCH #ifdef V6 /* * Lose typeahead (ick). */ vcook(); #endif addr = address(); #ifdef V6 vraw(); #endif ONERR #ifdef V6 vraw(); #endif globp = oglobp; ungetchar(d); splitw = 0; vclean(); vjumpto(dot, ocurs, 0); return; ENDCATCH if (globp == 0) globp = ""; else if (peekc) --globp; ungetchar(d); c = 0; if (*globp == 'z') globp++, c = '\n'; if (any(*globp, "^+-.")) c = *globp++; i = 0; while (isdigit((int)*globp)) i = i * 10 + *globp++ - '0'; if (*globp) c = *globp++; globp = oglobp; splitw = 0; vmoving = 0; if (i != 0) vsetsiz(i); if (opf == vmove) { if (state == ONEOPEN || state == HARDOPEN) outline = destline = WBOT; markit(addr); if (loc1 > linebuf && *loc1 == 0) loc1--; if (c) vjumpto(addr, loc1, c); else { vmoving = 0; if (loc1) { vmoving++; vmovcol = column(loc1); } getDOT(); if (state == CRTOPEN && addr != dot) vup1(); vupdown(addr - dot, NOSTR); } return; } lastcp[-1] = 'n'; getDOT(); wdot = addr; break; } /* * Apply. */ if (vreg && wdot == 0) wdot = dot; (*opf)(c); wdot = NOLINE; }
/* ** Add a member to a group, creating the group if ** it does not already exist. */ int group_members_add(const char *argv[], gu_boolean do_add) { const char *group = argv[0]; int x; char *ptr; int count = 0; void *qobj = NULL; if( ! am_administrator() ) return EXIT_DENIED; if(do_add) { if(! group || ! argv[1]) { fputs(_("You must specify a new or existing group and one or more printers\n" "to add to it.\n"), errors); return EXIT_SYNTAX; } } else { if(!group) { fputs(_("You must specify a new or existing group and zero or more printers\n" "to be its members.\n"), errors); return EXIT_SYNTAX; } } if(strlen(group) > MAX_DESTNAME) { fputs(_("Group name is too long.\n"), errors); return EXIT_SYNTAX; } if(strpbrk(group, DEST_DISALLOWED)) { fputs(_("Group name contains a disallowed character.\n"), errors); return EXIT_SYNTAX; } if(strchr(DEST_DISALLOWED_LEADING, (int)group[0])) { fputs(_("Group name begins with a disallowed character.\n"), errors); return EXIT_SYNTAX; } /* ** Make sure the proposed new members really exist. ** We do this by trying to open their configuration files ** with prnopen(). */ for(x=1; argv[x]; x++) { if(prnopen(argv[x], FALSE)) { fprintf(errors, _("The printer \"%s\" does not exist.\n"), argv[x]); return EXIT_BADDEST; } else { confclose(); } } /* ** If the group to which we are adding a printer ** does not exist, create it. */ if(grpopen(group, TRUE, TRUE)) return EXIT_INTERNAL; /* Copy up to but not including the 1st "Printer:" line. */ while(confread()) { if(lmatch(confline, "DefFiltOpts:")) /* discard */ continue; if(lmatch(confline, "Printer:")) /* stop */ break; conf_printf("%s\n", confline); /* copy */ } gu_Try { qobj = queueinfo_new(QUEUEINFO_GROUP, group); queueinfo_set_warnings_file(qobj, errors); queueinfo_set_debug_level(qobj, debug_level); /* Copy all the remaining lines. */ do { if((ptr = lmatchp(confline, "Printer:"))) { if(!do_add) /* If we are adding, just delete it. */ continue; for(x=1; argv[x]; x++) /* Is this the same as one we are adding? */ { if(strcmp(ptr, argv[x]) == 0) gu_Throw(_("%d Printer \"%s\" is already a member of \"%s\".\n"), EXIT_ALREADY, argv[x], group); queueinfo_add_printer(qobj, ptr); count++; } } /* Delete old "DefFiltOpts:" lines as we go. */ else if(lmatch(confline, "DefFiltOpts:")) continue; /* Other lines we keep. */ conf_printf("%s\n", confline); } while(confread()); /* Add a "Printer:" line for each new member. */ for(x=1; argv[x]; x++) { conf_printf("Printer: %s\n", argv[x]); queueinfo_add_printer(qobj, argv[x]); count++; } /* Emmit the new "DefFiltOpts:" line. */ { const char *cp = queueinfo_computedDefaultFilterOptions(qobj); if(cp) conf_printf("DefFiltOpts: %s\n", cp); } /* See if adding our printer will make the group too big. */ if(count > MAX_GROUPSIZE) gu_Throw(_("%d Group \"%s\" would have %d members, only %d are allowed.\n"), EXIT_OVERFLOW, group, count, MAX_GROUPSIZE); /* Commit the changes. */ confclose(); } gu_Final { if(qobj) queueinfo_free(qobj); } gu_Catch { confabort(); /* roll back the changes */ fprintf(errors, "%s: %s\n", myname, gu_exception); return exception_to_exitcode(gu_exception_code); } /* necessary because pprd keeps track of mounted media */ reread_group(group); return EXIT_OK; } /* end of group_add() */