File:  [LON-CAPA] / loncom / lonnet / c / lonnet.c
Revision 1.1: download - view: text, annotated - select for diffs
Tue Nov 23 19:27:17 1999 UTC (24 years, 6 months ago) by albertel
Branches: MAIN
CVS tags: HEAD
- Initial revisions of the c version of lonnet.
- Currently non-functional

#include "lonnet.h"
#include <stdio.h>     
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/un.h>


/*lonnet.c (by Guy Albertelli); based on lonnet.pm by Gerd Kortemeyer*/

char *strsave(char *s) 
{            
   char *p;  
   if (s==NULL) {return s;}
   p=(char*)malloc(strlen(s)+1);
   strcpy(p,s);
   return (p);
}

int get_apache_config(char* key_word,char* value) {
  FILE *fp;
  int done=0,failed=0,num,found=0,i,j,result=-1,returnVal;
  char testkey[MAX_BUFFER_SIZE],testval[MAX_BUFFER_SIZE],c;

  if ((fp=fopen("/etc/httpd/conf/access.conf","r"))==NULL) { return (-1); }
  
  do {
    testkey[0]='\0';testval[0]='\0';
    num = fscanf(fp,"PerlSetVar %s %s",testkey,testval);
    if (num == 2) { 
      result = strcasecmp(testkey,key_word); 
      //printf("num: %d:testkey:%s:testval:%s:\n",num,testkey,testval);
    }
    if (result==0) { done=1; }

    if (num==EOF) { failed=1; }
    found=0;
    if (num!=2) {
      while(1) {
	c=fgetc(fp);
	if (found) {
	  if (c!='\n') {
	    ungetc(c,fp);
	    break;
	  }
	}
	if (c=='\n') found=1;
	if (((char)c)==((char)EOF)) break;
      }
    }
  } while (!done && !failed);
  fclose(fp);
  
  /*strip out the " and \\ */
  if (done) {
    for(i=0,j=0;i<(strlen(testval)+1);i++) {
      value[j]='\0';
      if (testval[i] == '\\' && (i < (strlen(testval))) ) {
	i++;value[j]=testval[i];j++;
      } else if (testval[i] != '\"' ) {
	value[j]=testval[i];j++;
      }
    }
    value[j]='\0';
    returnVal=j;
  }
  return returnVal;
}

char *subreply (char* cmd, char* server) {
  char *answer,*peerfile, *tempStr, inbuf[MAX_BUFFER_SIZE];
  int sockFD, portFD, fromlen, length, totleng;
  struct sockaddr_un lonc;
  struct sockaddr_un from;
  
  answer=(char*)malloc(MAX_BUFFER_SIZE);
  answer[0]='\0';
  length=strlen(lonSockDir)+strlen(peerfile)+3;
  peerfile=(char*)malloc(length);
  sprintf(peerfile,"%s/%s",lonSockDir,server);
  
  if (length > UNIX_PATH_MAX) {
    fprintf(stderr,"Path to socket too long:%d\n",length);
    sprintf(answer,"Path to socket too long:%d\n",length);
    return answer;
  }

  /*
   */
  sockFD = socket (AF_UNIX, SOCK_STREAM, 0);
  strcpy(lonc.sun_path, peerfile);
  lonc.sun_family = AF_UNIX;
  if (bind (sockFD, (struct sockaddr *) &lonc,
	    strlen(lonc.sun_path) + sizeof(lonc.sun_family))) {
    fprintf(stderr,"Bind failed to %s\n",peerfile);
    sprintf(answer,"Bind failed to %s\n",peerfile);
    return answer;
  }
  
  listen (sockFD, 10);
  portFD = accept (sockFD, (struct sockaddr *) &from, &fromlen);
  
  write(portFD, cmd, strlen(cmd));
  
  while (1) {
    length=read(portFD, inbuf, MAX_BUFFER_SIZE);
    totleng = strlen(answer) + strlen(inbuf) + 1;
    tempStr = (char*)malloc(totleng);
    strcat(tempStr,answer);
    strcat(tempStr,inbuf);
    free(answer);  
    answer = tempStr;
    if ( length != MAX_BUFFER_SIZE ) { break; }
  }
  /*
   */

  return answer;
}

char * reply (char *cmd,char *server) {
  char *answer=NULL;
  answer=subreply(cmd,server);
  if (strcmp(answer,"con_lost")) { 
    free(answer);
    answer=subreply(cmd,server);
  }
  return answer;
}

/*
sub subreply {
    my ($cmd,$server)=@_;
    my $peerfile="$perlvar{'lonSockDir'}/$server";
    my $client=IO::Socket::UNIX->new(Peer    =>"$peerfile",
                                     Type    => SOCK_STREAM,
                                     Timeout => 10)
       or return "con_lost";
    print $client "$cmd\n";
    my $answer=<$client>;
    chomp($answer);
    if (!$answer) { $answer="con_lost"; }
    return $answer;
}

# ------------------------------------------------------ Critical communication
sub critical {
    my ($cmd,$server)=@_;
    &senddelayed($server);
    my $answer=reply($cmd,$server);
    if ($answer eq 'con_lost') {
        my $pingreply=reply('ping',$server);
	&reconlonc("$perlvar{'lonSockDir'}/$server");
        my $pongreply=reply('pong',$server);
        &logthis("Ping/Pong for $server: $pingreply/$pongreply");
        $answer=reply($cmd,$server);
        if ($answer eq 'con_lost') {
            my $now=time;
            my $middlename=$cmd;
            $middlename=~s/\W//g;
            my $dfilename=
             "$perlvar{'lonSockDir'}/delayed/$now.$middlename.$server";
            {
             my $dfh;
             if ($dfh=Apache::File->new(">$dfilename")) {
                print $dfh "$server:$cmd\n";
	     }
            }
            sleep 2;
            my $wcmd='';
            {
	     my $dfh;
             if ($dfh=Apache::File->new("$dfilename")) {
                $wcmd=<$dfh>;
	     }
            }
            chomp($wcmd);
            if ($wcmd eq "$server:$cmd") {
		&logthis("Connection buffer $dfilename: $cmd");
                &logperm("D:$server:$cmd");
	        return 'con_delayed';
            } else {
                &logthis("CRITICAL CONNECTION FAILED: $server $cmd");
                &logperm("F:$server:$cmd");
                return 'con_failed';
            }
        }
    }
    return $answer;
}
*/

/* need 
   - logthis
   - logperm
   - reconlonc, maybe, don't absolutely need to make critical reconnect
*/
   
int main() {
  char value[MAX_BUFFER_SIZE];
  get_apache_config("lonSockDir",value);
  lonSockDir=strsave(value);

  printf("Found a value of:%s\n",value);
  printf("Reply: %s\n",reply("put akey:value","zaphod"));
  return 1;
}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>