Remove UXPDS support
[oweals/cde.git] / cde / lib / tt / bin / tt_type_comp / mp_type_comp.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
27 //%%  $TOG: mp_type_comp.C /main/4 1999/10/14 18:37:58 mgreess $                                                        
28 /*
29  *
30  * mp_type_comp.cc
31  *
32  * Copyright (c) 1990 by Sun Microsystems, Inc.
33  *
34  * ToolTalk type compiler. Performs syntax and semantics checks on
35  * type input file and then writes out the type table in xdr format
36  * or in Classing Engine format.
37  */
38
39 #include <locale.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #if defined(linux)
43 #include <unistd.h>
44 #endif
45 #if defined(sgi) || defined(CSRG_BASED)
46 #include <getopt.h>
47 #endif
48 #if defined(USL)
49 #include "tt_options.h"
50 #if defined(OPT_BUG_USL)
51 extern "C" int getopt(int, char *const *, const char *);
52 #endif
53 #endif
54 #include "mp/mp_global.h"
55 #include "mp/mp_mp.h"
56 #include "mp_otype.h"
57 #include "mp_ptype.h"
58 #include "mp_types_table.h"
59 #include "mp_typedb.h"
60 #include "util/copyright.h"
61 #include "util/tt_global_env.h"
62 #include "util/tt_xdr_version.h"
63 #include "util/tt_port.h"
64 #include "util/tt_gettext.h"
65
66 #define _TT_DBCLIENT_SIDE
67 #include "db/db_server.h"
68
69 #if defined(ultrix)
70 extern "C" void xdrstdio_create(XDR *, FILE *, enum xdr_op);
71 #endif
72
73 typedef void (*cmd_fn)();
74
75 TT_INSERT_COPYRIGHT
76
77 #ifdef OPT_PATCH
78 static char PatchID[] = "Patch Id: 100626_03.";
79 static int Patch_ID100626_03;
80 #endif
81
82 _Tt_string              ifile;
83 _Tt_typedbLevel         cedb = TypedbNone;
84 _Tt_string              ofile;
85 _Tt_string_list_ptr     cargs;
86 int                     option_xdr = 1;
87 int                     option_remap_ptypes = 1;
88 _Tt_string              cpp_options("");
89
90 void
91 print_usage_and_exit()
92 {
93         _tt_syslog(stderr, LOG_ERR, "%s",
94                    catgets(_ttcatd, 4, 2,
95 "Usage:\n"
96 "tt_type_comp [-s] [-d db] [-mM] source_file\n"
97 "tt_type_comp [-s] [-d db] -r type ...\n"
98 "-M     merge source types into specified database, not updating existing types\n"
99 "-m     merge, but update existing types.  Default.\n"
100 "-r     remove source types from the specified database\n"
101 "-d db  database to operate on. One of: user, system, or network. Default: user\n"
102 "-G     perform garbage collection on the ToolTalk database server.\n"
103 "\n"
104 "tt_type_comp [-sE] -p|O|P [-d db]\n"
105 "tt_type_comp [-s]  -p|O|P compiled_file\n"
106 "-O     enumerate on stdout the names of all otypes read\n"
107 "-P     enumerate on stdout the names of all ptypes read\n"
108 "-p     pretty-print on stdout all the ToolTalk types read\n"
109 "-E     use the Classing Engine database(s) instead of the XDR database(s)\n"
110 "-d db  database to read from. One of: user, system, or network. Default: all\n"
111 "\n"
112 "tt_type_comp [-s] -x [-o compiled_file] source_file\n"
113 "-x     compile types from source_file (or stdin, if file is \"-\")\n"
114 "-o     write compiled types to compiled_file (or stdout, if file is \"-\")\n"
115 "       Default: source_file.xdr, or \"types.xdr\" if source is stdin\n"
116 "\n"
117 "tt_type_comp [-hv]\n"
118 "-v     print out version number\n"
119 "-h     print out this message\n"
120 "-s     do not print out any status messages.\n"
121 "\n"
122 "These cpp options will be passed through:\n"
123 "        -undef -Dname -Idirectory -Uname -Ydirectory"));
124         exit(1);
125 }
126
127
128 void
129 read_types(_Tt_string file, _Tt_typedb_ptr &db)
130 {
131         _Tt_parse_status result;
132         _Tt_types_table *table;
133         if (file == "-") {
134                 table = new _Tt_types_table(stdin, result);
135         } else {
136                 table = new _Tt_types_table(file, result);
137         }
138
139         if (result == _TT_PARSE_OK) {
140                 db = new _Tt_typedb();
141
142                 if (table->check_semantics() != _TT_PARSE_OK) {
143                         _tt_syslog(stderr, LOG_ERR,
144                                    catgets(_ttcatd, 4, 3,
145                                            "Semantic error in types file"));
146                         exit(2);
147                 }
148                 db->ptable = table->ptypes();
149                 db->otable = table->otypes();
150         } else {
151                 _Tt_string msg =  catgets(_ttcatd, 4, 4,
152                                           "Not a valid ToolTalk types file" );
153                 if (file.len() > 0) {
154                         msg = msg.cat( ": " ).cat( file );
155                 }
156                 _tt_syslog(stderr, LOG_ERR, msg);
157                 exit(2);
158         }
159 }
160
161
162 void
163 f_ce_print()
164 {
165         _Tt_typedb_ptr  db;
166
167         db = new _Tt_typedb();
168         if (db->init_ce(cedb) != TT_OK) {
169                 _tt_syslog(stderr, LOG_ERR,
170                            catgets(_ttcatd, 4, 5,
171                                    "Cannot read any ToolTalk types "
172                                    "from Classing Engine database"));
173                 exit(3);
174         }
175         db->pretty_print(stdout);
176 }
177
178 void
179 merge(int overwrite)
180 {
181
182         int                             status_ok = 1;
183         int                             exists;
184         _Tt_typedb_ptr                  db;
185         _Tt_ptype_table_cursor          db_ptypes;
186         _Tt_otype_table_cursor          db_otypes;
187         _Tt_typedb_ptr                  xdb;
188         _Tt_ptype_ptr                   pt;
189         _Tt_otype_ptr                   ot;
190         Tt_status                       st = TT_OK;
191
192         if (cedb == TypedbNone) {
193                 cedb = TypedbUser;
194         }
195
196         if (! option_xdr) {
197                 _tt_syslog(stderr, LOG_ERR,
198                            catgets(_ttcatd, 4, 6,
199                                    "Merging Classing Engine tables is no "
200                                    "longer supported"));
201                 exit(1);
202         }
203
204         xdb = new _Tt_typedb();
205         read_types(ifile, db);
206
207         if ((st=xdb->init_xdr(cedb)) != TT_OK) {
208                 // if TT_ERR_DBEXIST is returned from init_ce
209                 // we continue with the merge. It just means
210                 // we're starting up in an environment where
211                 // no tooltalk namespaces exist in any of the
212                 // Classing Engine databases.
213                 if (st != TT_ERR_DBEXIST) {
214                         if (st == TT_ERR_NO_MATCH) {
215                                 _tt_syslog(stderr, LOG_ERR,
216                                            catgets(_ttcatd, 4, 7,
217                                                    "Cannot read types in %s data"
218                                                    "base - version mismatch"),
219                                            _Tt_typedb::level_name(cedb));
220                         } else {
221                                 _tt_syslog(stderr, LOG_ERR,
222                                            catgets(_ttcatd, 4, 8,
223                                                    "Cannot read types in %s data"
224                                                    "base"),
225                                            _Tt_typedb::level_name(cedb));
226                         }
227                         /*
228                          * The most common way for this to fail seems to be
229                          * to not have OPENWINHOME set. Suggest this
230                          * to the user.
231                          */
232                         if (0==getenv("OPENWINHOME")) {
233                                 _tt_syslog(stderr, LOG_ERR,
234                                            catgets(_ttcatd, 4, 9,
235                                                    "$OPENWINHOME not set"));
236                         }
237                         exit(3);
238                 }
239         }
240
241         if (! xdb->begin_write(cedb)) {
242                 _tt_syslog(stderr, LOG_ERR,
243                            catgets(_ttcatd, 4, 10,
244                                    "Cannot initialize %s database for writing"),
245                            _Tt_typedb::level_name(cedb));
246                 exit(3);
247         }
248
249         db_otypes.reset(db->otable);
250         while (db_otypes.next()) {
251                 ot = xdb->otable->lookup(db_otypes->otid());
252                 exists = (! ot.is_null());
253                 if (exists) {
254                         if (! overwrite) {
255                                 continue;
256                         }
257                         if (! xdb->remove_otype(db_otypes->otid())) {
258                                 _tt_syslog(stderr, LOG_ERR,
259                                            catgets(_ttcatd, 4, 11,
260                                                    "Could not remove old "
261                                                    "definition for %s"),
262                                            (char *)db_otypes->otid());
263                                 xdb->abort_write();
264                                 exit(3);
265                         }
266                 }
267                 if (! _tt_global->silent) {
268                         printf( "%s %s...\n",
269                                 (exists)
270                                       ? catgets(_ttcatd, 4, 12, "Overwriting")
271                                       : catgets(_ttcatd, 4, 13, "Writing"),
272                                 (char *)db_otypes->otid());
273                 }
274                 if (! xdb->insert(*db_otypes)) {
275                         _tt_syslog(stderr, LOG_ERR,
276                                    catgets(_ttcatd, 4, 14, "Could not add "
277                                            "new definition for %s"),
278                                    (char *)db_otypes->otid());
279                         xdb->abort_write();
280                         exit(3);
281                 }
282         }
283
284         db_ptypes.reset(db->ptable);
285         while (db_ptypes.next()) {
286                 pt = xdb->ptable->lookup(db_ptypes->ptid());
287                 exists = (! pt.is_null());
288                 if (exists) {
289                         if (! overwrite) {
290                                 continue;
291                         }
292                         if (! xdb->remove_ptype(db_ptypes->ptid())) {
293                                 _tt_syslog(stderr, LOG_ERR,
294                                            catgets(_ttcatd, 4, 15,
295                                                    "Could not remove old "
296                                                    "definition for %s"),
297                                            (char *)db_ptypes->ptid());
298                                 xdb->abort_write();
299                         }
300                 }
301                 if (! _tt_global->silent) {
302                         printf("%s %s...\n",
303                                (exists)
304                                       ? catgets(_ttcatd, 4, 16, "Overwriting")
305                                       : catgets(_ttcatd, 4, 17, "Writing"),
306                                (char *)db_ptypes->ptid());
307                 }
308                 if (! xdb->insert(*db_ptypes)) {
309                         _tt_syslog(stderr, LOG_ERR,
310                                    catgets(_ttcatd, 4, 18, "Could not add "
311                                            "new definition for %s"),
312                                    (char *)db_ptypes->ptid());
313                         xdb->abort_write();
314                 }
315         }
316
317         if (! xdb->end_write()) {
318                 // diagnostic emitted by ::end_write()
319                 exit(3);
320         }
321 }
322
323 void
324 f_merge_overwrite()
325 {
326         merge(1);
327 }
328
329
330 void
331 f_merge_no_overwrite()
332 {
333         merge(0);
334 }
335
336
337 void
338 f_list_types(int otypes)
339 {
340         _Tt_typedb_ptr          db;
341         Tt_status               status;
342         int                     checkOW = 0;
343
344         if (cedb == TypedbNone) {
345                 cedb = TypedbAll;
346         }
347         db = new _Tt_typedb();
348         if (option_xdr) {
349                 if (ifile.len() > 0) {
350                         if (ifile == "-") {
351                                 status = db->init_xdr( stdin );
352                         } else {
353                                 status = db->init_xdr( ifile );
354                         }
355                 } else {
356                         status = db->init_xdr( cedb );
357                 }
358         } else {
359                 status = db->init_ce( cedb );
360         }
361         if (status != TT_OK) {
362                 if (status == TT_ERR_NO_MATCH) {
363                         _tt_syslog(stderr, LOG_ERR,
364                                    catgets(_ttcatd, 4, 19, "Version mismatch "
365                                            "in compiled types"));
366                 } else {
367                         _tt_syslog(stderr, LOG_ERR,
368                                    catgets(_ttcatd, 4, 20, "Cannot read types "
369                                            "in database"));
370                 }
371                 //
372                 // The most common way for this to fail seems to be
373                 // to not have OPENWINHOME set. Suggest this
374                 // to the user.
375                 //
376                 if (0==getenv("OPENWINHOME")) {
377                         _tt_syslog(stderr, LOG_ERR,
378                                    catgets(_ttcatd, 4, 21,
379                                            "$OPENWINHOME not set"));
380                 }
381                 exit(3);
382         }
383         if (otypes) {
384                 _Tt_otype_table_cursor  db_otypes;
385                 db_otypes.reset(db->otable);
386                 while (db_otypes.next()) {
387                         printf("%s\n", (char *)db_otypes->otid());
388                 }
389         } else {
390                 _Tt_ptype_table_cursor  db_ptypes;
391                 db_ptypes.reset(db->ptable);
392                 while (db_ptypes.next()) {
393                         printf("%s\n", (char *)db_ptypes->ptid());
394                 }
395         }
396 }
397
398 void
399 f_list_ptypes()
400 {
401         f_list_types( 0 );
402 }
403
404 void
405 f_list_otypes()
406 {
407         f_list_types( 1 );
408 }
409
410 void
411 f_remove_types()
412 {
413         _Tt_string_list_cursor  argc;
414         _Tt_typedb_ptr          db;
415         _Tt_otype_ptr           ot;
416         _Tt_ptype_ptr           pt;
417         int                     db_changed = 0;
418         Tt_status               err;
419
420         if (cedb == TypedbNone) {
421                 cedb = TypedbUser;
422         }
423         db = new _Tt_typedb();
424         if ((option_xdr && (err = db->init_xdr(cedb)) != TT_OK) ||
425             (!option_xdr && (err = db->init_ce(cedb)) != TT_OK)) {
426                 if (err == TT_ERR_NO_MATCH) {
427                         _tt_syslog(stderr, LOG_ERR,
428                                    catgets(_ttcatd, 4, 22,
429                                            "Cannot read types in %s data"
430                                            "base - version mismatch"),
431                                    _Tt_typedb::level_name(cedb));
432                 } else {
433                         _tt_syslog(stderr, LOG_ERR,
434                                    catgets(_ttcatd, 4, 23,
435                                            "Cannot read types in %s database"),
436                                    _Tt_typedb::level_name(cedb));
437                 }
438                 /*
439                  * The most common way for this to fail seems to be
440                  * to not have OPENWINHOME set. Suggest this
441                  * to the user.
442                  */
443                 if (0==getenv("OPENWINHOME")) {
444                         _tt_syslog(stderr, LOG_ERR,
445                                    catgets(_ttcatd, 4, 24,
446                                            "$OPENWINHOME not set"));
447                 }
448                 exit(3);
449         }
450
451         if (! db->begin_write(cedb)) {
452                 // diagnostic emitted
453                 exit(3);
454         }
455
456         argc.reset(cargs);
457         while (argc.next()) {
458                 pt = db->ptable->lookup(*argc);
459                 if (pt.is_null()) {
460                         ot = db->otable->lookup(*argc);
461                         if (! ot.is_null()) {
462                                 if (! _tt_global->silent) {
463                                         printf(catgets(_ttcatd, 4, 25,
464                                                        "Removing otype %s\n"),
465                                                (char *)(*argc));
466                                 }
467                                 db_changed = 1;
468                                 db->remove_otype(*argc);
469                         }
470                 } else {
471                         if (! _tt_global->silent) {
472                                 printf(catgets(_ttcatd, 4, 26,
473                                                "Removing ptype %s\n"),
474                                        (char *)(*argc));
475                         }
476                         db->remove_ptype(*argc);
477                         db_changed = 1;
478                 }
479         }
480         if (db_changed ) {
481                 // write out changes
482                 if (! db->end_write()) {
483                         exit(3);
484                 }
485         } else {
486                 db->abort_write();
487         }
488 }
489
490
491 void
492 f_xdr_file()
493 {
494         _Tt_typedb_ptr  db;
495
496         if (ofile.len() == 0) {
497                 if (ifile == "-") {
498                         ofile = "types.xdr";
499                 } else {
500                         ofile = ifile.cat(".xdr");
501                 }
502         }
503         read_types(ifile, db);
504
505         Tt_status status;
506         if (ofile == "-") {
507                 status = db->write( stdout );
508         } else {
509                 status = db->write( ofile );
510         }
511         if (status != TT_OK) {
512                 exit( 3 );
513         }
514         if (ofile != "-") {
515                 _Tt_typedb::send_saved( ofile );
516                 printf(catgets(_ttcatd, 4, 27, "output written to %s\n"),
517                        (char *)ofile);
518         }
519 }
520  
521
522 void
523 f_xdr_print()
524 {
525         _Tt_typedb_ptr  db;
526         Tt_status       status;
527         
528         db = new _Tt_typedb();
529         if (ifile.len() != 0) {
530                 if (ifile == "-") {
531                         status = db->init_xdr( stdin );
532                 } else {
533                         status = db->init_xdr( ifile );
534                 }
535         } else {
536                 if (cedb == TypedbNone) {
537                         cedb = TypedbAll;
538                 }
539                 status = db->init_xdr(cedb);
540         }
541         if (status != TT_OK) {
542                 // diagnostic emitted
543                 exit(3);
544         }
545         if (!db.is_null()) {
546                 db->pretty_print(stdout);
547         }
548 }
549
550 //
551 // This sends messages to the 'default' ToolTalk files.
552 // This forces an attempt to contact the sessions registered for
553 // each file, if they are dead, then a deleteSession() is sent
554 // to clear out (garbage collect) the information for that dead
555 // session. Dead sessions can occur in the dbserver if the system
556 // that had registered died without un-registering with dbserver
557 // for a file.
558 //
559 void
560 f_garbage_collect()
561 {
562         _Tt_db_client                   dbClient;
563         _Tt_string                      sessionId;
564
565         if (dbClient.getConnectionResults() == TT_DB_OK) {
566
567                 _Tt_string_list         *sessions;
568                 sessions = dbClient.get_all_sessions();
569
570                 if (sessions != NULL && sessions->count() > 0) {
571             
572                         // Delete the list of sessions that are dead.
573                         do {
574                                 Tt_status       ttstatus;
575
576                                 sessionId = sessions->top();
577                                 if ((ttstatus
578                                      = tt_default_session_set(sessionId))
579                                     != TT_OK) {
580                                         dbClient.delete_session(sessionId);
581                                 }
582                                 sessions->pop();
583                         } while(sessions->count() > 0);
584                 }
585                 dbClient.garbage_collect_in_server();
586         }
587         return;
588 }
589
590 void
591 process_args(int argc, char **argv)
592 {
593         extern char     *optarg;
594         extern int      optind;
595         extern int      opterr;
596         int             c;
597         int             args_left;
598         cmd_fn          fn;
599         int             fn_set = 0;
600
601         // default function is to merge types
602         fn = f_merge_overwrite;
603
604         // Need to parse out the cpp options specially because they
605         // don't work with getopt
606         for (int i = 1; i < argc; i++) {
607                 if (argv[i][0] == '-' &&
608                     (argv[i][1] == 'u' || argv[i][1] == 'D' ||
609                      argv[i][1] == 'I' || argv[i][1] == 'U' ||
610                      argv[i][1] == 'Y')) {
611                         if (argv[i][1] == 'u' &&
612                             strcmp(argv[i], "-undef") != 0) {
613                                 print_usage_and_exit();
614                         }
615                         cpp_options = cpp_options.cat(argv[i]).cat(" ");
616                         // getopt stops processing on an empty string, so
617                         // need a fake option for below
618                         argv[i] = "-Y";
619                 }
620         }
621         int need_file = 1;
622         int only_one_input = 0;
623         while ((c = getopt(argc, argv, "XEGOPsd:hmMo:prvxY")) != -1) {
624                 switch (c) {
625                       case 'X':
626                         option_xdr = 1;
627                         break;
628                       case 'E':
629                         option_xdr = 0;
630                         break;
631                       case 'O':
632                         fn_set++;
633                         fn = f_list_otypes;
634                         need_file = 0;
635                         only_one_input = 1;
636                         break;
637                       case 'P':
638                         fn_set++;
639                         fn = f_list_ptypes;
640                         need_file = 0;
641                         only_one_input = 1;
642                         break;
643                       case 's':
644                         _tt_global->silent = 1;
645                         break;
646                       case 'd':
647                         cedb = _Tt_typedb::level( optarg );
648                         if (cedb == TypedbNone) {
649                                 _tt_syslog( stderr, LOG_ERR,
650                                             catgets(_ttcatd, 4, 28,
651                                                     "Invalid database: %s"),
652                                             optarg );
653                                 print_usage_and_exit();
654                         }
655                         break;
656                       case 'h':
657                         print_usage_and_exit();
658                         break;
659                       case 'm':
660                         fn_set++;
661                         fn = f_merge_overwrite;
662                         break;
663                       case 'M':
664                         fn_set++;
665                         fn = f_merge_no_overwrite;
666                         break;
667                       case 'o':
668                         ofile = optarg;
669                         break;
670                       case 'p':
671                         fn_set++;
672                         need_file = 0;
673                         only_one_input = 1;
674                         if (option_xdr) {
675                                 fn = f_xdr_print;
676                         } else {
677                                 fn = f_ce_print;
678                         }
679                         break;
680                       case 'r':
681                         fn_set++;
682                         fn = f_remove_types;
683                         break;
684                       case 'v':
685                         _TT_PRINT_VERSIONS((char *)_tt_global->progname)
686                         exit(0);
687                       case 'x':
688                         fn_set++;
689                         fn = f_xdr_file;
690                         break;
691                       case 'Y':
692                         // A cpp option was handled, ignore this
693                         break;
694                       case 'G':
695                         // Garbage collect.
696                         need_file = 0;
697                         fn = f_garbage_collect;
698                         break;
699                       case '?':
700                       default:
701                         print_usage_and_exit();
702                         break;
703                 }
704         }
705         if (fn_set > 1) {
706                 _tt_syslog(stderr, LOG_ERR,
707                            catgets(_ttcatd, 4, 29,
708                                    "Specify only one of the options "
709                                    "-O -P -m -M -p -r -x"));
710                 print_usage_and_exit();
711         }
712         //
713         // Extra args are always either a filename or types to remove
714         //
715         ifile = argv[optind];
716         if (ifile.len() == 0) {
717                 if (need_file) {
718                         print_usage_and_exit();
719                 }
720         } else {
721                 if (only_one_input && (cedb != TypedbNone)) {
722                         print_usage_and_exit();
723                 }
724         }
725         if ((ofile.len() > 0) && (fn != f_xdr_file)) {
726                 print_usage_and_exit();
727         }
728         args_left = optind;
729         cargs = new _Tt_string_list();
730         while (argv[args_left]) {
731                 cargs->append(_Tt_string(argv[args_left++]));
732         }
733         (*fn)();
734 }
735
736 int main(int argc, char **argv)
737 {
738         _tt_global = new _Tt_global();
739         _tt_global->progname = argv[0];
740         setlocale( LC_ALL, "" );
741         _tt_openlog( _tt_global->progname, LOG_NOWAIT, 0 );
742         process_args(argc, argv);
743         return((int) 0);
744 }