1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1988 AT&T */
27 /* All Rights Reserved */
28
29 /*
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
33 *
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
37 */
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include "curses_inc.h"
43 #include "print.h"
44 #include <signal.h> /* use this file to determine if this is SVR4.0 system */
45
46 #ifdef SIGSTOP /* SVR4.0 and beyond */
47 #define _ULIBTI "/usr/share/lib/terminfo"
48 #else
49 #define _ULIBTI "/usr/lib/terminfo"
50 #endif
51
52 char *progname;
53
54 /* global variables */
55 static enum printtypes printing = pr_none;
56 static int onecolumn = 0; /* print a single column */
57 static int width = 60; /* width of multi-column printing */
58 static int restrictterm = 1; /* restrict termcap names */
59
60 /* local variables */
61 static int printed = 0;
62 static size_t caplen = 0;
63
64 void
pr_init(enum printtypes type)65 pr_init(enum printtypes type)
66 {
67 printing = type;
68 }
69
70 void
pr_onecolumn(int onoff)71 pr_onecolumn(int onoff)
72 {
73 onecolumn = onoff;
74 }
75
76 void
pr_width(int nwidth)77 pr_width(int nwidth)
78 {
79 if (nwidth > 0)
80 width = nwidth;
81 }
82
83 void
pr_caprestrict(int onoff)84 pr_caprestrict(int onoff)
85 {
86 restrictterm = onoff;
87 }
88
89 static char capbools[] =
90 "ambsbwdadbeoeshchshzinkmmimsncnsosptulxbxnxoxsxt";
91 static int ncapbools = sizeof (capbools) / sizeof (capbools[0]);
92
93 static char capnums[] =
94 "codBdCdFdNdTknlipbsgug";
95 static int ncapnums = sizeof (capnums) / sizeof (capnums[0]);
96
97 static char capstrs[] =
98 "ALDCDLDOICLERISFSRUPaealasbcbtcdcechclcmcsctcvdcdldmdsedeifshoi1i2i"
99 "cifimipisk0k1k2k3k4k5k6k7k8k9kbkdkekhklkokrkskul0l1l2l3l4l5l6l7l"
100 "8l9ndnlpcr1r2r3rcrfrpscsesosrsttetitsucueupusvbvevivs";
101 static int ncapstrs = sizeof (capstrs) / sizeof (capstrs[0]);
102
103 static int
findcapname(char * capname,char * caplist,int listsize)104 findcapname(char *capname, char *caplist, int listsize)
105 {
106 int low = 0, mid, high = listsize - 2;
107 while (low <= high) {
108 mid = (low + high) / 4 * 2;
109 if (capname[0] == caplist[mid]) {
110 if (capname[1] == caplist[mid + 1])
111 return (1);
112 else if (capname[1] < caplist[mid + 1])
113 high = mid - 2;
114 else
115 low = mid + 2;
116 } else if (capname[0] < caplist[mid])
117 high = mid - 2;
118 else
119 low = mid + 2;
120 }
121 return (0);
122 /*
123 * for (; *caplist; caplist += 2)
124 * if (caplist[0] == capname[0] && caplist[1] == capname[1])
125 * return (1);
126 * return (0);
127 */
128 }
129
130 /*
131 * Print out the first line of an entry.
132 */
133 void
pr_heading(char * term,char * synonyms)134 pr_heading(char *term, char *synonyms)
135 {
136 int do_print = 0; /* Can we print the path of the file ? */
137 char buffer[512]; /* Holds search pathname */
138 FILE *work_fp; /* Used to try and open the files */
139 char tail[4]; /* Used for terminfo pathname suffix */
140 char *terminfo; /* The value of $TERMINFO */
141
142
143 /*
144 * Try to obtain $TERMINFO
145 */
146 terminfo = getenv("TERMINFO");
147
148 if (term == (char *)0)
149 term = "";
150 /*
151 * Build the suffix for this device
152 */
153 tail[0] = '/';
154 tail[1] = *term;
155 tail[2] = '/';
156 tail[3] = '\0';
157
158 /*
159 * If we have it - use it, otherwise use /usr/share/lib/terminfo
160 * as base directory
161 */
162 if (terminfo != NULL)
163 (void) sprintf(buffer, "%s%s%s", terminfo, tail, term);
164 else
165 (void) sprintf(buffer, "%s%s%s", _ULIBTI, tail, term);
166
167 /*
168 * Attempt to open the file.
169 */
170 if ((work_fp = fopen(buffer, "rF")) == NULL) {
171 /*
172 * Open failed. If we were looking in /usr/share/lib/terminfo
173 * we are done, otherwise look there next.
174 */
175 if (strncmp(buffer, _ULIBTI, strlen(_ULIBTI)) == 0) {
176 /*
177 * We are done. Not in /usr/share/lib/terminfo,
178 * and $TERMINFO is not set.
179 */
180 (void) fprintf(stderr, "Error: Term \"%s\" not "
181 "found in %s\n", term, _ULIBTI);
182 } else {
183 /*
184 * Check /usr/share/lib/terminfo last. If this fails,
185 * all hope is lost as we know it is not in $TERMINFO.
186 */
187 (void) sprintf(buffer, "%s%s%s", _ULIBTI, tail, term);
188
189 if ((work_fp = fopen(buffer, "rF")) == NULL) {
190 /*
191 * All hope is lost
192 */
193 (void) fprintf(stderr, "Error: Term \"%s\" not "
194 "found in %s or %s\n", term, _ULIBTI,
195 getenv("TERMINFO"));
196 } else do_print = 1;
197 }
198 } else do_print = 1;
199
200 /*
201 * If we found it - print the comment(after closing the file)
202 */
203 if (do_print && *term) {
204 (void) fclose(work_fp);
205 (void) printf("# Reconstructed via infocmp from file: "
206 "%s\n", buffer);
207 }
208
209 switch ((int)printing) {
210 case (int)pr_terminfo:
211 (void) printf("%s,\n", synonyms);
212 break;
213 case (int)pr_cap:
214 (void) printf("%s:\\\n", synonyms);
215 caplen = strlen(synonyms) + 1;
216 break;
217 case (int)pr_longnames:
218 (void) printf("Terminal type %s\n", term);
219 (void) printf(" %s\n", synonyms);
220 break;
221 }
222 }
223
224 void
pr_bheading(void)225 pr_bheading(void)
226 {
227 if (printing == pr_longnames)
228 (void) printf("flags\n");
229 printed = 0;
230 }
231
232 void
pr_boolean(char * infoname,char * capname,char * fullname,int value)233 pr_boolean(char *infoname, char *capname, char *fullname, int value)
234 {
235 int vlen;
236 size_t nlen;
237
238 if (printing == pr_cap && restrictterm &&
239 !findcapname(capname, capbools, ncapbools))
240 return;
241
242 if (onecolumn) {
243 if (value < 0)
244 switch ((int)printing) {
245 case (int)pr_terminfo:
246 (void) printf("\t%s@,\n", infoname);
247 break;
248 case (int)pr_cap:
249 (void) printf("\t:%s@:\\\n", capname);
250 caplen += 4 + strlen(capname);
251 break;
252 case (int)pr_longnames:
253 (void) printf(" %s@\n", fullname);
254 }
255 else
256 switch ((int)printing) {
257 case (int)pr_terminfo:
258 (void) printf("\t%s,\n", infoname);
259 break;
260 case (int)pr_cap:
261 (void) printf("\t:%s:\\\n", capname);
262 caplen += 3 + strlen(capname);
263 break;
264 case (int)pr_longnames:
265 (void) printf(" %s\n", fullname);
266 }
267 } else {
268 switch ((int)printing) {
269 case (int)pr_terminfo: nlen = strlen(infoname);
270 break;
271 case (int)pr_cap: nlen = strlen(capname);
272 break;
273 case (int)pr_longnames:
274 nlen = strlen(fullname);
275 break;
276 }
277 vlen = (value < 0) ? 1 : 0;
278 if ((printed > 0) && (printed + nlen + vlen + 1 > width)) {
279 switch ((int)printing) {
280 case (int)pr_terminfo:
281 case (int)pr_longnames:
282 (void) printf("\n");
283 break;
284 case (int)pr_cap:
285 (void) printf(":\\\n");
286 caplen += 1;
287 }
288 printed = 0;
289 }
290 if (printed == 0) {
291 switch ((int)printing) {
292 case (int)pr_terminfo:
293 (void) printf("\t");
294 printed = 8;
295 break;
296 case (int)pr_cap:
297 (void) printf("\t:");
298 printed = 9;
299 caplen += 2;
300 break;
301 case (int)pr_longnames:
302 (void) printf(" ");
303 printed = 2;
304 }
305 } else {
306 switch ((int)printing) {
307 case (int)pr_terminfo:
308 case (int)pr_longnames:
309 (void) printf(" ");
310 break;
311 case (int)pr_cap:
312 (void) printf(":");
313 caplen += 1;
314 }
315 printed++;
316 }
317 if (value < 0)
318 switch ((int)printing) {
319 case (int)pr_terminfo:
320 (void) printf("%s@,", infoname);
321 printed += nlen + 2;
322 break;
323 case (int)pr_cap:
324 (void) printf("%s@", capname);
325 printed += nlen + 1;
326 caplen += nlen + 1;
327 break;
328 case (int)pr_longnames:
329 (void) printf("%s@,", fullname);
330 printed += nlen + 2;
331 }
332 else
333 switch ((int)printing) {
334 case (int)pr_terminfo:
335 (void) printf("%s,", infoname);
336 printed += nlen + 1;
337 break;
338 case (int)pr_cap:
339 (void) printf("%s", capname);
340 printed += nlen;
341 caplen += nlen;
342 break;
343 case (int)pr_longnames:
344 (void) printf("%s,", fullname);
345 printed += nlen + 1;
346 }
347 }
348 }
349
350 void
pr_bfooting(void)351 pr_bfooting(void)
352 {
353 if (!onecolumn && (printed > 0))
354 switch ((int)printing) {
355 case (int)pr_terminfo:
356 case (int)pr_longnames:
357 (void) printf("\n");
358 break;
359 case (int)pr_cap:
360 (void) printf(":\\\n");
361 caplen += 1;
362 }
363 }
364
365 void
pr_nheading(void)366 pr_nheading(void)
367 {
368 if (printing == pr_longnames)
369 (void) printf("\nnumbers\n");
370 printed = 0;
371 }
372
373 /*
374 * Return the length of the number if it were printed out
375 * with %d. The number is guaranteed to be in the range
376 * 0..maxshort.
377 */
378 static int
digitlen(int value)379 digitlen(int value)
380 {
381 return (value >= 10000 ? 5 :
382 value >= 1000 ? 4 :
383 value >= 100 ? 3 :
384 value >= 10 ? 2 :
385 value >= 0 ? 1 : 0);
386 }
387
388 void
pr_number(char * infoname,char * capname,char * fullname,int value)389 pr_number(char *infoname, char *capname, char *fullname, int value)
390 {
391 int vlen;
392 size_t nlen;
393
394 if (printing == pr_cap && restrictterm &&
395 !findcapname(capname, capnums, ncapnums))
396 return;
397
398 if (onecolumn) {
399 if (value < 0)
400 switch ((int)printing) {
401 case (int)pr_terminfo:
402 (void) printf("\t%s@,\n", infoname);
403 break;
404 case (int)pr_cap:
405 (void) printf("\t:%s@:\\\n", capname);
406 caplen += 4 + strlen(capname);
407 break;
408 case (int)pr_longnames:
409 (void) printf(" %s @\n", fullname);
410 }
411 else
412 switch ((int)printing) {
413 case (int)pr_terminfo:
414 (void) printf("\t%s#%d,\n", infoname,
415 value);
416 break;
417 case (int)pr_cap:
418 (void) printf("\t:%s#%d:\\\n",
419 capname, value);
420 caplen += 4 + strlen(capname) +
421 digitlen(value);
422 break;
423 case (int)pr_longnames:
424 (void) printf(" %s = %d\n", fullname,
425 value);
426 }
427 } else {
428 switch ((int)printing) {
429 case (int)pr_terminfo:
430 nlen = strlen(infoname);
431 break;
432 case (int)pr_cap:
433 nlen = strlen(capname);
434 break;
435 case (int)pr_longnames:
436 nlen = strlen(fullname);
437 break;
438 }
439 vlen = digitlen(value);
440 if ((printed > 0) && (printed + nlen + vlen + 2 > width)) {
441 switch ((int)printing) {
442 case (int)pr_terminfo:
443 case (int)pr_longnames:
444 (void) printf("\n");
445 break;
446 case (int)pr_cap:
447 (void) printf(":\\\n");
448 caplen += 1;
449 }
450 printed = 0;
451 }
452 if (printed == 0) {
453 switch ((int)printing) {
454 case (int)pr_terminfo:
455 (void) printf("\t");
456 printed = 8;
457 break;
458 case (int)pr_cap:
459 (void) printf("\t:");
460 printed = 9;
461 caplen += 2;
462 break;
463 case (int)pr_longnames:
464 (void) printf(" ");
465 printed = 2;
466 }
467 } else {
468 switch ((int)printing) {
469 case (int)pr_terminfo:
470 case (int)pr_longnames:
471 (void) printf(" ");
472 break;
473 case (int)pr_cap:
474 (void) printf(":");
475 caplen += 1;
476 }
477 printed++;
478 }
479 if (value < 0) {
480 switch ((int)printing) {
481 case (int)pr_terminfo:
482 (void) printf("%s@,", infoname);
483 printed += nlen + 2;
484 break;
485 case (int)pr_cap:
486 (void) printf("%s@", capname);
487 printed += nlen + 1;
488 caplen += nlen + 1;
489 break;
490 case (int)pr_longnames:
491 (void) printf("%s@,", fullname);
492 printed += nlen + 2;
493 }
494 } else
495 switch ((int)printing) {
496 case (int)pr_terminfo:
497 (void) printf("%s#%d,", infoname,
498 value);
499 printed += nlen + vlen + 2;
500 break;
501 case (int)pr_cap:
502 (void) printf("%s#%d", capname, value);
503 printed += nlen + vlen + 1;
504 caplen += nlen + vlen + 1;
505 break;
506 case (int)pr_longnames:
507 (void) printf("%s = %d,", fullname,
508 value);
509 printed += nlen + vlen + 4;
510 }
511 }
512 }
513
514 void
pr_nfooting(void)515 pr_nfooting(void)
516 {
517 if (!onecolumn && (printed > 0))
518 switch ((int)printing) {
519 case (int)pr_terminfo:
520 case (int)pr_longnames:
521 (void) printf("\n");
522 break;
523 case (int)pr_cap:
524 (void) printf(":\\\n");
525 caplen += 1;
526 }
527 }
528
529 void
pr_sheading(void)530 pr_sheading(void)
531 {
532 if (printing == pr_longnames)
533 (void) printf("\nstrings\n");
534 printed = 0;
535 }
536
537 void
pr_string(char * infoname,char * capname,char * fullname,char * value)538 pr_string(char *infoname, char *capname, char *fullname, char *value)
539 {
540 char *evalue;
541 int badcapvalue;
542 size_t nlen, vlen;
543
544 if (printing == pr_cap) {
545 if (restrictterm && !findcapname(capname, capstrs, ncapstrs))
546 return;
547 if (value)
548 value = infotocap(value, &badcapvalue);
549 }
550
551 if (onecolumn) {
552 if (value == NULL)
553 switch ((int)printing) {
554 case (int)pr_terminfo:
555 (void) printf("\t%s@,\n", infoname);
556 break;
557 case (int)pr_cap:
558 (void) printf("\t:%s@:\\\n", capname);
559 caplen += 4 + strlen(capname);
560 break;
561 case (int)pr_longnames:
562 (void) printf(" %s@\n", fullname);
563 }
564 else
565 switch ((int)printing) {
566 case (int)pr_terminfo:
567 (void) printf("\t%s=", infoname);
568 tpr(stdout, value);
569 (void) printf(",\n");
570 break;
571 case (int)pr_cap:
572 (void) printf("\t:%s%s=",
573 badcapvalue ? "." : "", capname);
574 caplen += 3 + strlen(capname) +
575 (badcapvalue ? 1 : 0);
576 caplen += cpr(stdout, value);
577 (void) printf(":\\\n");
578 caplen += 1;
579 break;
580 case (int)pr_longnames:
581 (void) printf(" %s = '", fullname);
582 tpr(stdout, value);
583 (void) printf("'\n");
584 }
585 } else {
586 switch ((int)printing) {
587 case (int)pr_terminfo:
588 nlen = strlen(infoname);
589 break;
590 case (int)pr_cap:
591 nlen = strlen(capname);
592 if (badcapvalue)
593 nlen++;
594 break;
595 case (int)pr_longnames:
596 nlen = strlen(fullname);
597 }
598 if (value == NULL)
599 vlen = 1;
600 else
601 if (printing == pr_cap)
602 vlen = strlen(evalue = cexpand(value));
603 else
604 vlen = strlen(evalue = iexpand(value));
605 if ((printed > 0) && (printed + nlen + vlen + 1 > width)) {
606 switch ((int)printing) {
607 case (int)pr_terminfo:
608 case (int)pr_longnames:
609 (void) printf("\n");
610 break;
611 case (int)pr_cap:
612 (void) printf(":\\\n");
613 caplen += 1;
614 }
615 printed = 0;
616 }
617 if (printed == 0) {
618 switch ((int)printing) {
619 case (int)pr_terminfo:
620 (void) printf("\t");
621 printed = 8;
622 break;
623 case (int)pr_cap:
624 (void) printf("\t:");
625 printed = 9;
626 caplen += 2;
627 break;
628 case (int)pr_longnames:
629 (void) printf(" ");
630 printed = 2;
631 }
632 } else {
633 switch ((int)printing) {
634 case (int)pr_terminfo:
635 case (int)pr_longnames:
636 (void) printf(" ");
637 break;
638 case (int)pr_cap:
639 (void) printf(":");
640 caplen += 1;
641 }
642 printed++;
643 }
644 if (value == NULL) {
645 switch ((int)printing) {
646 case (int)pr_terminfo:
647 (void) printf("%s@,", infoname);
648 printed += nlen + 2;
649 break;
650 case (int)pr_cap:
651 (void) printf("%s@", capname);
652 printed += nlen + 1;
653 caplen += nlen + 1;
654 break;
655 case (int)pr_longnames:
656 (void) printf("%s@,", fullname);
657 printed += nlen + 2;
658 }
659 } else
660 switch ((int)printing) {
661 case (int)pr_terminfo:
662 (void) printf("%s=%s,", infoname,
663 evalue);
664 printed += nlen + vlen + 2;
665 break;
666 case (int)pr_cap:
667 if (badcapvalue) {
668 (void) printf(".");
669 caplen += 1;
670 }
671 (void) printf("%s=%s", capname,
672 evalue);
673 printed += nlen + vlen + 1;
674 caplen += nlen + vlen + 1;
675 break;
676 case (int)pr_longnames:
677 (void) printf("%s = '%s',", fullname,
678 evalue);
679 printed += nlen + vlen + 6;
680 }
681 }
682 }
683
684 void
pr_sfooting(void)685 pr_sfooting(void)
686 {
687 if (onecolumn) {
688 if (printing == pr_cap)
689 (void) printf("\n");
690 } else {
691 if (printed > 0)
692 switch ((int)printing) {
693 case (int)pr_terminfo:
694 case (int)pr_longnames:
695 (void) printf("\n");
696 break;
697 case (int)pr_cap:
698 (void) printf(":\n");
699 caplen += 1;
700 }
701 }
702 if (caplen >= 1024) {
703 (void) fprintf(stderr, "%s: WARNING: termcap entry is too "
704 "long!\n", progname);
705 }
706
707 if (printing == pr_longnames)
708 (void) printf("end of strings\n");
709 }
710