8672 proc_t changes broke genunix dmods and walker
[unleashed.git] / usr / src / cmd / fold / fold.c
blob83a15a00e50af73f633b2b9d13f89d1eaf3201f2
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
40 #pragma ident "%Z%%M% %I% %E% SMI"
42 #include <stdio.h>
43 #include <locale.h>
44 #include <wchar.h>
45 #include <euc.h>
46 #include <stdlib.h> /* XCU4 */
47 #include <limits.h>
48 #include <libintl.h>
49 #include <langinfo.h>
50 #include <utime.h>
51 #include <widec.h>
52 #include <wctype.h>
53 #include <errno.h>
57 * fold - fold long lines for finite output devices
60 static int fold = 80;
61 static int bflg = 0;
62 static int sflg = 0;
63 static int wflg = 0;
64 static int lastc = 0;
65 static int col = 0;
66 static int ncol = 0;
67 static int spcol = 0;
68 static wchar_t line[LINE_MAX];
69 static wchar_t *lastout = line;
70 static wchar_t *curc = line;
71 static wchar_t *lastsp = NULL;
72 #define MAXARG _POSIX_ARG_MAX
75 * Fix lint errors
77 void exit();
78 static void Usage();
79 static void putch();
80 static void newline_init();
81 static int chr_width();
82 extern int errno;
83 static int get_foldw();
86 int
87 main(int argc, char *argv[])
89 int c, narg;
90 int ch;
91 char *cmdline[MAXARG];
92 int new_argc;
93 int w;
94 extern int optind;
95 extern char *optarg;
97 (void) setlocale(LC_ALL, "");
98 #if !defined(TEXT_DOMAIN)
99 #define TEXT_DOMAIN "SYS_TEST"
100 #endif
101 (void) textdomain(TEXT_DOMAIN);
104 * Parse -width separately and build
105 * the new command line without -width.
106 * Next, use getopt() to parse this
107 * new command line.
110 for (narg = new_argc = 0; narg < argc; narg ++) {
111 if (argv[narg][0] == '-' &&
112 isdigit(argv[narg][1])) {
114 if (get_foldw((char *)&argv[narg][1], &w) < 0)
115 exit(1);
117 fold = w; /* Update with new width */
118 } else {
119 /* Build the new command line */
120 cmdline[new_argc++] = argv[narg];
123 * Check to make sure the option with
124 * required arg should have arg.
125 * This would check errors introduced in
126 * mixing non-getopt() options and that of
127 * getopt()'s due to stripping non-getopt
128 * options.
130 if ((argv[narg][0] == '-') && (argv[narg][1] == 'w')) {
131 if (((narg+1) < argc) &&
132 (argv[narg+1][0] == '-')) {
133 (void) fprintf(stderr, "fold");
134 (void) fprintf(stderr, gettext(
135 ": option requires an argument -- w\n"));
136 Usage();
137 exit(1);
143 while ((ch = getopt(new_argc, cmdline, "w:bs")) != EOF) {
144 switch (ch) {
145 case 'b':
146 bflg++;
147 break;
148 case 's':
149 sflg++;
150 break;
151 case 'w':
152 wflg++;
153 /* No required arg ? */
154 if ((optarg == (char *)NULL) ||
155 ((optarg != (char *)NULL) &&
156 (*optarg == '-'))) {
157 (void) fprintf(stderr, "fold");
158 (void) fprintf(stderr, gettext(
159 ": option requires an argument -- w\n"));
160 Usage();
161 exit(1);
163 /* Bad number ? */
164 if (get_foldw(optarg, &w) < 0)
165 exit(1);
167 fold = w;
168 break;
169 default:
171 * Errors should be filtered in previous
172 * pass.
174 Usage();
175 exit(1);
176 } /* switch */
177 } /* while */
179 do {
180 if (new_argc > optind) {
181 if (freopen(cmdline[optind], "r", stdin) == NULL) {
182 perror(cmdline[optind]);
183 Usage();
184 exit(1);
186 optind++;
189 for (;;) {
190 c = getwc(stdin);
191 if (c == EOF)
192 break;
193 (void) putch(c);
194 lastc = c;
196 if (col != 0) newline_init();
197 } while (new_argc > optind);
199 return (0);
202 static void
203 putch(int c)
205 wchar_t tline[LINE_MAX];
207 switch (c) {
208 case '\n':
209 ncol = 0;
210 break;
211 case '\t':
212 if (bflg)
213 ncol = col + chr_width(c);
214 else
215 ncol = (col + 8) &~ 7;
216 break;
217 case '\b':
218 if (bflg)
219 ncol = col + chr_width(c);
220 else
221 ncol = col ? col - 1 : 0;
222 break;
223 case '\r':
224 if (bflg)
225 ncol = col + chr_width(c);
226 else
227 ncol = 0;
228 break;
230 default:
231 if (bflg)
232 ncol = col + chr_width(c);
233 else
234 ncol = col + wcwidth(c);
239 * Special processing when -b is not specified
240 * for backspace, and carriage return.
241 * No newline is inseted before or after the
242 * special character: backspace, or cr.
243 * See man page for the handling of backspace
244 * and CR when there is no -b.
246 if ((ncol > fold) && (bflg ||
247 (!bflg && (lastc != '\b') && (c != '\b') &&
248 (lastc != '\n') && (c != '\n')))) {
250 * Need to check the last position for blank
252 if (sflg && lastsp) {
254 * Save the output buffer
255 * as NULL has to be insert into the last
256 * sp position.
258 (void) wscpy(tline, line);
259 *lastsp = (wchar_t)NULL;
260 (void) fputws(lastout, stdout);
261 (void) putwchar('\n');
263 * Restore the output buffer to stuff
264 * NULL into the last sp position
265 * for the new line.
267 (void) wscpy(line, tline);
268 lastout = lastsp;
269 lastsp = NULL; /* Reset the last sp */
270 ncol -= spcol; /* Reset column positions */
271 col -= spcol;
272 } else {
273 (void) newline_init();
274 (void) putwchar('\n');
275 lastout = curc;
278 /* Output buffer is full ? */
279 if ((curc + 1) >= (line + LINE_MAX)) {
280 /* Reach buffer limit */
281 if (col > 0) {
282 *curc = (wchar_t)NULL;
283 (void) fputws(lastout, stdout);
284 lastsp = NULL;
286 curc = lastout = line;
290 /* Store in output buffer */
291 *curc++ = (wchar_t)c;
293 switch (c) {
294 case '\n':
295 (void) newline_init();
296 curc = lastout = line;
297 break;
298 case '\t':
299 if (bflg)
300 col = col + chr_width(c);
301 else
302 col = (col + 8) &~ 7;
303 if (sflg && iswspace(c)) {
304 lastsp = curc;
305 spcol = ncol;
308 break;
309 case '\b':
310 if (bflg)
311 col = ncol;
312 else {
313 if (col)
314 col--;
316 break;
317 case '\r':
318 col = 0;
319 break;
320 default:
321 if (sflg && iswspace(c)) {
322 lastsp = curc;
323 spcol = ncol;
326 if (bflg)
327 col += chr_width(c);
328 else
329 col += wcwidth(c);
331 break;
334 static
335 void
336 Usage()
338 (void) fprintf(stderr, gettext(
339 "Usage: fold [-bs] [-w width | -width ] [file...]\n"));
342 static
343 void
344 newline_init()
346 *curc = (wchar_t)NULL;
347 (void) fputws(lastout, stdout);
348 ncol = col = spcol = 0;
349 lastsp = NULL;
352 static int
353 chr_width(c)
354 register int c;
356 char chr[MB_LEN_MAX+1];
357 register int n;
359 n = wctomb(chr, (wchar_t)c);
361 return (n > 0 ? n : 0);
364 static int
365 get_foldw(toptarg, width)
366 char *toptarg;
367 int *width;
369 char *p;
371 if (!toptarg)
372 goto badno;
374 *width = 0;
375 errno = 0;
376 *width = strtoul(toptarg, &p, 10);
377 if (*width == -1)
378 goto badno;
380 if (*p)
381 goto badno;
383 if (!*width)
384 goto badno;
386 return (0);
388 badno:
389 /* fold error message */
390 (void) fprintf(stderr, gettext(
391 "Bad number for fold\n"));
392 Usage();
393 return (-1);