MES3.0はLinuxの下位互換性であり、MES3.0のユーザープログラムは原則としてLinuxでも同じソースコードで動作します。
以下、MES3.0で動作確認されたLinuxとソースコード互換のFTPクライアントの例です。
/****************************************/
/* Ftp client for anonymous ftp server */
/* Enable commands */
/* pwd */
/* cd [pass] */
/* dir */
/* get [pass] */
/* quit */
/****************************************/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <time.h>
#include <netdb.h>
#include <errno.h>
#define TIMOUT 4
#define BUFFSIZ 0x600
#define CMDSIZ 0x200
static char *buf, *cmd, *inp, echo;
static int get_status(int sock) {
int n, len, code;
char *p, *line;
int i;
buf[1] = 0;
p = buf;
do {
line = ++p;
if(line[0] == 0) {
bzero(buf, BUFFSIZ);
n = read(sock, buf, BUFFSIZ);
if(n <= 0) return -1;
line = buf;
}
p = strchr(line, '\n');
*p = 0;
if(echo) {
if(isdigit(line[0]) && isdigit(line[1]) && isdigit(line[2])) {
printf("%s", &line[4]);
} else {
printf("%s", line);
}
}
} while(!isdigit(line[0]) || !isdigit(line[1]) || !isdigit(line[2]) || line[3] != ' ');
putchar('\n');
sscanf(line, "%d", &code);
return code;
}
int main(int argc, char **argv) {
char *p, *p2, *file;
int i, j, ret, code, emport, n, cnt, retry, len;
unsigned int servip, ftpsk, datask;
FILE *fp;
struct sockaddr_in target, target2, serv;
struct hostent *hp;
struct timeval tv;
echo = 1;
if(argc != 2) {
printf("Usage : %s ftpserver\n", argv[0]);
return -1;
}
buf = malloc(BUFFSIZ + CMDSIZ * 2);
if(buf == NULL) {
printf("No memory\n");
return -1;
}
cmd = &buf[BUFFSIZ];
inp = &cmd[CMDSIZ];
hp = gethostbyname(argv[1]);
if(hp == NULL) {
printf("Ftp server not found\n");
free(buf);
return -1;
}
bcopy(hp->h_addr_list[0], &(serv.sin_addr), hp->h_length);
ftpsk = socket(AF_INET, SOCK_STREAM, 0);
if(ftpsk == -1) {
printf("No more socket\n");
free(buf);
return -1;
}
getsockopt(ftpsk, SOL_SOCKET, SO_RCVTIMEO, &tv, &len);
tv.tv_sec = TIMOUT;
tv.tv_usec = 0;
setsockopt(ftpsk, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
serv.sin_family = AF_INET;
serv.sin_port = htons(21);
ret = connect(ftpsk, (struct sockaddr *)&serv, sizeof(serv));
if(ret == -1) {
printf("FTP server connect error(1)\n");
close(ftpsk);
free(buf);
return -1;
}
code = get_status(ftpsk);
if(code != 220) {
printf("FTP server connect error(2)\n");
close(ftpsk);
free(buf);
return -1;
}
write(ftpsk, "USER anonymous\r\n", 16);
code = get_status(ftpsk);
if(code != 230) {
if(code == 331) {
write(ftpsk, "PASS MESUser@\r\n", 15);
code = get_status(ftpsk);
}
if(code != 230) {
printf("User connect error!\n");
close(ftpsk);
free(buf);
return -1;
}
}
for(;;) {
printf("ftp> ");
fgets(inp, CMDSIZ, stdin);
p = strchr(inp, (int)'\n');
*p = 0;
if(strcmp(inp, "quit") == 0) {
break;
} else if(strcmp(inp, "help") == 0) {
puts("Enable commands");
puts("\tpwd\n\tcd [pass]\n\tdir\n\tget [pass]\n\tquit");
continue;
} else if(strcmp(inp, "pwd") == 0) {
write(ftpsk, "PWD\r\n", 5);
get_status(ftpsk);
} else if(memcmp(inp, "cd ", 3) == 0) {
strcpy(cmd, "CWD ");
strcat(cmd, &inp[3]);
strcat(cmd, "\r\n");
write(ftpsk, cmd, strlen(cmd));
get_status(ftpsk);
} else if(strcmp(inp, "dir") == 0 || memcmp(inp, "get ", 4) == 0) {
if(strcmp(inp, "dir") == 0) {
strcpy(cmd, "LIST\r\n");
write(ftpsk, "TYPE A\r\n", 8);
fp = NULL;
}
if(memcmp(inp, "get ", 4) == 0) {
file = &inp[4];
if(strlen(file) == 0) continue;
strcpy(cmd, "RETR ");
strcat(cmd, &inp[4]);
strcat(cmd, "\r\n");
fp = fopen(file, "wb");
if(fp == NULL) continue;
write(ftpsk, "TYPE I\r\n", 8);
}
get_status(ftpsk);
write(ftpsk, "PASV\r\n", 6);
get_status(ftpsk);
p = buf;
for(i = 0;i < 4;i++) {
p = strchr(p, ',');
p++;
}
p2 = strchr(p, ',');
*p2 = 0;
sscanf(p, "%d", &i);
p = p2 + 1;
p2 = strchr(p, ')');
*p2 = 0;
sscanf(p, "%d", &j);
emport = (i << 8) + j;
datask = socket(AF_INET, SOCK_STREAM, 0);
if(datask == -1) {
printf("No more socket\n");
if(fp != NULL) fclose(fp);
continue;
}
target2.sin_family = AF_INET;
target2.sin_port = htons(20);
target2.sin_addr.s_addr = INADDR_ANY;
ret = bind(datask, (struct sockaddr *)&target2, sizeof(target2));
target2.sin_family = AF_INET;
bcopy(hp->h_addr_list[0], &(target2.sin_addr), hp->h_length);
target2.sin_port = htons(emport);
ret = connect(datask, (struct sockaddr *)&target2, sizeof(target2));
if(ret == -1) {
printf("FTP server connect error\n");
close(datask);
if(fp != NULL) fclose(fp);
continue;
}
write(ftpsk, cmd, strlen(cmd));
code = get_status(ftpsk);
if((code / 100) == 5) {
close(datask);
continue;
}
getsockopt(datask, SOL_SOCKET, SO_RCVTIMEO, &tv, &len);
tv.tv_sec = TIMOUT;
tv.tv_usec = 0;
setsockopt(datask, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
cnt = 0;
for(;;) {
cnt++;
n = read(datask, buf, BUFFSIZ);
if(n > 0){
if(strcmp(inp, "dir") == 0) {
write(1, buf, n);
}
if(memcmp(inp, "get ", 4) == 0) {
fwrite(buf, 1, n, fp);
if((cnt & 0x0f) == 0) {
putchar('.');
fflush(stdout);
}
}
} else {
break;
}
}
if(fp != NULL) fclose(fp);
close(datask);
for(i = 0;i < TIMOUT;i++) {
code = get_status(ftpsk);
if(code != -1) break;
sleep(1);
}
if(code == -1) {
echo = 0;
write(ftpsk, "ERR\r\n", 5);
while(get_status(ftpsk) <= 299);
echo = 1;
}
} else {
printf("Command not found.\n");
}
}
close(ftpsk);
free(buf);
return 0;
}