]> git.ipfire.org Git - thirdparty/util-linux.git/blame - text-utils/ul.c
misc: consolidate version printing and close_stdout()
[thirdparty/util-linux.git] / text-utils / ul.c
CommitLineData
6dbe3af9
KZ
1/*
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
fd6b7a7f 34/*
eb63b9b8
KZ
35 * modified by Kars de Jong <jongk@cs.utwente.nl>
36 * to use terminfo instead of termcap.
b50945d4 37 * 1999-02-22 Arkadiusz Miƛkiewicz <misiek@pld.ORG.PL>
eb63b9b8
KZ
38 * added Native Language Support
39 * 1999-09-19 Bruno Haible <haible@clisp.cons.org>
40 * modified to work correctly in multi-byte locales
41 */
fd6b7a7f 42
6dbe3af9 43#include <stdio.h>
fd6b7a7f 44#include <unistd.h> /* for getopt(), isatty() */
c0f19ccf 45#include <string.h> /* for memset(), strcpy() */
2b6fc908 46#include <stdlib.h> /* for getenv() */
5c36a0eb 47#include <limits.h> /* for INT_MAX */
4727b169 48#include <signal.h> /* for signal() */
59f8c787 49#include <errno.h>
a3b76180 50#include <getopt.h>
fd6b7a7f 51
3947ca4c
KZ
52#if defined(HAVE_NCURSESW_TERM_H)
53# include <ncursesw/term.h>
2ac1bc84
KZ
54#elif defined(HAVE_NCURSES_TERM_H)
55# include <ncurses/term.h>
3947ca4c
KZ
56#elif defined(HAVE_TERM_H)
57# include <term.h>
2ac1bc84
KZ
58#endif
59
f0961db2
DB
60#include "nls.h"
61#include "xalloc.h"
eb63b9b8 62#include "widechar.h"
eb76ca98 63#include "c.h"
b87cbe84 64#include "closestream.h"
eb63b9b8 65
06b04b23 66#ifdef HAVE_WIDECHAR
565239b0
SK
67/* Output an ASCII character as a wide character */
68static int put1wc(int c)
eb63b9b8 69{
565239b0
SK
70 if (putwchar(c) == WEOF)
71 return EOF;
72 else
73 return c;
eb63b9b8 74}
cc319747 75#define putwp(s) tputs(s, STDOUT_FILENO, put1wc)
eb63b9b8
KZ
76#else
77#define putwp(s) putp(s)
78#endif
79
a4949aaa 80static int handle_escape(FILE * f);
565239b0
SK
81static void filter(FILE *f);
82static void flushln(void);
83static void overstrike(void);
84static void iattr(void);
85static void initbuf(void);
86static void fwd(void);
87static void reverse(void);
88static void initinfo(void);
89static void outc(wint_t c, int width);
b0b24b11 90static void xsetmode(int newmode);
66ee8158
KZ
91static void setcol(int newcol);
92static void needcol(int col);
4727b169 93static void sig_handler(int signo);
cdbe31fc 94static void print_out(char *line);
6dbe3af9
KZ
95
96#define IESC '\033'
97#define SO '\016'
98#define SI '\017'
99#define HFWD '9'
100#define HREV '8'
101#define FREV '7'
6dbe3af9
KZ
102
103#define NORMAL 000
104#define ALTSET 001 /* Reverse */
105#define SUPERSC 002 /* Dim */
106#define SUBSC 004 /* Dim | Ul */
107#define UNDERL 010 /* Ul */
108#define BOLD 020 /* Bold */
109
2ba641e5
SK
110static int must_use_uc, must_overstrike;
111static char *CURS_UP,
112 *CURS_RIGHT,
113 *CURS_LEFT,
114 *ENTER_STANDOUT,
115 *EXIT_STANDOUT,
116 *ENTER_UNDERLINE,
117 *EXIT_UNDERLINE,
118 *ENTER_DIM,
119 *ENTER_BOLD,
120 *ENTER_REVERSE,
121 *UNDER_CHAR,
122 *EXIT_ATTRIBUTES;
6dbe3af9 123
2ba641e5 124struct CHAR {
6dbe3af9 125 char c_mode;
eb63b9b8 126 wchar_t c_char;
66ee8158 127 int c_width;
565239b0 128};
6dbe3af9 129
2ba641e5
SK
130static struct CHAR *obuf;
131static int obuflen;
132static int col, maxcol;
133static int mode;
134static int halfpos;
135static int upln;
136static int iflag;
6dbe3af9 137
86be6a32 138static void __attribute__((__noreturn__)) usage(void)
a3b76180 139{
86be6a32 140 FILE *out = stdout;
a2343e03
KZ
141 fputs(USAGE_HEADER, out);
142 fprintf(out, _(" %s [options] [<file> ...]\n"), program_invocation_short_name);
a3b76180 143
451dbcfa
BS
144 fputs(USAGE_SEPARATOR, out);
145 fputs(_("Do underlining.\n"), out);
146
147 fputs(USAGE_OPTIONS, out);
a2343e03
KZ
148 fputs(_(" -t, -T, --terminal TERMINAL override the TERM environment variable\n"), out);
149 fputs(_(" -i, --indicated underlining is indicated via a separate line\n"), out);
150 fputs(USAGE_SEPARATOR, out);
f45f3ec3 151 printf(USAGE_HELP_OPTIONS(30));
a2343e03 152
f45f3ec3 153 printf(USAGE_MAN_TAIL("ul(1)"));
a3b76180 154
86be6a32 155 exit(EXIT_SUCCESS);
a3b76180
SK
156}
157
fd6b7a7f 158int main(int argc, char **argv)
6dbe3af9 159{
0200c801 160 int c, ret, tflag = 0;
6dbe3af9
KZ
161 char *termtype;
162 FILE *f;
6dbe3af9 163
a3b76180 164 static const struct option longopts[] = {
87918040
SK
165 { "terminal", required_argument, NULL, 't' },
166 { "indicated", no_argument, NULL, 'i' },
167 { "version", no_argument, NULL, 'V' },
168 { "help", no_argument, NULL, 'h' },
169 { NULL, 0, NULL, 0 }
a3b76180
SK
170 };
171
7eda085c
KZ
172 setlocale(LC_ALL, "");
173 bindtextdomain(PACKAGE, LOCALEDIR);
174 textdomain(PACKAGE);
2c308875 175 close_stdout_atexit();
7eda085c 176
4727b169
DB
177 signal(SIGINT, sig_handler);
178 signal(SIGTERM, sig_handler);
179
6dbe3af9 180 termtype = getenv("TERM");
565239b0 181
a3b76180 182 while ((c = getopt_long(argc, argv, "it:T:Vh", longopts, NULL)) != -1)
565239b0 183 switch (c) {
6dbe3af9
KZ
184
185 case 't':
565239b0
SK
186 case 'T':
187 /* for nroff compatibility */
188 termtype = optarg;
0200c801 189 tflag = 1;
6dbe3af9
KZ
190 break;
191 case 'i':
192 iflag = 1;
193 break;
2c308875 194
a3b76180 195 case 'V':
2c308875 196 print_version(EXIT_SUCCESS);
a3b76180 197 case 'h':
86be6a32 198 usage();
6dbe3af9 199 default:
677ec86c 200 errtryhelp(EXIT_FAILURE);
6dbe3af9 201 }
cc319747 202 setupterm(termtype, STDOUT_FILENO, &ret);
565239b0 203 switch (ret) {
6dbe3af9
KZ
204
205 case 1:
206 break;
207
208 default:
59f8c787 209 warnx(_("trouble reading terminfo"));
b1557fe9 210 /* fallthrough */
6dbe3af9
KZ
211
212 case 0:
0200c801
SK
213 if (tflag)
214 warnx(_("terminal `%s' is not known, defaulting to `dumb'"),
215 termtype);
565239b0 216 setupterm("dumb", STDOUT_FILENO, (int *)0);
6dbe3af9
KZ
217 break;
218 }
fd6b7a7f 219 initinfo();
565239b0
SK
220 if ((tigetflag("os") && ENTER_BOLD==NULL ) ||
221 (tigetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL))
222 must_overstrike = 1;
6dbe3af9
KZ
223 initbuf();
224 if (optind == argc)
225 filter(stdin);
565239b0
SK
226 else
227 for (; optind < argc; optind++) {
228 f = fopen(argv[optind],"r");
229 if (!f)
289dcc90 230 err(EXIT_FAILURE, _("cannot open %s"),
565239b0
SK
231 argv[optind]);
232 filter(f);
78b0fdd3 233 fclose(f);
565239b0 234 }
78b0fdd3 235 free(obuf);
59f8c787 236 return EXIT_SUCCESS;
6dbe3af9
KZ
237}
238
a4949aaa
SK
239static int handle_escape(FILE * f)
240{
241 wint_t c;
242
243 switch (c = getwc(f)) {
244 case HREV:
245 if (halfpos == 0) {
246 mode |= SUPERSC;
247 halfpos--;
248 } else if (halfpos > 0) {
249 mode &= ~SUBSC;
250 halfpos--;
251 } else {
252 halfpos = 0;
253 reverse();
254 }
255 return 0;
256 case HFWD:
257 if (halfpos == 0) {
258 mode |= SUBSC;
259 halfpos++;
260 } else if (halfpos < 0) {
261 mode &= ~SUPERSC;
262 halfpos++;
263 } else {
264 halfpos = 0;
265 fwd();
266 }
267 return 0;
268 case FREV:
269 reverse();
270 return 0;
271 default:
272 /* unknown escape */
273 ungetwc(c, f);
274 return 1;
275 }
276}
277
565239b0 278static void filter(FILE *f)
6dbe3af9 279{
eb63b9b8 280 wint_t c;
66ee8158 281 int i, w;
6dbe3af9 282
d07b2237
SK
283 while ((c = getwc(f)) != WEOF) {
284 switch (c) {
285 case '\b':
286 setcol(col - 1);
66ee8158 287 continue;
d07b2237
SK
288 case '\t':
289 setcol((col + 8) & ~07);
290 continue;
291 case '\r':
292 setcol(0);
293 continue;
294 case SO:
295 mode |= ALTSET;
296 continue;
297 case SI:
298 mode &= ~ALTSET;
299 continue;
300 case IESC:
301 if (handle_escape(f)) {
302 c = getwc(f);
303 errx(EXIT_FAILURE,
304 _("unknown escape sequence in input: %o, %o"), IESC, c);
305 }
306 continue;
307 case '_':
308 if (obuf[col].c_char || obuf[col].c_width < 0) {
309 while (col > 0 && obuf[col].c_width < 0)
310 col--;
311 w = obuf[col].c_width;
312 for (i = 0; i < w; i++)
313 obuf[col++].c_mode |= UNDERL | mode;
314 setcol(col);
315 continue;
316 }
317 obuf[col].c_char = '_';
318 obuf[col].c_width = 1;
b1557fe9 319 /* fallthrough */
d07b2237
SK
320 case ' ':
321 setcol(col + 1);
322 continue;
323 case '\n':
324 flushln();
325 continue;
326 case '\f':
327 flushln();
328 putwchar('\f');
329 continue;
330 default:
331 if (!iswprint(c))
332 /* non printable */
333 continue;
334 w = wcwidth(c);
335 needcol(col + w);
336 if (obuf[col].c_char == '\0') {
337 obuf[col].c_char = c;
338 for (i = 0; i < w; i++)
339 obuf[col + i].c_mode = mode;
340 obuf[col].c_width = w;
341 for (i = 1; i < w; i++)
342 obuf[col + i].c_width = -1;
343 } else if (obuf[col].c_char == '_') {
344 obuf[col].c_char = c;
345 for (i = 0; i < w; i++)
346 obuf[col + i].c_mode |= UNDERL | mode;
347 obuf[col].c_width = w;
348 for (i = 1; i < w; i++)
349 obuf[col + i].c_width = -1;
350 } else if ((wint_t) obuf[col].c_char == c) {
351 for (i = 0; i < w; i++)
352 obuf[col + i].c_mode |= BOLD | mode;
353 } else {
354 w = obuf[col].c_width;
355 for (i = 0; i < w; i++)
356 obuf[col + i].c_mode = mode;
357 }
358 setcol(col + w);
6dbe3af9 359 continue;
66ee8158 360 }
6dbe3af9
KZ
361 }
362 if (maxcol)
363 flushln();
364}
365
565239b0 366static void flushln(void)
6dbe3af9 367{
5c36a0eb
KZ
368 int lastmode;
369 int i;
6dbe3af9
KZ
370 int hadmodes = 0;
371
372 lastmode = NORMAL;
565239b0 373 for (i = 0; i < maxcol; i++) {
6dbe3af9
KZ
374 if (obuf[i].c_mode != lastmode) {
375 hadmodes++;
b0b24b11 376 xsetmode(obuf[i].c_mode);
6dbe3af9
KZ
377 lastmode = obuf[i].c_mode;
378 }
379 if (obuf[i].c_char == '\0') {
5c36a0eb 380 if (upln) {
cdbe31fc 381 print_out(CURS_RIGHT);
5c36a0eb 382 } else
66ee8158 383 outc(' ', 1);
6dbe3af9 384 } else
66ee8158
KZ
385 outc(obuf[i].c_char, obuf[i].c_width);
386 if (obuf[i].c_width > 1)
565239b0 387 i += obuf[i].c_width - 1;
6dbe3af9
KZ
388 }
389 if (lastmode != NORMAL) {
b0b24b11 390 xsetmode(0);
6dbe3af9
KZ
391 }
392 if (must_overstrike && hadmodes)
393 overstrike();
eb63b9b8 394 putwchar('\n');
6dbe3af9
KZ
395 if (iflag && hadmodes)
396 iattr();
565239b0 397 fflush(stdout);
6dbe3af9
KZ
398 if (upln)
399 upln--;
400 initbuf();
401}
402
403/*
404 * For terminals that can overstrike, overstrike underlines and bolds.
405 * We don't do anything with halfline ups and downs, or Greek.
406 */
565239b0 407static void overstrike(void)
6dbe3af9
KZ
408{
409 register int i;
f20b214e 410 register wchar_t *lbuf = xmalloc((maxcol + 1) * sizeof(wchar_t));
eb63b9b8 411 register wchar_t *cp = lbuf;
6dbe3af9
KZ
412 int hadbold=0;
413
414 /* Set up overstrike buffer */
565239b0 415 for (i = 0; i < maxcol; i++)
6dbe3af9
KZ
416 switch (obuf[i].c_mode) {
417 case NORMAL:
418 default:
419 *cp++ = ' ';
420 break;
421 case UNDERL:
422 *cp++ = '_';
423 break;
424 case BOLD:
425 *cp++ = obuf[i].c_char;
66ee8158
KZ
426 if (obuf[i].c_width > 1)
427 i += obuf[i].c_width - 1;
6dbe3af9
KZ
428 hadbold=1;
429 break;
430 }
eb63b9b8 431 putwchar('\r');
565239b0 432 for (*cp = ' '; *cp == ' '; cp--)
6dbe3af9 433 *cp = 0;
67519cdd 434 fputws(lbuf, stdout);
6dbe3af9 435 if (hadbold) {
eb63b9b8 436 putwchar('\r');
565239b0
SK
437 for (cp = lbuf; *cp; cp++)
438 putwchar(*cp == '_' ? ' ' : *cp);
eb63b9b8 439 putwchar('\r');
565239b0
SK
440 for (cp = lbuf; *cp; cp++)
441 putwchar(*cp == '_' ? ' ' : *cp);
6dbe3af9 442 }
f20b214e 443 free(lbuf);
6dbe3af9
KZ
444}
445
565239b0 446static void iattr(void)
6dbe3af9
KZ
447{
448 register int i;
f20b214e 449 register wchar_t *lbuf = xmalloc((maxcol + 1) * sizeof(wchar_t));
aa971f7d 450 register wchar_t *cp = lbuf;
6dbe3af9 451
565239b0 452 for (i = 0; i < maxcol; i++)
6dbe3af9
KZ
453 switch (obuf[i].c_mode) {
454 case NORMAL: *cp++ = ' '; break;
455 case ALTSET: *cp++ = 'g'; break;
456 case SUPERSC: *cp++ = '^'; break;
457 case SUBSC: *cp++ = 'v'; break;
458 case UNDERL: *cp++ = '_'; break;
459 case BOLD: *cp++ = '!'; break;
460 default: *cp++ = 'X'; break;
461 }
565239b0 462 for (*cp = ' '; *cp == ' '; cp--)
6dbe3af9 463 *cp = 0;
67519cdd 464 fputws(lbuf, stdout);
eb63b9b8 465 putwchar('\n');
f20b214e 466 free(lbuf);
6dbe3af9
KZ
467}
468
565239b0 469static void initbuf(void)
6dbe3af9 470{
565239b0
SK
471 if (obuf == NULL) {
472 /* First time. */
cc319747 473 obuflen = BUFSIZ;
99361a9c
SK
474 obuf = xcalloc(obuflen, sizeof(struct CHAR));
475 } else
476 /* assumes NORMAL == 0 */
477 memset(obuf, 0, sizeof(struct CHAR) * maxcol);
6dbe3af9 478
5c36a0eb 479 setcol(0);
6dbe3af9
KZ
480 maxcol = 0;
481 mode &= ALTSET;
482}
483
565239b0 484static void fwd(void)
6dbe3af9 485{
5c36a0eb 486 int oldcol, oldmax;
6dbe3af9
KZ
487
488 oldcol = col;
489 oldmax = maxcol;
490 flushln();
5c36a0eb 491 setcol(oldcol);
6dbe3af9
KZ
492 maxcol = oldmax;
493}
494
565239b0 495static void reverse(void)
6dbe3af9
KZ
496{
497 upln++;
498 fwd();
cdbe31fc
SK
499 print_out(CURS_UP);
500 print_out(CURS_UP);
6dbe3af9
KZ
501 upln++;
502}
503
565239b0 504static void initinfo(void)
6dbe3af9 505{
fd6b7a7f
KZ
506 CURS_UP = tigetstr("cuu1");
507 CURS_RIGHT = tigetstr("cuf1");
508 CURS_LEFT = tigetstr("cub1");
6dbe3af9 509 if (CURS_LEFT == NULL)
6dbe3af9
KZ
510 CURS_LEFT = "\b";
511
fd6b7a7f
KZ
512 ENTER_STANDOUT = tigetstr("smso");
513 EXIT_STANDOUT = tigetstr("rmso");
514 ENTER_UNDERLINE = tigetstr("smul");
515 EXIT_UNDERLINE = tigetstr("rmul");
516 ENTER_DIM = tigetstr("dim");
517 ENTER_BOLD = tigetstr("bold");
518 ENTER_REVERSE = tigetstr("rev");
519 EXIT_ATTRIBUTES = tigetstr("sgr0");
6dbe3af9
KZ
520
521 if (!ENTER_BOLD && ENTER_REVERSE)
522 ENTER_BOLD = ENTER_REVERSE;
523 if (!ENTER_BOLD && ENTER_STANDOUT)
524 ENTER_BOLD = ENTER_STANDOUT;
525 if (!ENTER_UNDERLINE && ENTER_STANDOUT) {
526 ENTER_UNDERLINE = ENTER_STANDOUT;
527 EXIT_UNDERLINE = EXIT_STANDOUT;
528 }
529 if (!ENTER_DIM && ENTER_STANDOUT)
530 ENTER_DIM = ENTER_STANDOUT;
531 if (!ENTER_REVERSE && ENTER_STANDOUT)
532 ENTER_REVERSE = ENTER_STANDOUT;
533 if (!EXIT_ATTRIBUTES && EXIT_STANDOUT)
534 EXIT_ATTRIBUTES = EXIT_STANDOUT;
59f8c787 535
6dbe3af9
KZ
536 /*
537 * Note that we use REVERSE for the alternate character set,
9e930041 538 * not the as/ae capabilities. This is because we are modeling
6dbe3af9
KZ
539 * the model 37 teletype (since that's what nroff outputs) and
540 * the typical as/ae is more of a graphics set, not the greek
541 * letters the 37 has.
542 */
543
fd6b7a7f 544 UNDER_CHAR = tigetstr("uc");
6dbe3af9
KZ
545 must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE);
546}
547
6dbe3af9
KZ
548static int curmode = 0;
549
565239b0 550static void outc(wint_t c, int width) {
66ee8158
KZ
551 int i;
552
eb63b9b8 553 putwchar(c);
6dbe3af9 554 if (must_use_uc && (curmode&UNDERL)) {
565239b0 555 for (i = 0; i < width; i++)
cdbe31fc 556 print_out(CURS_LEFT);
565239b0 557 for (i = 0; i < width; i++)
cdbe31fc 558 print_out(UNDER_CHAR);
6dbe3af9
KZ
559 }
560}
561
b0b24b11 562static void xsetmode(int newmode)
6dbe3af9
KZ
563{
564 if (!iflag) {
565 if (curmode != NORMAL && newmode != NORMAL)
b0b24b11 566 xsetmode(NORMAL);
6dbe3af9
KZ
567 switch (newmode) {
568 case NORMAL:
565239b0 569 switch (curmode) {
6dbe3af9
KZ
570 case NORMAL:
571 break;
572 case UNDERL:
cdbe31fc 573 print_out(EXIT_UNDERLINE);
6dbe3af9
KZ
574 break;
575 default:
576 /* This includes standout */
cdbe31fc 577 print_out(EXIT_ATTRIBUTES);
6dbe3af9
KZ
578 break;
579 }
580 break;
581 case ALTSET:
cdbe31fc 582 print_out(ENTER_REVERSE);
6dbe3af9
KZ
583 break;
584 case SUPERSC:
585 /*
586 * This only works on a few terminals.
587 * It should be fixed.
588 */
cdbe31fc
SK
589 print_out(ENTER_UNDERLINE);
590 print_out(ENTER_DIM);
6dbe3af9
KZ
591 break;
592 case SUBSC:
cdbe31fc 593 print_out(ENTER_DIM);
6dbe3af9
KZ
594 break;
595 case UNDERL:
cdbe31fc 596 print_out(ENTER_UNDERLINE);
6dbe3af9
KZ
597 break;
598 case BOLD:
cdbe31fc 599 print_out(ENTER_BOLD);
6dbe3af9
KZ
600 break;
601 default:
602 /*
603 * We should have some provision here for multiple modes
604 * on at once. This will have to come later.
605 */
cdbe31fc 606 print_out(ENTER_STANDOUT);
6dbe3af9
KZ
607 break;
608 }
609 }
610 curmode = newmode;
611}
5c36a0eb 612
565239b0 613static void setcol(int newcol) {
5c36a0eb
KZ
614 col = newcol;
615
616 if (col < 0)
617 col = 0;
66ee8158
KZ
618 else if (col > maxcol)
619 needcol(col);
620}
5c36a0eb 621
72851044
SK
622static void needcol(int acol) {
623 maxcol = acol;
66ee8158
KZ
624
625 /* If col >= obuflen, expand obuf until obuflen > col. */
72851044 626 while (acol >= obuflen) {
66ee8158 627 /* Paranoid check for obuflen == INT_MAX. */
59f8c787
KZ
628 if (obuflen == INT_MAX)
629 errx(EXIT_FAILURE, _("Input line too long."));
66ee8158
KZ
630
631 /* Similar paranoia: double only up to INT_MAX. */
565239b0
SK
632 if (obuflen < (INT_MAX / 2))
633 obuflen *= 2;
634 else
635 obuflen = INT_MAX;
66ee8158
KZ
636
637 /* Now we can try to expand obuf. */
f0961db2 638 obuf = xrealloc(obuf, sizeof(struct CHAR) * obuflen);
5c36a0eb
KZ
639 }
640}
4727b169 641
2afa872f 642static void sig_handler(int signo __attribute__ ((__unused__)))
4727b169 643{
50644ff4 644 _exit(EXIT_SUCCESS);
4727b169
DB
645}
646
cdbe31fc
SK
647static void print_out(char *line)
648{
649 if (line == NULL)
650 return;
651
652 putwp(line);
653}