Advertisement
Guest User

csapp.c

a guest
Jul 1st, 2014
235
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 19.68 KB | None | 0 0
  1. /* $begin csapp.c */
  2. #include "csapp.h"
  3.  
  4. /* Updated with a reentrant open_clientfd_r function */
  5.  
  6. /**************************
  7.  * Error-handling functions
  8.  **************************/
  9. /* $begin errorfuns */
  10. /* $begin unixerror */
  11. void unix_error(char *msg) /* unix-style error */
  12. {
  13.     fprintf(stderr, "%s: %s\n", msg, strerror(errno));
  14.     exit(0);
  15. }
  16. /* $end unixerror */
  17.  
  18. void posix_error(int code, char *msg) /* posix-style error */
  19. {
  20.     fprintf(stderr, "%s: %s\n", msg, strerror(code));
  21.     exit(0);
  22. }
  23.  
  24. void dns_error(char *msg) /* dns-style error */
  25. {
  26.     fprintf(stderr, "%s: DNS error %d\n", msg, h_errno);
  27.     exit(0);
  28. }
  29.  
  30. void app_error(char *msg) /* application error */
  31. {
  32.     fprintf(stderr, "%s\n", msg);
  33.     exit(0);
  34. }
  35. /* $end errorfuns */
  36.  
  37. /*********************************************
  38.  * Wrappers for Unix process control functions
  39.  ********************************************/
  40.  
  41. /* $begin forkwrapper */
  42. pid_t Fork(void)
  43. {
  44.     pid_t pid;
  45.  
  46.     if ((pid = fork()) < 0)
  47.     unix_error("Fork error");
  48.     return pid;
  49. }
  50. /* $end forkwrapper */
  51.  
  52. void Execve(const char *filename, char *const argv[], char *const envp[])
  53. {
  54.     if (execve(filename, argv, envp) < 0)
  55.     unix_error("Execve error");
  56. }
  57.  
  58. /* $begin wait */
  59. pid_t Wait(int *status)
  60. {
  61.     pid_t pid;
  62.  
  63.     if ((pid  = wait(status)) < 0)
  64.     unix_error("Wait error");
  65.     return pid;
  66. }
  67. /* $end wait */
  68.  
  69. pid_t Waitpid(pid_t pid, int *iptr, int options)
  70. {
  71.     pid_t retpid;
  72.  
  73.     if ((retpid  = waitpid(pid, iptr, options)) < 0)
  74.     unix_error("Waitpid error");
  75.     return(retpid);
  76. }
  77.  
  78. /* $begin kill */
  79. void Kill(pid_t pid, int signum)
  80. {
  81.     int rc;
  82.  
  83.     if ((rc = kill(pid, signum)) < 0)
  84.     unix_error("Kill error");
  85. }
  86. /* $end kill */
  87.  
  88. void Pause()
  89. {
  90.     (void)pause();
  91.     return;
  92. }
  93.  
  94. unsigned int Sleep(unsigned int secs)
  95. {
  96.     int rc;
  97.  
  98.     if ((rc = sleep(secs)) < 0)
  99.     unix_error("Sleep error");
  100.     return rc;
  101. }
  102.  
  103. unsigned int Alarm(unsigned int seconds) {
  104.     return alarm(seconds);
  105. }
  106.  
  107. void Setpgid(pid_t pid, pid_t pgid) {
  108.     int rc;
  109.  
  110.     if ((rc = setpgid(pid, pgid)) < 0)
  111.     unix_error("Setpgid error");
  112.     return;
  113. }
  114.  
  115. pid_t Getpgrp(void) {
  116.     return getpgrp();
  117. }
  118.  
  119. /************************************
  120.  * Wrappers for Unix signal functions
  121.  ***********************************/
  122.  
  123. /* $begin sigaction */
  124. handler_t *Signal(int signum, handler_t *handler)
  125. {
  126.     struct sigaction action, old_action;
  127.  
  128.     action.sa_handler = handler;  
  129.     sigemptyset(&action.sa_mask); /* block sigs of type being handled */
  130.     action.sa_flags = SA_RESTART; /* restart syscalls if possible */
  131.  
  132.     if (sigaction(signum, &action, &old_action) < 0)
  133.     unix_error("Signal error");
  134.     return (old_action.sa_handler);
  135. }
  136. /* $end sigaction */
  137.  
  138. void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
  139. {
  140.     if (sigprocmask(how, set, oldset) < 0)
  141.     unix_error("Sigprocmask error");
  142.     return;
  143. }
  144.  
  145. void Sigemptyset(sigset_t *set)
  146. {
  147.     if (sigemptyset(set) < 0)
  148.     unix_error("Sigemptyset error");
  149.     return;
  150. }
  151.  
  152. void Sigfillset(sigset_t *set)
  153. {
  154.     if (sigfillset(set) < 0)
  155.     unix_error("Sigfillset error");
  156.     return;
  157. }
  158.  
  159. void Sigaddset(sigset_t *set, int signum)
  160. {
  161.     if (sigaddset(set, signum) < 0)
  162.     unix_error("Sigaddset error");
  163.     return;
  164. }
  165.  
  166. void Sigdelset(sigset_t *set, int signum)
  167. {
  168.     if (sigdelset(set, signum) < 0)
  169.     unix_error("Sigdelset error");
  170.     return;
  171. }
  172.  
  173. int Sigismember(const sigset_t *set, int signum)
  174. {
  175.     int rc;
  176.     if ((rc = sigismember(set, signum)) < 0)
  177.     unix_error("Sigismember error");
  178.     return rc;
  179. }
  180.  
  181.  
  182. /********************************
  183.  * Wrappers for Unix I/O routines
  184.  ********************************/
  185.  
  186. int Open(const char *pathname, int flags, mode_t mode)
  187. {
  188.     int rc;
  189.  
  190.     if ((rc = open(pathname, flags, mode))  < 0)
  191.     unix_error("Open error");
  192.     return rc;
  193. }
  194.  
  195. ssize_t Read(int fd, void *buf, size_t count)
  196. {
  197.     ssize_t rc;
  198.  
  199.     if ((rc = read(fd, buf, count)) < 0)
  200.     unix_error("Read error");
  201.     return rc;
  202. }
  203.  
  204. ssize_t Write(int fd, const void *buf, size_t count)
  205. {
  206.     ssize_t rc;
  207.  
  208.     if ((rc = write(fd, buf, count)) < 0)
  209.     unix_error("Write error");
  210.     return rc;
  211. }
  212.  
  213. off_t Lseek(int fildes, off_t offset, int whence)
  214. {
  215.     off_t rc;
  216.  
  217.     if ((rc = lseek(fildes, offset, whence)) < 0)
  218.     unix_error("Lseek error");
  219.     return rc;
  220. }
  221.  
  222. void Close(int fd)
  223. {
  224.     int rc;
  225.  
  226.     if ((rc = close(fd)) < 0)
  227.     unix_error("Close error");
  228. }
  229.  
  230. int Select(int  n, fd_set *readfds, fd_set *writefds,
  231.        fd_set *exceptfds, struct timeval *timeout)
  232. {
  233.     int rc;
  234.  
  235.     if ((rc = select(n, readfds, writefds, exceptfds, timeout)) < 0)
  236.     unix_error("Select error");
  237.     return rc;
  238. }
  239.  
  240. int Dup2(int fd1, int fd2)
  241. {
  242.     int rc;
  243.  
  244.     if ((rc = dup2(fd1, fd2)) < 0)
  245.     unix_error("Dup2 error");
  246.     return rc;
  247. }
  248.  
  249. void Stat(const char *filename, struct stat *buf)
  250. {
  251.     if (stat(filename, buf) < 0)
  252.     unix_error("Stat error");
  253. }
  254.  
  255. void Fstat(int fd, struct stat *buf)
  256. {
  257.     if (fstat(fd, buf) < 0)
  258.     unix_error("Fstat error");
  259. }
  260.  
  261. /***************************************
  262.  * Wrappers for memory mapping functions
  263.  ***************************************/
  264. void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
  265. {
  266.     void *ptr;
  267.  
  268.     if ((ptr = mmap(addr, len, prot, flags, fd, offset)) == ((void *) -1))
  269.     unix_error("mmap error");
  270.     return(ptr);
  271. }
  272.  
  273. void Munmap(void *start, size_t length)
  274. {
  275.     if (munmap(start, length) < 0)
  276.     unix_error("munmap error");
  277. }
  278.  
  279. /***************************************************
  280.  * Wrappers for dynamic storage allocation functions
  281.  ***************************************************/
  282.  
  283. void *Malloc(size_t size)
  284. {
  285.     void *p;
  286.  
  287.     if ((p  = malloc(size)) == NULL)
  288.     unix_error("Malloc error");
  289.     return p;
  290. }
  291.  
  292. void *Realloc(void *ptr, size_t size)
  293. {
  294.     void *p;
  295.  
  296.     if ((p  = realloc(ptr, size)) == NULL)
  297.     unix_error("Realloc error");
  298.     return p;
  299. }
  300.  
  301. void *Calloc(size_t nmemb, size_t size)
  302. {
  303.     void *p;
  304.  
  305.     if ((p = calloc(nmemb, size)) == NULL)
  306.     unix_error("Calloc error");
  307.     return p;
  308. }
  309.  
  310. void Free(void *ptr)
  311. {
  312.     free(ptr);
  313. }
  314.  
  315. /******************************************
  316.  * Wrappers for the Standard I/O functions.
  317.  ******************************************/
  318. void Fclose(FILE *fp)
  319. {
  320.     if (fclose(fp) != 0)
  321.     unix_error("Fclose error");
  322. }
  323.  
  324. FILE *Fdopen(int fd, const char *type)
  325. {
  326.     FILE *fp;
  327.  
  328.     if ((fp = fdopen(fd, type)) == NULL)
  329.     unix_error("Fdopen error");
  330.  
  331.     return fp;
  332. }
  333.  
  334. char *Fgets(char *ptr, int n, FILE *stream)
  335. {
  336.     char *rptr;
  337.  
  338.     if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream))
  339.     app_error("Fgets error");
  340.  
  341.     return rptr;
  342. }
  343.  
  344. FILE *Fopen(const char *filename, const char *mode)
  345. {
  346.     FILE *fp;
  347.  
  348.     if ((fp = fopen(filename, mode)) == NULL)
  349.     unix_error("Fopen error");
  350.  
  351.     return fp;
  352. }
  353.  
  354. void Fputs(const char *ptr, FILE *stream)
  355. {
  356.     if (fputs(ptr, stream) == EOF)
  357.     unix_error("Fputs error");
  358. }
  359.  
  360. size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
  361. {
  362.     size_t n;
  363.  
  364.     if (((n = fread(ptr, size, nmemb, stream)) < nmemb) && ferror(stream))
  365.     unix_error("Fread error");
  366.     return n;
  367. }
  368.  
  369. void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
  370. {
  371.     if (fwrite(ptr, size, nmemb, stream) < nmemb)
  372.     unix_error("Fwrite error");
  373. }
  374.  
  375.  
  376. /****************************
  377.  * Sockets interface wrappers
  378.  ****************************/
  379.  
  380. int Socket(int domain, int type, int protocol)
  381. {
  382.     int rc;
  383.  
  384.     if ((rc = socket(domain, type, protocol)) < 0)
  385.     unix_error("Socket error");
  386.     return rc;
  387. }
  388.  
  389. void Setsockopt(int s, int level, int optname, const void *optval, int optlen)
  390. {
  391.     int rc;
  392.  
  393.     if ((rc = setsockopt(s, level, optname, optval, optlen)) < 0)
  394.     unix_error("Setsockopt error");
  395. }
  396.  
  397. void Bind(int sockfd, struct sockaddr *my_addr, int addrlen)
  398. {
  399.     int rc;
  400.  
  401.     if ((rc = bind(sockfd, my_addr, addrlen)) < 0)
  402.     unix_error("Bind error");
  403. }
  404.  
  405. void Listen(int s, int backlog)
  406. {
  407.     int rc;
  408.  
  409.     if ((rc = listen(s,  backlog)) < 0)
  410.     unix_error("Listen error");
  411. }
  412.  
  413. int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
  414. {
  415.     int rc;
  416.  
  417.     if ((rc = accept(s, addr, addrlen)) < 0)
  418.     unix_error("Accept error");
  419.     return rc;
  420. }
  421.  
  422. void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
  423. {
  424.     int rc;
  425.  
  426.     if ((rc = connect(sockfd, serv_addr, addrlen)) < 0)
  427.     unix_error("Connect error");
  428. }
  429.  
  430. /************************
  431.  * DNS interface wrappers
  432.  ***********************/
  433.  
  434. /* $begin gethostbyname */
  435. struct hostent *Gethostbyname(const char *name)
  436. {
  437.     struct hostent *p;
  438.  
  439.     if ((p = gethostbyname(name)) == NULL)
  440.     dns_error("Gethostbyname error");
  441.     return p;
  442. }
  443. /* $end gethostbyname */
  444.  
  445. struct hostent *Gethostbyaddr(const char *addr, int len, int type)
  446. {
  447.     struct hostent *p;
  448.  
  449.     if ((p = gethostbyaddr(addr, len, type)) == NULL)
  450.     dns_error("Gethostbyaddr error");
  451.     return p;
  452. }
  453.  
  454. /************************************************
  455.  * Wrappers for Pthreads thread control functions
  456.  ************************************************/
  457.  
  458. void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
  459.             void * (*routine)(void *), void *argp)
  460. {
  461.     int rc;
  462.  
  463.     if ((rc = pthread_create(tidp, attrp, routine, argp)) != 0)
  464.     posix_error(rc, "Pthread_create error");
  465. }
  466.  
  467. void Pthread_cancel(pthread_t tid) {
  468.     int rc;
  469.  
  470.     if ((rc = pthread_cancel(tid)) != 0)
  471.     posix_error(rc, "Pthread_cancel error");
  472. }
  473.  
  474. void Pthread_join(pthread_t tid, void **thread_return) {
  475.     int rc;
  476.  
  477.     if ((rc = pthread_join(tid, thread_return)) != 0)
  478.     posix_error(rc, "Pthread_join error");
  479. }
  480.  
  481. /* $begin detach */
  482. void Pthread_detach(pthread_t tid) {
  483.     int rc;
  484.  
  485.     if ((rc = pthread_detach(tid)) != 0)
  486.     posix_error(rc, "Pthread_detach error");
  487. }
  488. /* $end detach */
  489.  
  490. void Pthread_exit(void *retval) {
  491.     pthread_exit(retval);
  492. }
  493.  
  494. pthread_t Pthread_self(void) {
  495.     return pthread_self();
  496. }
  497.  
  498. void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
  499.     pthread_once(once_control, init_function);
  500. }
  501.  
  502. /*******************************
  503.  * Wrappers for Posix semaphores
  504.  *******************************/
  505.  
  506. void Sem_init(sem_t *sem, int pshared, unsigned int value)
  507. {
  508.     if (sem_init(sem, pshared, value) < 0)
  509.     unix_error("Sem_init error");
  510. }
  511.  
  512. void P(sem_t *sem)
  513. {
  514.     if (sem_wait(sem) < 0)
  515.     unix_error("P error");
  516. }
  517.  
  518. void V(sem_t *sem)
  519. {
  520.     if (sem_post(sem) < 0)
  521.     unix_error("V error");
  522. }
  523.  
  524. /*********************************************************************
  525.  * The Rio package - robust I/O functions
  526.  **********************************************************************/
  527. /*
  528.  * rio_readn - robustly read n bytes (unbuffered)
  529.  */
  530. /* $begin rio_readn */
  531. ssize_t rio_readn(int fd, void *usrbuf, size_t n)
  532. {
  533.     size_t nleft = n;
  534.     ssize_t nread;
  535.     char *bufp = usrbuf;
  536.  
  537.     while (nleft > 0) {
  538.     if ((nread = read(fd, bufp, nleft)) < 0) {
  539.         if (errno == EINTR) /* interrupted by sig handler return */
  540.         nread = 0;      /* and call read() again */
  541.         else
  542.         return -1;      /* errno set by read() */
  543.     }
  544.     else if (nread == 0)
  545.         break;              /* EOF */
  546.     nleft -= nread;
  547.     bufp += nread;
  548.     }
  549.     return (n - nleft);         /* return >= 0 */
  550. }
  551. /* $end rio_readn */
  552.  
  553. /*
  554.  * rio_writen - robustly write n bytes (unbuffered)
  555.  */
  556. /* $begin rio_writen */
  557. ssize_t rio_writen(int fd, void *usrbuf, size_t n)
  558. {
  559.     size_t nleft = n;
  560.     ssize_t nwritten;
  561.     char *bufp = usrbuf;
  562.  
  563.     while (nleft > 0) {
  564.     if ((nwritten = write(fd, bufp, nleft)) <= 0) {
  565.         if (errno == EINTR)  /* interrupted by sig handler return */
  566.         nwritten = 0;    /* and call write() again */
  567.         else
  568.         return -1;       /* errorno set by write() */
  569.     }
  570.     nleft -= nwritten;
  571.     bufp += nwritten;
  572.     }
  573.     return n;
  574. }
  575. /* $end rio_writen */
  576.  
  577.  
  578. /*
  579.  * rio_read - This is a wrapper for the Unix read() function that
  580.  *    transfers min(n, rio_cnt) bytes from an internal buffer to a user
  581.  *    buffer, where n is the number of bytes requested by the user and
  582.  *    rio_cnt is the number of unread bytes in the internal buffer. On
  583.  *    entry, rio_read() refills the internal buffer via a call to
  584.  *    read() if the internal buffer is empty.
  585.  */
  586. /* $begin rio_read */
  587. static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
  588. {
  589.     int cnt;
  590.  
  591.     while (rp->rio_cnt <= 0) {  /* refill if buf is empty */
  592.     rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
  593.                sizeof(rp->rio_buf));
  594.     if (rp->rio_cnt < 0) {
  595.         if (errno != EINTR) /* interrupted by sig handler return */
  596.         return -1;
  597.     }
  598.     else if (rp->rio_cnt == 0)  /* EOF */
  599.         return 0;
  600.     else
  601.         rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */
  602.     }
  603.  
  604.     /* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
  605.     cnt = n;          
  606.     if (rp->rio_cnt < n)  
  607.     cnt = rp->rio_cnt;
  608.     memcpy(usrbuf, rp->rio_bufptr, cnt);
  609.     rp->rio_bufptr += cnt;
  610.     rp->rio_cnt -= cnt;
  611.     return cnt;
  612. }
  613. /* $end rio_read */
  614.  
  615. /*
  616.  * rio_readinitb - Associate a descriptor with a read buffer and reset buffer
  617.  */
  618. /* $begin rio_readinitb */
  619. void rio_readinitb(rio_t *rp, int fd)
  620. {
  621.     rp->rio_fd = fd;  
  622.     rp->rio_cnt = 0;  
  623.     rp->rio_bufptr = rp->rio_buf;
  624. }
  625. /* $end rio_readinitb */
  626.  
  627. /*
  628.  * rio_readnb - Robustly read n bytes (buffered)
  629.  */
  630. /* $begin rio_readnb */
  631. ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
  632. {
  633.     size_t nleft = n;
  634.     ssize_t nread;
  635.     char *bufp = usrbuf;
  636.    
  637.     while (nleft > 0) {
  638.     if ((nread = rio_read(rp, bufp, nleft)) < 0) {
  639.         if (errno == EINTR) /* interrupted by sig handler return */
  640.         nread = 0;      /* call read() again */
  641.         else
  642.         return -1;      /* errno set by read() */
  643.     }
  644.     else if (nread == 0)
  645.         break;              /* EOF */
  646.     nleft -= nread;
  647.     bufp += nread;
  648.     }
  649.     return (n - nleft);         /* return >= 0 */
  650. }
  651. /* $end rio_readnb */
  652.  
  653. /*
  654.  * rio_readlineb - robustly read a text line (buffered)
  655.  */
  656. /* $begin rio_readlineb */
  657. ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
  658. {
  659.     int n, rc;
  660.     char c, *bufp = usrbuf;
  661.     for (n = 1; n < maxlen; n++) {
  662.     if ((rc = rio_read(rp, &c, 1)) == 1) {
  663.         *bufp++ = c;
  664.         if (c == '\n')
  665.         break;
  666.     } else if (rc == 0) {
  667.         if (n == 1)
  668.         return 0; /* EOF, no data read */
  669.         else
  670.         break;    /* EOF, some data was read */
  671.     } else
  672.         return -1;    /* error */
  673.     }
  674.     *bufp = 0;
  675.     return n;
  676. }
  677. /* $end rio_readlineb */
  678.  
  679. /**********************************
  680.  * Wrappers for robust I/O routines
  681.  **********************************/
  682. ssize_t Rio_readn(int fd, void *ptr, size_t nbytes)
  683. {
  684.     ssize_t n;
  685.  
  686.     if ((n = rio_readn(fd, ptr, nbytes)) < 0)
  687.     {
  688.     //unix_error("Rio_readn error");
  689.         pthread_exit(NULL);
  690.     }
  691.     return n;
  692. }
  693.  
  694. void Rio_writen(int fd, void *usrbuf, size_t n)
  695. {
  696.     if (rio_writen(fd, usrbuf, n) != n)
  697.     {
  698.         pthread_exit(NULL);
  699.     //unix_error("Rio_writen error");
  700.        
  701.     }
  702. }
  703.  
  704. void Rio_readinitb(rio_t *rp, int fd)
  705. {
  706.     rio_readinitb(rp, fd);
  707. }
  708.  
  709. ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n)
  710. {
  711.     ssize_t rc;
  712.  
  713.     if ((rc = rio_readnb(rp, usrbuf, n)) < 0)
  714.     {
  715.     //unix_error("Rio_readnb error");
  716.         pthread_exit(NULL);
  717.     }
  718.     return rc;
  719. }
  720.  
  721. ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
  722. {
  723.     ssize_t rc;
  724.     if(!usrbuf)
  725.       printf("NULL");
  726.  
  727.     if ((rc = rio_readlineb(rp, usrbuf, maxlen)) < 0)
  728.     {
  729.     //unix_error("Rio_readlineb error");
  730.         pthread_exit(NULL);
  731.     }
  732.     return rc;
  733. }
  734.  
  735. /********************************
  736.  * Client/server helper functions
  737.  ********************************/
  738. /*
  739.  * open_clientfd - open connection to server at <hostname, port>
  740.  *   and return a socket descriptor ready for reading and writing.
  741.  *   Returns -1 and sets errno on Unix error.
  742.  *   Returns -2 and sets h_errno on DNS (gethostbyname) error.
  743.  *
  744.  *   WARNING: Not thread-safe because of call to gethostbyname.
  745.  *   Use open_clientfd_r instead.
  746.  */
  747. /* $begin open_clientfd */
  748. int open_clientfd(char *hostname, int port)
  749. {
  750.     int clientfd;
  751.     struct hostent *hp;
  752.     struct sockaddr_in serveraddr;
  753.  
  754.     if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  755.     return -1; /* check errno for cause of error */
  756.  
  757.     /* Fill in the server's IP address and port */
  758.     if ((hp = gethostbyname(hostname)) == NULL)
  759.     return -2; /* check h_errno for cause of error */
  760.     bzero((char *) &serveraddr, sizeof(serveraddr));
  761.     serveraddr.sin_family = AF_INET;
  762.     bcopy((char *)hp->h_addr_list[0],
  763.       (char *)&serveraddr.sin_addr.s_addr, hp->h_length);
  764.     serveraddr.sin_port = htons(port);
  765.  
  766.     /* Establish a connection with the server */
  767.     if (connect(clientfd, (SA *) &serveraddr, sizeof(serveraddr)) < 0)
  768.     return -1;
  769.     return clientfd;
  770. }
  771. /* $end open_clientfd */
  772.  
  773. /*
  774.  * open_clientfd_r - thread-safe version of open_clientfd
  775.  */
  776. int open_clientfd_r(char *hostname, int port) {
  777.     int clientfd;
  778.     struct addrinfo *addlist, *p;
  779.     char port_str[MAXLINE];
  780.     int rv;
  781.  
  782.     /* Create the socket descriptor */
  783.     if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  784.         return -1;
  785.     }
  786.  
  787.     /* Get a list of addrinfo structs */
  788.     sprintf(port_str, "%d", port);
  789.     if ((rv = getaddrinfo(hostname, port_str, NULL, &addlist)) != 0) {
  790.         return -1;
  791.     }
  792.  
  793.     /* Walk the list, using each addrinfo to try to connect */
  794.     for (p = addlist; p; p = p->ai_next) {
  795.         if (p->ai_family == AF_INET) {
  796.             if (connect(clientfd, p->ai_addr, p->ai_addrlen) == 0) {
  797.                 break; /* success */
  798.             }
  799.         }
  800.     }
  801.  
  802.     /* Clean up */
  803.     freeaddrinfo(addlist);
  804.     if (!p) { /* all connects failed */
  805.         close(clientfd);
  806.         return -1;
  807.     }
  808.     else { /* one of the connects succeeded */
  809.         return clientfd;
  810.     }
  811. }
  812.  
  813. /*  
  814.  * open_listenfd - open and return a listening socket on port
  815.  *     Returns -1 and sets errno on Unix error.
  816.  */
  817. /* $begin open_listenfd */
  818. int open_listenfd(int port)
  819. {
  820.     int listenfd, optval=1;
  821.     struct sockaddr_in serveraddr;
  822.  
  823.     /* Create a socket descriptor */
  824.     if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  825.     return -1;
  826.  
  827.     /* Eliminates "Address already in use" error from bind. */
  828.     if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
  829.            (const void *)&optval , sizeof(int)) < 0)
  830.     return -1;
  831.  
  832.     /* Listenfd will be an endpoint for all requests to port
  833.        on any IP address for this host */
  834.     bzero((char *) &serveraddr, sizeof(serveraddr));
  835.     serveraddr.sin_family = AF_INET;
  836.     serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  837.     serveraddr.sin_port = htons((unsigned short)port);
  838.     if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0)
  839.     return -1;
  840.  
  841.     /* Make it a listening socket ready to accept connection requests */
  842.     if (listen(listenfd, LISTENQ) < 0)
  843.     return -1;
  844.     return listenfd;
  845. }
  846. /* $end open_listenfd */
  847.  
  848. /******************************************
  849.  * Wrappers for the client/server helper routines
  850.  ******************************************/
  851. int Open_clientfd(char *hostname, int port)
  852. {
  853.     int rc;
  854.  
  855.     if ((rc = open_clientfd(hostname, port)) < 0) {
  856.     if (rc == -1)
  857.         unix_error("Open_clientfd Unix error");
  858.     else        
  859.         dns_error("Open_clientfd DNS error");
  860.     }
  861.     return rc;
  862. }
  863.  
  864. int Open_clientfd_r(char *hostname, int port)
  865. {
  866.     int rc;
  867.  
  868.     if ((rc = open_clientfd_r(hostname, port)) < 0) {
  869.         unix_error("Open_clientfd_r error");
  870.     }
  871.     return rc;
  872. }
  873.  
  874. int Open_listenfd(int port)
  875. {
  876.     int rc;
  877.  
  878.     if ((rc = open_listenfd(port)) < 0)
  879.     unix_error("Open_listenfd error");
  880.     return rc;
  881. }
  882. /* $end csapp.c */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement