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