Created
February 10, 2017 20:34
-
-
Save beefy/430b3e416a2c58f8ca7b8ee9543247fc to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/* $begin csapp.c */ | |
#include "csapp.h" | |
/************************** | |
* Error-handling functions | |
**************************/ | |
/* $begin errorfuns */ | |
/* $begin unixerror */ | |
void unix_error(char *msg) /* unix-style error */ | |
{ | |
fprintf(stderr, "%s: %s\n", msg, strerror(errno)); | |
exit(0); | |
} | |
/* $end unixerror */ | |
void posix_error(int code, char *msg) /* posix-style error */ | |
{ | |
fprintf(stderr, "%s: %s\n", msg, strerror(code)); | |
exit(0); | |
} | |
void dns_error(char *msg) /* dns-style error */ | |
{ | |
fprintf(stderr, "%s: DNS error %d\n", msg, h_errno); | |
exit(0); | |
} | |
void app_error(char *msg) /* application error */ | |
{ | |
fprintf(stderr, "%s\n", msg); | |
exit(0); | |
} | |
/* $end errorfuns */ | |
/********************************************* | |
* Wrappers for Unix process control functions | |
********************************************/ | |
/* $begin forkwrapper */ | |
pid_t Fork(void) | |
{ | |
pid_t pid; | |
if ((pid = fork()) < 0) | |
unix_error("Fork error"); | |
return pid; | |
} | |
/* $end forkwrapper */ | |
void Execve(const char *filename, char *const argv[], char *const envp[]) | |
{ | |
if (execve(filename, argv, envp) < 0) | |
unix_error("Execve error"); | |
} | |
/* $begin wait */ | |
pid_t Wait(int *status) | |
{ | |
pid_t pid; | |
if ((pid = wait(status)) < 0) | |
unix_error("Wait error"); | |
return pid; | |
} | |
/* $end wait */ | |
pid_t Waitpid(pid_t pid, int *iptr, int options) | |
{ | |
pid_t retpid; | |
if ((retpid = waitpid(pid, iptr, options)) < 0) | |
unix_error("Waitpid error"); | |
return(retpid); | |
} | |
/* $begin kill */ | |
void Kill(pid_t pid, int signum) | |
{ | |
int rc; | |
if ((rc = kill(pid, signum)) < 0) | |
unix_error("Kill error"); | |
} | |
/* $end kill */ | |
void Pause() | |
{ | |
(void)pause(); | |
return; | |
} | |
unsigned int Sleep(unsigned int secs) | |
{ | |
unsigned int rc; | |
if ((rc = sleep(secs)) < 0) | |
unix_error("Sleep error"); | |
return rc; | |
} | |
unsigned int Alarm(unsigned int seconds) { | |
return alarm(seconds); | |
} | |
void Setpgid(pid_t pid, pid_t pgid) { | |
int rc; | |
if ((rc = setpgid(pid, pgid)) < 0) | |
unix_error("Setpgid error"); | |
return; | |
} | |
pid_t Getpgrp(void) { | |
return getpgrp(); | |
} | |
/************************************ | |
* Wrappers for Unix signal functions | |
***********************************/ | |
/* $begin sigaction */ | |
handler_t *Signal(int signum, handler_t *handler) | |
{ | |
struct sigaction action, old_action; | |
action.sa_handler = handler; | |
sigemptyset(&action.sa_mask); /* block sigs of type being handled */ | |
action.sa_flags = SA_RESTART; /* restart syscalls if possible */ | |
if (sigaction(signum, &action, &old_action) < 0) | |
unix_error("Signal error"); | |
return (old_action.sa_handler); | |
} | |
/* $end sigaction */ | |
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset) | |
{ | |
if (sigprocmask(how, set, oldset) < 0) | |
unix_error("Sigprocmask error"); | |
return; | |
} | |
void Sigemptyset(sigset_t *set) | |
{ | |
if (sigemptyset(set) < 0) | |
unix_error("Sigemptyset error"); | |
return; | |
} | |
void Sigfillset(sigset_t *set) | |
{ | |
if (sigfillset(set) < 0) | |
unix_error("Sigfillset error"); | |
return; | |
} | |
void Sigaddset(sigset_t *set, int signum) | |
{ | |
if (sigaddset(set, signum) < 0) | |
unix_error("Sigaddset error"); | |
return; | |
} | |
void Sigdelset(sigset_t *set, int signum) | |
{ | |
if (sigdelset(set, signum) < 0) | |
unix_error("Sigdelset error"); | |
return; | |
} | |
int Sigismember(const sigset_t *set, int signum) | |
{ | |
int rc; | |
if ((rc = sigismember(set, signum)) < 0) | |
unix_error("Sigismember error"); | |
return rc; | |
} | |
/******************************** | |
* Wrappers for Unix I/O routines | |
********************************/ | |
int Open(const char *pathname, int flags, mode_t mode) | |
{ | |
int rc; | |
if ((rc = open(pathname, flags, mode)) < 0) | |
unix_error("Open error"); | |
return rc; | |
} | |
ssize_t Read(int fd, void *buf, size_t count) | |
{ | |
ssize_t rc; | |
if ((rc = read(fd, buf, count)) < 0) | |
unix_error("Read error"); | |
return rc; | |
} | |
ssize_t Write(int fd, const void *buf, size_t count) | |
{ | |
ssize_t rc; | |
if ((rc = write(fd, buf, count)) < 0) | |
unix_error("Write error"); | |
return rc; | |
} | |
off_t Lseek(int fildes, off_t offset, int whence) | |
{ | |
off_t rc; | |
if ((rc = lseek(fildes, offset, whence)) < 0) | |
unix_error("Lseek error"); | |
return rc; | |
} | |
void Close(int fd) | |
{ | |
int rc; | |
if ((rc = close(fd)) < 0) | |
unix_error("Close error"); | |
} | |
int Select(int n, fd_set *readfds, fd_set *writefds, | |
fd_set *exceptfds, struct timeval *timeout) | |
{ | |
int rc; | |
if ((rc = select(n, readfds, writefds, exceptfds, timeout)) < 0) | |
unix_error("Select error"); | |
return rc; | |
} | |
int Dup2(int fd1, int fd2) | |
{ | |
int rc; | |
if ((rc = dup2(fd1, fd2)) < 0) | |
unix_error("Dup2 error"); | |
return rc; | |
} | |
void Stat(const char *filename, struct stat *buf) | |
{ | |
if (stat(filename, buf) < 0) | |
unix_error("Stat error"); | |
} | |
void Fstat(int fd, struct stat *buf) | |
{ | |
if (fstat(fd, buf) < 0) | |
unix_error("Fstat error"); | |
} | |
/*************************************** | |
* Wrappers for memory mapping functions | |
***************************************/ | |
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) | |
{ | |
void *ptr; | |
if ((ptr = mmap(addr, len, prot, flags, fd, offset)) == ((void *) -1)) | |
unix_error("mmap error"); | |
return(ptr); | |
} | |
void Munmap(void *start, size_t length) | |
{ | |
if (munmap(start, length) < 0) | |
unix_error("munmap error"); | |
} | |
/*************************************************** | |
* Wrappers for dynamic storage allocation functions | |
***************************************************/ | |
void *Malloc(size_t size) | |
{ | |
void *p; | |
if ((p = malloc(size)) == NULL) | |
unix_error("Malloc error"); | |
return p; | |
} | |
void *Realloc(void *ptr, size_t size) | |
{ | |
void *p; | |
if ((p = realloc(ptr, size)) == NULL) | |
unix_error("Realloc error"); | |
return p; | |
} | |
void *Calloc(size_t nmemb, size_t size) | |
{ | |
void *p; | |
if ((p = calloc(nmemb, size)) == NULL) | |
unix_error("Calloc error"); | |
return p; | |
} | |
void Free(void *ptr) | |
{ | |
free(ptr); | |
} | |
/****************************************** | |
* Wrappers for the Standard I/O functions. | |
******************************************/ | |
void Fclose(FILE *fp) | |
{ | |
if (fclose(fp) != 0) | |
unix_error("Fclose error"); | |
} | |
FILE *Fdopen(int fd, const char *type) | |
{ | |
FILE *fp; | |
if ((fp = fdopen(fd, type)) == NULL) | |
unix_error("Fdopen error"); | |
return fp; | |
} | |
char *Fgets(char *ptr, int n, FILE *stream) | |
{ | |
char *rptr; | |
if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream)) | |
app_error("Fgets error"); | |
return rptr; | |
} | |
FILE *Fopen(const char *filename, const char *mode) | |
{ | |
FILE *fp; | |
if ((fp = fopen(filename, mode)) == NULL) | |
unix_error("Fopen error"); | |
return fp; | |
} | |
void Fputs(const char *ptr, FILE *stream) | |
{ | |
if (fputs(ptr, stream) == EOF) | |
unix_error("Fputs error"); | |
} | |
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream) | |
{ | |
size_t n; | |
if (((n = fread(ptr, size, nmemb, stream)) < nmemb) && ferror(stream)) | |
unix_error("Fread error"); | |
return n; | |
} | |
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) | |
{ | |
if (fwrite(ptr, size, nmemb, stream) < nmemb) | |
unix_error("Fwrite error"); | |
} | |
/**************************** | |
* Sockets interface wrappers | |
****************************/ | |
int Socket(int domain, int type, int protocol) | |
{ | |
int rc; | |
if ((rc = socket(domain, type, protocol)) < 0) | |
unix_error("Socket error"); | |
return rc; | |
} | |
void Setsockopt(int s, int level, int optname, const void *optval, int optlen) | |
{ | |
int rc; | |
if ((rc = setsockopt(s, level, optname, optval, optlen)) < 0) | |
unix_error("Setsockopt error"); | |
} | |
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen) | |
{ | |
int rc; | |
if ((rc = bind(sockfd, my_addr, addrlen)) < 0) | |
unix_error("Bind error"); | |
} | |
void Listen(int s, int backlog) | |
{ | |
int rc; | |
if ((rc = listen(s, backlog)) < 0) | |
unix_error("Listen error"); | |
} | |
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen) | |
{ | |
int rc; | |
if ((rc = accept(s, addr, addrlen)) < 0) | |
unix_error("Accept error"); | |
return rc; | |
} | |
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen) | |
{ | |
int rc; | |
if ((rc = connect(sockfd, serv_addr, addrlen)) < 0) | |
unix_error("Connect error"); | |
} | |
/************************ | |
* DNS interface wrappers | |
***********************/ | |
/* $begin gethostbyname */ | |
struct hostent *Gethostbyname(const char *name) | |
{ | |
struct hostent *p; | |
if ((p = gethostbyname(name)) == NULL) | |
dns_error("Gethostbyname error"); | |
return p; | |
} | |
/* $end gethostbyname */ | |
struct hostent *Gethostbyaddr(const char *addr, int len, int type) | |
{ | |
struct hostent *p; | |
if ((p = gethostbyaddr(addr, len, type)) == NULL) | |
dns_error("Gethostbyaddr error"); | |
return p; | |
} | |
/************************************************ | |
* Wrappers for Pthreads thread control functions | |
************************************************/ | |
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp, | |
void * (*routine)(void *), void *argp) | |
{ | |
int rc; | |
if ((rc = pthread_create(tidp, attrp, routine, argp)) != 0) | |
posix_error(rc, "Pthread_create error"); | |
} | |
void Pthread_cancel(pthread_t tid) { | |
int rc; | |
if ((rc = pthread_cancel(tid)) != 0) | |
posix_error(rc, "Pthread_cancel error"); | |
} | |
void Pthread_join(pthread_t tid, void **thread_return) { | |
int rc; | |
if ((rc = pthread_join(tid, thread_return)) != 0) | |
posix_error(rc, "Pthread_join error"); | |
} | |
/* $begin detach */ | |
void Pthread_detach(pthread_t tid) { | |
int rc; | |
if ((rc = pthread_detach(tid)) != 0) | |
posix_error(rc, "Pthread_detach error"); | |
} | |
/* $end detach */ | |
void Pthread_exit(void *retval) { | |
pthread_exit(retval); | |
} | |
pthread_t Pthread_self(void) { | |
return pthread_self(); | |
} | |
void Pthread_once(pthread_once_t *once_control, void (*init_function)()) { | |
pthread_once(once_control, init_function); | |
} | |
/******************************* | |
* Wrappers for Posix semaphores | |
*******************************/ | |
void Sem_init(sem_t *sem, int pshared, unsigned int value) | |
{ | |
if (sem_init(sem, pshared, value) < 0) | |
unix_error("Sem_init error"); | |
} | |
void P(sem_t *sem) | |
{ | |
if (sem_wait(sem) < 0) | |
unix_error("P error"); | |
} | |
void V(sem_t *sem) | |
{ | |
if (sem_post(sem) < 0) | |
unix_error("V error"); | |
} | |
/********************************************************************* | |
* The Rio package - robust I/O functions | |
**********************************************************************/ | |
/* | |
* rio_readn - robustly read n bytes (unbuffered) | |
*/ | |
/* $begin rio_readn */ | |
ssize_t rio_readn(int fd, void *usrbuf, size_t n) | |
{ | |
size_t nleft = n; | |
ssize_t nread; | |
char *bufp = usrbuf; | |
while (nleft > 0) { | |
if ((nread = read(fd, bufp, nleft)) < 0) { | |
if (errno == EINTR) /* interrupted by sig handler return */ | |
nread = 0; /* and call read() again */ | |
else | |
return -1; /* errno set by read() */ | |
} | |
else if (nread == 0) | |
break; /* EOF */ | |
nleft -= nread; | |
bufp += nread; | |
} | |
return (n - nleft); /* return >= 0 */ | |
} | |
/* $end rio_readn */ | |
/* | |
* rio_writen - robustly write n bytes (unbuffered) | |
*/ | |
/* $begin rio_writen */ | |
ssize_t rio_writen(int fd, void *usrbuf, size_t n) | |
{ | |
size_t nleft = n; | |
ssize_t nwritten; | |
char *bufp = usrbuf; | |
while (nleft > 0) { | |
if ((nwritten = write(fd, bufp, nleft)) <= 0) { | |
if (errno == EINTR) /* interrupted by sig handler return */ | |
nwritten = 0; /* and call write() again */ | |
else | |
return -1; /* errorno set by write() */ | |
} | |
nleft -= nwritten; | |
bufp += nwritten; | |
} | |
return n; | |
} | |
/* $end rio_writen */ | |
/* | |
* rio_read - This is a wrapper for the Unix read() function that | |
* transfers min(n, rio_cnt) bytes from an internal buffer to a user | |
* buffer, where n is the number of bytes requested by the user and | |
* rio_cnt is the number of unread bytes in the internal buffer. On | |
* entry, rio_read() refills the internal buffer via a call to | |
* read() if the internal buffer is empty. | |
*/ | |
/* $begin rio_read */ | |
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n) | |
{ | |
int cnt; | |
while (rp->rio_cnt <= 0) { /* refill if buf is empty */ | |
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf, | |
sizeof(rp->rio_buf)); | |
if (rp->rio_cnt < 0) { | |
if (errno != EINTR) /* interrupted by sig handler return */ | |
return -1; | |
} | |
else if (rp->rio_cnt == 0) /* EOF */ | |
return 0; | |
else | |
rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */ | |
} | |
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */ | |
cnt = n; | |
if (rp->rio_cnt < n) | |
cnt = rp->rio_cnt; | |
memcpy(usrbuf, rp->rio_bufptr, cnt); | |
rp->rio_bufptr += cnt; | |
rp->rio_cnt -= cnt; | |
return cnt; | |
} | |
/* $end rio_read */ | |
/* | |
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer | |
*/ | |
/* $begin rio_readinitb */ | |
void rio_readinitb(rio_t *rp, int fd) | |
{ | |
rp->rio_fd = fd; | |
rp->rio_cnt = 0; | |
rp->rio_bufptr = rp->rio_buf; | |
} | |
/* $end rio_readinitb */ | |
/* | |
* rio_readnb - Robustly read n bytes (buffered) | |
*/ | |
/* $begin rio_readnb */ | |
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n) | |
{ | |
size_t nleft = n; | |
ssize_t nread; | |
char *bufp = usrbuf; | |
while (nleft > 0) { | |
if ((nread = rio_read(rp, bufp, nleft)) < 0) { | |
if (errno == EINTR) /* interrupted by sig handler return */ | |
nread = 0; /* call read() again */ | |
else | |
return -1; /* errno set by read() */ | |
} | |
else if (nread == 0) | |
break; /* EOF */ | |
nleft -= nread; | |
bufp += nread; | |
} | |
return (n - nleft); /* return >= 0 */ | |
} | |
/* $end rio_readnb */ | |
/* | |
* rio_readlineb - robustly read a text line (buffered) | |
*/ | |
/* $begin rio_readlineb */ | |
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen) | |
{ | |
int n, rc; | |
char c, *bufp = usrbuf; | |
for (n = 1; n < maxlen; n++) { | |
if ((rc = rio_read(rp, &c, 1)) == 1) { | |
*bufp++ = c; | |
if (c == '\n') | |
break; | |
} else if (rc == 0) { | |
if (n == 1) | |
return 0; /* EOF, no data read */ | |
else | |
break; /* EOF, some data was read */ | |
} else | |
return -1; /* error */ | |
} | |
*bufp = 0; | |
return n; | |
} | |
/* $end rio_readlineb */ | |
/********************************** | |
* Wrappers for robust I/O routines | |
**********************************/ | |
ssize_t Rio_readn(int fd, void *ptr, size_t nbytes) | |
{ | |
ssize_t n; | |
if ((n = rio_readn(fd, ptr, nbytes)) < 0) | |
unix_error("Rio_readn error"); | |
return n; | |
} | |
void Rio_writen(int fd, void *usrbuf, size_t n) | |
{ | |
if (rio_writen(fd, usrbuf, n) != n) | |
unix_error("Rio_writen error"); | |
} | |
void Rio_readinitb(rio_t *rp, int fd) | |
{ | |
rio_readinitb(rp, fd); | |
} | |
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n) | |
{ | |
ssize_t rc; | |
if ((rc = rio_readnb(rp, usrbuf, n)) < 0) | |
unix_error("Rio_readnb error"); | |
return rc; | |
} | |
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen) | |
{ | |
ssize_t rc; | |
if ((rc = rio_readlineb(rp, usrbuf, maxlen)) < 0) | |
unix_error("Rio_readlineb error"); | |
return rc; | |
} | |
/******************************** | |
* Client/server helper functions | |
********************************/ | |
/* | |
* open_clientfd - open connection to server at <hostname, port> | |
* and return a socket descriptor ready for reading and writing. | |
* Returns -1 and sets errno on Unix error. | |
* Returns -2 and sets h_errno on DNS (gethostbyname) error. | |
*/ | |
/* $begin open_clientfd */ | |
int open_clientfd(char *hostname, int port) | |
{ | |
int clientfd; | |
struct hostent *hp; | |
struct sockaddr_in serveraddr; | |
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) | |
return -1; /* check errno for cause of error */ | |
/* Fill in the server's IP address and port */ | |
if ((hp = gethostbyname(hostname)) == NULL) | |
return -2; /* check h_errno for cause of error */ | |
bzero((char *) &serveraddr, sizeof(serveraddr)); | |
serveraddr.sin_family = AF_INET; | |
bcopy((char *)hp->h_addr_list[0], | |
(char *)&serveraddr.sin_addr.s_addr, hp->h_length); | |
serveraddr.sin_port = htons(port); | |
/* Establish a connection with the server */ | |
if (connect(clientfd, (SA *) &serveraddr, sizeof(serveraddr)) < 0) | |
return -1; | |
return clientfd; | |
} | |
/* $end open_clientfd */ | |
/* | |
* open_listenfd - open and return a listening socket on port | |
* Returns -1 and sets errno on Unix error. | |
*/ | |
/* $begin open_listenfd */ | |
int open_listenfd(int port) | |
{ | |
int listenfd, optval=1; | |
struct sockaddr_in serveraddr; | |
/* Create a socket descriptor */ | |
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) | |
return -1; | |
/* Eliminates "Address already in use" error from bind. */ | |
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, | |
(const void *)&optval , sizeof(int)) < 0) | |
return -1; | |
/* Listenfd will be an endpoint for all requests to port | |
on any IP address for this host */ | |
bzero((char *) &serveraddr, sizeof(serveraddr)); | |
serveraddr.sin_family = AF_INET; | |
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); | |
serveraddr.sin_port = htons((unsigned short)port); | |
if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0) | |
return -1; | |
/* Make it a listening socket ready to accept connection requests */ | |
if (listen(listenfd, LISTENQ) < 0) | |
return -1; | |
return listenfd; | |
} | |
/* $end open_listenfd */ | |
/****************************************** | |
* Wrappers for the client/server helper routines | |
******************************************/ | |
int Open_clientfd(char *hostname, int port) | |
{ | |
int rc; | |
if ((rc = open_clientfd(hostname, port)) < 0) { | |
if (rc == -1) | |
unix_error("Open_clientfd Unix error"); | |
else | |
dns_error("Open_clientfd DNS error"); | |
} | |
return rc; | |
} | |
int Open_listenfd(int port) | |
{ | |
int rc; | |
if ((rc = open_listenfd(port)) < 0) | |
unix_error("Open_listenfd error"); | |
return rc; | |
} | |
/* $end csapp.c */ | |
This file contains hidden or 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
/* $begin csapp.h */ | |
#ifndef __CSAPP_H__ | |
#define __CSAPP_H__ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <ctype.h> | |
#include <setjmp.h> | |
#include <signal.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <sys/mman.h> | |
#include <errno.h> | |
#include <math.h> | |
#include <pthread.h> | |
#include <semaphore.h> | |
#include <sys/socket.h> | |
#include <netdb.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
/* Default file permissions are DEF_MODE & ~DEF_UMASK */ | |
/* $begin createmasks */ | |
#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH | |
#define DEF_UMASK S_IWGRP|S_IWOTH | |
/* $end createmasks */ | |
/* Simplifies calls to bind(), connect(), and accept() */ | |
/* $begin sockaddrdef */ | |
typedef struct sockaddr SA; | |
/* $end sockaddrdef */ | |
/* Persistent state for the robust I/O (Rio) package */ | |
/* $begin rio_t */ | |
#define RIO_BUFSIZE 8192 | |
typedef struct { | |
int rio_fd; /* descriptor for this internal buf */ | |
int rio_cnt; /* unread bytes in internal buf */ | |
char *rio_bufptr; /* next unread byte in internal buf */ | |
char rio_buf[RIO_BUFSIZE]; /* internal buffer */ | |
} rio_t; | |
/* $end rio_t */ | |
/* External variables */ | |
extern int h_errno; /* defined by BIND for DNS errors */ | |
extern char **environ; /* defined by libc */ | |
/* Misc constants */ | |
#define MAXLINE 8192 /* max text line length */ | |
#define MAXBUF 8192 /* max I/O buffer size */ | |
#define LISTENQ 1024 /* second argument to listen() */ | |
/* Our own error-handling functions */ | |
void unix_error(char *msg); | |
void posix_error(int code, char *msg); | |
void dns_error(char *msg); | |
void app_error(char *msg); | |
/* Process control wrappers */ | |
pid_t Fork(void); | |
void Execve(const char *filename, char *const argv[], char *const envp[]); | |
pid_t Wait(int *status); | |
pid_t Waitpid(pid_t pid, int *iptr, int options); | |
void Kill(pid_t pid, int signum); | |
unsigned int Sleep(unsigned int secs); | |
void Pause(void); | |
unsigned int Alarm(unsigned int seconds); | |
void Setpgid(pid_t pid, pid_t pgid); | |
pid_t Getpgrp(); | |
/* Signal wrappers */ | |
typedef void handler_t(int); | |
handler_t *Signal(int signum, handler_t *handler); | |
void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset); | |
void Sigemptyset(sigset_t *set); | |
void Sigfillset(sigset_t *set); | |
void Sigaddset(sigset_t *set, int signum); | |
void Sigdelset(sigset_t *set, int signum); | |
int Sigismember(const sigset_t *set, int signum); | |
/* Unix I/O wrappers */ | |
int Open(const char *pathname, int flags, mode_t mode); | |
ssize_t Read(int fd, void *buf, size_t count); | |
ssize_t Write(int fd, const void *buf, size_t count); | |
off_t Lseek(int fildes, off_t offset, int whence); | |
void Close(int fd); | |
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, | |
struct timeval *timeout); | |
int Dup2(int fd1, int fd2); | |
void Stat(const char *filename, struct stat *buf); | |
void Fstat(int fd, struct stat *buf) ; | |
/* Memory mapping wrappers */ | |
void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset); | |
void Munmap(void *start, size_t length); | |
/* Standard I/O wrappers */ | |
void Fclose(FILE *fp); | |
FILE *Fdopen(int fd, const char *type); | |
char *Fgets(char *ptr, int n, FILE *stream); | |
FILE *Fopen(const char *filename, const char *mode); | |
void Fputs(const char *ptr, FILE *stream); | |
size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream); | |
void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); | |
/* Dynamic storage allocation wrappers */ | |
void *Malloc(size_t size); | |
void *Realloc(void *ptr, size_t size); | |
void *Calloc(size_t nmemb, size_t size); | |
void Free(void *ptr); | |
/* Sockets interface wrappers */ | |
int Socket(int domain, int type, int protocol); | |
void Setsockopt(int s, int level, int optname, const void *optval, int optlen); | |
void Bind(int sockfd, struct sockaddr *my_addr, int addrlen); | |
void Listen(int s, int backlog); | |
int Accept(int s, struct sockaddr *addr, socklen_t *addrlen); | |
void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen); | |
/* DNS wrappers */ | |
struct hostent *Gethostbyname(const char *name); | |
struct hostent *Gethostbyaddr(const char *addr, int len, int type); | |
/* Pthreads thread control wrappers */ | |
void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp, | |
void * (*routine)(void *), void *argp); | |
void Pthread_join(pthread_t tid, void **thread_return); | |
void Pthread_cancel(pthread_t tid); | |
void Pthread_detach(pthread_t tid); | |
void Pthread_exit(void *retval); | |
pthread_t Pthread_self(void); | |
void Pthread_once(pthread_once_t *once_control, void (*init_function)()); | |
/* POSIX semaphore wrappers */ | |
void Sem_init(sem_t *sem, int pshared, unsigned int value); | |
void P(sem_t *sem); | |
void V(sem_t *sem); | |
/* Rio (Robust I/O) package */ | |
ssize_t rio_readn(int fd, void *usrbuf, size_t n); | |
ssize_t rio_writen(int fd, void *usrbuf, size_t n); | |
void rio_readinitb(rio_t *rp, int fd); | |
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n); | |
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen); | |
/* Wrappers for Rio package */ | |
ssize_t Rio_readn(int fd, void *usrbuf, size_t n); | |
void Rio_writen(int fd, void *usrbuf, size_t n); | |
void Rio_readinitb(rio_t *rp, int fd); | |
ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n); | |
ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen); | |
/* Client/server helper functions */ | |
int open_clientfd(char *hostname, int portno); | |
int open_listenfd(int portno); | |
/* Wrappers for client/server helper functions */ | |
int Open_clientfd(char *hostname, int port); | |
int Open_listenfd(int port); | |
#endif /* __CSAPP_H__ */ | |
/* $end csapp.h */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment