📄 dhcp-util.c
字号:
/* $Header: /cvsroot/dhcp-agent/dhcp-agent/src/dhcp-util.c,v 1.17 2003/07/02 15:18:22 actmodern Exp $ * * Copyright 2002 Thamer Alharbash * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. The names of the authors may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Utility routines. * */#define MODULE_NAME "dhcp-util"#include "dhcp-local.h"#include "dhcp-libutil.h"#include "dhcp-log.h"static uint8_t interactive = 1;static int verbosity_level = NORMAL_VERBOSITY_LEVEL;/* * * * * * * * * * * * message routines * * * * * * * * * * * *//* set the verbosity level. */int set_verbosity_level(int verbosity_level_to_set){ /* return error if verbosity level is out of bounds. */ if(verbosity_level_to_set < 0 || verbosity_level_to_set > MAX_VERBOSITY_LEVEL) return 1; verbosity_level = verbosity_level_to_set; return 0;}/* get the current verbosity level. */int get_verbosity_level(void){ return verbosity_level;}/* append with colon seperation -- utility routine for message_proc. */static void message_append_colon_sep(stringbuffer_t *sb, const char *str){ if(str != NULL) stringbuffer_aprintf(sb, "%s : ", str); return;}/* message proc workhorse */static void message_proc(const char *prefix, const char *module_name, const char *func_name, const char *file, const char *fmt, va_list ap){ static stringbuffer_t *prefix_sb = NULL; static stringbuffer_t *msg_sb = NULL; const char *ptr = NULL; if(msg_sb == NULL) msg_sb = stringbuffer_create(); if(prefix_sb == NULL) prefix_sb = stringbuffer_create(); stringbuffer_clear(msg_sb); stringbuffer_clear(prefix_sb); /* print prefix, module_name, func_name, file, line if they exist and make them colon seperated. */ message_append_colon_sep(prefix_sb, prefix); message_append_colon_sep(prefix_sb, module_name); message_append_colon_sep(prefix_sb, func_name); message_append_colon_sep(prefix_sb, file); stringbuffer_avprintf(msg_sb, fmt, ap); stringbuffer_align(msg_sb, 10, MESSAGE_LINE_LENGTH - strlen(getprogname())); stringbuffer_marknewlines(msg_sb); if(interactive == 1) { if(stringbuffer_getlen(prefix_sb)) /* only print prefix on first line if it is available. */ fprintf(stderr, "%s : %s\n", getprogname(), stringbuffer_getstring(prefix_sb)); while((ptr = stringbuffer_getnextline(msg_sb, ptr)) != NULL) fprintf(stderr, "%s : %s\n", getprogname(), ptr); } else { while((ptr = stringbuffer_getnextline(msg_sb, ptr)) != NULL) error_log(ptr); } return;}/* send error message. */void error_message(const char *func_name, const char *fmt, ...){ va_list ap; if(get_verbosity_level() == QUIET_VERBOSITY_LEVEL) return; va_start(ap, fmt); message_proc("error", NULL, func_name, NULL, fmt, ap); va_end(ap); return;}/* send error message and exit. (convenience) */void fatal_message(const char *func_name, const char *fmt, ...){ va_list ap; if(get_verbosity_level() == QUIET_VERBOSITY_LEVEL) return; va_start(ap, fmt); message_proc("fatal", NULL, func_name, NULL, fmt, ap); va_end(ap); exit(1);}/* send info message */void info_message(const char *fmt, ...){ va_list ap; if(get_verbosity_level() < NORMAL_VERBOSITY_LEVEL) return; va_start(ap, fmt); message_proc(NULL, NULL, NULL, NULL, fmt, ap); va_end(ap); return;}/* send warning messages: includes diagnostics. */void warn_message(char *fmt, ...){ va_list ap; if(get_verbosity_level() < WARNING_VERBOSITY_LEVEL) return; va_start(ap, fmt); message_proc("warning", NULL, NULL, NULL, fmt, ap); va_end(ap); return;}/* send debug message. */void debug_message(const char *module_name, const char *func, const char *file, const char *fmt, ...){ va_list ap; if(get_verbosity_level() < DEBUG_VERBOSITY_LEVEL) return; va_start(ap, fmt); message_proc("debug", module_name, func, file, fmt, ap); va_end(ap); return;}void set_interactive(uint8_t interactive_arg){ /* set to 1 or 0. */ interactive = interactive_arg; return;}/* * * * * * * * * * * * * * * * * * * * * dynamic memory allocation wrappers. * * * * * * * * * * * * * * * * * * * * */void *xmalloc(size_t size){ void *p; p = malloc(size); if(p == NULL) FATAL_MESSAGE("could not allocate memory! aborting!"); return p;}void *xcalloc(size_t size){ void *p;#ifdef HAVE_CALLOC p = calloc(1, size); if(p == NULL) FATAL_MESSAGE("could not allocate memory! aborting!");#else p = xmalloc(size); /* error handled by xmalloc */ memset(p, 0, size);#endif return p;}void *xrealloc(void *p, size_t size){ p = realloc(p, size); if(p == NULL) FATAL_MESSAGE("could not allocate memory! aborting!"); return p;}void xfree(void *p){ free(p); return;}/* * * * * * * * * * * * string routines. * * most of these * * need to die. * * * * * * * * * * * */#ifndef HAVE_STRDUPchar *strdup(const char *s){ char *newstring; int len = strlen(s); newstring = xmalloc(len + 1); strncpy(newstring, s, len); newstring[len] = '\0'; return newstring;}#endif/* strdup wrapper -- although our replacement strdup never * returns NULL we use the system's strdup if its available. * here we'll exit on failure irregardless of which strdup we * wind up using. */char *xstrdup(const char *string){ char *s = strdup(string); if(s == NULL) FATAL_MESSAGE("could not allocate memory! aborting!"); return s;}/* String routines. *//* * Splice two strings together. * */char *splice_string(const char *s1, const char *s2){ char *new_string; if(s1 == NULL) return (strdup(s2)); if(s2 == NULL) return (strdup(s1)); new_string = xmalloc(strlen(s1) + strlen(s2) + 1); strcpy(new_string, s1); strcat(new_string, s2); return new_string;}/* splice many strings lets us pass a variable amount of strings to be spliced. */char *splice_many_strings(int num, char *string, ...){ va_list ap; char *s, *tmp; char *new_string; new_string = xstrdup(string); if(num <= 1) return new_string; /* be nice to stupid callers. */ va_start(ap, string); while(num--) { s = va_arg(ap, char *); tmp = new_string; new_string = splice_string(new_string, s); xfree(tmp); } va_end(ap); return new_string;}/* is a valid C string? */int is_string(const char *string, int len){ const char *cp; int i = 0; cp = string; while(i < len) { if(*cp == '\0') return 1; i++; cp++; } return 0;}/* parse hex string (0x:0x...0x) to value. (not fun to write) */int hex_string_to_value(const char *string, unsigned char *dst){ char *sep, *ptr; char *new_string; char *val_string; int len, i; len = strlen(string); if(len < 17) return -1; if(len == 17) new_string = splice_string(string, ":"); else new_string = xstrdup(string); if(strlen(new_string) > 18) { xfree(new_string); return -1; } i = 0; ptr = new_string; while((sep = strchr(ptr, ':')) != NULL) { *sep = 0; val_string = splice_string(" ", ptr); dst[i] = strtoul(val_string, NULL, 16); xfree(val_string); i++; ptr = sep + 1; } xfree(new_string); return 0;}/* * * * * * * * * * * * * * * * * * simple check routines. * * use these for types checking * * and other similar checks. * * * * * * * * * * * * * * * * * *//* check for seven bit cleanliness. */int is_seven_bit_clean(const char *data, int len){ int i; const unsigned char *ptr = data; for(i = 0; i < len; i++) { if(ptr[i] >= 128) return 0; } return 1;}/* is numeric */int is_unsigned_numeric(const char *string){ const char *ptr; for(ptr = string; *ptr; ptr++) { if(!isdigit((int)*ptr)) return 0; } return 1;}/* is numeric */int is_signed_numeric(const char *string){ const char *ptr; /* check for a prefix '-' character */ for(ptr = string; *ptr; ptr++) { if(*ptr == '-') break; else if(isdigit((int)*ptr)) break; else return 0; } for(; *ptr; ptr++) { if(!isdigit((int)*ptr)) return 0; } return 1;}/* * * * * * * * * * * * * * * * * * * * * Random number generation. * * We're interfacing into dnet's code * * here. * * * * * * * * * * * * * * * * * * * * */static rand_t *ran_gen = NULL;/* initialize random seed. */static void init_rand(void){ if(ran_gen == NULL) if((ran_gen = rand_open()) == NULL) FATAL_MESSAGE("unable to access random number generator"); return;}uint16_t get_random_uint16(void){ init_rand(); /* reinit if needed. */ return (rand_uint16(ran_gen));}uint32_t get_random_uint32(void){ init_rand(); /* reinit if needed. */ return (rand_uint32(ran_gen));}/* timeval difference. */struct timeval timeval_diff(struct timeval begin, struct timeval end){ struct timeval difference; if(begin.tv_usec > end.tv_usec) { end.tv_sec--; end.tv_usec += 1000000; } difference.tv_sec = end.tv_sec - begin.tv_sec; difference.tv_usec = end.tv_usec - begin.tv_usec; return difference;}#if !defined(HAVE_GETPROGNAME)const char *getprogname(void){ /* * Compatibility looks like this: * if getprogname this will not be. * if __progname is available use it here. * if __progname is not available set it in main source, * and use it here. */ /* FIXME: do the system provided getprogname() do this? */ if(__progname[0] == '.' && __progname[1] == '/') return (__progname + 2); else return (__progname);}#endif /* HAVE_GETPROGNAME *//* convert a string ip to ip_addr_t */ip_addr_t *string_ip_to_ip_addr(const char *string_ip){ ip_addr_t *ip; ip = xmalloc(sizeof(ip_addr_t)); /* FIXME: use inet_aton if available */ *(ip) = inet_addr(string_ip); if(*(ip) == INADDR_NONE) { xfree(ip); return NULL; } return ip;}/* convert a string ip to ip_addr_t */eth_addr_t *string_eth_addr_to_eth_addr(const char *eth_addr){ eth_addr_t *eth; eth = xmalloc(sizeof(eth_addr_t)); if(hex_string_to_value(eth_addr, eth->data)) { xfree(eth); return NULL; } return eth;}/* convert an ethernet address to a string and return a copy. */char *eth_addr_to_string(eth_addr_t eth_addr){ char *string; stringbuffer_t *sb; sb = stringbuffer_create(); stringbuffer_aprintf(sb, "%x:%x:%x:%x:%x:%x", eth_addr.data[0], eth_addr.data[1], eth_addr.data[2], eth_addr.data[3], eth_addr.data[4], eth_addr.data[5]); string = xstrdup(stringbuffer_getstring(sb)); stringbuffer_destroy(sb); return string;}/* convert an ip address to a string and return a copy. */char *ip_addr_to_string(ip_addr_t ip_addr){ char *string; char *ip_string; struct in_addr in_addr; in_addr.s_addr = ip_addr; ip_string = inet_ntoa(in_addr); string = xstrdup(ip_string); return string;}void sleep_random(uint16_t max_sleep){ sleep((get_random_uint16()%(max_sleep + 1)) + 1);}/* change int our working directory. */void do_change_work_dir(const char *work_dir){ /* Switch into our work directory */ if(!file_permissions_are(work_dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)) { FATAL_MESSAGE("wrong permissions on work directory: %s (use rwx only for owner)", work_dir); } if(chdir(work_dir) < 0) FATAL_MESSAGE("cannot enter work directory", work_dir); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -