1 /*****************************************************************
2 ** File Name:client.c
3 * Author:Maxiao
4 * Date:2003.5.23
5 *****************************************************************/
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <stdlib.h>
9 #include <limits.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <netdb.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
17 #include <errno.h>
18 #include <dirent.h>
19
20 #define MAX_INPUT_SIZE 254
21 #define SERVICE_PORT 3482
22 #define FILEBUF_SIZE 1000
23
24
25 unsigned int get(char * filename, char * server);
26 unsigned int put(char * filename, char * server);
27 unsigned int pwd(char * server);
28 unsigned int dir(char * server);
29 unsigned int rcd(char * filename, char * server);
30 void help();
31 void lpwd();
32 void ldir();
33 void lcd(char * filename);
34
35 int main(int argc, char *argv[]) {
36 char line_in[MAX_INPUT_SIZE+1];
37 unsigned int bytes;
38
39 line_in[0] = \'\0\';
40
41 /* Enforce the correct usage */
42 if (argc != 2) {
43 printf("\nUsage: \"./client ServerName( or IpAddress)\"\n");
44 exit(1);
45 }
46
47 /* Print a welcome and instructions */
48 help();
49
50 printf("\n> "); /* First prompt */
51
52 while (strncmp("quit", line_in, 4) != 0) { /* As long as "quit" wasn\'t entered */
53 fgets(line_in, MAX_INPUT_SIZE, stdin); /* Get the input line */
54 line_in[strlen(line_in)-1] = \'\0\'; /* Replace the newline that gets copied */
55
56 if (strncmp("quit", line_in, 4) != 0) { /* If it\'s not "quit" */
57 if (strncmp("put", line_in, 3) == 0) {
58 /* PUT command... */
59 if ((bytes=put(&(line_in[4]), argv[1]))) {
60 printf("put successful: %d bytes sent to server", bytes);
61 } else {
62 printf("put unsuccessful...");
63 }
64 } else if (strncmp("get", line_in, 3) == 0) {
65 /* GET command... */
66 if ((bytes=get(&(line_in[4]), argv[1]))) {
67 printf("get successful: %d bytes retrieved from server", bytes);
68 } else {
69 printf("get unsuccessful... file probably does not exist");
70 }
71 } else if (strncmp("dir", line_in, 3) == 0) {
72 /* dir command... (remote) */
73 if (dir(argv[1])==0) {
74 printf("Unable to retrieve remote directory listing!");
75 }
76 } else if (strncmp("ldir", line_in, 4) == 0) {
77 /* ldir command... (local) */
78 ldir();
79 } else if (strncmp("lpwd", line_in, 3) == 0) {
80 /* lpwd command... (local) */
81 lpwd();
82 } else if (strncmp("?", line_in, 1) == 0) {
83 /* ? command... (local) */
84 help();
85 } else if (strncmp("pwd", line_in, 3) == 0) {
86 /* pwd command... (remote) */
87 if (pwd(argv[1])==0) {
88 printf("Unable to retrieve remote directory listing!");
89 }
90 } else if (strncmp("rcd", line_in, 3) == 0) {
91 /* rcd command... (remote)*/
92 if ((bytes=rcd(&(line_in[4]), argv[1]))) {
93 printf("get unsuccessful.", bytes);
94 } else {
95 printf(&(line_in[4]));
96 }
97 } else if (strncmp("lcd", line_in, 3) == 0) {
98 /* lcd command... (local)*/
99 lcd(&(line_in[4])) ;
100
101 } else {
102 printf("Unrecognized command!");
103 }
104 printf("\n> "); /* Next prompt */
105 }
106 }
107
108 exit(0);
109 }
110
111 /*show the help info*/
112 void help() {
113 printf("\nWelcome to FTP program client!\n");
114 printf("Valid commands are (case sensitive):\n");
115 printf("\tget\t\tPlaces a remote file in the local directory\n");
116 printf("\tput\t\tPlaces a local file in the remote directory\n");
117 printf("\tpwd\t\tLists a remote current directory\n");
118 printf("\tdir\t\tLists the contents of the remote directory\n");
119 printf("\trcd\t\tChange a remote current directory\n");
120 printf("\t?\t\tFor help\n");
121 printf("\tquit\t\tExits the program\n");
122 printf("\tlpwd\t\tLists a local current directory\n");
123 printf("\tldir\t\tLists the contents of the local directory\n");
124 printf("\tlcd\t\tChange client current directory\n");
125 }
126
127 /*Places a local file in the remote directory*/
128 unsigned int put(char * filename, char * server) {
129 int sck;
130 struct sockaddr_in serv_adr;
131 struct hostent *host;
132 FILE *infile;
133 unsigned char databuf[FILEBUF_SIZE];
134 int bytes = 0, bytesread = 0;
135
136 /* Open the file locally */
137 if ((infile = fopen(filename, "r")) == 0) {
138 perror("fopen failed to open file");
139 return 0;
140 }
141
142 /* Attempt to get the IP for the server by hostname */
143 host = gethostbyname(server);
144 if (host == (struct hostent *) NULL) {
145 perror("gethostbyname failed");
146 return 0;
147 }
148
149 /* Setup the port for the connection */
150 memset(&serv_adr, 0, sizeof(serv_adr));
151 serv_adr.sin_family = AF_INET;
152 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length);
153 serv_adr.sin_port = htons(SERVICE_PORT);
154
155 /* Get the socket */
156 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
157 perror("error on socket()");
158 return 0;
159 }
160
161 /* Connect to the server */
162 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) {
163 perror("error on connect()");
164 return 0;
165 }
166
167 /* Write the command & filename, followed by two newlines */
168 write(sck, "PUT ", 4);
169 write(sck, filename, strlen(filename));
170 write(sck, "\n\n", 2);
171
172 /* Read from the file and write to the socket */
173 while ((bytes = read(fileno(infile), databuf, FILEBUF_SIZE)) > 0) {
174 write(sck, databuf, bytes);
175 bytesread += bytes;
176 }
177
178 /* Close the file */
179 fclose(infile);
180
181 if ((bytes = read(sck, databuf, 2)) > 0) {
182 /* Read the status bytes from the server, print and return accordingly */
183 if ((databuf[0] == \'E\') && (databuf[1] == \'R\')) {
184 printf("Server error on PUT!\n");
185 close(sck);
186 return 0;
187 } else if ((databuf[0] == \'N\') && (databuf[1] == \'W\')) {
188 printf("File created on server\n");
189 close(sck);
190 return bytesread;
191 } else if ((databuf[0] == \'U\') && (databuf[1] == \'P\')) {
192 printf("File updated on server\n");
193 close(sck);
194 return bytesread;
195 }
196 } else return 0;
197 }
198
199 /*Places a remote file in the local directory*/
200 unsigned int get(char * filename, char * server) {
201 int sck;
202 struct sockaddr_in serv_adr;
203 struct hostent *host;
204 FILE *outfile;
205 short file_open=0;
206 unsigned char databuf[FILEBUF_SIZE];
207 int bytes = 0, bytesread = 0;
208
209 /* Attempt to get the IP for the server by hostname */
210 host = gethostbyname(server);
211 if (host == (struct hostent *) NULL) {
212 perror("gethostbyname failed");
213 return 0;
214 }
215
216 /* Setup the port for the connection */
217 memset(&serv_adr, 0, sizeof(serv_adr));
218 serv_adr.sin_family = AF_INET;
219 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length);
220 serv_adr.sin_port = htons(SERVICE_PORT);
221
222 /* Get the socket */
223 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
224 perror("error on socket()");
225 return 0;
226 }
227
228 /* Connect to the server */
229 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) {
230 perror("error on connect()");
231 return 0;
232 }
233
234 /* Write the command & filename, followed by two newlines */
235 write(sck, "GET ", 4);
236 write(sck, filename, strlen(filename));
237 write(sck, "\n\n", 2);
238
239 /* Read from the socket and write to the file */
240 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) {
241 if (file_open == 0) {
242 /* Open the file the first time we actually read data */
243 if ((outfile = fopen(filename, "w")) == 0) {
244 perror("fopen failed to open file");
245 close(sck);
246 return 0;
247 }
248 file_open = 1;
249 }
250 write(fileno(outfile), databuf, bytes);
251 bytesread += bytes;
252 }
253
254 /* Close the file and socket */
255 if (file_open != 0) fclose(outfile);
256 close(sck);
257
258 return bytesread;
259 }
260
261 /*Lists the contents of the remote directory*/
262 unsigned int dir(char * server) {
263 int sck;
264 struct sockaddr_in serv_adr;
265 struct hostent *host;
266 unsigned char databuf[FILEBUF_SIZE];
267 int bytes = 0, bytesread = 0;
268
269 /* Attempt to get the IP for the server by hostname */
270 host = gethostbyname(server);
271 if (host == (struct hostent *) NULL) {
272 perror("gethostbyname failed");
273 return 0;
274 }
275
276 /* Setup the port for the connection */
277 memset(&serv_adr, 0, sizeof(serv_adr));
278 serv_adr.sin_family = AF_INET;
279 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length);
280 serv_adr.sin_port = htons(SERVICE_PORT);
281
282 /* Get the socket */
283 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
284 perror("error on socket()");
285 return 0;
286 }
287
288 /* Connect to the server */
289 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) {
290 perror("error on connect()");
291 return 0;
292 }
293
294 /* Write the command followed by two newlines */
295 write(sck, "DI\n\n", 4);
296
297 printf("Remote directory listing:\n");
298
299 /* Read from the socket and write to stdout */
300 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) {
301 write(fileno(stdout), databuf, bytes);
302 bytesread += bytes;
303 }
304
305 close(sck); /* Close the socket */
306
307 return bytesread;
308 }
309
310 /*ists the contents of the local directory*/
311 void ldir() {
312 FILE *fcmd;
313 char buffer[PIPE_BUF];
314 int n;
315
316 printf("Local directory listing:\n");
317
318 /* Open the pipe to the ls command */
319 if ((fcmd = popen("ls -l", "r")) == 0) {
320 perror("popen error");
321 return;
322 }
323
324 /* Read from the pipe and write to stdout */
325 while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0)
326 write(fileno(stdout), buffer, n);
327
328 /* Close the pipe */
329 if (pclose(fcmd) != 0) {
330 printf("Non-zero return value from \"ldir\"");
331 }
332 }
333
334 /*Lists a local current directory*/
335 unsigned int pwd(char * server) {
336 int sck;
337 struct sockaddr_in serv_adr;
338 struct hostent *host;
339 unsigned char databuf[FILEBUF_SIZE];
340 int bytes = 0, bytesread = 0;
341
342 /* Attempt to get the IP for the server by hostname */
343 host = gethostbyname(server);
344 if (host == (struct hostent *) NULL) {
345 perror("gethostbyname failed");
346 return 0;
347 }
348
349 /* Setup the port for the connection */
350 memset(&serv_adr, 0, sizeof(serv_adr));
351 serv_adr.sin_family = AF_INET;
352 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length);
353 serv_adr.sin_port = htons(SERVICE_PORT);
354
355 /* Get the socket */
356 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
357 perror("error on socket()");
358 return 0;
359 }
360
361 /* Connect to the server */
362 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) {
363 perror("error on connect()");
364 return 0;
365 }
366
367 /* Write the command followed by two newlines */
368 write(sck, "PW\n\n", 4);
369
370
371 printf("Remote directory listing:\n");
372
373 /* Read from the socket and write to stdout */
374 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) {
375
376 write(fileno(stdout), databuf, bytes);
377 bytesread += bytes;
378 }
379
380 close(sck); /* Close the socket */
381
382 return bytesread;
383 }
384 void lpwd() {
385 FILE *fcmd;
386 char buffer[PIPE_BUF];
387 int n;
388
389 printf("Local directory listing:\n");
390
391 /* Open the pipe to the ls command */
392 if ((fcmd = popen("pwd", "r")) == 0) {
393 perror("popen error");
394 return;
395 }
396
397 /* Read from the pipe and write to stdout */
398 while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0)
399 write(fileno(stdout), buffer, n);
400
401 /* Close the pipe */
402 if (pclose(fcmd) != 0) {
403 printf("Non-zero return value from \"lpwd\"");
404 }
405 }
406
407 unsigned int rcd(char * filename, char * server) {
408 int sck;
409 struct sockaddr_in serv_adr;
410 struct hostent *host;
411 unsigned char databuf[FILEBUF_SIZE];
412 int bytes = 0, bytesread = 0;
413
414 /* Attempt to get the IP for the server by hostname */
415 host = gethostbyname(server);
416 if (host == (struct hostent *) NULL) {
417 perror("gethostbyname failed");
418 return 0;
419 }
420
421 /* Setup the port for the connection */
422 memset(&serv_adr, 0, sizeof(serv_adr));
423 serv_adr.sin_family = AF_INET;
424 memcpy(&serv_adr.sin_addr, host->h_addr, host->h_length);
425 serv_adr.sin_port = htons(SERVICE_PORT);
426
427 /* Get the socket */
428 if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
429 perror("error on socket()");
430 return 0;
431 }
432
433 /* Connect to the server */
434 if (connect(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) {
435 perror("error on connect()");
436 return 0;
437 }
438
439 /* Write the command followed by two newlines */
440 write(sck, "RC ", 4);
441 write(sck, filename, strlen(filename));
442 write(sck, "\n\n", 2);
443
444 printf("Current remote directory has changed, now is :\n");
445
446 /* Read from the socket and write to stdout */
447 while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0) {
448 write(fileno(stdout), databuf, bytes);
449 bytesread += bytes;
450 }
451
452 close(sck); /* Close the socket */
453
454 return bytesread;
455 }
456
457 void lcd(char * filename) {
458 FILE *fcmd;
459 char buffer[PIPE_BUF];
460 int n;
461 chdir(filename);
462 printf("Current client directory has changed ,now is:\n");
463 printf(filename);
464 printf("\n");
465
466 }
/*****************************************************************
** File Name:server.c
* Author:Maxiao
* Date:2003.5.23
*****************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <dirent.h>
#define MAX_INPUT_SIZE 254
#define SERVICE_PORT 3482
#define FILEBUF_SIZE 1000
void get(char * filename, int sck);
void put(char * filename, int sck);
void rcd(char * filename, int sck);
void dir(int sck);
void pwd(int sck);
int main(int argc, char *argv[]) {
char buffer[FILEBUF_SIZE];
int sck, clnt_sck;
int clnt_len;
int i = 0;
int opt;
struct sockaddr_in serv_adr, clnt_adr;
printf("\nWelcome to FTP program server!\n");
/* Get the socket */
if ((sck = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("error on socket()");
exit(1);
}
/* This is to avoid the 120-second timeout on the port when the server is killed */
opt = 1;
if (setsockopt(sck, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) {
perror("setsockopt error");
exit(2);
}
/* Configure the server address, port, etc. */
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_adr.sin_port = htons(SERVICE_PORT);
/* Bind this port to this process */
if (bind(sck, (struct sockaddr *)&serv_adr, sizeof(serv_adr)) < 0) {
perror("bind error");
exit(3);
}
/* Listen on this port for incoming connections */
if (listen(sck, 5) < 0) {
perror("listen error");
exit(4);
}
/* Infinite loop */
while (1) {
i=0;
clnt_len = sizeof(clnt_adr);
/* Accept an incoming request */
if ((clnt_sck = accept(sck, (struct sockaddr *) &clnt_adr, &clnt_len)) < 0) {
perror("accept error");
close(sck);
exit(5);
}
/* Get the first two bytes to see what it is */
read(clnt_sck, buffer, 2);
if ((buffer[0] == \'G\') && (buffer[1] == \'E\')) {
/* It\'s a GET */
read(clnt_sck, buffer, 2); /* Consume the "T " */
read(clnt_sck, buffer, 2); /* Start reading the filename */
/* Read until we get a newline or two */
while ((buffer[i] != \'\n\') && (buffer[i+1] != \'\n\')) {
i += 2;
read(clnt_sck, &buffer[i], 2);
}
/* If we only got one newline, consume the second, then place the null in the proper place */
if (buffer[i] == \'\n\') buffer[i] = \'\0\';
else {
read(clnt_sck, &buffer[i+1], 1);
buffer[i+1] = \'\0\';
}
get(buffer, clnt_sck); /* Do the actual GET */
} else if ((buffer[0] == \'P\') && (buffer[1] == \'U\')) {
/* It\'s a PUT */
read(clnt_sck, buffer, 2); /* Consume the "T " */
read(clnt_sck, buffer, 2); /* Start reading the filename */
/* Read until we get a newline or two */
while ((buffer[i] != \'\n\') && (buffer[i+1] != \'\n\')) {
i += 2;
read(clnt_sck, &buffer[i], 2);
}
/* If we only got one newline, consume the second, then place the null in the proper place */
if (buffer[i] == \'\n\') buffer[i] = \'\0\';
else {
read(clnt_sck, &buffer[i+1], 1);
buffer[i+1] = \'\0\';
}
put(buffer, clnt_sck); /* Do the actual PUT */
} else if ((buffer[0] == \'R\') && (buffer[1] == \'C\')) {
/* It\'s a PUT */
read(clnt_sck, buffer, 2); /* Consume the "T " */
read(clnt_sck, buffer, 2); /* Start reading the filename */
/* Read until we get a newline or two */
while ((buffer[i] != \'\n\') && (buffer[i+1] != \'\n\')) {
i += 2;
read(clnt_sck, &buffer[i], 2);
}
/* If we only got one newline, consume the second, then place the null in the proper place */
if (buffer[i] == \'\n\') buffer[i] = \'\0\';
else {
read(clnt_sck, &buffer[i+1], 1);
buffer[i+1] = \'\0\';
}
rcd(buffer, clnt_sck); /* Do the actual PUT */
} else if ((buffer[0] == \'D\') && (buffer[1] == \'I\')) {
/* It\'s an LS */
read(clnt_sck, buffer, 2); /* Consume the two newlines */
dir(clnt_sck); /* Perform the LS */
} else if ((buffer[0] == \'P\') && (buffer[1] == \'W\')) {
/* It\'s an LS */
read(clnt_sck, buffer, 2); /* Consume the two newlines */
pwd(clnt_sck); /* Perform the LS */
}
close(clnt_sck); /* Close the incoming client connection */
}
exit(0); /* This will never happen */
}
void put(char * filename, int sck) {
FILE *outfile;
unsigned char databuf[FILEBUF_SIZE];
struct stat sbuf;
int bytes = 0;
char return_code[2];
/* stat() the file to see if it\'s an update or create */
if (stat(filename, &sbuf) == -1) {
return_code[0] = \'N\'; return_code[1] = \'W\';
} else {
return_code[0] = \'U\'; return_code[1] = \'P\';
}
/* Return the appropriate status code */
write(sck, return_code, 2);
if ((outfile = fopen(filename, "w")) == 0) {
perror("fopen failed to open file");
/* Return the error status code */
return_code[0] = \'E\'; return_code[1] = \'R\';
write(sck, return_code, 2);
return;
}
/* Read the incoming bytes and write to the file */
while ((bytes = read(sck, databuf, FILEBUF_SIZE)) > 0)
write(fileno(outfile), databuf, bytes);
/* Close the file */
fclose(outfile);
}
void get(char * filename, int sck) {
FILE *infile;
unsigned char databuf[FILEBUF_SIZE];
int bytes = 0;
/* Open up the file locally */
if ((infile = fopen(filename, "r")) == 0) {
perror("fopen failed to open file");
return;
}
/* Read from the file and write the bytes to the socket */
while ((bytes = read(fileno(infile), databuf, FILEBUF_SIZE)) > 0)
write(sck, databuf, bytes);
/* Close the file */
fclose(infile);
}
/* Read from the file and write the bytes to the socket */
void dir(int sck) {
FILE *fcmd;
char buffer[PIPE_BUF];
int n;
/* Open the pipe to the ls -l command */
if ((fcmd = popen("ls -l", "r")) == 0) {
perror("popen error");
return;
}
/* Read from the pipe and write to the socket */
while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0)
write(sck, buffer, n);
/* Close the pipe - we should never get a non-zero return from ls */
if (pclose(fcmd) != 0) {
printf("Non-zero return value from \"ls -l\"");
}
}
void pwd(int sck) {
FILE *fcmd;
char buffer[PIPE_BUF];
int n;
/* Open the pipe to the ls -l command */
if ((fcmd = popen("pwd", "r")) == 0) {
perror("popen error");
return;
}
/* Read from the pipe and write to the socket */
while ((n = read(fileno(fcmd), buffer, PIPE_BUF)) > 0)
write(sck, buffer, n);
/* Close the pipe - we should never get a non-zero return from ls */
if (pclose(fcmd) != 0) {
printf("Non-zero return value from \"ls -l\"");
}
}
void rcd(char *filename, int sck) {
FILE *fcmd;
char buffer[PIPE_BUF];
int n;
chdir(filename);
}