/* * XX_SUPPORT.C * * Copyright 2019 VMS Software, Inc. * * Contains VMS specific support for exit handler, Control-T handler, * log file output, and getting the nodename. Plus a number of support * routines for printing. * * To use, include this code: * * #include "xx_support.h" * * And build * cc xx+xx_support+sys$library:sys$lib_c.tlb/lib * * And during program initialization: * * xx$init(); */ /* Print a line */ void print_line (char *line, char *logline) { int status, len; if (line) { char c = cur_time_str[DATE_END]; cur_time_str[DATE_END] = 0; printf("%s: %s\n", &cur_time_str[DATE_START], line); cur_time_str[DATE_END] = c; } if (log_flag) { len = sprintf(log_line, "%s %s: %s", cur_time_str, nodename, logline); log_rab.rab$l_rbf = log_line; log_rab.rab$w_rsz = len; log_rab.rab$b_mbf = 8; log_rab.rab$l_rop = RAB$M_WBH; status = sys$put(&log_rab); if ($FAIL(status)) log_flag = 0; status = sys$flush(&log_rab); if ($FAIL(status)) log_flag = 0; } } void print_vline (char *pline) { if (verbose_flag) print_line(pline, pline); else print_line(0, pline); } /* pk_dump - Dump packet data for the length specified */ void pk_dump (char *what, uint32_t *pk, int pkt_len) { int off, i, j, k; uint32_t data, mask; sprintf(pline, "%s", what); print_line(pline, pline); /* Print packet contents if anything here */ pk_dump_packet(pk, pkt_len); } /* Print packet contents if specified */ void pk_dump_packet (uint32_t *pk, int dump_len) { int off, k; uint32_t data, mask; if (swap_flag == FALSE) { void pk_dump_packet_noswap (uint32_t *pk, int dump_len); pk_dump_packet_noswap(pk, dump_len); return; } if (dump_len) { off = 0; while (dump_len >= 32) { sprintf(pline, " %04x: %08x %08x %08x %08x %08x %08x %08x %08x", off, bswp32(pk[0]), bswp32(pk[1]), bswp32(pk[2]), bswp32(pk[3]), bswp32(pk[4]), bswp32(pk[5]), bswp32(pk[6]), bswp32(pk[7])); print_line(pline, pline); off += 32; pk += 8; dump_len -= 32; } if (dump_len) { if ((k = sprintf(pline, " %04x: ", off)) < 0) k = 0; while (dump_len >= 4) { k += sprintf(&pline[k], " %08x", bswp32(pk[0])); pk++; if (k < 0) k = 0; dump_len -= 4; } if (dump_len) { data = bswp32(pk[0]); k += sprintf(&pline[k], " "); if (k < 0) k = 0; sprintf(&pline[k], "%08x", data); pline[k + dump_len * 2] = 0; } print_line(pline, pline); } } } void pk_dump_packet_noswap (uint32_t *pk, int dump_len) { int off, i, j, k; uint32_t data, mask; if (dump_len) { off = 0; while (dump_len >= 32) { sprintf(pline, " %04x: %08x %08x %08x %08x %08x %08x %08x %08x", off, pk[0], pk[1], pk[2], pk[3], pk[4], pk[5], pk[6], pk[7]); print_line(pline, pline); off += 32; pk += 8; dump_len -= 32; } if (dump_len) { if ((k = sprintf(pline, " %04x: ", off)) < 0) k = 0; while (dump_len >= 4) { k += sprintf(&pline[k], " %08x", pk[0]); pk++; if (k < 0) k = 0; dump_len -= 4; } if (dump_len) { mask = 0xFFFFFFFF; data = pk[0]; i = 4 - dump_len; j = 8; k += sprintf(&pline[k], " "); if (k < 0) k = 0; while (i--) { k += sprintf(&pline[k], " "); if (k < 0) k = 0; mask >>= 8; j -= 2; } sprintf(&pline[k], "%0*x", j, data & mask); } print_line(pline, pline); } } } /* Calculate interval time */ uint64_t get_delta (struct timeval *cur_time, struct timeval *last_time) { uint64_t sec = cur_time->tv_sec - last_time->tv_sec; uint64_t usec; if (cur_time->tv_usec > last_time->tv_usec) usec = cur_time->tv_usec - last_time->tv_usec; else { usec = cur_time->tv_usec + 1000000 - last_time->tv_usec; sec--; } sec *= 1000000; return sec + usec; } /* Convert 64-bit value to 8 character string */ void cvt_value (uint64_t val, char *val_str) { if (val < 100000) sprintf(val_str, " %7llu", val); else if (val < 100000000) sprintf(val_str, " %6lluk", val / 1000); else if (val < 100000000000) sprintf(val_str, " %6llum", val / 1000000); else if (val < 100000000000000) sprintf(val_str, " %6llug", val / 1000000000); else sprintf(val_str, " %6llut", val / 1000000000000); } /* Convert 64-bit value to 6 character string */ void cvt_value_short (uint64_t val, char *val_str) { if (val < 1000) sprintf(val_str, " %5llu", val); else if (val < 1000000) sprintf(val_str, " %4lluk", val / 1000); else if (val < 1000000000) sprintf(val_str, " %4llum", val / 1000000); else if (val < 1000000000000) sprintf(val_str, " %4llug", val / 1000000000); else { strcpy(val_str, " *****"); } } /* Get system name */ void xx$get_sys_name () { int i, status, nodename_len; /* Item list entry (for GETSYI) */ struct item_entry { short buflen; /* Supplied buffer length */ short code; /* Item code */ char *bufadr; /* Buffer address */ int *lenadr; /* Returned buffer length */ }; struct item_entry ilist[2]; /* Item list for GETSYI */ /* Get nodename (reserving 2 bytes for space and zero terminator in buflen) */ nodename_len = 0; memset(&ilist,0,sizeof(ilist)); /* Clear item list for GETSYI */ ilist[0].buflen = sizeof(nodename) - 2; /* Item 1 - buffer size */ ilist[0].code = SYI$_NODENAME; /* - code (NODENAME) */ ilist[0].bufadr = (char *)&nodename; /* - buffer address */ ilist[0].lenadr = &nodename_len; /* - return length */ status = sys$getsyiw(0,0,0,&ilist,0,0,0); /* Do the GETSYI */ if ($FAIL(status)) nodename[0] = 0; else nodename[nodename_len] = 0; for (i=0; i