int dealrecvfile(int sockfd) { char name[128]; int nread,fd; again: if((nread=Readline(sockfd,name,sizeof(name)))>0) name[nread-1]='\0';//remove the '\n' fo the tail else { log_msg("client terminated early"); Close(sockfd); exit(1); } if(access(name,F_OK)==0)//file existed { Writen(sockfd,error,strlen(error)); goto again; } Writen(sockfd,right,strlen(right)); fd=open(name,O_CREAT|O_WRONLY,S_IRWXU);//在这里不使用包装函数,是为了记录信息 if(fd<0) { log_err("connot open file %s",name); log_msg("receive file %s failed",name); return -1; } recvfile(sockfd,fd); log_msg("receive file %s completed",name); Close(fd); return 0; }
int main(int argc, char *argv[]) { if(argc != 6) { die_with_err("Incorrect number of arguments\n" "receiver <filename> <listening_port> <sender_IP> " "<sender_port> <log_filename>"); } FILE *fp = fopen(argv[1], "wb"); if(fp == nullptr) { die_with_err("Failed to creater file"); } FILE *log = (strcmp("stdout", argv[5]) ? fopen(argv[5], "w") : stdout); if(log == nullptr) { die_with_err("Failed to creater file"); } int recv_sock = udp_init_listen(argv[2]); int send_sock = create_tcpsock(argv[3], argv[4]); if(recvfile(fp, recv_sock, send_sock, log)) { printf("Delivery was unsuccessful\n"); } else { printf("Delivery completed successfully\n"); } fclose(fp); if(log != stdout) fclose(log); close(recv_sock); close(send_sock); return 0; }
void *doftp(void *sd) { int req, msg_ok, ret = 0,dump; long ssock = (long)sd; ret = auth_user(ssock); if (ret == -1) { close(ssock); return; } while(1) { req = 0; if((readn(ssock,(char *)&req,sizeof(req))) < 0) { printf("server: read error %d\n",errno); return; } req = ntohs(req); switch(req) { case STOREFILE: status=sendfile(ssock); break; case REQUESTFILE: status=recvfile(ssock); break; case MKDIR: status=makedir(ssock); break; case LIST: status=listdir(ssock); break; case DELETEFILE: status=deletefile(ssock); break; case END: printf("Client sent request to end connection.\n"); close(ssock); return; default: break; } if(status==-1) break; } return; }
void *doftp(void *sd) { int req, msg_ok; long ssock = (long)sd; auth_user(ssock); while(1) { req = 0; if((readn(ssock,(char *)&req,sizeof(req))) < 0) { printf("server: read error %d\n",errno); exit(0); } req = ntohs(req); switch(req) { case STOREFILE: sendfile(ssock); break; case REQUESTFILE: recvfile(ssock); break; default: printf("server: command not supported\n"); msg_ok = COMMANDNOTSUPPORTED; msg_ok = htons(msg_ok); if((writen(ssock,(char *)&msg_ok,sizeof(msg_ok))) < 0) { printf("server: write error :%d\n",errno); exit(0); } } } }
/** *函数说明:完成从服务器下载文件的过程 *参数说明:参数1是连接服务器的socket描述符 */ void download(int st) { //等待服务器返回的可下载文件列表 struct fileinfo filelist[100]; memset(filelist, 0, sizeof(filelist)); recv(st, filelist, sizeof(filelist), 0); //获得文件数目,如果为0,那么返回 if (getfilenum(filelist) == 0) { printf("server has no file to download\n"); return; } //将文件列表显示出来 showfilelist(filelist); //得到一个合法的文件名,将其文件信息发送给服务器 struct fileinfo file; char file_md5_server[100] = {0};//存储服务器文件的md5值 while(1) { printf("enter a file name to download:\n"); //从键盘输入文件名,如果错误,重新输入 memset(&file, 0, sizeof(file)); if (getfile(&file) == -1) { continue; } send(st, &file, sizeof(file), 0); //判断文件是否可以下载,如果可以,那么退出循环 if (candownload(st, file_md5_server, sizeof(file_md5_server)) == 0) { break; } } //得到文件的完整路径 long long filesize = getfilesize(filelist, file.filename); char file_dir[128]; memset(file_dir, 0, sizeof(file_dir)); strcpy(file_dir, CLIENT_FILES_DIR); strcat(file_dir, file.filename); //得到该文件在本地的大小,如果不存在,则为0 struct stat64 filestat; long long file_cur_size = 0; if (lstat64(file_dir, &filestat) == 0) { file_cur_size = filestat.st_size; } //接收文件,如果是正常接收,那么校验MD5 while (recvfile(file_dir, filesize, file_cur_size, st) == 0) { //判断md5值是否正确,正确则接收完毕,否则重新接收 //得到本地文件的md5值 char file_md5_local[100] = {0}; getfile_md5(file_dir, file_md5_local); if (strcmp(file_md5_local, file_md5_server) == 0) { printf("check MD5, MD5 is correct!\n"); //给服务器发送接收完毕信息 int i = 0; send(st, &i, sizeof(i), 0); break; } else { printf("check MD5, MD5 is not correct!recv agin!\n"); file_cur_size = 0; //给服务器发送重新接收信息 int i = -1; send(st, &i, sizeof(i), 0); } } }
void do_select(int msock) { int max_fd, msg_ok, ret = 0, req, max_index, i, client_fd, c_len, total_ready; fd_set rset, wholeset; int client[FD_SETSIZE], n, sock_fd; char buffer[MAXLINE]; struct sockaddr_in client_addr; max_fd = msock; max_index = -1; for(i=0; i<FD_SETSIZE; i++) client[i] = -1; FD_ZERO(&wholeset); FD_SET(msock, &wholeset); while (1) { memcpy(&rset, &wholeset, sizeof(rset)); total_ready = select(max_fd + 1, &rset, NULL, NULL, NULL); if (FD_ISSET(msock, &rset)) { printf("Waiting for client connection\n"); //accept an incoming connection c_len = sizeof(struct sockaddr_in); client_fd = accept(msock, (struct sockaddr *)&client_addr, (socklen_t *)&c_len); if(client_fd == -1) { perror("ERROR: accept()\n"); exit(1); } ret = auth_user(client_fd); if (ret == -1) close(client_fd); else { for(i=0; i<FD_SETSIZE; i++) { if (client[i] < 0) { client[i] = client_fd; break; } } if (i==FD_SETSIZE) { perror("Too many clients\n"); exit(1); } FD_SET(client_fd, &wholeset); if (client_fd > max_fd) max_fd = client_fd; if(i > max_index) max_index = i; if (--total_ready <= 0) continue; } } for(i=0; i<=max_index; i++) { if ((sock_fd = client[i]) < 0) continue; if(FD_ISSET(sock_fd, &rset)) { //doftp((void *)(long)sock_fd); n = readn(sock_fd,(char *)&req,sizeof(req)); if(n <= 0) { close(sock_fd); FD_CLR(sock_fd, &wholeset); client[i] = -1; if (n < 0) printf("server: read error %d\n",errno); //status=endexecution(option); } else { req = ntohs(req); switch(req) { case STOREFILE: status=sendfile(sock_fd); break; case REQUESTFILE: status=recvfile(sock_fd); break; case MKDIR: status=makedir(sock_fd); break; case LIST: status=listdir(sock_fd); break; case DELETEFILE: status=deletefile(sock_fd); break; case END: printf("Client sent request to end connection.\n"); close(sock_fd); FD_CLR(sock_fd, &wholeset); client[i] = -1; break; default: break; } } if(--total_ready <= 0) break; } } } }
/* * Receive file(s). */ void get(int argc, char *argv[]) { int fd; register int n; register char *cp; char *src; if (argc < 2) { strcpy(line, "get "); printf("(files) "); fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); makeargv(); argc = margc; argv = margv; } if (argc < 2) { getusage(argv[0]); return; } if (!connected) { for (n = 1; n < argc ; n++) if (index(argv[n], ':') == 0) { getusage(argv[0]); return; } } for (n = 1; n < argc ; n++) { src = index(argv[n], ':'); if (src == NULL) src = argv[n]; else { struct hostent *hp; *src++ = 0; hp = gethostbyname(argv[n]); if (hp == NULL) { fprintf(stderr, "tftp: %s: ", argv[n]); herror(NULL); continue; } if (hp->h_length > (int)sizeof(s_inn.sin_addr)) { hp->h_length = sizeof(s_inn.sin_addr); } memcpy(&s_inn.sin_addr, hp->h_addr, hp->h_length); s_inn.sin_family = hp->h_addrtype; connected = 1; strncpy(hostname, hp->h_name, sizeof(hostname)); hostname[sizeof(hostname)-1] = 0; } if (argc < 4) { cp = argc == 3 ? argv[2] : tail(src); fd = creat(cp, 0644); if (fd < 0) { fprintf(stderr, "tftp: "); perror(cp); return; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); s_inn.sin_port = port; recvfile(fd, src, mode); break; } cp = tail(src); /* new .. jdg */ fd = creat(cp, 0644); if (fd < 0) { fprintf(stderr, "tftp: "); perror(cp); continue; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); s_inn.sin_port = port; recvfile(fd, src, mode); } }
/* * Receive file(s). */ void get(int argc, char *argv[]) { int fd; int n; char *cp; char *src; if (argc < 2) { strlcpy(line, "get ", sizeof(line)); printf("(files) "); readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin); if (makeargv()) return; argc = margc; argv = margv; } if (argc < 2) { getusage(argv[0]); return; } if (!connected) { for (n = 1; n < argc; n++) if (strrchr(argv[n], ':') == 0) { getusage(argv[0]); return; } } for (n = 1; n < argc; n++) { src = strrchr(argv[n], ':'); if (src == NULL) src = argv[n]; else { char *cp; *src++ = 0; cp = argv[n]; if (cp[0] == '[' && cp[strlen(cp) - 1] == ']') { cp[strlen(cp) - 1] = '\0'; cp++; } setpeer(cp, NULL); if (!connected) continue; } if (argc < 4) { cp = argc == 3 ? argv[2] : tail(src); fd = open(cp, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd < 0) { warn("create: %s", cp); return; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); recvfile(fd, src, mode); break; } cp = tail(src); /* new .. jdg */ fd = open(cp, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (fd < 0) { warn("create: %s", cp); continue; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); recvfile(fd, src, mode); } }
/* * Receive file(s). */ void get(int argc, char *argv[]) { int fd; int n; char *cp; char *src; if (argc < 2) { strlcpy(line, "get ", sizeof(line)); printf("(files) "); readcmd(&line[strlen(line)], LBUFLEN - strlen(line), stdin); if (makeargv()) return; argc = margc; argv = margv; } if (argc < 2) { getusage(argv[0]); return; } if (!connected) { for (n = 1; n < argc; n++) if (strchr(argv[n], ':') == 0) { getusage(argv[0]); return; } } for (n = 1; n < argc; n++) { src = strchr(argv[n], ':'); if (src == NULL) src = argv[n]; else { struct hostent *hp; *src++ = 0; hp = gethostbyname(argv[n]); if (hp == NULL) { warnx("%s: %s", argv[n], hstrerror(h_errno)); continue; } bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length); peeraddr.sin_family = hp->h_addrtype; connected = 1; strlcpy(hostname, hp->h_name, sizeof(hostname)); } if (argc < 4) { cp = argc == 3 ? argv[2] : tail(src); fd = creat(cp, 0644); if (fd < 0) { warn("create: %s", cp); return; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); peeraddr.sin_port = port; recvfile(fd, src, mode); break; } cp = tail(src); /* new .. jdg */ fd = creat(cp, 0644); if (fd < 0) { warn("create: %s", cp); continue; } if (verbose) printf("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); peeraddr.sin_port = port; recvfile(fd, src, mode); } }
int anruf( header_p sys, header_p ich, int lmodem, int tries ) { char dialstr[80]; char lockname[FILENAME_MAX]; header_p p; char *name, *pw; const char **v; int i, err; int dial_cnt = 1; /* fuer Janus */ char *arcer=NULL, *arcerin=NULL, *transfer=NULL, *domain; header_p t, d; int netcall_error; char filename[FILENAME_MAX]; char tmpname[FILENAME_MAX]; char outname[FILENAME_MAX]; char inname[FILENAME_MAX]; char sysname[FILENAME_MAX]; struct stat st; /* ende fuer Janus */ t = find(HD_ARCEROUT, sys); if (!t) { newlog(ERRLOG, "Kein ausgehender Packer definiert"); return 1; } arcer = t->text; strlwr(arcer); t = find(HD_ARCERIN, sys); if (!t) { newlog(ERRLOG, "Kein eingehender Packer definiert"); return 1; } arcerin = t->text; strlwr(arcerin); t = find(HD_PROTO, sys); if (!t) { newlog(ERRLOG, "Kein Uebertragungsprotokoll definiert"); return 1; } transfer = t->text; strlwr(transfer); name = NULL; p = find(HD_SYS, ich); if (p) name = p->text; pw = NULL; p = find(HD_PASSWD, sys); if (p) pw = p->text; p = find(HD_X_CALL, sys); if (!p) { fprintf(stderr, "Welches Netcall-Verfahren????\n"); exit(20); } for (i = 0, v = verf; *v; i++, v++) if (stricmp(*v, p->text) == 0) break; if (!*v) return 1; if (i < ZCONNECT) { t = find(HD_SYS, sys); if (!t) { newlog(ERRLOG, "Illegale Systemdatei: Kein " HN_SYS ": Header oder falscher Name: %s", filename); return 1; } d = find(HD_DOMAIN, sys); if (!d) { newlog(ERRLOG, "Illegale Systemdatei: Kein " HN_DOMAIN ": Header: %s", filename); return 1; } for (domain = strtok(d->text, " ;,:"); domain; domain = strtok(NULL, " ;,:")) { sprintf(sysname, "%s.%s", t->text, domain); strlwr(sysname); sprintf(tmpname, "%s/%s", netcalldir, sysname); newlog(logname, "Suche Verzeichnis, versuche %s...", tmpname); if (access(tmpname, R_OK|X_OK) == 0) break; } if(access(tmpname, R_OK|X_OK)) { /* Problem: temp. Verzeichnis nicht zu haben */ newlog(logname, "Problem beim Netcall: Verzeichnis " "nicht gefunden"); return 1; } } /* ##### HIER WIRD ANGEWAEHLT ##### */ p = find(HD_TEL, sys); while(tries) { if(!p) p = find(HD_TEL, sys); make_dialstr(dialstr, sizeof(dialstr), p->text); fprintf(stderr, "%3d. Anwahlversuch (noch %d): %-.25s\n", dial_cnt++, tries, dialstr); if (redial(dialstr, lmodem, 1) != 0 ) { tries--; p = p->other; } else { /* connect */ break; } } set_local(lmodem, 0); time(&online_start); if (i < ZCONNECT) { if (name) dfree(name); name = dstrdup(boxstat.boxname); strupr(name); #ifdef ENABLE_CAPS_IN_PASSWORD strupr(pw); #endif } if(login(lmodem, i, name, pw)) return 0; if (i < ZCONNECT) { /* JANUS */ int have_file = 0; netcall_error = 0; if ( janus_wait(lmodem) != 0 ) return 0; sprintf(tmpname, "%s/%s.%d.dir", netcalldir, sysname, getpid()); mkdir(tmpname, 0755); chdir(tmpname); /* outname: ausgehendes Archiv * filename: */ sprintf(outname, "%s/caller.%s", tmpname, arcer); sprintf(filename, "%s/%s.%s", netcalldir, sysname, arcer); sprintf(lockname, "%s/%s/" PREARC_LOCK, netcalldir, sysname); if (access(filename, R_OK) != 0) { FILE *f; if(access(filename, F_OK) == 0) { newlog(ERRLOG, "Leerer Puffer, weil keine Erlaubnis " "zum Lesen von %s: %s", outname, strerror(errno)); } f = fopen(outname, "wb"); if (!f) { newlog(ERRLOG, "Kann Netcall %s nicht erzeugen: %s", outname, strerror(errno)); fclose(deblogfile); return 1; } fputs("\r\n", f); fclose(f); } else { /* can read filename */ if (waitnolock(lockname, 180)) { fclose(deblogfile); newlog(OUTGOING, "System %s Prearc LOCK: %s", sysname, lockname ); return 1; } fprintf(stderr, "Link: %s -> %s\n", filename, outname); if(link(filename, outname)) { fclose(deblogfile); newlog(ERRLOG, "Linken: %s -> %s fehlgeschlagen: %s", filename, outname, strerror(errno)); netcall_error = 1; goto finish; } have_file = 1; } sprintf(inname, "called.%s", arcer); st.st_size = 0; if(stat(outname, &st)) { fprintf(stderr, "Zugriff auf %s fehlgeschlagen: %s\n", outname, strerror(errno)); netcall_error = 1; goto finish; } newlog(logname, "Sende %s (%ld Bytes) per %s", outname, (long)st.st_size, transfer); err = sendfile(transfer, outname); if (err) { newlog(logname, "Versand der Daten fehlgeschlagen"); netcall_error = 1; goto finish; } newlog(logname, "Empfange mit %s", transfer); if (recvfile(transfer, inname)) { newlog(logname, "Empfang der Daten fehlgeschlagen"); netcall_error = 1; goto finish; } st.st_size = 0; if(stat(inname, &st)) { newlog(logname, "Zugriff auf %s fehlgeschlagen: %s", inname, strerror(errno)); } newlog(logname, "%ld Bytes empfangen", (long)st.st_size); finish: /* Fertig, Modem auflegen */ signal(SIGHUP, SIG_IGN); fclose(stdin); fclose(stdout); hayes_hangup(lmodem); DMLOG("hayes hangup modem"); hangup(lmodem); DMLOG("hangup modem"); anrufdauer(); restore_linesettings(lmodem); DMLOG("restoring modem parameters"); close(lmodem); lmodem=-1; DMLOG("close modem"); /* neuer stdin */ fopen("/dev/null", "r"); /* stderr wird in stdout kopiert */ dup2(fileno(stderr),fileno(stdout)); if(!netcall_error) { /* Netcall war erfolgreich, also Daten loeschen */ if(have_file) { /* Backups von Nullpuffern sind uninteressant */ backup3(backoutdir,filename,sysname,arcer); } /* das ist nur ein Link, den putzen wir weg */ if ( unlink(outname)) { newlog(ERRLOG, "Loeschen von %s fehlgeschlagen: %s", outname, strerror(errno)); } fclose(deblogfile); /* * Und empfangene Daten (im Hintergrund) einlesen, * das Modem wird sofort wieder freigegeben. */ switch(fork()) { case -1: { /* cannot fork */ perror("forking import"); newlog(ERRLOG, "Forken des Importteils " "fehlgeschlagen: %s", strerror(errno)); break; } case 0: { /* Ich bin child */ deblogfile=fopen("/tmp/import.deblogfile", "a"); DMLOG("child forked"); import_all(arcerin, sysname); chdir ("/"); if(rmdir(tmpname)) { newlog(ERRLOG, "Loeschen von %s " "fehlgeschlagen: %s", tmpname, strerror(errno)); } fclose(deblogfile); exit(0); } default: /* parent */ break; } } return(1); } else { /* ZCONNECT */ system_master(ich, sys); if (auflegen) return 1; bereitstellen(); files = 1; senden_queue = todo; todo = NULL; while (!auflegen) { datei_master(ich, sys); } anrufdauer(); close(lmodem); DMLOG("close modem"); aufraeumen(); exit (0); } return 1; }
/* * Receive file(s). */ void get (int argc, char *argv[]) { int fd; register int n; register char *cp; char *src; if (argc < 2) get_args ("get", "(files) ", &argc, &argv); if (argc < 2) { getusage (argv[0]); return; } if (!connected) { for (n = 1; n < argc; n++) if (strchr (argv[n], ':') == 0) { getusage (argv[0]); return; } } for (n = 1; n < argc; n++) { src = strchr (argv[n], ':'); if (src == NULL) src = argv[n]; else { *src++ = 0; if (resolve_name (argv[n], 0) != RESOLVE_OK) continue; } if (argc < 4) { cp = argc == 3 ? argv[2] : tail (src); fd = creat (cp, 0644); if (fd < 0) { fprintf (stderr, "tftp: "); perror (cp); return; } if (verbose) printf ("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); peeraddr.sin_port = port ? port : sp->s_port; recvfile (fd, src, mode); break; } cp = tail (src); /* new .. jdg */ fd = creat (cp, 0644); if (fd < 0) { fprintf (stderr, "tftp: "); perror (cp); continue; } if (verbose) printf ("getting from %s:%s to %s [%s]\n", hostname, src, cp, mode); peeraddr.sin_port = port ? port : sp->s_port; recvfile (fd, src, mode); } }
// Runs the interactive loop and all file transfers. // Returns: exit status int main(void) { // Used to control DNS resolution requests: struct addrinfo hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_DGRAM; // Bind to an ephemeral network port: struct addrinfo *server = NULL; int sfd = openudp(0); if(sfd < 0) handle_error("bind()"); // Allocate (small) space to store user input: char *buf = malloc(1); size_t cap = 1; char *cmd; // First word of buf size_t len; // Length of cmd // Main input loop, which normally only breaks upon a GFO: do { // Keep prompting until the user brings us back something good: do { printf("%s", SHL_PS1); readin(&buf, &cap); } while(homog(buf, ' ')); // Cleave off the command (first word): cmd = strtok(buf, " "); len = strlen(cmd); if(strncmp(cmd, CMD_CON, len) == 0) { // Read the arguments: const char *hostname = strtok(NULL, " "); const char *tmp = strtok(NULL, " "); in_port_t port = PORT_UNPRIVILEGED; if(tmp) port = atoi(tmp); // Ensure a hostname or IP has been provided: if(!hostname) { usage(CMD_CON, "hostname", "port"); continue; } // Avoid leaking any existing address: if(server) { freeaddrinfo(server); server = NULL; } // Try to resolve the requested hostname: if(getaddrinfo(hostname, NULL, &hints, &server)) { fprintf(stderr, "Unable to resolve hostname\n"); freeaddrinfo(server); server = NULL; continue; } ((struct sockaddr_in *)server->ai_addr)->sin_port = htons(port); } else if(strncmp(cmd, CMD_GET, len) == 0 || strncmp(cmd, CMD_PUT, len) == 0) { bool putting = strncmp(cmd, CMD_PUT, 1) == 0; // Ensure we're already connected to a server: if(!server) { noconn(cmd); continue; } // Make sure we were given a path argument: char *pathname = strtok(NULL, ""); if(!pathname) { usage(putting ? CMD_PUT : CMD_GET, "pathname", NULL); continue; } // Since basename() might modify pathname, copy it: char filename[strlen(pathname)+1]; memcpy(filename, pathname, sizeof filename); int fd; if(putting) { // Try opening the file for reading: if((fd = open(pathname, O_RDONLY)) < 0) { fprintf(stderr, "local: Unable to read specified file\n"); continue; } // Send a request and record the port used to acknowledge: struct sockaddr_in dest_addr; sendreq(sfd, basename(filename), OPC_WRQ, server->ai_addr); uint8_t *rmtack = recvpkta(sfd, &dest_addr); if(iserr(rmtack)) { fprintf(stderr, "remote: %s\n", strerr(rmtack)); free(rmtack); continue; } free(rmtack); // Transmit the file: sendfile(sfd, fd, &dest_addr); } else // getting { // Try opening a file of that name for writing: if((fd = open(basename(filename), O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0) { fprintf(stderr, "local: Unable to create the new file\n"); continue; } // Send a request and await the incoming file: sendreq(sfd, pathname, OPC_RRQ, server->ai_addr); const char *res = recvfile(sfd, fd); if(res) { fprintf(stderr, "remote: %s\n", res); close(fd); fd = -1; unlink(basename(filename)); } } if(fd >= 0) close(fd); } else if(strncmp(cmd, CMD_HLP, len) == 0) { printf("Commands may be abbreviated. Commands are:\n\n"); printf("%s\t\tconnect to remote tftp\n", CMD_CON); printf("%s\t\tsend file\n", CMD_PUT); printf("%s\t\treceive file\n", CMD_GET); printf("%s\t\texit tftp\n", CMD_GFO); printf("%s\t\tprint help information\n", CMD_HLP); } else if(strncmp(cmd, CMD_GFO, len) != 0) { fprintf(stderr, "%s: unknown directive\n", cmd); fprintf(stderr, "Try ? for help.\n"); } } while(strncmp(cmd, CMD_GFO, len) != 0); free(buf); if(server) freeaddrinfo(server); return 0; }