forked from AllenDowney/ExercisesInC
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8ea9ceb
commit 90477ed
Showing
1 changed file
with
284 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,284 @@ | ||
#include "util.h" | ||
|
||
void err_doit (int errnoflag, int level, char *fmt, va_list ap) | ||
{ | ||
int errno_save, n; | ||
char buf[MAXLINE]; | ||
|
||
errno_save = errno; /* value caller might want printed */ | ||
vsnprintf (buf, sizeof(buf), fmt, ap); | ||
n = strnlen (buf, MAXLINE); | ||
if (errnoflag) | ||
snprintf (buf+n, sizeof(buf) - n, ": %s", strerror(errno_save)); | ||
strcat (buf, "\n"); | ||
|
||
fflush (stdout); | ||
fputs (buf, stderr); | ||
fflush (stderr); | ||
} | ||
|
||
void err_sys (char *fmt, ...) | ||
{ | ||
va_list ap; | ||
va_start (ap, fmt); | ||
err_doit (1, LOG_ERR, fmt, ap); | ||
va_end(ap); | ||
exit(1); | ||
} | ||
|
||
void err_quit (char *fmt, ...) | ||
{ | ||
va_list ap; | ||
va_start (ap, fmt); | ||
err_doit (0, LOG_ERR, fmt, ap); | ||
va_end(ap); | ||
exit(1); | ||
} | ||
|
||
char *sock_ntop_host(const struct sockaddr *sa, socklen_t salen) | ||
{ | ||
static char str[128]; | ||
|
||
switch (sa->sa_family) { | ||
case AF_INET: { | ||
struct sockaddr_in *sin = (struct sockaddr_in *) sa; | ||
|
||
if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) { | ||
return NULL; | ||
} else { | ||
return str; | ||
} | ||
} | ||
case AF_UNIX: { | ||
struct sockaddr_un *unp = (struct sockaddr_un *) sa; | ||
|
||
/* OK to have no pathname bound to the socket: happens on | ||
every connect() unless client calls bind() first. */ | ||
if (unp->sun_path[0] == 0) | ||
strcpy(str, "(no pathname bound)"); | ||
else | ||
snprintf(str, sizeof(str), "%s", unp->sun_path); | ||
return str; | ||
} | ||
default: | ||
snprintf(str, sizeof(str), "sock_ntop_host: unknown AF_xxx: %d, len %d", | ||
sa->sa_family, salen); | ||
return str; | ||
} | ||
return NULL; | ||
} | ||
|
||
char *Sock_ntop_host(const struct sockaddr *sa, socklen_t salen) | ||
{ | ||
char *ptr; | ||
|
||
if ( (ptr = sock_ntop_host(sa, salen)) == NULL) | ||
err_sys("sock_ntop_host error"); /* inet_ntop() sets errno */ | ||
return(ptr); | ||
} | ||
|
||
void sock_set_port(struct sockaddr *sa, socklen_t salen, int port) | ||
{ | ||
switch (sa->sa_family) { | ||
case AF_INET: { | ||
struct sockaddr_in *sin = (struct sockaddr_in *) sa; | ||
|
||
sin->sin_port = port; | ||
return; | ||
} | ||
return; | ||
} | ||
} | ||
|
||
int sock_cmp_addr(const struct sockaddr *sa1, const struct sockaddr *sa2, | ||
socklen_t salen) | ||
{ | ||
if (sa1->sa_family != sa2->sa_family) | ||
return(-1); | ||
|
||
switch (sa1->sa_family) { | ||
case AF_INET: { | ||
return(memcmp( &((struct sockaddr_in *) sa1)->sin_addr, | ||
&((struct sockaddr_in *) sa2)->sin_addr, | ||
sizeof(struct in_addr))); | ||
} | ||
|
||
case AF_UNIX: { | ||
return(strcmp( ((struct sockaddr_un *) sa1)->sun_path, | ||
((struct sockaddr_un *) sa2)->sun_path)); | ||
} | ||
} | ||
return -1; | ||
} | ||
|
||
void tv_sub (struct timeval *out, struct timeval *in) | ||
{ | ||
if ( (out->tv_usec -= in->tv_usec) < 0) { /* out -= in */ | ||
--out->tv_sec; | ||
out->tv_usec += 1000000; | ||
} | ||
out->tv_sec -= in->tv_sec; | ||
} | ||
|
||
char *icmpcode_v4(int code) | ||
{ | ||
switch (code) { | ||
case 0: return("network unreachable"); | ||
case 1: return("host unreachable"); | ||
case 2: return("protocol unreachable"); | ||
case 3: return("port unreachable"); | ||
case 4: return("fragmentation required but DF bit set"); | ||
case 5: return("source route failed"); | ||
case 6: return("destination network unknown"); | ||
case 7: return("destination host unknown"); | ||
case 8: return("source host isolated (obsolete)"); | ||
case 9: return("destination network administratively prohibited"); | ||
case 10: return("destination host administratively prohibited"); | ||
case 11: return("network unreachable for TOS"); | ||
case 12: return("host unreachable for TOS"); | ||
case 13: return("communication administratively prohibited by filtering"); | ||
case 14: return("host recedence violation"); | ||
case 15: return("precedence cutoff in effect"); | ||
default: return("[unknown code]"); | ||
} | ||
} | ||
|
||
Sigfunc *signal(int signo, Sigfunc *func) | ||
{ | ||
struct sigaction act, oact; | ||
|
||
act.sa_handler = func; | ||
sigemptyset(&act.sa_mask); | ||
act.sa_flags = 0; | ||
if (signo == SIGALRM) { | ||
act.sa_flags |= SA_INTERRUPT; /* SunOS 4.x (and Linux, apparently) */ | ||
} | ||
if (sigaction(signo, &act, &oact) < 0) | ||
return(SIG_ERR); | ||
return(oact.sa_handler); | ||
} | ||
|
||
Sigfunc *Signal(int signo, Sigfunc *func) /* for our signal() function */ | ||
{ | ||
Sigfunc *sigfunc; | ||
|
||
if ( (sigfunc = signal(signo, func)) == SIG_ERR) | ||
err_sys("signal error"); | ||
return(sigfunc); | ||
} | ||
|
||
void *Malloc(size_t size) | ||
{ | ||
void *ptr; | ||
|
||
if ( (ptr = malloc(size)) == NULL) | ||
err_sys("malloc error"); | ||
return(ptr); | ||
} | ||
|
||
void *Calloc(size_t n, size_t size) | ||
{ | ||
void *ptr; | ||
|
||
if ( (ptr = calloc(n, size)) == NULL) | ||
err_sys("calloc error"); | ||
return(ptr); | ||
} | ||
|
||
void Gettimeofday(struct timeval *tv, void *foo) | ||
{ | ||
if (gettimeofday(tv, foo) == -1) | ||
err_sys("gettimeofday error"); | ||
return; | ||
} | ||
|
||
void Pipe(int *fds) | ||
{ | ||
if (pipe(fds) < 0) | ||
err_sys("pipe error"); | ||
} | ||
|
||
void Bind(int fd, const struct sockaddr *sa, socklen_t salen) | ||
{ | ||
if (bind(fd, sa, salen) < 0) | ||
err_sys("bind error"); | ||
} | ||
|
||
void Setsockopt(int fd, int level, int optname, const void *optval, | ||
socklen_t optlen) | ||
{ | ||
if (setsockopt(fd, level, optname, optval, optlen) < 0) | ||
err_sys("setsockopt error"); | ||
} | ||
|
||
struct addrinfo * | ||
host_serv (char *host, char *serv, int family, int socktype) | ||
{ | ||
int n; | ||
struct addrinfo hints, *res; | ||
|
||
bzero (&hints, sizeof(struct addrinfo)); | ||
hints.ai_flags = AI_CANONNAME; /* return canonical name */ | ||
hints.ai_family = family; | ||
hints.ai_socktype = socktype; | ||
|
||
n = getaddrinfo (host, serv, &hints, &res); | ||
if (n != 0) { | ||
return NULL; | ||
} else { | ||
return res; /* return pointer to first on linked list */ | ||
} | ||
} | ||
|
||
/* | ||
* There is no easy way to pass back the integer return code from | ||
* getaddrinfo() in the function above, short of adding another argument | ||
* that is a pointer, so the easiest way to provide the wrapper function | ||
* is just to duplicate the simple function as we do here. | ||
*/ | ||
|
||
struct addrinfo * | ||
Host_serv(const char *host, const char *serv, int family, int socktype) | ||
{ | ||
int n; | ||
struct addrinfo hints, *res; | ||
|
||
bzero(&hints, sizeof(struct addrinfo)); | ||
hints.ai_flags = AI_CANONNAME; /* always return canonical name */ | ||
hints.ai_family = family; /* 0, AF_INET, AF_INET6, etc. */ | ||
hints.ai_socktype = socktype; /* 0, SOCK_STREAM, SOCK_DGRAM, etc. */ | ||
|
||
if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) | ||
err_quit("host_serv error for %s, %s: %s", | ||
(host == NULL) ? "(no hostname)" : host, | ||
(serv == NULL) ? "(no service name)" : serv, | ||
gai_strerror(n)); | ||
|
||
return(res); /* return pointer to first on linked list */ | ||
} | ||
|
||
ssize_t Read(int fd, void *ptr, size_t nbytes) | ||
{ | ||
ssize_t n; | ||
|
||
if ( (n = read(fd, ptr, nbytes)) == -1) | ||
err_sys("read error"); | ||
return(n); | ||
} | ||
|
||
void Write(int fd, void *ptr, size_t nbytes) | ||
{ | ||
if (write(fd, ptr, nbytes) != nbytes) | ||
err_sys("write error"); | ||
} | ||
|
||
ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags, | ||
struct sockaddr *sa, socklen_t *salenptr) | ||
{ | ||
ssize_t n; | ||
|
||
n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr); | ||
if (n < 0) | ||
err_sys("recvfrom error"); | ||
return(n); | ||
} |