home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / admin / nls_lib.sha / text0000.txt < prev   
Encoding:
Text File  |  1994-03-01  |  31.1 KB  |  1,260 lines

  1. I've been wanting to add National Language Support to Shadow for some
  2. time now but there is no freely redistributable NLS package that I am
  3. aware of.  I found some stuff in an old hacked up ELM directory, but
  4. it didn't look to be complete.  This isn't what I'd call "complete",
  5. but it's better than anything I've found.  And it includes a sample
  6. message catalog for the three commands that are included.
  7. --
  8. #!/bin/sh
  9. # shar:    Shell Archiver  (v1.29)
  10. #
  11. #    Run the following text with /bin/sh to create:
  12. #      LICENSE
  13. #      Makefile
  14. #      patchlevel.h
  15. #      gencat.c
  16. #      gencat.msg.En_US
  17. #      catgets.c
  18. #      l_catclose.c
  19. #      l_catgets.c
  20. #      l_catopen.c
  21. #      nl_types.h
  22. #
  23. sed 's/^X//' << 'SHAR_EOF' > LICENSE &&
  24. X(*
  25. XThis document is freely plagiarised from the 'Artistic Licence',
  26. Xdistributed as part of the Perl v4.0 kit by Larry Wall, which is
  27. Xavailable from most major archive sites.  I stole it from CrackLib.
  28. X
  29. X    @(#)LICENSE    3.1    20:07:28    02 Feb 1994
  30. X*)
  31. X
  32. XThis documents purpose is to state the conditions under which this
  33. XPackage (See definition below) viz: "NLS-LIB", the National Language
  34. XLibrary which is held in John Frederick Haugh, II, may be copied, such
  35. Xthat the copyright holder maintains some semblance of artistic control
  36. Xover the development of the package, while giving the users of the
  37. Xpackage the right to use and distribute the Package in a more-or-less
  38. Xcustomary fashion, plus the right to make reasonable modifications. 
  39. X
  40. XSo there.
  41. X
  42. X***************************************************************************
  43. X
  44. XDefinitions:
  45. X
  46. X
  47. XA "Package" refers to the collection of files distributed by the
  48. XCopyright Holder, and derivatives of that collection of files created
  49. Xthrough textual modification, or segments thereof. 
  50. X
  51. X"Standard Version" refers to such a Package if it has not been modified,
  52. Xor has been modified in accordance with the wishes of the Copyright
  53. XHolder.
  54. X
  55. X"Copyright Holder" is whoever is named in the copyright or copyrights
  56. Xfor the package.
  57. X
  58. X"You" is you, if you're thinking about copying or distributing this
  59. XPackage.
  60. X
  61. X"Reasonable copying fee" is whatever you can justify on the basis of
  62. Xmedia cost, duplication charges, time of people involved, and so on.
  63. X(You will not be required to justify it to the Copyright Holder, but
  64. Xonly to the computing community at large as a market that must bear the
  65. Xfee.)
  66. X
  67. X"Freely Available" means that no fee is charged for the item itself,
  68. Xthough there may be fees involved in handling the item.  It also means
  69. Xthat recipients of the item may redistribute it under the same
  70. Xconditions they received it.
  71. X
  72. X
  73. X1.  You may make and give away verbatim copies of the source form of the
  74. XStandard Version of this Package without restriction, provided that you
  75. Xduplicate all of the original copyright notices and associated
  76. Xdisclaimers.
  77. X
  78. X2.  You may apply bug fixes, portability fixes and other modifications
  79. Xderived from the Public Domain or from the Copyright Holder.  A Package
  80. Xmodified in such a way shall still be considered the Standard Version.
  81. X
  82. X3.  You may otherwise modify your copy of this Package in any way,
  83. Xprovided that you insert a prominent notice in each changed file stating
  84. Xhow and when AND WHY you changed that file, and provided that you do at
  85. Xleast ONE of the following:
  86. X
  87. Xa) place your modifications in the Public Domain or otherwise make them
  88. XFreely Available, such as by posting said modifications to Usenet or an
  89. Xequivalent medium, or placing the modifications on a major archive site
  90. Xsuch as uunet.uu.net, or by allowing the Copyright Holder to include
  91. Xyour modifications in the Standard Version of the Package.
  92. X
  93. Xb) use the modified Package only within your corporation or organization.
  94. X
  95. Xc) rename any non-standard executables so the names do not conflict with
  96. Xstandard executables, which must also be provided, and provide separate
  97. Xdocumentation for each non-standard executable that clearly documents
  98. Xhow it differs from the Standard Version.
  99. X
  100. Xd) make other distribution arrangements with the Copyright Holder.
  101. X
  102. X4.  You may distribute the programs of this Package in object code or
  103. Xexecutable form, provided that you do at least ONE of the following:
  104. X
  105. Xa) distribute a Standard Version of the executables and library files,
  106. Xtogether with instructions (in the manual page or equivalent) on where
  107. Xto get the Standard Version.
  108. X
  109. Xb) accompany the distribution with the machine-readable source of the
  110. XPackage with your modifications.
  111. X
  112. Xc) accompany any non-standard executables with their corresponding
  113. XStandard Version executables, giving the non-standard executables
  114. Xnon-standard names, and clearly documenting the differences in manual
  115. Xpages (or equivalent), together with instructions on where to get the
  116. XStandard Version.
  117. X
  118. Xd) make other distribution arrangements with the Copyright Holder.
  119. X
  120. X5.  You may charge a reasonable copying fee for any distribution of this
  121. XPackage.  You may charge any fee you choose for support of this Package. 
  122. XYOU MAY NOT CHARGE A FEE FOR THIS PACKAGE ITSELF.  However, you may
  123. Xdistribute this Package in aggregate with other (possibly commercial)
  124. Xprograms as part of a larger (possibly commercial) software distribution
  125. Xprovided that YOU DO NOT ADVERTISE this package as a product of your
  126. Xown. 
  127. X
  128. X6.  The name of the Copyright Holder may not be used to endorse or
  129. Xpromote products derived from this software without specific prior
  130. Xwritten permission.
  131. X
  132. X7.  THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
  133. XWARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  134. XMERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  135. X
  136. X                The End
  137. SHAR_EOF
  138. chmod 0644 LICENSE || echo "restore of LICENSE fails"
  139. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  140. X#
  141. X# Copyright 1994, John F. Haugh II
  142. X# An unpublished work.
  143. X# All rights reserved.
  144. X#
  145. X# Permission is granted to copy and create derivative works for any
  146. X# non-commercial purpose, provided this copyright notice is preserved
  147. X# in all copies of source code, or included in human readable form
  148. X# and conspicuously displayed on all copies of object code or
  149. X# distribution media.
  150. X#
  151. X# This software is provided on an AS-IS basis and the author makes
  152. X# no warrantee of any kind.  The "Artistic License" located in the
  153. X# file LICENSE contains complete licensing information.
  154. X#
  155. X#    %W%    %U%    %G%
  156. X
  157. XDEBUG = -g
  158. XOPTIM = -O
  159. XCFLAGS = $(DEBUG) $(OPTIM)
  160. XRANLIB = echo
  161. X
  162. XLANG = En_US
  163. X
  164. XFILES = LICENSE Makefile patchlevel.h \
  165. X    gencat.c gencat.msg.En_US catgets.c \
  166. X    l_catclose.c l_catgets.c l_catopen.c nl_types.h
  167. X
  168. Xall: gencat catgets dspcat libnls.a gencat.cat
  169. X
  170. Xgencat: gencat.o libnls.a
  171. X    cc $(DEBUG) -o gencat gencat.o libnls.a
  172. X
  173. Xcatgets: catgets.o libnls.a
  174. X    cc $(DEBUG) -o catgets catgets.o libnls.a
  175. X
  176. Xdspcat: dspcat.o libnls.a
  177. X    cc $(DEBUG) -o dspcat dspcat.o libnls.a
  178. X
  179. Xgencat.cat: gencat.msg.$(LANG)
  180. X    ./gencat gencat.cat gencat.msg.$(LANG)
  181. X
  182. Xlibnls.a(l_catclose.o): l_catclose.c nl_types.h
  183. Xlibnls.a(l_catopen.o): l_catopen.c nl_types.h
  184. Xlibnls.a(l_catgets.o): l_catgets.c nl_types.h
  185. X
  186. Xlibnls.a: \
  187. X    libnls.a(l_catclose.o) \
  188. X    libnls.a(l_catgets.o) \
  189. X    libnls.a(l_catopen.o)
  190. X    $(RANLIB) libnls.a
  191. X
  192. Xclean:
  193. X    rm -f *.o a.out core
  194. X
  195. Xclobber: clean
  196. X    rm -f catgets gencat libnls.a gencat.cat
  197. X
  198. Xshar: libnls.shar
  199. X
  200. Xlibnls.shar: $(FILES)
  201. X    shar $(SHARFLAGS) $(FILES) > libnls.shar
  202. SHAR_EOF
  203. chmod 0644 Makefile || echo "restore of Makefile fails"
  204. sed 's/^X//' << 'SHAR_EOF' > patchlevel.h &&
  205. X/*
  206. X * Copyright 1994, John F. Haugh II
  207. X * An unpublished work.
  208. X * All rights reserved.
  209. X *
  210. X * Permission is granted to copy and create derivative works for any
  211. X * non-commercial purpose, provided this copyright notice is preserved
  212. X * in all copies of source code, or included in human readable form
  213. X * and conspicuously displayed on all copies of object code or
  214. X * distribution media.
  215. X *
  216. X * This software is provided on an AS-IS basis and the author makes
  217. X * no warrantee of any kind.  The "Artistic License" located in the
  218. X * file LICENSE contains complete licensing information.
  219. X *
  220. X *    %W%    %U%    %G%
  221. X */
  222. X
  223. X#define    RELEASE        1
  224. X#define    PATCHLEVEL    0
  225. X#define    VERSION        "1.0.0"
  226. SHAR_EOF
  227. chmod 0644 patchlevel.h || echo "restore of patchlevel.h fails"
  228. sed 's/^X//' << 'SHAR_EOF' > gencat.c &&
  229. X/*
  230. X * Copyright 1994, John F. Haugh II
  231. X * All rights reserved.
  232. X *
  233. X * Permission is granted to copy and create derivative works for any
  234. X * non-commercial purpose, provided this copyright notice is preserved
  235. X * in all copies of source code, or included in human readable form
  236. X * and conspicuously displayed on all copies of object code or
  237. X * distribution media.
  238. X *
  239. X * This software is provided on an AS-IS basis and the author makes
  240. X * no warrantee of any kind.  The "Artistic License" located in the
  241. X * file LICENSE contains complete licensing information.
  242. X */
  243. X
  244. X#ifndef    lint
  245. Xstatic    char    sccsid[] = "%W%    %U%    %G%";
  246. X#endif
  247. X
  248. X#include <sys/types.h>
  249. X#include <stdlib.h>
  250. X#include <unistd.h>
  251. X#include <stdio.h>
  252. X#include <ctype.h>
  253. X#include <string.h>
  254. X
  255. X#include "nl_types.h"
  256. X
  257. Xnl_catd    catd;
  258. X#define    M(msg,def)    catgets (catd, 1, msg, def)
  259. X
  260. Xint    lineno;
  261. Xint    quotec;
  262. X
  263. Xchar    **messages[NL_SETMAX];
  264. X
  265. Xvoid
  266. Xinvalid (FILE * fp)
  267. X{
  268. X    int    c;
  269. X
  270. X    fprintf (stderr, M(3, "invalid input line %d\n"), lineno);
  271. X
  272. X    while ((c = getc (fp)) != '\n' && c != EOF)
  273. X        ;
  274. X}
  275. X
  276. Xint
  277. Xoctal (FILE * fp)
  278. X{
  279. X    int    c;
  280. X    int    c1, c2, c3;
  281. X
  282. X    c1 = getc (fp);
  283. X    c2 = getc (fp);
  284. X    c3 = getc (fp);
  285. X
  286. X    if (! (c1 >= '0' && c1 <= '7' &&
  287. X            c2 >= '0' && c2 <= '7' &&
  288. X            c3 >= '0' && c3 <= '7'))
  289. X        return EOF;
  290. X
  291. X    c = ((c1 - '0') << 6) | ((c2 - '0') << 3) | (c3 - '0');
  292. X    return c;
  293. X}
  294. X
  295. Xvoid
  296. Xcomment (FILE * fp)
  297. X{
  298. X    int    c;
  299. X
  300. X    while ((c = getc (fp)) != EOF && c != '\n')
  301. X        ;
  302. X}
  303. X
  304. Xmessage (nl_catd catd, FILE * fp, int set)
  305. X{
  306. X    int    c;
  307. X    int    i;
  308. X    enum    { line_begin,
  309. X        number,
  310. X        text_begin, text_mid, text_end,
  311. X        done
  312. X    } state = line_begin;
  313. X    int    quoted;
  314. X    char    msg_num[16];
  315. X    int    cur_msg;
  316. X    char    line[NL_TEXTMAX+2];
  317. X
  318. X    while (state != done) {
  319. X        if ((c = getc (fp)) == EOF) {
  320. X            if (state == text_mid) {
  321. X                state = done;
  322. X                continue;
  323. X            }
  324. X            invalid (fp);
  325. X            return;
  326. X        }
  327. X        if (state == line_begin) {
  328. X            if (c == EOF || ! isdigit (c)) {
  329. X                invalid (fp);
  330. X                return;
  331. X            }
  332. X            state = number;
  333. X            i = 1;
  334. X            msg_num[0] = c;
  335. X            continue;
  336. X        }
  337. X        if (state == number) {
  338. X            if (isdigit (c)) {
  339. X                if (i >= sizeof msg_num - 1) {
  340. X                    invalid (fp);
  341. X                    return;
  342. X                }
  343. X                msg_num[i++] = c;
  344. X                continue;
  345. X            }
  346. X            if (isspace (c)) {
  347. X                msg_num[i] = '\0';
  348. X                cur_msg = atoi (msg_num);
  349. X                if (cur_msg < 1 || cur_msg > NL_MSGMAX) {
  350. X                    invalid (fp);
  351. X                    return;
  352. X                }
  353. X                if (catd->nl_sets < set)
  354. X                    catd->nl_sets = set;
  355. X
  356. X                if (catd->nl_msgs[set-1] == 0) {
  357. X                    catd->nl_msgs[set-1] = (off_t *)
  358. X                        calloc (NL_MSGMAX,
  359. X                            sizeof (off_t));
  360. X                }
  361. X                if (catd->nl_nmsgs[set-1] < cur_msg)
  362. X                    catd->nl_nmsgs[set-1] = cur_msg;
  363. X
  364. X                /*
  365. X                 * Just a number?  Delete the message from
  366. X                 * the catalog.
  367. X                 */
  368. X
  369. X                if (c == '\n') {
  370. X                    if (messages[set-1][cur_msg-1]) {
  371. X                        free (messages[set-1][cur_msg-1]);
  372. X                        messages[set-1][cur_msg-1] = 0;
  373. X                    }
  374. X                    return;
  375. X                }
  376. X
  377. X                /*
  378. X                 * Message ID followed by whitespace starts
  379. X                 * a valid message.  Reset the buffer pointer
  380. X                 * to start collecting characters.
  381. X                 */
  382. X
  383. X                state = text_begin;
  384. X                i = 0;
  385. X                continue;
  386. X            }
  387. X
  388. X            /*
  389. X             * There must be whitespace after the number.
  390. X             */
  391. X
  392. X            invalid (fp);
  393. X            return;
  394. X        }
  395. X
  396. X        /*
  397. X         * At the beginning of a message a single "quote" character
  398. X         * is allowed.  If `c' is that character, discard it and
  399. X         * change state.  Otherwise, push the charcter back because
  400. X         * it is part of the actual message text.
  401. X         */
  402. X
  403. X        if (state == text_begin) {
  404. X
  405. X            /*
  406. X             * No characters at all?  This is an empty message.
  407. X             */
  408. X
  409. X            if (c == '\n') {
  410. X                ungetc (c, fp);
  411. X                state = text_end;
  412. X                continue;
  413. X            }
  414. X            if (c != quotec)
  415. X                ungetc (c, fp);
  416. X            else
  417. X                quoted = 1;
  418. X
  419. X            state = text_mid;
  420. X            continue;
  421. X        }
  422. X
  423. X        if (state == text_mid) {
  424. X            if (quoted && c == quotec) {
  425. X                if ((c = getc (fp)) == EOF || c == '\n') {
  426. X                    ungetc (c, fp);
  427. X                    state = text_end;
  428. X                    continue;
  429. X                } else {
  430. X                    ungetc (c, fp);
  431. X                    c = quotec;
  432. X                }
  433. X            }
  434. X            if (c == '\n') {
  435. X                ungetc (c, fp);
  436. X                state = text_end;
  437. X                continue;
  438. X            }
  439. X            if (c == '\\') {
  440. X                c = getc (fp);
  441. X                if (c == EOF) {
  442. X                    invalid (fp);
  443. X                    return;
  444. X                }
  445. X                if (c == '\n')
  446. X                    continue;
  447. X
  448. X                switch (c) {
  449. X                    case 'n': c = '\n'; break;
  450. X                    case 't': c = '\t'; break;
  451. X                    case 'v': c = '\v'; break;
  452. X                    case 'b': c = '\b'; break;
  453. X                    case 'r': c = '\r'; break;
  454. X                    case 'f': c = '\f'; break;
  455. X                    case '\\': c = '\\'; break;
  456. X                    default:
  457. X                        if (isdigit (c)) {
  458. X                            ungetc (c, fp);
  459. X                            c = octal (fp);
  460. X                        }
  461. X                        if (c == EOF) {
  462. X                            invalid (fp);
  463. X                            return;
  464. X                        }
  465. X                }
  466. X            }
  467. X            if (i < NL_TEXTMAX)
  468. X                line[i++] = c;
  469. X
  470. X            continue;
  471. X        }
  472. X
  473. X        if (state == text_end) {
  474. X            if (i < NL_TEXTMAX)
  475. X                line[i] = '\0';
  476. X
  477. X            state = done;
  478. X            continue;
  479. X        }
  480. X    }
  481. X    if (i >= NL_TEXTMAX) {
  482. X        invalid (fp);
  483. X        return;
  484. X    }
  485. X    line[i] = '\0';
  486. X
  487. X    if (messages[set-1] == (char **) 0) {
  488. X        messages[set-1] =
  489. X            (char **) malloc (sizeof (char *) * NL_MSGMAX);
  490. X        memset (messages[set-1], 0, sizeof (char *) * NL_MSGMAX);
  491. X    }
  492. X    if (messages[set-1][cur_msg-1])
  493. X        free (messages[set - 1][cur_msg - 1]);
  494. X
  495. X    messages[set - 1][cur_msg - 1] = strdup (line);
  496. X}
  497. X
  498. Xint
  499. Xload_catalog (nl_catd new_catd)
  500. X{
  501. X    int    i, j, k;
  502. X    int    c;
  503. X    nl_cat_header header;
  504. X    char    buf[NL_TEXTMAX+1];
  505. X
  506. X    if (fread (&header, sizeof header, 1, new_catd->nl_cat_fp) != 1)
  507. X        return -1;
  508. X
  509. X    if (header.nl_sets < 1 || header.nl_sets > NL_SETMAX)
  510. X        return -1;
  511. X
  512. X    new_catd->nl_sets = header.nl_sets;
  513. X    memcpy (new_catd->nl_nmsgs, header.nl_nmsgs, sizeof header.nl_nmsgs);
  514. X
  515. X    for (i = 0;i < NL_SETMAX;i++) {
  516. X        if (! (new_catd->nl_msgs[i] = (off_t *) calloc
  517. X                (NL_MSGMAX, sizeof (off_t)))) {
  518. X            fprintf (stderr, M(11, "no memory"));
  519. X            exit (1);
  520. X        }
  521. X        if (! (messages[i] = (char **) calloc
  522. X                (NL_MSGMAX, sizeof (char *)))) {
  523. X            fprintf (stderr, M(11, "no memory"));
  524. X            exit (1);
  525. X        }
  526. X        if (new_catd->nl_nmsgs[i] == 0)
  527. X            continue;
  528. X
  529. X        if (fread (new_catd->nl_msgs[i], sizeof (off_t),
  530. X            new_catd->nl_nmsgs[i], new_catd->nl_cat_fp) !=
  531. X                new_catd->nl_nmsgs[i])    
  532. X            return -1;
  533. X    }
  534. X    for (i = 0;i < new_catd->nl_sets;i++) {
  535. X        for (j = 0;j < new_catd->nl_nmsgs[i];j++) {
  536. X            for (k = 0;(c = getc (new_catd->nl_cat_fp)) &&
  537. X                    c != EOF && k < NL_TEXTMAX;)
  538. X                buf[k++] = c;
  539. X
  540. X            if (k >= NL_TEXTMAX)
  541. X                return -1;
  542. X
  543. X            buf[k] = '\0';
  544. X            if (! (messages[i][j] = strdup (buf))) {
  545. X                fprintf (stderr, M(11, "no memory"));
  546. X                exit (1);
  547. X            }
  548. X        }
  549. X    }
  550. X    return 0;
  551. X}
  552. X
  553. Xmain (int argc, char ** argv)
  554. X{
  555. X    int    i, j;
  556. X    int    c;
  557. X    int    created = 0;
  558. X    nl_catd    new_catd;
  559. X    nl_cat_header header;
  560. X    char    error[BUFSIZ];
  561. X    int    nerrors = 0;
  562. X    int    cur_set = NL_SETD;
  563. X    FILE    *input = 0;
  564. X    off_t    base;
  565. X
  566. X    catd = catopen ("gencat", 0);
  567. X
  568. X    if (argc < 3) {
  569. X        fprintf (stderr, M(1, "usage: gencat catfile msgfile ...\n"));
  570. X        exit (1);
  571. X    }
  572. X    if (! (new_catd = (nl_catd) malloc (sizeof *new_catd))) {
  573. X        perror (M(4, "gencat: can't create new catalog descriptor"));
  574. X        exit (1);
  575. X    }
  576. X    memset (new_catd, 0, sizeof *new_catd);
  577. X    memset (&header, 0, sizeof header);
  578. X
  579. X    /*
  580. X     * See if the file already exists.  If it doesn't we will be
  581. X     * creating it from scratch.
  582. X     */
  583. X
  584. X    if (access (argv[1], 0) == -1)
  585. X        created = 1;
  586. X
  587. X    /*
  588. X     * Try to open the message catalog.  If it exists, it will be
  589. X     * opened for read/update, if it doesn't we create a brand new
  590. X     * empty file.
  591. X     */
  592. X
  593. X    if (! (new_catd->nl_cat_fp = fopen (argv[1], created ? "w":"r+"))) {
  594. X        if (created)
  595. X            sprintf (error, M(6, "gencat: can't create catalog %s"),
  596. X                argv[1]);
  597. X        else
  598. X            sprintf (error, M(9, "gencat: can't open catalog %s"),
  599. X                argv[1]);
  600. X
  601. X        perror (error);
  602. X        exit (1);
  603. X    }
  604. X
  605. X    /*
  606. X     * Initialize the catalog descriptor to completely empty.  If
  607. X     * there was an existing catalog file, we're going to go load
  608. X     * it up in a second.
  609. X     */
  610. X
  611. X    new_catd->nl_sets = 0;
  612. X    for (i = 0;i < NL_SETMAX;i++) {
  613. X        new_catd->nl_nmsgs[i] = 0;
  614. X        new_catd->nl_msgs[i] = (off_t *) 0;
  615. X    }
  616. X    if (! created) {
  617. X        if (load_catalog (new_catd)) {
  618. X            fprintf (stderr, M(10, "invalid catalog file %s\n"),
  619. X                argv[1]);
  620. X            exit (1);
  621. X        }
  622. X    }
  623. X
  624. X    for (i = 2;i < argc;i++) {
  625. X        if (input && input != stdin) {
  626. X            fclose (input);
  627. X            input = 0;
  628. X        }
  629. X        if (strcmp (argv[i], "-") == 0) {
  630. X            input = stdin;
  631. X        } else if (! (input = fopen (argv[i], "r"))) {
  632. X            sprintf (error, M(7, "gencat: can't open %s"), argv[i]);
  633. X            perror (error);
  634. X            nerrors++;
  635. X            continue;
  636. X        }
  637. X        lineno = 0;
  638. X        if (argc > 3)
  639. X            printf ("%s:\n", argv[i]);
  640. X
  641. X        while ((c = getc (input)) != EOF) {
  642. X            lineno++;
  643. X            if (c != '$') {
  644. X                ungetc (c, input);
  645. X                message (new_catd, input,  cur_set);
  646. X                continue;
  647. X            }
  648. X            if ((c = getc (input)) == EOF)
  649. X                break;
  650. X
  651. X            if (c == ' ' || c == '\t' || c == '\n') {
  652. X                if (c != '\n')
  653. X                    comment (input);
  654. X
  655. X                continue;
  656. X            }
  657. X            if (c == 's') {
  658. X                int    new_set;
  659. X
  660. X                ungetc (c, input);
  661. X                if (fscanf (input, "set%*[     ]%d%*[^\n]",
  662. X                        &new_set) != 1) {
  663. X                    invalid (input);
  664. X                    nerrors++;
  665. X                    continue;
  666. X                }
  667. X                if (new_set < 1 || new_set > NL_SETMAX) {
  668. X                    invalid (input);
  669. X                    nerrors++;
  670. X                    continue;
  671. X                }
  672. X                getc (input);
  673. X                cur_set = new_set;
  674. X                continue;
  675. X            }
  676. X            if (c == 'd') {
  677. X                char    old_set;
  678. X
  679. X                ungetc (c, input);
  680. X                if (fscanf (input, "delset%*[     ]%d%*[^\n]",
  681. X                        &old_set) != 1) {
  682. X                    invalid (input);
  683. X                    nerrors++;
  684. X                    continue;
  685. X                }
  686. X                if (old_set < 1 || old_set >= NL_SETMAX) {
  687. X                    invalid (input);
  688. X                    nerrors++;
  689. X                    continue;
  690. X                }
  691. X                memset (new_catd->nl_msgs[old_set - 1], 0,
  692. X                    NL_MSGMAX * sizeof (off_t));
  693. X                new_catd->nl_nmsgs[old_set - 1] = 0;
  694. X                for (i = 0;i < NL_MSGMAX;i++) {
  695. X                    if (messages[old_set-1][i])
  696. X                        free (messages[old_set-1][i]);
  697. X
  698. X                    messages[old_set-1][i] = 0;
  699. X                }
  700. X                getc (input);
  701. X                continue;
  702. X            }
  703. X            if (c == 'q') {
  704. X                char    new_quotec;
  705. X
  706. X                ungetc (c, input);
  707. X                if (fscanf (input, "quote%*[     ]%c%*[^\n]\n",
  708. X                        &new_quotec) != 1) {
  709. X                    invalid (input);
  710. X                    nerrors++;
  711. X                    continue;
  712. X                }
  713. X                getc (input);
  714. X                quotec = new_quotec;
  715. X                continue;
  716. X            }
  717. X        }
  718. X    }
  719. X
  720. X    /*
  721. X     * There were some errors and they were already reported.  If we
  722. X     * created the message catalog go ahead and delete the file.
  723. X     */
  724. X
  725. X    if (nerrors) {
  726. X        if (created)
  727. X            (void) unlink (argv[1]);
  728. X
  729. X        exit (2);
  730. X    }
  731. X
  732. X    /*
  733. X     * Scan the in-core message catalog information to determine
  734. X     * how many sets were defined and how many messages are in each
  735. X     * set.  The information in the catalog descriptor right now
  736. X     * may be wrong as sets and messages may have been deleted.
  737. X     */
  738. X
  739. X    for (i = 0;i < NL_SETMAX;i++) {
  740. X
  741. X        /*
  742. X         * If there are no messages at all in the set, or there
  743. X         * never were, just say so and skip.
  744. X         */
  745. X
  746. X        if (new_catd->nl_msgs[i] == (off_t *) 0 ||
  747. X                new_catd->nl_nmsgs[i] == 0) {
  748. X            new_catd->nl_nmsgs[i] = 0;
  749. X            continue;
  750. X        }
  751. X
  752. X        /*
  753. X         * There must have been a message sometime in the past,
  754. X         * so set the count to zero and see what the highest
  755. X         * numbered one is now.
  756. X         */
  757. X
  758. X        new_catd->nl_nmsgs[i] = 0;
  759. X        for (j = 0;j < NL_MSGMAX;j++) {
  760. X            if (messages[i][j])
  761. X                new_catd->nl_nmsgs[i] = j + 1;
  762. X        }
  763. X
  764. X        /*
  765. X         * There weren't any?  The last one must have been
  766. X         * deleted, so we completely delete the set now by saying
  767. X         * it has no messages.
  768. X         */
  769. X
  770. X        if (new_catd->nl_nmsgs[i] == 0)
  771. X            continue;
  772. X
  773. X        /*
  774. X         * This set has at least one message, make it the highest
  775. X         * numbered set.
  776. X         */
  777. X
  778. X        new_catd->nl_sets = i + 1;
  779. X    }
  780. X    header.nl_sets = new_catd->nl_sets;
  781. X    memcpy (header.nl_nmsgs, new_catd->nl_nmsgs,
  782. X        new_catd->nl_sets * sizeof (off_t));
  783. X
  784. X    base = sizeof header;
  785. X    for (i = 0;i < new_catd->nl_sets;i++)
  786. X        base += new_catd->nl_nmsgs[i] * sizeof (off_t);
  787. X
  788. X    for (i = 0;i < new_catd->nl_sets;i++) {
  789. X        for (j = 0;j < new_catd->nl_nmsgs[i];j++) {
  790. X            if (messages[i][j] == (char *) 0) {
  791. X                new_catd->nl_msgs[i][j] = 0;
  792. X                continue;
  793. X            }
  794. X            new_catd->nl_msgs[i][j] = base;
  795. X            base += strlen (messages[i][j]) + 1;
  796. X        }
  797. X    }
  798. X    if (! created) {
  799. X        if (! (new_catd->nl_cat_fp = fopen (argv[1], "w"))) {
  800. X            sprintf (error, M(6, "gencat: can't create catalog %s"),
  801. X                argv[1]);
  802. X            perror (error);
  803. X            exit (1);
  804. X        }
  805. X    }
  806. X    if (fwrite (&header, sizeof header, 1, new_catd->nl_cat_fp) != 1) {
  807. X        sprintf (error, M(8, "gencat: can't write to %s"), argv[1]);
  808. X        perror (error);
  809. X        exit (1);
  810. X    }
  811. X    for (i = 0;i < new_catd->nl_sets;i++) {
  812. X        if (new_catd->nl_nmsgs[i] == 0)
  813. X            continue;
  814. X
  815. X        if (fwrite (new_catd->nl_msgs[i], sizeof (off_t),
  816. X            new_catd->nl_nmsgs[i], new_catd->nl_cat_fp) !=
  817. X                new_catd->nl_nmsgs[i]) {
  818. X            sprintf (error,
  819. X                M(8, "gencat: can't write to %s"), argv[1]);
  820. X            perror (error);
  821. X            exit (1);
  822. X        }
  823. X    }
  824. X    for (i = 0;i < new_catd->nl_sets;i++) {
  825. X        if (new_catd->nl_msgs[i] == (off_t *) 0)
  826. X            continue;
  827. X
  828. X        for (j = 0;j < new_catd->nl_nmsgs[i];j++) {
  829. X            if (messages[i][j] == (char *) 0)
  830. X                continue;
  831. X
  832. X            if (fwrite (messages[i][j],
  833. X                strlen (messages[i][j]) + 1, 1,
  834. X                    new_catd->nl_cat_fp) != 1) {
  835. X                sprintf (error,
  836. X                    M(8, "gencat: can't write to %s"),
  837. X                    argv[1]);
  838. X                perror (error);
  839. X                exit (1);
  840. X            }
  841. X        }
  842. X    }
  843. X    exit (0);
  844. X}
  845. SHAR_EOF
  846. chmod 0644 gencat.c || echo "restore of gencat.c fails"
  847. sed 's/^X//' << 'SHAR_EOF' > gencat.msg.En_US &&
  848. X$quote "
  849. X$
  850. X$ message catalog for "gencat"
  851. X$
  852. X$set 1
  853. X1 Usage: gencat catfile msgfile ...\n
  854. X2 gencat: Unable to open the file %s\n
  855. X3 Invalid line in input file, line %d\n
  856. X4 gencat: Unable to create new message catalog\n
  857. X5 gencat: Unable to create temporary file\n
  858. X6 gencat: Unable to create message catalog file %s
  859. X7 gencat: Unable to open message file %s
  860. X8 gencat: Unable to write to message catalog file %s
  861. X9 gencat: Unable to open message catalog file %s
  862. X10 gencat: The file %s is not a valid message catalog\n
  863. X11 gencat: Out of memory loading message catalog
  864. X$
  865. X$ message catalog for "catgets"
  866. X$
  867. X$set 2
  868. X1 Usage: catgets catalog set msg default\n
  869. X$
  870. X$ message catalog for "dspcat"
  871. X$
  872. X$set 3
  873. X1 Usage: dspcat catalog [ set [ msg ] ]\n
  874. X2 dspcat: Unable to open message catalog file %s\n
  875. X3 dspcat: "%s" is an invalid set number.\n
  876. X4 dspcat: "%s" is an invalid message number.\n
  877. SHAR_EOF
  878. chmod 0644 gencat.msg.En_US || echo "restore of gencat.msg.En_US fails"
  879. sed 's/^X//' << 'SHAR_EOF' > catgets.c &&
  880. X/*
  881. X * Copyright 1994, John F. Haugh II
  882. X * All rights reserved.
  883. X *
  884. X * Permission is granted to copy and create derivative works for any
  885. X * non-commercial purpose, provided this copyright notice is preserved
  886. X * in all copies of source code, or included in human readable form
  887. X * and conspicuously displayed on all copies of object code or
  888. X * distribution media.
  889. X *
  890. X * This software is provided on an AS-IS basis and the author makes
  891. X * no warrantee of any kind.  The "Artistic License" located in the
  892. X * file LICENSE contains complete licensing information.
  893. X */
  894. X
  895. X#ifndef lint
  896. Xstatic char sccsid[] = "%W%    %U%    %G%";
  897. X#endif
  898. X
  899. X#include <stdio.h>
  900. X#include "nl_types.h"
  901. X
  902. Xnl_catd    catd;
  903. X#define    M(msg,def)    catgets (catd, 2, msg, def)
  904. X
  905. Xmain (int argc, char ** argv)
  906. X{
  907. X    nl_catd    cmd_catd;
  908. X    char    *msg;
  909. X
  910. X    catd = catopen ("gencat", 0);
  911. X
  912. X    if (argc < 5) {
  913. X        fprintf (stderr,
  914. X            M(1, "usage: catgets catalog set msg default\n"));
  915. X        exit (1);
  916. X    }
  917. X    cmd_catd = catopen (argv[1], 0);
  918. X    if (msg = catgets (cmd_catd, atoi (argv[2]), atoi (argv[3]), argv[4]))
  919. X        write (1, msg, strlen (msg));
  920. X    else
  921. X        write (1, argv[4], strlen (argv[4]));
  922. X
  923. X    exit (1);
  924. X}
  925. SHAR_EOF
  926. chmod 0644 catgets.c || echo "restore of catgets.c fails"
  927. sed 's/^X//' << 'SHAR_EOF' > l_catclose.c &&
  928. X/*
  929. X * Copyright 1994, John F. Haugh II
  930. X * All rights reserved.
  931. X *
  932. X * Permission is granted to copy and create derivative works for any
  933. X * non-commercial purpose, provided this copyright notice is preserved
  934. X * in all copies of source code, or included in human readable form
  935. X * and conspicuously displayed on all copies of object code or
  936. X * distribution media.
  937. X *
  938. X * This software is provided on an AS-IS basis and the author makes
  939. X * no warrantee of any kind.  The "Artistic License" located in the
  940. X * file LICENSE contains complete licensing information.
  941. X */
  942. X
  943. X#ifndef    lint
  944. Xstatic    char    sccsid[] = "%W%    %U%    %G%";
  945. X#endif
  946. X
  947. X#include <sys/types.h>
  948. X#include <stdio.h>
  949. X#include "nl_types.h"
  950. X
  951. Xint
  952. Xcatclose (nl_catd catd)
  953. X{
  954. X    int    i;
  955. X
  956. X    if (catd == (nl_catd) -1)
  957. X        return -1;
  958. X
  959. X    fclose (catd->nl_cat_fp);
  960. X
  961. X    for (i = 0;i <= catd->nl_sets;i++)
  962. X        if (catd->nl_msgs[i])
  963. X            free (catd->nl_nmsgs);
  964. X
  965. X    free (catd);
  966. X    return 0;
  967. X}
  968. SHAR_EOF
  969. chmod 0644 l_catclose.c || echo "restore of l_catclose.c fails"
  970. sed 's/^X//' << 'SHAR_EOF' > l_catgets.c &&
  971. X/*
  972. X * Copyright 1994, John F. Haugh II
  973. X * All rights reserved.
  974. X *
  975. X * Permission is granted to copy and create derivative works for any
  976. X * non-commercial purpose, provided this copyright notice is preserved
  977. X * in all copies of source code, or included in human readable form
  978. X * and conspicuously displayed on all copies of object code or
  979. X * distribution media.
  980. X *
  981. X * This software is provided on an AS-IS basis and the author makes
  982. X * no warrantee of any kind.  The "Artistic License" located in the
  983. X * file LICENSE contains complete licensing information.
  984. X */
  985. X
  986. X#ifndef    lint
  987. Xstatic    char    sccsid[] = "%W%    %U%    %G%";
  988. X#endif
  989. X
  990. X#include <sys/types.h>
  991. X#include <stdio.h>
  992. X#include "nl_types.h"
  993. X
  994. Xchar *
  995. Xcatgets (nl_catd catd, int set_num, int msg_num, char * def_msg)
  996. X{
  997. X    static    char    buf[NL_TEXTMAX];
  998. X    int    i;
  999. X    int    c;
  1000. X
  1001. X    if (catd == (nl_catd) -1)
  1002. X        return def_msg;
  1003. X
  1004. X    if (set_num < 1 || set_num > catd->nl_sets)
  1005. X        return def_msg;
  1006. X
  1007. X    if (msg_num < 1 || msg_num > catd->nl_nmsgs[set_num-1])
  1008. X        return def_msg;
  1009. X
  1010. X    if (catd->nl_msgs[set_num-1][msg_num-1] == (off_t) 0)
  1011. X        return def_msg;
  1012. X
  1013. X    if (fseek (catd->nl_cat_fp, catd->nl_msgs[set_num-1][msg_num-1], 0))
  1014. X        return def_msg;
  1015. X
  1016. X    for (i = 0;i < (NL_TEXTMAX-1);i++) {
  1017. X        if ((c = getc (catd->nl_cat_fp)) == '\0' || c == EOF)
  1018. X            break;
  1019. X
  1020. X        buf[i] = c;
  1021. X    }
  1022. X    buf[i++] = '\0';
  1023. X    return buf;
  1024. X}
  1025. SHAR_EOF
  1026. chmod 0644 l_catgets.c || echo "restore of l_catgets.c fails"
  1027. sed 's/^X//' << 'SHAR_EOF' > l_catopen.c &&
  1028. X/*
  1029. X * Copyright 1994, John F. Haugh II
  1030. X * All rights reserved.
  1031. X *
  1032. X * Permission is granted to copy and create derivative works for any
  1033. X * non-commercial purpose, provided this copyright notice is preserved
  1034. X * in all copies of source code, or included in human readable form
  1035. X * and conspicuously displayed on all copies of object code or
  1036. X * distribution media.
  1037. X *
  1038. X * This software is provided on an AS-IS basis and the author makes
  1039. X * no warrantee of any kind.  The "Artistic License" located in the
  1040. X * file LICENSE contains complete licensing information.
  1041. X */
  1042. X
  1043. X#ifndef    lint
  1044. Xstatic    char    sccsid[] = "%W%    %U%    %G%";
  1045. X#endif
  1046. X
  1047. X#include <limits.h>
  1048. X#include <unistd.h>
  1049. X#include <stdlib.h>
  1050. X#include <string.h>
  1051. X#include <stdio.h>
  1052. X
  1053. X#undef    NL_MSGMAX
  1054. X#undef    NL_SETMAX
  1055. X#undef    NL_TEXTMAX
  1056. X
  1057. X#include "nl_types.h"
  1058. X
  1059. Xstatic    char    lang_var[32];
  1060. Xstatic    char    language[16];
  1061. Xstatic    char    territory[16];
  1062. Xstatic    char    codeset[16];
  1063. X
  1064. Xstatic void
  1065. Xget_lang_var ()
  1066. X{
  1067. X    char    *lang;
  1068. X
  1069. X    if (! (lang = getenv ("LANG")))
  1070. X        lang = "C";
  1071. X
  1072. X    strncpy (lang_var, lang, sizeof lang_var);
  1073. X
  1074. X    switch (sscanf (lang_var, "%16[^_]_%16[^.].%16s",
  1075. X            language, territory, codeset)) {
  1076. X        default:
  1077. X        case 0:
  1078. X            language[0] = '\0';
  1079. X        case 1:
  1080. X            territory[0] = '\0';
  1081. X        case 2:
  1082. X            codeset[0] = '\0';
  1083. X        case 3:
  1084. X            return;
  1085. X    }
  1086. X}
  1087. X
  1088. Xstatic int
  1089. Xget_cat_name (char * file, const char * path, const char * name)
  1090. X{
  1091. X    char    *begin, *end;
  1092. X    char    *cp1, *cp2;
  1093. X    char    dummy[BUFSIZ];
  1094. X
  1095. X    strncpy (dummy, path, sizeof dummy - 1);
  1096. X    dummy[BUFSIZ-1] = '\0';
  1097. X    file[0] = '\0';
  1098. X
  1099. X    for (begin = dummy;begin;begin = end) {
  1100. X        if (end = strchr (begin, ':'))
  1101. X            *end++ = '\0';
  1102. X
  1103. X        for (cp1 = begin, cp2 = file;*cp1;) {
  1104. X            if (*cp1 != '%') {
  1105. X                *cp2++ = *cp1++;
  1106. X                continue;
  1107. X            }
  1108. X            switch (*++cp1) {
  1109. X                default:
  1110. X                case '%':
  1111. X                    *cp2++ = *cp1++;
  1112. X                    continue;
  1113. X                case 'N':
  1114. X                    strcpy (cp2, name);
  1115. X                    cp1++;
  1116. X                    cp2 += strlen (name);
  1117. X                    continue;
  1118. X                case 'L':
  1119. X                    strcpy (cp2, lang_var);
  1120. X                    cp1++;
  1121. X                    cp2 += strlen (lang_var);
  1122. X                    continue;
  1123. X                case 'l':
  1124. X                    strcpy (cp2, language);
  1125. X                    cp1++;
  1126. X                    cp2 += strlen (language);
  1127. X                    continue;
  1128. X                case 't':
  1129. X                    strcpy (cp2, territory);
  1130. X                    cp1++;
  1131. X                    cp2 += strlen (territory);
  1132. X                    continue;
  1133. X                case 'c':
  1134. X                    strcpy (cp2, codeset);
  1135. X                    cp1++;
  1136. X                    cp2 += strlen (codeset);
  1137. X                    continue;
  1138. X            }
  1139. X        }
  1140. X        *cp2 = '\0';
  1141. X
  1142. X        if (access (file, 0) == 0)
  1143. X            return 0;
  1144. X    }
  1145. X    return -1;
  1146. X}
  1147. X
  1148. Xnl_catd
  1149. Xcatopen (const char * name, int oflag)
  1150. X{
  1151. X    char    *nlspath;
  1152. X    char    catalog[PATH_MAX];
  1153. X    int    i;
  1154. X    nl_catd catd;
  1155. X    nl_cat_header header;
  1156. X
  1157. X    if (! (nlspath = getenv ("NLSPATH")))
  1158. X        nlspath = "/usr/lib/nls/%L/%N.cat";
  1159. X
  1160. X    get_lang_var ();
  1161. X
  1162. X    if (strcmp (language, "C") == 0)
  1163. X        return (nl_catd) -1;
  1164. X
  1165. X    if (get_cat_name (catalog, nlspath, name))
  1166. X        return (nl_catd) -1;
  1167. X
  1168. X    if (! (catd = (nl_catd) malloc (sizeof *catd)))
  1169. X        return (nl_catd) -1;
  1170. X
  1171. X    if (! (catd->nl_cat_fp = fopen (catalog, "r"))) {
  1172. X        free (catd);
  1173. X        return (nl_catd) -1;
  1174. X    }
  1175. X    if (fread (&header, sizeof header, 1, catd->nl_cat_fp) != 1) {
  1176. X        fclose (catd->nl_cat_fp);
  1177. X        free (catd);
  1178. X        return (nl_catd) -1;
  1179. X    }
  1180. X    catd->nl_sets = header.nl_sets;
  1181. X    for (i = 0;i < catd->nl_sets;i++)
  1182. X        catd->nl_msgs[i] = (off_t *) 0;
  1183. X
  1184. X    for (i = 0;i < header.nl_sets;i++) {
  1185. X        catd->nl_nmsgs[i] = header.nl_nmsgs[i];
  1186. X
  1187. X        if (catd->nl_nmsgs[i] == 0) {
  1188. X            catd->nl_msgs[i] = (off_t *) 0;
  1189. X            continue;
  1190. X        }
  1191. X        if (! (catd->nl_msgs[i] = (off_t *)
  1192. X                malloc (sizeof (off_t) * header.nl_nmsgs[i])))
  1193. X            goto fail;
  1194. X        if (fread (catd->nl_msgs[i], sizeof (off_t) *
  1195. X                header.nl_nmsgs[i], 1, catd->nl_cat_fp) != 1)
  1196. X            goto fail;
  1197. X    }
  1198. X    return catd;
  1199. X
  1200. Xfail:
  1201. X    fclose (catd->nl_cat_fp);
  1202. X
  1203. X    for (i = 0;i <= catd->nl_sets;i++)
  1204. X        if (catd->nl_msgs[i])
  1205. X            free (catd->nl_nmsgs);
  1206. X
  1207. X    free (catd);
  1208. X    return (nl_catd) -1;
  1209. X}
  1210. SHAR_EOF
  1211. chmod 0644 l_catopen.c || echo "restore of l_catopen.c fails"
  1212. sed 's/^X//' << 'SHAR_EOF' > nl_types.h &&
  1213. X/*
  1214. X * Copyright 1994, John F. Haugh II
  1215. X * All rights reserved.
  1216. X *
  1217. X * Permission is granted to copy and create derivative works for any
  1218. X * non-commercial purpose, provided this copyright notice is preserved
  1219. X * in all copies of source code, or included in human readable form
  1220. X * and conspicuously displayed on all copies of object code or
  1221. X * distribution media.
  1222. X *
  1223. X * This software is provided on an AS-IS basis and the author makes
  1224. X * no warrantee of any kind.  The "Artistic License" located in the
  1225. X * file LICENSE contains complete licensing information.
  1226. X *
  1227. X *    %W%    %U%    %G%
  1228. X */
  1229. X
  1230. X#define    NL_MSGMAX    256
  1231. X#define    NL_SETD        1
  1232. X#define    NL_SETMAX    16
  1233. X#define    NL_TEXTMAX    1024
  1234. X
  1235. Xtypedef struct {
  1236. X    FILE    *nl_cat_fp;
  1237. X    int    nl_sets;
  1238. X    int    nl_nmsgs[NL_SETMAX];
  1239. X    off_t    *nl_msgs[NL_SETMAX];
  1240. X} * nl_catd;
  1241. X
  1242. Xtypedef struct {
  1243. X    int    nl_sets;
  1244. X    int    nl_nmsgs[NL_SETMAX];
  1245. X} nl_cat_header;
  1246. X
  1247. Xnl_catd catopen (const char *, int);
  1248. Xint catclose (nl_catd);
  1249. Xchar *catgets (nl_catd, int, int, char *);
  1250. SHAR_EOF
  1251. chmod 0644 nl_types.h || echo "restore of nl_types.h fails"
  1252. exit 0
  1253. -- 
  1254. John F. Haugh II  [ NRA-ILA ] [ Kill Barney ] !'s: ...!cs.utexas.edu!rpp386!jfh
  1255. Ma Bell: (512) 251-2151 [GOP][DoF #17][PADI][ENTJ]   @'s: jfh@rpp386.cactus.org
  1256.  There are three documents that run my life: The King James Bible, the United
  1257.  States Constitution, and the UNIX System V Release 4 Programmer's Reference.
  1258.  
  1259.  
  1260.