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