xref: /freebsd/usr.sbin/cxgbetool/tcb_common.c (revision 10328f8b112381e25e324688c8603caf4cee94ac)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Chelsio Communications, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include "tcb_common.h"
33 
34 /***:-----------------------------------------------------------------------
35  ***: externals
36  ***:-----------------------------------------------------------------------
37  */
38 
39 extern _TCBVAR g_tcb_info4[];
40 extern _TCBVAR g_scb_info4[];
41 extern _TCBVAR g_fcb_info4[];
42 extern void t4_display_tcb_aux_0(_TCBVAR *tvp,int aux);
43 extern void t4_display_tcb_aux_1(_TCBVAR *tvp,int aux);
44 extern void t4_display_tcb_aux_2(_TCBVAR *tvp,int aux);
45 extern void t4_display_tcb_aux_3(_TCBVAR *tvp,int aux);
46 
47 extern _TCBVAR g_tcb_info5[];
48 extern _TCBVAR g_scb_info5[];
49 extern _TCBVAR g_fcb_info5[];
50 extern void t5_display_tcb_aux_0(_TCBVAR *tvp,int aux);
51 extern void t5_display_tcb_aux_1(_TCBVAR *tvp,int aux);
52 extern void t5_display_tcb_aux_2(_TCBVAR *tvp,int aux);
53 extern void t5_display_tcb_aux_3(_TCBVAR *tvp,int aux);
54 
55 extern _TCBVAR g_tcb_info6[];
56 extern _TCBVAR g_scb_info6[];
57 extern _TCBVAR g_fcb_info6[];
58 extern void t6_display_tcb_aux_0(_TCBVAR *tvp,int aux);
59 extern void t6_display_tcb_aux_1(_TCBVAR *tvp,int aux);
60 extern void t6_display_tcb_aux_2(_TCBVAR *tvp,int aux);
61 extern void t6_display_tcb_aux_3(_TCBVAR *tvp,int aux);
62 extern void t6_display_tcb_aux_4(_TCBVAR *tvp,int aux);
63 
64 /***:-----------------------------------------------------------------------
65  ***: globals
66  ***:-----------------------------------------------------------------------
67  */
68 
69 _TCBVAR *g_tcb_info=g_tcb_info5;
70 _TCBVAR *g_scb_info=g_scb_info5;
71 _TCBVAR *g_fcb_info=g_fcb_info5;
72 static int g_tN=0;
73 
74 static int g_prntstyl=PRNTSTYL_COMP;
75 
76 static int g_got_scb=0;
77 static int g_got_fcb=0;
78 
79 
80 /***:-----------------------------------------------------------------------
81 ***: error exit functions
82 ***:-----------------------------------------------------------------------
83 */
84 
85 /**: err_exit functions
86 *:  ------------------
87 */
88 
89 void tcb_prflush(void)
90 {
91     fflush(stdout);
92     fflush(stderr);
93 }
94 
95 
96 void tcb_code_err_exit(char *fmt, ...)
97 {
98   va_list args;
99   va_start(args, fmt);
100   printf("Coding Error in: ");
101   vprintf(fmt, args);
102   printf("\n");
103   tcb_prflush();
104   va_end(args);
105   exit(1);
106 }
107 
108 /***:-----------------------------------------------------------------------
109 ***: tcb_hexdump functions
110 ***:-----------------------------------------------------------------------
111 */
112 
113 void
114 tcb_hexdump(unsigned base, unsigned char *buf, unsigned int size)
115 {
116     unsigned offset;
117 
118     for (offset = 0; offset < size; ++offset) {
119         if (!(offset % 16)) printf("\n0x%4.4x: ", base + offset);
120         else if (!(offset % 8)) printf(" ");
121         printf("%2.2x ", (unsigned char)buf[offset]);
122     }
123 }
124 
125 int tcb_strmatch_nc(char *cs, char *ct) {
126     while (*cs)
127         if (tolower(*cs++) != tolower(*ct++)) return (FALSE);
128     return (!(*ct));  /*return TRUE if *ct NULL at same time as *cs==NULL*/
129 }
130 
131 
132 /*: -------------------------------------------------------------------------
133 string functions
134 tcb_strmatch_nc:     Similar to exact match, but case insensitive.
135 */
136 
137 
138 int
139 tcb_strncmp_nc(char *cs, char *ct, int n)
140 {
141     /*case insensitive version of the standard strncmp() function */
142     int i = 0;
143     int ret;
144 
145 
146     ret = 0;
147     for (i = 0; i < n && 0 == ret && !(EOS == *cs && EOS == *ct); ++i) {
148         /* this is weird, but it matched GCC linux when strings don't
149         * have any upper case characters.
150         */
151         ret = tolower(*cs++) - tolower(*ct++);
152     }
153     return ret;
154 }
155 
156 int
157 tcb_startswith_nc(char *cs, char *ct)
158 { /* return true if cs start with ct */
159     return (0 == tcb_strncmp_nc(cs, ct, (int)strlen(ct)));
160 }
161 
162 
163 
164 
165 /***:-----------------------------------------------------------------------
166  ***: START OF WINDOWS FUNCTIONS
167  ***:-----------------------------------------------------------------------
168  */
169 
170 
171 /***:-----------------------------------------------------------------------
172  ***: print utilities
173  ***:-----------------------------------------------------------------------
174  */
175 
176 static int g_PR_indent=1;
177 
178 void PR(char *fmt, ...)
179 {
180   int fmt_len;
181   va_list args;
182   va_start(args,fmt);
183 
184   if (g_PR_indent) printf("  ");
185   g_PR_indent=0;
186   fmt_len=(int) strlen(fmt);
187   if (fmt_len>0 && fmt[fmt_len-1]=='\n') g_PR_indent=1;
188 
189   vprintf(fmt,args);
190   tcb_prflush();
191   va_end(args);
192 }
193 
194 
195 /***:-----------------------------------------------------------------------
196  ***: val()
197  ***:-----------------------------------------------------------------------
198  */
199 
200 _TCBVAR *
201 lu_tcbvar(char *name)
202 {
203   _TCBVAR *tvp=g_tcb_info;
204 
205   while (tvp->name!=NULL) {
206     if      (tcb_strmatch_nc(name,tvp->name)) return tvp;
207     else if (tcb_strmatch_nc(name,tvp->aka )) return tvp;
208     tvp+=1;
209   }
210   tcb_code_err_exit("lu_tcbvar: bad name %s\n",name);
211   return NULL;
212 }
213 
214 unsigned
215 val(char *name)
216 {
217   _TCBVAR *tvp;
218 
219   tvp=lu_tcbvar(name);
220   return tvp->val;
221 }
222 
223 ui64
224 val64(char *name)
225 {
226   _TCBVAR *tvp;
227 
228   tvp=lu_tcbvar(name);
229   return tvp->rawval;
230 }
231 
232 
233 
234 /***:-----------------------------------------------------------------------
235  ***: get_tcb_bits
236  ***:-----------------------------------------------------------------------
237  */
238 
239 
240 static int
241 get_tcb_bit(unsigned char *A, int bit)
242 {
243   int ret=0;
244   int ix,shift;
245 
246   ix = 127 - (bit>>3);
247   shift=bit&0x7;
248   /*  prdbg("  ix: %u, shift=%u\n",ix,shift); */
249   ret=(A[ix] >> shift) & 1;
250   return ret;
251 }
252 
253 static ui64
254 get_tcb_bits (unsigned char  *A, int hi, int lo)
255 {
256   ui64 ret=0;
257 
258   if (lo>hi) {
259     int temp=lo;
260     lo=hi;
261     hi=temp;
262   }
263 
264   while (hi>=lo) {
265     ret = (ret<<1) | get_tcb_bit(A,hi);
266     --hi;
267   }
268 
269   return ret;
270 }
271 
272 
273 void
274 decompress_val(_TCBVAR *tvp,unsigned ulp_type,unsigned tx_max,
275 	       unsigned rcv_nxt,unsigned rx_frag0_start_idx_raw)
276 {
277   unsigned rawval=(unsigned) tvp->rawval;
278 
279   switch(tvp->comp) {
280   case COMP_NONE: tvp->val=rawval;  break;
281   case COMP_ULP:  tvp->val=rawval;  break;
282   case COMP_TX_MAX:
283     tvp->val=(tx_max - rawval) & 0xFFFFFFFF;
284     break;
285   case COMP_RCV_NXT:
286     if (tcb_startswith_nc(tvp->name,"rx_frag")) {
287       unsigned fragx=0;
288       if (!tcb_strmatch_nc(tvp->name,"rx_frag0_start_idx_raw"))
289 	fragx=rawval;
290       tvp->val=(rcv_nxt+rx_frag0_start_idx_raw+fragx) & 0xFFFFFFFF;
291     } else {
292       tvp->val=(rcv_nxt - rawval) & 0xFFFFFFFF;
293     }
294     break;
295   case COMP_PTR: tvp->val=rawval;  break;
296   case COMP_LEN:
297     {
298       tvp->val=rawval;
299       if (PM_MODE_RDDP==ulp_type ||  PM_MODE_DDP==ulp_type ||
300 	  PM_MODE_IANDP==ulp_type) {
301 	/* TP does this internally.  Not sure if I should show the
302 	 *  unaltered value or the raw value.  For now I
303 	 *  will diplay the raw value.  For now I've added the code
304 	 *  mainly to stop windows compiler from warning about ulp_type
305 	 *  being an unreferenced parameter.
306 	 */
307 	tvp->val=0;
308 	tvp->val=rawval;  /* comment this out to display altered value */
309       }
310     }
311     break;
312   default:
313     tcb_code_err_exit("decompress_val, bad switch: %d",tvp->comp);
314     break;
315   }
316 
317 
318 
319 }
320 
321 
322 void
323 get_tcb_field(_TCBVAR *tvp,unsigned char *buf)
324 {
325   assert(tvp->hi-tvp->lo+1<=64);
326   assert(tvp->hi>=tvp->lo);
327 
328   tvp->rawval=get_tcb_bits(buf,tvp->lo,tvp->hi);
329   /* assume no compression and 32-bit value for now */
330   tvp->val=(unsigned) (tvp->rawval & 0xFFFFFFFF);
331 
332 
333 }
334 
335 
336 /***:-----------------------------------------------------------------------
337  ***: spr_* functions
338  ***:-----------------------------------------------------------------------
339  */
340 
341 char *
342 spr_tcp_state (unsigned state)
343 {
344   char *ret="UNKNOWN";
345 
346   if      ( 0 == state) {ret = "CLOSED";}
347   else if ( 1 == state) {ret = "LISTEN";}
348   else if ( 2 == state) {ret = "SYN_SENT";}
349   else if ( 3 == state) {ret = "SYN_RCVD";}
350   else if ( 4 == state) {ret = "ESTABLISHED";}
351   else if ( 5 == state) {ret = "CLOSE_WAIT";}
352   else if ( 6 == state) {ret = "FIN_WAIT_1";}
353   else if ( 7 == state) {ret = "CLOSING";}
354   else if ( 8 == state) {ret = "LAST_ACK";}
355   else if ( 9 == state) {ret = "FIN_WAIT_2";}
356   else if (10 == state) {ret = "TIME_WAIT";}
357   else if (11 == state) {ret = "ESTABLISHED_RX";}
358   else if (12 == state) {ret = "ESTABLISHED_TX";}
359   else if (13 == state) {ret = "SYN_PEND";}
360   else if (14 == state) {ret = "ESC_1_STATE";}
361   else if (15 == state) {ret = "ESC_2_STATE";}
362 
363   return ret;
364 }
365 
366 char *
367 spr_cctrl_sel(unsigned sel0,unsigned sel1)
368 {
369   unsigned sel=(sel1<<1) | sel0;
370   char *ret="UNKNOWN";
371 
372   if      ( 0 == sel) {ret = "Reno";}
373   else if ( 1 == sel) {ret = "Tahoe";}
374   else if ( 2 == sel) {ret = "NewReno";}
375   else if ( 3 == sel) {ret = "HighSpeed";}
376 
377   return ret;
378 }
379 
380 
381 char *
382 spr_ulp_type(unsigned ulp_type)
383 {
384   char *ret="UNKNOWN";
385 
386   /*The tp.h PM_MODE_XXX call 1 DDP and 5 IANDP, but external
387    * documentation (tcb.h" calls 5 ddp, and doesn't mention 1 or 3.
388    */
389 
390   if      ( PM_MODE_PASS  == ulp_type) {ret = "TOE";}
391   else if ( PM_MODE_DDP   == ulp_type) {ret = "DDP";}
392   else if ( PM_MODE_ISCSI == ulp_type) {ret = "ISCSI";}
393   else if ( PM_MODE_IWARP == ulp_type) {ret = "IWARP";}
394   else if ( PM_MODE_RDDP  == ulp_type) {ret = "RDMA";}
395   else if ( PM_MODE_IANDP == ulp_type) {ret = "IANDP_DDP";}
396   else if ( PM_MODE_FCOE  == ulp_type) {ret = "FCoE";}
397   else if ( PM_MODE_USER  == ulp_type) {ret = "USER";}
398   else if ( PM_MODE_TLS   == ulp_type) {ret = "TLS";}
399   else if ( PM_MODE_DTLS  == ulp_type) {ret = "DTLS";}
400 
401   return ret;
402 }
403 
404 char *
405 spr_ip_version(unsigned ip_version)
406 {
407   char *ret="UNKNOWN";
408 
409   if      ( 0 == ip_version) {ret = "IPv4";}
410   else if ( 1 == ip_version) {ret = "IPv6";}
411 
412   return ret;
413 }
414 
415 
416 
417 /***:-----------------------------------------------------------------------
418  ***: display_tcb()
419  ***:-----------------------------------------------------------------------
420  */
421 
422 void
423 display_tcb_compressed(_TCBVAR *tvp,int aux)
424 {
425 
426   if (g_tN==4) {
427     t4_display_tcb_aux_0(tvp,aux);
428     if      (1==aux) t4_display_tcb_aux_1(tvp,aux);
429     else if (2==aux) t4_display_tcb_aux_2(tvp,aux);
430     else if (3==aux) t4_display_tcb_aux_3(tvp,aux);
431 
432   } else if (g_tN==5) {
433     t5_display_tcb_aux_0(tvp,aux);
434     if      (1==aux) t5_display_tcb_aux_1(tvp,aux);
435     else if (2==aux) t5_display_tcb_aux_2(tvp,aux);
436     else if (3==aux) t5_display_tcb_aux_3(tvp,aux);
437   } else if (g_tN==6) {
438     t6_display_tcb_aux_0(tvp,aux);
439     if      (1==aux) t6_display_tcb_aux_1(tvp,aux);
440     else if (2==aux) t6_display_tcb_aux_2(tvp,aux);
441     else if (3==aux) t6_display_tcb_aux_3(tvp,aux);
442     else if (4==aux) t6_display_tcb_aux_4(tvp,aux);
443   }
444 }
445 
446 
447 
448 
449 /***:-----------------------------------------------------------------------
450  ***: parse_n_decode_tcb
451  ***:-----------------------------------------------------------------------
452  */
453 
454 
455 unsigned
456 parse_tcb( _TCBVAR *base_tvp, unsigned char *buf)
457 {   /* parse the TCB */
458   _TCBVAR *tvp=base_tvp;
459   unsigned ulp_type;
460   int aux=1;  /* assume TOE or iSCSI */
461   unsigned tx_max=0, rcv_nxt=0, rx_frag0_start_idx_raw=0;
462   int got_tx_max=0, got_rcv_nxt=0, got_rx_frag0_start_idx_raw=0;
463 
464 
465   /* parse the TCB */
466   while (tvp->name!=NULL) {
467     get_tcb_field(tvp,buf);
468     if (!got_tx_max && tcb_strmatch_nc("tx_max",tvp->name)) {
469       tx_max=tvp->val;
470       got_tx_max=1;
471     }
472     if (!got_rcv_nxt && tcb_strmatch_nc("rcv_nxt",tvp->name)) {
473       rcv_nxt=tvp->val;
474       got_rcv_nxt=1;
475     }
476     if (!got_rx_frag0_start_idx_raw &&
477 	tcb_strmatch_nc("rx_frag0_start_idx_raw",tvp->name)) {
478       rx_frag0_start_idx_raw=tvp->val;
479       got_rx_frag0_start_idx_raw=1;
480     }
481     tvp+=1;
482   }
483 
484   tvp=base_tvp;
485   ulp_type=tvp->val;  /* ULP type is always first variable in TCB */
486   if (PM_MODE_IANDP==ulp_type || PM_MODE_FCOE==ulp_type) aux=3;
487   else if (PM_MODE_RDDP==ulp_type) aux=2;
488   else if (6==g_tN && (PM_MODE_TLS==ulp_type || PM_MODE_DTLS==ulp_type)) aux=4;
489   else aux=1;
490 
491   assert(got_tx_max && got_rcv_nxt && got_rx_frag0_start_idx_raw);
492 
493   /* decompress the compressed values */
494   tvp=base_tvp;
495   while (tvp->name!=NULL) {
496     decompress_val(tvp,ulp_type,tx_max,rcv_nxt,rx_frag0_start_idx_raw);
497     tvp+=1;
498   }
499 
500   return aux;
501 }
502 
503 
504 
505 void
506 parse_scb( _TCBVAR *base_tvp, unsigned char *buf)
507 {   /* parse the SCB */
508   _TCBVAR *tvp=base_tvp;
509 
510   while (tvp->name!=NULL) {
511     if (tcb_strmatch_nc("scb_slush",tvp->name)) {
512       /* the scb_slush field is all of remaining memory */
513       tvp->rawval=0;
514       tvp->val=0;
515     } else {
516       get_tcb_field(tvp,buf);
517     }
518     tvp+=1;
519   }
520 }
521 
522 
523 void
524 parse_fcb( _TCBVAR *base_tvp, unsigned char *buf)
525 {   /* parse the FCB */
526   _TCBVAR *tvp=base_tvp;
527 
528   while (tvp->name!=NULL) {
529     get_tcb_field(tvp,buf);
530     tvp+=1;
531   }
532 }
533 
534 
535 void
536 display_list_tcb(_TCBVAR *base_tvp,int aux)
537 {
538   _TCBVAR *tvp=base_tvp;
539   while (tvp->name!=NULL) {
540     if (tvp->aux==0 || tvp->aux==aux) {
541       if (tvp->hi-tvp->lo+1<=32) {
542 	printf("  %4d:%4d %31s: %10u (0x%1x)",tvp->lo,tvp->hi,tvp->name,
543 	       (unsigned) tvp->rawval,(unsigned) tvp->rawval);
544 	if (COMP_TX_MAX==tvp->comp || COMP_RCV_NXT==tvp->comp)
545 	  printf("  -> %1u (0x%x)", tvp->val,tvp->val);
546       } else {
547 	printf("  %4d:%4d %31s: 0x%1llx",tvp->lo,tvp->hi,tvp->name,
548 	       tvp->rawval);
549       }
550       printf("\n");
551     }
552     tvp+=1;
553   }
554 }
555 
556 void
557 display_tcb(_TCBVAR *tvp,unsigned char *buf,int aux)
558 {
559   if (g_prntstyl==PRNTSTYL_VERBOSE ||
560       g_prntstyl==PRNTSTYL_RAW) {
561     tcb_hexdump(0,buf,128);
562     printf("\n");
563   }
564 
565   if (g_prntstyl==PRNTSTYL_VERBOSE ||
566       g_prntstyl==PRNTSTYL_LIST) {
567     display_list_tcb(tvp,aux);
568   }
569 
570   if (g_prntstyl==PRNTSTYL_VERBOSE ||
571       g_prntstyl==PRNTSTYL_COMP) {
572     display_tcb_compressed(tvp,aux);
573   }
574 
575 }
576 
577 void
578 parse_n_display_tcb(unsigned char *buf)
579 {
580   _TCBVAR *tvp=g_tcb_info;
581   int aux;
582 
583   aux=parse_tcb(tvp,buf);
584   display_tcb(tvp,buf,aux);
585 }
586 
587 void
588 parse_n_display_scb(unsigned char *buf)
589 {
590   _TCBVAR *tvp=g_scb_info;
591 
592   parse_scb(tvp,buf);
593   if (g_prntstyl==PRNTSTYL_VERBOSE ||
594       g_prntstyl==PRNTSTYL_RAW) {
595     tcb_hexdump(0,buf,128);
596     printf("\n");
597   }
598   if (g_prntstyl==PRNTSTYL_VERBOSE ||
599       g_prntstyl==PRNTSTYL_LIST ||
600       g_prntstyl==PRNTSTYL_COMP) {
601     display_list_tcb(tvp,0);
602   }
603 }
604 
605 void
606 parse_n_display_fcb(unsigned char *buf)
607 {
608   _TCBVAR *tvp=g_fcb_info;
609 
610   parse_fcb(tvp,buf);
611   if (g_prntstyl==PRNTSTYL_VERBOSE ||
612       g_prntstyl==PRNTSTYL_RAW) {
613     tcb_hexdump(0,buf,128);
614     printf("\n");
615   }
616 
617   if (g_prntstyl==PRNTSTYL_VERBOSE ||
618       g_prntstyl==PRNTSTYL_LIST ||
619       g_prntstyl==PRNTSTYL_COMP) {
620     display_list_tcb(tvp,0);
621   }
622 }
623 
624 void
625 parse_n_display_xcb(unsigned char *buf)
626 {
627   if      (g_got_scb) parse_n_display_scb(buf);
628   else if (g_got_fcb) parse_n_display_fcb(buf);
629   else                parse_n_display_tcb(buf);
630 }
631 
632 /***:-----------------------------------------------------------------------
633  ***: swizzle_tcb
634  ***:-----------------------------------------------------------------------
635  */
636 
637 void
638 swizzle_tcb(unsigned char *buf)
639 {
640   int i,j,k;
641 
642   for (i=0, j=128-16 ; i<j ; i+=16, j-=16) {
643     unsigned char temp;
644     for (k=0; k<16; ++k) {
645       temp=buf[i+k];
646       buf[i+k]=buf[j+k];
647       buf[j+k]=temp;
648     }
649   }
650 }
651 
652 
653 /***:-----------------------------------------------------------------------
654  ***: END OF WINDOWS FUNCTIONS
655  ***:-----------------------------------------------------------------------
656  */
657 
658 void set_tidtype(unsigned int tidtype)
659 {
660     if (tidtype == TIDTYPE_SCB)
661     {
662         g_got_scb = 1;
663     }
664     else if (tidtype == TIDTYPE_FCB)
665     {
666         g_got_fcb = 1;
667     }
668     else
669     {
670         g_got_scb = 0;
671         g_got_fcb = 0;
672     }
673 
674 }
675 
676 void
677 set_tcb_info(unsigned int tidtype, unsigned int cardtype)
678 {
679     set_tidtype(tidtype);
680 
681     g_tN = cardtype;
682     if (4 == g_tN) {
683         g_tcb_info = g_tcb_info4;
684         g_scb_info = g_scb_info4;
685         g_fcb_info = g_fcb_info4;
686     }
687     else if (5 == g_tN) {
688         g_tcb_info = g_tcb_info5;
689         g_scb_info = g_scb_info5;
690         g_fcb_info = g_fcb_info5;
691     }
692     else if (6 == g_tN) {
693         g_tcb_info = g_tcb_info6;
694         g_scb_info = g_scb_info6;
695         g_fcb_info = g_fcb_info6;
696     }
697 }
698 
699 void
700 set_print_style(unsigned int prntstyl)
701 {
702   g_prntstyl=prntstyl;
703 }
704