diff --git a/usr.bin/nl/nl.1 b/usr.bin/nl/nl.1 index 846de61e69e4..be7fbe1697dc 100644 --- a/usr.bin/nl/nl.1 +++ b/usr.bin/nl/nl.1 @@ -34,7 +34,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd September 20, 2001 +.Dd July 13, 2004 .Dt NL 1 .Os .Sh NAME @@ -223,6 +223,17 @@ The default .Ar width is 6. .El +.Sh ENVIRONMENT +The +.Ev LANG, +.Ev LC_ALL, +.Ev LC_CTYPE +and +.Ev LC_COLLATE +environment variables affect the execution of +.Nm +as described in +.Xr environ 7 . .Sh DIAGNOSTICS .Ex -std .Sh SEE ALSO @@ -238,7 +249,3 @@ The .Nm utility first appeared in .At V.2 . -.Sh BUGS -The -.Nm -utility does not recognize multibyte characters. diff --git a/usr.bin/nl/nl.c b/usr.bin/nl/nl.c index e3a5342bfc17..662ce268aa94 100644 --- a/usr.bin/nl/nl.c +++ b/usr.bin/nl/nl.c @@ -53,6 +53,7 @@ __RCSID("$FreeBSD$"); #include #include #include +#include typedef enum { number_all, /* number all lines */ @@ -107,11 +108,13 @@ static size_t buffersize; */ static char *intbuffer; +/* delimiter characters that indicate the start of a logical page section */ +static char delim[2 * MB_LEN_MAX]; +static int delimlen; + /* * Configurable parameters. */ -/* delimiter characters that indicate the start of a logical page section */ -static char delim[2] = { '\\', ':' }; /* line numbering format */ static const char *format = FORMAT_RN; @@ -141,11 +144,13 @@ main(argc, argv) int argc; char *argv[]; { - int c; + int c, n; long val; unsigned long uval; char *ep; - size_t intbuffersize; + size_t intbuffersize, clen; + char delim1[MB_LEN_MAX] = { '\\' }, delim2[MB_LEN_MAX] = { ':' }; + size_t delim1len = 1, delim2len = 1; (void)setlocale(LC_ALL, ""); @@ -158,16 +163,24 @@ main(argc, argv) parse_numbering(optarg, BODY); break; case 'd': - if (optarg[0] != '\0') - delim[0] = optarg[0]; - if (optarg[1] != '\0') - delim[1] = optarg[1]; - /* at most two delimiter characters */ - if (optarg[2] != '\0') { - errx(EXIT_FAILURE, - "invalid delim argument -- %s", - optarg); - /* NOTREACHED */ + clen = mbrlen(optarg, MB_CUR_MAX, NULL); + if (clen == (size_t)-1 || clen == (size_t)-2) + errc(EXIT_FAILURE, EILSEQ, NULL); + if (clen != 0) { + memcpy(delim1, optarg, delim1len = clen); + clen = mbrlen(optarg + delim1len, + MB_CUR_MAX, NULL); + if (clen == (size_t)-1 || + clen == (size_t)-2) + errc(EXIT_FAILURE, EILSEQ, NULL); + if (clen != 0) { + memcpy(delim2, optarg + delim1len, + delim2len = clen); + if (optarg[delim1len + clen] != '\0') + errx(EXIT_FAILURE, + "invalid delim argument -- %s", + optarg); + } } break; case 'f': @@ -251,6 +264,11 @@ main(argc, argv) /* NOTREACHED */ } + /* Generate the delimiter sequence */ + memcpy(delim, delim1, delim1len); + memcpy(delim + delim1len, delim2, delim2len); + delimlen = delim1len + delim2len; + /* Determine the maximum input line length to operate on. */ if ((val = sysconf(_SC_LINE_MAX)) == -1) /* ignore errno */ val = LINE_MAX; @@ -290,10 +308,10 @@ filter() while (fgets(buffer, (int)buffersize, stdin) != NULL) { for (idx = FOOTER; idx <= NP_LAST; idx++) { /* Does it look like a delimiter? */ - if (buffer[2 * idx + 0] == delim[0] && - buffer[2 * idx + 1] == delim[1]) { + if (memcmp(buffer + delimlen * idx, delim, + delimlen) == 0) { /* Was this the whole line? */ - if (buffer[2 * idx + 2] == '\n') { + if (buffer[delimlen * (idx + 1)] == '\n') { section = idx; adjblank = 0; if (restart)