· 7 years ago · Apr 24, 2018, 04:26 AM
1===============================================================ssSet.cpp
2extern "C" {
3 #include "csapp.h"
4}
5
6#include <iostream>
7#include <string>
8#include "packets.h"
9
10using namespace std;
11
12int main(int argc, char *argv[]){
13
14 char* machineName;
15 int TCPport;
16 int secretKey;
17 int client;
18 char variableName[15];
19 char value[100];
20
21 if(argc != 6){
22 cout << "Usage: ./ssSet host port secret variableName value" << endl;
23 return -1;
24 }else{
25 machineName = argv[1];
26 TCPport = stoi(argv[2]);
27 secretKey = stoi(argv[3]);
28 strncpy(variableName, argv[4], 15);
29 strncpy(value, argv[5], 100);
30 }
31
32i//----------------------------------------
33//----------PASS VARIABLES HERE-----------
34//----------------------------------------
35 char auth_buf[8];
36 char set_buf[125];
37 char* data_buf;
38 char response_buf[4];
39 auth_packet packet_auth;
40 set_packet packet_set;
41 rio_t rio;
42 packet_auth.key = secretKey;
43 packet_auth.choice = 0;
44
45 strncpy(packet_set.var_name, variableName, 15);
46 packet_set.var_len = strlen(value);
47 strncpy(packet_set.var_data, value, 100);
48
49 htonAuth(packet_auth, auth_buf);
50 htonSet(packet_set, set_buf);
51 data_buf = concat_bufs(auth_buf, set_buf, 8, 125);
52 client = open_clientfd(machineName, TCPport);
53 Rio_readinitb(&rio, client);
54 if (client < 0) {
55 printf("Error connecting to %s: %s\n", machineName, strerror(errno));
56 return -1;
57 } else {
58 // transmit message
59 Rio_writen(client, data_buf, 125 + 8);
60 }
61
62 // wait for response
63 Rio_readinitb(&rio, client);
64 Rio_readnb(&rio, response_buf, 4);
65 Close(client);
66
67 // extract info from buf
68 int8_t status;
69 memcpy(&status, response_buf+0, 1);
70
71 if (status == -1) {
72 cout << "failed" << endl;
73 }
74
75 return 0;
76}
77=========================================================================ssRun.cpp
78extern "C" {
79 #include "csapp.h"
80}
81#include <iostream>
82#include <string>
83#include "packets.h"
84
85using namespace std;
86
87int main(int argc, char *argv[]){
88
89 char* machineName;
90 int TCPport;
91 int secretKey;
92 char* program;
93
94 if(argc != 5){
95 cout << "Usage: ./ssRun host port secret program" << endl;
96 return -1;
97 }else{
98 machineName = argv[1];
99 TCPport = stoi(argv[2]);
100 secretKey = stoi(argv[3]);
101 program = argv[4];
102 }
103
104//----------------------------------------
105//----------PASS VARIABLES HERE-----------
106//----------------------------------------
107 char auth_buf[8];
108 char run_buf[117];
109 char* data_buf;
110 char response_buf[110];
111 auth_packet packet_auth;
112 run_packet packet_run;
113 rio_t rio;
114 packet_auth.key = secretKey;
115 packet_auth.choice = 3;
116
117 strncpy(packet_run.prg_name, program, 8);
118
119 htonAuth(packet_auth, auth_buf);
120 htonRun(packet_run, run_buf);
121 data_buf = concat_bufs(auth_buf, run_buf, 8, 8);
122
123 // create connection
124 int client = open_clientfd(machineName, TCPport);
125 Rio_readinitb(&rio, client);
126 if (client < 0) {
127 printf("failed\n");
128 return -1;
129 } else {
130 // transmit message
131 uint8_t zero = 0;
132 for (int x = 16; x < 125; x++) {
133 memcpy(data_buf+x, &zero, 1);
134 }
135 Rio_writen(client, data_buf, 125);
136 }
137 // wait for response
138 Rio_readinitb(&rio, client);
139 Rio_readnb(&rio, response_buf, 108);
140 Close(client);
141
142 // extract info from buf
143 int8_t status;
144 memcpy(&status, response_buf+0, 1);
145
146 if (status == -1) {
147 printf("failed\n");
148 } else {
149 uint32_t data_len;
150 char data[100];
151 memcpy(&data_len, response_buf+4, 4);
152 data_len = ntohl(data_len);
153 memcpy(data, response_buf+8, data_len);
154 cout << data << endl;
155 }
156 return 0;
157}
158===============================================ssGet.cpp
159extern "C" {
160 #include "csapp.h"
161}
162#include <iostream>
163#include <string>
164#include "packets.h"
165
166using namespace std;
167
168int main(int argc, char *argv[]){
169
170 char* machineName;
171 int TCPport;
172 int secretKey;
173 char variableName[15];
174
175 if(argc != 5){
176 cout << "Usage: ./ssGet host port secret variableName" << endl;
177 return -1;
178 }else{
179 machineName = argv[1];
180 TCPport = stoi(argv[2]);
181 secretKey = stoi(argv[3]);
182 strncpy(variableName, argv[4], 15);
183 }
184
185//----------------------------------------
186//----------PASS VARIABLES HERE-----------
187//----------------------------------------
188 char auth_buf[8];
189 char get_buf[117];
190 char* data_buf;
191 char response_buf[110];
192 auth_packet packet_auth;
193 get_packet packet_get;
194 rio_t rio;
195 packet_auth.key = secretKey;
196 packet_auth.choice = 1;
197
198 strncpy(packet_get.var_name, variableName, 15);
199
200 htonAuth(packet_auth, auth_buf);
201 htonGet(packet_get, get_buf);
202 data_buf = concat_bufs(auth_buf, get_buf, 8, 15);
203
204 // create connection
205 int client = open_clientfd(machineName, TCPport);
206 if (client < 0) {
207 printf("Error connecting to %s: %s\n", machineName, strerror(errno));
208 return -1;
209 } else {
210 // transmit message
211 Rio_writen(client, data_buf, 125);
212 //cout << "Message sent" << endl;
213 }
214
215 // wait for response
216 Rio_readinitb(&rio, client);
217 Rio_readnb(&rio, response_buf, 110);
218 Close(client);
219 // extract info from buf
220 int8_t status;
221 uint32_t data_len;
222 char data[100];
223
224 memcpy(&status, response_buf+0, 1);
225 if (status == -1) {
226 printf("failed\n");
227 } else {
228 memcpy(&data_len, response_buf+4, 4);
229 data_len = ntohl(data_len);
230 memcpy(data, response_buf+8, 100);
231 cout << data << endl;
232 }
233
234 return 0;
235}
236=================================================================ssDigest.cpp
237extern "C" {
238 #include "csapp.h"
239}
240#include "packets.h"
241#include <iostream>
242
243using namespace std;
244
245int main(int argc, char *argv[]){
246
247 char* machineName;
248 int TCPport;
249 int secretKey;
250 char value[100];
251
252 if(argc != 5){
253 cout << "Usage: ./ssDigest host port secret value" << endl;
254 return -1;
255 }else{
256 machineName = argv[1];
257 TCPport = stoi(argv[2]);
258 secretKey = stoi(argv[3]);
259 strncpy(value, argv[4], 100);
260 }
261
262//----------------------------------------
263//----------PASS VARIABLES HERE-----------
264//----------------------------------------
265 char auth_buf[8];
266 char digest_buf[117];
267 char* data_buf;
268 char response_buf[110];
269 auth_packet packet_auth;
270 digest_packet packet_digest;
271 rio_t rio;
272 packet_auth.key = secretKey;
273 packet_auth.choice = 2;
274 strncpy(packet_digest.val_data, value, strlen(value));
275 packet_digest.val_len = strlen(value);
276 htonAuth(packet_auth, auth_buf);
277 htonDigest(packet_digest, digest_buf);
278 data_buf = concat_bufs(auth_buf, digest_buf, 8, 117);
279 int client = open_clientfd(machineName, TCPport);
280 Rio_readinitb(&rio, client);
281 if (client < 0) {
282 printf("failed\n");
283 return -1;
284 } else {
285 Rio_writen(client, data_buf, 8 + 117);
286 }
287
288 // wait for response
289 Rio_readinitb(&rio, client);
290 Rio_readnb(&rio, response_buf, 110);
291 Close(client);
292
293 // extract data
294 int8_t status;
295 uint32_t data_len;
296 char data[100];
297
298 memcpy(&status, response_buf+0, 1);
299 if (status == -1) {
300 printf("failed\n");
301 } else {
302 memcpy(&data_len, response_buf+4, 4);
303 data_len = ntohl(data_len);
304 memcpy(data, response_buf+8, 100);
305 cout << data << endl;
306 }
307 return 0;
308}
309====================================== simpled
310extern "C" {
311 #include "csapp.h"
312}
313
314#include <iostream>
315#include <vector>
316#include <cstring>
317#include <string.h>
318#include <cstdlib>
319#include <stdlib.h>
320#include <fcntl.h>
321#include <unistd.h>
322#include "packets.h"
323
324using namespace std;
325
326#define MAX_LENGTH 108
327#define CAP_LEN 100
328#define MAX_BUF 125
329#define MAX_VN 15
330#define MAX_RESPONSE 110
331char result[MAX_LENGTH];
332
333void ssSet(char data_buf[MAX_BUF], int conn){
334
335 uint32_t vl;
336 char vn[MAX_VN];
337 char vd[CAP_LEN];
338 memcpy(&vn, data_buf+8, MAX_VN);
339 memcpy(&vl, data_buf+23, 4);
340 vl = ntohl(vl);
341 memcpy(&vd, data_buf+27, vl+1);
342 setenv(vn, vd, 1);
343
344 // send back 0 or -1
345 int8_t result = 0;
346 char response_buf[4];
347 memcpy(response_buf+0, &result, 1);
348 memcpy(response_buf+1, &result, 1);
349 memcpy(response_buf+2, &result, 1);
350 memcpy(response_buf+3, &result, 1);
351
352 Rio_writen(conn, response_buf, 4);
353
354 cout << "Request type = set" << endl
355 << "Detail = " << vn << endl
356 << "Operation Status = success" << endl
357 << "--------------------------" << endl;
358}
359
360void ssGet(char data_buf[MAX_BUF], int conn){
361 char variableName[MAX_VN];
362 memcpy(&variableName, data_buf+8, MAX_VN);
363 char *temp;
364 temp = getenv(variableName);
365 if(temp){
366
367 char tempStr[5];
368 tempStr[0] = '0';
369 tempStr[1] = '0';
370 tempStr[2] = '0';
371 tempStr[3] = '0';
372 tempStr[4] = '\0';
373 int strLen = strlen(temp);
374 memcpy(result+0, &tempStr, 4);
375 memcpy(result+4, &strLen, 4);
376 memcpy(result+8, temp, (strLen));
377 Rio_writen(conn, result, MAX_RESPONSE);
378 cout << "Request type = get" << endl
379 << "Detail = " << variableName << endl
380 << "Operation Status = success" << endl
381 << "--------------------------" << endl;
382 }else{
383
384 char response[MAX_RESPONSE];
385 int8_t failed = -1;
386 memcpy(response, &failed,1);
387 Rio_writen(conn, response, MAX_RESPONSE);
388 cout << "Request type = get" << endl
389 << "Detail = " << variableName << endl
390 << "Operation Status = failure" << endl
391 << "--------------------------" << endl;
392 }
393
394}
395void ssDigest(char data_buf[MAX_BUF], int conn){
396 char c_value[CAP_LEN];
397 memcpy(c_value, data_buf+12, CAP_LEN);
398 string data(c_value);
399 char buffer[CAP_LEN];
400 string first = "sh -c 'echo `/bin/hostname` ";
401 string last = " | /usr/bin/md5sum' > /tmp/serv";
402 string total = first + data + last;
403 system(total.c_str());
404 FILE * fp = fopen("/tmp/serv", "r");
405 fseek(fp, SEEK_SET, 0);
406 fread(buffer, 1, CAP_LEN, fp);
407 fclose(fp);
408
409 char response[MAX_RESPONSE];
410 int8_t success = 0;
411 memcpy(response, &success, 1);
412 uint32_t data_len = htonl(strlen(buffer));
413 memcpy(response+4, &data_len, 4);
414 memcpy(response+8, buffer, CAP_LEN);
415 Rio_writen(conn, response, MAX_LENGTH);
416
417 cout << "Request type = digest" << endl
418 << "Detail = " << c_value << endl
419 << "Operation Status = success" << endl
420 << "--------------------------" << endl;
421}
422
423void ssRun(char data_buf[MAX_BUF], int conn){
424 // get request out
425 char request[8];
426 bool failed = false;
427 memcpy(request, data_buf+8, 8);
428 char buffer[CAP_LEN];
429 char inet[CAP_LEN] = "inet";
430 char hosts[CAP_LEN] = "hosts";
431 char uptime[CAP_LEN] = "uptime";
432 remove("/tmp/serv");
433 if(strcmp(request, inet) == 0){
434 system("/sbin/ifconfig -a > /tmp/serv");
435 }else if(strcmp(request, hosts) == 0){
436 system("/bin/cat /etc/hosts > /tmp/serv");
437 }else if(strcmp(request, uptime) == 0){
438 system("/usr/bin/uptime > /tmp/serv");
439 }else {
440 failed = true;
441 }
442
443
444 buffer[CAP_LEN] = '\n';
445 if (failed) {
446
447 char response[MAX_RESPONSE];
448 int8_t failed = -1;
449 memcpy(response, &failed,1);
450 Rio_writen(conn, response, MAX_RESPONSE);
451 cout << "Request type = run" << endl
452 << "Detail = " << request << endl
453 << "Operation Status = failure" << endl
454 << "--------------------------" << endl;
455 } else {
456
457 FILE * fp = fopen("/tmp/serv", "r");
458 fseek(fp, SEEK_SET, 0);
459 fread(buffer, 1, CAP_LEN, fp);
460 fclose(fp);
461 buffer[CAP_LEN] = '\n';
462 char response[MAX_RESPONSE];
463 int8_t success = 0;
464 memcpy(response, &success,1);
465 uint32_t data_len = htonl(strlen(buffer));
466 memcpy(response+4, &data_len, 4);
467 memcpy(response+8, buffer, CAP_LEN);
468 Rio_writen(conn, response, MAX_LENGTH);
469 cout << "Request type = run" << endl
470 << "Detail = " << request << endl
471 << "Operation Status = success" << endl
472 << "--------------------------" << endl;
473 }
474}
475
476void getBuf(char buffer[MAX_BUF], int conn) {
477
478 rio_t rio;
479
480 Rio_readinitb(&rio, conn);
481 Rio_readnb(&rio, buffer, MAX_BUF);
482
483}
484
485bool authorized(char data_buf[MAX_BUF], int server_key, uint32_t &r_choice) {
486 int key;
487 uint8_t choice;
488 memcpy(&key, data_buf+0, 4);
489 key = ntohl(key);
490 memcpy(&choice, data_buf+4, 1);
491 r_choice = choice;
492 if (key == server_key) {
493 cout << "Secret Key: " << key << endl;
494 return true;
495 }else {
496 cout << "Secret Key: " << key << endl;
497 cout << "--------------------------" << endl;
498 return false;
499 }
500}
501
502void runFunction(int choice, char data_buf[MAX_BUF], int conn) {
503 switch(choice) {
504 case 0: ssSet(data_buf, conn);
505 break;
506 case 1: ssGet(data_buf, conn);
507 break;
508 case 2: ssDigest(data_buf, conn);
509 break;
510 case 3: ssRun(data_buf, conn);
511 break;
512 default: exit(-1);
513
514 }
515}
516int main(int argc, char** argv){
517 if (argc != 3) {
518 printf("Usage: %s <port> <key>\n", argv[0]);
519 return -1;
520 }
521
522 uint32_t key, port, listen, client, conn, choice;
523 struct sockaddr_in clientaddr;
524 char data_buf[MAX_BUF];
525 port = atoi(argv[1]);
526 key = atoi(argv[2]);
527 listen = open_listenfd(port);
528
529 if (listen < 0) {
530 printf("Error starting server: %s\n", strerror(errno));
531 return -1;
532 } else {
533 while (1) {
534 client = sizeof(clientaddr);
535 conn = Accept(listen, (SA*)&clientaddr, &client);
536 getBuf(data_buf, conn);
537 if (authorized(data_buf, key, choice)) {
538 // authorized connection
539 runFunction(choice, data_buf, conn);
540 } else {
541 // unauthorized connection
542 }
543 memset(result, 0, sizeof(result));
544 Close(conn);
545 }
546
547 }
548
549 return 0;
550
551}
552================================================= packets.h
553// A library for simplifying data packet construction
554
555#ifndef PACKETS_H
556#define PACKETS_H
557
558#define MAX_DATA_LEN 100
559#define MAX_VAR_LEN 15
560#define SS_SET 0
561#define SS_GET 1
562#define SS_DIGEST 2
563#define SS_RUN 3
564
565extern "C" {
566 #include "csapp.h"
567}
568#include <iostream>
569#include <string>
570#include <cstdio>
571#include <errno.h>
572#include <stdint.h>
573
574typedef struct {
575 uint32_t key : 32;
576 uint8_t choice : 8;
577 const uint8_t padding = 0;
578} auth_packet;
579
580typedef struct {
581 char var_name[MAX_VAR_LEN];
582 uint32_t var_len;
583 char var_data[MAX_DATA_LEN];
584} set_packet;
585
586typedef struct {
587 char var_name[MAX_VAR_LEN];
588} get_packet;
589
590typedef struct {
591 char prg_name[8];
592} run_packet;
593
594typedef struct {
595 uint32_t val_len;
596 char val_data[MAX_DATA_LEN];
597} digest_packet;
598
599typedef struct {
600 bool success;
601 uint8_t type;
602 const uint8_t padding = 0;
603 uint32_t val_len;
604 char val[MAX_DATA_LEN];
605} response_packet;
606
607void htonAuth(auth_packet packet, char buffer[8]);
608void htonSet(set_packet packet, char buffer[125]);
609void htonGet(get_packet packet, char buffer[125]);
610void htonRun(run_packet packet, char buffer[8]);
611void htonDigest(digest_packet packet, char buffer[125]);
612void htonResponse(response_packet packet, char buffer[125]);
613
614char* concat_bufs(char* b1, char* b2, int b1_size, int b2_size);
615
616void unwrapAuth(int &key, int &choice, char* buffer);
617void unwrapSet(char* &var_name, int &var_len, char* &var_data, char* buffer);
618void unwrapGet(char* &var_name, char* buffer);
619void unwrapDigest(int &val_len, char* &val, char* buffer);
620void unwrapRun(char* &prg_name, char* buffer);
621
622
623
624
625
626#endif
627========================================packets.cpp
628
629#include "packets.h"
630
631
632
633void htonAuth(auth_packet packet, char buffer[8]) {
634 uint32_t u32;
635 uint8_t u8;
636 u32 = htonl(packet.key);
637 memcpy(buffer+0, &u32, 4);
638 u8 = packet.choice;
639 memcpy(buffer+4, &u8, 1);
640 u8 = htons(packet.padding);
641 memcpy(buffer+5, &u8, 1);
642 memcpy(buffer+6, &u8, 1);
643 memcpy(buffer+7, &u8, 1);
644}
645
646void htonSet(set_packet packet, char buffer[125]) {
647 uint32_t u32;
648 memcpy(buffer+0, &packet.var_name, MAX_VAR_LEN);
649 u32 = htonl(packet.var_len);
650 memcpy(buffer+15, &u32, sizeof(uint32_t));
651 memcpy(buffer+19, &packet.var_data, MAX_DATA_LEN);
652}
653
654void htonGet(get_packet packet, char buffer[15]) {
655 memcpy(buffer+0, &packet.var_name, MAX_VAR_LEN);
656}
657
658void htonRun(run_packet packet, char buffer[8]) {
659 memcpy(buffer+0, &packet.prg_name, 8);
660}
661
662void htonDigest(digest_packet packet, char buffer[125]) {
663 uint32_t u32;
664 u32 = htonl(packet.val_len);
665 memcpy(buffer+0, &u32, sizeof(uint32_t));
666 memcpy(buffer+4, &packet.val_data, MAX_DATA_LEN);
667}
668
669void htonResponse(response_packet packet, char buffer[125]) {
670 uint32_t u32;
671 int8_t s;
672 if (packet.success) {
673 s = 0;
674 } else {
675 s = -1;
676 return;
677 }
678 memcpy(buffer+0, &s, 1);
679 memcpy(buffer+1, &packet.padding, 3);
680 if (packet.type == SS_GET) { return; }
681 u32 = htonl(packet.val_len);
682 memcpy(buffer+4, &u32, sizeof(uint32_t));
683 memcpy(buffer+8, &packet.val, MAX_DATA_LEN);
684}
685
686char* concat_bufs(char* b1, char* b2, int b1_size, int b2_size) {
687 char* result = (char*)malloc(b1_size + b2_size);
688 memcpy(result+0, b1, b1_size);
689 memcpy(result+b1_size, b2, b2_size);
690 return result;
691}
692void unwrapAuth(int& key, int& choice, char* buffer) {
693 memcpy(&key, buffer+0, 4);
694 memcpy(&choice, buffer+4, 1);
695 key = ntohl(key);
696}
697
698void unwrapSet(char* &var_name, int &var_len, char* &var_data, char* buffer) {
699 memcpy(&var_name, buffer+8, 15);
700 memcpy(&var_len, buffer+23, 4);
701 var_len = ntohl(var_len);
702 memcpy(&var_data, buffer+27, var_len);
703}
704
705void unwrapGet(char* &var_name, char* buffer) {
706 memcpy(&var_name, buffer+8, 15);
707}
708
709void unwrapDigest(int &val_len, char* &val, char* buffer) {
710 memcpy(&val_len, buffer+8, 4);
711 val_len = ntohl(val_len);
712 memcpy(&val, buffer+12, val_len);
713}
714
715void unwrapRun(char* &prg_name, char* buffer) {
716 memcpy(&prg_name, buffer+8, 8);
717}
718==================================================csapp.h
719/* $begin csapp.h */
720#ifndef __CSAPP_H__
721#define __CSAPP_H__
722
723#include <stdio.h>
724#include <stdlib.h>
725#include <unistd.h>
726#include <string.h>
727#include <ctype.h>
728#include <setjmp.h>
729#include <signal.h>
730#include <sys/time.h>
731#include <sys/types.h>
732#include <sys/wait.h>
733#include <sys/stat.h>
734#include <fcntl.h>
735#include <sys/mman.h>
736#include <errno.h>
737#include <math.h>
738#include <pthread.h>
739#include <semaphore.h>
740#include <sys/socket.h>
741#include <netdb.h>
742#include <netinet/in.h>
743#include <arpa/inet.h>
744
745
746/* Default file permissions are DEF_MODE & ~DEF_UMASK */
747/* $begin createmasks */
748#define DEF_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
749#define DEF_UMASK S_IWGRP|S_IWOTH
750/* $end createmasks */
751
752/* Simplifies calls to bind(), connect(), and accept() */
753/* $begin sockaddrdef */
754typedef struct sockaddr SA;
755/* $end sockaddrdef */
756
757/* Persistent state for the robust I/O (Rio) package */
758/* $begin rio_t */
759#define RIO_BUFSIZE 8192
760typedef struct {
761 int rio_fd; /* Descriptor for this internal buf */
762 int rio_cnt; /* Unread bytes in internal buf */
763 char *rio_bufptr; /* Next unread byte in internal buf */
764 char rio_buf[RIO_BUFSIZE]; /* Internal buffer */
765} rio_t;
766/* $end rio_t */
767
768/* External variables */
769extern int h_errno; /* Defined by BIND for DNS errors */
770extern char **environ; /* Defined by libc */
771
772/* Misc constants */
773#define MAXLINE 8192 /* Max text line length */
774#define MAXBUF 8192 /* Max I/O buffer size */
775#define LISTENQ 1024 /* Second argument to listen() */
776
777/* Our own error-handling functions */
778void unix_error(char *msg);
779void posix_error(int code, char *msg);
780void dns_error(char *msg);
781void app_error(char *msg);
782
783/* Process control wrappers */
784pid_t Fork(void);
785void Execve(const char *filename, char *const argv[], char *const envp[]);
786pid_t Wait(int *status);
787pid_t Waitpid(pid_t pid, int *iptr, int options);
788void Kill(pid_t pid, int signum);
789unsigned int Sleep(unsigned int secs);
790void Pause(void);
791unsigned int Alarm(unsigned int seconds);
792void Setpgid(pid_t pid, pid_t pgid);
793pid_t Getpgrp();
794
795/* Signal wrappers */
796typedef void handler_t(int);
797handler_t *Signal(int signum, handler_t *handler);
798void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
799void Sigemptyset(sigset_t *set);
800void Sigfillset(sigset_t *set);
801void Sigaddset(sigset_t *set, int signum);
802void Sigdelset(sigset_t *set, int signum);
803int Sigismember(const sigset_t *set, int signum);
804
805/* Unix I/O wrappers */
806int Open(const char *pathname, int flags, mode_t mode);
807ssize_t Read(int fd, void *buf, size_t count);
808ssize_t Write(int fd, const void *buf, size_t count);
809off_t Lseek(int fildes, off_t offset, int whence);
810void Close(int fd);
811int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
812 struct timeval *timeout);
813int Dup2(int fd1, int fd2);
814void Stat(const char *filename, struct stat *buf);
815void Fstat(int fd, struct stat *buf) ;
816
817/* Memory mapping wrappers */
818void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
819void Munmap(void *start, size_t length);
820
821/* Standard I/O wrappers */
822void Fclose(FILE *fp);
823FILE *Fdopen(int fd, const char *type);
824char *Fgets(char *ptr, int n, FILE *stream);
825FILE *Fopen(const char *filename, const char *mode);
826void Fputs(const char *ptr, FILE *stream);
827size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
828void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
829
830/* Dynamic storage allocation wrappers */
831void *Malloc(size_t size);
832void *Realloc(void *ptr, size_t size);
833void *Calloc(size_t nmemb, size_t size);
834void Free(void *ptr);
835
836/* Sockets interface wrappers */
837int Socket(int domain, int type, int protocol);
838void Setsockopt(int s, int level, int optname, const void *optval, int optlen);
839void Bind(int sockfd, struct sockaddr *my_addr, int addrlen);
840void Listen(int s, int backlog);
841int Accept(int s, struct sockaddr *addr, socklen_t *addrlen);
842void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
843
844/* DNS wrappers */
845struct hostent *Gethostbyname(const char *name);
846struct hostent *Gethostbyaddr(const char *addr, int len, int type);
847
848/* Pthreads thread control wrappers */
849void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
850 void * (*routine)(void *), void *argp);
851void Pthread_join(pthread_t tid, void **thread_return);
852void Pthread_cancel(pthread_t tid);
853void Pthread_detach(pthread_t tid);
854void Pthread_exit(void *retval);
855pthread_t Pthread_self(void);
856void Pthread_once(pthread_once_t *once_control, void (*init_function)());
857
858/* POSIX semaphore wrappers */
859void Sem_init(sem_t *sem, int pshared, unsigned int value);
860void P(sem_t *sem);
861void V(sem_t *sem);
862
863/* Rio (Robust I/O) package */
864ssize_t rio_readn(int fd, void *usrbuf, size_t n);
865ssize_t rio_writen(int fd, void *usrbuf, size_t n);
866void rio_readinitb(rio_t *rp, int fd);
867ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);
868ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
869
870/* Wrappers for Rio package */
871ssize_t Rio_readn(int fd, void *usrbuf, size_t n);
872void Rio_writen(int fd, void *usrbuf, size_t n);
873void Rio_readinitb(rio_t *rp, int fd);
874ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n);
875ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen);
876
877/* Client/server helper functions */
878int open_clientfd(char *hostname, int portno);
879int open_listenfd(int portno);
880
881/* Wrappers for client/server helper functions */
882int Open_clientfd(char *hostname, int port);
883int Open_listenfd(int port);
884
885#endif /* __CSAPP_H__ */
886/* $end csapp.h */
887======================================csapp.c
888/* Updated 4/18/13 droh:
889 * rio_readlineb: fixed edge case bug
890 * rio_readnb: removed redundant EINTR check
891 */
892/* $begin csapp.c */
893#include "csapp.h"
894
895/**************************
896 * Error-handling functions
897 **************************/
898/* $begin errorfuns */
899/* $begin unixerror */
900void unix_error(char *msg) /* Unix-style error */
901{
902 fprintf(stderr, "%s: %s\n", msg, strerror(errno));
903 exit(0);
904}
905/* $end unixerror */
906
907void posix_error(int code, char *msg) /* Posix-style error */
908{
909 fprintf(stderr, "%s: %s\n", msg, strerror(code));
910 exit(0);
911}
912
913void dns_error(char *msg) /* DNS-style error */
914{
915 fprintf(stderr, "%s: DNS error %d\n", msg, h_errno);
916 exit(0);
917}
918
919void app_error(char *msg) /* Application error */
920{
921 fprintf(stderr, "%s\n", msg);
922 exit(0);
923}
924/* $end errorfuns */
925
926/*********************************************
927 * Wrappers for Unix process control functions
928 ********************************************/
929
930/* $begin forkwrapper */
931pid_t Fork(void)
932{
933 pid_t pid;
934
935 if ((pid = fork()) < 0)
936 unix_error("Fork error");
937 return pid;
938}
939/* $end forkwrapper */
940
941void Execve(const char *filename, char *const argv[], char *const envp[])
942{
943 if (execve(filename, argv, envp) < 0)
944 unix_error("Execve error");
945}
946
947/* $begin wait */
948pid_t Wait(int *status)
949{
950 pid_t pid;
951
952 if ((pid = wait(status)) < 0)
953 unix_error("Wait error");
954 return pid;
955}
956/* $end wait */
957
958pid_t Waitpid(pid_t pid, int *iptr, int options)
959{
960 pid_t retpid;
961
962 if ((retpid = waitpid(pid, iptr, options)) < 0)
963 unix_error("Waitpid error");
964 return(retpid);
965}
966
967/* $begin kill */
968void Kill(pid_t pid, int signum)
969{
970 int rc;
971
972 if ((rc = kill(pid, signum)) < 0)
973 unix_error("Kill error");
974}
975/* $end kill */
976
977void Pause()
978{
979 (void)pause();
980 return;
981}
982
983unsigned int Sleep(unsigned int secs)
984{
985 unsigned int rc;
986
987 if ((rc = sleep(secs)) < 0)
988 unix_error("Sleep error");
989 return rc;
990}
991
992unsigned int Alarm(unsigned int seconds) {
993 return alarm(seconds);
994}
995
996void Setpgid(pid_t pid, pid_t pgid) {
997 int rc;
998
999 if ((rc = setpgid(pid, pgid)) < 0)
1000 unix_error("Setpgid error");
1001 return;
1002}
1003
1004pid_t Getpgrp(void) {
1005 return getpgrp();
1006}
1007
1008/************************************
1009 * Wrappers for Unix signal functions
1010 ***********************************/
1011
1012/* $begin sigaction */
1013handler_t *Signal(int signum, handler_t *handler)
1014{
1015 struct sigaction action, old_action;
1016
1017 action.sa_handler = handler;
1018 sigemptyset(&action.sa_mask); /* Block sigs of type being handled */
1019 action.sa_flags = SA_RESTART; /* Restart syscalls if possible */
1020
1021 if (sigaction(signum, &action, &old_action) < 0)
1022 unix_error("Signal error");
1023 return (old_action.sa_handler);
1024}
1025/* $end sigaction */
1026
1027void Sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
1028{
1029 if (sigprocmask(how, set, oldset) < 0)
1030 unix_error("Sigprocmask error");
1031 return;
1032}
1033
1034void Sigemptyset(sigset_t *set)
1035{
1036 if (sigemptyset(set) < 0)
1037 unix_error("Sigemptyset error");
1038 return;
1039}
1040
1041void Sigfillset(sigset_t *set)
1042{
1043 if (sigfillset(set) < 0)
1044 unix_error("Sigfillset error");
1045 return;
1046}
1047
1048void Sigaddset(sigset_t *set, int signum)
1049{
1050 if (sigaddset(set, signum) < 0)
1051 unix_error("Sigaddset error");
1052 return;
1053}
1054
1055void Sigdelset(sigset_t *set, int signum)
1056{
1057 if (sigdelset(set, signum) < 0)
1058 unix_error("Sigdelset error");
1059 return;
1060}
1061
1062int Sigismember(const sigset_t *set, int signum)
1063{
1064 int rc;
1065 if ((rc = sigismember(set, signum)) < 0)
1066 unix_error("Sigismember error");
1067 return rc;
1068}
1069
1070
1071/********************************
1072 * Wrappers for Unix I/O routines
1073 ********************************/
1074
1075int Open(const char *pathname, int flags, mode_t mode)
1076{
1077 int rc;
1078
1079 if ((rc = open(pathname, flags, mode)) < 0)
1080 unix_error("Open error");
1081 return rc;
1082}
1083
1084ssize_t Read(int fd, void *buf, size_t count)
1085{
1086 ssize_t rc;
1087
1088 if ((rc = read(fd, buf, count)) < 0)
1089 unix_error("Read error");
1090 return rc;
1091}
1092
1093ssize_t Write(int fd, const void *buf, size_t count)
1094{
1095 ssize_t rc;
1096
1097 if ((rc = write(fd, buf, count)) < 0)
1098 unix_error("Write error");
1099 return rc;
1100}
1101
1102off_t Lseek(int fildes, off_t offset, int whence)
1103{
1104 off_t rc;
1105
1106 if ((rc = lseek(fildes, offset, whence)) < 0)
1107 unix_error("Lseek error");
1108 return rc;
1109}
1110
1111void Close(int fd)
1112{
1113 int rc;
1114
1115 if ((rc = close(fd)) < 0)
1116 unix_error("Close error");
1117}
1118
1119int Select(int n, fd_set *readfds, fd_set *writefds,
1120 fd_set *exceptfds, struct timeval *timeout)
1121{
1122 int rc;
1123
1124 if ((rc = select(n, readfds, writefds, exceptfds, timeout)) < 0)
1125 unix_error("Select error");
1126 return rc;
1127}
1128
1129int Dup2(int fd1, int fd2)
1130{
1131 int rc;
1132
1133 if ((rc = dup2(fd1, fd2)) < 0)
1134 unix_error("Dup2 error");
1135 return rc;
1136}
1137
1138void Stat(const char *filename, struct stat *buf)
1139{
1140 if (stat(filename, buf) < 0)
1141 unix_error("Stat error");
1142}
1143
1144void Fstat(int fd, struct stat *buf)
1145{
1146 if (fstat(fd, buf) < 0)
1147 unix_error("Fstat error");
1148}
1149
1150/***************************************
1151 * Wrappers for memory mapping functions
1152 ***************************************/
1153void *Mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
1154{
1155 void *ptr;
1156
1157 if ((ptr = mmap(addr, len, prot, flags, fd, offset)) == ((void *) -1))
1158 unix_error("mmap error");
1159 return(ptr);
1160}
1161
1162void Munmap(void *start, size_t length)
1163{
1164 if (munmap(start, length) < 0)
1165 unix_error("munmap error");
1166}
1167
1168/***************************************************
1169 * Wrappers for dynamic storage allocation functions
1170 ***************************************************/
1171
1172void *Malloc(size_t size)
1173{
1174 void *p;
1175
1176 if ((p = malloc(size)) == NULL)
1177 unix_error("Malloc error");
1178 return p;
1179}
1180
1181void *Realloc(void *ptr, size_t size)
1182{
1183 void *p;
1184
1185 if ((p = realloc(ptr, size)) == NULL)
1186 unix_error("Realloc error");
1187 return p;
1188}
1189
1190void *Calloc(size_t nmemb, size_t size)
1191{
1192 void *p;
1193
1194 if ((p = calloc(nmemb, size)) == NULL)
1195 unix_error("Calloc error");
1196 return p;
1197}
1198
1199void Free(void *ptr)
1200{
1201 free(ptr);
1202}
1203
1204/******************************************
1205 * Wrappers for the Standard I/O functions.
1206 ******************************************/
1207void Fclose(FILE *fp)
1208{
1209 if (fclose(fp) != 0)
1210 unix_error("Fclose error");
1211}
1212
1213FILE *Fdopen(int fd, const char *type)
1214{
1215 FILE *fp;
1216
1217 if ((fp = fdopen(fd, type)) == NULL)
1218 unix_error("Fdopen error");
1219
1220 return fp;
1221}
1222
1223char *Fgets(char *ptr, int n, FILE *stream)
1224{
1225 char *rptr;
1226
1227 if (((rptr = fgets(ptr, n, stream)) == NULL) && ferror(stream))
1228 app_error("Fgets error");
1229
1230 return rptr;
1231}
1232
1233FILE *Fopen(const char *filename, const char *mode)
1234{
1235 FILE *fp;
1236
1237 if ((fp = fopen(filename, mode)) == NULL)
1238 unix_error("Fopen error");
1239
1240 return fp;
1241}
1242
1243void Fputs(const char *ptr, FILE *stream)
1244{
1245 if (fputs(ptr, stream) == EOF)
1246 unix_error("Fputs error");
1247}
1248
1249size_t Fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
1250{
1251 size_t n;
1252
1253 if (((n = fread(ptr, size, nmemb, stream)) < nmemb) && ferror(stream))
1254 unix_error("Fread error");
1255 return n;
1256}
1257
1258void Fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
1259{
1260 if (fwrite(ptr, size, nmemb, stream) < nmemb)
1261 unix_error("Fwrite error");
1262}
1263
1264
1265/****************************
1266 * Sockets interface wrappers
1267 ****************************/
1268
1269int Socket(int domain, int type, int protocol)
1270{
1271 int rc;
1272
1273 if ((rc = socket(domain, type, protocol)) < 0)
1274 unix_error("Socket error");
1275 return rc;
1276}
1277
1278void Setsockopt(int s, int level, int optname, const void *optval, int optlen)
1279{
1280 int rc;
1281
1282 if ((rc = setsockopt(s, level, optname, optval, optlen)) < 0)
1283 unix_error("Setsockopt error");
1284}
1285
1286void Bind(int sockfd, struct sockaddr *my_addr, int addrlen)
1287{
1288 int rc;
1289
1290 if ((rc = bind(sockfd, my_addr, addrlen)) < 0)
1291 unix_error("Bind error");
1292}
1293
1294void Listen(int s, int backlog)
1295{
1296 int rc;
1297
1298 if ((rc = listen(s, backlog)) < 0)
1299 unix_error("Listen error");
1300}
1301
1302int Accept(int s, struct sockaddr *addr, socklen_t *addrlen)
1303{
1304 int rc;
1305
1306 if ((rc = accept(s, addr, addrlen)) < 0)
1307 unix_error("Accept error");
1308 return rc;
1309}
1310
1311void Connect(int sockfd, struct sockaddr *serv_addr, int addrlen)
1312{
1313 int rc;
1314
1315 if ((rc = connect(sockfd, serv_addr, addrlen)) < 0)
1316 unix_error("Connect error");
1317}
1318
1319/************************
1320 * DNS interface wrappers
1321 ***********************/
1322
1323/* $begin gethostbyname */
1324struct hostent *Gethostbyname(const char *name)
1325{
1326 struct hostent *p;
1327
1328 if ((p = gethostbyname(name)) == NULL)
1329 dns_error("Gethostbyname error");
1330 return p;
1331}
1332/* $end gethostbyname */
1333
1334struct hostent *Gethostbyaddr(const char *addr, int len, int type)
1335{
1336 struct hostent *p;
1337
1338 if ((p = gethostbyaddr(addr, len, type)) == NULL)
1339 dns_error("Gethostbyaddr error");
1340 return p;
1341}
1342
1343/************************************************
1344 * Wrappers for Pthreads thread control functions
1345 ************************************************/
1346
1347void Pthread_create(pthread_t *tidp, pthread_attr_t *attrp,
1348 void * (*routine)(void *), void *argp)
1349{
1350 int rc;
1351
1352 if ((rc = pthread_create(tidp, attrp, routine, argp)) != 0)
1353 posix_error(rc, "Pthread_create error");
1354}
1355
1356void Pthread_cancel(pthread_t tid) {
1357 int rc;
1358
1359 if ((rc = pthread_cancel(tid)) != 0)
1360 posix_error(rc, "Pthread_cancel error");
1361}
1362
1363void Pthread_join(pthread_t tid, void **thread_return) {
1364 int rc;
1365
1366 if ((rc = pthread_join(tid, thread_return)) != 0)
1367 posix_error(rc, "Pthread_join error");
1368}
1369
1370/* $begin detach */
1371void Pthread_detach(pthread_t tid) {
1372 int rc;
1373
1374 if ((rc = pthread_detach(tid)) != 0)
1375 posix_error(rc, "Pthread_detach error");
1376}
1377/* $end detach */
1378
1379void Pthread_exit(void *retval) {
1380 pthread_exit(retval);
1381}
1382
1383pthread_t Pthread_self(void) {
1384 return pthread_self();
1385}
1386
1387void Pthread_once(pthread_once_t *once_control, void (*init_function)()) {
1388 pthread_once(once_control, init_function);
1389}
1390
1391/*******************************
1392 * Wrappers for Posix semaphores
1393 *******************************/
1394
1395void Sem_init(sem_t *sem, int pshared, unsigned int value)
1396{
1397 if (sem_init(sem, pshared, value) < 0)
1398 unix_error("Sem_init error");
1399}
1400
1401void P(sem_t *sem)
1402{
1403 if (sem_wait(sem) < 0)
1404 unix_error("P error");
1405}
1406
1407void V(sem_t *sem)
1408{
1409 if (sem_post(sem) < 0)
1410 unix_error("V error");
1411}
1412
1413/*********************************************************************
1414 * The Rio package - robust I/O functions
1415 **********************************************************************/
1416/*
1417 * rio_readn - robustly read n bytes (unbuffered)
1418 */
1419/* $begin rio_readn */
1420ssize_t rio_readn(int fd, void *usrbuf, size_t n)
1421{
1422 size_t nleft = n;
1423 ssize_t nread;
1424 char *bufp = usrbuf;
1425
1426 while (nleft > 0) {
1427 if ((nread = read(fd, bufp, nleft)) < 0) {
1428 if (errno == EINTR) /* Interrupted by sig handler return */
1429 nread = 0; /* and call read() again */
1430 else
1431 return -1; /* errno set by read() */
1432 }
1433 else if (nread == 0)
1434 break; /* EOF */
1435 nleft -= nread;
1436 bufp += nread;
1437 }
1438 return (n - nleft); /* return >= 0 */
1439}
1440/* $end rio_readn */
1441
1442/*
1443 * rio_writen - robustly write n bytes (unbuffered)
1444 */
1445/* $begin rio_writen */
1446ssize_t rio_writen(int fd, void *usrbuf, size_t n)
1447{
1448 size_t nleft = n;
1449 ssize_t nwritten;
1450 char *bufp = usrbuf;
1451
1452 while (nleft > 0) {
1453 if ((nwritten = write(fd, bufp, nleft)) <= 0) {
1454 if (errno == EINTR) /* Interrupted by sig handler return */
1455 nwritten = 0; /* and call write() again */
1456 else
1457 return -1; /* errno set by write() */
1458 }
1459 nleft -= nwritten;
1460 bufp += nwritten;
1461 }
1462 return n;
1463}
1464/* $end rio_writen */
1465
1466
1467/*
1468 * rio_read - This is a wrapper for the Unix read() function that
1469 * transfers min(n, rio_cnt) bytes from an internal buffer to a user
1470 * buffer, where n is the number of bytes requested by the user and
1471 * rio_cnt is the number of unread bytes in the internal buffer. On
1472 * entry, rio_read() refills the internal buffer via a call to
1473 * read() if the internal buffer is empty.
1474 */
1475/* $begin rio_read */
1476static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
1477{
1478 int cnt;
1479
1480 while (rp->rio_cnt <= 0) { /* Refill if buf is empty */
1481 rp->rio_cnt = read(rp->rio_fd, rp->rio_buf,
1482 sizeof(rp->rio_buf));
1483 if (rp->rio_cnt < 0) {
1484 if (errno != EINTR) /* Interrupted by sig handler return */
1485 return -1;
1486 }
1487 else if (rp->rio_cnt == 0) /* EOF */
1488 return 0;
1489 else
1490 rp->rio_bufptr = rp->rio_buf; /* Reset buffer ptr */
1491 }
1492
1493 /* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
1494 cnt = n;
1495 if (rp->rio_cnt < n)
1496 cnt = rp->rio_cnt;
1497 memcpy(usrbuf, rp->rio_bufptr, cnt);
1498 rp->rio_bufptr += cnt;
1499 rp->rio_cnt -= cnt;
1500 return cnt;
1501}
1502/* $end rio_read */
1503
1504/*
1505 * rio_readinitb - Associate a descriptor with a read buffer and reset buffer
1506 */
1507/* $begin rio_readinitb */
1508void rio_readinitb(rio_t *rp, int fd)
1509{
1510 rp->rio_fd = fd;
1511 rp->rio_cnt = 0;
1512 rp->rio_bufptr = rp->rio_buf;
1513}
1514/* $end rio_readinitb */
1515
1516/*
1517 * rio_readnb - Robustly read n bytes (buffered)
1518 */
1519/* $begin rio_readnb */
1520ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
1521{
1522 size_t nleft = n;
1523 ssize_t nread;
1524 char *bufp = usrbuf;
1525
1526 while (nleft > 0) {
1527 if ((nread = rio_read(rp, bufp, nleft)) < 0)
1528 return -1; /* errno set by read() */
1529 else if (nread == 0)
1530 break; /* EOF */
1531 nleft -= nread;
1532 bufp += nread;
1533 }
1534 return (n - nleft); /* return >= 0 */
1535}
1536/* $end rio_readnb */
1537
1538/*
1539 * rio_readlineb - robustly read a text line (buffered)
1540 */
1541/* $begin rio_readlineb */
1542ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
1543{
1544 int n, rc;
1545 char c, *bufp = usrbuf;
1546
1547 for (n = 1; n < maxlen; n++) {
1548 if ((rc = rio_read(rp, &c, 1)) == 1) {
1549 *bufp++ = c;
1550 if (c == '\n') {
1551 n++;
1552 break;
1553 }
1554 } else if (rc == 0) {
1555 if (n == 1)
1556 return 0; /* EOF, no data read */
1557 else
1558 break; /* EOF, some data was read */
1559 } else
1560 return -1; /* Error */
1561 }
1562 *bufp = 0;
1563 return n-1;
1564}
1565/* $end rio_readlineb */
1566
1567/**********************************
1568 * Wrappers for robust I/O routines
1569 **********************************/
1570ssize_t Rio_readn(int fd, void *ptr, size_t nbytes)
1571{
1572 ssize_t n;
1573
1574 if ((n = rio_readn(fd, ptr, nbytes)) < 0)
1575 unix_error("Rio_readn error");
1576 return n;
1577}
1578
1579void Rio_writen(int fd, void *usrbuf, size_t n)
1580{
1581 if (rio_writen(fd, usrbuf, n) != n)
1582 unix_error("Rio_writen error");
1583}
1584
1585void Rio_readinitb(rio_t *rp, int fd)
1586{
1587 rio_readinitb(rp, fd);
1588}
1589
1590ssize_t Rio_readnb(rio_t *rp, void *usrbuf, size_t n)
1591{
1592 ssize_t rc;
1593
1594 if ((rc = rio_readnb(rp, usrbuf, n)) < 0)
1595 unix_error("Rio_readnb error");
1596 return rc;
1597}
1598
1599ssize_t Rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
1600{
1601 ssize_t rc;
1602
1603 if ((rc = rio_readlineb(rp, usrbuf, maxlen)) < 0)
1604 unix_error("Rio_readlineb error");
1605 return rc;
1606}
1607
1608/********************************
1609 * Client/server helper functions
1610 ********************************/
1611/*
1612 * open_clientfd - open connection to server at <hostname, port>
1613 * and return a socket descriptor ready for reading and writing.
1614 * Returns -1 and sets errno on Unix error.
1615 * Returns -2 and sets h_errno on DNS (gethostbyname) error.
1616 */
1617/* $begin open_clientfd */
1618int open_clientfd(char *hostname, int port)
1619{
1620 int clientfd;
1621 struct hostent *hp;
1622 struct sockaddr_in serveraddr;
1623
1624 if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
1625 return -1; /* Check errno for cause of error */
1626
1627 /* Fill in the server's IP address and port */
1628 if ((hp = gethostbyname(hostname)) == NULL)
1629 return -2; /* Check h_errno for cause of error */
1630 bzero((char *) &serveraddr, sizeof(serveraddr));
1631 serveraddr.sin_family = AF_INET;
1632 bcopy((char *)hp->h_addr_list[0],
1633 (char *)&serveraddr.sin_addr.s_addr, hp->h_length);
1634 serveraddr.sin_port = htons(port);
1635
1636 /* Establish a connection with the server */
1637 if (connect(clientfd, (SA *) &serveraddr, sizeof(serveraddr)) < 0)
1638 return -1;
1639 return clientfd;
1640}
1641/* $end open_clientfd */
1642
1643/*
1644 * open_listenfd - open and return a listening socket on port
1645 * Returns -1 and sets errno on Unix error.
1646 */
1647/* $begin open_listenfd */
1648int open_listenfd(int port)
1649{
1650 int listenfd, optval=1;
1651 struct sockaddr_in serveraddr;
1652
1653 /* Create a socket descriptor */
1654 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
1655 return -1;
1656
1657 /* Eliminates "Address already in use" error from bind */
1658 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
1659 (const void *)&optval , sizeof(int)) < 0)
1660 return -1;
1661
1662 /* Listenfd will be an endpoint for all requests to port
1663 on any IP address for this host */
1664 bzero((char *) &serveraddr, sizeof(serveraddr));
1665 serveraddr.sin_family = AF_INET;
1666 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
1667 serveraddr.sin_port = htons((unsigned short)port);
1668 if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0)
1669 return -1;
1670
1671 /* Make it a listening socket ready to accept connection requests */
1672 if (listen(listenfd, LISTENQ) < 0)
1673 return -1;
1674 return listenfd;
1675}
1676/* $end open_listenfd */
1677
1678/******************************************
1679 * Wrappers for the client/server helper routines
1680 ******************************************/
1681int Open_clientfd(char *hostname, int port)
1682{
1683 int rc;
1684
1685 if ((rc = open_clientfd(hostname, port)) < 0) {
1686 if (rc == -1)
1687 unix_error("Open_clientfd Unix error");
1688 else
1689 dns_error("Open_clientfd DNS error");
1690 }
1691 return rc;
1692}
1693
1694int Open_listenfd(int port)
1695{
1696 int rc;
1697
1698 if ((rc = open_listenfd(port)) < 0)
1699 unix_error("Open_listenfd error");
1700 return rc;
1701}
1702/* $end csapp.c */
1703=============================================================================makefile
1704CFLAGS = -Wall
1705CPPFLAGS = -Wall
1706
1707SERVER = simpled
1708CLIENTS = ssSet ssGet ssDigest ssRun
1709
1710all: $(SERVER) $(CLIENTS)
1711
1712csapp.h:
1713 wget http://csapp.cs.cmu.edu/2e/ics2/code/include/csapp.h
1714
1715csapp.c:
1716 wget http://csapp.cs.cmu.edu/2e/ics2/code/src/csapp.c
1717
1718csapp.o: csapp.h csapp.c
1719 gcc $(CFLAGS) -c csapp.h csapp.c
1720
1721packets.o: packets.h packets.cpp
1722 g++ $(CPPFLAGS) -std=c++11 -c packets.h packets.cpp
1723
1724clients: ssSet ssGet ssDigest ssRun
1725
1726simpled: simpled.cpp csapp.o packets.o
1727 g++ $(CPPFLAGS) -std=c++11 simpled.cpp csapp.o packets.o -lpthread -o simpled
1728
1729ssSet: ssSet.cpp csapp.o packets.o
1730 g++ $(CPPFLAGS) -std=c++11 ssSet.cpp csapp.o packets.o -lpthread -o ssSet
1731
1732ssGet: ssGet.cpp csapp.o packets.o
1733 g++ $(CPPFLAGS) -std=c++11 ssGet.cpp csapp.o packets.o -lpthread -o ssGet
1734
1735ssDigest: ssDigest.cpp csapp.o packets.o
1736 g++ $(CPPFLAGS) -std=c++11 ssDigest.cpp csapp.o packets.o -lpthread -o ssDigest
1737
1738ssRun: ssRun.cpp csapp.o packets.o
1739 g++ $(CPPFLAGS) -std=c++11 ssRun.cpp csapp.o packets.o -lpthread -o ssRun
1740
1741.PHONY: clean
1742clean:
1743 /bin/rm -rf csapp.h csapp.c *.o simpled ssSet ssGet ssDigest ssRun