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 }