xref: /illumos-gate/usr/src/cmd/lp/cmd/lpadmin/options.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include "ctype.h"
33 #include "stdio.h"
34 #include "string.h"
35 #include "stdlib.h"
36 #include <libintl.h>
37 
38 #include "lp.h"
39 #include "printers.h"
40 
41 #define	WHO_AM_I	I_AM_LPADMIN
42 #include "oam.h"
43 
44 #include "lpadmin.h"
45 
46 #ifdef LP_USE_PAPI_ATTR
47 #if	defined(CAN_DO_MODULES)
48 #define	OPT_LIST "A:ac:d:D:e:f:F:H:hi:I:lm:Mn:o:p:Q:r:S:s:T:u:U:v:W:x:t:P:"
49 #else
50 #define	OPT_LIST "A:ac:d:D:e:f:F:hi:I:lm:Mn:o:p:Q:r:S:s:T:u:U:v:W:x:t:P:"
51 #endif
52 
53 #else
54 #if	defined(CAN_DO_MODULES)
55 #define	OPT_LIST	"A:ac:d:D:e:f:F:H:hi:I:lm:Mo:p:Q:r:S:s:T:u:U:v:W:x:t:P:"
56 #else
57 #define	OPT_LIST	"A:ac:d:D:e:f:F:hi:I:lm:Mo:p:Q:r:S:s:T:u:U:v:W:x:t:P:"
58 #endif
59 #endif
60 
61 #define	MALLOC(pointer) \
62 	if (!(pointer = strdup(optarg))) { \
63 		LP_ERRMSG (ERROR, E_LP_MALLOC); \
64 		done (1); \
65 	} else
66 
67 #define	REALLOC(pointer) \
68 	if (!(pointer = realloc(pointer, (unsigned) (strlen(pointer) + 1 + strlen(optarg) + 1)))) { \
69 		LP_ERRMSG (ERROR, E_LP_MALLOC); \
70 		done (1); \
71 	} else if (strcat(pointer, " ")) \
72 		(void)strcat (pointer, optarg); \
73 	else
74 
75 extern char		*optarg;
76 
77 extern int		optind,
78 			opterr,
79 			optopt;
80 
81 extern double		strtod();
82 
83 extern long		strtol();
84 
85 int			a	= 0,	/* alignment needed for mount */
86 			banner	= -1,	/* allow/don't-allow nobanner */
87 #if	defined(DIRECT_ACCESS)
88 			C	= 0,	/* direct a.o.t. normal access */
89 #endif
90 		filebreak	= 0,
91 		h	= 0,	/* hardwired terminal */
92 		j	= 0,	/* do -F just for current job */
93 		l	= 0,	/* login terminal */
94 		M	= 0,	/* do mount */
95 		t	= 0,	/* tray number*/
96 		o	= 0,	/* some -o options given */
97 		Q	= -1,	/* queue threshold for alert */
98 		W	= -1;	/* alert interval */
99 
100 char		*A	= 0,	/* alert type */
101 		*c	= 0,	/* class name */
102 		*cpi	= 0,	/* string value of -o cpi= */
103 		*d	= 0,	/* default destination */
104 		*D	= 0,	/* description */
105 		*e	= 0,	/* copy existing interface */
106 		*f	= 0,	/* forms list - allow/deny */
107 		*P	= 0,	/* paper list  */
108 		*F	= 0,	/* fault recovery */
109 		**H	= 0,	/* list of modules to push */
110 		*i	= 0,	/* interface pathname */
111 		**I	= 0,	/* content-type-list */
112 		*length	= 0,	/* string value of -o length= */
113 		*lpi	= 0,	/* string value of -o lpi= */
114 		*m	= 0,	/* model name */
115 		modifications[128], /* list of mods to make */
116 #ifdef LP_USE_PAPI_ATTR
117 		*n_opt	= NULL,	/* PPD file name */
118 #endif
119 		*p	= 0,	/* printer name */
120 		*r	= 0,	/* class to remove printer from */
121 		*s	= 0,	/* system printer is on */
122 		*stty_opt= 0,	/* string value of -o stty= */
123 		**o_options = 0,/* undefined lpadmin -o options */
124 		**S	= 0,	/* -set/print-wheel list */
125 		**T	= 0,	/* terminfo names */
126 		*u	= 0,	/* user allow/deny list */
127 		*U	= 0,	/* dialer_info */
128 		*v	= 0,	/* device pathname */
129 		*width	= 0,	/* string value of -o width= */
130 		*x	= 0;	/* destination to be deleted */
131 
132 SCALED		cpi_sdn = { 0, 0 },
133 		length_sdn = { 0, 0 },
134 		lpi_sdn = { 0, 0 },
135 		width_sdn = { 0, 0 };
136 
137 static char	*modp	= modifications;
138 
139 static void	oparse();
140 
141 static char *	empty_list[] = { 0 };
142 
143 /**
144  ** options() - PARSE COMMAND LINE ARGUMENTS INTO OPTIONS
145  **/
146 
147 void			options (argc, argv)
148 	int			argc;
149 	char			*argv[];
150 {
151 	int		optsw,
152 			ac,
153 			Aflag = 0;
154 
155 	char		*cp,
156 			*rest,
157 			**av;
158 	char stroptsw[3] = "-X";
159 
160 #if	defined(__STDC__)
161 	typedef char * const *	stupid;	/* dumb-ass ANSI C */
162 #else
163 	typedef char **		stupid;
164 #endif
165 
166 
167 	/*
168 	 * Add a fake value to the end of the "argv" list, to
169 	 * catch the case that a valued-option comes last.
170 	 */
171 	av = malloc((argc + 2) * sizeof(char *));
172 	for (ac = 0; ac < argc; ac++)
173 		av[ac] = argv[ac];
174 	av[ac++] = "--";
175 
176 	opterr = 0;
177 	while ((optsw = getopt(ac, (stupid)av, OPT_LIST)) != EOF) {
178 
179 		switch (optsw) {
180 
181 		/*
182 		 * These options MAY take a value. Check the value;
183 		 * if it begins with a '-', assume it's really the next
184 		 * option.
185 		 */
186 		case 'd':
187 		case 'p':	/* MR bl87-27863 */
188 		case 'I':
189 #if	defined(CAN_DO_MODULES)
190 		case 'H':
191 #endif
192 			if (*optarg == '-') {
193 				/*
194 				 * This will work if we were given
195 				 *
196 				 *	-x -foo
197 				 *
198 				 * but would fail if we were given
199 				 *
200 				 *	-x-foo
201 				 */
202 				optind--;
203 				switch (optsw) {
204 				case 'd':
205 #if	defined(CAN_DO_MODULES)
206 				case 'H':
207 #endif
208 					optarg = NAME_NONE;
209 					break;
210 				case 'p':
211 					optarg = NAME_ALL;
212 					break;
213 				case 'I':
214 					optarg = 0;
215 					break;
216 				}
217 			}
218 			break;
219 
220 		/*
221 		 * These options MUST have a value. Check the value;
222 		 * if it begins with a dash or is null, complain.
223 		 */
224 		case 'Q':
225 		case 'W':
226 		case 't':
227 			/*
228 			 * These options take numeric values, which might
229 			 * be negative. Negative values are handled later,
230 			 * but here we just screen them.
231 			 */
232 			(void)strtol(optarg, &rest, 10);
233 			if (!rest || !*rest)
234 				break;
235 			/*FALLTHROUGH*/
236 		case 'A':
237 		case 'c':
238 		case 'e':
239 		case 'f':
240 		case 'P':
241 		case 'F':
242 		case 'i':
243 		case 'm':
244 #ifdef LP_USE_PAPI_ATTR
245 		case 'n':
246 #endif
247 		case 'o':
248 /*		case 'p': */	/* MR bl87-27863 */
249 		case 'r':
250 		case 'S':
251 		case 's':
252 		case 'T':
253 		case 'u':
254 		case 'U':
255 		case 'v':
256 		case 'x':
257 			/*
258 			 * These options also must have non-null args.
259 			 */
260 			if (!*optarg) {
261 				stroptsw[1] = optsw;
262 				cp = stroptsw;
263 				LP_ERRMSG1 (ERROR, E_LP_NULLARG, cp);
264 				done (1);
265 			}
266 			if (*optarg == '-') {
267 				stroptsw[1] = optsw;
268 				cp = stroptsw;
269 				LP_ERRMSG1 (ERROR, E_LP_OPTARG, cp);
270 				done (1);
271 			}
272 			if (optsw == 'A')
273 				Aflag++;
274 			break;
275 		case 'D':
276 			/*
277 			 * These options can have a null arg.
278 			 */
279 			if (*optarg == '-') {
280 				stroptsw[1] = optsw;
281 				cp = stroptsw;
282 				LP_ERRMSG1 (ERROR, E_LP_OPTARG, cp);
283 				done (1);
284 			}
285 			break;
286 		}
287 
288 		switch (optsw) {
289 
290 		case 'a':	/* alignment pattern needed for mount */
291 			a = 1;
292 			break;
293 
294 		case 'A':	/* alert type */
295 			if (A)
296 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'A');
297 			MALLOC(A);
298 			Aflag++;
299 			if (!STREQU(A, NAME_QUIET) && !STREQU(A, NAME_LIST))
300 				*modp++ = 'A';
301 			break;
302 
303 		case 'c':	/* class to insert printer p */
304 			if (c)
305 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'c');
306 			MALLOC(c);
307 		break;
308 
309 #if	defined(DIRECT_ACCESS)
310 		case 'C':
311 			C = 1;
312 			break;
313 #endif
314 
315 		case 'd':	/* system default destination */
316 			if (d)
317 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'd');
318 			MALLOC(d);
319 			break;
320 
321 		case 'D':	/* description */
322 			if (D)
323 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'D');
324 			MALLOC(D);
325 			*modp++ = 'D';
326 			break;
327 
328 		case 'e':	/* existing printer interface */
329 			if (e)
330 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'e');
331 			MALLOC(e);
332 			*modp++ = 'e';
333 			break;
334 
335 		case 'f':	/* set up forms allow/deny */
336 			if (f)
337 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'f');
338 			MALLOC(f);
339 			break;
340 
341 		case 'P':	/* set up forms allow/deny */
342 			if (P)
343 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'P');
344 			MALLOC(P);
345 			break;
346 
347 		case 'F':	/* fault recovery */
348 			if (F)
349 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'F');
350 			MALLOC(F);
351 			*modp++ = 'F';
352 			break;
353 
354 #if	defined(CAN_DO_MODULES)
355 		case 'H':
356 			if (H)
357 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'H');
358 			if (!optarg || !*optarg || STREQU(NAME_NONE, optarg))
359 				H = empty_list;
360 			if (!(H = getlist(optarg, LP_WS, LP_SEP))) {
361 				LP_ERRMSG (ERROR, E_LP_MALLOC);
362 				done(1);
363 			}
364 			*modp++ = 'H';
365 			break;
366 #endif
367 
368 		case 'h':	/* hardwired terminal */
369 			h = 1;
370 			*modp++ = 'h';
371 			break;
372 
373 		case 'i':	/* interface pathname */
374 			if (i)
375 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'i');
376 			MALLOC(i);
377 			*modp++ = 'i';
378 			break;
379 
380 		case 'I':	/* content-type-list */
381 			if (I)
382 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'I');
383 			if (!optarg || !*optarg || STREQU(NAME_NONE, optarg))
384 				I = empty_list;
385 			else if (!(I = getlist(optarg, LP_WS, LP_SEP))) {
386 				LP_ERRMSG (ERROR, E_LP_MALLOC);
387 				done (1);
388 			}
389 			*modp++ = 'I';
390 			break;
391 
392 #if	defined(J_OPTION)
393 		case 'j':	/* fault recovery just for current job */
394 			j = 1;
395 (void) printf (gettext("Sorry, the -j option is currently broken\n"));
396 			break;
397 #endif
398 
399 		case 'l':	/* login terminal */
400 			l = 1;
401 			*modp++ = 'l';
402 			break;
403 
404 		case 'm':	/* model interface */
405 			if (m)
406 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'm');
407 			MALLOC(m);
408 			*modp++ = 'm';
409 			break;
410 
411 #ifdef LP_USE_PAPI_ATTR
412 		case 'n':	/* PPD file */
413 			if (n_opt)
414 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'n');
415 			MALLOC(n_opt);
416 			*modp++ = 'n';
417 			break;
418 #endif
419 
420 		case 'M':	/* a mount request */
421 			M = 1;
422 			break;
423 
424 		case 'o':	/* several different options */
425 			oparse (optarg);
426 			o = 1;
427 			break;
428 
429 		case 'p':	/* printer name */
430 			if (p)
431 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'p');
432 			MALLOC(p);
433 			break;
434 
435 		case 'Q':
436 			if (Q != -1)
437 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'Q');
438 			if (STREQU(NAME_ANY, optarg))
439 				Q = 1;
440 			else {
441 				Q = strtol(optarg, &rest, 10);
442 				if (Q < 0) {
443 					LP_ERRMSG1 (ERROR, E_LP_NEGARG, 'Q');
444 					done (1);
445 				}
446 				if (rest && *rest) {
447 					LP_ERRMSG1 (ERROR, E_LP_GARBNMB, 'Q');
448 					done (1);
449 				}
450 				if (Q == 0) {
451 					LP_ERRMSG1 (ERROR, E_ADM_ZEROARG, 'Q');
452 					done (1);
453 				}
454 			}
455 			*modp++ = 'Q';
456 			break;
457 
458 		case 'r':	/* class to remove p from */
459 			if (r)
460 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'r');
461 			MALLOC(r);
462 			break;
463 
464 		case 'S':	/* char_set/print-wheels */
465 			if (S)
466 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'S');
467 			if (!(S = getlist(optarg, LP_WS, LP_SEP))) {
468 				LP_ERRMSG (ERROR, E_LP_MALLOC);
469 				done (1);
470 			}
471 			*modp++ = 'S';
472 			break;
473 
474 		case 's':
475 			if (s)
476 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 's');
477 
478 			if ((cp = strchr(optarg, '!')))
479 				*cp = '\0';
480 
481 			if ((STREQU(optarg, NAME_NONE)) ||
482 				(STREQU(optarg, "localhost")))
483 
484 				s = Local_System;
485 			else if (STREQU(optarg, Local_System)) {
486 				if (cp) {
487 					LP_ERRMSG (ERROR, E_ADM_NAMEONLOCAL);
488 					done(1);
489 				} else
490 					s = Local_System;
491 			} else {
492 				if (cp)
493 				    *cp = '!';
494 
495 				MALLOC(s);
496 			}
497 
498 			/* 's' already used for stty 'R' for remote? */
499 			*modp++ = 'R';
500 			break;
501 
502 		case 't':	/* tray number*/
503 			if (t != 0) LP_ERRMSG1 (WARNING, E_LP_2MANY, 't');
504 			t = strtol(optarg, &rest, 10);
505 			if (t <= 0) {
506 				LP_ERRMSG1 (ERROR, E_LP_NEGARG, 't');
507 				done (1);
508 			}
509 			if (rest && *rest) {
510 				LP_ERRMSG1 (ERROR, E_LP_GARBNMB, 't');
511 				done (1);
512 			}
513 			break;
514 
515 		case 'T':	/* terminfo names for p */
516 			if (T)
517 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'T');
518 			if (!(T = getlist(optarg, LP_WS, LP_SEP))) {
519 				LP_ERRMSG (ERROR, E_LP_MALLOC);
520 				done (1);
521 			}
522 			*modp++ = 'T';
523 			break;
524 
525 		case 'u':	/* user allow/deny list */
526 			if (u)
527 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'u');
528 			MALLOC(u);
529 			break;
530 
531 		case 'U':	/* dialer_info */
532 			if (U)
533 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'U');
534 			MALLOC(U);
535 			*modp++ = 'U';
536 			break;
537 
538 		case 'v':	/* device pathname */
539 			if (v)
540 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'v');
541 			MALLOC(v);
542 			*modp++ = 'v';
543 			break;
544 
545 		case 'W':	/* alert interval */
546 			if (W != -1)
547 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'W');
548 			if (STREQU(NAME_ONCE, optarg))
549 				W = 0;
550 			else {
551 				W = strtol(optarg, &rest, 10);
552 				if (W < 0) {
553 					LP_ERRMSG1 (ERROR, E_LP_NEGARG, 'W');
554 					done (1);
555 				}
556 				if (rest && *rest) {
557 					LP_ERRMSG1 (ERROR, E_LP_GARBNMB, 'W');
558 					done (1);
559 				}
560 			}
561 			*modp++ = 'W';
562 			break;
563 
564 		case 'x':	/* destination to be deleted */
565 			if (x)
566 				LP_ERRMSG1 (WARNING, E_LP_2MANY, 'x');
567 			MALLOC(x);
568 			break;
569 
570 		default:
571 			if (optopt == '?') {
572 				usage ();
573 				done (0);
574 
575 			} else {
576 				stroptsw[1] = optsw;
577 				cp = stroptsw;
578 
579 				if (strchr(OPT_LIST, optopt))
580 					LP_ERRMSG1 (ERROR, E_LP_OPTARG, cp);
581 				else
582 					LP_ERRMSG1 (ERROR, E_LP_OPTION, cp);
583 				done (1);
584 			}
585 		}
586 	}
587 
588 	if (optind < argc)
589 		LP_ERRMSG1 (WARNING, E_LP_EXTRA, argv[optind]);
590 
591 	if ((v) && (!Aflag)) {
592 		if (!(A = strdup("write"))) {
593 			LP_ERRMSG (ERROR, E_LP_MALLOC);
594 			done (1);
595 		}
596 		*modp++ = 'A';
597 	}
598 
599 	return;
600 }
601 
602 /**
603  ** oparse() - PARSE -o OPTION
604  **/
605 
606 static void		oparse (optarg)
607 	char			*optarg;
608 {
609 	register char		**list	= dashos(optarg);
610 
611 
612 	if (!list)
613 		return;
614 
615 	for ( ; (optarg = *list); list++)
616 
617 		if (STREQU(optarg, "banner")) {
618 			if (banner != -1)
619 				LP_ERRMSG1 (
620 					WARNING,
621 					E_ADM_2MANY,
622 					"banner/nobanner"
623 				);
624 			banner = BAN_ALWAYS;
625 			*modp++ = 'b';
626 
627 		} else if (STREQU(optarg, "nobanner")) {
628 			if (banner != -1)
629 				LP_ERRMSG1 (
630 					WARNING,
631 					E_ADM_2MANY,
632 					"banner/nobanner"
633 				);
634 			banner = BAN_OPTIONAL;
635 			*modp++ = 'b';
636 
637 		/* handle banner=(always|optional|never) */
638 		} else if (STRNEQU(optarg, "banner=", 7)) {
639 			char *ptr;
640 
641 			ptr = (optarg += 7);
642 			if (banner != -1)
643 				LP_ERRMSG1 ( WARNING, E_ADM_2MANY,
644 				"banner/nobanner/banner=(always|optional|never)"
645 				);
646 
647 			/* like "banner", always print a banner */
648 			if (strcasecmp(ptr, "always") == 0)
649 				banner = BAN_ALWAYS;
650 			/* like "nobanner", print a banner unless requested */
651 			if (strcasecmp(ptr, "optional") == 0)
652 				banner = BAN_OPTIONAL;
653 			/* never print a banner */
654 			if (strcasecmp(ptr, "never") == 0)
655 				banner = BAN_NEVER;
656 			*modp++ = 'b';
657 
658 		} else if (STRNEQU(optarg, "length=", 7)) {
659 			if (length)
660 				LP_ERRMSG1 (
661 					WARNING,
662 					E_ADM_2MANY,
663 					"length="
664 				);
665 			length = (optarg += 7);
666 
667 			if (!*optarg) {
668 				length_sdn.val = 0;
669 				length_sdn.sc = 0;
670 
671 			} else {
672 				length_sdn = _getsdn(optarg, &optarg, 0);
673 				if (errno == EINVAL) {
674 					LP_ERRMSG (ERROR, E_LP_BADSCALE);
675 					done (1);
676 				}
677 			}
678 			*modp++ = 'L';
679 
680 		} else if (STRNEQU(optarg, "width=", 6)) {
681 			if (width)
682 				LP_ERRMSG1 (
683 					WARNING,
684 					E_ADM_2MANY,
685 					"width="
686 				);
687 			width = (optarg += 6);
688 
689 			if (!*optarg) {
690 				width_sdn.val = 0;
691 				width_sdn.sc = 0;
692 
693 			} else {
694 				width_sdn = _getsdn(optarg, &optarg, 0);
695 				if (errno == EINVAL) {
696 					LP_ERRMSG (ERROR, E_LP_BADSCALE);
697 					done (1);
698 				}
699 			}
700 			*modp++ = 'w';
701 
702 		} else if (STRNEQU(optarg, "cpi=", 4)) {
703 			if (cpi)
704 				LP_ERRMSG1 (WARNING, E_ADM_2MANY, "cpi=");
705 
706 			cpi = (optarg += 4);
707 
708 			if (!*optarg) {
709 				cpi_sdn.val = 0;
710 				cpi_sdn.sc = 0;
711 
712 			} else {
713 				cpi_sdn = _getsdn(optarg, &optarg, 1);
714 				if (errno == EINVAL) {
715 					LP_ERRMSG (ERROR, E_LP_BADSCALE);
716 					done (1);
717 				}
718 			}
719 			*modp++ = 'c';
720 
721 		} else if (STRNEQU(optarg, "lpi=", 4)) {
722 			if (lpi)
723 				LP_ERRMSG1 (WARNING, E_ADM_2MANY, "lpi=");
724 			lpi = (optarg += 4);
725 
726 			if (!*optarg) {
727 				lpi_sdn.val = 0;
728 				lpi_sdn.sc = 0;
729 
730 			} else {
731 				lpi_sdn = _getsdn(optarg, &optarg, 0);
732 				if (errno == EINVAL) {
733 					LP_ERRMSG (ERROR, E_LP_BADSCALE);
734 					done (1);
735 				}
736 			}
737 			*modp++ = 'M';
738 
739 		} else if (STRNEQU(optarg, "stty=", 5)) {
740 
741 			optarg += 5;
742 			if (!*optarg)
743 				stty_opt = 0;
744 
745 			else {
746 				if (strchr(LP_QUOTES, *optarg)) {
747 					register int		len
748 							= strlen(optarg);
749 
750 					if (optarg[len - 1] == *optarg)
751 						optarg[len - 1] = 0;
752 					optarg++;
753 				}
754 				if (stty_opt)
755 					REALLOC (stty_opt);
756 				else
757 					MALLOC (stty_opt);
758 			}
759 			*modp++ = 's';
760 
761 		} else if (STREQU(optarg, "filebreak")) {
762 			filebreak = 1;
763 
764 		} else if (STREQU(optarg, "nofilebreak")) {
765 			filebreak = 0;
766 
767 		/* added support for using -o to pass any key=value pair */
768 		} else if (*optarg) {
769 
770 			if ((addlist(&o_options, optarg)) != 0) {
771 				fprintf(stderr, gettext("System Error %d\n"), errno);
772 			}
773 
774 			*modp++ = 'o';
775 			optarg++;
776 		}
777 
778 	return;
779 }
780