xfreecd

Audio CD player for X
git clone https://www.brianlane.com/git/xfreecd
Log | Files | Refs | README | LICENSE

cddbd.c (30124B)


      1 /* ---------------------------------------------------------------------
      2    cddbd interface for XfreeCD
      3 
      4    Copyright 1998 by Brian C. Lane
      5    nexus@tatoosh.com
      6    http://www.tatoosh.com/nexus
      7 
      8    This program is free software; you can redistribute it and/or
      9    modify it under the terms of the GNU General Public License
     10    as published by the Free Software Foundation; either version 2
     11    of the License, or (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     21 
     22    =============================[ HISTORY ]=============================
     23    07/05/98	Removed the strcat of tmpstr from the track offset loop
     24    		when requesting CD info. This was causing the odd
     25    		behavior, depending on the state of memory.
     26 
     27    06/19/98     Changed offset in the track loop to be 0 reference
     28                 instead of 1.
     29 
     30    06/16/98     NIN Broken is living up to its name. It is causing the
     31                 server to return an error 500. Hmm, I somehow left out
     32 		the length of the cd. This is fixed. It now downloads
     33 		NIN correctly (woo hoo, ack, pthhhtttt). Anyone want
     34 		a copy of NIN Broken? I'll mail it to you in little
     35 		pieces...
     36 
     37    06/02/98     Sending the full line returned by the server to the
     38                 caling process in cdinfo.line
     39 
     40    05/24/98     Adding support for inexact matches.
     41                 Adding a return type of CDDBD_INEX_LINE
     42 
     43    05/11/98     Adding more information from main process. Passes a
     44                 cdinfo structure.
     45 
     46    05/10/98     Added basic socket open/close/read/write functions.
     47 
     48    05/09/98     Started this part of the XfreeCD code. 
     49 
     50 
     51    ---------------------------------------------------------------------
     52    This implements the internet connection to a cddbd server. Local data
     53    is accessed using the functions in ... 
     54 
     55    Hmm, how to implemetn all this?
     56    State machine for error responses and link to next command?
     57 
     58    I also need to get more info on the CD than just the CD's discid
     59 
     60    --------------------------------------------------------------------- */
     61 #include <stdio.h>
     62 #include <stdlib.h>
     63 #include <fcntl.h>
     64 #include <sys/ioctl.h>
     65 #include <sys/types.h>
     66 #include <sys/socket.h>
     67 #include <unistd.h>
     68 #include <netinet/in.h>
     69 #include <arpa/inet.h>
     70 #include <netdb.h>
     71 #include <string.h>
     72 #include <gtk/gtk.h>
     73 #include "xfreecd.h"
     74 #include "child_sync.h"
     75 #include "cd_control.h"
     76 #include "cddbd.h"
     77 #include "cddb.h"
     78 
     79 
     80 #undef DEBUG1
     81 #undef DEBUG3
     82 
     83 int cddbd( int );
     84 
     85 /*
     86    Fire up the cddb process.
     87    Create a socket pair.
     88    Fork a child process
     89    Return the parent's file descriptor for the socket or -1 + errno
     90    fill in childpid with the child's PID
     91    Child calls cddbd 
     92 */
     93 int start_cddbd( int *childpid )
     94 {
     95   int  fd[2];
     96 
     97   if( socketpair( AF_UNIX, SOCK_STREAM, 0, fd ) < 0 )
     98     return(-1);
     99 
    100   if( ( *childpid = fork() ) < 0 )
    101   {
    102     perror("start_cddbd, cannot fork");
    103     return(-1);
    104   } else if( *childpid == 0 ) {
    105     close( fd[0] );
    106 
    107     /* Synchronize with the parent, exit if it fails */
    108     if( parent_sync( fd[1] ) == 0 )
    109       cddbd( fd[1] );
    110     
    111     close( fd[1] );
    112     exit(0);
    113   } 
    114   close( fd[1] );
    115 
    116   if( child_sync( fd[0] ) == 0 )
    117     return(fd[0]);  
    118 
    119   return(-1);
    120 }
    121 
    122 /* -----------------------------------------------------------------------
    123    Read a line from the socket
    124    ----------------------------------------------------------------------- */
    125 int readn( register int fd, register char *ptr, register int nbytes )
    126 {
    127   int   nleft,
    128         nread;
    129 
    130   nleft = nbytes;
    131   while( nleft > 0 )
    132     {
    133       nread = read( fd, ptr, nleft );
    134       if( nread < 0 )
    135 	return( nread );
    136       else if( nread == 0 )
    137 	break;
    138 
    139       nleft -= nread;
    140       ptr += nread;
    141     }
    142   return (nbytes - nleft);
    143 }
    144 
    145 
    146 /* -----------------------------------------------------------------------
    147    Write n bytes of data to the socket
    148 
    149    Loop until all the data is written. 
    150    ----------------------------------------------------------------------- */
    151 int writen( register int fd, register char *ptr, register int nbytes )
    152 {
    153   int   nleft,
    154         nwritten;
    155 
    156   nleft = nbytes;
    157   while( nleft > 0 )
    158     {
    159       nwritten = write( fd, ptr, nleft );
    160       if( nwritten <= 0 )
    161 	return( nwritten );
    162 
    163       nleft -= nwritten;
    164       ptr += nwritten;
    165     }
    166 
    167   return (nbytes - nleft );
    168 }
    169 
    170 
    171 /* -----------------------------------------------------------------------
    172    A VERY inefficent read routine. I need to rewrite this to read as much
    173    as possible and scan the buffer read...
    174    
    175    But then how do you put back characters after the CR that you want to
    176    read the next time it is called? Static holding previous spares maybe?
    177    ----------------------------------------------------------------------- */
    178 int readline( register int fd, register char *ptr, register int maxlen )
    179 {
    180   int  n,
    181        rc;
    182   char c;
    183 
    184   for( n = 1; n < maxlen; n++ )
    185     {
    186       if( ( rc = read( fd, &c, 1 ) ) == 1 )
    187 	{
    188 	  *ptr++ = c;
    189 	  if( c == '\n' )
    190 	    break;
    191 	} else if( rc == 0 ) {
    192 	  if( n == 1 )
    193 	    return(0);
    194 	  else
    195 	    break;
    196 	} else {
    197 	  return(-1);
    198 	}
    199     }
    200 
    201   *ptr = 0;
    202   return(n);
    203 }
    204 
    205 
    206 /* -----------------------------------------------------------------------
    207    Open a cddbd connection, return the fd
    208 
    209    This handles the connection and initial login to the server,
    210    returns error codes on failure.
    211 
    212    Pass the server name and port
    213    ----------------------------------------------------------------------- */
    214 int open_cddbd( char *server, int port )
    215 {
    216   struct sockaddr_in   tcp_srv_addr;    /* Server's Internet socket addr. */
    217   struct hostent       tcp_host_info;   /* from gethostbyname */
    218   struct hostent       *hp;
    219   unsigned long        inaddr;
    220   int                  fd;
    221 
    222 
    223   bzero( &tcp_srv_addr, sizeof( tcp_srv_addr ) );
    224   tcp_srv_addr.sin_family = AF_INET;
    225 
    226 
    227   /* Setup the port, exit if illegal passed */
    228   if( port < 1 )
    229     return(-2);
    230 
    231   tcp_srv_addr.sin_port = htons( port );
    232 
    233   /* Try the hostname as a dotted decimal first */
    234   if( ( inaddr = inet_addr( server ) ) != INADDR_NONE )
    235     {
    236       bcopy((char *)&inaddr,(char *)&tcp_srv_addr.sin_addr,sizeof(inaddr));
    237       tcp_host_info.h_name = NULL;
    238     } else {
    239       /* Not dotted decimal, try it as a name */
    240       if( ( hp = gethostbyname( server ) ) == NULL )
    241 	{
    242 	  return(-3);
    243 	}
    244       tcp_host_info = *hp;    /* Copy the structure */
    245       bcopy( hp->h_addr, (char *) &tcp_srv_addr.sin_addr, hp->h_length );
    246     }
    247 
    248   /* Create the socket */
    249   if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
    250     {
    251       return(-4);
    252     }
    253 
    254   /* Connect to the server */
    255   if( connect(fd,(struct sockaddr *)&tcp_srv_addr,sizeof(tcp_srv_addr)) < 0 )
    256     {
    257       close( fd );
    258       return(-5);
    259     }
    260 
    261   return(fd);
    262 }
    263 
    264 /* -----------------------------------------------------------------------
    265    Close down the connection to the server.
    266 
    267    Send quit and close socket
    268    ----------------------------------------------------------------------- */
    269 int close_cddbd( fd )
    270 {
    271   char  line[255];
    272 
    273   writen( fd, "quit\n", strlen( "quit\n" ) );
    274 
    275   /* Read the closing banner from the server */
    276   if( readline( fd, line, 255 ) < 0 )
    277     {
    278       close( fd );
    279       return(-2);
    280     }
    281 
    282 #ifdef DEBUG1
    283   g_print("%s", line );
    284 #endif
    285 
    286   close( fd );
    287   return(0);
    288 }
    289 
    290 
    291 /* -----------------------------------------------------------------------
    292    Return the response code
    293    ----------------------------------------------------------------------- */
    294 int cddbd_code( char *line )
    295 {
    296   char *p;
    297 
    298   p = strtok( line, " \n" );
    299   return( atoi( p ) );
    300 }
    301 
    302 
    303 
    304 /* -----------------------------------------------------------------------
    305    Watch for commands from the main process and execute connections to
    306    the indicated cddbd internet database server.
    307 
    308    Commands ... DB_*
    309    Uses the cddbd_cmnd structure to pass the command, server and port.
    310 
    311    Also need to read the sites listing, and motd.
    312 
    313    Retrieve data for ID from server SERVER using PORT
    314 
    315    returns a CDINFO structure with a status byte? How to keep it updated
    316    without returning a full CDINFO every time?   
    317 
    318    As we progress thru the protocol, send back status updates to the parent
    319    process.
    320 
    321    ----------------------------------------------------------------------- */
    322 int cddbd( int control_fd )
    323 {
    324   struct CDINFO  cdinfo;
    325   FILE           *fp;
    326   int            cddbd_fd;
    327   char           line[255],
    328                  *tmpfile,
    329                  *p;
    330   int            x,
    331                  code;
    332 
    333 
    334   for(;;)
    335   {
    336     /* Get the command from the parent process */
    337     if( read( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    338       {
    339 	perror("cddbd read error");
    340 	return(-1);
    341       }
    342 
    343     switch( cdinfo.cddbd_cmnd )
    344       {
    345       case DB_DIAG :
    346 	puts("cddbd diagnostic\n");
    347 	break;
    348 
    349 	/* Get the info on a CD from the server */
    350       case DB_READ :
    351 
    352 #ifdef DEBUG1
    353 	g_print("Searching for 0x%08x at %s : %d\n", cdinfo.discid, cdinfo.server, cdinfo.port );
    354 #endif
    355 
    356 	if( (cddbd_fd = open_cddbd( cdinfo.server, cdinfo.port )) < 0 )
    357 	  {
    358 	    close_cddbd( cddbd_fd );
    359 
    360 	    /* Tell the parent the connection failed */
    361 	    cdinfo.cddbd_stat = CDDBD_OPEN_ERR;
    362 	    sprintf( cdinfo.line, "err=%d", cddbd_fd );
    363 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    364 	      {
    365 		perror("cddbd write error-1");
    366 		break;
    367 	      }
    368 	    break;
    369 	  }
    370 
    371 	/* Tell the parent we are connected ok */
    372 	cdinfo.cddbd_stat = CDDBD_OPEN_OK;
    373 	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    374 	      {
    375 		perror("cddbd write error-2");
    376 		break;
    377 	      }
    378 	  	
    379 	/* Read the opening banner from the server */
    380 	if( readline( cddbd_fd, line, 255 ) < 0 )
    381 	  {
    382 	    close( cddbd_fd );
    383 	    /* Tell the parent the read failed */
    384 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    385 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    386 	      {
    387 		perror("cddbd write error-3");
    388 		break;
    389 	      }
    390 	    break;
    391 	  }  
    392 
    393 #ifdef DEBUG1
    394 	g_print( "%s", line );
    395 #endif
    396 
    397 	strncpy( cdinfo.line, line, 254 );
    398 	code = cddbd_code( line );
    399 	if( code > 201 )
    400 	  {
    401 	    close_cddbd( cddbd_fd );
    402 	    /* Tell the parent the connect failed */
    403 	    cdinfo.cddbd_stat = code;
    404 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    405 	      {
    406 		perror("cddbd write error-4");
    407 		break;
    408 	      }
    409 	    break;
    410 	  }
    411 
    412 	/* Identify ourself to the server */
    413 	sprintf( line, "cddb hello %s %s XfreeCD %s\n", getenv("USER"),
    414 		                                        getenv("HOSTNAME"),
    415 		                                        VERSION );
    416 
    417 #ifdef DEBUG1
    418 	g_print("%s", line );
    419 #endif
    420 
    421 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
    422 	  {
    423 	    close( cddbd_fd );
    424 
    425 	    /* Tell the parent the write failed */
    426 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
    427 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    428 	      {
    429 		perror("cddbd write error-5");
    430 		break;
    431 	      }
    432 	    break;
    433 	  }
    434 
    435 	/* Get the response from the server */
    436 	if( readline( cddbd_fd, line, 255 ) < 0 )
    437 	  {
    438 	    close( cddbd_fd );
    439 
    440 	    /* Tell the parent the read failed */
    441 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    442 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    443 	      {
    444 		perror("cddbd write error-6");
    445 		break;
    446 	      }
    447 	    break;
    448 	  }  
    449 
    450 #ifdef DEBUG1
    451 	g_print( "%s", line );
    452 #endif
    453 
    454 	strncpy( cdinfo.line, line, 254 );
    455 	code = cddbd_code( line );
    456 	if( code > 200 )
    457 	  {
    458 	    close_cddbd( cddbd_fd );
    459 
    460 	    /* Tell the parent the read failed */
    461 	    cdinfo.cddbd_stat = code;
    462 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    463 	      {
    464 		perror("cddbd write error-7");
    465 		break;
    466 	      }
    467 	    break;
    468 	  }
    469 
    470 	/* Send a Query to the server */
    471 	/* This can be quite! long (try NIN broken, 99 tracks) so break it up
    472 	   into smaller chuncks
    473 	*/
    474 	sprintf( line, "cddb query %08lx %d ", cdinfo.discid, cdinfo.tochdr.cdth_trk1 );
    475 
    476 #ifdef DEBUG1
    477 	g_print("%s", line );
    478 #endif
    479 
    480 	/* Write the first part of the query to the server */
    481 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
    482 	  {
    483 	    close( cddbd_fd );
    484 
    485 	    /* Tell the parent the write failed */
    486 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
    487 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    488 	      {
    489 		perror("cddbd write error-8");
    490 		break;
    491 	      }
    492 	    break;
    493 	  }
    494 
    495 	/* List of offsets, send it one offset at a time */
    496 	for( x = 0; x < cdinfo.tochdr.cdth_trk1; x++ )
    497 	  {
    498 	    sprintf( line, "%ld ", cdinfo.track[x].frame_offset );
    499 
    500 #ifdef DEBUG1
    501 	    g_print("[%d]%s", x, line );
    502 #endif
    503 
    504 	    /* Write this next chunck of the request */
    505 	    if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
    506 	      {
    507 		close( cddbd_fd );
    508 
    509 		/* Tell the parent the write failed */
    510 		cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
    511 		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    512 		  {
    513 		    perror("cddbd write error-8");
    514 		    break;
    515 		  }
    516 		break;
    517 	      }
    518 	  }
    519 
    520 	/* End of the query with length in seconds */
    521 	sprintf(line, "%d\n", cdinfo.cd_length );
    522 
    523 #ifdef DEBUG1
    524 	g_print("%s", line );
    525 #endif
    526 
    527 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
    528 	  {
    529 	    close( cddbd_fd );
    530 
    531 	    /* Tell the parent the write failed */
    532 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
    533 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    534 	      {
    535 		perror("cddbd write error-8");
    536 		break;
    537 	      }
    538 	    break;
    539 	  }
    540 
    541         /* Get the response from the server, get the coded response,
    542 	   and the rest up to the '.'
    543 	*/
    544 	/* Get the response from the server */
    545 	if( readline( cddbd_fd, line, 255 ) < 0 )
    546 	  {
    547 	    close( cddbd_fd );
    548 
    549 	    /* Tell the parent the read failed */
    550 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    551 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    552 	      {
    553 		perror("cddbd write error-9");
    554 		break;
    555 	      }
    556 	    break;
    557 	  }  
    558 
    559 #ifdef DEBUG1
    560 	g_print( "%s", line );
    561 #endif
    562 
    563 	strncpy( cdinfo.line, line, 254 );
    564 	code = cddbd_code( line );
    565 	if( (code > 211) || (code==202) )
    566 	  {
    567 	    close_cddbd( cddbd_fd );
    568 
    569 	    /* Tell the parent the read failed */
    570 	    cdinfo.cddbd_stat = code;
    571 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    572 	      {
    573 		perror("cddbd write error-10");
    574 		break;
    575 	      }
    576 	    break;
    577 	  }
    578 
    579 	/* Inexact match, get the list */
    580 	if( code == 211 )
    581 	  {
    582 	    /* Return the inexact match lines to the sparent process */
    583 	    while( line[0] != '.' )
    584 	      {
    585 		if( readline( cddbd_fd, line, 255 ) < 0 )
    586 		  {
    587 		    close( cddbd_fd );
    588 
    589 		    /* Tell the parent the read failed */
    590 		    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    591 		    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    592 		      {
    593 			perror("cddbd write error-11");
    594 			break;
    595 		      }
    596 		    break;
    597 		  }  
    598 
    599 #ifdef DEBUG1
    600 		g_print( "%s", line );
    601 #endif
    602 		/* Send the line to the parent */
    603 		cdinfo.cddbd_stat = CDDBD_INEX_LINE;
    604 		strncpy( cdinfo.line, line, 254 );
    605 		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    606 		  {
    607 		    perror("cddbd write error-11a");
    608 		    break;
    609 		  } 
    610 	      }
    611 
    612 	    /* We are finished with the server */
    613 	    close_cddbd( cddbd_fd );
    614 	    break;
    615 	  }
    616 
    617 	/* Exact match, get the category ?? and discid ?? */
    618 	if( code == 200 )
    619 	  {
    620 	    /* Tell the parent that we got a match */
    621 	    cdinfo.cddbd_stat = CDDBD_MATCH_OK;
    622 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    623 	      {
    624 		perror("cddbd write error-11a");
    625 		break;
    626 	      }
    627 	    
    628 	    /* Get the category (code has already placed a null in line) */
    629 	    p = strtok( NULL, " \n" );
    630 	    if( cdinfo.category == NULL )
    631 	      cdinfo.category = g_string_new( p );
    632 	    else
    633 	      cdinfo.category = g_string_assign( cdinfo.category, p );
    634 
    635 #ifdef DEBUG3
    636 	    g_print("category = %s\n", cdinfo.category->str );
    637 #endif
    638 	    /* We could also get the discid and title here... */
    639 	  }
    640 
    641 
    642 	/* Send a read command to the server */
    643 	sprintf( line, "cddb read %s %08lx\n", cdinfo.category->str, cdinfo.discid );
    644 
    645 #ifdef DEBUG1
    646 		g_print( "%s", line );
    647 #endif
    648 
    649 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
    650 	  {
    651 	    close( cddbd_fd );
    652 
    653 	    /* Tell the parent the read failed */
    654 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
    655 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    656 	      {
    657 		perror("cddbd write error-12");
    658 		break;
    659 	      }
    660 	    break;
    661 	  }
    662 
    663 	/* Get the response from the server */
    664 	if( readline( cddbd_fd, line, 255 ) < 0 )
    665 	  {
    666 	    close( cddbd_fd );
    667 
    668 	    /* Tell the parent the read failed */
    669 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    670 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    671 	      {
    672 		perror("cddbd write error-13");
    673 		break;
    674 	      }
    675 	    break;
    676 	  }  
    677 
    678 #ifdef DEBUG1
    679 	g_print( "%s", line );
    680 #endif
    681 
    682 	strncpy( cdinfo.line, line, 254 );
    683 	code = cddbd_code( line );
    684 	if( code > 210 )
    685 	  {
    686 	    close_cddbd( cddbd_fd );
    687 	    
    688 	    /* Tell the parent the read failed */
    689 	    cdinfo.cddbd_stat = code;
    690 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    691 	      {
    692 		perror("cddbd write error-14");
    693 		break;
    694 	      }
    695 	    break;
    696 	  }
    697 
    698 	/* 
    699 	   Get the database file from the server.
    700 	   Write the file into a temporary file to be read by cddb_read
    701 	*/
    702 	if( ( tmpfile = tmpnam( NULL ) ) == NULL )
    703 	  {
    704 	    close_cddbd( cddbd_fd );
    705 
    706 	    /* Tell the parent the read failed */
    707 	    cdinfo.cddbd_stat = CDDBD_TMPF_ERR;
    708 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    709 	      {
    710 		perror("cddbd write error-15");
    711 		break;
    712 	      }
    713 	    break;	    
    714 	  }
    715 
    716 	if( ( fp = fopen( tmpfile, "wb" ) ) == NULL )
    717 	  {
    718 	    close_cddbd( cddbd_fd );
    719 
    720 	    /* Tell the parent the read failed */
    721 	    cdinfo.cddbd_stat = CDDBD_FOPEN_ERR;
    722 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    723 	      {
    724 		perror("cddbd write error-16");
    725 		break;
    726 	      }
    727 	    break;
    728 	  }
    729 
    730 	/* Tell the parent we are reading the database entry */
    731 	cdinfo.cddbd_stat = CDDBD_ENTRY_OK;
    732 	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    733 	  {
    734 	    perror("cddbd write error-14a");
    735 	    break;
    736 	  }
    737 
    738 	while( line[0] != '.' )
    739 	  {
    740 	    /* Get the response from the server */
    741 	    if( readline( cddbd_fd, line, 255 ) < 0 )
    742 	      {
    743 		close( cddbd_fd );
    744 
    745 		/* Tell the parent the read failed */
    746 		cdinfo.cddbd_stat = CDDBD_READ_ERR;
    747 		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    748 		  {
    749 		    perror("cddbd write error-17");
    750 		    break;
    751 		  }
    752 		break;
    753 	      }  
    754       
    755 #ifdef DEBUG1
    756 	    g_print( "%s", line );
    757 #endif
    758 	    /* Strip trailing CR -- kludge, may not be there... */
    759 	    line[strlen(line)-2] = 0;
    760 	    fprintf(fp, "%s\n", line);
    761 	  }
    762 
    763 	fclose( fp );
    764 
    765 	/* We are finished with the server */
    766 	close_cddbd( cddbd_fd );
    767 
    768 
    769 	/* Read the file into the cdinfo structure, and write it to its
    770 	   final location in the local database.
    771 	*/
    772 	if( read_cddb_file( tmpfile, &cdinfo ) == 0 )
    773 	  {
    774 	    /* Make sure it is saved with our discid! */
    775 	    cdinfo.discid = cddb_discid( &cdinfo );
    776 
    777 	    if( write_cddb( &cdinfo, 1 ) == 0 )
    778 	      cdinfo.cddbd_stat = CDDBD_DONE_OK;
    779 	    else
    780 	    cdinfo.cddbd_stat = CDDBD_DONE_ERR;
    781 	  } else {
    782 	    cdinfo.cddbd_stat = CDDBD_DONE_ERR;
    783 	  }
    784 
    785 #ifdef DEBUG3
    786 	    g_print("category = %s\n", cdinfo.category->str );
    787 #endif
    788 
    789 	/* Send the new structure back to the parent process */
    790 	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    791 	  {
    792 	    perror("cddbd write error-18");
    793 	    break;
    794 	  }
    795 
    796 	/* Delete the temporary file */
    797 #ifdef DEBUG1
    798 	g_print( "tmpfile=%s\n", tmpfile );
    799 #else
    800 	unlink( tmpfile );
    801 #endif
    802 	
    803 	break;
    804 
    805       /* Get the MOTD from the current server */
    806       case DB_MOTD :
    807 	if( (cddbd_fd = open_cddbd( cdinfo.server, cdinfo.port )) < 0 )
    808 	  {
    809 	    close_cddbd( cddbd_fd );
    810 
    811 	    /* Tell the parent the connection failed */
    812 	    cdinfo.cddbd_stat = CDDBD_OPEN_ERR;
    813 	    sprintf( cdinfo.line, "err=%d", cddbd_fd );
    814 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    815 	      {
    816 		perror("cddbd write error-1");
    817 		break;
    818 	      }
    819 	    break;
    820 	  }
    821 
    822 	/* Read the opening banner from the server */
    823 	if( readline( cddbd_fd, line, 255 ) < 0 )
    824 	  {
    825 	    close( cddbd_fd );
    826 	    /* Tell the parent the read failed */
    827 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    828 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    829 	      {
    830 		perror("cddbd write error-3");
    831 		break;
    832 	      }
    833 	    break;
    834 	  }  
    835 
    836 #ifdef DEBUG1
    837 	g_print( "%s", line );
    838 #endif
    839 
    840 	strncpy( cdinfo.line, line, 254 );
    841 	code = cddbd_code( line );
    842 	if( code > 201 )
    843 	  {
    844 	    close_cddbd( cddbd_fd );
    845 	    /* Tell the parent the connect failed */
    846 	    cdinfo.cddbd_stat = code;
    847 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    848 	      {
    849 		perror("cddbd write error-4");
    850 		break;
    851 	      }
    852 	    break;
    853 	  }
    854 
    855 	/* Identify ourself to the server */
    856 	sprintf( line, "cddb hello %s %s XfreeCD %s\n", getenv("USER"),
    857 		                                        getenv("HOSTNAME"),
    858 		                                        VERSION );
    859 
    860 #ifdef DEBUG1
    861 	g_print("%s", line );
    862 #endif
    863 
    864 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
    865 	  {
    866 	    close( cddbd_fd );
    867 
    868 	    /* Tell the parent the write failed */
    869 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
    870 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    871 	      {
    872 		perror("cddbd write error-5");
    873 		break;
    874 	      }
    875 	    break;
    876 	  }
    877 
    878 	/* Get the response from the server */
    879 	if( readline( cddbd_fd, line, 255 ) < 0 )
    880 	  {
    881 	    close( cddbd_fd );
    882 
    883 	    /* Tell the parent the read failed */
    884 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    885 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    886 	      {
    887 		perror("cddbd write error-6");
    888 		break;
    889 	      }
    890 	    break;
    891 	  }  
    892 
    893 #ifdef DEBUG1
    894 	g_print( "%s", line );
    895 #endif
    896 
    897 	strncpy( cdinfo.line, line, 254 );
    898 	code = cddbd_code( line );
    899 	if( code > 200 )
    900 	  {
    901 	    close_cddbd( cddbd_fd );
    902 
    903 	    /* Tell the parent the read failed */
    904 	    cdinfo.cddbd_stat = code;
    905 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    906 	      {
    907 		perror("cddbd write error-7");
    908 		break;
    909 	      }
    910 	    break;
    911 	  }
    912 
    913 	/* Tell the server we want the MOTD */
    914 	strcpy( line, "motd\n" );
    915 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
    916 	  {
    917 	    close( cddbd_fd );
    918 
    919 	    /* Tell the parent the write failed */
    920 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
    921 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    922 	      {
    923 		perror("cddbd write error-7");
    924 		break;
    925 	      }
    926 	    break;
    927 	  }
    928 
    929 	/* Get the response from the server */
    930 	if( readline( cddbd_fd, line, 255 ) < 0 )
    931 	  {
    932 	    close( cddbd_fd );
    933 
    934 	    /* Tell the parent the read failed */
    935 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
    936 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    937 	      {
    938 		perror("cddbd write error-8");
    939 		break;
    940 	      }
    941 	    break;
    942 	  }
    943 
    944 #ifdef DEBUG1
    945 	g_print( "%s", line );
    946 #endif
    947 
    948 	strncpy( cdinfo.line, line, 254 );
    949 	code = cddbd_code( line );
    950 	if( code > 210 )
    951 	  {
    952 	    close_cddbd( cddbd_fd );
    953 
    954 	    /* Tell the parent the read failed */
    955 	    cdinfo.cddbd_stat = code;
    956 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    957 	      {
    958 		perror("cddbd write error-7");
    959 		break;
    960 	      }
    961 	    break;
    962 	  }
    963 
    964 	/* Tell the parent about the MOTD date and time */
    965 	cdinfo.cddbd_stat = CDDBD_MOTD_LINE;
    966 	strncpy( cdinfo.line, line, 254 );
    967 	if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    968 	  {
    969 	    perror("cddbd write error-8");
    970 	    break;
    971 	  }
    972 
    973 	/* Read the MOTD one line at a time */
    974 	while( line[0] != '.' )
    975 	  {
    976 	    /* Get the response from the server */
    977 	    if( readline( cddbd_fd, line, 255 ) < 0 )
    978 	      {
    979 		close( cddbd_fd );
    980 
    981 		/* Tell the parent the read failed */
    982 		cdinfo.cddbd_stat = CDDBD_READ_ERR;
    983 		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    984 		  {
    985 		    perror("cddbd write error-8");
    986 		    break;
    987 		  }
    988 		break;
    989 	      }
    990 
    991 #ifdef DEBUG10
    992 	    g_print( "%s", line );
    993 #endif
    994 
    995 	    /* Send the line to the parent */
    996 	    cdinfo.cddbd_stat = CDDBD_MOTD_LINE;
    997 	    strncpy( cdinfo.line, line, 254 );
    998 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
    999 	      {
   1000 		perror("cddbd write error-8");
   1001 		break;
   1002 	      } 
   1003 	  }
   1004 
   1005 	close_cddbd( cddbd_fd );
   1006 
   1007 	break;
   1008 
   1009 	/* 
   1010 	   Read the list of sites from the server.
   1011 	   Only return sites that we can talk to (cddb, not html)
   1012 	*/
   1013       case DB_SITES :
   1014 	if( (cddbd_fd = open_cddbd( cdinfo.server, cdinfo.port )) < 0 )
   1015 	  {
   1016 	    close_cddbd( cddbd_fd );
   1017 
   1018 	    /* Tell the parent the connection failed */
   1019 	    cdinfo.cddbd_stat = CDDBD_OPEN_ERR;
   1020 	    sprintf( cdinfo.line, "err=%d", cddbd_fd );
   1021 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1022 	      {
   1023 		perror("cddbd write error-1");
   1024 		break;
   1025 	      }
   1026 	    break;
   1027 	  }
   1028 
   1029 	/* Read the opening banner from the server */
   1030 	if( readline( cddbd_fd, line, 255 ) < 0 )
   1031 	  {
   1032 	    close( cddbd_fd );
   1033 	    /* Tell the parent the read failed */
   1034 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
   1035 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1036 	      {
   1037 		perror("cddbd write error-3");
   1038 		break;
   1039 	      }
   1040 	    break;
   1041 	  }  
   1042 
   1043 #ifdef DEBUG1
   1044 	g_print( "%s", line );
   1045 #endif
   1046 
   1047 	strncpy( cdinfo.line, line, 254 );
   1048 	code = cddbd_code( line );
   1049 	if( code > 201 )
   1050 	  {
   1051 	    close_cddbd( cddbd_fd );
   1052 	    /* Tell the parent the connect failed */
   1053 	    cdinfo.cddbd_stat = code;
   1054 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1055 	      {
   1056 		perror("cddbd write error-4");
   1057 		break;
   1058 	      }
   1059 	    break;
   1060 	  }
   1061 
   1062 	/* Identify ourself to the server */
   1063 	sprintf( line, "cddb hello %s %s XfreeCD %s\n", getenv("USER"),
   1064 		                                        getenv("HOSTNAME"),
   1065 		                                        VERSION );
   1066 
   1067 #ifdef DEBUG1
   1068 	g_print("%s", line );
   1069 #endif
   1070 
   1071 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
   1072 	  {
   1073 	    close( cddbd_fd );
   1074 
   1075 	    /* Tell the parent the write failed */
   1076 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
   1077 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1078 	      {
   1079 		perror("cddbd write error-5");
   1080 		break;
   1081 	      }
   1082 	    break;
   1083 	  }
   1084 
   1085 	/* Get the response from the server */
   1086 	if( readline( cddbd_fd, line, 255 ) < 0 )
   1087 	  {
   1088 	    close( cddbd_fd );
   1089 
   1090 	    /* Tell the parent the read failed */
   1091 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
   1092 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1093 	      {
   1094 		perror("cddbd write error-6");
   1095 		break;
   1096 	      }
   1097 	    break;
   1098 	  }  
   1099 
   1100 #ifdef DEBUG1
   1101 	g_print( "%s", line );
   1102 #endif
   1103 
   1104 	strncpy( cdinfo.line, line, 254 );
   1105 	code = cddbd_code( line );
   1106 	if( code > 200 )
   1107 	  {
   1108 	    close_cddbd( cddbd_fd );
   1109 
   1110 	    /* Tell the parent the read failed */
   1111 	    cdinfo.cddbd_stat = code;
   1112 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1113 	      {
   1114 		perror("cddbd write error-7");
   1115 		break;
   1116 	      }
   1117 	    break;
   1118 	  }
   1119 
   1120 	/* Tell the server we want the MOTD */
   1121 	strcpy( line, "sites\n" );
   1122 	if( writen( cddbd_fd, line, strlen( line ) ) < 0 )
   1123 	  {
   1124 	    close( cddbd_fd );
   1125 
   1126 	    /* Tell the parent the write failed */
   1127 	    cdinfo.cddbd_stat = CDDBD_WRITE_ERR;
   1128 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1129 	      {
   1130 		perror("cddbd write error-7");
   1131 		break;
   1132 	      }
   1133 	    break;
   1134 	  }
   1135 
   1136 	/* Get the response from the server */
   1137 	if( readline( cddbd_fd, line, 255 ) < 0 )
   1138 	  {
   1139 	    close( cddbd_fd );
   1140 
   1141 	    /* Tell the parent the read failed */
   1142 	    cdinfo.cddbd_stat = CDDBD_READ_ERR;
   1143 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1144 	      {
   1145 		perror("cddbd write error-8");
   1146 		break;
   1147 	      }
   1148 	    break;
   1149 	  }
   1150 
   1151 #ifdef DEBUG1
   1152 	g_print( "%s", line );
   1153 #endif
   1154 
   1155 	strncpy( cdinfo.line, line, 254 );
   1156 	code = cddbd_code( line );
   1157 	if( code > 210 )
   1158 	  {
   1159 	    close_cddbd( cddbd_fd );
   1160 
   1161 	    /* Tell the parent the read failed */
   1162 	    cdinfo.cddbd_stat = code;
   1163 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1164 	      {
   1165 		perror("cddbd write error-7");
   1166 		break;
   1167 	      }
   1168 	    break;
   1169 	  }
   1170 
   1171 	/* Read the MOTD one line at a time */
   1172 	while( line[0] != '.' )
   1173 	  {
   1174 	    /* Get the response from the server */
   1175 	    if( readline( cddbd_fd, line, 255 ) < 0 )
   1176 	      {
   1177 		close( cddbd_fd );
   1178 
   1179 		/* Tell the parent the read failed */
   1180 		cdinfo.cddbd_stat = CDDBD_READ_ERR;
   1181 		if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1182 		  {
   1183 		    perror("cddbd write error-8");
   1184 		    break;
   1185 		  }
   1186 		break;
   1187 	      }
   1188 
   1189 #ifdef DEBUG10
   1190 	    g_print( "%s", line );
   1191 #endif
   1192 
   1193 	    /*
   1194 	       Here we should check the protocol level and parse the
   1195 	       response and only return sites that we can talk to.
   1196 	    
   1197 	       For the moment, just return the lines to the parent
   1198 	    */
   1199 
   1200 	    /* Send the line to the parent */
   1201 	    cdinfo.cddbd_stat = CDDBD_SITE_LINE;
   1202 	    strncpy( cdinfo.line, line, 254 );
   1203 	    if( write( control_fd, &cdinfo, sizeof( struct CDINFO ) ) != sizeof( struct CDINFO ) )
   1204 	      {
   1205 		perror("cddbd write error-8");
   1206 		break;
   1207 	      } 
   1208 	  }
   1209 
   1210 	close_cddbd( cddbd_fd );
   1211 	break;
   1212 
   1213 
   1214       case DB_QUIT :
   1215 	return(0);
   1216 	break;
   1217       }
   1218   }
   1219   return(0);
   1220 }