libnl 1.1
|
00001 /* 00002 * lib/utils.c Utility Functions 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @defgroup utils Utilities 00014 * @{ 00015 */ 00016 00017 #include <netlink-local.h> 00018 #include <netlink/netlink.h> 00019 #include <netlink/utils.h> 00020 #include <linux/socket.h> 00021 00022 /** 00023 * Debug level 00024 */ 00025 int nl_debug = 0; 00026 00027 struct nl_dump_params nl_debug_dp = { 00028 .dp_type = NL_DUMP_FULL, 00029 }; 00030 00031 static void __init nl_debug_init(void) 00032 { 00033 char *nldbg, *end; 00034 00035 if ((nldbg = getenv("NLDBG"))) { 00036 long level = strtol(nldbg, &end, 0); 00037 if (nldbg != end) 00038 nl_debug = level; 00039 } 00040 00041 nl_debug_dp.dp_fd = stderr; 00042 } 00043 00044 /** 00045 * @name Error Code Helpers 00046 * @{ 00047 */ 00048 00049 static char *errbuf; 00050 static int nlerrno; 00051 00052 /** @cond SKIP */ 00053 int __nl_error(int err, const char *file, unsigned int line, const char *func, 00054 const char *fmt, ...) 00055 { 00056 char *user_err; 00057 va_list args; 00058 00059 if (errbuf) { 00060 free(errbuf); 00061 errbuf = NULL; 00062 } 00063 00064 nlerrno = err; 00065 00066 if (fmt) { 00067 va_start(args, fmt); 00068 vasprintf(&user_err, fmt, args); 00069 va_end(args); 00070 } 00071 00072 #ifdef VERBOSE_ERRORS 00073 asprintf(&errbuf, "%s:%u:%s: %s (errno = %s)", 00074 file, line, func, fmt ? user_err : "", strerror(err)); 00075 #else 00076 asprintf(&errbuf, "%s (errno = %s)", 00077 fmt ? user_err : "", strerror(err)); 00078 #endif 00079 00080 if (fmt) 00081 free(user_err); 00082 00083 return -err; 00084 } 00085 00086 int __nl_read_num_str_file(const char *path, int (*cb)(long, const char *)) 00087 { 00088 FILE *fd; 00089 char buf[128]; 00090 00091 fd = fopen(path, "r"); 00092 if (fd == NULL) 00093 return nl_error(errno, "Unable to open file %s for reading", 00094 path); 00095 00096 while (fgets(buf, sizeof(buf), fd)) { 00097 int goodlen, err; 00098 long num; 00099 char *end; 00100 00101 if (*buf == '#' || *buf == '\n' || *buf == '\r') 00102 continue; 00103 00104 num = strtol(buf, &end, 0); 00105 if (end == buf) 00106 return nl_error(EINVAL, "Parsing error"); 00107 00108 if (num == LONG_MIN || num == LONG_MAX) 00109 return nl_error(errno, "Number of out range"); 00110 00111 while (*end == ' ' || *end == '\t') 00112 end++; 00113 00114 goodlen = strcspn(end, "#\r\n\t "); 00115 if (goodlen == 0) 00116 return nl_error(EINVAL, "Empty string"); 00117 00118 end[goodlen] = '\0'; 00119 00120 err = cb(num, end); 00121 if (err < 0) 00122 return err; 00123 } 00124 00125 fclose(fd); 00126 00127 return 0; 00128 } 00129 00130 /** @endcond */ 00131 00132 int nl_get_errno(void) 00133 { 00134 return nlerrno; 00135 } 00136 00137 00138 /** 00139 * Return error message for an error code 00140 * @return error message 00141 */ 00142 char *nl_geterror(void) 00143 { 00144 if (errbuf) 00145 return errbuf; 00146 00147 if (nlerrno) 00148 return strerror(nlerrno); 00149 00150 return "Sucess\n"; 00151 } 00152 00153 /** 00154 * Print a libnl error message 00155 * @arg s error message prefix 00156 * 00157 * Prints the error message of the call that failed last. 00158 * 00159 * If s is not NULL and *s is not a null byte the argument 00160 * string is printed, followed by a colon and a blank. Then 00161 * the error message and a new-line. 00162 */ 00163 void nl_perror(const char *s) 00164 { 00165 if (s && *s) 00166 fprintf(stderr, "%s: %s\n", s, nl_geterror()); 00167 else 00168 fprintf(stderr, "%s\n", nl_geterror()); 00169 } 00170 00171 /** @} */ 00172 00173 /** 00174 * @name Unit Pretty-Printing 00175 * @{ 00176 */ 00177 00178 /** 00179 * Cancel down a byte counter 00180 * @arg l byte counter 00181 * @arg unit destination unit pointer 00182 * 00183 * Cancels down a byte counter until it reaches a reasonable 00184 * unit. The chosen unit is assigned to \a unit. 00185 * 00186 * @return The cancelled down byte counter in the new unit. 00187 */ 00188 double nl_cancel_down_bytes(unsigned long long l, char **unit) 00189 { 00190 if (l >= 1099511627776LL) { 00191 *unit = "TiB"; 00192 return ((double) l) / 1099511627776LL; 00193 } else if (l >= 1073741824) { 00194 *unit = "GiB"; 00195 return ((double) l) / 1073741824; 00196 } else if (l >= 1048576) { 00197 *unit = "MiB"; 00198 return ((double) l) / 1048576; 00199 } else if (l >= 1024) { 00200 *unit = "KiB"; 00201 return ((double) l) / 1024; 00202 } else { 00203 *unit = "B"; 00204 return (double) l; 00205 } 00206 } 00207 00208 /** 00209 * Cancel down a bit counter 00210 * @arg l bit counter 00211 * @arg unit destination unit pointer 00212 * 00213 * Cancels downa bit counter until it reaches a reasonable 00214 * unit. The chosen unit is assigned to \a unit. 00215 * 00216 * @return The cancelled down bit counter in the new unit. 00217 */ 00218 double nl_cancel_down_bits(unsigned long long l, char **unit) 00219 { 00220 if (l >= 1099511627776ULL) { 00221 *unit = "Tbit"; 00222 return ((double) l) / 1099511627776ULL; 00223 } else if (l >= 1073741824) { 00224 *unit = "Gbit"; 00225 return ((double) l) / 1073741824; 00226 } else if (l >= 1048576) { 00227 *unit = "Mbit"; 00228 return ((double) l) / 1048576; 00229 } else if (l >= 1024) { 00230 *unit = "Kbit"; 00231 return ((double) l) / 1024; 00232 } else { 00233 *unit = "bit"; 00234 return (double) l; 00235 } 00236 00237 } 00238 00239 /** 00240 * Cancel down a micro second value 00241 * @arg l micro seconds 00242 * @arg unit destination unit pointer 00243 * 00244 * Cancels down a microsecond counter until it reaches a 00245 * reasonable unit. The chosen unit is assigned to \a unit. 00246 * 00247 * @return The cancelled down microsecond in the new unit 00248 */ 00249 double nl_cancel_down_us(uint32_t l, char **unit) 00250 { 00251 if (l >= 1000000) { 00252 *unit = "s"; 00253 return ((double) l) / 1000000; 00254 } else if (l >= 1000) { 00255 *unit = "ms"; 00256 return ((double) l) / 1000; 00257 } else { 00258 *unit = "us"; 00259 return (double) l; 00260 } 00261 } 00262 00263 /** @} */ 00264 00265 /** 00266 * @name Generic Unit Translations 00267 * @{ 00268 */ 00269 00270 /** 00271 * Convert a character string to a size 00272 * @arg str size encoded as character string 00273 * 00274 * Converts the specified size as character to the corresponding 00275 * number of bytes. 00276 * 00277 * Supported formats are: 00278 * - b,kb/k,m/mb,gb/g for bytes 00279 * - bit,kbit/mbit/gbit 00280 * 00281 * @return The number of bytes or -1 if the string is unparseable 00282 */ 00283 long nl_size2int(const char *str) 00284 { 00285 char *p; 00286 long l = strtol(str, &p, 0); 00287 if (p == str) 00288 return -1; 00289 00290 if (*p) { 00291 if (!strcasecmp(p, "kb") || !strcasecmp(p, "k")) 00292 l *= 1024; 00293 else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g")) 00294 l *= 1024*1024*1024; 00295 else if (!strcasecmp(p, "gbit")) 00296 l *= 1024*1024*1024/8; 00297 else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m")) 00298 l *= 1024*1024; 00299 else if (!strcasecmp(p, "mbit")) 00300 l *= 1024*1024/8; 00301 else if (!strcasecmp(p, "kbit")) 00302 l *= 1024/8; 00303 else if (!strcasecmp(p, "bit")) 00304 l /= 8; 00305 else if (strcasecmp(p, "b") != 0) 00306 return -1; 00307 } 00308 00309 return l; 00310 } 00311 00312 /** 00313 * Convert a character string to a probability 00314 * @arg str probability encoded as character string 00315 * 00316 * Converts the specified probability as character to the 00317 * corresponding probability number. 00318 * 00319 * Supported formats are: 00320 * - 0.0-1.0 00321 * - 0%-100% 00322 * 00323 * @return The probability relative to NL_PROB_MIN and NL_PROB_MAX 00324 */ 00325 long nl_prob2int(const char *str) 00326 { 00327 char *p; 00328 double d = strtod(str, &p); 00329 00330 if (p == str) 00331 return -1; 00332 00333 if (d > 1.0) 00334 d /= 100.0f; 00335 00336 if (d > 1.0f || d < 0.0f) 00337 return -1; 00338 00339 if (*p && strcmp(p, "%") != 0) 00340 return -1; 00341 00342 return rint(d * NL_PROB_MAX); 00343 } 00344 00345 /** @} */ 00346 00347 /** 00348 * @name Time Translations 00349 * @{ 00350 */ 00351 00352 #ifdef USER_HZ 00353 static uint32_t user_hz = USER_HZ; 00354 #else 00355 static uint32_t user_hz = 100; 00356 #endif 00357 00358 static double ticks_per_usec = 1.0f; 00359 00360 /* Retrieves the configured HZ and ticks/us value in the kernel. 00361 * The value is cached. Supported ways of getting it: 00362 * 00363 * 1) environment variable 00364 * 2) /proc/net/psched and sysconf 00365 * 00366 * Supports the environment variables: 00367 * PROC_NET_PSCHED - may point to psched file in /proc 00368 * PROC_ROOT - may point to /proc fs */ 00369 static void __init get_psched_settings(void) 00370 { 00371 char name[FILENAME_MAX]; 00372 FILE *fd; 00373 int got_hz = 0, got_tick = 0; 00374 00375 if (getenv("HZ")) { 00376 long hz = strtol(getenv("HZ"), NULL, 0); 00377 00378 if (LONG_MIN != hz && LONG_MAX != hz) { 00379 user_hz = hz; 00380 got_hz = 1; 00381 } 00382 } 00383 00384 if (!got_hz) 00385 user_hz = sysconf(_SC_CLK_TCK); 00386 00387 if (getenv("TICKS_PER_USEC")) { 00388 double t = strtod(getenv("TICKS_PER_USEC"), NULL); 00389 00390 ticks_per_usec = t; 00391 got_tick = 1; 00392 } 00393 00394 00395 if (getenv("PROC_NET_PSCHED")) 00396 snprintf(name, sizeof(name), "%s", getenv("PROC_NET_PSCHED")); 00397 else if (getenv("PROC_ROOT")) 00398 snprintf(name, sizeof(name), "%s/net/psched", 00399 getenv("PROC_ROOT")); 00400 else 00401 strncpy(name, "/proc/net/psched", sizeof(name) - 1); 00402 00403 if ((fd = fopen(name, "r"))) { 00404 uint32_t tick, us, nom; 00405 int r = fscanf(fd, "%08x%08x%08x%*08x", &tick, &us, &nom); 00406 00407 if (4 == r && nom == 1000000 && !got_tick) 00408 ticks_per_usec = (double)tick/(double)us; 00409 00410 fclose(fd); 00411 } 00412 } 00413 00414 00415 /** 00416 * Return the value of HZ 00417 */ 00418 int nl_get_hz(void) 00419 { 00420 return user_hz; 00421 } 00422 00423 00424 /** 00425 * Convert micro seconds to ticks 00426 * @arg us micro seconds 00427 * @return number of ticks 00428 */ 00429 uint32_t nl_us2ticks(uint32_t us) 00430 { 00431 return us * ticks_per_usec; 00432 } 00433 00434 00435 /** 00436 * Convert ticks to micro seconds 00437 * @arg ticks number of ticks 00438 * @return microseconds 00439 */ 00440 uint32_t nl_ticks2us(uint32_t ticks) 00441 { 00442 return ticks / ticks_per_usec; 00443 } 00444 00445 long nl_time2int(const char *str) 00446 { 00447 char *p; 00448 long l = strtol(str, &p, 0); 00449 if (p == str) 00450 return -1; 00451 00452 if (*p) { 00453 if (!strcasecmp(p, "min") == 0 || !strcasecmp(p, "m")) 00454 l *= 60; 00455 else if (!strcasecmp(p, "hour") || !strcasecmp(p, "h")) 00456 l *= 60*60; 00457 else if (!strcasecmp(p, "day") || !strcasecmp(p, "d")) 00458 l *= 60*60*24; 00459 else if (strcasecmp(p, "s") != 0) 00460 return -1; 00461 } 00462 00463 return l; 00464 } 00465 00466 /** 00467 * Convert milliseconds to a character string 00468 * @arg msec number of milliseconds 00469 * @arg buf destination buffer 00470 * @arg len buffer length 00471 * 00472 * Converts milliseconds to a character string split up in days, hours, 00473 * minutes, seconds, and milliseconds and stores it in the specified 00474 * destination buffer. 00475 * 00476 * @return The destination buffer. 00477 */ 00478 char * nl_msec2str(uint64_t msec, char *buf, size_t len) 00479 { 00480 int i, split[5]; 00481 char *units[] = {"d", "h", "m", "s", "msec"}; 00482 00483 #define _SPLIT(idx, unit) if ((split[idx] = msec / unit) > 0) msec %= unit 00484 _SPLIT(0, 86400000); /* days */ 00485 _SPLIT(1, 3600000); /* hours */ 00486 _SPLIT(2, 60000); /* minutes */ 00487 _SPLIT(3, 1000); /* seconds */ 00488 #undef _SPLIT 00489 split[4] = msec; 00490 00491 memset(buf, 0, len); 00492 00493 for (i = 0; i < ARRAY_SIZE(split); i++) { 00494 if (split[i] > 0) { 00495 char t[64]; 00496 snprintf(t, sizeof(t), "%s%d%s", 00497 strlen(buf) ? " " : "", split[i], units[i]); 00498 strncat(buf, t, len - strlen(buf) - 1); 00499 } 00500 } 00501 00502 return buf; 00503 } 00504 00505 /** @} */ 00506 00507 /** 00508 * @name Link Layer Protocol Translations 00509 * @{ 00510 */ 00511 00512 static struct trans_tbl llprotos[] = { 00513 {0, "generic"}, 00514 __ADD(ARPHRD_ETHER,ether) 00515 __ADD(ARPHRD_EETHER,eether) 00516 __ADD(ARPHRD_AX25,ax25) 00517 __ADD(ARPHRD_PRONET,pronet) 00518 __ADD(ARPHRD_CHAOS,chaos) 00519 __ADD(ARPHRD_IEEE802,ieee802) 00520 __ADD(ARPHRD_ARCNET,arcnet) 00521 __ADD(ARPHRD_APPLETLK,atalk) 00522 __ADD(ARPHRD_DLCI,dlci) 00523 __ADD(ARPHRD_ATM,atm) 00524 __ADD(ARPHRD_METRICOM,metricom) 00525 __ADD(ARPHRD_IEEE1394,ieee1394) 00526 #ifdef ARPHRD_EUI64 00527 __ADD(ARPHRD_EUI64,eui64) 00528 #endif 00529 __ADD(ARPHRD_INFINIBAND,infiniband) 00530 __ADD(ARPHRD_SLIP,slip) 00531 __ADD(ARPHRD_CSLIP,cslip) 00532 __ADD(ARPHRD_SLIP6,slip6) 00533 __ADD(ARPHRD_CSLIP6,cslip6) 00534 __ADD(ARPHRD_RSRVD,rsrvd) 00535 __ADD(ARPHRD_ADAPT,adapt) 00536 __ADD(ARPHRD_ROSE,rose) 00537 __ADD(ARPHRD_X25,x25) 00538 #ifdef ARPHRD_HWX25 00539 __ADD(ARPHRD_HWX25,hwx25) 00540 #endif 00541 __ADD(ARPHRD_PPP,ppp) 00542 __ADD(ARPHRD_HDLC,hdlc) 00543 __ADD(ARPHRD_LAPB,lapb) 00544 __ADD(ARPHRD_DDCMP,ddcmp) 00545 __ADD(ARPHRD_RAWHDLC,rawhdlc) 00546 __ADD(ARPHRD_TUNNEL,ipip) 00547 __ADD(ARPHRD_TUNNEL6,tunnel6) 00548 __ADD(ARPHRD_FRAD,frad) 00549 __ADD(ARPHRD_SKIP,skip) 00550 __ADD(ARPHRD_LOOPBACK,loopback) 00551 __ADD(ARPHRD_LOCALTLK,localtlk) 00552 __ADD(ARPHRD_FDDI,fddi) 00553 __ADD(ARPHRD_BIF,bif) 00554 __ADD(ARPHRD_SIT,sit) 00555 __ADD(ARPHRD_IPDDP,ip/ddp) 00556 __ADD(ARPHRD_IPGRE,gre) 00557 __ADD(ARPHRD_PIMREG,pimreg) 00558 __ADD(ARPHRD_HIPPI,hippi) 00559 __ADD(ARPHRD_ASH,ash) 00560 __ADD(ARPHRD_ECONET,econet) 00561 __ADD(ARPHRD_IRDA,irda) 00562 __ADD(ARPHRD_FCPP,fcpp) 00563 __ADD(ARPHRD_FCAL,fcal) 00564 __ADD(ARPHRD_FCPL,fcpl) 00565 __ADD(ARPHRD_FCFABRIC,fcfb_0) 00566 __ADD(ARPHRD_FCFABRIC+1,fcfb_1) 00567 __ADD(ARPHRD_FCFABRIC+2,fcfb_2) 00568 __ADD(ARPHRD_FCFABRIC+3,fcfb_3) 00569 __ADD(ARPHRD_FCFABRIC+4,fcfb_4) 00570 __ADD(ARPHRD_FCFABRIC+5,fcfb_5) 00571 __ADD(ARPHRD_FCFABRIC+6,fcfb_6) 00572 __ADD(ARPHRD_FCFABRIC+7,fcfb_7) 00573 __ADD(ARPHRD_FCFABRIC+8,fcfb_8) 00574 __ADD(ARPHRD_FCFABRIC+9,fcfb_9) 00575 __ADD(ARPHRD_FCFABRIC+10,fcfb_10) 00576 __ADD(ARPHRD_FCFABRIC+11,fcfb_11) 00577 __ADD(ARPHRD_FCFABRIC+12,fcfb_12) 00578 __ADD(ARPHRD_IEEE802_TR,tr) 00579 __ADD(ARPHRD_IEEE80211,ieee802.11) 00580 #ifdef ARPHRD_IEEE80211_PRISM 00581 __ADD(ARPHRD_IEEE80211_PRISM, ieee802.11_prism) 00582 #endif 00583 #ifdef ARPHRD_VOID 00584 __ADD(ARPHRD_VOID,void) 00585 #endif 00586 }; 00587 00588 char * nl_llproto2str(int llproto, char *buf, size_t len) 00589 { 00590 return __type2str(llproto, buf, len, llprotos, ARRAY_SIZE(llprotos)); 00591 } 00592 00593 int nl_str2llproto(const char *name) 00594 { 00595 return __str2type(name, llprotos, ARRAY_SIZE(llprotos)); 00596 } 00597 00598 /** @} */ 00599 00600 00601 /** 00602 * @name Ethernet Protocol Translations 00603 * @{ 00604 */ 00605 00606 static struct trans_tbl ether_protos[] = { 00607 __ADD(ETH_P_LOOP,loop) 00608 __ADD(ETH_P_PUP,pup) 00609 __ADD(ETH_P_PUPAT,pupat) 00610 __ADD(ETH_P_IP,ip) 00611 __ADD(ETH_P_X25,x25) 00612 __ADD(ETH_P_ARP,arp) 00613 __ADD(ETH_P_BPQ,bpq) 00614 __ADD(ETH_P_IEEEPUP,ieeepup) 00615 __ADD(ETH_P_IEEEPUPAT,ieeepupat) 00616 __ADD(ETH_P_DEC,dec) 00617 __ADD(ETH_P_DNA_DL,dna_dl) 00618 __ADD(ETH_P_DNA_RC,dna_rc) 00619 __ADD(ETH_P_DNA_RT,dna_rt) 00620 __ADD(ETH_P_LAT,lat) 00621 __ADD(ETH_P_DIAG,diag) 00622 __ADD(ETH_P_CUST,cust) 00623 __ADD(ETH_P_SCA,sca) 00624 __ADD(ETH_P_RARP,rarp) 00625 __ADD(ETH_P_ATALK,atalk) 00626 __ADD(ETH_P_AARP,aarp) 00627 #ifdef ETH_P_8021Q 00628 __ADD(ETH_P_8021Q,802.1q) 00629 #endif 00630 __ADD(ETH_P_IPX,ipx) 00631 __ADD(ETH_P_IPV6,ipv6) 00632 #ifdef ETH_P_WCCP 00633 __ADD(ETH_P_WCCP,wccp) 00634 #endif 00635 __ADD(ETH_P_PPP_DISC,ppp_disc) 00636 __ADD(ETH_P_PPP_SES,ppp_ses) 00637 __ADD(ETH_P_MPLS_UC,mpls_uc) 00638 __ADD(ETH_P_MPLS_MC,mpls_mc) 00639 __ADD(ETH_P_ATMMPOA,atmmpoa) 00640 __ADD(ETH_P_ATMFATE,atmfate) 00641 __ADD(ETH_P_EDP2,edp2) 00642 __ADD(ETH_P_802_3,802.3) 00643 __ADD(ETH_P_AX25,ax25) 00644 __ADD(ETH_P_ALL,all) 00645 __ADD(ETH_P_802_2,802.2) 00646 __ADD(ETH_P_SNAP,snap) 00647 __ADD(ETH_P_DDCMP,ddcmp) 00648 __ADD(ETH_P_WAN_PPP,wan_ppp) 00649 __ADD(ETH_P_PPP_MP,ppp_mp) 00650 __ADD(ETH_P_LOCALTALK,localtalk) 00651 __ADD(ETH_P_PPPTALK,ppptalk) 00652 __ADD(ETH_P_TR_802_2,tr_802.2) 00653 __ADD(ETH_P_MOBITEX,mobitex) 00654 __ADD(ETH_P_CONTROL,control) 00655 __ADD(ETH_P_IRDA,irda) 00656 __ADD(ETH_P_ECONET,econet) 00657 __ADD(ETH_P_HDLC,hdlc) 00658 }; 00659 00660 char *nl_ether_proto2str(int eproto, char *buf, size_t len) 00661 { 00662 return __type2str(eproto, buf, len, ether_protos, 00663 ARRAY_SIZE(ether_protos)); 00664 } 00665 00666 int nl_str2ether_proto(const char *name) 00667 { 00668 return __str2type(name, ether_protos, ARRAY_SIZE(ether_protos)); 00669 } 00670 00671 /** @} */ 00672 00673 /** 00674 * @name IP Protocol Translations 00675 * @{ 00676 */ 00677 00678 char *nl_ip_proto2str(int proto, char *buf, size_t len) 00679 { 00680 struct protoent *p = getprotobynumber(proto); 00681 00682 if (p) { 00683 snprintf(buf, len, "%s", p->p_name); 00684 return buf; 00685 } 00686 00687 snprintf(buf, len, "0x%x", proto); 00688 return buf; 00689 } 00690 00691 int nl_str2ip_proto(const char *name) 00692 { 00693 struct protoent *p = getprotobyname(name); 00694 unsigned long l; 00695 char *end; 00696 00697 if (p) 00698 return p->p_proto; 00699 00700 l = strtoul(name, &end, 0); 00701 if (l == ULONG_MAX || *end != '\0') 00702 return -1; 00703 00704 return (int) l; 00705 } 00706 00707 /** @} */ 00708 00709 /** 00710 * @name Dumping Helpers 00711 * @{ 00712 */ 00713 00714 /** 00715 * Handle a new line while dumping 00716 * @arg params Dumping parameters 00717 * @arg line Number of lines dumped already. 00718 * 00719 * This function must be called before dumping any onto a 00720 * new line. It will ensure proper prefixing as specified 00721 * by the dumping parameters. 00722 * 00723 * @note This function will NOT dump any newlines itself 00724 */ 00725 void nl_new_line(struct nl_dump_params *params, int line) 00726 { 00727 if (params->dp_prefix) { 00728 int i; 00729 for (i = 0; i < params->dp_prefix; i++) { 00730 if (params->dp_fd) 00731 fprintf(params->dp_fd, " "); 00732 else if (params->dp_buf) 00733 strncat(params->dp_buf, " ", 00734 params->dp_buflen - 00735 sizeof(params->dp_buf) - 1); 00736 } 00737 } 00738 00739 if (params->dp_nl_cb) 00740 params->dp_nl_cb(params, line); 00741 } 00742 00743 /** 00744 * Dump a formatted character string 00745 * @arg params Dumping parameters 00746 * @arg fmt printf style formatting string 00747 * @arg ... Arguments to formatting string 00748 * 00749 * Dumps a printf style formatting string to the output device 00750 * as specified by the dumping parameters. 00751 */ 00752 void nl_dump(struct nl_dump_params *params, const char *fmt, ...) 00753 { 00754 va_list args; 00755 00756 va_start(args, fmt); 00757 __dp_dump(params, fmt, args); 00758 va_end(args); 00759 } 00760 00761 /** @} */ 00762 00763 /** @} */