Avatar billede futter2 Nybegynder
03. oktober 2001 - 22:49 Der er 13 kommentarer og
1 løsning

FTP med C++Builder

Er der nogen der har nogle erfaringer med at lave en simpel FTP server i C++Builder (f.eks med NMFTP)
Avatar billede mickni33 Nybegynder
03. oktober 2001 - 23:20 #1
Brug NMFTP1 componenten og følgende kode, Du kan se de forskellige metoder der kan bruges herunder.

__fastcall TFormMain::TFormMain(TComponent* Owner)
        : TForm(Owner)
{
}


void __fastcall TFormMain::Button1Click(TObject *Sender)
{
  if (CheckBox1->Checked)
  {
    NMFTP1->Proxy = Edit6->Text;
    NMFTP1->Proxy = StrToInt(Edit7->Text);
  }
  NMFTP1->Host = HostTxt->Text;
  NMFTP1->Port = StrToInt(PortTxt->Text);
  NMFTP1->UserID = UserTxt->Text;
  NMFTP1->Password = PassTxt->Text;
  NMFTP1->Connect();
}

void __fastcall TFormMain::Button2Click(TObject *Sender)
{
  NMFTP1->Disconnect();           
}

void __fastcall TFormMain::Button3Click(TObject *Sender)
{
  NMFTP1->Nlist();       
}

void __fastcall TFormMain::Button4Click(TObject *Sender)
{
  NMFTP1->List();       
}

void __fastcall TFormMain::Button5Click(TObject *Sender)
{
  NMFTP1->ChangeDir(DirTxt->Text);       
}

void __fastcall TFormMain::Button6Click(TObject *Sender)
{
  NMFTP1->Download(RemoteTxt->Text, LocalTxt->Text);       
}

void __fastcall TFormMain::Button7Click(TObject *Sender)
{
  NMFTP1->Abort();       
}

void __fastcall TFormMain::Button8Click(TObject *Sender)
{
  NMFTP1->DownloadRestore(RemoteTxt->Text, LocalTxt->Text);       
}

void __fastcall TFormMain::Button18Click(TObject *Sender)
{
  NMFTP1->Rename(Edit8->Text, Edit9->Text);       
}

void __fastcall TFormMain::Button17Click(TObject *Sender)
{
  NMFTP1->Reinitialize();
  PageControl1->ActivePage = TabSheet2;
}

void __fastcall TFormMain::Button16Click(TObject *Sender)
{
  NMFTP1->Delete(Edit5->Text);
}

void __fastcall TFormMain::Button14Click(TObject *Sender)
{
  NMFTP1->MakeDirectory(Edit1->Text);       
}

void __fastcall TFormMain::Button15Click(TObject *Sender)
{
  NMFTP1->RemoveDir(Edit2->Text);       
}
void __fastcall TFormMain::Button11Click(TObject *Sender)
{
  NMFTP1->UploadAppend(Edit3->Text, Edit4->Text);       
}

void __fastcall TFormMain::Button12Click(TObject *Sender)
{
  NMFTP1->UploadUnique(Edit3->Text);       
}

void __fastcall TFormMain::Button13Click(TObject *Sender)
{
  NMFTP1->UploadRestore(Edit3->Text, Edit4->Text, StrToInt(PosTxt->Text));
}

void __fastcall TFormMain::Button10Click(TObject *Sender)
{
  NMFTP1->Upload(Edit3->Text, Edit4->Text);
}

void __fastcall TFormMain::Button9Click(TObject *Sender)
{
  NMFTP1->Abort();
}

void __fastcall TFormMain::NMFTP1Connect(TObject *Sender)
{
  StatusBar1->SimpleText = \"Connected\";       
}

void __fastcall TFormMain::NMFTP1ConnectionFailed(TObject *Sender)
{
  ShowMessage(\"Connection Failed\");       
}

void __fastcall TFormMain::NMFTP1Disconnect(TObject *Sender)
{
  if (StatusBar1 != 0)
    StatusBar1->SimpleText = \"Disconnected\";       
}

void __fastcall TFormMain::NMFTP1Error(TComponent *Sender, WORD Errno,
      AnsiString Errmsg)
{
  ShowMessage(\"Error \"+IntToStr(Errno)+\": \"+Errmsg);       
}

void __fastcall TFormMain::NMFTP1Failure(bool &handled, TCmdType Trans_Type)
{
  switch (Trans_Type) {
    case cmdChangeDir: StatusBar1->SimpleText = \"ChangeDir failure\"; break;
    case cmdMakeDir: StatusBar1->SimpleText = \"MakeDir failure\"; break;
    case cmdDelete: StatusBar1->SimpleText = \"Delete failure\"; break;
    case cmdRemoveDir: StatusBar1->SimpleText = \"RemoveDir failure\"; break;
    case cmdList: StatusBar1->SimpleText = \"List failure\"; break;
    case cmdRename: StatusBar1->SimpleText = \"Rename failure\"; break;
    case cmdUpRestore: StatusBar1->SimpleText = \"UploadRestore failure\"; break;
    case cmdDownRestore: StatusBar1->SimpleText = \"DownloadRestore failure\"; break;
    case cmdDownload: StatusBar1->SimpleText = \"Download failure\"; break;
    case cmdUpload: StatusBar1->SimpleText = \"Upload failure\"; break;
    case cmdAppend: StatusBar1->SimpleText = \"UploadAppend failure\"; break;
    case cmdReInit: StatusBar1->SimpleText = \"ReInit failure\"; break;
    case cmdAllocate: StatusBar1->SimpleText = \"Allocate failure\"; break;
    case cmdNList: StatusBar1->SimpleText = \"NList failure\"; break;
    case cmdDoCommand: StatusBar1->SimpleText = \"DoCommand failure\"; break;
    default: ShowMessage(\"Unrecognized command failed.\"); break;
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1HostResolved(TComponent *Sender)
{
  StatusBar1->SimpleText = \"Host Resolved\";       
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1InvalidHost(bool &handled)
{
  AnsiString NewHost;
  if (InputQuery(\"Invalid Host\", \"Please Choose another host\", NewHost))
  {
    NMFTP1->Host = NewHost;
    handled = true;
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1ListItem(AnsiString Listing)
{
  Memo1->Lines->Add(Listing);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1PacketRecvd(TObject *Sender)
{
  StatusBar1->SimpleText = IntToStr(NMFTP1->BytesRecvd)+\" bytes of \"+IntToStr(NMFTP1->BytesTotal)+\" received\";
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1PacketSent(TObject *Sender)
{
  StatusBar1->SimpleText = IntToStr(NMFTP1->BytesSent)+\" bytes of \"+IntToStr(NMFTP1->BytesTotal)+\" sent\";       
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1Status(TComponent *Sender, AnsiString Status)
{
  if (StatusBar1 != 0)
    StatusBar1->SimpleText = Status;       
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1Success(TCmdType Trans_Type)
{
  switch(Trans_Type)
  {
    case cmdChangeDir: StatusBar1->SimpleText = \"ChangeDir success\"; break;
    case cmdMakeDir: StatusBar1->SimpleText = \"MakeDir success\"; break;
    case cmdDelete: StatusBar1->SimpleText = \"Delete success\"; break;
    case cmdRemoveDir: StatusBar1->SimpleText = \"RemoveDir success\"; break;
    case cmdList: StatusBar1->SimpleText = \"List success\"; break;
    case cmdRename: StatusBar1->SimpleText = \"Rename success\"; break;
    case cmdUpRestore: StatusBar1->SimpleText = \"UploadRestore success\"; break;
    case cmdDownRestore: StatusBar1->SimpleText = \"DownloadRestore success\"; break;
    case cmdDownload: StatusBar1->SimpleText = \"Download success\"; break;
    case cmdUpload: StatusBar1->SimpleText = \"Upload success\"; break;
    case cmdAppend: StatusBar1->SimpleText = \"UploadAppend success\"; break;
    case cmdReInit: StatusBar1->SimpleText = \"ReInit success\"; break;
    case cmdAllocate: StatusBar1->SimpleText = \"Allocate success\"; break;
    case cmdNList: StatusBar1->SimpleText = \"NList success\"; break;
    case cmdDoCommand: StatusBar1->SimpleText = \"DoCommand success\"; break;
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1TransactionStart(TObject *Sender)
{
  StatusBar1->SimpleText = \"Starting data transaction\";       
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1TransactionStop(TObject *Sender)
{
  StatusBar1->SimpleText = \"Transaction Complete\";       
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::NMFTP1UnSupportedFunction(TCmdType Trans_Type)
{
  switch(Trans_Type)
  {
    case cmdChangeDir: ShowMessage(\"ChangeDir not supported\"); break;
    case cmdMakeDir: ShowMessage(\"MakeDir not supported\"); break;
    case cmdDelete: ShowMessage(\"Delete not supported\"); break;
    case cmdRemoveDir: ShowMessage(\"RemoveDir not supported\"); break;
    case cmdList: ShowMessage(\"List not supported\"); break;
    case cmdRename: ShowMessage(\"Rename not supported\"); break;
    case cmdUpRestore: ShowMessage(\"UploadRestore not supported\"); break;
    case cmdDownRestore: ShowMessage(\"DownloadRestore not supported\"); break;
    case cmdDownload: ShowMessage(\"Download not supported\"); break;
    case cmdUpload: ShowMessage(\"Upload not supported\"); break;
    case cmdAppend: ShowMessage(\"UploadAppend not supported\"); break;
    case cmdReInit: ShowMessage(\"ReInit not supported\"); break;
    case cmdAllocate: ShowMessage(\"Allocate not supported\"); break;
    case cmdNList: ShowMessage(\"NList not supported\"); break;
    case cmdDoCommand: ShowMessage(\"DoCommand not supported\"); break;
  }
}
Avatar billede mickni33 Nybegynder
03. oktober 2001 - 23:22 #2
og husk når det er ftp skal der stå port 21
Avatar billede futter2 Nybegynder
03. oktober 2001 - 23:25 #3
Tak for interessen mickni33, men....
Jeg skal bruge en server, det du kommer med er eksemplet fra C++Builderen
og er ikke en server. Mit (nuværende) problem er OnAccept eventen. I hjælpen står det at den ligger i TPowerSock og at jeg skal lave en component til dem, det har jeg gjort men det virker ikke en s... Så hvis du har en ide om hvad jeg skal gøre eller et link/eksempel ville det give nogle points...
Avatar billede futter2 Nybegynder
03. oktober 2001 - 23:26 #4
Je jeg har bruget port 21 (til FTP)
Avatar billede mickni33 Nybegynder
03. oktober 2001 - 23:28 #5
oookay bruger lige en halv time idag så er det sengetid
Avatar billede futter2 Nybegynder
03. oktober 2001 - 23:29 #6

http://www.iana.org/assignments/port-numbers
er der listet en masse port numre og deres betydning. (du kender den sikkert i forvejen)
Avatar billede mickni33 Nybegynder
04. oktober 2001 - 00:05 #7
OK her er noget hardcore  C kode en ftp server.
Sig lige til hvis du heller vil have den på mail

#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
#include <stddef.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>

#define YES 0
#define NO 1
#define PASS 2
#define MAX_CONNECTIONS 100
#define RECV_SIZE 1024            //Groesse des recv_buffer

struct client_struct {
    int client_no;                //Nummer des Clients  (1..MAX_CONNECTIONS)
    int client_socket;            //Socketnummer
    pthread_t thread_nr;            //Threadnummer
    pthread_attr_t thread_attribute;      //Attribute des Threads
    pthread_t recv_nr;              //Threadnummer fuer recv_all_incoming
    int is_in_use;              //wird er im Moment benutzt?
    int logged_in;                  //schon eingeloggt?
    char user[9];                //Username
    char *recv_buffer;            //Puffer fuer empfangene Daten
    char *working_dir;            //Zeiger aufs momentane Verzeichnis
    int head;              //ab hier werden Daten abgelegt
    int tail;              //bis hierhin werden Daten empfangen
    unsigned long int data_ip:32;      //IP fuer Datenleitung
    unsigned int data_port:16;          //Port fuer Datenleitung
    unsigned int data_socket;          //Socket fuer die Datenleitung
    unsigned int passive:8;          //Passiver-Modus?
    char stru;                      //Daten-Struktur (F,R)
    unsigned int type;              //Daten-Type (A,AN,I,L8)
    char mode;                      //Datenübertragungsmodus (S)
    struct passwd pass_entry;      //Daten des Users
};

char *user_out=      \"530 User not logged in\\xd\\xa\";
char *error_in_param=\"501 Syntax error in parameters or arguments\\xd\\xa\";
char *server_root=\"/home/ftp\";

int lauschen;
int lauschen_port=0x2505;
pthread_t local_console_thread;
pthread_attr_t local_console_thread_attr;
struct client_struct incoming_client[MAX_CONNECTIONS];      //hier werden bis zu MAX_CONNECTIONS Andockende Clients abgespeichert
struct sockaddr_in s_in;

void cwd_command(struct client_struct *arg,char *buf);

int get_free_client(void){            //sucht einen freien Platz in dem Clientarray
int i;
    for (i=0;i<MAX_CONNECTIONS;i++) if (incoming_client[i].is_in_use==NO) {
        incoming_client[i].is_in_use=YES;
        return i ;
    }
    return -1;
}

char *get_command(struct client_struct *arg){              //liefert ein Kommando vom Client
char *command_buf;
int pos,command_size;
    pos=arg->head;
    if (pos==arg->tail) return NULL;          //Warteschlange ist leer
    for (pos=arg->head;pos!=arg->tail-2;pos=(pos+1)%RECV_SIZE)
    if (arg->recv_buffer[pos]==0x0d) break;
    if (arg->recv_buffer[pos+1]==0x0a) {
        pos++;
        command_size=pos>arg->head?pos-arg->head+1:RECV_SIZE-(arg->head-pos)+1;
        printf(\"Command Size %d bytes from client %d\\n\",command_size,arg->client_no);
        command_buf=calloc(command_size+1,1);
        memcpy(command_buf,arg->recv_buffer+arg->head,command_size);
        arg->head+=command_size;
        pos=0;
        command_buf[command_size]=0;
        while ((command_buf[pos]!=32)&&(command_buf[pos]!=0x0d)){
            command_buf[pos]=tolower(command_buf[pos]);
            pos++;
        }
        return command_buf;
    }
    return NULL;
}

void retr_command(struct client_struct *arg,char *buf){        //RETR-Kommando
char *syntax_error=\"500 Syntax error\\xd\\xa\";
int i;
FILE *download;
char *data,*dir;
char *data_out;
int read;
unsigned long size;
struct sockaddr_in s_in;
    if (arg->logged_in==NO) return;
    for (i=0;i<strlen(buf);i++) if (buf[i]==\' \') break;
    i++;          //i zeigt auf die Datei
    if (i==strlen(buf)) {                //keine Datei angegeben
        send(arg->client_socket,syntax_error,18,0);
        return;
    }
    dir=calloc(1024,1);
    strcat(dir,arg->working_dir);
    if (strlen(dir)!=1) strcat(dir,\"/\");
    strcat(dir,buf+i);
    dir[strlen(dir)-2]=0;            //\\xd\\xa abschneiden
    download=fopen(dir,\"r\");      //Datei [ffnen;
    if (download==NULL){                //Fehler beim [ffnen
        switch (errno){
            default:   
                        send(arg->client_socket,\"450 Operation not permitted\\xd\\xa\",29,0);
                        break;
        }
        free(dir);
        return;
    }
    fseek(download,0,SEEK_END);
    size=ftell(download);
    fseek(download,0,SEEK_SET);
    data=calloc(10*1024,1);
    if (data==NULL){
        free(dir);
        send(arg->client_socket,\"550 Internal Error\\xd\\xa\",20,0);
        return;
    }
    send(arg->client_socket,\"150 Opening Data connection\\xd\\xa\",29,0);
    arg->data_socket=socket(AF_INET,SOCK_STREAM,0);
    if (arg->data_socket==-1){
        free(data);
        free(dir);
        send(arg->client_socket,\"425 Can not open data connection\\xd\\xa\",32,0);
        return;
    }
    s_in.sin_port=htons(arg->data_port);
    s_in.sin_addr.s_addr=htonl(arg->data_ip);
    s_in.sin_family=AF_INET;
    if (connect(arg->data_socket,(struct sockaddr *)&s_in,sizeof(s_in))==-1){
        free(data);
        free(dir);
        send(arg->client_socket,\"425 Can not open data connection\\xd\\xa\",32,0);
        return;
    }
    if (arg->type==(unsigned int)\'I\'||arg->type==(unsigned int)(\'L\'*256+\'8\')){    //keine Konvertierung nötig
        do{
            read=fread(data,1,10*1024,download);
            if (ferror(download)>0) {
                send(arg->client_socket,\"426 Connection abort\\xd\\xa\",22,0);
                break;
            }
            send(arg->data_socket,data,read,0);
        } while(!feof(download));
    }
    else {        //\\xd bzw \\xa muß in \\xd\\xa umgewandelt werden
        data_out=calloc(10*1024*2,1);              //worst-case annehmen
        do{
            int i;
            read=fread(data,1,10*1024,download);
            for(i=0;i<read;i++) if (data[i]==\'\\xd\'||data[i]==\'\\xa\') {
                    data_out[i]=\'\\xd\';
                    data_out[i+1]=\'\\xa\';
                    i+=2;
                    read++;
                }
                else data_out[i]=data[i];
            if (ferror(download)>0) {
                send(arg->client_socket,\"426 Connection abort\\xd\\xa\",22,0);
                break;
            }
            send(arg->data_socket,data_out,read,0);
        }while(!feof(download));
        free(data_out);
    }
    if (ferror(download)>0) {
        free(data);
        free(dir);
        return;
    }
    shutdown(arg->data_socket,2);
    send(arg->client_socket,\"226 Transfer complete\\xd\\xa\",23,0);
    free(data);
    free(dir);
    return;
}

void stor_command(struct client_struct *arg,char *buf){        //STOR-Kommando
char *syntax_error=\"500 Syntax error\\xd\\xa\";
int i;
FILE *upload;
char *data_in,*dir;
char *data_out;
int write;
unsigned long size;
struct sockaddr_in s_in;
    if (arg->logged_in==NO) return;
    for (i=0;i<strlen(buf);i++) if (buf[i]==\' \') break;
    i++;          //i zeigt auf die Datei
    if (i==strlen(buf)) {                //keine Datei angegeben
        send(arg->client_socket,syntax_error,18,0);
        return;
    }
    dir=calloc(1024,1);
    strcat(dir,arg->working_dir);
    if (strlen(dir)!=1) strcat(dir,\"/\");
    strcat(dir,buf+i);
    dir[strlen(dir)-2]=0;            //\\xd\\xa abschneiden
    upload=fopen(dir,\"w\");      //Datei [ffnen;
    if (upload==NULL){                //Fehler beim [ffnen
        switch (errno){
            default:   
                        send(arg->client_socket,\"450 Operation not permitted\\xd\\xa\",29,0);
                        break;
        }
        free(dir);
        return;
    }
    data_in=calloc(10*1024,1);
    if (data_in==NULL){
        free(dir);
        send(arg->client_socket,\"550 Internal Error\\xd\\xa\",20,0);
        return;
    }
    send(arg->client_socket,\"150 Opening Data connection\\xd\\xa\",29,0);
    arg->data_socket=socket(AF_INET,SOCK_STREAM,0);
    if (arg->data_socket==-1){
        free(data_in);
        free(dir);
        send(arg->client_socket,\"425 Can not open data connection\\xd\\xa\",32,0);
        return;
    }
    s_in.sin_port=htons(arg->data_port);
    s_in.sin_addr.s_addr=htonl(arg->data_ip);
    s_in.sin_family=AF_INET;
    if (connect(arg->data_socket,(struct sockaddr *)&s_in,sizeof(s_in))==-1){
        free(data_in);
        free(dir);
        send(arg->client_socket,\"425 Can not open data connection\\xd\\xa\",32,0);
        return;
    }
    if (arg->type==(unsigned int)\'I\'||arg->type==(unsigned int)(\'L\'*256+\'8\')){    //keine Konvertierung nötig
        do{
            write=recv(arg->data_socket,data_in,10*1024,0);
            fwrite(data_in,1,write,upload);
            if (ferror(upload)>0) {
                send(arg->client_socket,\"426 Connection abort\\xd\\xa\",22,0);
                break;
            }
        } while(write>0);
    }
    else {        //\\xd bzw \\xa muß in \\xd\\xa umgewandelt werden
        data_out=calloc(10*1024*2,1);              //worst-case annehmen
        do{
            int i;
            write=recv(arg->data_socket,data_in,10*1024,0);
            for(i=0;i<write;i++) if (data_in[i]==\'\\xd\' || data_in[i]==\'\\xa\') {
                    data_out[i]=\'\\xd\';
                    data_out[i+1]=\'\\xa\';
                    i+=2;
                    write++;
                }
                else data_out[i]=data_in[i];
            fwrite(data_out,1,10*1024,upload);
            if (ferror(upload)>0) {
                send(arg->client_socket,\"426 Connection abort\\xd\\xa\",22,0);
                break;
            }
        }while(write>0);
        free(data_out);
    }
    if (ferror(upload)>0) {
        free(data_in);
        free(dir);
        return;
    }
    shutdown(arg->data_socket,2);
    send(arg->client_socket,\"226 Transfer complete\\xd\\xa\",23,0);
    free(data_in);
    free(dir);
    return;
}

void help(struct client_struct *arg){
char *help_message=\"214-The following commands are recognized:\\xd\\xa  CDUP CWD HELP LIST NLST NOOP PASS PORT PWD USER \\xd\\n214 report errors to matthias.kay@itzehoe.netsurf.de\\xd\\xa\";
    printf(\"Command HELP from client %d\\n\",arg->client_no);
    send(arg->client_socket,help_message,151,0);
    printf(\"send help message to client %d\\n\",arg->client_no);
    return;
}

void noop_command(struct client_struct *arg, char *buf){  //NOOP-Kommando
char *noop_msg=\"200 OK\\xd\\xa\";
    send(arg->client_socket,noop_msg,8,0);
    return;
}

int is_dir_ok(struct client_struct *arg, char *dir){      //testet, ob gültiger Zugriff auf Verzeichnis möglich
char *cur_dir;
    if (chdir(arg->working_dir)!=0) return NO;
    if (chdir(dir)!=0) return NO;
    cur_dir=getcwd(NULL,2048);
    if (strstr(cur_dir,server_root)==NULL) {
        free(cur_dir);
        return NO;
    }
    else if(strstr(cur_dir,server_root)==cur_dir) {
        free(cur_dir);
        return YES;
    }
    else {
        free(cur_dir);
        return NO;
    }
    return;
}

void cdup_command(struct client_struct *arg, char *buf){
char *buf1;
    buf1=calloc(strlen(\"cwd ..\\xd\\xa\")+1,1);
    if (buf1==NULL) {
        send(arg->client_socket,\"550 Internal Error\\xd\\xa\",20,0);
        return;
    }
    strcpy(buf1,\"cwd ..\\xd\\xa\");
    cwd_command(arg,buf1);
    free (buf1);
    return;
}

void pwd_command(struct client_struct *arg, char *buf){      //PWD-Kommando
char *not_valid=\"501 Working directory is not valid!\\xd\\xa\";
char *buf1;
    if(arg->logged_in==NO) {
        send(arg->client_socket,user_out,24,0);
        return;
    }
    if (chdir(arg->working_dir)!=0) {
        send(arg->client_socket,not_valid,37,0);
        return;
    }
    buf1=calloc(strlen(arg->working_dir)+2,1);
    if (buf1==NULL){
        send(arg->client_socket,\"550 Internal Error\\xd\\xa\",20,0);
        return;
    }
    strcpy(buf1,arg->working_dir);
    strcat(buf1,\"\\xd\\xa\");
    send(arg->client_socket,buf1,strlen(buf1),0);
    free(buf1);
    return;
}

void cwd_command(struct client_struct *arg, char *buf){      //CWD-Kommando
char *cwd_ok=\"250 CWD command ok\\xd\\xa\";
char *no_dir=\"501 Unknown directory\\xd\\xa\";
char *no_perm=\"550 Permission denied\\xd\\xa\";
char *not_entry=\"550 Not a directory\\xd\\xa\";
    if(arg->logged_in==NO || strlen(buf)<6) {
        send(arg->client_socket,user_out,24,0);
        return;
    }
    buf[strlen(buf)-2]=0;  //\\xd\\xa vom Verzeichnisnamen abschneiden
    if (is_dir_ok(arg,buf+4)==YES) {
        char *test;
        chdir(arg->working_dir);
        chdir(buf+4);
        free(arg->working_dir);
        test=getcwd(NULL,2048);
        if (test==NULL){
            send(arg->client_socket,\"550 Internal Error\\xd\\xa\",20,0);
            return;
        }
        arg->working_dir=test;
        send(arg->client_socket,cwd_ok,20,0);
    }
    else {
        switch (errno){
            case EACCES:printf(\"CWD: Access to %s not possible for client %d\\n\",buf+4,arg->client_no);
                        send(arg->client_socket,no_perm,23,0);
                        break;
            default:
            case ENOENT:printf(\"CWD: Directory %s does not exist by client %d\\n\",buf+4,arg->client_no);
                        send(arg->client_socket,no_dir,24,0);
                        break;
            case ENOTDIR:printf(\"CWD: Dir %s is not a directory from client %d\\n\",buf+4,arg->client_no);
                        send(arg->client_socket,not_entry,21,0);
                        break;
        }
    }
    return;
}

void list_dir(struct client_struct *arg, char *buf){        //LIST-Kommando
DIR *dp;
struct dirent *ep;
int size;
struct sockaddr_in s_in;
char *command_ok=\"226 Transfer complete\\xd\\xa\";
char *start_trans=\"150 Opening ASCII mode data connection for file list\\xd\\xa\";
char *no_data=\"425 Can not open data connection\\xd\\xa\";
char *no_perm=\"550 Permission denied\\xd\\xa\";
char *no_dir=\"550 Directory does not exist\\xd\\xa\";
char *not_entry=\"550 Not a directory or file\\xd\\xa\";
char *buffer;
struct stat file_info;
    if(arg->logged_in==NO) {
        send(arg->client_socket,user_out,24,0);
        printf(\"LIST Command on client %d  user not logged in\\n\",arg->client_no);
        arg->passive=NO;
        return;
    }
    printf(\"Command: LIST from client %d\\n\",arg->client_no);
    buffer=calloc(1024,1);
    for(size=0;buf[size]!=\'\\xd\';size++);
    buf[size]=0;
    if (buf[4]==\' \') dp=opendir(buf+5);
    else dp=opendir(arg->working_dir);
    if (dp==NULL || (buf[4]==\' \' && is_dir_ok(arg,buf+5)==NO)){
        switch (errno){
            case EACCES:printf(\"LIST: Access to %s not possible for client %d\\n\",buf+5,arg->client_no);
                        send(arg->client_socket,no_perm,23,0);
                        break;
            default:
            case ENOENT:printf(\"LIST: Directory %s does not exist by client %d\\n\",buf+5,arg->client_no);
                        send(arg->client_socket,no_dir,30,0);
                        break;
            case ENOTDIR:printf(\"LIST: Dir %s is not a directory from client %d\\n\",buf+5,arg->client_no);
                        send(arg->client_socket,not_entry,29,0);
                        break;
        }
        free(buffer);
        arg->passive=NO;
        return;
    }
    send(arg->client_socket,start_trans,54,0);
    if (arg->passive==NO){
        arg->data_socket=socket(AF_INET,SOCK_STREAM,0);
        if (arg->data_socket==-1){
            printf(\"LIST: error in socket() from client %d\\n\",arg->client_no);
            send(arg->client_socket,no_data,21,0);
            free(buffer);
            arg->passive=NO;
            return;
        }
        s_in.sin_addr.s_addr=htonl(arg->data_ip);
        s_in.sin_port=htons(arg->data_port);
        s_in.sin_family=AF_INET;
        if (connect(arg->data_socket,(struct sockaddr *)&s_in,sizeof(s_in))!=0){
            printf(\"LIST: No data connection possible to client %d  connect()\\n\",arg->client_no);
            send(arg->client_socket,no_data,32,0);
            shutdown(arg->data_socket,2);
            free(buffer);
            arg->passive=NO;
            printf(\"FEHLER\\n\");
            return;
        }
    }
    else {                    //falls pasv_command abgesetzt
    int sock_save;
    struct sockaddr sock_addr;
    int i=sizeof(sock_addr);
        sock_save=accept(arg->data_socket,&sock_addr,&i);
        shutdown(arg->data_socket,2);
        arg->data_socket=sock_save;
    }
    if (dp!=NULL){
        while (ep=readdir(dp)){
            if (lstat(ep->d_name,&file_info)==-1) ;
            puts(ep->d_name);
            buffer[0]=0;
            buffer=strcat(buffer,ctime(&(file_info.st_atime))); //Zeitinfo holen
            buffer=strcpy(buffer,buffer+4);        //Wochentag entfernen
            strcpy(buffer+7,buffer+16);        //Uhrzeit entfernen
            sprintf(buffer+strlen(buffer)-1,\"%8ld %s\\xd\\xa\",file_info.st_size,ep->d_name);
            memmove(buffer+12,buffer,strlen(buffer));
            strncpy(buffer,\"---------- \",11);
            if (S_ISLNK(file_info.st_mode)) buffer[0]=\'l\';
            if (S_ISDIR(file_info.st_mode)) buffer[0]=\'d\';
            if (file_info.st_mode & S_IRUSR==S_IRUSR) buffer[1]=\'r\';
            if (file_info.st_mode & S_IWUSR==S_IWUSR) buffer[2]=\'w\';
            if (file_info.st_mode & S_IXUSR==S_IXUSR) buffer[3]=\'x\';
            if (file_info.st_mode & S_IRGRP==S_IRGRP) buffer[4]=\'r\';
            if (file_info.st_mode & S_IWGRP==S_IWGRP) buffer[5]=\'w\';
            if (file_info.st_mode & S_IXGRP==S_IXGRP) buffer[6]=\'x\';
            if (file_info.st_mode & S_IROTH==S_IROTH) buffer[7]=\'r\';
            if (file_info.st_mode & S_IWOTH==S_IWOTH) buffer[8]=\'w\';
            if (file_info.st_mode & S_IXOTH==S_IXOTH) buffer[9]=\'x\';
            send(arg->data_socket,buffer,strlen(buffer),0);
            for(size=0;size<1024;size++) buffer[size]=0;
        }
        closedir(dp);
        send(arg->client_socket,command_ok,23,0);
        shutdown(arg->data_socket,2);
    } 
    free(buffer);
    arg->passive=NO;
    return;
}
   
void name_list(struct client_struct *arg,char *buf){        //NLST-Kommando
DIR *dp;
struct dirent *ep;
int size;
struct sockaddr_in s_in;
char *command_ok=\"226 Transfer complete\\xd\\xa\";
char *start_trans=\"150 Opening ASCII mode data connection for file list\\xd\\xa\";
char *no_data=\"425 Can not open data connection\\xd\\xa\";
char *no_perm=\"550 Permission denied\\xd\\xa\";
char *no_dir=\"550 Directory does not exist\\xd\\xa\";
char *not_entry=\"550 Not a directory or file\\xd\\xa\";
char *buffer;
    if(arg->logged_in==NO) {
        send(arg->client_socket,user_out,24,0);
        printf(\"NLST Command on client %d  user not logged in\\n\",arg->client_no);
        arg->passive=NO;
        return;
    }
    printf(\"Command: NLST from client %d\\n\",arg->client_no);
    buffer=calloc(1024,1);
    for(size=0;buf[size]!=\'\\xd\';size++);
    buf[size]=0;
    if (buf[4]==\' \') dp=opendir(buf+5);
    else dp=opendir(arg->working_dir);
    if (dp==NULL || (buf[4]==\' \' && is_dir_ok(arg,buf+5)==NO)){
        switch (errno){
            case EACCES:printf(\"NLST: Access to %s not possible for client %d\\n\",buf+5,arg->client_no);
                        send(arg->client_socket,no_perm,23,0);
                        break;
            default:
            case ENOENT:printf(\"NLST: Directory %s does not exist by client %d\\n\",buf+5,arg->client_no);
                        send(arg->client_socket,no_dir,30,0);
                        break;
            case ENOTDIR:printf(\"NLST: %s is not a directory from client %d\\n\",buf+5,arg->client_no);
                        send(arg->client_socket,not_entry,29,0);
                        break;
        }
        free(buffer);
        arg->passive=NO;
        return;
    }
    send(arg->client_socket,start_trans,54,0);
    if (arg->passive==NO){
        arg->data_socket=socket(AF_INET,SOCK_STREAM,0);
        if (arg->data_socket==-1){
            printf(\"NLST: error in socket() from client %d\\n\",arg->client_no);
            send(arg->client_socket,no_data,21,0);
            free(buffer);
            arg->passive=NO;
            return;
        }
        s_in.sin_addr.s_addr=htonl(arg->data_ip);
        s_in.sin_port=htons(arg->data_port);
        s_in.sin_family=AF_INET;
        if (connect(arg->data_socket,(struct sockaddr *)&s_in,sizeof(s_in))!=0){
            printf(\"NLST: No data connection possible to client %d  connect()\\n\",arg->client_no);
            send(arg->client_socket,no_data,32,0);
            shutdown(arg->data_socket,2);
            free(buffer);
            printf(\"FEHLER\\n\");
            arg->passive=NO;
            return;
        }
    }
    else {                    //falls pasv_command abgesetzt
    int sock_save;
    struct sockaddr sock_addr;
    int i=sizeof(sock_addr);
        sock_save=accept(arg->data_socket,&sock_addr,&i);
        shutdown(arg->data_socket,2);
        arg->data_socket=sock_save;
    }
    if (dp!=NULL){
        while (ep=readdir(dp)){
            sprintf(buffer,\"%s\\xd\\xa\",ep->d_name);
            for(size=0;buffer[size]!=0;size++);
            send(arg->data_socket,buffer,size,0);
        }
        closedir(dp);
        send(arg->client_socket,command_ok,23,0);
        shutdown(arg->data_socket,2);
    } 
    free(buffer);
    printf(\"Success\\n\");
    arg->passive=NO;
    return;
}

void user_login(struct client_struct *arg,char *buf){      //USER Kommando
char *pass_req=\"331 Password required\\xd\\xa\";
struct passwd *p_entry;
char *user_ok= \"230 Username OK, server is ready\\xd\\xa\";
char *user_out=\"501 Username wrong, not logged in\\xd\\xa\";
char *buf1;
int user_length=0;
    buf1=calloc(1024,1);
    memcpy(buf1,pass_req,26);
    while (buf[5+user_length]!=10) user_length++;
    if (user_length!=0){
        memcpy(buf1+27,buf+5,user_length-1);
        buf1[27+user_length+1]=0;
    }
    if ((user_length==0) || (p_entry=getpwnam(buf1+27))==NULL){
        send(arg->client_socket,user_out,35,0);
        printf(\"User %s existiert nicht!\\n\",buf1+27);free(buf1);
        return;
    }
    memcpy(&arg->pass_entry,p_entry,sizeof(struct passwd));
    strncpy(arg->user+0,buf+27,8);
    arg->user[8]=0;
    if (arg->pass_entry.pw_passwd==NULL) {
        arg->logged_in=YES;
        chroot(server_root);
        if (setgid(p_entry->pw_gid)==-1){
            send(arg->client_socket,\"500 Internal Error\\xd\\xa\",20,0);
            return;
        }
        if (setuid(p_entry->pw_uid)==-1){
            send(arg->client_socket,\"500 Internal Error\\xd\\xa\",20,0);
            return;
        }
        send(arg->client_socket,user_ok,34,0);
    }
    else {
        arg->logged_in=PASS;
        send(arg->client_socket,pass_req,strlen(pass_req),0);
    }
    free(buf1);               
    return;
}

void pass_command(struct client_struct *arg,char *buf){            //PASS-Kommando
char *pass_ok=\"230 Password ok, server is ready\\xd\\xa\";
char *pass_false=\"501 Password wrong\\xd\\xa\";
char *pass_syn=\"500 Syntax error\\xd\\xa\";
char *pass_no=\"501 don\'t need a password\\xd\\xa\";
char *salt,*en_pwd;
    if (arg->logged_in==NO){
        send(arg->client_socket,user_out,strlen(user_out),0);
        return;
    }
    if (arg->logged_in==YES){              //es wird kein Passwort ben[tigt
        send(arg->client_socket,pass_no,strlen(pass_no),0);
        return;
    }
    if (strlen(buf)<7){
        send(arg->client_socket,pass_syn,strlen(pass_syn),0);
        return;
    }
    salt=calloc(3,1);
    salt[0]=arg->pass_entry.pw_passwd[0];
    salt[1]=arg->pass_entry.pw_passwd[1];
    en_pwd=crypt(buf+5,salt);
    if (strcmp(en_pwd,arg->pass_entry.pw_passwd)!=0) {          //PASS ist falsch
        send(arg->client_socket,pass_false,strlen(pass_false),0);
        free(salt);
        return;
    }
    if (setgid(p_entry->pw_gid)==-1){
      send(arg->client_socket,\"500 Internal Error\\xd\\xa\",20,0);
      return;
  }
  if (setuid(p_entry->pw_uid)==-1){
      send(arg->client_socket,\"500 Internal Error\\xd\\xa\",20,0);
      return;
  }
  send(arg->client_socket,pass_ok,strlen(pass_ok),0);
  chroot(server_root);
  free(salt);
  return;
}

void port_command(struct client_struct *arg,char *buf){      //PORT Kommando
int i,j,k;
unsigned int port;
char *command_ok=\"200 PORT command ok\\xd\\xa\";
    if(arg->logged_in==NO) {
        send(arg->client_socket,user_out,24,0);
        return;
    }
    k=j=0;
    for (i=0;buf[i]!=0;i++) if (buf[i]==\',\') {  //alle \',\' durch \'.\' ersetzen
        buf[i]=\'.\';
        k++;
        if (k==4){                    //ab hier beginnt der Port
            port=atoi(buf+i+1)*256;    //das erste Byte
            for(j=i+1;buf[j]!=\',\';j++);  //das zweite Byte suchen
            port+=atoi(buf+j+1);
            buf[i]=\' \';          //trennt IP von Port
        }
    }
    if (k!=5){          //das waren zu wenig/viel Parameter
        send(arg->client_socket,error_in_param,45,0);
        return;
    }
    for (i=0;buf[i]!=0 && buf[i]!=\' \';i++);  //ersten Parameter suchen (IP)
    i++;
    if ((arg->data_ip=ntohl(inet_addr(buf+i)))==-1){            //Adresse fuer Datenleitung ermitteln
        send(arg->client_socket,error_in_param,45,0);
        return;
    }
    arg->data_port=port;      //neuer Port wurde berechnet
    send(arg->client_socket,command_ok,21,0);
    return;
}


void syst_command(struct client_struct *arg,char *buf){        //SYST-Kommando
send(arg->client_socket,\"215 UNIX\\xd\\xa\",strlen(\"215 UNIX\\xd\\xa\"),0);
return;
}

void recv_all_incoming(struct client_struct *arg){
char *buf;
int pos,rest_size,count;
    buf=calloc(RECV_SIZE,1);
    for (;;){
        rest_size=arg->head-arg->tail;
        if (rest_size>0) rest_size--;
        else rest_size+=RECV_SIZE-1;
        pos=0;
        count=recv(arg->client_socket,buf,rest_size,0);          //soviele Daten empfangen, wie noch Platz im Puffer
        printf(\"received %d bytes from client %d\\n\",count,arg->client_no);
        if (count==0) {                  //Client hat Verbindung unterbrochen\'
            printf(\"recv_all_incoming(): client closed connection  client %d\\n\",arg->client_no);
            free(buf);
            pthread_exit(NULL);
            return;
        }
        while (count>0) {
            arg->recv_buffer[arg->tail]=buf[pos];
            arg->tail=(arg->tail+1)%RECV_SIZE;
            pos++;
            count--;
        }
    }
    free(buf);
    return;
}

void pasv_command(struct client_struct *arg,char *buf){        //PASV-Kommando
char *pasv_1=\"227 Entering Passiv Mode (\";
char *pasv_3=\")\\xd\\xa\";
char *pasv_2,*pasv_ok;
int i,sock_save;
struct sockaddr_in sock_in;
struct sockaddr sock_addr;
int addr_size=sizeof(sock_addr);
    (arg->data_port)++;          //hier wartet der Server auf eine Datenverbindung
    pasv_ok=calloc(1024,1);
    strcpy(pasv_ok,pasv_1);
    pasv_2=inet_ntoa(htonl(arg->data_ip));
    strcat(pasv_ok,pasv_2);
    strcat(pasv_ok,\",\");
    sprintf(pasv_ok+strlen(pasv_ok),\"%d,\",arg->data_port/256);
    sprintf(pasv_ok+strlen(pasv_ok),\"%d\",arg->data_port%256);
    strcat(pasv_ok,pasv_3);
    for(i=0;i<strlen(pasv_ok);i++) if (pasv_ok[i]==\'.\') pasv_ok[i]=\',\';
    arg->passive=YES;
    arg->data_socket=socket(AF_INET,SOCK_STREAM,0);
    if (arg->data_socket==-1) puts(\"Socket Error\");
    sock_in.sin_family=AF_INET;
    sock_in.sin_port=htons(arg->data_port);
    sock_in.sin_addr.s_addr=inet_addr(\"127.0.0.1\"); //htonl(arg->data_ip);
    if (arg->data_socket==-1) puts(\"Socket Error\");
    if (bind(arg->data_socket,(struct sockaddr *)&sock_in,sizeof(sock_in))==-1){
        send(arg->client_socket,\"550 Internal Error\\xd\\xa\",20,0);
        puts(\"Bind-Error\");
        return;
    }
    if (listen(arg->data_socket,1)==-1) puts(\"Error-Listen\");
    send(arg->client_socket,pasv_ok,strlen(pasv_ok),0);
 
 
    free(pasv_ok);
    return;
}

void stru_command(struct client_struct *arg,char *buf){      //STRU-Kommando
char c;
    if (strlen(buf)!=8){        //Es wurde zuviel/zuwenig angegeben
        send(arg->client_socket,\"500 Syntax error\\xd\\xa\",18,0);
        return;
    }
    c=toupper(buf[strlen(buf)-1-2]);          //Strukturtyp holen
    if (c!=\'F\'&&c!=\'R\'&&c!=\'P\'){
        send(arg->client_socket,\"501 Unknown structure\\xd\\xa\",23,0);
        return;
    }
    if (c==\'P\' || c==\'R\'){
        send(arg->client_socket,\"504 Structure unavailable\\xd\\xa\",27,0);
        return;
    }
    arg->stru=c;
    send(arg->client_socket,\"200 Command OK\\xd\\xa\",16,0);
    return;
}

void mode_command(struct client_struct *arg,char *buf){      //MODE-Kommando
char c;
    if (strlen(buf)!=8){        //Es wurde zuviel/zuwenig angegeben
        send(arg->client_socket,\"500 Syntax error\\xd\\xa\",18,0);
        return;
    }
    c=toupper(buf[strlen(buf)-1-2]);          //Modustyp holen
    if (c!=\'B\'&&c!=\'C\'&&c!=\'S\'){
        send(arg->client_socket,\"501 Unknown mode\\xd\\xa\",18,0);
        return;
    }
    if (c==\'C\'){
        send(arg->client_socket,\"504 Modus unavailable\\xd\\xa\",23,0);
        return;
    }
    arg->mode=c;
    send(arg->client_socket,\"200 Command OK\\xd\\xa\",16,0);
    return;
}

void type_command(struct client_struct *arg,char *buf){      //TYPE-Kommando
#define AN (unsigned int)(\'A\'*256+\'N\')
#define L8 (unsigned int)(\'L\'*256+\'8\')
unsigned int c;
    if (strlen(buf)!=8 && strlen(buf)!=9){        //Es wurde zuviel/zuwenig angegeben
        send(arg->client_socket,\"500 Syntax error\\xd\\xa\",18,0);
        return;
    }
    if (strlen(buf)==8) c=(unsigned int) toupper(buf[strlen(buf)-1-2]);
    else c=(unsigned int) (toupper(buf[strlen(buf)-1-3])*256+toupper(buf[strlen(buf)-1-2]));
    if (arg->type!=(unsigned int)\'A\' && arg->type!=(unsigned int)\'I\' && arg->type!=L8 && arg->type!=AN){
        send(arg->client_socket,\"501 Unknown type\\xd\\xa\",18,0);
        return;
    }           
    arg->type=c;
    if (arg->type==(unsigned int)\'A\') send(arg->client_socket,\"200 Command ok, but TYPE A is TYPE AN!\\xd\\xa\",40,0);
    else send(arg->client_socket,\"200 Command OK\\xd\\xa\",16,0);
    return;
#undef AN
#undef L8
}

void handle_incoming(struct client_struct *arg){            //hier werden die Clients bedient
char *actual_command;
char *welcome_message=\"220 FTP-Server V1.0 is ready (written by Matthias Kay 1997)\\xd\\xa\";
    send(arg->client_socket,welcome_message,61,0);      //Welcome message senden
    printf(\"send welcome_message to client %d\\n\",arg->client_no);
    pthread_create(&arg->recv_nr,&local_console_thread_attr,(void *)recv_all_incoming,arg);
    actual_command=calloc(1,1);        //wegen free(actual_command)
    do {
        do {
            free(actual_command);
            while ((actual_command=get_command(arg))==NULL) ;
            printf(\"%s\",actual_command);
            if (strncmp(\"help\",actual_command,4)==0) help(arg);
            else if (strncmp(\"user\",actual_command,4)==0) user_login(arg,actual_command);
            else if (strncmp(\"port\",actual_command,4)==0) port_command(arg,actual_command);
            else if (strncmp(\"nlst\",actual_command,4)==0) name_list(arg,actual_command);
            else if (strncmp(\"list\",actual_command,4)==0) list_dir(arg,actual_command);
            else if (strncmp(\"cwd\",actual_command,3)==0) cwd_command(arg,actual_command);
            else if (strncmp(\"pwd\",actual_command,3)==0) pwd_command(arg,actual_command);
            else if (strncmp(\"cdup\",actual_command,4)==0) cdup_command(arg,actual_command);
            else if (strncmp(\"noop\",actual_command,4)==0) noop_command(arg,actual_command);
            else if (strncmp(\"syst\",actual_command,4)==0) syst_command(arg,actual_command);
            else if (strncmp(\"pasv\",actual_command,4)==0) pasv_command(arg,actual_command);
            else if (strncmp(\"retr\",actual_command,4)==0) retr_command(arg,actual_command);
            else if (strncmp(\"type\",actual_command,4)==0) type_command(arg,actual_command);
            else if (strncmp(\"mode\",actual_command,4)==0) mode_command(arg,actual_command);
            else if (strncmp(\"stru\",actual_command,4)==0) stru_command(arg,actual_command);                     
            else if (strncmp(\"pass\",actual_command,4)==0) pass_command(arg,actual_command);
            else if (strncmp(\"stor\",actual_command,4)==0) stor_command(arg,actual_command);
        }while (strncmp(\"quit\",actual_command,4)!=0 && strncmp(\"rein\",actual_command,4)!=0);
            //hier den \"rein\"-Befehl einfügen!!
    } while (strncmp(\"quit\",actual_command,4)!=0);
    send(arg->client_socket,\"221 Goodbye\\xd\\xa\",13,0);
    shutdown(arg->client_socket,2);
    return;
}

int main () {
int dummy_size,i,next_client;            //Nummer von n]chsten freien Client

    for (i=0;i<MAX_CONNECTIONS;i++) {
        incoming_client[i].is_in_use=NO;        //alle Clients als unbenutzt markieren
        incoming_client[i].logged_in=NO;
        incoming_client[i].client_no=i;
        incoming_client[i].data_port=htons(20);
        incoming_client[i].working_dir=server_root;
        incoming_client[i].passive=NO;
        incoming_client[i].stru=\'F\';
        incoming_client[i].mode=\'S\';
        incoming_client[i].type=(unsigned int) (\'A\'*256+\'N\');
    }
    printf(\"FTP-SERVER    (c)1997  Matthias Kay\\n\");
    lauschen=socket(AF_INET,SOCK_STREAM,0);
    if (lauschen==-1) {
        printf(\"FTP: Fehler beim Erstellen des Sockets!\\n\");
        printf(\"%d\",errno);
        exit(1);
    }
    s_in.sin_port=htons(lauschen_port);
    s_in.sin_addr.s_addr=inet_addr(\"127.0.0.1\");
    s_in.sin_family=AF_INET;
    if (bind(lauschen,(struct sockaddr *)&s_in,sizeof(s_in))==-1) {
        printf(\"FTP: Bind-Error!\\n\");
        printf(\"%d\",errno);
        exit(1);
    }
    if (listen(lauschen,5)==-1) {
        printf(\"FTP: Listen-Error!\\n\");
        printf(\"%d\",errno);
        exit(1);
    }
    for (;;){
        while ((next_client=get_free_client())==-1) ;          //bis ein freier gefunden wurde
        dummy_size=sizeof(s_in);
        incoming_client[next_client].client_socket=accept(lauschen,(struct sockaddr*)&s_in,&dummy_size);
        printf(\"FTP: Verbunden mit %x: %d\\n\",s_in.sin_addr,s_in.sin_port);
        pthread_attr_init(&incoming_client[next_client].thread_attribute);
        incoming_client[next_client].thread_attribute.detachstate=PTHREAD_CREATE_DETACHED;
        incoming_client[next_client].recv_buffer=calloc(RECV_SIZE,1);
        incoming_client[next_client].head=0;
        incoming_client[next_client].tail=0;
        incoming_client[next_client].data_ip=ntohl(s_in.sin_addr.s_addr);
        pthread_create(&incoming_client[next_client].thread_nr,&incoming_client[next_client].thread_attribute,(void *)handle_incoming,&incoming_client[next_client]);
    }
    printf(\"Socket geschlossen\\n\");
    shutdown(lauschen,2);
    return 0;
}
Avatar billede futter2 Nybegynder
04. oktober 2001 - 00:09 #8
Jeg prøver lige.
Mange tak for interessen.
Skriver igen efter nogle test........
Avatar billede mickni33 Nybegynder
04. oktober 2001 - 00:13 #9
Det ser fandme flot ud det kode tror også lige jeg kigger lidt på det selv. kunne ikke finde noget til builderen. Fandt kun til linux men det kan dog også bruges i builderen.
Avatar billede futter2 Nybegynder
04. oktober 2001 - 00:21 #10
ja, jeg tror jeg vil begynde at lave min eget FTR SERVER class ud fra denne kode, hvis jeg alså kan finde ud af det, hvis du gør det samme kunne vi måske snakke om kommende problemer, men jeg er tilfreds med svaret sp du får pointene.
Avatar billede futter2 Nybegynder
04. oktober 2001 - 00:22 #11
ups det var ikke det første svat der var accepteret men det med UNIX koden.
Avatar billede mickni33 Nybegynder
04. oktober 2001 - 00:24 #12
Jeg takker mange gange. Tænkte netop på det samme man har bedre overblik når det bliver delt op i klasser man kan måske endda undlade en masse ting.
min mail er mickni@mail.dk
Avatar billede mickni33 Nybegynder
04. oktober 2001 - 00:25 #13
nej men det giver det samme for der er kun mig der har været på
Avatar billede futter2 Nybegynder
04. oktober 2001 - 00:26 #14
ok, min e-mail er futter@post9.tele.dk
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester