/*
ztalk -- full rate ztalk, using /dev/audio
modified by fein = feinmann@cs.mcgill.ca
Wed Mar 30 17:50:44 EST 1994

A LOT OF source clean up by fein 
Thu Mar 31 02:07:55 EST 1994
All the implicit declarations and unused vars removed.
And commentation error is fixed.
------------------------------------------------------------
originally from sd = Scott Doty, scott@cs.santarosa.edu
Mon Mar 28 03:34:03 PST 1994
Extremely alpha -- use at your own risk -- don't blame me
or these guys:
*/

/* Copyright (C) 1993 Free Software Association of Germany

   The following is only valid, if you use this outside the Federal
   Republic of Germany.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   If you don't have a a copy of the GNU General Public License
   write to the Free Software Foundation, Inc., 675 Mass Ave, 
   Cambridge, MA 02139, USA.

   (C)opyright 1993,1994 FREE SOFTWARE ASSOCIATION OF GERMANY

   ----------------------------------------------------------------

   Fuer die Nutzung dieses Quell-Codes innerhalb der Bundesrepublik
   Deutschland gilt:

   Dieses Programm ist freie Software und kann unter den Bedingungen
   der Deutschen Free Software Lizenz weitergeben und/oder modifiziert
   werden.

   Wir haben dieses Programm in der Hoffnung entwickelt, dass es
   sich als nuetzlich erweist. Wir uebernehmen jedoch *KEINERLEI*
   Garantien auf die Funktion oder Verwendbarkeit dieses Programms.
   Der Anwender nutzt dieses Programm * AUF EIGENES RISIKO *

   Diesem Programm sollte eine Kopie der Deutschen Free Software Lizenz
   (DFSL) beigefuegt sein. Falls nicht, kann eine Kopie von uns angefordert
   werden: Free Software Association of Germany, Heimatring 19,
   60596 Frankfurt (info@elara.fsag..de), Telefon: ++49 - 69 - 6312083

   (C)opyright 1993,1994 FREE SOFTWARE ASSOCIATION OF GERMANY */


#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/soundcard.h>
#include <linux/time.h>
#include <sys/dir.h>
#include "ztalk.h"
#include "gsm.h"
#include "ul2s.h"

#ifdef TERM
#include "client.h"
#endif

#define AUDIO "/dev/audio"
#define VMDIR "/tmp/vmail"
#ifdef DEVELOP
#define TCP_PORT_ZTALK	5111
#else
#define TCP_PORT_ZTALK	5109
#endif

#ifdef WANT_FILE
int send_sound(METHOD method,char send_file[50]);
#else
int send_sound(METHOD method);
#endif
int compress_buffer(    METHOD method,
                        unsigned char *buf_record,
                        int size_record,
                        unsigned char ** buf_send,
                        int * size_send
                );
int transmit_buffer(METHOD method, unsigned char * bu, int cnt);
void read_line(int hd);
int gl_tcp_open(char *host, char *service, int port);
int slow_write(int hd,char *s,int sz);
void yikes (char * msg, int stat);

int VERBOSE = 1;
/* unsigned char sndbuff[100000]; *//*we'll use the read buffer*/
static unsigned char buf_record[SIZE_MB]; /* sd: that outta clear the rug. */

int pos_record = 0;

#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif

struct sockaddr_in	tcp_srv_addr;
struct sockaddr_in	myctladdr;
struct sockaddr_in	data_addr;
struct servent		tcp_serv_info;
struct hostent		tcp_host_info;

char current_ip[100];
char host[100];
int great_errno; 

#ifndef lint
static	char copyright[] =
"Copyright (c) 1994 Scott Doty, released under conditions of the GPL.\n"
"Portions Copyright (c) 1993, 1994 Free Software Association of Germany.\n";
#endif

#ifndef lint
static char sccsid[] = "@(#) ztalk  Version 0.2a"
			" Mon Mar 28 03:34:28 PST 1994\n";
#endif 
    
#ifndef FD_SETSIZE
/* Forward compatability */
#define FD_SET(n, p)    ((p)->fds_bits[0] |= (1<<(n)))
#define FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1<<(n)))
#define FD_ISSET(n, p)  ((p)->fds_bits[0] & (1<<(n)))
#define FD_ZERO(p)      ((p)->fds_bits[0] = 0)
#endif

void helpmenu(char option) {
/* Some people have requested for on-line help. Here you go. :-) 
                                        -fein                   */

	printf("\n");
        switch(option) {
        case 'h': case '?':
                printf("[h/?]: show help for given command\n");

                printf("\n'h h' will list all the commands\n\n");
#ifdef WANT_FILE
		printf("[z]: start file sending mode\n");
#endif
                printf("[l]: list all the entries in the address book\n");
                printf("[!]: send message to an address\n");
                printf("[m]: send message to an aliased address\n");
                printf("[a]: set away -turn on the logger\n");
		printf("[v]: list the logged voice mails\n");
                printf("[p]: play the mesg with matching pattern\n");
                printf("[f]: toggle compression mode on/off\n");
                printf("[.]: repeat - send the msg to the previous dest\n");
                printf("[q]: quit - exit from ztalk session\n");

                break;
#ifdef WANT_FILE
	case 'z':
		printf("[z]: start file sending mode\n");
		printf("     z off - turn file recording off\n");
		printf("     z <file> - send audio file <file>\n");
		break;
#endif
        case 'l':
                printf("[l]: list all the entries in the address book\n");
                printf("     No argument is necessary\n");
                break;
        case '!':
                printf("[!]: send message to an address\n");
                printf("     ! <destination address>\n");
                printf("     eg. ! binkley.cs.mcgill.ca\n");
                break;
        case 'm':
                printf("[m]: send message to an aliased address\n");
                printf("     m <alias>\n");
                printf("     eg. m fein\n");
                break;
        case 'a':
                printf("[a]: toggle away(for logging) on/off\n");
                printf("     No argument is necessary\n");
                break;
	case 'v':
                printf("[v]: list the logged voice mails\n");
		printf("     No argument is nceessary\n");
		break;
	case 'p':
		printf("[p]: play the mesg with matching pattern\n");
		printf("     p a: plays all messages\n");
		printf("     p #: play message message numbered # from the 'v' message list\n");
		break;
        case 'f':
                printf("[f]: toggle compression mode on/off\n");
                printf("     No arguement is necessary\n");          
                break;
        case '.':
                printf("[.]: repeat - send the msg to the previous dest\n");
                printf("     No arguement is necessary\n");
                break;
        case 'q':
                printf("[q]: quit - exit from ztalk session\n");
                printf("     No argument is necessary\n");
                break;
        printf("\n[Invalid Argument]: h <command> for help\n\n");
        }
}
        
char *addresslist(char *datafile, char *InAlias)  {
/* Because I wanted to be able to change the address book while I am
   in ztalk shell, I made it re-read each time.. Don't complain! :-) 
                                        -fein                   */

    int  ind=1;
    char alias[100], lookedup[100];
    FILE *inputfile;
 
    printf("\n[Reading in the database.] \n");
    inputfile=fopen(datafile, "r");
    while (1) {
        fscanf(inputfile, "%s", alias);
        if (alias[0]=='$') {
            printf("[Invalid Alias]\n");
            fclose(inputfile);
            return "error";
         }      
        fscanf(inputfile, "%s", lookedup);
        if (strcmp(InAlias,alias)==0) {
            printf("<Alias - Effective Destination Address(%d): %s>\n"
                    ,ind, lookedup);
            fclose(inputfile);
            return lookedup;
          }
        ind++;
      }
  }

void main(int argc, char **argv)
{
    METHOD method = ME_GSM;

    int fileOK;
    int do_rec=0;
    int dirc;
    FILE *fp;
    FILE *aud;
    FILE *fil;
    FILE *ring;
    DIR *dirp;
    struct direct *dp;
    int dirp_count = 0;
    int count = 1;
    char key_check ='a';
    char keypress = '\0';
    char tmp[50];
    char vmdir[50];
    char infile[100];
    char initfile[15]="/.ztalkrc";
    char prev[40]="error";
    char vmplay[60];
#ifdef WANT_FILE
    char send_file[50];
#endif

    signal(SIGINT, SIG_DFL);

    strcpy(infile,getenv("HOME"));
    printf("\nHome dir is %s\n", infile);
    strcat(infile, initfile);
    printf("Initfile is %s\n", infile);
    if ((fp=(fopen("/tmp/.ztalk_away", "r")))!=NULL) {
        printf("\n[Currently Msg Log Turned On]\n"); 
        fclose(fp); }
    else 
        printf("[Currently Msg Log Turned Off]\n");

    if((NULL != argv[1])&&(strcmp(argv[1],"-f")==0)) {
        method = ME_FULL;
        printf("\n[Compression Turned Off]\n");
      }
    fileOK = ((fp=fopen(infile, "r"))!=NULL);
    if (fileOK==0) printf("\n[No Addressbook Loaded] - continued\n");
        
    while (1) {
        printf("\n[ztalk]: "); 
        scanf("%s", host);
        switch(host[0]) {
        case 'h': case '?':
            scanf("%s", host);
            helpmenu(host[0]);
            do_rec=0;
            break;
        case 'l':
            if (fileOK!=0) system("$PAGER ~/.ztalkrc");
            else printf("\n[No Address Book Available]\n");
            do_rec=0;
            break;
        case '!':
            scanf("%s", host);
            printf("\n<Address Input: %s>\n", host);
            do_rec=1;
            break;
#ifdef WANT_FILE
        case 'z':
 	    scanf("%s",send_file);
	    if(!strcmp(send_file,"off")) {
	        printf("ztalk: File recording turned off.\n");
		send_file[0]='\0';
		do_rec = 0;
		break;
	      }
	    if((fp=fopen(send_file,"rb"))==NULL) {
                printf("ztalk: File does not exist.\n");
	        printf("ztalk: File recording turned off.\n");
                send_file[0]='\0';
	        do_rec=0;
	        break;
	      }
	    else {
      	        fclose(fp);
	      }
	    printf("ztalk: File recording turned on.\n");
	    do_rec=0;
	    break;
#endif
       case 'm':
           scanf("%s", host);
           if (fileOK!=0) {
               strcpy(host,addresslist(infile, host));
               do_rec=1;}
           else
               printf("\n[No Address Book Available]\n");
           break;
       case 'a':
           if ((fp=(fopen("/tmp/.ztalk_away", "r")))!=NULL) {
               remove("/tmp/.ztalk_away");
               printf("[Toggled: Msg Log Turned Off]\n"); 
	     }
           else {
               fopen("/tmp/.ztalk_away", "w+");
               printf("[Toggled: Msg Log Turned On]\n");
	     }
           do_rec=0;
           break;
       case 'f':
           if (method==ME_FULL) {
               printf("[Toggled: Now In GSM Compression Mode]\n");
               method=ME_GSM;
	     }
	   else {
               printf("[Toggled: Now In Full Rate Mode]\n");
               method=ME_FULL;
	     }
           do_rec=0;
           break;
       case '.':
           strcpy(host, prev);
           printf("<Repeat - Effective Destination Address: %s>\n", host);
           do_rec=1;
           break;
       case 'v':
	   getchar();
           dirp = opendir(VMDIR);
           while((dp = readdir(dirp))!=NULL) {
	       if(!(!strcmp(dp->d_name,".")||!strcmp(dp->d_name,".."))) {
		   dirp_count++;
		   printf("\t(%2d) %s\n",dirp_count,dp->d_name);
		   if((dirp_count/count) == 23) {
		       printf("\t<ENTER: Continue - 'q' for QUIT>: ");
		       if (getchar()=='q') break;
		       count++;
		     }
		 }
	     }
	   count = 1;
	   dirp_count = 0;
           closedir(dirp);
  	   do_rec=0;
           break;
       case 'p':
	   strcpy(vmdir,VMDIR);
	   strcat(vmdir,"/");
	   strcpy(tmp,vmdir);
  	   scanf("%s", host);
	   getchar(); /* remove Enter input from scanf */
	   if(!strcmp(host,"a")) {
	       printf("\n[ Playing Back All the Voice Mails ]\n\n");
	       dirp = opendir(VMDIR);
	       while((dp = readdir(dirp))!=NULL) {
	           if(!(!strcmp(dp->d_name,".")||!strcmp(dp->d_name,".."))) {
		       aud = fopen("/dev/audio","wb");
		       strcat(tmp,dp->d_name);
		       printf("Now playing: [%s]\n", dp->d_name);
		       fil = fopen(tmp,"rb");
		       while(!feof(fil)) {
			   fputc(fgetc(fil),aud);
	               }
		       fclose(fil);
	               ring = fopen("/tmp/.ztalk_ring", "rb");
                       while(!feof(ring)) {
                           fputc(fgetc(ring),aud);
                       }
		       fclose(ring);
		       fclose(aud);
		       printf(" <Enter: Continue - 'q': Quit - 'd': Delete>: ");
                       key_check=getchar();
		       if (key_check=='d') { 
			  getchar();
			  printf("\n[ Message %s Deleted ]\n\n", tmp);
                          remove(tmp);
		       }
		       strcpy(tmp,vmdir);
                       if (key_check=='q') break;
		   }
               }	
	       break;
	     }
	   else {
	       if(atoi(host)) {
	           dirp = opendir(VMDIR);
		   for(dirc=-1;dirc<=atoi(host);dirc++) {
	               dp = readdir(dirp);
		     }
	           aud = fopen("/dev/audio","wb");
		   strcat(tmp,dp->d_name);
                   printf("\n[ Playing Voicemail Message (%d) %s ]\n"
                         ,atoi(host), dp->d_name);
		   fil = fopen(tmp,"rb");
		   while(!feof(fil)) {
		       fputc(fgetc(fil),aud);
		     }
		   fclose(fil);
                   ring = fopen("/tmp/.ztalk_ring", "rb");
                   while(!feof(ring)) {
                   fputc(fgetc(ring),aud);
                   }
                   fclose(ring);
		   fclose(aud);
                   printf(" <Enter: Quit - 'd': Delete>: ");
		   key_check=getchar();
                   if (key_check=='d') {
                   getchar();
                   remove(tmp);
                   printf("\n[ Message %s Deleted ]\n", tmp);
                   }
		   break;
		 }
	       printf("ztalk: Undefined play option.\n");
	     }
/*
 	   strcpy(vmplay, "ls -CF /tmp/vmail/*");
	   strcat(vmplay, host);
	   strcat(vmplay, "*");
	   system(vmplay);
	   strcpy(vmplay, "vmplay ");
	   strcat(vmplay, host);
	   system(vmplay);
*/
	   do_rec=0;
           break; 
       case 'q':
           printf("\n[ZTALK Terminated]\n\n");
           exit(0);
       do_rec=0;
       printf("\n[Invalid Command]\n");
	  }


       if (strcmp(host, "error")==0) do_rec=0;
       if (do_rec==1) {
           strcpy(prev, host);
#ifdef WANT_FILE
    	   send_sound(method,send_file);
#else
           send_sound(method);
#endif
	 }
      }
  }


/*
 * send_sound() -- get audio, compress, transmit
 */
#ifdef WANT_FILE
int send_sound(METHOD method,char send_file[50])
#else
int send_sound(METHOD method)
#endif
{
    fd_set readfds;			/* for select on kbd */
    struct timeval timeout;		/* for select on kbd */
    int	key_pressed = 0;	/* for select on kbd */
    char	c=0;			/* kbd read value */
    int 	samps_read=0;		/* samples read from (/dev) AUDIO */
    int	audio=-1;		/* handle to audio device */
#ifdef WANT_FILE
    int     file=-1;                /* handle input file */
#endif
    int	stat_compressor = 0;	/* status from compressor call */
    int	stat_transmit = 0;	/* status from transmit call */
    int 	size_send = 0;		/* send buffer size */
    unsigned char * buf_send = NULL;  /* pointer to transmit buffer */

    timeout.tv_usec = 10;
    timeout.tv_sec = 0;

    if (VERBOSE == 1)
        printf("ztalk: starting record\n");
	
    pos_record = 0;
#ifdef WANT_FILE
    if(send_file[0] == '\0') { /* check for NULL */
#endif
        while(audio<0) {
    	    audio = open(AUDIO,O_RDONLY);
	    if(audio < 0) {
		printf("ztalk:waiting for %s...\n",AUDIO);
		sleep(1);
	      }
	  }
#ifdef WANT_FILE
      }
#endif

    printf("Recording: Hit [RETURN] to stop\n");

#ifdef WANT_FILE
    if(send_file[0] != '\0' ) { /* check for NULL */
        file = open(send_file,O_RDONLY);
	do {
            samps_read = read(file,&buf_record[pos_record],1024);
            if(samps_read < 0) continue;
            pos_record += samps_read;
          } while(samps_read);
        close(file);
      }
    else {        
#endif
        while (!key_pressed) {
  	    /* check the kbd */
	    FD_ZERO(&readfds);
	    FD_SET(0,&readfds);
	    key_pressed = select(1,&readfds,(fd_set*)0,(fd_set *)0, &timeout);

	    /* record audio */
	    samps_read = read(audio,&buf_record[pos_record],1024);
	    if (samps_read < 0 ) continue;
	    pos_record += samps_read;
	
	  } /* while !keypressed */
/* no matter what, close this immediately -- might be incoming messages  :) */
        close(audio);

        if (key_pressed <= 0) return(-1);	/* did user abort? */
#ifdef WANT_FILE
      }
#endif

/* implied: if (key_pressed > 0) */

    if (VERBOSE == 1) printf("ztalk: ending record\n");
#ifdef WANT_FILE
    if(send_file[0]=='\0') { /* check for NULL */
#endif
        read(0,&c,1);		
#ifdef WANT_FILE
      }
#endif

    stat_compressor = compress_buffer(	method,
					buf_record,
					pos_record,
					&buf_send,
					&size_send
					); 

    if (stat_compressor) yikes("compressor",stat_compressor);

    stat_transmit = transmit_buffer(	method,
					buf_send,
					size_send
					);

    if (buf_send != buf_record) free(buf_send);

    if (stat_transmit) yikes ("transmit failure",stat_transmit);

    return(0);
  }

int compress_buffer(	METHOD method,
			unsigned char *buf_record,
			int size_record,
			unsigned char ** buf_send,
			int * size_send
		)
{
    int stat_retval = 0;
    int pos_send=0;		/* position in send buffer */
    int pos_record=0;	/* position in record buffer */
    int i = 0, ticker = 0;	/* spare indices */
    gsm_byte * buf_gsm = NULL;

    switch(method) {
	case ME_FULL: {
	    *buf_send = buf_record;
	    *size_send = size_record;
	    break;
	  }
	case ME_GSM: {
	    gsm_signal g_samples[160];
	    gsm gh = NULL;
		
	    printf("gsm:compressing...");
	    if(!(gh = gsm_create())) return (-2);

	    *size_send = (size_record/5) + (size_record/16);
	    buf_gsm = (gsm_byte *) malloc(*size_send);
	    if(NULL == buf_gsm) return(-2);
	    while(pos_record < size_record) { /* this gets a little hairy... */
		  /* could also use optimization... */
		  /* also, sorry about the nl's -- consider
		     the alternative.  8) */
		for( i = 0; i < 160; i++) 
		    g_samples[i]=(gsm_signal) U2S((buf_record[pos_record+i]));
		    gsm_encode(	gh,g_samples,(buf_gsm + pos_send));
		    pos_send+=33;
		    pos_record+=160;
			
		    ticker++;
		    if (ticker > 31) {	/* for impatient users :) */
			ticker = 0;
			printf(".");
			fflush(stdout);
		      }
	      }
	    gsm_destroy(gh);
            *buf_send = buf_gsm;
	    *size_send = pos_send;
	    printf("\ngsm:done.\n");
	    break;
	  }
        default:	stat_retval=-1;
      }
    return(stat_retval);
  }

int transmit_buffer(METHOD method, unsigned char * bu, int cnt)
{
    int hd = -1;
    char out[512];

#ifdef TERM
    char pp1[256];
    char port[256];
#endif

    void killit() {
        close(hd);
        exit(1);
      }

    signal(SIGINT, killit);	/* if aborted, close the stream   -fein- */

/* first, check the method */
    if (method < 0 || method >= ME_UNSUPPORTED) return(-1);

    if (VERBOSE == 1) printf("ztalk: connecting to %s\n",host);

#ifdef TERM

    sprintf(port,"%d",TCP_PORT_ZTALK);
    sprintf(pp1,"%s",host);
 
    if(strchr(pp1,':')==NULL) {
        strcat(pp1,":");
	strcat(pp1,port);
      }

    printf("ztalk:making TERM connection to %s\n",pp1);

    if((hd = connect_server(0)) < 0) {
        perror("Couldn't open term socket\n");
        close(hd);
    }
    else if(send_command(hd, C_PORT, 0, "%s", pp1) < 0) {
        printf("Could not make TERM connection to %s.\n", host);
	hd = -1;
    } else send_command(hd, C_DUMB, 1, 0);

#else

    /* connect */
    hd = gl_tcp_open(host,NULL,TCP_PORT_ZTALK);

#endif /* TERM */

    if (hd < 0)
        printf("ztalk: Unable to connect to %s\n",host);
    else {	/* Now that ztalk is interactive, I didn't want it to exit
        	   from the main program just because unable to connect to
        	   remote host.		-fein-				*/
        if (VERBOSE == 1) printf("ztalk: sending data\n");

        read_line(hd);	/* get opening banner */

        /* send type of data & size */
        sprintf(out,"%c%d\n",id_compression[method],cnt);
        write(hd,out,strlen(out));
   
        /* get the reply */
        read_line(hd);

        /* transmit sound block */
        slow_write(hd,bu,cnt);
        sprintf(out,"0000\n");
        write(hd,out,strlen(out));
      }

    /* close the connection */
    close(hd);
    return (0); 
  }

int gl_tcp_open(host, service,port)
char *host;
char *service;
int port;
{
    struct in_addr adress;
    int len;
    int fd, resvport;
    unsigned long inaddr;
    struct servent *sp;
    struct hostent *hp;

    bzero(( char *) &tcp_srv_addr, sizeof(tcp_srv_addr));
    tcp_srv_addr.sin_family = AF_INET;

    if (service != NULL) {
	if (( sp = getservbyname(service,"tcp")) == NULL) {
	    return (-1);
	  }
	tcp_serv_info = *sp;
	if (port > 0)
	    tcp_srv_addr.sin_port = htons(port);
	else
	    tcp_srv_addr.sin_port = sp->s_port;
      }
    else {
	if (port <= 0)	{
	    great_errno = 101;
	    return (-2);
	  }
	tcp_srv_addr.sin_port = htons(port);
      }

    if ((inaddr = inet_addr(host)) != INADDR_NONE)	{
	bcopy((char *) &inaddr, (char *) &tcp_srv_addr.sin_addr,
            sizeof(inaddr));
	bcopy((char *) &inaddr, (char *) &adress.s_addr,
	    sizeof(inaddr));
	tcp_host_info.h_name = NULL;
      }
    else {
	if (( hp = gethostbyname(host)) == NULL) {
	    great_errno = 102;
	    return (-3);	
	  }
	tcp_host_info = *hp;
	bcopy(hp->h_addr, (char *) &tcp_srv_addr.sin_addr,
	    hp->h_length);
	bcopy(hp->h_addr, (char *) &adress.s_addr,
	    hp->h_length);
      }


    strcpy(current_ip,inet_ntoa(adress));

    if (port >= 0)	{
	if ((fd = socket(AF_INET, SOCK_STREAM,0)) < 0)	{
	    great_errno = 108;
	    return (-4);
	  }
      }
    else if (port < 0)	{
	resvport = IPPORT_RESERVED -1;
	if (( fd = rresvport(&resvport) < 0))	{
	    great_errno = 108;
	    return (-5);
	  }
      }
    alarm(60);
    if (connect(fd, (struct sockaddr *) &tcp_srv_addr,
	sizeof(tcp_srv_addr)) < 0)	{
	close(fd);
	great_errno = 107;
	alarm(0);
	return (-6);
      }

    len = sizeof (myctladdr);
    if (getsockname(fd, (struct sockaddr *)&myctladdr, &len) < 0) {
	perror("ftp: getsockname");
	alarm(0);
	close(fd);
	return(-7);
		}
    alarm(0);
    return (fd);
  }


int slow_write(int hd,char *s,int sz)
{
    int pos;
    int a;
    int tz;
    
    pos = 0;
    tz = sz;  


    while (1)       {
        a = write(hd,&s[pos],tz);
        if (a < 0)	
            return (-1);
        pos +=a;
        tz -= a;
        if (pos >= sz)
             return (pos);
      }
  }

void read_line(int hd)
{
    char c;
    char bu[100];
    int a;

    a = 0;

    while (1)	{ 
	if (read(hd,&c,1)!= 1)
	    break; 
	if (c == 10)
	    break;
	bu[a++] = c;
      }
    bu[a] = 0;
    printf("<%s>\n",bu);
}

void yikes (char * msg, int stat) {
    fprintf(stderr,"ztalk error:%s returned %d\n",msg,stat);
    exit(1);
  }
