[Debburn-changes] r436 - cdrkit/trunk/icedax

Eduard Bloch blade at alioth.debian.org
Thu Nov 23 20:26:48 CET 2006


Author: blade
Date: 2006-11-23 20:26:47 +0100 (Thu, 23 Nov 2006)
New Revision: 436

Added:
   cdrkit/trunk/icedax/icedax.c
   cdrkit/trunk/icedax/icedax.h
Removed:
   cdrkit/trunk/icedax/cdda2wav.c
   cdrkit/trunk/icedax/cdda2wav.h
Modified:
   cdrkit/trunk/icedax/CMakeLists.txt
   cdrkit/trunk/icedax/interface.c
   cdrkit/trunk/icedax/ioctl.c
   cdrkit/trunk/icedax/resample.c
   cdrkit/trunk/icedax/scsi_cmds.c
   cdrkit/trunk/icedax/toc.c
Log:
cdda2wav -> icedax

Modified: cdrkit/trunk/icedax/CMakeLists.txt
===================================================================
--- cdrkit/trunk/icedax/CMakeLists.txt	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/CMakeLists.txt	2006-11-23 19:26:47 UTC (rev 436)
@@ -1,4 +1,4 @@
-PROJECT (CDDA2WAV)
+PROJECT (icedax)
 INCLUDE_DIRECTORIES(../include ../wodim ${CMAKE_BINARY_DIR})
 include(../include/AddScgBits.cmake)
 include(../include/AddSchilyBits.cmake)
@@ -18,11 +18,11 @@
 ENDIF (WIN32)
 
 LINK_DIRECTORIES(../libschily ../libusal ../libdeflt ../libparanoia)
-ADD_EXECUTABLE (cdda2wav aifc.c aiff.c base64.c cd_misc.c cdda2wav.c defaults.c getnum.c interface.c ioctl.c md5c.c modes.c raw.c resample.c ringbuff.c scsi_cdr.c scsi_cmds.c scsi_scan.c semshm.c setuid.c sha_func.c sndconfig.c sun.c toc.c wav.c)
-TARGET_LINK_LIBRARIES(cdda2wav ${EXTRA_LIBS})
-SET_TARGET_PROPERTIES(cdda2wav PROPERTIES  SKIP_BUILD_RPATH TRUE)
+ADD_EXECUTABLE (icedax aifc.c aiff.c base64.c cd_misc.c icedax.c defaults.c getnum.c interface.c ioctl.c md5c.c modes.c raw.c resample.c ringbuff.c scsi_cdr.c scsi_cmds.c scsi_scan.c semshm.c setuid.c sha_func.c sndconfig.c sun.c toc.c wav.c)
+TARGET_LINK_LIBRARIES(icedax ${EXTRA_LIBS})
+SET_TARGET_PROPERTIES(icedax PROPERTIES  SKIP_BUILD_RPATH TRUE)
 
-INSTALL(TARGETS cdda2wav DESTINATION bin)
+INSTALL(TARGETS icedax DESTINATION bin)
 INSTALL(PROGRAMS pitchplay readmult cdda2mp3 cdda2ogg DESTINATION bin)
-INSTALL(FILES cdda2ogg.1 cdda2wav.1 pitchplay.1 readmult.1 list_audio_tracks.1 DESTINATION share/man/man1)
+INSTALL(FILES cdda2ogg.1 icedax.1 pitchplay.1 readmult.1 list_audio_tracks.1 DESTINATION share/man/man1)
 

Deleted: cdrkit/trunk/icedax/cdda2wav.c
===================================================================
--- cdrkit/trunk/icedax/cdda2wav.c	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/cdda2wav.c	2006-11-23 19:26:47 UTC (rev 436)
@@ -1,3064 +0,0 @@
-/*
- * This file has been modified for the cdrkit suite.
- *
- * The behaviour and appearence of the program code below can differ to a major
- * extent from the version distributed by the original author(s).
- *
- * For details, see Changelog file distributed with the cdrkit package. If you
- * received this file from another source then ask the distributing person for
- * a log of modifications.
- *
- */
-
-/* @(#)cdda2wav.c	1.64 06/02/19 Copyright 1998-2004 Heiko Eissfeldt, Copyright 2004-2006 J. Schilling */
-#ifndef lint
-static char     sccsid[] =
-"@(#)cdda2wav.c	1.64 06/02/19 Copyright 1998-2004 Heiko Eissfeldt, Copyright 2004-2006 J. Schilling";
-
-#endif
-#undef DEBUG_BUFFER_ADDRESSES
-#undef GPROF
-#undef DEBUG_FORKED
-#undef DEBUG_CLEANUP
-#undef DEBUG_DYN_OVERLAP
-#undef DEBUG_READS
-#define DEBUG_ILLLEADOUT	0	/* 0 disables, 1 enables */
-/*
- * Copyright: GNU Public License 2 applies
- *
- *   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.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-/*
- * parts    (C) Peter Widow
- * parts    (C) Thomas Niederreiter
- * parts    (C) RSA Data Security, Inc.
- *
- * last changes:
- *   18.12.93 - first version,	OK
- *   01.01.94 - generalized & clean up HE
- *   10.06.94 - first linux version HE
- *   12.06.94 - wav header alignment problem fixed HE
- *   12.08.94 - open the cdrom device O_RDONLY makes more sense :-)
- *		no more floating point math
- *		change to sector size 2352 which is more common
- *		sub-q-channel information per kernel ioctl requested
- *		doesn't work as well as before
- *		some new options (-max -i)
- *   01.02.95 - async i/o via semaphores and shared memory
- *   03.02.95 - overlapped reading on sectors
- *   03.02.95 - generalized sample rates. all integral divisors are legal
- *   04.02.95 - sun format added
- *              more divisors: all integral halves >= 1 allowed
- *		floating point math needed again
- *   06.02.95 - bugfix for last track and not d0
- *              tested with photo-cd with audio tracks
- *		tested with xa disk 
- *   29.01.96 - new options for bulk transfer
- *   01.06.96 - tested with enhanced cd
- *   01.06.96 - tested with cd-plus
- *   02.06.96 - support pipes
- *   02.06.96 - support raw format
- *   04.02.96 - security hole fixed
- *   22.04.97 - large parts rewritten
- *   28.04.97 - make file names DOS compatible
- *   01.09.97 - add speed control
- *   20.10.97 - add find mono option
- *   Jan/Feb 98 - conversion to use Joerg Schillings SCSI library
- *   see ChangeLog
- */
-
-#include "config.h"
-
-#include <unixstd.h>
-#include <stdio.h>
-#include <standard.h>
-#include <stdxlib.h>
-#include <strdefs.h>
-#include <schily.h>
-#include <signal.h>
-#include <math.h>
-#include <fctldefs.h>
-#include <timedefs.h>
-#if defined (HAVE_LIMITS_H)
-#include <limits.h>
-#endif
-#if defined (HAVE_SYS_IOCTL_H)
-#include <sys/ioctl.h>
-#endif
-#include <errno.h>
-#include <statdefs.h>
-#include <waitdefs.h>
-#if defined (HAVE_SETPRIORITY)
-#include <sys/resource.h>
-#endif
-#include <vadefs.h>
-
-#include <usal/scsitransp.h>
-
-#ifdef	HAVE_AREAS
-#include <be/kernel/OS.h>
-#endif
-
-#include "mytype.h"
-#include "sndconfig.h"
-
-#include "semshm.h"	/* semaphore functions */
-#include "sndfile.h"
-#include "wav.h"	/* wav file header structures */
-#include "sun.h"	/* sun audio file header structures */
-#include "raw.h"	/* raw file handling */
-#include "aiff.h"	/* aiff file handling */
-#include "aifc.h"	/* aifc file handling */
-#ifdef	USE_LAME
-#include "mp3.h"	/* mp3 file handling */
-#endif
-#include "interface.h"  /* low level cdrom interfacing */
-#include "cdda2wav.h"
-#include "resample.h"
-#include "toc.h"
-#include "setuid.h"
-#include "ringbuff.h"
-#include "global.h"
-#include "exitcodes.h"
-#ifdef	USE_PARANOIA
-#include "cdda_paranoia.h"
-#endif
-#include "defaults.h"
-
-static void RestrictPlaybackRate(long newrate);
-static void output_indices(FILE *fp, index_list *p, unsigned trackstart);
-static int 	write_info_file(char *fname_baseval, unsigned int track, 
-									 unsigned long SamplesDone, int numbered);
-static void CloseAudio(int channels_val, unsigned long nSamples, 
-							  struct soundfile *audio_out);
-static void CloseAll(void);
-static void OpenAudio(char *fname, double rate, long nBitsPerSample, 
-							 long channels_val, unsigned long expected_bytes, 
-							 struct soundfile*audio_out);
-static void set_offset(myringbuff *p, int offset);
-static int 	get_offset(myringbuff *p);
-static void usage(void);
-static void init_globals(void);
-static int	is_fifo(char *filename);
-
-
-/* Rules:
- * unique parameterless options first,
- * unique parametrized option names next,
- * ambigious parameterless option names next,
- * ambigious string parametrized option names last
- */
-static const char *opts = "paranoia,paraopts&,version,help,h,\
-no-write,N,dump-rates,R,bulk,B,alltracks,verbose-scsi+,V+,\
-find-extremes,F,find-mono,G,no-infofile,H,\
-deemphasize,T,info-only,J,silent-scsi,Q,\
-cddbp-server*,cddbp-port*,\
-scanbus,device*,dev*,D*,auxdevice*,A*,interface*,I*,output-format*,O*,\
-output-endianess*,E*,cdrom-endianess*,C*,speed#,S#,\
-playback-realtime#L,p#L,md5#,M#,set-overlap#,P#,sound-device*,K*,\
-cddb#,L#,channels*,c*,bits-per-sample#,b#,rate#,r#,gui,g,\
-divider*,a*,track*,t*,index#,i#,duration*,d*,offset#,o#,\
-sectors-per-request#,n#,verbose-level&,v&,buffers-in-ring#,l#,\
-stereo,s,mono,m,wait,w,echo,e,quiet,q,max,x\
-";
-
-
-#ifdef	NEED_O_BINARY
-#include <io.h>		/* for setmode() prototype */
-#endif
-
-/* global variables */
-global_t global;
-
-/* static variables */
-static unsigned long nSamplesDone = 0;
-
-static	int child_pid = -2;
-
-static unsigned long *nSamplesToDo;
-static unsigned int current_track;
-static int bulk = 0;
-
-unsigned int get_current_track(void);
-
-unsigned int get_current_track()
-{
-	return current_track;
-}
-
-static void RestrictPlaybackRate(long  newrate)
-{
-       global.playback_rate = newrate;
-
-       if ( global.playback_rate < 25 ) global.playback_rate = 25;   /* filter out insane values */
-       if ( global.playback_rate > 250 ) global.playback_rate = 250;
-
-       if ( global.playback_rate < 100 )
-               global.nsectors = (global.nsectors*global.playback_rate)/100;
-}
-
-
-long SamplesNeeded(long amount, long undersampling_val)
-{
-  long retval = ((undersampling_val * 2 + Halved)*amount)/2;
-  if (Halved && (*nSamplesToDo & 1))
-    retval += 2;
-  return retval;
-}
-
-static int argc2;
-static int argc3;
-static char **argv2;
-
-static void reset_name_iterator(void);
-static void reset_name_iterator()
-{
-	argv2 -= argc3 - argc2;
-	argc2 = argc3;
-}
-
-static char *get_next_name(void);
-static char *get_next_name()
-{
-	if (argc2 > 0) {
-		argc2--;
-		return (*argv2++);
-	} else {
-		return NULL;
-	}
-}
-
-static char *cut_extension(char *fname);
-
-static char *cut_extension(char *fname)
-{
-	char *pp;
-
-	pp = strrchr(fname, '.');
-
-	if (pp == NULL) {
-		pp = fname + strlen(fname);
-	}
-	*pp = '\0';
-
-	return pp;
-}
-
-#ifdef INFOFILES
-static void output_indices(FILE *fp, index_list *p, unsigned trackstart)
-{
-  int ci;
-
-  fprintf(fp, "Index=\t\t");
-
-  if (p == NULL) {
-    fprintf(fp, "0\n");
-    return;
-  }
-
-  for (ci = 1; p != NULL; ci++, p = p->next) {
-    int frameoff = p->frameoffset;
-
-    if (p->next == NULL)
-	 fputs("\nIndex0=\t\t", fp);
-#if 0
-    else if ( ci > 8 && (ci % 8) == 1)
-	 fputs("\nIndex =\t\t", fp);
-#endif
-    if (frameoff != -1)
-         fprintf(fp, "%d ", frameoff - trackstart);
-    else
-         fprintf(fp, "-1 ");
-  }
-  fputs("\n", fp);
-}
-
-/*
- * write information before the start of the sampling process
- *
- *
- * uglyfied for Joerg Schillings ultra dumb line parser
- */
-static int write_info_file(char *fname_baseval, unsigned int track, 
-                           unsigned long int SamplesDone, int numbered)
-{
-  FILE *info_fp;
-  char fname[200];
-  char datetime[30];
-  time_t utc_time;
-  struct tm *tmptr;
-
-  /* write info file */
-  if (!strcmp(fname_baseval,"-")) return 0;
-
-  strncpy(fname, fname_baseval, sizeof(fname) -1);
-  fname[sizeof(fname) -1] = 0;
-  if (numbered)
-    sprintf(cut_extension(fname), "_%02u.inf", track);
-  else
-    strcpy(cut_extension(fname), ".inf");
-
-  info_fp = fopen (fname, "w");
-  if (!info_fp)
-    return -1;
-
-#if 0
-#ifdef MD5_SIGNATURES
-  if (global.md5blocksize)
-    MD5Final (global.MD5_result, &global.context);
-#endif
-#endif
-
-  utc_time = time(NULL);
-  tmptr = localtime(&utc_time);
-  if (tmptr) {
-    strftime(datetime, sizeof(datetime), "%x %X", tmptr);
-  } else {
-    strncpy(datetime, "unknown", sizeof(datetime));
-  }
-  fprintf(info_fp, "#created by cdda2wav %s %s\n#\n", VERSION
-	  , datetime
-	  );
-  fprintf(info_fp,
-"CDINDEX_DISCID=\t'%s'\n" , global.cdindex_id);
-  fprintf(info_fp,
-"CDDB_DISCID=\t0x%08lx\n\
-MCN=\t\t%s\n\
-ISRC=\t\t%15.15s\n\
-#\n\
-Albumperformer=\t'%s'\n\
-Performer=\t'%s'\n\
-Albumtitle=\t'%s'\n"
-	  , (unsigned long) global.cddb_id
-	  , Get_MCN()
-	  , Get_ISRC(track)
-	  , global.creator != NULL ? global.creator : (const unsigned char *)""
-	  , global.trackcreator[track] != NULL ? global.trackcreator[track] :
-		(global.creator != NULL ? global.creator : (const unsigned char *)"")
-	  , global.disctitle != NULL ? global.disctitle : (const unsigned char *)""
-	  );
-  fprintf(info_fp,
-	  "Tracktitle=\t'%s'\n"
-	  , global.tracktitle[track] ? global.tracktitle[track] : (const unsigned char *)""
-	  );
-  fprintf(info_fp, "Tracknumber=\t%u\n"
-	  , track
-	  );
-  fprintf(info_fp, 
-	  "Trackstart=\t%ld\n"
-	  , Get_AudioStartSector(track)
-	  );
-  fprintf(info_fp, 
-	  "# track length in sectors (1/75 seconds each), rest samples\nTracklength=\t%ld, %d\n"
-	  , SamplesDone/588L,(int)(SamplesDone%588));
-  fprintf(info_fp, 
-	  "Pre-emphasis=\t%s\n"
-	  , Get_Preemphasis(track) && (global.deemphasize == 0) ? "yes" : "no");
-  fprintf(info_fp, 
-	  "Channels=\t%d\n"
-	  , Get_Channels(track) ? 4 : global.channels == 2 ? 2 : 1);
-	{ int cr = Get_Copyright(track);
-		fputs("Copy_permitted=\t", info_fp);
-		switch (cr) {
-			case 0:
-				fputs("once (copyright protected)\n", info_fp);
-			break;
-			case 1:
-				fputs("no (SCMS first copy)\n", info_fp);
-			break;
-			case 2:
-				fputs("yes (not copyright protected)\n", info_fp);
-			break;
-			default:
-				fputs("unknown\n", info_fp);
-		}
-	}
-  fprintf(info_fp, 
-	  "Endianess=\t%s\n"
-	  , global.need_big_endian ? "big" : "little"
-	  );
-  fprintf(info_fp, "# index list\n");
-  output_indices(info_fp, global.trackindexlist[track],
-		 Get_AudioStartSector(track));
-#if 0
-/* MD5 checksums in info files are currently broken.
- *  for on-the-fly-recording the generation of info files has been shifted
- *  before the recording starts, so there is no checksum at that point.
- */
-#ifdef MD5_SIGNATURES
-  fprintf(info_fp, 
-	  "#(blocksize) checksum\nMD-5=\t\t(%d) %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
-	  , global.md5blocksize
-	  , global.MD5_result[0]
-	  , global.MD5_result[1]
-	  , global.MD5_result[2]
-	  , global.MD5_result[3]
-	  , global.MD5_result[4]
-	  , global.MD5_result[5]
-	  , global.MD5_result[6]
-	  , global.MD5_result[7]
-	  , global.MD5_result[8]
-	  , global.MD5_result[9]
-	  , global.MD5_result[10]
-	  , global.MD5_result[11]
-	  , global.MD5_result[12]
-	  , global.MD5_result[13]
-	  , global.MD5_result[14]
-	  , global.MD5_result[15]);
-#endif
-#endif
-  fclose(info_fp);
-  return 0;
-}
-#endif
-
-static void CloseAudio(int channels_val, unsigned long nSamples, 
-                       struct soundfile *audio_out)
-{
-      /* define length */
-      audio_out->ExitSound( global.audio, (nSamples-global.SkippedSamples)*global.OutSampleSize*channels_val );
-
-      close (global.audio);
-      global.audio = -1;
-}
-
-static unsigned int track = 1;
-
-/* On terminating:
- * define size-related entries in audio file header, update and close file */
-static void CloseAll()
-{
-	WAIT_T chld_return_status;
-	int amiparent;
-
-	/* terminate child process first */
-	amiparent = child_pid > 0;
-
-	if (global.iloop > 0) {
-		/* set to zero */
-		global.iloop = 0;
-	}
-
-#if	defined	HAVE_FORK_AND_SHAREDMEM
-# ifdef DEBUG_CLEANUP
-	fprintf(stderr, "%s terminating, \n", amiparent ? 
-		"Parent (READER)" : "Child (WRITER)");
-#endif
-#else
-# ifdef DEBUG_CLEANUP
-	fprintf(stderr, "Cdda2wav single process terminating, \n");
-# endif
-#endif
-
-	if (amiparent || child_pid < 0) {
-		/* switch to original mode and close device */
-		EnableCdda (get_scsi_p(), 0, 0);
-	}
-
-	if (!amiparent) {
-		/* do general clean up */
-
-		if (global.audio>=0) {
-			if (bulk) {
-				/* finish sample file for this track */
-				CloseAudio(global.channels,
-				 global.nSamplesDoneInTrack, global.audio_out);
-			} else {
-				/* finish sample file for this track */
-				CloseAudio(global.channels,
-				 (unsigned int) *nSamplesToDo, global.audio_out);
-			}
-		}
-
-		/* tell minimum and maximum amplitudes, if required */
-		if (global.findminmax) {
-			fprintf(stderr,
-			"Right channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", 
-			global.minamp[0], global.maxamp[0]);
-			fprintf(stderr,
-			"Left  channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", 
-			global.minamp[1], global.maxamp[1]);
-		}
-
-		/* tell mono or stereo recording, if required */
-		if (global.findmono) {
-			fprintf(stderr, "Audio samples are originally %s.\n", global.ismono ? "mono" : "stereo");
-		}
-
-		return;	/* end of child or single process */
-	}
-
-
-	if (global.have_forked == 1) {
-#ifdef DEBUG_CLEANUP
-		fprintf(stderr, "Parent wait for child death, \n");
-#endif
-
-		/* wait for child to terminate */
-		if (0 > wait(&chld_return_status)) {
-			perror("");
-		} else {
-			if (WIFEXITED(chld_return_status)) {
-				if (WEXITSTATUS(chld_return_status)) {
-					fprintf(stderr, "\nW Child exited with %d\n", WEXITSTATUS(chld_return_status));
-				}
-			}
-			if (WIFSIGNALED(chld_return_status)) {
-				fprintf(stderr, "\nW Child exited due to signal %d\n", WTERMSIG(chld_return_status));
-			}
-			if (WIFSTOPPED(chld_return_status)) {
-				fprintf(stderr, "\nW Child is stopped due to signal %d\n", WSTOPSIG(chld_return_status));
-			}
-		}
-
-#ifdef DEBUG_CLEANUP
-		fprintf(stderr, "\nW Parent child death, state:%d\n", chld_return_status);
-#endif
-	}
-
-#ifdef GPROF
-	rename("gmon.out", "gmon.child");
-#endif
-}
-
-
-/* report a usage error and exit */
-#ifdef  PROTOTYPES
-static void usage2 (const char *szMessage, ...)
-#else
-static void usage2(const char *szMessage, va_dcl va_alist)
-#endif
-{
-	va_list marker;
-
-#ifdef  PROTOTYPES
-	va_start(marker, szMessage);
-#else
-	va_start(marker);
-#endif
-
-	vfprintf(stderr, szMessage, marker);
-
-	va_end(marker);
-	fprintf(stderr, "\nPlease use -help or consult the man page for help.\n");
-
-	exit (1);
-}
-
-
-/* report a fatal error, clean up and exit */
-#ifdef  PROTOTYPES
-void FatalError (const char *szMessage, ...)
-#else
-void FatalError(const char *szMessage, va_dcl va_alist)
-#endif
-{
-	va_list marker;
-
-#ifdef  PROTOTYPES
-	va_start(marker, szMessage);
-#else
-	va_start(marker);
-#endif
-
-	vfprintf(stderr, szMessage, marker);
-
-	va_end(marker);
-
-	if (child_pid >= 0) {
-		if (child_pid == 0) {
-			pid_t	ppid;
-			/*
-			 * Kill the parent too if we are not orphaned.
-			 */
-			ppid = getppid();
-			if (ppid > 1)
-				kill(ppid, SIGINT);
-		} else {
-			kill(child_pid, SIGINT);
-		}
-	}
-	exit (1);
-}
-
-
-/* open the audio output file and prepare the header. 
- * the header will be defined on terminating (when the size
- * is known). So hitting the interrupt key leaves an intact
- * file.
- */
-static void OpenAudio(char *fname, double rate, long nBitsPerSample, 
-                      long channels_val, unsigned long expected_bytes, 
-                      struct soundfile *audio_out)
-{
-  if (global.audio == -1) {
-
-    global.audio = open (fname, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY
-#ifdef SYNCHRONOUS_WRITE
-			 | O_SYNC
-#endif
-		  , 0666);
-    if (global.audio == -1) {
-      if (errno == EAGAIN && is_fifo(fname)) {
-        FatalError ("Could not open fifo %s. Probably no fifo reader present.\n", fname);
-      }
-      perror("open audio sample file");
-      FatalError ("Could not open file %s\n", fname);
-    }
-  }
-  global.SkippedSamples = 0;
-  any_signal = 0;
-  audio_out->InitSound( global.audio, channels_val, (unsigned long)rate, nBitsPerSample, expected_bytes );
-
-#ifdef MD5_SIGNATURES
-  if (global.md5blocksize)
-    MD5Init (&global.context);
-  global.md5count = global.md5blocksize;
-#endif
-}
-
-#include "scsi_cmds.h"
-
-static int RealEnd(SCSI *usalp, UINT4 *buff);
-
-static int RealEnd(SCSI *usalp, UINT4 *buff)
-{
-	if (usal_cmd_err(usalp) != 0) {
-		int c,k,q;
-
-		k = usal_sense_key(usalp);
-		c = usal_sense_code(usalp);
-		q = usal_sense_qual(usalp);
-		if ((k == 0x05 /* ILLEGAL_REQUEST */ &&
-		     c == 0x21 /* lba out of range */ &&
-		     q == 0x00) ||
-		    (k == 0x05 /* ILLEGAL_REQUEST */ &&
-		     c == 0x63 /*end of user area encountered on this track*/ &&
-		     q == 0x00) ||
-		    (k == 0x08 /* BLANK_CHECK */ &&
-		     c == 0x64 /* illegal mode for this track */ &&
-		     q == 0x00)) {
-			return 1;
-		}
-	}
-
-	if (usal_getresid(usalp) > 16) return 1;
-
-	{
-		unsigned char *p;
-		/* Look into the subchannel data */
-		buff += CD_FRAMESAMPLES;
-		p = (unsigned char *)buff;
-		if (p[0] == 0x21 && p[1] == 0xaa) {
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static void set_offset(myringbuff *p, int offset)
-{
-#ifdef DEBUG_SHM
-  fprintf(stderr, "Write offset %d at %p\n", offset, &p->offset);
-#endif
-  p->offset = offset;
-}
-
-
-static int get_offset(myringbuff *p)
-{
-#ifdef DEBUG_SHM
-  fprintf(stderr, "Read offset %d from %p\n", p->offset, &p->offset);
-#endif
-  return p->offset;
-}
-
-
-static void usage()
-{
-  fputs(
-"usage: cdda2wav [OPTIONS ...] [trackfilenames ...]\n\
-OPTIONS:\n\
-        [-c chans] [-s] [-m] [-b bits] [-r rate] [-a divider] [-S speed] [-x]\n\
-        [-t track[+endtrack]] [-i index] [-o offset] [-d duration] [-F] [-G]\n\
-        [-q] [-w] [-v vopts] [-R] [-P overlap] [-B] [-T] [-C input-endianess]\n\
-        [-e] [-n sectors] [-N] [-J] [-L cddbp-mode] [-H] [-g] [-l buffers] [-D cd-device]\n\
-        [-I interface] [-K sound-device] [-O audiotype] [-E output-endianess]\n\
-        [-A auxdevice] [-paranoia] [-cddbp-server=name] [-cddbp-port=port] [-version]\n", stderr);
-  fputs("\
-  (-D) dev=device		set the cdrom or scsi device (as Bus,Id,Lun).\n\
-  (-A) auxdevice=device		set the aux device (typically /dev/cdrom).\n\
-  (-K) sound-device=device	set the sound device to use for -e (typically /dev/dsp).\n\
-  (-I) interface=interface	specify the interface for cdrom access.\n\
-        (generic_scsi or cooked_ioctl).\n\
-  (-c) channels=channels	set 1 for mono, 2 or s for stereo (s: channels swapped).\n\
-  (-s) -stereo			select stereo recording.\n\
-  (-m) -mono			select mono recording.\n\
-  (-x) -max			select maximum quality (stereo/16-bit/44.1 KHz).\n\
-  (-b) bits=bits		set bits per sample per channel (8, 12 or 16 bits).\n\
-  (-r) rate=rate		set rate in samples per second. -R gives all rates\n\
-  (-a) divider=divider		set rate to 44100Hz / divider. -R gives all rates\n\
-  (-R) -dump-rates		dump a table with all available sample rates\n\
-  (-S) speed=speedfactor	set the cdrom drive to a given speed during reading\n\
-  (-P) set-overlap=sectors	set amount of overlap sampling (default is 0)\n\
-  (-n) sectors-per-request=secs	read 'sectors' sectors per request.\n\
-  (-l) buffers-in-ring=buffers	use a ring buffer with 'buffers' elements.\n\
-  (-t) track=track[+end track]	select start track (option. end track).\n\
-  (-i) index=index		select start index.\n\
-  (-o) offset=offset		start at 'offset' sectors behind start track/index.\n\
-        one sector equivalents 1/75 second.\n\
-  (-O) output-format=audiotype	set to wav, au (sun), cdr (raw), aiff or aifc format.\n\
-  (-C) cdrom-endianess=endian	set little, big or guess input sample endianess.\n\
-  (-E) output-endianess=endian	set little or big output sample endianess.\n\
-  (-d) duration=seconds		set recording time in seconds or 0 for whole track.\n\
-  (-w) -wait			wait for audio signal, then start recording.\n\
-  (-F) -find-extremes		find extrem amplitudes in samples.\n\
-  (-G) -find-mono		find if input samples are mono.\n\
-  (-T) -deemphasize		undo pre-emphasis in input samples.\n\
-  (-e) -echo			echo audio data to sound device (see -K) SOUND_DEV.\n\
-  (-v) verbose-level=optlist	controls verbosity (for a list use -vhelp).\n\
-  (-N) -no-write		do not create audio sample files.\n\
-  (-J) -info-only		give disc information only.\n\
-  (-L) cddb=cddbpmode		do cddbp title lookups.\n\
-        resolve multiple entries according to cddbpmode: 0=interactive, 1=first entry\n\
-  (-H) -no-infofile		no info file generation.\n\
-  (-g) -gui			generate special output suitable for gui frontends.\n\
-  (-Q) -silent-scsi		do not print status of erreneous scsi-commands.\n\
-       -scanbus			scan the SCSI bus and exit\n\
-  (-M) md5=count		calculate MD-5 checksum for blocks of 'count' bytes.\n\
-  (-q) -quiet			quiet operation, no screen output.\n\
-  (-p) playback-realtime=perc	play (echo) audio pitched at perc percent (50%-200%).\n\
-  (-V) -verbose-scsi		each option increases verbosity for SCSI commands.\n\
-  (-h) -help			show this help screen.\n\
-  (-B) -alltracks, -bulk	record each track into a seperate file.\n\
-       -paranoia		use the lib paranoia for reading.\n\
-       -paraopts=opts		set options for lib paranoia (see -paraopts=help).\n\
-       -cddbp-server=servername	set the cddbp server to use for title lookups.\n\
-       -cddbp-port=portnumber	set the cddbp port to use for title lookups.\n\
-       -version			print version information.\n\
-\n\
-Please note: some short options will be phased out soon (disappear)!\n\
-\n\
-parameters: (optional) one or more file names or - for standard output.\n\
-", stderr);
-  fputs("Version ", stderr);
-  fputs(VERSION, stderr);
-  fprintf(stderr, "\n\
-defaults	%s, %d bit, %d.%02d Hz, track 1, no offset, one track,\n",
-	  CHANNELS-1?"stereo":"mono", BITS_P_S,
-	 44100 / UNDERSAMPLING,
-	 (4410000 / UNDERSAMPLING) % 100);
-  fprintf(stderr, "\
-          type %s '%s', don't wait for signal, not quiet,\n",
-          AUDIOTYPE, FILENAME);
-  fprintf(stderr, "\
-          use %s, device %s, aux %s\n",
-	  DEF_INTERFACE, CD_DEVICE, AUX_DEVICE);
-  exit( SYNTAX_ERROR );
-}
-
-static void init_globals()
-{
-#ifdef	HISTORICAL_JUNK
-  global.dev_name = CD_DEVICE;	/* device name */
-#endif
-  global.aux_name = AUX_DEVICE;/* auxiliary cdrom device */
-  strncpy(global.fname_base, FILENAME, sizeof(global.fname_base));/* auxiliary cdrom device */
-  global.have_forked = 0;	/* state variable for clean up */
-  global.parent_died = 0;	/* state variable for clean up */
-  global.audio    = -1;		/* audio file desc */
-  global.cooked_fd  = -1;	/* cdrom file desc */
-  global.no_file  =  0;		/* flag no_file */
-  global.no_infofile  =  0;	/* flag no_infofile */
-  global.no_cddbfile  =  0;	/* flag no_cddbfile */
-  global.quiet	  =  0;		/* flag quiet */
-  global.verbose  =  SHOW_TOC + SHOW_SUMMARY + SHOW_STARTPOSITIONS + SHOW_TITLES;	/* verbose level */
-  global.scsi_silent = 0;
-  global.scsi_verbose = 0;		/* SCSI verbose level */
-  global.scanbus = 0;
-  global.multiname = 0;		/* multiple file names given */
-  global.sh_bits  =  0;		/* sh_bits: sample bit shift */
-  global.Remainder=  0;		/* remainder */
-  global.iloop    =  0;		/* todo counter */
-  global.SkippedSamples =  0;	/* skipped samples */
-  global.OutSampleSize  =  0;	/* output sample size */
-  global.channels = CHANNELS;	/* output sound channels */
-  global.nSamplesDoneInTrack = 0; /* written samples in current track */
-  global.buffers = 4;           /* buffers to use */
-  global.nsectors = NSECTORS;   /* sectors to read in one request */
-  global.overlap = 1;           /* amount of overlapping sectors */
-  global.useroverlap = -1;      /* amount of overlapping sectors user override */
-  global.need_hostorder = 0;	/* processing needs samples in host endianess */
-  global.in_lendian = -1;	/* input endianess from SetupSCSI() */
-  global.outputendianess = NONE; /* user specified output endianess */
-  global.findminmax  =  0;	/* flag find extrem amplitudes */
-#ifdef HAVE_LIMITS_H
-  global.maxamp[0] = INT_MIN;	/* maximum amplitude */
-  global.maxamp[1] = INT_MIN;	/* maximum amplitude */
-  global.minamp[0] = INT_MAX;	/* minimum amplitude */
-  global.minamp[1] = INT_MAX;	/* minimum amplitude */
-#else
-  global.maxamp[0] = -32768;	/* maximum amplitude */
-  global.maxamp[1] = -32768;	/* maximum amplitude */
-  global.minamp[0] = 32767;	/* minimum amplitude */
-  global.minamp[1] = 32767;	/* minimum amplitude */
-#endif
-  global.speed = DEFAULT_SPEED; /* use default */ 
-  global.userspeed = -1;        /* speed user override */
-  global.findmono  =  0;	/* flag find if samples are mono */
-  global.ismono  =  1;		/* flag if samples are mono */
-  global.swapchannels  =  0;	/* flag if channels shall be swapped */
-  global.deemphasize  =  0;	/* flag undo pre-emphasis in samples */
-  global.playback_rate = 100;   /* new fancy selectable sound output rate */
-  global.gui  =  0;		/* flag plain formatting for guis */
-  global.cddb_id = 0;           /* disc identifying id for CDDB database */
-  global.cddb_revision = 0;     /* entry revision for CDDB database */
-  global.cddb_year = 0;         /* disc identifying year for CDDB database */
-  global.cddb_genre[0] = '\0';  /* disc identifying genre for CDDB database */
-  global.cddbp = 0;             /* flag if titles shall be looked up from CDDBP */
-  global.cddbp_server = 0;      /* user supplied CDDBP server */
-  global.cddbp_port = 0;        /* user supplied CDDBP port */
-  global.illleadout_cd = 0;     /* flag if illegal leadout is present */
-  global.reads_illleadout = 0;  /* flag if cdrom drive reads cds with illegal leadouts */
-  global.disctitle = NULL;
-  global.creator = NULL;
-  global.copyright_message = NULL;
-  memset(global.tracktitle, 0, sizeof(global.tracktitle));
-  memset(global.trackindexlist, 0, sizeof(global.trackindexlist));
-
-  global.just_the_toc = 0;
-#ifdef	USE_PARANOIA
-	global.paranoia_parms.disable_paranoia = 
-	global.paranoia_parms.disable_extra_paranoia = 
-	global.paranoia_parms.disable_scratch_detect =
-	global.paranoia_parms.disable_scratch_repair = 0;
-	global.paranoia_parms.retries = 20;
-	global.paranoia_parms.overlap = -1;
-	global.paranoia_parms.mindynoverlap = -1;
-	global.paranoia_parms.maxdynoverlap = -1;
-#endif
-}
-
-#if !defined (HAVE_STRCASECMP) || (HAVE_STRCASECMP != 1)
-#include <ctype.h>
-static int strcasecmp(const char *s1, const char *s2);
-static int strcasecmp(const char *s1, const char *s2)
-{
-  if (s1 && s2) {
-    while (*s1 && *s2 && (tolower(*s1) - tolower(*s2) == 0)) {
-      s1++;
-      s2++;
-    }
-    if (*s1 == '\0' && *s2 == '\0') return 0;
-    if (*s1 == '\0') return -1;
-    if (*s2 == '\0') return +1;
-    return tolower(*s1) - tolower(*s2);
-  }
-  return -1;
-}
-#endif
-
-static int is_fifo(char *filename)
-{
-#if	defined S_ISFIFO
-  struct stat statstruct;
-
-  if (stat(filename, &statstruct)) {
-    /* maybe the output file does not exist. */
-    if (errno == ENOENT)
-	return 0;
-    else comerr("Error during stat for output file\n");
-  } else {
-    if (S_ISFIFO(statstruct.st_mode)) {
-	return 1;
-    }
-  }
-  return 0;
-#else
-  return 0;
-#endif
-}
-
-
-#if !defined (HAVE_STRTOUL) || (HAVE_STRTOUL != 1)
-static unsigned int strtoul(const char *s1, char **s2, int base);
-static unsigned int strtoul(const char *s1, char **s2, int base)
-{
-	long retval;
-
-	if (base == 10) {
-		/* strip zeros in front */
-		while (*s1 == '0')
-			s1++;
-	}
-	if (s2 != NULL) {
-		*s2 = astol(s1, &retval);
-	} else {
-		(void) astol(s1, &retval);
-	}
-
-	return (unsigned long) retval; 	
-}
-#endif
-
-static unsigned long SectorBurst;
-#if (SENTINEL > CD_FRAMESIZE_RAW)
-error block size for overlap check has to be < sector size
-#endif
-
-
-static void
-switch_to_realtime_priority(void);
-
-#ifdef  HAVE_SYS_PRIOCNTL_H
-
-#include <sys/priocntl.h>
-#include <sys/rtpriocntl.h>
-static void switch_to_realtime_priority()
-{
-        pcinfo_t        info;
-        pcparms_t       param;
-        rtinfo_t        rtinfo;
-        rtparms_t       rtparam;
-	int		pid;
-
-	pid = getpid();
-
-        /* get info */
-        strcpy(info.pc_clname, "RT");
-        if (-1 == priocntl(P_PID, pid, PC_GETCID, (void *)&info)) {
-                errmsg("Cannot get priority class id priocntl(PC_GETCID)\n");
-		goto prio_done;
-	}
-
-        memmove(&rtinfo, info.pc_clinfo, sizeof(rtinfo_t));
-
-        /* set priority not to the max */
-        rtparam.rt_pri = rtinfo.rt_maxpri - 2;
-        rtparam.rt_tqsecs = 0;
-        rtparam.rt_tqnsecs = RT_TQDEF;
-        param.pc_cid = info.pc_cid;
-        memmove(param.pc_clparms, &rtparam, sizeof(rtparms_t));
-	priv_on();
-	needroot(0);
-        if (-1 == priocntl(P_PID, pid, PC_SETPARMS, (void *)&param))
-                errmsg("Cannot set priority class parameters priocntl(PC_SETPARMS)\n");
-prio_done:
-	priv_off();
-	dontneedroot();
-}
-#else
-#if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING -0 >= 0
-#define	USE_POSIX_PRIORITY_SCHEDULING
-#endif
-#ifdef	USE_POSIX_PRIORITY_SCHEDULING
-#include <sched.h>
-
-static void switch_to_realtime_priority()
-{
-#ifdef  _SC_PRIORITY_SCHEDULING
-	if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) {
-		errmsg("WARNING: RR-scheduler not available, disabling.\n");
-	} else
-#endif
-	{
-	int sched_fifo_min, sched_fifo_max;
-	struct sched_param sched_parms;
-
-	sched_fifo_min = sched_get_priority_min(SCHED_FIFO);
-	sched_fifo_max = sched_get_priority_max(SCHED_FIFO);
-	sched_parms.sched_priority = sched_fifo_max - 1;
-	priv_on();
-	needroot(0);
-	if (-1 == sched_setscheduler(getpid(), SCHED_FIFO, &sched_parms)
-		&& global.quiet != 1)
-		errmsg("cannot set posix realtime scheduling policy\n");
-	priv_off();
-	dontneedroot();
-	}
-}
-#else
-#if defined(__CYGWIN32__)
-
-/*
- * NOTE: Base.h from Cygwin-B20 has a second typedef for BOOL.
- *	 We define BOOL to make all local code use BOOL
- *	 from Windows.h and use the hidden __SBOOL for
- *	 our global interfaces.
- *
- * NOTE: windows.h from Cygwin-1.x includes a structure field named sample,
- *	 so me may not define our own 'sample' or need to #undef it now.
- *	 With a few nasty exceptions, Microsoft assumes that any global
- *	 defines or identifiers will begin with an Uppercase letter, so
- *	 there may be more of these problems in the future.
- *
- * NOTE: windows.h defines interface as an alias for struct, this 
- *	 is used by COM/OLE2, I guess it is class on C++
- *	 We man need to #undef 'interface'
- */
-#define	BOOL	WBOOL		/* This is the Win BOOL		*/
-#define	format	__format	/* Avoid format parameter hides global ... */
-#include <windows.h>
-#undef format
-#undef interface
-
-static void switch_to_realtime_priority()
-{
-   /* set priority class */
-   if (FALSE == SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) {
-     fprintf(stderr, "No realtime priority possible.\n");
-     return;
-   }
-
-   /* set thread priority */
-   if (FALSE == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
-     fprintf(stderr, "Could not set realtime priority.\n");
-   }
-}
-#else
-static void switch_to_realtime_priority()
-{
-}
-#endif
-#endif
-#endif
-
-/* SCSI cleanup */
-int on_exitscsi(void *status);
-
-int on_exitscsi(void *status)
-{
-	exit((int)status);
-	return 0;
-}
-
-/* wrapper for signal handler exit needed for Mac-OS-X */
-static void exit_wrapper(int status);
-
-static void exit_wrapper(int status)
-{
-#if defined DEBUG_CLEANUP
-	fprintf( stderr, "Exit(%d) for %s\n", status, child_pid == 0 ? "Child" : "Parent");
-	fflush(stderr);
-#endif
-
-	if (child_pid != 0) {
-		SCSI *usalp = get_scsi_p();
-		if (usalp->running) {
-			usalp->cb_fun = on_exitscsi;
-			usalp->cb_arg = (void *)status;
-		} else {
-			on_exitscsi((void *)status);
-		} 
-	} else {
-		exit(status);
-	}
-}
-
-/* signal handler for process communication */
-static void set_nonforked(int status);
-
-/* ARGSUSED */
-static void set_nonforked(int status)
-{
-	global.parent_died = 1;
-#if defined DEBUG_CLEANUP
-fprintf( stderr, "SIGPIPE received from %s\n.", child_pid == 0 ? "Child" : "Parent");
-#endif
-	if (child_pid == 0) {
-		pid_t	ppid;
-		/*
-		 * Kill the parent too if we are not orphaned.
-		 */
-		ppid = getppid();
-		if (ppid > 1)
-			kill(ppid, SIGINT);
-	} else {
-		kill(child_pid, SIGINT);
-	}
-	exit(SIGPIPE_ERROR);
-}
-
-
-
-#ifdef	USE_PARANOIA
-static struct paranoia_statistics
-{
-	long	c_sector;
-	long	v_sector;
-	int	last_heartbeatstate;
-	long	lasttime;
-	char	heartbeat;
-	int	minoverlap;
-	int	curoverlap;
-	int	maxoverlap;
-	int	slevel;
-	int	slastlevel;
-	int	stimeout;
-	int	rip_smile_level;
-	unsigned verifies;
-	unsigned reads;
-	unsigned fixup_edges;
-	unsigned fixup_atoms;
-	unsigned readerrs;
-	unsigned skips;
-	unsigned overlaps;
-	unsigned scratchs;
-	unsigned drifts;
-	unsigned fixup_droppeds;
-	unsigned fixup_dupeds;
-}	*para_stat;
-
-
-static void paranoia_reset(void);
-static void paranoia_reset()
-{
-	para_stat->c_sector = 0;
-	para_stat->v_sector = 0;
-	para_stat->last_heartbeatstate = 0;
-	para_stat->lasttime = 0;
-	para_stat->heartbeat = ' ';
-	para_stat->minoverlap = 0x7FFFFFFF;
-	para_stat->curoverlap = 0;
-	para_stat->maxoverlap = 0;
-	para_stat->slevel = 0;
-	para_stat->slastlevel = 0;
-	para_stat->stimeout = 0;
-	para_stat->rip_smile_level = 0;
-	para_stat->verifies = 0;
-	para_stat->reads = 0;
-	para_stat->readerrs = 0;
-	para_stat->fixup_edges = 0;
-	para_stat->fixup_atoms = 0;
-	para_stat->fixup_droppeds = 0;
-	para_stat->fixup_dupeds = 0;
-	para_stat->drifts = 0;
-	para_stat->scratchs = 0;
-	para_stat->overlaps = 0;
-	para_stat->skips = 0;
-}
-
-static void paranoia_callback(long inpos, int function);
-
-static void paranoia_callback(long inpos, int function)
-{
-	struct timeval thistime;
-	long	test;
-
-	switch (function) {
-		case	-2:
-			para_stat->v_sector = inpos / CD_FRAMEWORDS;
-			return;
-		case	-1:
-			para_stat->last_heartbeatstate = 8;
-			para_stat->heartbeat = '*';
-			para_stat->slevel = 0;
-			para_stat->v_sector = inpos / CD_FRAMEWORDS;
-		break;
-		case	PARANOIA_CB_VERIFY:
-			if (para_stat->stimeout >= 30) {
-				if (para_stat->curoverlap > CD_FRAMEWORDS) {
-					para_stat->slevel = 2;
-				} else {
-					para_stat->slevel = 1;
-				}
-			}
-			para_stat->verifies++;
-		break;
-		case	PARANOIA_CB_READ:
-			if (inpos / CD_FRAMEWORDS > para_stat->c_sector) {
-				para_stat->c_sector = inpos / CD_FRAMEWORDS;
-			}
-			para_stat->reads++;
-		break;
-		case	PARANOIA_CB_FIXUP_EDGE:
-			if (para_stat->stimeout >= 5) {
-				if (para_stat->curoverlap > CD_FRAMEWORDS) {
-					para_stat->slevel = 2;
-				} else {
-					para_stat->slevel = 1;
-				}
-			}
-			para_stat->fixup_edges++;
-		break;
-		case	PARANOIA_CB_FIXUP_ATOM:
-			if (para_stat->slevel < 3 || para_stat->stimeout > 5) {
-				para_stat->slevel = 3;
-			}
-			para_stat->fixup_atoms++;
-		break;
-		case	PARANOIA_CB_READERR:
-			para_stat->slevel = 6;
-			para_stat->readerrs++;
-		break;
-		case	PARANOIA_CB_SKIP:
-			para_stat->slevel = 8;
-			para_stat->skips++;
-		break;
-		case	PARANOIA_CB_OVERLAP:
-			para_stat->curoverlap = inpos;
-			if (inpos > para_stat->maxoverlap)
-				para_stat->maxoverlap = inpos;
-			if (inpos < para_stat->minoverlap)
-				para_stat->minoverlap = inpos;
-			para_stat->overlaps++;
-		break;
-		case	PARANOIA_CB_SCRATCH:
-			para_stat->slevel = 7;
-			para_stat->scratchs++;
-		break;
-		case	PARANOIA_CB_DRIFT:
-			if (para_stat->slevel < 4 || para_stat->stimeout > 5) {
-				para_stat->slevel = 4;
-			}
-			para_stat->drifts++;
-		break;
-		case	PARANOIA_CB_FIXUP_DROPPED:
-			para_stat->slevel = 5;
-			para_stat->fixup_droppeds++;
-		break;
-		case	PARANOIA_CB_FIXUP_DUPED:
-			para_stat->slevel = 5;
-			para_stat->fixup_dupeds++;
-		break;
-	}
-
-	gettimeofday(&thistime, NULL);
-	/* now in tenth of seconds. */
-	test = thistime.tv_sec * 10 + thistime.tv_usec / 100000;
-
-	if (para_stat->lasttime != test
-		|| function == -1
-		|| para_stat->slastlevel != para_stat->slevel) {
-
-		if (function == -1
-			|| para_stat->slastlevel != para_stat->slevel) {
-
-			static const char hstates[] = " .o0O0o.";
-
-			para_stat->lasttime = test;
-			para_stat->stimeout++;
-
-			para_stat->last_heartbeatstate++;
-			if (para_stat->last_heartbeatstate > 7) {
-				para_stat->last_heartbeatstate = 0;
-			}
-			para_stat->heartbeat = hstates[para_stat->last_heartbeatstate];
-
-			if (function == -1) {
-				para_stat->heartbeat = '*';
-			}
-		}
-
-		if (para_stat->slastlevel != para_stat->slevel) {
-			para_stat->stimeout = 0;
-		}
-		para_stat->slastlevel = para_stat->slevel;
-	}
-
-	if (para_stat->slevel < 8) {
-		para_stat->rip_smile_level = para_stat->slevel;
-	} else {
-		para_stat->rip_smile_level = 0;
-	}
-}
-#endif
-
-static long lSector;
-static long lSector_p2;
-static double rate = 44100.0 / UNDERSAMPLING;
-static int bits = BITS_P_S;
-static char fname[200];
-static const char *audio_type;
-static long BeginAtSample;
-static unsigned long SamplesToWrite; 
-static unsigned minover;
-static unsigned maxover;
-
-static unsigned long calc_SectorBurst(void);
-static unsigned long calc_SectorBurst()
-{
-	unsigned long SectorBurstVal;
-
-	SectorBurstVal = min(global.nsectors,
-		  (global.iloop + CD_FRAMESAMPLES-1) / CD_FRAMESAMPLES);
-	if ( lSector+(int)SectorBurst-1 >= lSector_p2 )
-		SectorBurstVal = lSector_p2 - lSector;
-	return SectorBurstVal;
-}
-
-/* if PERCENTAGE_PER_TRACK is defined, the percentage message will reach
- * 100% every time a track end is reached or the time limit is reached.
- *
- * Otherwise if PERCENTAGE_PER_TRACK is not defined, the percentage message
- * will reach 100% once at the very end of the last track.
- */
-#define	PERCENTAGE_PER_TRACK
-
-static int do_read(myringbuff *p, unsigned *total_unsuccessful_retries);
-static int do_read(myringbuff *p, unsigned *total_unsuccessful_retries)
-{
-	unsigned char *newbuf;
-	int offset;
-	unsigned int added_size;
-
-	/* how many sectors should be read */
-	SectorBurst =  calc_SectorBurst();
-
-#ifdef	USE_PARANOIA
-	if (global.paranoia_selected) {
-		int i;
-
-		for (i = 0; i < SectorBurst; i++) {
-			void *dp;
-
-			dp = paranoia_read_limited(global.cdp, paranoia_callback,
-				global.paranoia_parms.retries);
-/*
-			{
-				char *err;
-				char *msg;
-				err = cdda_errors(global.cdp);
-				msg = cdda_messages(global.cdp);
-				if (err) {
-					fputs(err, stderr);
-					free(err);
-				}
-				if (msg) {
-					fputs(msg, stderr);
-					free(msg);
-				}
-			}
-*/
-			if (dp != NULL)	{
-				memcpy(p->data + i*CD_FRAMESAMPLES, dp,
-					CD_FRAMESIZE_RAW);
-			} else {
-				fputs("E unrecoverable error!", stderr);
-				exit(READ_ERROR);
-			}
-		}
-		newbuf = (unsigned char *)p->data;
-		offset = 0;
-        	set_offset(p,offset);
-		added_size = SectorBurst * CD_FRAMESAMPLES;
-		global.overlap = 0;
-		handle_inputendianess(p->data, added_size);
-	} else 
-#endif
-	{
-		unsigned int retry_count;
-#define MAX_READRETRY 12
-
-		retry_count = 0;
-		do {
-			SCSI *usalp = get_scsi_p();
-			int retval;
-#ifdef DEBUG_READS
-fprintf(stderr, "reading from %lu to %lu, overlap %u\n", lSector, lSector + SectorBurst -1, global.overlap);
-#endif
-
-#ifdef DEBUG_BUFFER_ADDRESSES
-fprintf(stderr, "%p %l\n", p->data, global.pagesize);
-if (((unsigned)p->data) & (global.pagesize -1) != 0) {
-  fprintf(stderr, "Address %p is NOT page aligned!!\n", p->data);
-}
-#endif
-
-			if (global.reads_illleadout != 0 && lSector > Get_StartSector(LastTrack())) {
-				int singles = 0;
-				UINT4 bufferSub[CD_FRAMESAMPLES + 24];
-
-				/* we switch to single sector reads,
-				 * in order to handle the remaining sectors. */
-				usalp->silent++;
-				do {
-					int retval2 = ReadCdRomSub( usalp, bufferSub, lSector+singles, 1 );
-					*eorecording = RealEnd( usalp, bufferSub );
-					if (*eorecording) {
-						break;
-					}
-					memcpy(p->data+singles*CD_FRAMESAMPLES, bufferSub, CD_FRAMESIZE_RAW);
-					singles++;
-				} while (singles < SectorBurst);
-				usalp->silent--;
-
-				if ( *eorecording ) {
-					patch_real_end(lSector+singles);
-					SectorBurst = singles;
-#if	DEBUG_ILLLEADOUT
-fprintf(stderr, "iloop=%11lu, nSamplesToDo=%11lu, end=%lu -->\n",
-global.iloop, *nSamplesToDo, lSector+singles);
-#endif
-
-					*nSamplesToDo -= global.iloop - SectorBurst*CD_FRAMESAMPLES;
-					global.iloop = SectorBurst*CD_FRAMESAMPLES;
-#if	DEBUG_ILLLEADOUT
-fprintf(stderr, "iloop=%11lu, nSamplesToDo=%11lu\n\n",
-global.iloop, *nSamplesToDo);
-#endif
-
-				}
-			} else {
-				retval = ReadCdRom( usalp, p->data, lSector, SectorBurst );
-			}
-			handle_inputendianess(p->data, SectorBurst * CD_FRAMESAMPLES);
-			if (NULL ==
-				(newbuf = synchronize( p->data, SectorBurst*CD_FRAMESAMPLES,
-                			*nSamplesToDo-global.iloop ))) {
-				/* could not synchronize!
-				 * Try to invalidate the cdrom cache.
-				 * Increase overlap setting, if possible.
-				 */	
-				/*trash_cache(p->data, lSector, SectorBurst);*/
-				if (global.overlap < global.nsectors - 1) {
-					global.overlap++;
-					lSector--;
-					SectorBurst = calc_SectorBurst();
-#ifdef DEBUG_DYN_OVERLAP
-fprintf(stderr, "using increased overlap of %u\n", global.overlap);
-#endif
-				} else {
-					lSector += global.overlap - 1;
-					global.overlap = 1;
-					SectorBurst =  calc_SectorBurst();
-				}
-			} else
-				break;
-		} while (++retry_count < MAX_READRETRY);
-
-		if (retry_count == MAX_READRETRY && newbuf == NULL && global.verbose != 0) {
-			(*total_unsuccessful_retries)++;
-		}
-
-		if (newbuf) {
-			offset = newbuf - ((unsigned char *)p->data);
-		} else {
-			offset = global.overlap * CD_FRAMESIZE_RAW;
-		}
-		set_offset(p,offset);
-
-		/* how much has been added? */
-		added_size = SectorBurst * CD_FRAMESAMPLES - offset/4;
-
-		if (newbuf && *nSamplesToDo != global.iloop) {
-			minover = min(global.overlap, minover);
-			maxover = max(global.overlap, maxover);
-
-
-			/* should we reduce the overlap setting ? */
-			if (offset > CD_FRAMESIZE_RAW && global.overlap > 1) {
-#ifdef DEBUG_DYN_OVERLAP
-fprintf(stderr, "decreasing overlap from %u to %u (jitter %d)\n", global.overlap, global.overlap-1, offset - (global.overlap)*CD_FRAMESIZE_RAW);
-#endif
-				global.overlap--;
-				SectorBurst =  calc_SectorBurst();
-			}
-		}
-	}
-	if (global.iloop >= added_size) {
-		global.iloop -= added_size;
-	} else {
-		global.iloop = 0;
-	}
-
-	lSector += SectorBurst - global.overlap;
-
-#if	defined	PERCENTAGE_PER_TRACK && defined HAVE_FORK_AND_SHAREDMEM
-	{
-		int as;
-		while ((as = Get_StartSector(current_track+1)) != -1
-			&& lSector >= as) {
-			current_track++;
-		}
-	}
-#endif
-
-	return offset;
-}
-
-static void
-print_percentage(unsigned *poper, int c_offset);
-
-static void print_percentage(unsigned *poper, int c_offset)
-{
-	unsigned per;
-#ifdef	PERCENTAGE_PER_TRACK
-	/* Thomas Niederreiter wants percentage per track */
-	unsigned start_in_track = max(BeginAtSample,
-		Get_AudioStartSector(current_track)*CD_FRAMESAMPLES);
-
-	per = min(BeginAtSample + (long)*nSamplesToDo,
-		Get_StartSector(current_track+1)*CD_FRAMESAMPLES)
-		- (long)start_in_track;
-
-	per = (BeginAtSample+nSamplesDone
-		- start_in_track
-		)/(per/100);
-
-#else
-	per = global.iloop ? (nSamplesDone)/(*nSamplesToDo/100) : 100;
-#endif
-
-	if (global.overlap > 0) {
-		fprintf(stderr, "\r%2d/%2d/%2d/%7d %3d%%",
-			minover, maxover, global.overlap,
-			c_offset - global.overlap*CD_FRAMESIZE_RAW,
-			per);
-	} else if (*poper != per) {
-		fprintf(stderr, "\r%3d%%", per);
-	}
-	*poper = per;
-	fflush(stderr);
-}
-
-static unsigned long do_write(myringbuff *p);
-static unsigned long do_write(myringbuff *p)
-{
-	int current_offset;
-	unsigned int InSamples;
-	static unsigned oper = 200;
-
-	current_offset = get_offset(p);
-
-	/* how many bytes are available? */
-	InSamples = global.nsectors*CD_FRAMESAMPLES - current_offset/4;
-	/* how many samples are wanted? */
-	InSamples = min((*nSamplesToDo-nSamplesDone),InSamples);
-
-	/* when track end is reached, close current file and start a new one */
-	while ((nSamplesDone < *nSamplesToDo) && (InSamples != 0)) {
-		long unsigned int how_much = InSamples;
-
-		long int left_in_track;
-		left_in_track  = Get_StartSector(current_track+1)*CD_FRAMESAMPLES
-				 - (int)(BeginAtSample+nSamplesDone);
-
-		if (*eorecording != 0 && current_track == cdtracks+1 &&
-       		    (*total_segments_read) == (*total_segments_written)+1) {
-			/* limit, if the actual end of the last track is
-			 * not known from the toc. */
-			left_in_track = InSamples;
-		}
-
-if (left_in_track < 0) {
-	fprintf(stderr, "internal error: negative left_in_track:%ld, current_track=%d\n",left_in_track, current_track);
-}
-
-		if (bulk) {
-			how_much = min(how_much, (unsigned long) left_in_track);
-		}
-
-#ifdef MD5_SIGNATURES
-		if (global.md5count) {
-			MD5Update (&global.context, ((unsigned char *)p->data) +current_offset, min(global.md5count,how_much));
-			global.md5count -= min(global.md5count,how_much);
-		}
-#endif
-		if ( SaveBuffer ( p->data + current_offset/4,
-			 how_much,
-			 &nSamplesDone) ) {
-			if (global.have_forked == 1) {
-				pid_t	ppid;
-				/*
-				 * Kill the parent too if we are not orphaned.
-				 */
-				ppid = getppid();
-				if (ppid > 1)
-					kill(ppid, SIGINT);
-			}
-			exit(WRITE_ERROR);
-		}
-
-		global.nSamplesDoneInTrack += how_much;
-		SamplesToWrite -= how_much;
-
-		/* move residual samples upto buffer start */
-		if (how_much < InSamples) {
-			memmove(
-			  (char *)(p->data) + current_offset,
-			  (char *)(p->data) + current_offset + how_much*4,
-			  (InSamples - how_much) * 4);
-		}
-
-		if ((unsigned long) left_in_track <= InSamples || SamplesToWrite == 0) {
-			/* the current portion to be handled is 
-			   the end of a track */
-
-			if (bulk) {
-				/* finish sample file for this track */
-				CloseAudio(global.channels,
-				  global.nSamplesDoneInTrack, global.audio_out);
-			} else if (SamplesToWrite == 0) {
-				/* finish sample file for this track */
-				CloseAudio(global.channels,
-				  (unsigned int) *nSamplesToDo, global.audio_out);
-			}
-
-			if (global.verbose) {
-#ifdef	USE_PARANOIA
-				double	f;
-#endif
-				print_percentage(&oper, current_offset);
-				fputc(' ', stderr);
-#ifndef	THOMAS_SCHAU_MAL
-				if ((unsigned long)left_in_track > InSamples) {
-					fputs(" incomplete", stderr);
-				}
-#endif
-				if (global.tracktitle[current_track] != NULL) {
-					fprintf( stderr,
-						" track %2u '%s' recorded", 
-						current_track,
-						global.tracktitle[current_track]);
-				} else {
-					fprintf( stderr,
-						" track %2u recorded",
-						current_track);
-				}
-#ifdef	USE_PARANOIA
-				oper = para_stat->readerrs + para_stat->skips +
-					  para_stat->fixup_edges + para_stat->fixup_atoms + 
-					  para_stat->fixup_droppeds + para_stat->fixup_dupeds + 
-					  para_stat->drifts;
-				f = (100.0 * oper) / (((double)global.nSamplesDoneInTrack)/588.0);
-
-				if (para_stat->readerrs) {
-					fprintf(stderr, " with audible hard errors");
-				} else if ((para_stat->skips) > 0) {
-					fprintf(stderr, " with %sretry/skip errors",
-							f < 2.0 ? "":"audible ");
-				} else if (oper > 0) {
-					oper = f;
-					
-					fprintf(stderr, " with ");
-					if (oper < 2)
-						fprintf(stderr, "minor");
-					else if (oper < 10)
-						fprintf(stderr, "medium");
-					else if (oper < 67)
-						fprintf(stderr, "noticable audible");
-					else if (oper < 100)
-						fprintf(stderr, "major audible");
-					else
-						fprintf(stderr, "extreme audible");
-					fprintf(stderr, " problems");
-				} else {
-					fprintf(stderr, " successfully");
-				}
-				if (f >= 0.1)
-					fprintf(stderr, " (%.1f%% problem sectors)", f);
-#else
-				fprintf(stderr, " successfully");
-#endif
-
-				if (waitforsignal == 1) {
-					fprintf(stderr, ". %d silent samples omitted", global.SkippedSamples);
-				}
-				fputs("\n", stderr);
-
-				if (global.reads_illleadout && *eorecording == 1) {
-					fprintf(stderr, "Real lead out at: %ld sectors\n", 
-					  (*nSamplesToDo+BeginAtSample)/CD_FRAMESAMPLES);
-				}
-#ifdef	USE_PARANOIA
-				if (global.paranoia_selected) {
-					oper = 200;	/* force new output */
-					print_percentage(&oper, current_offset);
-					if (para_stat->minoverlap == 0x7FFFFFFF)
-						para_stat->minoverlap = 0;
-					fprintf(stderr, "  %u rderr, %u skip, %u atom, %u edge, %u drop, %u dup, %u drift\n"
-						,para_stat->readerrs
-						,para_stat->skips
-						,para_stat->fixup_atoms
-						,para_stat->fixup_edges
-						,para_stat->fixup_droppeds
-						,para_stat->fixup_dupeds
-						,para_stat->drifts);
-					oper = 200;	/* force new output */
-					print_percentage(&oper, current_offset);
-					fprintf(stderr, "  %u overlap(%.4g .. %.4g)\n",
-						para_stat->overlaps,
-						(float)para_stat->minoverlap / (2352.0/2.0),
-						(float)para_stat->maxoverlap / (2352.0/2.0));
-					paranoia_reset();
-				}
-#endif
-			}
-
-			global.nSamplesDoneInTrack = 0;
-			if ( bulk && SamplesToWrite > 0 ) {
-				if ( !global.no_file ) {
-					char *tmp_fname;
-
-					/* build next filename */
-					tmp_fname = get_next_name();
-					if (tmp_fname != NULL) {
-						strncpy(global.fname_base,
-							tmp_fname,
-							sizeof global.fname_base);
-						global.fname_base[
-							sizeof(global.fname_base)-1] =
-							'\0';
-					}
-
-					tmp_fname = cut_extension(global.fname_base);
-					tmp_fname[0] = '\0';
-
-					if (global.multiname == 0) {
-						sprintf(fname, "%s_%02u.%s",
-							global.fname_base,
-							current_track+1,
-							audio_type);
-					} else {
-						sprintf(fname, "%s.%s",
-							global.fname_base,
-							audio_type);
-					}
-
-					OpenAudio( fname, rate, bits, global.channels,
-						(Get_AudioStartSector(current_track+1) -
-						 Get_AudioStartSector(current_track))
-							*CD_FRAMESIZE_RAW,
-						global.audio_out);
-				} /* global.nofile */
-			} /* if ( bulk && SamplesToWrite > 0 ) */
-			current_track++;
-
-		} /* left_in_track <= InSamples */
-		InSamples -= how_much;
-
-	}  /* end while */
-	if (!global.quiet && *nSamplesToDo != nSamplesDone) {
-		print_percentage(&oper, current_offset);
-	}
-	return nSamplesDone;
-}
-
-#define PRINT_OVERLAP_INIT \
-   if (global.verbose) { \
-	if (global.overlap > 0) \
-		fprintf(stderr, "overlap:min/max/cur, jitter, percent_done:\n  /  /  /          0%%"); \
-	else \
-		fputs("percent_done:\n  0%", stderr); \
-   }
-
-#if defined HAVE_FORK_AND_SHAREDMEM
-static void forked_read(void);
-
-/* This function does all audio cdrom reads
- * until there is nothing more to do
- */
-static void forked_read()
-{
-   unsigned total_unsuccessful_retries = 0;
-
-#if !defined(HAVE_SEMGET) || !defined(USE_SEMAPHORES)
-   init_child();
-#endif
-
-   minover = global.nsectors;
-
-   PRINT_OVERLAP_INIT
-   while (global.iloop) { 
-
-      do_read(get_next_buffer(), &total_unsuccessful_retries);
-
-      define_buffer();
-
-   } /* while (global.iloop) */
-
-   if (total_unsuccessful_retries) {
-      fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries);
-   }
-}
-
-static void forked_write(void);
-
-static void forked_write()
-{
-
-    /* don't need these anymore.  Good security policy says we get rid
-       of them ASAP */
-	priv_off();
-	neverneedroot();
-	neverneedgroup();
-
-#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
-#else
-    init_parent();
-#endif
-
-    for (;nSamplesDone < *nSamplesToDo;) {
-	if (*eorecording == 1 && (*total_segments_read) == (*total_segments_written)) break;
-
-	/* get oldest buffers */
-      
-	nSamplesDone = do_write(get_oldest_buffer());
-
-        drop_buffer();
-
-    } /* end for */
-
-}
-#endif
-
-/* This function implements the read and write calls in one loop (in case
- * there is no fork/thread_create system call).
- * This means reads and writes have to wait for each other to complete.
- */
-static void nonforked_loop(void);
-
-static void nonforked_loop()
-{
-    unsigned total_unsuccessful_retries = 0;
-
-    minover = global.nsectors;
-
-    PRINT_OVERLAP_INIT
-    while (global.iloop) { 
-
-      do_read(get_next_buffer(), &total_unsuccessful_retries);
-
-      do_write(get_oldest_buffer());
-
-    }
-
-    if (total_unsuccessful_retries) {
-      fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries);
-    }
-
-}
-
-void verbose_usage(void);
-
-void verbose_usage()
-{
-	fputs("\
-	help		lists all verbose options.\n\
-	disable		disables verbose mode.\n\
-	all		enables all verbose options.\n\
-	toc		display the table of contents.\n\
-	summary		display a summary of track parameters.\n\
-	indices		retrieve/display index positions.\n\
-	catalog		retrieve/display media catalog number.\n\
-	trackid		retrieve/display international standard recording code.\n\
-	sectors		display the start sectors of each track.\n\
-	titles		display any known track titles.\n\
-", stderr);
-}
-
-#ifdef	USE_PARANOIA
-void paranoia_usage(void);
-
-void paranoia_usage()
-{
-	fputs("\
-	help		lists all paranoia options.\n\
-	disable		disables paranoia mode. Paranoia is still being used.\n\
-	no-verify	switches verify off, and overlap on.\n\
-	retries=amount	set the number of maximum retries per sector.\n\
-	overlap=amount	set the number of sectors used for statical paranoia overlap.\n\
-	minoverlap=amt	set the min. number of sectors used for dynamic paranoia overlap.\n\
-	maxoverlap=amt	set the max. number of sectors used for dynamic paranoia overlap.\n\
-", stderr);
-}
-#endif
-
-int
-handle_verbose_opts(char *optstr, long *flagp);
-
-int handle_verbose_opts(char *optstr, long *flagp)
-{
-	char	*ep;
-	char	*np;
-	int	optlen;
-
-	*flagp = 0;
-	while (*optstr) {
-		if ((ep = strchr(optstr, ',')) != NULL) {
-			optlen = ep - optstr;
-			np = ep + 1;
-		} else {
-			optlen = strlen(optstr);
-			np = optstr + optlen;
-		}
-		if (strncmp(optstr, "toc", optlen) == 0) {
-			*flagp |= SHOW_TOC;
-		}
-		else if (strncmp(optstr, "summary", optlen) == 0) {
-			*flagp |= SHOW_SUMMARY;
-		}
-		else if (strncmp(optstr, "indices", optlen) == 0) {
-			*flagp |= SHOW_INDICES;
-		}
-		else if (strncmp(optstr, "catalog", optlen) == 0) {
-			*flagp |= SHOW_MCN;
-		}
-		else if (strncmp(optstr, "trackid", optlen) == 0) {
-			*flagp |= SHOW_ISRC;
-		}
-		else if (strncmp(optstr, "sectors", optlen) == 0) {
-			*flagp |= SHOW_STARTPOSITIONS;
-		}
-		else if (strncmp(optstr, "titles", optlen) == 0) {
-			*flagp |= SHOW_TITLES;
-		}
-		else if (strncmp(optstr, "all", optlen) == 0) {
-			*flagp |= SHOW_MAX;
-		}
-		else if (strncmp(optstr, "disable", optlen) == 0) {
-			*flagp = 0;
-		}
-		else if (strncmp(optstr, "help", optlen) == 0) {
-			verbose_usage();
-			exit(NO_ERROR);
-		}
-		else {
-			char	*endptr;
-			unsigned arg = strtoul(optstr, &endptr, 10);
-			if (optstr != endptr
-				&& arg <= SHOW_MAX) {
-				*flagp |= arg;
-				fprintf(stderr, "Warning: numerical parameters for -v are no more supported in the next releases!\n");
-			}
-			else {
-				fprintf(stderr, "unknown option %s\n", optstr);
-				verbose_usage();
-				exit(SYNTAX_ERROR);
-			}
-		}
-		optstr = np;
-	}
-	return 1;
-}
-
-
-int
-handle_paranoia_opts(char *optstr, long *flagp);
-
-int handle_paranoia_opts(char *optstr, long *flagp)
-{
-#ifdef	USE_PARANOIA
-	char	*ep;
-	char	*np;
-	int	optlen;
-
-	while (*optstr) {
-		if ((ep = strchr(optstr, ',')) != NULL) {
-			optlen = ep - optstr;
-			np = ep + 1;
-		} else {
-			optlen = strlen(optstr);
-			np = optstr + optlen;
-		}
-		if (strncmp(optstr, "retries=", min(8,optlen)) == 0) {
-			char *eqp = strchr(optstr, '=');
-			int   rets;
-
-			astoi(eqp+1, &rets);
-			if (rets >= 0) {
-				global.paranoia_parms.retries = rets;
-			}
-		}
-		else if (strncmp(optstr, "overlap=", min(8, optlen)) == 0) {
-			char *eqp = strchr(optstr, '=');
-			int   rets;
-
-			astoi(eqp+1, &rets);
-			if (rets >= 0) {
-				global.paranoia_parms.overlap = rets;
-			}
-		}
-		else if (strncmp(optstr, "minoverlap=", min(11, optlen)) == 0) {
-			char *eqp = strchr(optstr, '=');
-			int   rets;
-
-			astoi(eqp+1, &rets);
-			if (rets >= 0) {
-				global.paranoia_parms.mindynoverlap = rets;
-			}
-		}
-		else if (strncmp(optstr, "maxoverlap=", min(11, optlen)) == 0) {
-			char *eqp = strchr(optstr, '=');
-			int   rets;
-
-			astoi(eqp+1, &rets);
-			if (rets >= 0) {
-				global.paranoia_parms.maxdynoverlap = rets;
-			}
-		}
-		else if (strncmp(optstr, "no-verify", optlen) == 0) {
-			global.paranoia_parms.disable_extra_paranoia = 1;
-		}
-		else if (strncmp(optstr, "disable", optlen) == 0) {
-			global.paranoia_parms.disable_paranoia = 1;
-		}
-		else if (strncmp(optstr, "help", optlen) == 0) {
-			paranoia_usage();
-			exit(NO_ERROR);
-		}
-		else {
-			fprintf(stderr, "unknown option %s\n", optstr);
-			paranoia_usage();
-			exit(SYNTAX_ERROR);
-		}
-		optstr = np;
-	}
-	return 1;
-#else
-	fputs("lib paranoia support is not configured!\n", stderr);
-	return 0;
-#endif
-}
-
-
-/* and finally: the MAIN program */
-int main(int argc, char *argv[])
-{
-  long lSector_p1;
-  long sector_offset = 0;
-  unsigned long endtrack = 1;
-  double rectime = DURATION;
-  int cd_index = -1;
-  double int_part;
-  int littleendian = -1;
-  char *int_name;
-  static char *user_sound_device = "";
-  char * env_p;
-  int tracks_included;
-	int	moreargs;
-
-  int_name = DEF_INTERFACE;
-  audio_type = AUDIOTYPE;
-  save_args(argc, argv);
-
-  /* init global variables */
-  init_globals();
-{
-  int am_i_cdda2wav;
-  /* When being invoked as list_audio_tracks, just dump a list of
-     audio tracks. */
-  am_i_cdda2wav = !(strlen(argv[0]) >= sizeof("list_audio_tracks")-1
-	&& !strcmp(argv[0]+strlen(argv[0])+1-sizeof("list_audio_tracks"),"list_audio_tracks"));
-  if (!am_i_cdda2wav) global.verbose = SHOW_JUSTAUDIOTRACKS;
-}
-  /* Control those set-id privileges... */
-  initsecurity();
-
-  env_p = getenv("CDDA_DEVICE");
-  if (env_p != NULL) {
-    global.dev_name = env_p;
-  }
-
-  env_p = getenv("CDDBP_SERVER");
-  if (env_p != NULL) {
-    global.cddbp_server = env_p;
-  }
-
-  env_p = getenv("CDDBP_PORT");
-  if (env_p != NULL) {
-    global.cddbp_port = env_p;
-  }
-
-{
-	int	cac;
-	char	*const*cav;
-
-	BOOL	version = FALSE;
-	BOOL	help = FALSE;
-	char	*channels = NULL;
-	int	irate = -1;
-	char	*divider = NULL;
-	char	*trackspec = NULL;
-	char	*duration = NULL;
-
-	char	*oendianess = NULL;
-	char	*cendianess = NULL;
-	int	cddbp = -1;
-	BOOL	stereo = FALSE;
-	BOOL	mono = FALSE;
-	BOOL	domax = FALSE;
-	BOOL	dump_rates = FALSE;
-	int	userverbose = -1;
-	long	paraopts = 0;
-
-	cac = argc;
-	cav = argv;
-	cac--;
-	cav++;
-	if (getargs(&cac, &cav, opts
-			, &global.paranoia_selected
-			, handle_paranoia_opts, &paraopts
-			, &version
-			, &help, &help
-
-			, &global.no_file, &global.no_file
-			, &dump_rates, &dump_rates
-			, &bulk, &bulk, &bulk
-			, &global.scsi_verbose, &global.scsi_verbose
-
-			, &global.findminmax, &global.findminmax
-			, &global.findmono, &global.findmono
-			, &global.no_infofile, &global.no_infofile
-
-			, &global.deemphasize, &global.deemphasize
-			, &global.just_the_toc, &global.just_the_toc
-			, &global.scsi_silent, &global.scsi_silent
-
-			, &global.cddbp_server, &global.cddbp_port
-			, &global.scanbus
-			, &global.dev_name, &global.dev_name, &global.dev_name
-			, &global.aux_name, &global.aux_name
-			, &int_name, &int_name
-			, &audio_type, &audio_type
-
-			, &oendianess, &oendianess
-			, &cendianess, &cendianess
-			, &global.userspeed, &global.userspeed
-
-			, &global.playback_rate, &global.playback_rate
-			, &global.md5blocksize, &global.md5blocksize
-			, &global.useroverlap, &global.useroverlap
-			, &user_sound_device, &user_sound_device
-
-			, &cddbp, &cddbp
-			, &channels, &channels
-			, &bits, &bits
-			, &irate, &irate
-			, &global.gui, &global.gui
-
-			, &divider, &divider
-			, &trackspec, &trackspec
-			, &cd_index, &cd_index
-			, &duration, &duration
-			, &sector_offset, &sector_offset
-
-			, &global.nsectors, &global.nsectors
-			, handle_verbose_opts, &userverbose
-			, handle_verbose_opts, &userverbose
-			, &global.buffers, &global.buffers
-
-			, &stereo, &stereo
-			, &mono, &mono
-			, &waitforsignal, &waitforsignal
-			, &global.echo, &global.echo
-			, &global.quiet, &global.quiet
-			, &domax, &domax
-
-			) < 0) {
-		errmsgno(EX_BAD, "Bad Option: %s.\n", cav[0]);
-		fputs ("use 'cdda2wav -help' to get more information.\n", stderr);
-		exit (SYNTAX_ERROR);
-	}
-	if (getfiles(&cac, &cav, opts) == 0)
-		/* No more file type arguments */;
-	moreargs = cav - argv;
-	if (version) {
-		fputs ("cdda2wav version ", stderr);
-		fputs (VERSION, stderr);
-		fputs ("\n"
-          "NOTE: modified version of the cdrkit suite, differs from the original\n", stderr);
-		exit (NO_ERROR);
-	}
-	if (help) {
-		usage();
-	}
-	if (!global.scanbus)
-		cdr_defaults(&global.dev_name, NULL, NULL, NULL); 
-	if (dump_rates) {	/* list available rates */
-		int ii;
-
-		fputs("\
-Available rates are:\n\
-Rate   Divider      Rate   Divider      Rate   Divider      Rate   Divider\n\
-"			, stderr );
-		for (ii = 1; ii <= 44100 / 880 / 2; ii++) {
-			long i2 = ii;
-			fprintf(stderr, "%7.1f  %2ld         %7.1f  %2ld.5       ",
-	        		44100.0/i2, i2, 44100.0/(i2+0.5), i2);
-			i2 += 25;
-			fprintf(stderr, "%7.1f  %2ld         %7.1f  %2ld.5\n",
-        			44100.0/i2, i2, 44100.0/(i2+0.5), i2);
-			i2 -= 25;
-		}
-		exit(NO_ERROR);
-	}
-	if (channels) {
-		if (*channels == 's') {
-			global.channels = 2;
-			global.swapchannels = 1;
-		} else {
-			global.channels = strtol(channels, NULL, 10);
-		}
-	}
-	if (irate >= 0) {
-		rate = irate;
-	}
-	if (divider) {
-		double divider_d;
-		divider_d = strtod(divider , NULL);
-		if (divider_d > 0.0) {
-			rate = 44100.0 / divider_d;
-		} else {
-			fputs("E option -divider requires a nonzero, positive argument.\nSee -dump-rates.", stderr);
-			exit(SYNTAX_ERROR);
-		}
-	}
-	if (trackspec) {
-		char * endptr;
-		char * endptr2;
-		track = strtoul(trackspec, &endptr, 10 );
-		endtrack = strtoul(endptr, &endptr2, 10 );
-		if (endptr2 == endptr) {
-			endtrack = track;
-		} else if (track == endtrack) {
-			bulk = -1;
-		}
-	}
-	if (duration) {
-		char *end_ptr = NULL;
-		rectime = strtod(duration, &end_ptr );
-		if (*end_ptr == 'f') {
-			rectime = rectime / 75.0;
-			/* TODO: add an absolute end of recording. */
-#if	0
-		} else if (*end_ptr == 'F') {
-			rectime = rectime / 75.0;
-#endif
-		} else if (*end_ptr != '\0') {
-			rectime = -1.0;
-		}
-	}
-	if (oendianess) {
-		if (strcasecmp(oendianess, "little") == 0) {
-			global.outputendianess = LITTLE;
-		} else if (strcasecmp(oendianess, "big") == 0) {
-			global.outputendianess = BIG;
-		} else {
-			usage2("wrong parameter '%s' for option -E", oendianess);
-		}
-	}
-	if (cendianess) {
-		if (strcasecmp(cendianess, "little") == 0) {
-			littleendian = 1;
-		} else if (strcasecmp(cendianess, "big") == 0) {
-			littleendian = 0;
-		} else if (strcasecmp(cendianess, "guess") == 0) {
-			littleendian = -2;
-		} else {
-			usage2("wrong parameter '%s' for option -C", cendianess);
-		}
-	}
-	if (cddbp >= 0) {
-		global.cddbp = 1 + cddbp;
-	}
-	if (stereo) {
-		global.channels = 2;
-	}
-	if (mono) {
-		global.channels = 1;
-        	global.need_hostorder = 1;
-	}
-	if (global.echo) {
-#ifdef	ECHO_TO_SOUNDCARD
-		if (global.playback_rate != 100) {
-		        RestrictPlaybackRate( global.playback_rate );
-		}
-       		global.need_hostorder = 1;
-#else
-		fprintf(stderr, "There is no sound support compiled into %s.\n",argv[0]);
-		global.echo = 0;
-#endif
-	}
-	if (global.quiet) {
-		global.verbose = 0;
-	}
-	if (domax) {
-		global.channels = 2; bits = 16; rate = 44100;
-	}
-	if (global.findminmax) {
-	        global.need_hostorder = 1;
-	}
-	if (global.deemphasize) {
-	        global.need_hostorder = 1;
-	}
-	if (global.just_the_toc) {
-		global.verbose = SHOW_MAX;
-		bulk = 1;
-	}
-	if (global.gui) {
-#ifdef	Thomas_will_es
-		global.no_file = 1;
-		global.no_infofile = 1;
-		global.verbose = SHOW_MAX;
-#endif
-		global.no_cddbfile = 1;
-	}
-	if (global.no_file) {
-		global.no_infofile = 1;
-		global.no_cddbfile = 1;
-	}
-	if (global.no_infofile) {
-		global.no_cddbfile = 1;
-	}
-	if (global.md5blocksize) {
-#ifdef	MD5_SIGNATURES
-		fputs("MD5 signatures are currently broken! Sorry\n", stderr);
-#else
-		fputs("The option MD5 signatures is not configured!\n", stderr);
-#endif
-	}
-	if (user_sound_device) {
-#ifndef	ECHO_TO_SOUNDCARD
-		fputs("There is no sound support configured!\n", stderr);
-#endif
-	}
-	if (global.paranoia_selected) {
-		global.useroverlap = 0;
-	}
-	if (userverbose >= 0) {
-		global.verbose = userverbose;
-	}
-}
-
-  /* check all parameters */
-  if (global.buffers < 1) {
-    usage2("Incorrect buffer setting: %d", global.buffers);
-  }
-
-  if (global.nsectors < 1) {
-    usage2("Incorrect nsectors setting: %d", global.nsectors);
-  }
-
-  if (global.verbose < 0 || global.verbose > SHOW_MAX) {
-    usage2("Incorrect verbose level setting: %d",global.verbose);
-  }
-  if (global.verbose == 0) global.quiet = 1;
-
-  if ( rectime < 0.0 ) {
-    usage2("Incorrect recording time setting: %d.%02d",
-			(int)rectime, (int)(rectime*100+0.5) % 100);
-  }
-
-  if ( global.channels != 1 && global.channels != 2 ) {
-    usage2("Incorrect channel setting: %d",global.channels);
-  }
-
-  if ( bits != 8 && bits != 12 && bits != 16 ) {
-    usage2("Incorrect bits_per_sample setting: %d",bits);
-  }
-
-  if ( rate < 827.0 || rate > 44100.0 ) {
-    usage2("Incorrect sample rate setting: %d.%02d",
-	(int)rate, ((int)rate*100) % 100);
-  }
-
-  int_part = (double)(long) (2*44100.0 / rate);
-  
-  if (2*44100.0 / rate - int_part >= 0.5 ) {
-      int_part += 1.0;
-      fprintf( stderr, "Nearest available sample rate is %d.%02d Hertz\n",
-	      2*44100 / (int)int_part,
-	      (2*4410000 / (int)int_part) % 100);
-  }
-  Halved = ((int) int_part) & 1;
-  rate = 2*44100.0 / int_part;
-  undersampling = (int) int_part / 2.0;
-  samples_to_do = undersampling;
-
-  if (!strcmp((char *)int_name,"generic_scsi"))
-      interface = GENERIC_SCSI;
-  else if (!strcmp((char *)int_name,"cooked_ioctl"))
-      interface = COOKED_IOCTL;
-  else  {
-    usage2("Incorrect interface setting: %s",int_name);
-  }
-
-  /* check * init audio file */
-  if (!strncmp(audio_type,"wav",3)) {
-    global.audio_out = &wavsound;
-  } else if (!strncmp(audio_type, "sun", 3) || !strncmp(audio_type, "au", 2)) {
-    /* Enhanced compatibility */
-    audio_type = "au";
-    global.audio_out = &sunsound;
-  } else if (!strncmp(audio_type, "cdr", 3) || 
-             !strncmp(audio_type, "raw", 3)) {
-    global.audio_out = &rawsound;
-  } else if (!strncmp(audio_type, "aiff", 4)) {
-    global.audio_out = &aiffsound;
-  } else if (!strncmp(audio_type, "aifc", 4)) {
-    global.audio_out = &aifcsound;
-#ifdef USE_LAME
-  } else if (!strncmp(audio_type, "mp3", 3)) {
-    global.audio_out = &mp3sound;
-    if (!global.quiet) {
-	unsigned char Lame_version[20];
-
-	fetch_lame_version(Lame_version);
-	fprintf(stderr, "Using LAME version %s.\n", Lame_version);
-    }
-    if (bits < 9) {
-	bits = 16;
-	fprintf(stderr, "Warning: sample size forced to 16 bit for MP3 format.\n");
-    }
-#endif /* USE_LAME */
-  } else {
-    usage2("Incorrect audio type setting: %3s", audio_type);
-  }
-
-  if (bulk == -1) bulk = 0;
-
-  global.need_big_endian = global.audio_out->need_big_endian;
-  if (global.outputendianess != NONE)
-    global.need_big_endian = global.outputendianess == BIG;
-
-  if (global.no_file) global.fname_base[0] = '\0';
-
-  if (!bulk) {
-    strcat(global.fname_base, ".");
-    strcat(global.fname_base, audio_type);
-  }
-
-  /* If we need to calculate with samples or write them to a soundcard,
-   * we need a conversion to host byte order.
-   */ 
-  if (global.channels != 2 
-      || bits != 16
-      || rate != 44100)
-	global.need_hostorder = 1;
-
-  /* Bad hack!!
-   * Remove for release 2.0
-   * this is a bug compatibility feature.
-   */
-  if (global.gui && global.verbose == SHOW_TOC)
-	global.verbose |= SHOW_STARTPOSITIONS | SHOW_SUMMARY | SHOW_TITLES;
-
-  /*
-   * all options processed.
-   * Now a file name per track may follow 
-   */
-  argc2 = argc3 = argc - moreargs;
-  argv2 = argv + moreargs;
-  if ( moreargs < argc ) {
-    if (!strcmp(argv[moreargs],"-")) {
-#ifdef	NEED_O_BINARY
-      setmode(fileno(stdout), O_BINARY);
-#endif
-      global.audio = dup (fileno(stdout));
-      strncpy( global.fname_base, "standard_output", sizeof(global.fname_base) );
-      global.fname_base[sizeof(global.fname_base)-1]=0;
-    } else if (!is_fifo(argv[moreargs])) {
-	/* we do have at least one argument */
-	global.multiname = 1;
-    }
-  }
-
-#define SETSIGHAND(PROC, SIG, SIGNAME) if (signal(SIG, PROC) == SIG_ERR) \
-	{ fprintf(stderr, "cannot set signal %s handler\n", SIGNAME); exit(SETSIG_ERROR); }
-    SETSIGHAND(exit_wrapper, SIGINT, "SIGINT")
-    SETSIGHAND(exit_wrapper, SIGQUIT, "SIGQUIT")
-    SETSIGHAND(exit_wrapper, SIGTERM, "SIGTERM")
-    SETSIGHAND(exit_wrapper, SIGHUP, "SIGHUP")
-
-    SETSIGHAND(set_nonforked, SIGPIPE, "SIGPIPE")
-
-  /* setup interface and open cdrom device */
-  /* request sychronization facilities and shared memory */
-  SetupInterface( );
-
-  /* use global.useroverlap to set our overlap */
-  if (global.useroverlap != -1)
-	global.overlap = global.useroverlap;
-
-  /* check for more valid option combinations */
-
-  if (global.nsectors < 1+global.overlap) {
-	fprintf( stderr, "Warning: Setting #nsectors to minimum of %d, due to jitter correction!\n", global.overlap+1);
-	  global.nsectors = global.overlap+1;
-  }
-
-  if (global.overlap > 0 && global.buffers < 2) {
-	fprintf( stderr, "Warning: Setting #buffers to minimum of 2, due to jitter correction!\n");
-	  global.buffers = 2;
-  }
-
-    /* Value of 'nsectors' must be defined here */
-
-    global.shmsize = 0;
-#ifdef	USE_PARANOIA
-    while (global.shmsize < sizeof (struct paranoia_statistics))
-		global.shmsize += global.pagesize;
-#endif
-    global.shmsize += 10*global.pagesize;	/* XXX Der Speicherfehler ist nicht in libparanoia sondern in cdda2wav :-( */
-    global.shmsize += HEADER_SIZE + ENTRY_SIZE_PAGE_AL * global.buffers;
-
-#if	defined (HAVE_FORK_AND_SHAREDMEM)
-	/*
-	 * The (void *) cast is to avoid a GCC warning like:
-	 * warning: dereferencing type-punned pointer will break strict-aliasing rules
-	 * which does not apply to this code. (void *) introduces a compatible
-	 * intermediate type in the cast list.
-	 */
-    he_fill_buffer = request_shm_sem(global.shmsize, (unsigned char **)(void *)&he_fill_buffer);
-    if (he_fill_buffer == NULL) {
-	fprintf( stderr, "no shared memory available!\n");
-	exit(SHMMEM_ERROR);
-    }
-#else /* do not have fork() and shared memory */
-    he_fill_buffer = malloc(global.shmsize);
-    if (he_fill_buffer == NULL) {
-	fprintf( stderr, "no buffer memory available!\n");
-	exit(NOMEM_ERROR);
-    }
-#endif
-#ifdef	USE_PARANOIA
-    {
-	int	i = 0;
-
-	para_stat = (struct paranoia_statistics *)he_fill_buffer;
-	while (i < sizeof (struct paranoia_statistics)) {
-			i += global.pagesize;
-			he_fill_buffer += global.pagesize;
-			global.shmsize -= global.pagesize;
-	}
-    }
-#endif
-
-    if (global.verbose != 0)
-   	 fprintf(stderr,
-   		 "%u bytes buffer memory requested, %d buffers, %d sectors\n",
-   		 global.shmsize, global.buffers, global.nsectors);
-
-    /* initialize pointers into shared memory segment */
-    last_buffer = he_fill_buffer + 1;
-    total_segments_read = (unsigned long *) (last_buffer + 1);
-    total_segments_written = total_segments_read + 1;
-    child_waits = (int *) (total_segments_written + 1);
-    parent_waits = child_waits + 1;
-    in_lendian = parent_waits + 1;
-    eorecording = in_lendian + 1;
-    *total_segments_read = *total_segments_written = 0;
-    nSamplesToDo = (unsigned long *)(eorecording + 1);
-    *eorecording = 0;
-    *in_lendian = global.in_lendian;
-
-    set_total_buffers(global.buffers, sem_id);
-
-
-#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
-  atexit ( free_sem );
-#endif
-
-  /*
-   * set input endian default
-   */
-  if (littleendian != -1)
-    *in_lendian = littleendian;
-
-  /* get table of contents */
-  cdtracks = ReadToc();
-  if (cdtracks == 0) {
-    fprintf(stderr, "No track in table of contents! Aborting...\n");
-    exit(MEDIA_ERROR);
-  }
-
-  calc_cddb_id();
-  calc_cdindex_id();
-
-#if	1
-  Check_Toc();
-#endif
-
-  if (ReadTocText != NULL && FirstAudioTrack () != -1) {
-	ReadTocText(get_scsi_p());
-	handle_cdtext();
-  }
-  if ( global.verbose == SHOW_JUSTAUDIOTRACKS ) {
-    unsigned int z;
-
-    for (z = 0; z < cdtracks; z++)
-	if (Get_Datatrack(z) == 0)
-	  printf("%02d\t%06ld\n", Get_Tracknumber(z), Get_AudioStartSector(z));
-    exit(NO_ERROR);
-  }
-
-  if ( global.verbose != 0 ) {
-    fputs( "#Cdda2wav version ", stderr );
-    fputs( VERSION, stderr );
-#if defined USE_POSIX_PRIORITY_SCHEDULING || defined HAVE_SYS_PRIOCNTL_H
-    fputs( ", real time sched.", stderr );
-#endif
-#if defined ECHO_TO_SOUNDCARD
-    fputs( ", soundcard", stderr );
-#endif
-#if defined USE_PARANOIA
-    fputs( ", libparanoia", stderr );
-#endif
-    fputs( " support\n", stderr );
-  }
-
-  FixupTOC(cdtracks + 1);
-
-#if	0
-  if (!global.paranoia_selected) {
-    fprintf(stderr, "NICE\n");
-    /* try to get some extra kicks */
-    priv_on();
-    needroot(0);
-#if defined HAVE_SETPRIORITY
-    setpriority(PRIO_PROCESS, 0, -20);
-#else
-# if defined(HAVE_NICE) && (HAVE_NICE == 1)
-    nice(-20);
-# endif
-#endif
-    priv_off();
-    dontneedroot();
-  }
-#endif
-
-  /* switch cdrom to audio mode */
-  EnableCdda (get_scsi_p(), 1, CD_FRAMESIZE_RAW);
-
-  atexit ( CloseAll );
-
-  DisplayToc();
-  if ( FirstAudioTrack () == -1 ) {
-    if (no_disguised_audiotracks()) {
-      FatalError ( "This disk has no audio tracks\n" );
-    }
-  }
-
-  Read_MCN_ISRC();
-
-  /* check if start track is in range */
-  if ( track < 1 || track > cdtracks ) {
-    usage2("Incorrect start track setting: %d",track);
-  }
-
-  /* check if end track is in range */
-  if ( endtrack < track || endtrack > cdtracks ) {
-    usage2("Incorrect end track setting: %ld",endtrack);
-  }
-
-  do {
-    lSector = Get_AudioStartSector ( track );
-    lSector_p1 = Get_EndSector ( track ) + 1;
-
-    if ( lSector < 0 ) {
-      if ( bulk == 0 ) {
-        FatalError ( "Track %d not found\n", track );
-      } else {
-        fprintf(stderr, "Skipping data track %d...\n", track);
-	if (endtrack == track) endtrack++;
-        track++;
-      }
-    }
-  } while (bulk != 0 && track <= cdtracks && lSector < 0);
-
-  if ((global.illleadout_cd == 0 || global.reads_illleadout != 0) && cd_index != -1) {
-    if (global.verbose && !global.quiet) {
-      global.verbose |= SHOW_INDICES;
-    }
-    sector_offset += ScanIndices( track, cd_index, bulk );
-  } else {
-    cd_index = 1;
-    if (global.deemphasize || (global.verbose & SHOW_INDICES)) {
-      ScanIndices( track, cd_index, bulk );
-    }
-  }
-
-  lSector += sector_offset;
-  /* check against end sector of track */
-  if ( lSector >= lSector_p1 ) {
-    fprintf(stderr, "W Sector offset %lu exceeds track size (ignored)\n", sector_offset );
-    lSector -= sector_offset;
-  }
-
-  if ( lSector < 0L ) {
-    fputs( "Negative start sector! Set to zero.\n", stderr );
-    lSector = 0L;
-  }
-
-  lSector_p2 = Get_LastSectorOnCd( track );
-  if (bulk == 1 && track == endtrack && rectime == 0.0)
-     rectime = 99999.0;
-  if ( rectime == 0.0 ) {
-    /* set time to track time */
-    *nSamplesToDo = (lSector_p1 - lSector) * CD_FRAMESAMPLES;
-    rectime = (lSector_p1 - lSector) / 75.0;
-    if (CheckTrackrange( track, endtrack) == 1) {
-      lSector_p2 = Get_EndSector ( endtrack ) + 1;
-
-      if (lSector_p2 >= 0) {
-        rectime = (lSector_p2 - lSector) / 75.0;
-        *nSamplesToDo = (long)(rectime*44100.0 + 0.5);
-      } else {
-        fputs( "End track is no valid audio track (ignored)\n", stderr );
-      }
-    } else {
-      fputs( "Track range does not consist of audio tracks only (ignored)\n", stderr );
-    }
-  } else {
-    /* Prepare the maximum recording duration.
-     * It is defined as the biggest amount of
-     * adjacent audio sectors beginning with the
-     * specified track/index/offset. */
-
-    if ( rectime > (lSector_p2 - lSector) / 75.0 ) {
-      rectime = (lSector_p2 - lSector) / 75.0;
-      lSector_p1 = lSector_p2;
-    }
-
-    /* calculate # of samples to read */
-    *nSamplesToDo = (long)(rectime*44100.0 + 0.5);
-  }
-
-  global.OutSampleSize = (1+bits/12);
-  if (*nSamplesToDo/undersampling == 0L) {
-      usage2("Time interval is too short. Choose a duration greater than %d.%02d secs!", 
-	       undersampling/44100, (int)(undersampling/44100) % 100);
-  }
-  if ( moreargs < argc ) {
-    if (!strcmp(argv[moreargs],"-") || is_fifo(argv[moreargs])) {
-      /*
-       * pipe mode
-       */
-      if (bulk == 1) {
-        fprintf(stderr, "W Bulk mode is disabled while outputting to a %spipe\n",
-		is_fifo(argv[moreargs]) ? "named " : "");
-        bulk = 0;
-      }
-      global.no_cddbfile = 1;
-    }
-  }
-  if (global.no_infofile == 0) {
-    global.no_infofile = 1;
-    if (global.channels == 1 || bits != 16 || rate != 44100) {
-      fprintf(stderr, "W Sample conversions disable generation of info files!\n");
-    } else if (waitforsignal == 1) {
-      fprintf(stderr, "W Option -w 'wait for signal' disables generation of info files!\n");
-    } else if (sector_offset != 0) {
-      fprintf(stderr, "W Using an start offset (option -o) disables generation of info files!\n");
-    } else if (!bulk &&
-      !((lSector == Get_AudioStartSector(track)) &&
-        ((long)(lSector + rectime*75.0 + 0.5) == Get_EndSector(track) + 1))) {
-      fprintf(stderr, "W Duration is not set for complete tracks (option -d), this disables generation\n  of info files!\n");
-    } else {
-      global.no_infofile = 0;
-    }
-  }
-
-  SamplesToWrite = *nSamplesToDo*2/(int)int_part;
-
-  {
-	int first = FirstAudioTrack();
-	tracks_included = Get_Track(
-	      (unsigned) (lSector + *nSamplesToDo/CD_FRAMESAMPLES -1))
-				     - max((int)track,first) +1;
-  }
-
-  if (global.multiname != 0 && moreargs + tracks_included > argc) {
-	global.multiname = 0;
-  }
-
-  if ( !waitforsignal ) {
-
-#ifdef INFOFILES
-      if (!global.no_infofile) {
-	int i;
-
-	for (i = track; i < (int)track + tracks_included; i++) {
-		unsigned minsec, maxsec;
-	        char *tmp_fname;
-
-	        /* build next filename */
-
-	        tmp_fname = get_next_name();
-	        if (tmp_fname != NULL)
-		  strncpy( global.fname_base, tmp_fname, sizeof(global.fname_base)-8 );
- 		global.fname_base[sizeof(global.fname_base)-1]=0;
-		minsec = max(lSector, Get_AudioStartSector(i));
-		maxsec = min(lSector + rectime*75.0 + 0.5, 1+Get_EndSector(i));
-		if ((int)minsec == Get_AudioStartSector(i) &&
-		    (int)maxsec == 1+Get_EndSector(i)) {
-			write_info_file(global.fname_base,i,(maxsec-minsec)*CD_FRAMESAMPLES, bulk && global.multiname == 0);
-		} else {
-			fprintf(stderr,
-				 "Partial length copy for track %d, no info file will be generated for this track!\n", i);
-		}
-		if (!bulk) break;
-	}
-	reset_name_iterator();
-      }
-#endif
-
-  }
-
-  if (global.just_the_toc) exit(NO_ERROR);
-
-#ifdef  ECHO_TO_SOUNDCARD
-  if (user_sound_device[0] != '\0') {
-      set_snd_device(user_sound_device);
-  }
-  init_soundcard(rate, bits);
-#endif /* ECHO_TO_SOUNDCARD */
-
-  if (global.userspeed > -1)
-     global.speed = global.userspeed;
-
-  if (global.speed != 0 && SelectSpeed != NULL) {
-     SelectSpeed(get_scsi_p(), global.speed);
-  }
-
-  current_track = track;
-
-  if ( !global.no_file ) {
-    {
-      char *myfname;
-
-      myfname = get_next_name();
-
-      if (myfname != NULL) {
-        strncpy( global.fname_base, myfname, sizeof(global.fname_base)-8 );
-        global.fname_base[sizeof(global.fname_base)-1]=0;
-      }
-    }
-
-    /* strip audio_type extension */
-    {
-      char *cp = global.fname_base;
-
-      cp = strrchr(cp, '.');
-      if (cp == NULL) {
-	cp = global.fname_base + strlen(global.fname_base);
-      }
-      *cp = '\0';
-    }
-    if (bulk && global.multiname == 0) {
-      sprintf(fname, "%s_%02u.%s",global.fname_base,current_track,audio_type);
-    } else {
-      sprintf(fname, "%s.%s",global.fname_base,audio_type);
-    }
-
-    OpenAudio( fname, rate, bits, global.channels, 
-	      (unsigned)(SamplesToWrite*global.OutSampleSize*global.channels),
-		global.audio_out);
-  }
-
-  global.Remainder = (75 % global.nsectors)+1;
-
-  global.sh_bits = 16 - bits;		/* shift counter */
-
-  global.iloop = *nSamplesToDo;
-  if (Halved && (global.iloop&1))
-      global.iloop += 2;
-
-  BeginAtSample = lSector * CD_FRAMESAMPLES;
-
-#if	1
-	if ( (global.verbose & SHOW_SUMMARY) && !global.just_the_toc &&
-	     (global.reads_illleadout == 0 ||
-	      lSector+*nSamplesToDo/CD_FRAMESAMPLES
-	       <= (unsigned) Get_AudioStartSector(cdtracks-1))) {
-
-		fprintf(stderr, "samplefile size will be %lu bytes.\n",
-			global.audio_out->GetHdrSize() +
-			global.audio_out->InSizeToOutSize(SamplesToWrite*global.OutSampleSize*global.channels)  ); 
-		fprintf (stderr, "recording %d.%04d seconds %s with %d bits @ %5d.%01d Hz"
-			,(int)rectime , (int)(rectime * 10000) % 10000,
-			global.channels == 1 ? "mono":"stereo", bits, (int)rate, (int)(rate*10)%10);
-		if (!global.no_file && *global.fname_base)
-			fprintf(stderr, " ->'%s'...", global.fname_base );
-		fputs("\n", stderr);
-	}
-#endif
-
-#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
-#else
-	init_pipes();
-#endif
-
-#ifdef	USE_PARANOIA
-	if (global.paranoia_selected) {
-		long paranoia_mode;
-
-		global.cdp = paranoia_init(get_scsi_p(), global.nsectors);
-
-		if (global.paranoia_parms.overlap >= 0) {
-			int	overlap = global.paranoia_parms.overlap;
-
-			if (overlap > global.nsectors - 1) 
-				overlap = global.nsectors - 1;
-			paranoia_overlapset(global.cdp, overlap);
-		}
-		/*
-		 * Default to a  minimum of dynamic overlapping == 0.5 sectors.
-		 * If we don't do this, we get the default from libparanoia
-		 * which is approx. 0.1.
-		 */
-		if (global.paranoia_parms.mindynoverlap < 0)
-			paranoia_dynoverlapset(global.cdp, CD_FRAMEWORDS/2, -1);
-		paranoia_dynoverlapset(global.cdp,
-			global.paranoia_parms.mindynoverlap * CD_FRAMEWORDS,
-			global.paranoia_parms.maxdynoverlap * CD_FRAMEWORDS);
-
-		paranoia_mode = PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP;
-
-		if (global.paranoia_parms.disable_paranoia) {
-			paranoia_mode = PARANOIA_MODE_DISABLE;
-		}
-		if (global.paranoia_parms.disable_extra_paranoia) {
-			paranoia_mode |= PARANOIA_MODE_OVERLAP;
-			paranoia_mode &= ~PARANOIA_MODE_VERIFY;
-		}
-		/* not yet implemented */
-		if (global.paranoia_parms.disable_scratch_detect) {
-			paranoia_mode &= ~(PARANOIA_MODE_SCRATCH|PARANOIA_MODE_REPAIR);
-		}
-		/* not yet implemented */
-		if (global.paranoia_parms.disable_scratch_repair) {
-			paranoia_mode &= ~PARANOIA_MODE_REPAIR;
-		}
-
-		paranoia_modeset(global.cdp, paranoia_mode);
-		if (global.verbose)
-			fprintf(stderr, "using lib paranoia for reading.\n");
-		paranoia_seek(global.cdp, lSector, SEEK_SET);
-		paranoia_reset();
-	}
-#endif
-#if defined(HAVE_FORK_AND_SHAREDMEM)
-
-	/* Everything is set up. Now fork and let one process read cdda sectors
-	   and let the other one store them in a wav file */
-
-	/* forking */
-	child_pid = fork();
-	if (child_pid > 0 && global.gui > 0 && global.verbose > 0)
-		fprintf( stderr, "child pid is %d\n", child_pid);
-
-	/*********************** fork **************************************/
-	if (child_pid == 0) {
-		/* child WRITER section */
-
-#ifdef	HAVE_AREAS
-		/* Under BeOS a fork() with shared memory does not work as
-		 * it does under System V Rel. 4. The mapping of the child
-		 * works with copy on write semantics, so changes do not propagate
-		 * back and forth. The existing mapping has to be deleted
-		 * and replaced by an clone without copy on write semantics.
-		 * This is done with clone_area(...,B_CLONE_ADDRESS,...).
-		 * Thanks to file support.c from the postgreSQL project.
-		 */
-		area_info inf;
-		int32 cook = 0;
-		/* iterate over all mappings to find our shared memory mapping. */
-		while (get_next_area_info(0, &cook, &inf) == B_OK)
-		{
-			/* check the name of the mapping. */
-			if (!strcmp(inf.name, AREA_NAME))
-			{
-				void *area_address;
-				area_id area_parent;
-
-				/* kill the cow mapping. */
-				area_address = inf.address;
-				if (B_OK != delete_area(inf.area))
-				{
-					fprintf(stderr, "delete_area: no valid area.\n");
-					exit(SHMMEM_ERROR);
-				}
-				/* get the parent mapping. */
-				area_parent = find_area(inf.name);
-				if (area_parent == B_NAME_NOT_FOUND)
-				{
-					fprintf(stderr, "find_area: no such area name.\n");
-					exit(SHMMEM_ERROR);
-				}
-				/* clone the parent mapping without cow. */
-				if (B_OK > clone_area("shm_child", &area_address, B_CLONE_ADDRESS,
-					B_READ_AREA | B_WRITE_AREA, area_parent))
-				{
-					fprintf(stderr,"clone_area failed\n");
-					exit(SHMMEM_ERROR);
-				}
-			}
-		}
-#endif
-#ifdef	__EMX__
-		if (DosGetSharedMem(he_fill_buffer, 3)) {
-			comerr("DosGetSharedMem() failed.\n");
-		}
-#endif
-		global.have_forked = 1;
-		forked_write();
-#ifdef	__EMX__
-		DosFreeMem(he_fill_buffer);
-		_exit(NO_ERROR);
-		/* NOTREACHED */
-#endif
-		exit_wrapper(NO_ERROR);
-		/* NOTREACHED */
-	} else if (child_pid > 0) {
-		/* parent READER section */
-    
-		global.have_forked = 1;
-		switch_to_realtime_priority();
-
-		forked_read();
-#ifdef	HAVE_AREAS
-		{
-			area_id aid;
-			aid = find_area(AREA_NAME);
-			if (aid < B_OK) {
-				comerrno(aid, "find_area() failed.\n");
-			}
-			delete_area(aid);
-		}
-#endif
-#ifdef	__EMX__
-		DosFreeMem(he_fill_buffer);
-#endif
-		exit_wrapper(NO_ERROR);
-		/* NOTREACHED */
-	} else
-		perror("fork error.");
-
-#endif
-	/* version without fork */
-	{
-		global.have_forked = 0;
-#if	0
-		if (!global.paranoia_selected) {
-			fprintf(stderr, "REAL\n");
-			switch_to_realtime_priority();
-		}
-#endif
-		fprintf(stderr, "a nonforking version is running...\n");
-		nonforked_loop();
-		exit_wrapper(NO_ERROR);
-		/* NOTREACHED */
-	}
-#ifdef	USE_PARANOIA
-	if (global.paranoia_selected)
-		paranoia_free(global.cdp);
-#endif
-
-	return 0;
-}

Deleted: cdrkit/trunk/icedax/cdda2wav.h
===================================================================
--- cdrkit/trunk/icedax/cdda2wav.h	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/cdda2wav.h	2006-11-23 19:26:47 UTC (rev 436)
@@ -1,150 +0,0 @@
-/*
- * This file has been modified for the cdrkit suite.
- *
- * The behaviour and appearence of the program code below can differ to a major
- * extent from the version distributed by the original author(s).
- *
- * For details, see Changelog file distributed with the cdrkit package. If you
- * received this file from another source then ask the distributing person for
- * a log of modifications.
- *
- */
-
-/* @(#)cdda2wav.h	1.4 00/02/13 Copyright 1998,1999,2000 Heiko Eissfeldt */
-/***
- * CopyPolicy: GNU Public License 2 applies
- * Copyright (C) by Heiko Eissfeldt
- *
- * prototypes from cdda2wav.c
- */
-
-#ifdef max
-#undef max
-#endif
-#ifdef min
-#undef min
-#endif
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#define min(a,b) ((a) < (b) ? (a) : (b))
-
-
-/* verbose levels */
-#define SHOW_TOC	1
-#define SHOW_SUMMARY	2
-#define SHOW_INDICES	4
-#define SHOW_MCN	8
-#define SHOW_ISRC	16
-#define SHOW_STARTPOSITIONS	32
-#define SHOW_TITLES	64
-#define SHOW_JUSTAUDIOTRACKS	128
-#define SHOW_MAX	255
-
-/* Endianess */
-#define GUESS (-2)
-#define NONE (-1)
-#define LITTLE 0
-#define BIG 1
-
-void FatalError(const char *szMessage, ...);
-void AnalyzeQchannel(unsigned frame);
-long SamplesNeeded(long amount, long undersampling);
-unsigned int get_current_track(void);
-
-#if defined (sun) && !defined(SVR4)
-#define  atexit(f) on_exit(f, 0)
-#endif
-
-#ifndef	_LINUX_CDROM_H
-#define	_LINUX_CDROM_H
-
-/*
- * some fix numbers
- */
-#define CD_MINS             74 /* max. minutes per CD, not really a limit */
-#define CD_SECS             60 /* seconds per minute */
-#define CD_FRAMES           75 /* frames per second */
-
-#define CD_SYNC_SIZE        12 /* 12 sync bytes per raw data frame, not transfered by the drive */
-#define CD_HEAD_SIZE         4 /* header (address) bytes per raw data frame */
-#define CD_SUBHEAD_SIZE      8 /* subheader bytes per raw XA data frame */
-#define CD_XA_HEAD        (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
-#define CD_XA_SYNC_HEAD   (CD_SYNC_SIZE+CD_XA_HEAD)/* sync bytes + header of XA frame */
-
-#define CD_FRAMESIZE      2048 /* bytes per frame, "cooked" mode */
-#define CD_FRAMESIZE_RAW  2352 /* bytes per frame, "raw" mode */
-/* most drives don't deliver everything: */
-#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /* 2340 */
-#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /* 2336 */
-/* Optics drive also has a 'read all' mode: */
-#define CD_FRAMESIZE_RAWER 2646 /* bytes per frame */
-
-#define CD_EDC_SIZE         4 /* bytes EDC per most raw data frame types */
-#define CD_ZERO_SIZE        8 /* bytes zero per yellow book mode 1 frame */
-#define CD_ECC_SIZE       276 /* bytes ECC per most raw data frame types */
-#define CD_XA_TAIL        (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */
-
-#define CD_FRAMESIZE_SUB    96 /* subchannel data "frame" size */
-#define CD_MSF_OFFSET      150 /* MSF numbering offset of first frame */
-
-#define CD_CHUNK_SIZE       24 /* lowest-level "data bytes piece" */
-#define CD_NUM_OF_CHUNKS    98 /* chunks per frame */
-
-#define CD_FRAMESIZE_XA CD_FRAMESIZE_RAW1 /* obsolete name */
-#define CD_BLOCK_OFFSET    CD_MSF_OFFSET /* obsolete name */
-
-/*
- * the raw frame layout:
- *
- * - audio (red):                  | audio_sample_bytes |
- *                                 |        2352        |
- *
- * - data (yellow, mode1):         | sync - head - data - EDC - zero - ECC |
- *                                 |  12  -   4  - 2048 -  4  -   8  - 276 |
- *
- * - data (yellow, mode2):         | sync - head - data |
- *                                 |  12  -   4  - 2336 |
- *
- * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
- *                                 |  12  -   4  -  8  - 2048 -  4  - 276 |
- *
- * - XA data (green, mode2 form2): | sync - head - sub - data - EDC |
- *                                 |  12  -   4  -  8  - 2324 -  4  |
- */
-
-
-/*
- * CD-ROM address types (cdrom_tocentry.cdte_format)
- */
-#if	!defined CDROM_LBA
-#define	CDROM_LBA 0x01 /* "logical block": first frame is #0 */
-#define	CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
-#endif
-/*
- * bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl)
- */
-#define	CDROM_DATA_TRACK	0x04
-
-/*
- * The leadout track is always 0xAA, regardless of # of tracks on disc
- */
-#define	CDROM_LEADOUT	0xAA
-
-/*
- * audio states (from SCSI-2, but seen with other drives, too)
- */
-#define	CDROM_AUDIO_INVALID	0x00	/* audio status not supported */
-#define	CDROM_AUDIO_PLAY	0x11	/* audio play operation in progress */
-#define	CDROM_AUDIO_PAUSED	0x12	/* audio play operation paused */
-#define	CDROM_AUDIO_COMPLETED	0x13	/* audio play successfully completed */
-#define	CDROM_AUDIO_ERROR	0x14	/* audio play stopped due to error */
-#define	CDROM_AUDIO_NO_STATUS	0x15	/* no current audio status to return */
-
-#ifdef FIVETWELVE
-#define	CDROM_MODE1_SIZE	512
-#else
-#define	CDROM_MODE1_SIZE	2048
-#endif /*FIVETWELVE*/
-#define	CDROM_MODE2_SIZE	2336
-
-#endif
-

Copied: cdrkit/trunk/icedax/icedax.c (from rev 435, cdrkit/trunk/icedax/cdda2wav.c)
===================================================================
--- cdrkit/trunk/icedax/cdda2wav.c	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/icedax.c	2006-11-23 19:26:47 UTC (rev 436)
@@ -0,0 +1,3064 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)cdda2wav.c	1.64 06/02/19 Copyright 1998-2004 Heiko Eissfeldt, Copyright 2004-2006 J. Schilling */
+#ifndef lint
+static char     sccsid[] =
+"@(#)cdda2wav.c	1.64 06/02/19 Copyright 1998-2004 Heiko Eissfeldt, Copyright 2004-2006 J. Schilling";
+
+#endif
+#undef DEBUG_BUFFER_ADDRESSES
+#undef GPROF
+#undef DEBUG_FORKED
+#undef DEBUG_CLEANUP
+#undef DEBUG_DYN_OVERLAP
+#undef DEBUG_READS
+#define DEBUG_ILLLEADOUT	0	/* 0 disables, 1 enables */
+/*
+ * Copyright: GNU Public License 2 applies
+ *
+ *   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.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+/*
+ * parts    (C) Peter Widow
+ * parts    (C) Thomas Niederreiter
+ * parts    (C) RSA Data Security, Inc.
+ *
+ * last changes:
+ *   18.12.93 - first version,	OK
+ *   01.01.94 - generalized & clean up HE
+ *   10.06.94 - first linux version HE
+ *   12.06.94 - wav header alignment problem fixed HE
+ *   12.08.94 - open the cdrom device O_RDONLY makes more sense :-)
+ *		no more floating point math
+ *		change to sector size 2352 which is more common
+ *		sub-q-channel information per kernel ioctl requested
+ *		doesn't work as well as before
+ *		some new options (-max -i)
+ *   01.02.95 - async i/o via semaphores and shared memory
+ *   03.02.95 - overlapped reading on sectors
+ *   03.02.95 - generalized sample rates. all integral divisors are legal
+ *   04.02.95 - sun format added
+ *              more divisors: all integral halves >= 1 allowed
+ *		floating point math needed again
+ *   06.02.95 - bugfix for last track and not d0
+ *              tested with photo-cd with audio tracks
+ *		tested with xa disk 
+ *   29.01.96 - new options for bulk transfer
+ *   01.06.96 - tested with enhanced cd
+ *   01.06.96 - tested with cd-plus
+ *   02.06.96 - support pipes
+ *   02.06.96 - support raw format
+ *   04.02.96 - security hole fixed
+ *   22.04.97 - large parts rewritten
+ *   28.04.97 - make file names DOS compatible
+ *   01.09.97 - add speed control
+ *   20.10.97 - add find mono option
+ *   Jan/Feb 98 - conversion to use Joerg Schillings SCSI library
+ *   see ChangeLog
+ */
+
+#include "config.h"
+
+#include <unixstd.h>
+#include <stdio.h>
+#include <standard.h>
+#include <stdxlib.h>
+#include <strdefs.h>
+#include <schily.h>
+#include <signal.h>
+#include <math.h>
+#include <fctldefs.h>
+#include <timedefs.h>
+#if defined (HAVE_LIMITS_H)
+#include <limits.h>
+#endif
+#if defined (HAVE_SYS_IOCTL_H)
+#include <sys/ioctl.h>
+#endif
+#include <errno.h>
+#include <statdefs.h>
+#include <waitdefs.h>
+#if defined (HAVE_SETPRIORITY)
+#include <sys/resource.h>
+#endif
+#include <vadefs.h>
+
+#include <usal/scsitransp.h>
+
+#ifdef	HAVE_AREAS
+#include <be/kernel/OS.h>
+#endif
+
+#include "mytype.h"
+#include "sndconfig.h"
+
+#include "semshm.h"	/* semaphore functions */
+#include "sndfile.h"
+#include "wav.h"	/* wav file header structures */
+#include "sun.h"	/* sun audio file header structures */
+#include "raw.h"	/* raw file handling */
+#include "aiff.h"	/* aiff file handling */
+#include "aifc.h"	/* aifc file handling */
+#ifdef	USE_LAME
+#include "mp3.h"	/* mp3 file handling */
+#endif
+#include "interface.h"  /* low level cdrom interfacing */
+#include "icedax.h"
+#include "resample.h"
+#include "toc.h"
+#include "setuid.h"
+#include "ringbuff.h"
+#include "global.h"
+#include "exitcodes.h"
+#ifdef	USE_PARANOIA
+#include "cdda_paranoia.h"
+#endif
+#include "defaults.h"
+
+static void RestrictPlaybackRate(long newrate);
+static void output_indices(FILE *fp, index_list *p, unsigned trackstart);
+static int 	write_info_file(char *fname_baseval, unsigned int track, 
+									 unsigned long SamplesDone, int numbered);
+static void CloseAudio(int channels_val, unsigned long nSamples, 
+							  struct soundfile *audio_out);
+static void CloseAll(void);
+static void OpenAudio(char *fname, double rate, long nBitsPerSample, 
+							 long channels_val, unsigned long expected_bytes, 
+							 struct soundfile*audio_out);
+static void set_offset(myringbuff *p, int offset);
+static int 	get_offset(myringbuff *p);
+static void usage(void);
+static void init_globals(void);
+static int	is_fifo(char *filename);
+
+
+/* Rules:
+ * unique parameterless options first,
+ * unique parametrized option names next,
+ * ambigious parameterless option names next,
+ * ambigious string parametrized option names last
+ */
+static const char *opts = "paranoia,paraopts&,version,help,h,\
+no-write,N,dump-rates,R,bulk,B,alltracks,verbose-scsi+,V+,\
+find-extremes,F,find-mono,G,no-infofile,H,\
+deemphasize,T,info-only,J,silent-scsi,Q,\
+cddbp-server*,cddbp-port*,\
+scanbus,device*,dev*,D*,auxdevice*,A*,interface*,I*,output-format*,O*,\
+output-endianess*,E*,cdrom-endianess*,C*,speed#,S#,\
+playback-realtime#L,p#L,md5#,M#,set-overlap#,P#,sound-device*,K*,\
+cddb#,L#,channels*,c*,bits-per-sample#,b#,rate#,r#,gui,g,\
+divider*,a*,track*,t*,index#,i#,duration*,d*,offset#,o#,\
+sectors-per-request#,n#,verbose-level&,v&,buffers-in-ring#,l#,\
+stereo,s,mono,m,wait,w,echo,e,quiet,q,max,x\
+";
+
+
+#ifdef	NEED_O_BINARY
+#include <io.h>		/* for setmode() prototype */
+#endif
+
+/* global variables */
+global_t global;
+
+/* static variables */
+static unsigned long nSamplesDone = 0;
+
+static	int child_pid = -2;
+
+static unsigned long *nSamplesToDo;
+static unsigned int current_track;
+static int bulk = 0;
+
+unsigned int get_current_track(void);
+
+unsigned int get_current_track()
+{
+	return current_track;
+}
+
+static void RestrictPlaybackRate(long  newrate)
+{
+       global.playback_rate = newrate;
+
+       if ( global.playback_rate < 25 ) global.playback_rate = 25;   /* filter out insane values */
+       if ( global.playback_rate > 250 ) global.playback_rate = 250;
+
+       if ( global.playback_rate < 100 )
+               global.nsectors = (global.nsectors*global.playback_rate)/100;
+}
+
+
+long SamplesNeeded(long amount, long undersampling_val)
+{
+  long retval = ((undersampling_val * 2 + Halved)*amount)/2;
+  if (Halved && (*nSamplesToDo & 1))
+    retval += 2;
+  return retval;
+}
+
+static int argc2;
+static int argc3;
+static char **argv2;
+
+static void reset_name_iterator(void);
+static void reset_name_iterator()
+{
+	argv2 -= argc3 - argc2;
+	argc2 = argc3;
+}
+
+static char *get_next_name(void);
+static char *get_next_name()
+{
+	if (argc2 > 0) {
+		argc2--;
+		return (*argv2++);
+	} else {
+		return NULL;
+	}
+}
+
+static char *cut_extension(char *fname);
+
+static char *cut_extension(char *fname)
+{
+	char *pp;
+
+	pp = strrchr(fname, '.');
+
+	if (pp == NULL) {
+		pp = fname + strlen(fname);
+	}
+	*pp = '\0';
+
+	return pp;
+}
+
+#ifdef INFOFILES
+static void output_indices(FILE *fp, index_list *p, unsigned trackstart)
+{
+  int ci;
+
+  fprintf(fp, "Index=\t\t");
+
+  if (p == NULL) {
+    fprintf(fp, "0\n");
+    return;
+  }
+
+  for (ci = 1; p != NULL; ci++, p = p->next) {
+    int frameoff = p->frameoffset;
+
+    if (p->next == NULL)
+	 fputs("\nIndex0=\t\t", fp);
+#if 0
+    else if ( ci > 8 && (ci % 8) == 1)
+	 fputs("\nIndex =\t\t", fp);
+#endif
+    if (frameoff != -1)
+         fprintf(fp, "%d ", frameoff - trackstart);
+    else
+         fprintf(fp, "-1 ");
+  }
+  fputs("\n", fp);
+}
+
+/*
+ * write information before the start of the sampling process
+ *
+ *
+ * uglyfied for Joerg Schillings ultra dumb line parser
+ */
+static int write_info_file(char *fname_baseval, unsigned int track, 
+                           unsigned long int SamplesDone, int numbered)
+{
+  FILE *info_fp;
+  char fname[200];
+  char datetime[30];
+  time_t utc_time;
+  struct tm *tmptr;
+
+  /* write info file */
+  if (!strcmp(fname_baseval,"-")) return 0;
+
+  strncpy(fname, fname_baseval, sizeof(fname) -1);
+  fname[sizeof(fname) -1] = 0;
+  if (numbered)
+    sprintf(cut_extension(fname), "_%02u.inf", track);
+  else
+    strcpy(cut_extension(fname), ".inf");
+
+  info_fp = fopen (fname, "w");
+  if (!info_fp)
+    return -1;
+
+#if 0
+#ifdef MD5_SIGNATURES
+  if (global.md5blocksize)
+    MD5Final (global.MD5_result, &global.context);
+#endif
+#endif
+
+  utc_time = time(NULL);
+  tmptr = localtime(&utc_time);
+  if (tmptr) {
+    strftime(datetime, sizeof(datetime), "%x %X", tmptr);
+  } else {
+    strncpy(datetime, "unknown", sizeof(datetime));
+  }
+  fprintf(info_fp, "#created by cdda2wav %s %s\n#\n", VERSION
+	  , datetime
+	  );
+  fprintf(info_fp,
+"CDINDEX_DISCID=\t'%s'\n" , global.cdindex_id);
+  fprintf(info_fp,
+"CDDB_DISCID=\t0x%08lx\n\
+MCN=\t\t%s\n\
+ISRC=\t\t%15.15s\n\
+#\n\
+Albumperformer=\t'%s'\n\
+Performer=\t'%s'\n\
+Albumtitle=\t'%s'\n"
+	  , (unsigned long) global.cddb_id
+	  , Get_MCN()
+	  , Get_ISRC(track)
+	  , global.creator != NULL ? global.creator : (const unsigned char *)""
+	  , global.trackcreator[track] != NULL ? global.trackcreator[track] :
+		(global.creator != NULL ? global.creator : (const unsigned char *)"")
+	  , global.disctitle != NULL ? global.disctitle : (const unsigned char *)""
+	  );
+  fprintf(info_fp,
+	  "Tracktitle=\t'%s'\n"
+	  , global.tracktitle[track] ? global.tracktitle[track] : (const unsigned char *)""
+	  );
+  fprintf(info_fp, "Tracknumber=\t%u\n"
+	  , track
+	  );
+  fprintf(info_fp, 
+	  "Trackstart=\t%ld\n"
+	  , Get_AudioStartSector(track)
+	  );
+  fprintf(info_fp, 
+	  "# track length in sectors (1/75 seconds each), rest samples\nTracklength=\t%ld, %d\n"
+	  , SamplesDone/588L,(int)(SamplesDone%588));
+  fprintf(info_fp, 
+	  "Pre-emphasis=\t%s\n"
+	  , Get_Preemphasis(track) && (global.deemphasize == 0) ? "yes" : "no");
+  fprintf(info_fp, 
+	  "Channels=\t%d\n"
+	  , Get_Channels(track) ? 4 : global.channels == 2 ? 2 : 1);
+	{ int cr = Get_Copyright(track);
+		fputs("Copy_permitted=\t", info_fp);
+		switch (cr) {
+			case 0:
+				fputs("once (copyright protected)\n", info_fp);
+			break;
+			case 1:
+				fputs("no (SCMS first copy)\n", info_fp);
+			break;
+			case 2:
+				fputs("yes (not copyright protected)\n", info_fp);
+			break;
+			default:
+				fputs("unknown\n", info_fp);
+		}
+	}
+  fprintf(info_fp, 
+	  "Endianess=\t%s\n"
+	  , global.need_big_endian ? "big" : "little"
+	  );
+  fprintf(info_fp, "# index list\n");
+  output_indices(info_fp, global.trackindexlist[track],
+		 Get_AudioStartSector(track));
+#if 0
+/* MD5 checksums in info files are currently broken.
+ *  for on-the-fly-recording the generation of info files has been shifted
+ *  before the recording starts, so there is no checksum at that point.
+ */
+#ifdef MD5_SIGNATURES
+  fprintf(info_fp, 
+	  "#(blocksize) checksum\nMD-5=\t\t(%d) %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
+	  , global.md5blocksize
+	  , global.MD5_result[0]
+	  , global.MD5_result[1]
+	  , global.MD5_result[2]
+	  , global.MD5_result[3]
+	  , global.MD5_result[4]
+	  , global.MD5_result[5]
+	  , global.MD5_result[6]
+	  , global.MD5_result[7]
+	  , global.MD5_result[8]
+	  , global.MD5_result[9]
+	  , global.MD5_result[10]
+	  , global.MD5_result[11]
+	  , global.MD5_result[12]
+	  , global.MD5_result[13]
+	  , global.MD5_result[14]
+	  , global.MD5_result[15]);
+#endif
+#endif
+  fclose(info_fp);
+  return 0;
+}
+#endif
+
+static void CloseAudio(int channels_val, unsigned long nSamples, 
+                       struct soundfile *audio_out)
+{
+      /* define length */
+      audio_out->ExitSound( global.audio, (nSamples-global.SkippedSamples)*global.OutSampleSize*channels_val );
+
+      close (global.audio);
+      global.audio = -1;
+}
+
+static unsigned int track = 1;
+
+/* On terminating:
+ * define size-related entries in audio file header, update and close file */
+static void CloseAll()
+{
+	WAIT_T chld_return_status;
+	int amiparent;
+
+	/* terminate child process first */
+	amiparent = child_pid > 0;
+
+	if (global.iloop > 0) {
+		/* set to zero */
+		global.iloop = 0;
+	}
+
+#if	defined	HAVE_FORK_AND_SHAREDMEM
+# ifdef DEBUG_CLEANUP
+	fprintf(stderr, "%s terminating, \n", amiparent ? 
+		"Parent (READER)" : "Child (WRITER)");
+#endif
+#else
+# ifdef DEBUG_CLEANUP
+	fprintf(stderr, "Cdda2wav single process terminating, \n");
+# endif
+#endif
+
+	if (amiparent || child_pid < 0) {
+		/* switch to original mode and close device */
+		EnableCdda (get_scsi_p(), 0, 0);
+	}
+
+	if (!amiparent) {
+		/* do general clean up */
+
+		if (global.audio>=0) {
+			if (bulk) {
+				/* finish sample file for this track */
+				CloseAudio(global.channels,
+				 global.nSamplesDoneInTrack, global.audio_out);
+			} else {
+				/* finish sample file for this track */
+				CloseAudio(global.channels,
+				 (unsigned int) *nSamplesToDo, global.audio_out);
+			}
+		}
+
+		/* tell minimum and maximum amplitudes, if required */
+		if (global.findminmax) {
+			fprintf(stderr,
+			"Right channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", 
+			global.minamp[0], global.maxamp[0]);
+			fprintf(stderr,
+			"Left  channel: minimum amplitude :%d/-32768, maximum amplitude :%d/32767\n", 
+			global.minamp[1], global.maxamp[1]);
+		}
+
+		/* tell mono or stereo recording, if required */
+		if (global.findmono) {
+			fprintf(stderr, "Audio samples are originally %s.\n", global.ismono ? "mono" : "stereo");
+		}
+
+		return;	/* end of child or single process */
+	}
+
+
+	if (global.have_forked == 1) {
+#ifdef DEBUG_CLEANUP
+		fprintf(stderr, "Parent wait for child death, \n");
+#endif
+
+		/* wait for child to terminate */
+		if (0 > wait(&chld_return_status)) {
+			perror("");
+		} else {
+			if (WIFEXITED(chld_return_status)) {
+				if (WEXITSTATUS(chld_return_status)) {
+					fprintf(stderr, "\nW Child exited with %d\n", WEXITSTATUS(chld_return_status));
+				}
+			}
+			if (WIFSIGNALED(chld_return_status)) {
+				fprintf(stderr, "\nW Child exited due to signal %d\n", WTERMSIG(chld_return_status));
+			}
+			if (WIFSTOPPED(chld_return_status)) {
+				fprintf(stderr, "\nW Child is stopped due to signal %d\n", WSTOPSIG(chld_return_status));
+			}
+		}
+
+#ifdef DEBUG_CLEANUP
+		fprintf(stderr, "\nW Parent child death, state:%d\n", chld_return_status);
+#endif
+	}
+
+#ifdef GPROF
+	rename("gmon.out", "gmon.child");
+#endif
+}
+
+
+/* report a usage error and exit */
+#ifdef  PROTOTYPES
+static void usage2 (const char *szMessage, ...)
+#else
+static void usage2(const char *szMessage, va_dcl va_alist)
+#endif
+{
+	va_list marker;
+
+#ifdef  PROTOTYPES
+	va_start(marker, szMessage);
+#else
+	va_start(marker);
+#endif
+
+	vfprintf(stderr, szMessage, marker);
+
+	va_end(marker);
+	fprintf(stderr, "\nPlease use -help or consult the man page for help.\n");
+
+	exit (1);
+}
+
+
+/* report a fatal error, clean up and exit */
+#ifdef  PROTOTYPES
+void FatalError (const char *szMessage, ...)
+#else
+void FatalError(const char *szMessage, va_dcl va_alist)
+#endif
+{
+	va_list marker;
+
+#ifdef  PROTOTYPES
+	va_start(marker, szMessage);
+#else
+	va_start(marker);
+#endif
+
+	vfprintf(stderr, szMessage, marker);
+
+	va_end(marker);
+
+	if (child_pid >= 0) {
+		if (child_pid == 0) {
+			pid_t	ppid;
+			/*
+			 * Kill the parent too if we are not orphaned.
+			 */
+			ppid = getppid();
+			if (ppid > 1)
+				kill(ppid, SIGINT);
+		} else {
+			kill(child_pid, SIGINT);
+		}
+	}
+	exit (1);
+}
+
+
+/* open the audio output file and prepare the header. 
+ * the header will be defined on terminating (when the size
+ * is known). So hitting the interrupt key leaves an intact
+ * file.
+ */
+static void OpenAudio(char *fname, double rate, long nBitsPerSample, 
+                      long channels_val, unsigned long expected_bytes, 
+                      struct soundfile *audio_out)
+{
+  if (global.audio == -1) {
+
+    global.audio = open (fname, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY
+#ifdef SYNCHRONOUS_WRITE
+			 | O_SYNC
+#endif
+		  , 0666);
+    if (global.audio == -1) {
+      if (errno == EAGAIN && is_fifo(fname)) {
+        FatalError ("Could not open fifo %s. Probably no fifo reader present.\n", fname);
+      }
+      perror("open audio sample file");
+      FatalError ("Could not open file %s\n", fname);
+    }
+  }
+  global.SkippedSamples = 0;
+  any_signal = 0;
+  audio_out->InitSound( global.audio, channels_val, (unsigned long)rate, nBitsPerSample, expected_bytes );
+
+#ifdef MD5_SIGNATURES
+  if (global.md5blocksize)
+    MD5Init (&global.context);
+  global.md5count = global.md5blocksize;
+#endif
+}
+
+#include "scsi_cmds.h"
+
+static int RealEnd(SCSI *usalp, UINT4 *buff);
+
+static int RealEnd(SCSI *usalp, UINT4 *buff)
+{
+	if (usal_cmd_err(usalp) != 0) {
+		int c,k,q;
+
+		k = usal_sense_key(usalp);
+		c = usal_sense_code(usalp);
+		q = usal_sense_qual(usalp);
+		if ((k == 0x05 /* ILLEGAL_REQUEST */ &&
+		     c == 0x21 /* lba out of range */ &&
+		     q == 0x00) ||
+		    (k == 0x05 /* ILLEGAL_REQUEST */ &&
+		     c == 0x63 /*end of user area encountered on this track*/ &&
+		     q == 0x00) ||
+		    (k == 0x08 /* BLANK_CHECK */ &&
+		     c == 0x64 /* illegal mode for this track */ &&
+		     q == 0x00)) {
+			return 1;
+		}
+	}
+
+	if (usal_getresid(usalp) > 16) return 1;
+
+	{
+		unsigned char *p;
+		/* Look into the subchannel data */
+		buff += CD_FRAMESAMPLES;
+		p = (unsigned char *)buff;
+		if (p[0] == 0x21 && p[1] == 0xaa) {
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static void set_offset(myringbuff *p, int offset)
+{
+#ifdef DEBUG_SHM
+  fprintf(stderr, "Write offset %d at %p\n", offset, &p->offset);
+#endif
+  p->offset = offset;
+}
+
+
+static int get_offset(myringbuff *p)
+{
+#ifdef DEBUG_SHM
+  fprintf(stderr, "Read offset %d from %p\n", p->offset, &p->offset);
+#endif
+  return p->offset;
+}
+
+
+static void usage()
+{
+  fputs(
+"usage: cdda2wav [OPTIONS ...] [trackfilenames ...]\n\
+OPTIONS:\n\
+        [-c chans] [-s] [-m] [-b bits] [-r rate] [-a divider] [-S speed] [-x]\n\
+        [-t track[+endtrack]] [-i index] [-o offset] [-d duration] [-F] [-G]\n\
+        [-q] [-w] [-v vopts] [-R] [-P overlap] [-B] [-T] [-C input-endianess]\n\
+        [-e] [-n sectors] [-N] [-J] [-L cddbp-mode] [-H] [-g] [-l buffers] [-D cd-device]\n\
+        [-I interface] [-K sound-device] [-O audiotype] [-E output-endianess]\n\
+        [-A auxdevice] [-paranoia] [-cddbp-server=name] [-cddbp-port=port] [-version]\n", stderr);
+  fputs("\
+  (-D) dev=device		set the cdrom or scsi device (as Bus,Id,Lun).\n\
+  (-A) auxdevice=device		set the aux device (typically /dev/cdrom).\n\
+  (-K) sound-device=device	set the sound device to use for -e (typically /dev/dsp).\n\
+  (-I) interface=interface	specify the interface for cdrom access.\n\
+        (generic_scsi or cooked_ioctl).\n\
+  (-c) channels=channels	set 1 for mono, 2 or s for stereo (s: channels swapped).\n\
+  (-s) -stereo			select stereo recording.\n\
+  (-m) -mono			select mono recording.\n\
+  (-x) -max			select maximum quality (stereo/16-bit/44.1 KHz).\n\
+  (-b) bits=bits		set bits per sample per channel (8, 12 or 16 bits).\n\
+  (-r) rate=rate		set rate in samples per second. -R gives all rates\n\
+  (-a) divider=divider		set rate to 44100Hz / divider. -R gives all rates\n\
+  (-R) -dump-rates		dump a table with all available sample rates\n\
+  (-S) speed=speedfactor	set the cdrom drive to a given speed during reading\n\
+  (-P) set-overlap=sectors	set amount of overlap sampling (default is 0)\n\
+  (-n) sectors-per-request=secs	read 'sectors' sectors per request.\n\
+  (-l) buffers-in-ring=buffers	use a ring buffer with 'buffers' elements.\n\
+  (-t) track=track[+end track]	select start track (option. end track).\n\
+  (-i) index=index		select start index.\n\
+  (-o) offset=offset		start at 'offset' sectors behind start track/index.\n\
+        one sector equivalents 1/75 second.\n\
+  (-O) output-format=audiotype	set to wav, au (sun), cdr (raw), aiff or aifc format.\n\
+  (-C) cdrom-endianess=endian	set little, big or guess input sample endianess.\n\
+  (-E) output-endianess=endian	set little or big output sample endianess.\n\
+  (-d) duration=seconds		set recording time in seconds or 0 for whole track.\n\
+  (-w) -wait			wait for audio signal, then start recording.\n\
+  (-F) -find-extremes		find extrem amplitudes in samples.\n\
+  (-G) -find-mono		find if input samples are mono.\n\
+  (-T) -deemphasize		undo pre-emphasis in input samples.\n\
+  (-e) -echo			echo audio data to sound device (see -K) SOUND_DEV.\n\
+  (-v) verbose-level=optlist	controls verbosity (for a list use -vhelp).\n\
+  (-N) -no-write		do not create audio sample files.\n\
+  (-J) -info-only		give disc information only.\n\
+  (-L) cddb=cddbpmode		do cddbp title lookups.\n\
+        resolve multiple entries according to cddbpmode: 0=interactive, 1=first entry\n\
+  (-H) -no-infofile		no info file generation.\n\
+  (-g) -gui			generate special output suitable for gui frontends.\n\
+  (-Q) -silent-scsi		do not print status of erreneous scsi-commands.\n\
+       -scanbus			scan the SCSI bus and exit\n\
+  (-M) md5=count		calculate MD-5 checksum for blocks of 'count' bytes.\n\
+  (-q) -quiet			quiet operation, no screen output.\n\
+  (-p) playback-realtime=perc	play (echo) audio pitched at perc percent (50%-200%).\n\
+  (-V) -verbose-scsi		each option increases verbosity for SCSI commands.\n\
+  (-h) -help			show this help screen.\n\
+  (-B) -alltracks, -bulk	record each track into a seperate file.\n\
+       -paranoia		use the lib paranoia for reading.\n\
+       -paraopts=opts		set options for lib paranoia (see -paraopts=help).\n\
+       -cddbp-server=servername	set the cddbp server to use for title lookups.\n\
+       -cddbp-port=portnumber	set the cddbp port to use for title lookups.\n\
+       -version			print version information.\n\
+\n\
+Please note: some short options will be phased out soon (disappear)!\n\
+\n\
+parameters: (optional) one or more file names or - for standard output.\n\
+", stderr);
+  fputs("Version ", stderr);
+  fputs(VERSION, stderr);
+  fprintf(stderr, "\n\
+defaults	%s, %d bit, %d.%02d Hz, track 1, no offset, one track,\n",
+	  CHANNELS-1?"stereo":"mono", BITS_P_S,
+	 44100 / UNDERSAMPLING,
+	 (4410000 / UNDERSAMPLING) % 100);
+  fprintf(stderr, "\
+          type %s '%s', don't wait for signal, not quiet,\n",
+          AUDIOTYPE, FILENAME);
+  fprintf(stderr, "\
+          use %s, device %s, aux %s\n",
+	  DEF_INTERFACE, CD_DEVICE, AUX_DEVICE);
+  exit( SYNTAX_ERROR );
+}
+
+static void init_globals()
+{
+#ifdef	HISTORICAL_JUNK
+  global.dev_name = CD_DEVICE;	/* device name */
+#endif
+  global.aux_name = AUX_DEVICE;/* auxiliary cdrom device */
+  strncpy(global.fname_base, FILENAME, sizeof(global.fname_base));/* auxiliary cdrom device */
+  global.have_forked = 0;	/* state variable for clean up */
+  global.parent_died = 0;	/* state variable for clean up */
+  global.audio    = -1;		/* audio file desc */
+  global.cooked_fd  = -1;	/* cdrom file desc */
+  global.no_file  =  0;		/* flag no_file */
+  global.no_infofile  =  0;	/* flag no_infofile */
+  global.no_cddbfile  =  0;	/* flag no_cddbfile */
+  global.quiet	  =  0;		/* flag quiet */
+  global.verbose  =  SHOW_TOC + SHOW_SUMMARY + SHOW_STARTPOSITIONS + SHOW_TITLES;	/* verbose level */
+  global.scsi_silent = 0;
+  global.scsi_verbose = 0;		/* SCSI verbose level */
+  global.scanbus = 0;
+  global.multiname = 0;		/* multiple file names given */
+  global.sh_bits  =  0;		/* sh_bits: sample bit shift */
+  global.Remainder=  0;		/* remainder */
+  global.iloop    =  0;		/* todo counter */
+  global.SkippedSamples =  0;	/* skipped samples */
+  global.OutSampleSize  =  0;	/* output sample size */
+  global.channels = CHANNELS;	/* output sound channels */
+  global.nSamplesDoneInTrack = 0; /* written samples in current track */
+  global.buffers = 4;           /* buffers to use */
+  global.nsectors = NSECTORS;   /* sectors to read in one request */
+  global.overlap = 1;           /* amount of overlapping sectors */
+  global.useroverlap = -1;      /* amount of overlapping sectors user override */
+  global.need_hostorder = 0;	/* processing needs samples in host endianess */
+  global.in_lendian = -1;	/* input endianess from SetupSCSI() */
+  global.outputendianess = NONE; /* user specified output endianess */
+  global.findminmax  =  0;	/* flag find extrem amplitudes */
+#ifdef HAVE_LIMITS_H
+  global.maxamp[0] = INT_MIN;	/* maximum amplitude */
+  global.maxamp[1] = INT_MIN;	/* maximum amplitude */
+  global.minamp[0] = INT_MAX;	/* minimum amplitude */
+  global.minamp[1] = INT_MAX;	/* minimum amplitude */
+#else
+  global.maxamp[0] = -32768;	/* maximum amplitude */
+  global.maxamp[1] = -32768;	/* maximum amplitude */
+  global.minamp[0] = 32767;	/* minimum amplitude */
+  global.minamp[1] = 32767;	/* minimum amplitude */
+#endif
+  global.speed = DEFAULT_SPEED; /* use default */ 
+  global.userspeed = -1;        /* speed user override */
+  global.findmono  =  0;	/* flag find if samples are mono */
+  global.ismono  =  1;		/* flag if samples are mono */
+  global.swapchannels  =  0;	/* flag if channels shall be swapped */
+  global.deemphasize  =  0;	/* flag undo pre-emphasis in samples */
+  global.playback_rate = 100;   /* new fancy selectable sound output rate */
+  global.gui  =  0;		/* flag plain formatting for guis */
+  global.cddb_id = 0;           /* disc identifying id for CDDB database */
+  global.cddb_revision = 0;     /* entry revision for CDDB database */
+  global.cddb_year = 0;         /* disc identifying year for CDDB database */
+  global.cddb_genre[0] = '\0';  /* disc identifying genre for CDDB database */
+  global.cddbp = 0;             /* flag if titles shall be looked up from CDDBP */
+  global.cddbp_server = 0;      /* user supplied CDDBP server */
+  global.cddbp_port = 0;        /* user supplied CDDBP port */
+  global.illleadout_cd = 0;     /* flag if illegal leadout is present */
+  global.reads_illleadout = 0;  /* flag if cdrom drive reads cds with illegal leadouts */
+  global.disctitle = NULL;
+  global.creator = NULL;
+  global.copyright_message = NULL;
+  memset(global.tracktitle, 0, sizeof(global.tracktitle));
+  memset(global.trackindexlist, 0, sizeof(global.trackindexlist));
+
+  global.just_the_toc = 0;
+#ifdef	USE_PARANOIA
+	global.paranoia_parms.disable_paranoia = 
+	global.paranoia_parms.disable_extra_paranoia = 
+	global.paranoia_parms.disable_scratch_detect =
+	global.paranoia_parms.disable_scratch_repair = 0;
+	global.paranoia_parms.retries = 20;
+	global.paranoia_parms.overlap = -1;
+	global.paranoia_parms.mindynoverlap = -1;
+	global.paranoia_parms.maxdynoverlap = -1;
+#endif
+}
+
+#if !defined (HAVE_STRCASECMP) || (HAVE_STRCASECMP != 1)
+#include <ctype.h>
+static int strcasecmp(const char *s1, const char *s2);
+static int strcasecmp(const char *s1, const char *s2)
+{
+  if (s1 && s2) {
+    while (*s1 && *s2 && (tolower(*s1) - tolower(*s2) == 0)) {
+      s1++;
+      s2++;
+    }
+    if (*s1 == '\0' && *s2 == '\0') return 0;
+    if (*s1 == '\0') return -1;
+    if (*s2 == '\0') return +1;
+    return tolower(*s1) - tolower(*s2);
+  }
+  return -1;
+}
+#endif
+
+static int is_fifo(char *filename)
+{
+#if	defined S_ISFIFO
+  struct stat statstruct;
+
+  if (stat(filename, &statstruct)) {
+    /* maybe the output file does not exist. */
+    if (errno == ENOENT)
+	return 0;
+    else comerr("Error during stat for output file\n");
+  } else {
+    if (S_ISFIFO(statstruct.st_mode)) {
+	return 1;
+    }
+  }
+  return 0;
+#else
+  return 0;
+#endif
+}
+
+
+#if !defined (HAVE_STRTOUL) || (HAVE_STRTOUL != 1)
+static unsigned int strtoul(const char *s1, char **s2, int base);
+static unsigned int strtoul(const char *s1, char **s2, int base)
+{
+	long retval;
+
+	if (base == 10) {
+		/* strip zeros in front */
+		while (*s1 == '0')
+			s1++;
+	}
+	if (s2 != NULL) {
+		*s2 = astol(s1, &retval);
+	} else {
+		(void) astol(s1, &retval);
+	}
+
+	return (unsigned long) retval; 	
+}
+#endif
+
+static unsigned long SectorBurst;
+#if (SENTINEL > CD_FRAMESIZE_RAW)
+error block size for overlap check has to be < sector size
+#endif
+
+
+static void
+switch_to_realtime_priority(void);
+
+#ifdef  HAVE_SYS_PRIOCNTL_H
+
+#include <sys/priocntl.h>
+#include <sys/rtpriocntl.h>
+static void switch_to_realtime_priority()
+{
+        pcinfo_t        info;
+        pcparms_t       param;
+        rtinfo_t        rtinfo;
+        rtparms_t       rtparam;
+	int		pid;
+
+	pid = getpid();
+
+        /* get info */
+        strcpy(info.pc_clname, "RT");
+        if (-1 == priocntl(P_PID, pid, PC_GETCID, (void *)&info)) {
+                errmsg("Cannot get priority class id priocntl(PC_GETCID)\n");
+		goto prio_done;
+	}
+
+        memmove(&rtinfo, info.pc_clinfo, sizeof(rtinfo_t));
+
+        /* set priority not to the max */
+        rtparam.rt_pri = rtinfo.rt_maxpri - 2;
+        rtparam.rt_tqsecs = 0;
+        rtparam.rt_tqnsecs = RT_TQDEF;
+        param.pc_cid = info.pc_cid;
+        memmove(param.pc_clparms, &rtparam, sizeof(rtparms_t));
+	priv_on();
+	needroot(0);
+        if (-1 == priocntl(P_PID, pid, PC_SETPARMS, (void *)&param))
+                errmsg("Cannot set priority class parameters priocntl(PC_SETPARMS)\n");
+prio_done:
+	priv_off();
+	dontneedroot();
+}
+#else
+#if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING -0 >= 0
+#define	USE_POSIX_PRIORITY_SCHEDULING
+#endif
+#ifdef	USE_POSIX_PRIORITY_SCHEDULING
+#include <sched.h>
+
+static void switch_to_realtime_priority()
+{
+#ifdef  _SC_PRIORITY_SCHEDULING
+	if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) {
+		errmsg("WARNING: RR-scheduler not available, disabling.\n");
+	} else
+#endif
+	{
+	int sched_fifo_min, sched_fifo_max;
+	struct sched_param sched_parms;
+
+	sched_fifo_min = sched_get_priority_min(SCHED_FIFO);
+	sched_fifo_max = sched_get_priority_max(SCHED_FIFO);
+	sched_parms.sched_priority = sched_fifo_max - 1;
+	priv_on();
+	needroot(0);
+	if (-1 == sched_setscheduler(getpid(), SCHED_FIFO, &sched_parms)
+		&& global.quiet != 1)
+		errmsg("cannot set posix realtime scheduling policy\n");
+	priv_off();
+	dontneedroot();
+	}
+}
+#else
+#if defined(__CYGWIN32__)
+
+/*
+ * NOTE: Base.h from Cygwin-B20 has a second typedef for BOOL.
+ *	 We define BOOL to make all local code use BOOL
+ *	 from Windows.h and use the hidden __SBOOL for
+ *	 our global interfaces.
+ *
+ * NOTE: windows.h from Cygwin-1.x includes a structure field named sample,
+ *	 so me may not define our own 'sample' or need to #undef it now.
+ *	 With a few nasty exceptions, Microsoft assumes that any global
+ *	 defines or identifiers will begin with an Uppercase letter, so
+ *	 there may be more of these problems in the future.
+ *
+ * NOTE: windows.h defines interface as an alias for struct, this 
+ *	 is used by COM/OLE2, I guess it is class on C++
+ *	 We man need to #undef 'interface'
+ */
+#define	BOOL	WBOOL		/* This is the Win BOOL		*/
+#define	format	__format	/* Avoid format parameter hides global ... */
+#include <windows.h>
+#undef format
+#undef interface
+
+static void switch_to_realtime_priority()
+{
+   /* set priority class */
+   if (FALSE == SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS)) {
+     fprintf(stderr, "No realtime priority possible.\n");
+     return;
+   }
+
+   /* set thread priority */
+   if (FALSE == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST)) {
+     fprintf(stderr, "Could not set realtime priority.\n");
+   }
+}
+#else
+static void switch_to_realtime_priority()
+{
+}
+#endif
+#endif
+#endif
+
+/* SCSI cleanup */
+int on_exitscsi(void *status);
+
+int on_exitscsi(void *status)
+{
+	exit((int)status);
+	return 0;
+}
+
+/* wrapper for signal handler exit needed for Mac-OS-X */
+static void exit_wrapper(int status);
+
+static void exit_wrapper(int status)
+{
+#if defined DEBUG_CLEANUP
+	fprintf( stderr, "Exit(%d) for %s\n", status, child_pid == 0 ? "Child" : "Parent");
+	fflush(stderr);
+#endif
+
+	if (child_pid != 0) {
+		SCSI *usalp = get_scsi_p();
+		if (usalp->running) {
+			usalp->cb_fun = on_exitscsi;
+			usalp->cb_arg = (void *)status;
+		} else {
+			on_exitscsi((void *)status);
+		} 
+	} else {
+		exit(status);
+	}
+}
+
+/* signal handler for process communication */
+static void set_nonforked(int status);
+
+/* ARGSUSED */
+static void set_nonforked(int status)
+{
+	global.parent_died = 1;
+#if defined DEBUG_CLEANUP
+fprintf( stderr, "SIGPIPE received from %s\n.", child_pid == 0 ? "Child" : "Parent");
+#endif
+	if (child_pid == 0) {
+		pid_t	ppid;
+		/*
+		 * Kill the parent too if we are not orphaned.
+		 */
+		ppid = getppid();
+		if (ppid > 1)
+			kill(ppid, SIGINT);
+	} else {
+		kill(child_pid, SIGINT);
+	}
+	exit(SIGPIPE_ERROR);
+}
+
+
+
+#ifdef	USE_PARANOIA
+static struct paranoia_statistics
+{
+	long	c_sector;
+	long	v_sector;
+	int	last_heartbeatstate;
+	long	lasttime;
+	char	heartbeat;
+	int	minoverlap;
+	int	curoverlap;
+	int	maxoverlap;
+	int	slevel;
+	int	slastlevel;
+	int	stimeout;
+	int	rip_smile_level;
+	unsigned verifies;
+	unsigned reads;
+	unsigned fixup_edges;
+	unsigned fixup_atoms;
+	unsigned readerrs;
+	unsigned skips;
+	unsigned overlaps;
+	unsigned scratchs;
+	unsigned drifts;
+	unsigned fixup_droppeds;
+	unsigned fixup_dupeds;
+}	*para_stat;
+
+
+static void paranoia_reset(void);
+static void paranoia_reset()
+{
+	para_stat->c_sector = 0;
+	para_stat->v_sector = 0;
+	para_stat->last_heartbeatstate = 0;
+	para_stat->lasttime = 0;
+	para_stat->heartbeat = ' ';
+	para_stat->minoverlap = 0x7FFFFFFF;
+	para_stat->curoverlap = 0;
+	para_stat->maxoverlap = 0;
+	para_stat->slevel = 0;
+	para_stat->slastlevel = 0;
+	para_stat->stimeout = 0;
+	para_stat->rip_smile_level = 0;
+	para_stat->verifies = 0;
+	para_stat->reads = 0;
+	para_stat->readerrs = 0;
+	para_stat->fixup_edges = 0;
+	para_stat->fixup_atoms = 0;
+	para_stat->fixup_droppeds = 0;
+	para_stat->fixup_dupeds = 0;
+	para_stat->drifts = 0;
+	para_stat->scratchs = 0;
+	para_stat->overlaps = 0;
+	para_stat->skips = 0;
+}
+
+static void paranoia_callback(long inpos, int function);
+
+static void paranoia_callback(long inpos, int function)
+{
+	struct timeval thistime;
+	long	test;
+
+	switch (function) {
+		case	-2:
+			para_stat->v_sector = inpos / CD_FRAMEWORDS;
+			return;
+		case	-1:
+			para_stat->last_heartbeatstate = 8;
+			para_stat->heartbeat = '*';
+			para_stat->slevel = 0;
+			para_stat->v_sector = inpos / CD_FRAMEWORDS;
+		break;
+		case	PARANOIA_CB_VERIFY:
+			if (para_stat->stimeout >= 30) {
+				if (para_stat->curoverlap > CD_FRAMEWORDS) {
+					para_stat->slevel = 2;
+				} else {
+					para_stat->slevel = 1;
+				}
+			}
+			para_stat->verifies++;
+		break;
+		case	PARANOIA_CB_READ:
+			if (inpos / CD_FRAMEWORDS > para_stat->c_sector) {
+				para_stat->c_sector = inpos / CD_FRAMEWORDS;
+			}
+			para_stat->reads++;
+		break;
+		case	PARANOIA_CB_FIXUP_EDGE:
+			if (para_stat->stimeout >= 5) {
+				if (para_stat->curoverlap > CD_FRAMEWORDS) {
+					para_stat->slevel = 2;
+				} else {
+					para_stat->slevel = 1;
+				}
+			}
+			para_stat->fixup_edges++;
+		break;
+		case	PARANOIA_CB_FIXUP_ATOM:
+			if (para_stat->slevel < 3 || para_stat->stimeout > 5) {
+				para_stat->slevel = 3;
+			}
+			para_stat->fixup_atoms++;
+		break;
+		case	PARANOIA_CB_READERR:
+			para_stat->slevel = 6;
+			para_stat->readerrs++;
+		break;
+		case	PARANOIA_CB_SKIP:
+			para_stat->slevel = 8;
+			para_stat->skips++;
+		break;
+		case	PARANOIA_CB_OVERLAP:
+			para_stat->curoverlap = inpos;
+			if (inpos > para_stat->maxoverlap)
+				para_stat->maxoverlap = inpos;
+			if (inpos < para_stat->minoverlap)
+				para_stat->minoverlap = inpos;
+			para_stat->overlaps++;
+		break;
+		case	PARANOIA_CB_SCRATCH:
+			para_stat->slevel = 7;
+			para_stat->scratchs++;
+		break;
+		case	PARANOIA_CB_DRIFT:
+			if (para_stat->slevel < 4 || para_stat->stimeout > 5) {
+				para_stat->slevel = 4;
+			}
+			para_stat->drifts++;
+		break;
+		case	PARANOIA_CB_FIXUP_DROPPED:
+			para_stat->slevel = 5;
+			para_stat->fixup_droppeds++;
+		break;
+		case	PARANOIA_CB_FIXUP_DUPED:
+			para_stat->slevel = 5;
+			para_stat->fixup_dupeds++;
+		break;
+	}
+
+	gettimeofday(&thistime, NULL);
+	/* now in tenth of seconds. */
+	test = thistime.tv_sec * 10 + thistime.tv_usec / 100000;
+
+	if (para_stat->lasttime != test
+		|| function == -1
+		|| para_stat->slastlevel != para_stat->slevel) {
+
+		if (function == -1
+			|| para_stat->slastlevel != para_stat->slevel) {
+
+			static const char hstates[] = " .o0O0o.";
+
+			para_stat->lasttime = test;
+			para_stat->stimeout++;
+
+			para_stat->last_heartbeatstate++;
+			if (para_stat->last_heartbeatstate > 7) {
+				para_stat->last_heartbeatstate = 0;
+			}
+			para_stat->heartbeat = hstates[para_stat->last_heartbeatstate];
+
+			if (function == -1) {
+				para_stat->heartbeat = '*';
+			}
+		}
+
+		if (para_stat->slastlevel != para_stat->slevel) {
+			para_stat->stimeout = 0;
+		}
+		para_stat->slastlevel = para_stat->slevel;
+	}
+
+	if (para_stat->slevel < 8) {
+		para_stat->rip_smile_level = para_stat->slevel;
+	} else {
+		para_stat->rip_smile_level = 0;
+	}
+}
+#endif
+
+static long lSector;
+static long lSector_p2;
+static double rate = 44100.0 / UNDERSAMPLING;
+static int bits = BITS_P_S;
+static char fname[200];
+static const char *audio_type;
+static long BeginAtSample;
+static unsigned long SamplesToWrite; 
+static unsigned minover;
+static unsigned maxover;
+
+static unsigned long calc_SectorBurst(void);
+static unsigned long calc_SectorBurst()
+{
+	unsigned long SectorBurstVal;
+
+	SectorBurstVal = min(global.nsectors,
+		  (global.iloop + CD_FRAMESAMPLES-1) / CD_FRAMESAMPLES);
+	if ( lSector+(int)SectorBurst-1 >= lSector_p2 )
+		SectorBurstVal = lSector_p2 - lSector;
+	return SectorBurstVal;
+}
+
+/* if PERCENTAGE_PER_TRACK is defined, the percentage message will reach
+ * 100% every time a track end is reached or the time limit is reached.
+ *
+ * Otherwise if PERCENTAGE_PER_TRACK is not defined, the percentage message
+ * will reach 100% once at the very end of the last track.
+ */
+#define	PERCENTAGE_PER_TRACK
+
+static int do_read(myringbuff *p, unsigned *total_unsuccessful_retries);
+static int do_read(myringbuff *p, unsigned *total_unsuccessful_retries)
+{
+	unsigned char *newbuf;
+	int offset;
+	unsigned int added_size;
+
+	/* how many sectors should be read */
+	SectorBurst =  calc_SectorBurst();
+
+#ifdef	USE_PARANOIA
+	if (global.paranoia_selected) {
+		int i;
+
+		for (i = 0; i < SectorBurst; i++) {
+			void *dp;
+
+			dp = paranoia_read_limited(global.cdp, paranoia_callback,
+				global.paranoia_parms.retries);
+/*
+			{
+				char *err;
+				char *msg;
+				err = cdda_errors(global.cdp);
+				msg = cdda_messages(global.cdp);
+				if (err) {
+					fputs(err, stderr);
+					free(err);
+				}
+				if (msg) {
+					fputs(msg, stderr);
+					free(msg);
+				}
+			}
+*/
+			if (dp != NULL)	{
+				memcpy(p->data + i*CD_FRAMESAMPLES, dp,
+					CD_FRAMESIZE_RAW);
+			} else {
+				fputs("E unrecoverable error!", stderr);
+				exit(READ_ERROR);
+			}
+		}
+		newbuf = (unsigned char *)p->data;
+		offset = 0;
+        	set_offset(p,offset);
+		added_size = SectorBurst * CD_FRAMESAMPLES;
+		global.overlap = 0;
+		handle_inputendianess(p->data, added_size);
+	} else 
+#endif
+	{
+		unsigned int retry_count;
+#define MAX_READRETRY 12
+
+		retry_count = 0;
+		do {
+			SCSI *usalp = get_scsi_p();
+			int retval;
+#ifdef DEBUG_READS
+fprintf(stderr, "reading from %lu to %lu, overlap %u\n", lSector, lSector + SectorBurst -1, global.overlap);
+#endif
+
+#ifdef DEBUG_BUFFER_ADDRESSES
+fprintf(stderr, "%p %l\n", p->data, global.pagesize);
+if (((unsigned)p->data) & (global.pagesize -1) != 0) {
+  fprintf(stderr, "Address %p is NOT page aligned!!\n", p->data);
+}
+#endif
+
+			if (global.reads_illleadout != 0 && lSector > Get_StartSector(LastTrack())) {
+				int singles = 0;
+				UINT4 bufferSub[CD_FRAMESAMPLES + 24];
+
+				/* we switch to single sector reads,
+				 * in order to handle the remaining sectors. */
+				usalp->silent++;
+				do {
+					int retval2 = ReadCdRomSub( usalp, bufferSub, lSector+singles, 1 );
+					*eorecording = RealEnd( usalp, bufferSub );
+					if (*eorecording) {
+						break;
+					}
+					memcpy(p->data+singles*CD_FRAMESAMPLES, bufferSub, CD_FRAMESIZE_RAW);
+					singles++;
+				} while (singles < SectorBurst);
+				usalp->silent--;
+
+				if ( *eorecording ) {
+					patch_real_end(lSector+singles);
+					SectorBurst = singles;
+#if	DEBUG_ILLLEADOUT
+fprintf(stderr, "iloop=%11lu, nSamplesToDo=%11lu, end=%lu -->\n",
+global.iloop, *nSamplesToDo, lSector+singles);
+#endif
+
+					*nSamplesToDo -= global.iloop - SectorBurst*CD_FRAMESAMPLES;
+					global.iloop = SectorBurst*CD_FRAMESAMPLES;
+#if	DEBUG_ILLLEADOUT
+fprintf(stderr, "iloop=%11lu, nSamplesToDo=%11lu\n\n",
+global.iloop, *nSamplesToDo);
+#endif
+
+				}
+			} else {
+				retval = ReadCdRom( usalp, p->data, lSector, SectorBurst );
+			}
+			handle_inputendianess(p->data, SectorBurst * CD_FRAMESAMPLES);
+			if (NULL ==
+				(newbuf = synchronize( p->data, SectorBurst*CD_FRAMESAMPLES,
+                			*nSamplesToDo-global.iloop ))) {
+				/* could not synchronize!
+				 * Try to invalidate the cdrom cache.
+				 * Increase overlap setting, if possible.
+				 */	
+				/*trash_cache(p->data, lSector, SectorBurst);*/
+				if (global.overlap < global.nsectors - 1) {
+					global.overlap++;
+					lSector--;
+					SectorBurst = calc_SectorBurst();
+#ifdef DEBUG_DYN_OVERLAP
+fprintf(stderr, "using increased overlap of %u\n", global.overlap);
+#endif
+				} else {
+					lSector += global.overlap - 1;
+					global.overlap = 1;
+					SectorBurst =  calc_SectorBurst();
+				}
+			} else
+				break;
+		} while (++retry_count < MAX_READRETRY);
+
+		if (retry_count == MAX_READRETRY && newbuf == NULL && global.verbose != 0) {
+			(*total_unsuccessful_retries)++;
+		}
+
+		if (newbuf) {
+			offset = newbuf - ((unsigned char *)p->data);
+		} else {
+			offset = global.overlap * CD_FRAMESIZE_RAW;
+		}
+		set_offset(p,offset);
+
+		/* how much has been added? */
+		added_size = SectorBurst * CD_FRAMESAMPLES - offset/4;
+
+		if (newbuf && *nSamplesToDo != global.iloop) {
+			minover = min(global.overlap, minover);
+			maxover = max(global.overlap, maxover);
+
+
+			/* should we reduce the overlap setting ? */
+			if (offset > CD_FRAMESIZE_RAW && global.overlap > 1) {
+#ifdef DEBUG_DYN_OVERLAP
+fprintf(stderr, "decreasing overlap from %u to %u (jitter %d)\n", global.overlap, global.overlap-1, offset - (global.overlap)*CD_FRAMESIZE_RAW);
+#endif
+				global.overlap--;
+				SectorBurst =  calc_SectorBurst();
+			}
+		}
+	}
+	if (global.iloop >= added_size) {
+		global.iloop -= added_size;
+	} else {
+		global.iloop = 0;
+	}
+
+	lSector += SectorBurst - global.overlap;
+
+#if	defined	PERCENTAGE_PER_TRACK && defined HAVE_FORK_AND_SHAREDMEM
+	{
+		int as;
+		while ((as = Get_StartSector(current_track+1)) != -1
+			&& lSector >= as) {
+			current_track++;
+		}
+	}
+#endif
+
+	return offset;
+}
+
+static void
+print_percentage(unsigned *poper, int c_offset);
+
+static void print_percentage(unsigned *poper, int c_offset)
+{
+	unsigned per;
+#ifdef	PERCENTAGE_PER_TRACK
+	/* Thomas Niederreiter wants percentage per track */
+	unsigned start_in_track = max(BeginAtSample,
+		Get_AudioStartSector(current_track)*CD_FRAMESAMPLES);
+
+	per = min(BeginAtSample + (long)*nSamplesToDo,
+		Get_StartSector(current_track+1)*CD_FRAMESAMPLES)
+		- (long)start_in_track;
+
+	per = (BeginAtSample+nSamplesDone
+		- start_in_track
+		)/(per/100);
+
+#else
+	per = global.iloop ? (nSamplesDone)/(*nSamplesToDo/100) : 100;
+#endif
+
+	if (global.overlap > 0) {
+		fprintf(stderr, "\r%2d/%2d/%2d/%7d %3d%%",
+			minover, maxover, global.overlap,
+			c_offset - global.overlap*CD_FRAMESIZE_RAW,
+			per);
+	} else if (*poper != per) {
+		fprintf(stderr, "\r%3d%%", per);
+	}
+	*poper = per;
+	fflush(stderr);
+}
+
+static unsigned long do_write(myringbuff *p);
+static unsigned long do_write(myringbuff *p)
+{
+	int current_offset;
+	unsigned int InSamples;
+	static unsigned oper = 200;
+
+	current_offset = get_offset(p);
+
+	/* how many bytes are available? */
+	InSamples = global.nsectors*CD_FRAMESAMPLES - current_offset/4;
+	/* how many samples are wanted? */
+	InSamples = min((*nSamplesToDo-nSamplesDone),InSamples);
+
+	/* when track end is reached, close current file and start a new one */
+	while ((nSamplesDone < *nSamplesToDo) && (InSamples != 0)) {
+		long unsigned int how_much = InSamples;
+
+		long int left_in_track;
+		left_in_track  = Get_StartSector(current_track+1)*CD_FRAMESAMPLES
+				 - (int)(BeginAtSample+nSamplesDone);
+
+		if (*eorecording != 0 && current_track == cdtracks+1 &&
+       		    (*total_segments_read) == (*total_segments_written)+1) {
+			/* limit, if the actual end of the last track is
+			 * not known from the toc. */
+			left_in_track = InSamples;
+		}
+
+if (left_in_track < 0) {
+	fprintf(stderr, "internal error: negative left_in_track:%ld, current_track=%d\n",left_in_track, current_track);
+}
+
+		if (bulk) {
+			how_much = min(how_much, (unsigned long) left_in_track);
+		}
+
+#ifdef MD5_SIGNATURES
+		if (global.md5count) {
+			MD5Update (&global.context, ((unsigned char *)p->data) +current_offset, min(global.md5count,how_much));
+			global.md5count -= min(global.md5count,how_much);
+		}
+#endif
+		if ( SaveBuffer ( p->data + current_offset/4,
+			 how_much,
+			 &nSamplesDone) ) {
+			if (global.have_forked == 1) {
+				pid_t	ppid;
+				/*
+				 * Kill the parent too if we are not orphaned.
+				 */
+				ppid = getppid();
+				if (ppid > 1)
+					kill(ppid, SIGINT);
+			}
+			exit(WRITE_ERROR);
+		}
+
+		global.nSamplesDoneInTrack += how_much;
+		SamplesToWrite -= how_much;
+
+		/* move residual samples upto buffer start */
+		if (how_much < InSamples) {
+			memmove(
+			  (char *)(p->data) + current_offset,
+			  (char *)(p->data) + current_offset + how_much*4,
+			  (InSamples - how_much) * 4);
+		}
+
+		if ((unsigned long) left_in_track <= InSamples || SamplesToWrite == 0) {
+			/* the current portion to be handled is 
+			   the end of a track */
+
+			if (bulk) {
+				/* finish sample file for this track */
+				CloseAudio(global.channels,
+				  global.nSamplesDoneInTrack, global.audio_out);
+			} else if (SamplesToWrite == 0) {
+				/* finish sample file for this track */
+				CloseAudio(global.channels,
+				  (unsigned int) *nSamplesToDo, global.audio_out);
+			}
+
+			if (global.verbose) {
+#ifdef	USE_PARANOIA
+				double	f;
+#endif
+				print_percentage(&oper, current_offset);
+				fputc(' ', stderr);
+#ifndef	THOMAS_SCHAU_MAL
+				if ((unsigned long)left_in_track > InSamples) {
+					fputs(" incomplete", stderr);
+				}
+#endif
+				if (global.tracktitle[current_track] != NULL) {
+					fprintf( stderr,
+						" track %2u '%s' recorded", 
+						current_track,
+						global.tracktitle[current_track]);
+				} else {
+					fprintf( stderr,
+						" track %2u recorded",
+						current_track);
+				}
+#ifdef	USE_PARANOIA
+				oper = para_stat->readerrs + para_stat->skips +
+					  para_stat->fixup_edges + para_stat->fixup_atoms + 
+					  para_stat->fixup_droppeds + para_stat->fixup_dupeds + 
+					  para_stat->drifts;
+				f = (100.0 * oper) / (((double)global.nSamplesDoneInTrack)/588.0);
+
+				if (para_stat->readerrs) {
+					fprintf(stderr, " with audible hard errors");
+				} else if ((para_stat->skips) > 0) {
+					fprintf(stderr, " with %sretry/skip errors",
+							f < 2.0 ? "":"audible ");
+				} else if (oper > 0) {
+					oper = f;
+					
+					fprintf(stderr, " with ");
+					if (oper < 2)
+						fprintf(stderr, "minor");
+					else if (oper < 10)
+						fprintf(stderr, "medium");
+					else if (oper < 67)
+						fprintf(stderr, "noticable audible");
+					else if (oper < 100)
+						fprintf(stderr, "major audible");
+					else
+						fprintf(stderr, "extreme audible");
+					fprintf(stderr, " problems");
+				} else {
+					fprintf(stderr, " successfully");
+				}
+				if (f >= 0.1)
+					fprintf(stderr, " (%.1f%% problem sectors)", f);
+#else
+				fprintf(stderr, " successfully");
+#endif
+
+				if (waitforsignal == 1) {
+					fprintf(stderr, ". %d silent samples omitted", global.SkippedSamples);
+				}
+				fputs("\n", stderr);
+
+				if (global.reads_illleadout && *eorecording == 1) {
+					fprintf(stderr, "Real lead out at: %ld sectors\n", 
+					  (*nSamplesToDo+BeginAtSample)/CD_FRAMESAMPLES);
+				}
+#ifdef	USE_PARANOIA
+				if (global.paranoia_selected) {
+					oper = 200;	/* force new output */
+					print_percentage(&oper, current_offset);
+					if (para_stat->minoverlap == 0x7FFFFFFF)
+						para_stat->minoverlap = 0;
+					fprintf(stderr, "  %u rderr, %u skip, %u atom, %u edge, %u drop, %u dup, %u drift\n"
+						,para_stat->readerrs
+						,para_stat->skips
+						,para_stat->fixup_atoms
+						,para_stat->fixup_edges
+						,para_stat->fixup_droppeds
+						,para_stat->fixup_dupeds
+						,para_stat->drifts);
+					oper = 200;	/* force new output */
+					print_percentage(&oper, current_offset);
+					fprintf(stderr, "  %u overlap(%.4g .. %.4g)\n",
+						para_stat->overlaps,
+						(float)para_stat->minoverlap / (2352.0/2.0),
+						(float)para_stat->maxoverlap / (2352.0/2.0));
+					paranoia_reset();
+				}
+#endif
+			}
+
+			global.nSamplesDoneInTrack = 0;
+			if ( bulk && SamplesToWrite > 0 ) {
+				if ( !global.no_file ) {
+					char *tmp_fname;
+
+					/* build next filename */
+					tmp_fname = get_next_name();
+					if (tmp_fname != NULL) {
+						strncpy(global.fname_base,
+							tmp_fname,
+							sizeof global.fname_base);
+						global.fname_base[
+							sizeof(global.fname_base)-1] =
+							'\0';
+					}
+
+					tmp_fname = cut_extension(global.fname_base);
+					tmp_fname[0] = '\0';
+
+					if (global.multiname == 0) {
+						sprintf(fname, "%s_%02u.%s",
+							global.fname_base,
+							current_track+1,
+							audio_type);
+					} else {
+						sprintf(fname, "%s.%s",
+							global.fname_base,
+							audio_type);
+					}
+
+					OpenAudio( fname, rate, bits, global.channels,
+						(Get_AudioStartSector(current_track+1) -
+						 Get_AudioStartSector(current_track))
+							*CD_FRAMESIZE_RAW,
+						global.audio_out);
+				} /* global.nofile */
+			} /* if ( bulk && SamplesToWrite > 0 ) */
+			current_track++;
+
+		} /* left_in_track <= InSamples */
+		InSamples -= how_much;
+
+	}  /* end while */
+	if (!global.quiet && *nSamplesToDo != nSamplesDone) {
+		print_percentage(&oper, current_offset);
+	}
+	return nSamplesDone;
+}
+
+#define PRINT_OVERLAP_INIT \
+   if (global.verbose) { \
+	if (global.overlap > 0) \
+		fprintf(stderr, "overlap:min/max/cur, jitter, percent_done:\n  /  /  /          0%%"); \
+	else \
+		fputs("percent_done:\n  0%", stderr); \
+   }
+
+#if defined HAVE_FORK_AND_SHAREDMEM
+static void forked_read(void);
+
+/* This function does all audio cdrom reads
+ * until there is nothing more to do
+ */
+static void forked_read()
+{
+   unsigned total_unsuccessful_retries = 0;
+
+#if !defined(HAVE_SEMGET) || !defined(USE_SEMAPHORES)
+   init_child();
+#endif
+
+   minover = global.nsectors;
+
+   PRINT_OVERLAP_INIT
+   while (global.iloop) { 
+
+      do_read(get_next_buffer(), &total_unsuccessful_retries);
+
+      define_buffer();
+
+   } /* while (global.iloop) */
+
+   if (total_unsuccessful_retries) {
+      fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries);
+   }
+}
+
+static void forked_write(void);
+
+static void forked_write()
+{
+
+    /* don't need these anymore.  Good security policy says we get rid
+       of them ASAP */
+	priv_off();
+	neverneedroot();
+	neverneedgroup();
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+#else
+    init_parent();
+#endif
+
+    for (;nSamplesDone < *nSamplesToDo;) {
+	if (*eorecording == 1 && (*total_segments_read) == (*total_segments_written)) break;
+
+	/* get oldest buffers */
+      
+	nSamplesDone = do_write(get_oldest_buffer());
+
+        drop_buffer();
+
+    } /* end for */
+
+}
+#endif
+
+/* This function implements the read and write calls in one loop (in case
+ * there is no fork/thread_create system call).
+ * This means reads and writes have to wait for each other to complete.
+ */
+static void nonforked_loop(void);
+
+static void nonforked_loop()
+{
+    unsigned total_unsuccessful_retries = 0;
+
+    minover = global.nsectors;
+
+    PRINT_OVERLAP_INIT
+    while (global.iloop) { 
+
+      do_read(get_next_buffer(), &total_unsuccessful_retries);
+
+      do_write(get_oldest_buffer());
+
+    }
+
+    if (total_unsuccessful_retries) {
+      fprintf(stderr,"%u unsuccessful matches while reading\n",total_unsuccessful_retries);
+    }
+
+}
+
+void verbose_usage(void);
+
+void verbose_usage()
+{
+	fputs("\
+	help		lists all verbose options.\n\
+	disable		disables verbose mode.\n\
+	all		enables all verbose options.\n\
+	toc		display the table of contents.\n\
+	summary		display a summary of track parameters.\n\
+	indices		retrieve/display index positions.\n\
+	catalog		retrieve/display media catalog number.\n\
+	trackid		retrieve/display international standard recording code.\n\
+	sectors		display the start sectors of each track.\n\
+	titles		display any known track titles.\n\
+", stderr);
+}
+
+#ifdef	USE_PARANOIA
+void paranoia_usage(void);
+
+void paranoia_usage()
+{
+	fputs("\
+	help		lists all paranoia options.\n\
+	disable		disables paranoia mode. Paranoia is still being used.\n\
+	no-verify	switches verify off, and overlap on.\n\
+	retries=amount	set the number of maximum retries per sector.\n\
+	overlap=amount	set the number of sectors used for statical paranoia overlap.\n\
+	minoverlap=amt	set the min. number of sectors used for dynamic paranoia overlap.\n\
+	maxoverlap=amt	set the max. number of sectors used for dynamic paranoia overlap.\n\
+", stderr);
+}
+#endif
+
+int
+handle_verbose_opts(char *optstr, long *flagp);
+
+int handle_verbose_opts(char *optstr, long *flagp)
+{
+	char	*ep;
+	char	*np;
+	int	optlen;
+
+	*flagp = 0;
+	while (*optstr) {
+		if ((ep = strchr(optstr, ',')) != NULL) {
+			optlen = ep - optstr;
+			np = ep + 1;
+		} else {
+			optlen = strlen(optstr);
+			np = optstr + optlen;
+		}
+		if (strncmp(optstr, "toc", optlen) == 0) {
+			*flagp |= SHOW_TOC;
+		}
+		else if (strncmp(optstr, "summary", optlen) == 0) {
+			*flagp |= SHOW_SUMMARY;
+		}
+		else if (strncmp(optstr, "indices", optlen) == 0) {
+			*flagp |= SHOW_INDICES;
+		}
+		else if (strncmp(optstr, "catalog", optlen) == 0) {
+			*flagp |= SHOW_MCN;
+		}
+		else if (strncmp(optstr, "trackid", optlen) == 0) {
+			*flagp |= SHOW_ISRC;
+		}
+		else if (strncmp(optstr, "sectors", optlen) == 0) {
+			*flagp |= SHOW_STARTPOSITIONS;
+		}
+		else if (strncmp(optstr, "titles", optlen) == 0) {
+			*flagp |= SHOW_TITLES;
+		}
+		else if (strncmp(optstr, "all", optlen) == 0) {
+			*flagp |= SHOW_MAX;
+		}
+		else if (strncmp(optstr, "disable", optlen) == 0) {
+			*flagp = 0;
+		}
+		else if (strncmp(optstr, "help", optlen) == 0) {
+			verbose_usage();
+			exit(NO_ERROR);
+		}
+		else {
+			char	*endptr;
+			unsigned arg = strtoul(optstr, &endptr, 10);
+			if (optstr != endptr
+				&& arg <= SHOW_MAX) {
+				*flagp |= arg;
+				fprintf(stderr, "Warning: numerical parameters for -v are no more supported in the next releases!\n");
+			}
+			else {
+				fprintf(stderr, "unknown option %s\n", optstr);
+				verbose_usage();
+				exit(SYNTAX_ERROR);
+			}
+		}
+		optstr = np;
+	}
+	return 1;
+}
+
+
+int
+handle_paranoia_opts(char *optstr, long *flagp);
+
+int handle_paranoia_opts(char *optstr, long *flagp)
+{
+#ifdef	USE_PARANOIA
+	char	*ep;
+	char	*np;
+	int	optlen;
+
+	while (*optstr) {
+		if ((ep = strchr(optstr, ',')) != NULL) {
+			optlen = ep - optstr;
+			np = ep + 1;
+		} else {
+			optlen = strlen(optstr);
+			np = optstr + optlen;
+		}
+		if (strncmp(optstr, "retries=", min(8,optlen)) == 0) {
+			char *eqp = strchr(optstr, '=');
+			int   rets;
+
+			astoi(eqp+1, &rets);
+			if (rets >= 0) {
+				global.paranoia_parms.retries = rets;
+			}
+		}
+		else if (strncmp(optstr, "overlap=", min(8, optlen)) == 0) {
+			char *eqp = strchr(optstr, '=');
+			int   rets;
+
+			astoi(eqp+1, &rets);
+			if (rets >= 0) {
+				global.paranoia_parms.overlap = rets;
+			}
+		}
+		else if (strncmp(optstr, "minoverlap=", min(11, optlen)) == 0) {
+			char *eqp = strchr(optstr, '=');
+			int   rets;
+
+			astoi(eqp+1, &rets);
+			if (rets >= 0) {
+				global.paranoia_parms.mindynoverlap = rets;
+			}
+		}
+		else if (strncmp(optstr, "maxoverlap=", min(11, optlen)) == 0) {
+			char *eqp = strchr(optstr, '=');
+			int   rets;
+
+			astoi(eqp+1, &rets);
+			if (rets >= 0) {
+				global.paranoia_parms.maxdynoverlap = rets;
+			}
+		}
+		else if (strncmp(optstr, "no-verify", optlen) == 0) {
+			global.paranoia_parms.disable_extra_paranoia = 1;
+		}
+		else if (strncmp(optstr, "disable", optlen) == 0) {
+			global.paranoia_parms.disable_paranoia = 1;
+		}
+		else if (strncmp(optstr, "help", optlen) == 0) {
+			paranoia_usage();
+			exit(NO_ERROR);
+		}
+		else {
+			fprintf(stderr, "unknown option %s\n", optstr);
+			paranoia_usage();
+			exit(SYNTAX_ERROR);
+		}
+		optstr = np;
+	}
+	return 1;
+#else
+	fputs("lib paranoia support is not configured!\n", stderr);
+	return 0;
+#endif
+}
+
+
+/* and finally: the MAIN program */
+int main(int argc, char *argv[])
+{
+  long lSector_p1;
+  long sector_offset = 0;
+  unsigned long endtrack = 1;
+  double rectime = DURATION;
+  int cd_index = -1;
+  double int_part;
+  int littleendian = -1;
+  char *int_name;
+  static char *user_sound_device = "";
+  char * env_p;
+  int tracks_included;
+	int	moreargs;
+
+  int_name = DEF_INTERFACE;
+  audio_type = AUDIOTYPE;
+  save_args(argc, argv);
+
+  /* init global variables */
+  init_globals();
+{
+  int am_i_cdda2wav;
+  /* When being invoked as list_audio_tracks, just dump a list of
+     audio tracks. */
+  am_i_cdda2wav = !(strlen(argv[0]) >= sizeof("list_audio_tracks")-1
+	&& !strcmp(argv[0]+strlen(argv[0])+1-sizeof("list_audio_tracks"),"list_audio_tracks"));
+  if (!am_i_cdda2wav) global.verbose = SHOW_JUSTAUDIOTRACKS;
+}
+  /* Control those set-id privileges... */
+  initsecurity();
+
+  env_p = getenv("CDDA_DEVICE");
+  if (env_p != NULL) {
+    global.dev_name = env_p;
+  }
+
+  env_p = getenv("CDDBP_SERVER");
+  if (env_p != NULL) {
+    global.cddbp_server = env_p;
+  }
+
+  env_p = getenv("CDDBP_PORT");
+  if (env_p != NULL) {
+    global.cddbp_port = env_p;
+  }
+
+{
+	int	cac;
+	char	*const*cav;
+
+	BOOL	version = FALSE;
+	BOOL	help = FALSE;
+	char	*channels = NULL;
+	int	irate = -1;
+	char	*divider = NULL;
+	char	*trackspec = NULL;
+	char	*duration = NULL;
+
+	char	*oendianess = NULL;
+	char	*cendianess = NULL;
+	int	cddbp = -1;
+	BOOL	stereo = FALSE;
+	BOOL	mono = FALSE;
+	BOOL	domax = FALSE;
+	BOOL	dump_rates = FALSE;
+	int	userverbose = -1;
+	long	paraopts = 0;
+
+	cac = argc;
+	cav = argv;
+	cac--;
+	cav++;
+	if (getargs(&cac, &cav, opts
+			, &global.paranoia_selected
+			, handle_paranoia_opts, &paraopts
+			, &version
+			, &help, &help
+
+			, &global.no_file, &global.no_file
+			, &dump_rates, &dump_rates
+			, &bulk, &bulk, &bulk
+			, &global.scsi_verbose, &global.scsi_verbose
+
+			, &global.findminmax, &global.findminmax
+			, &global.findmono, &global.findmono
+			, &global.no_infofile, &global.no_infofile
+
+			, &global.deemphasize, &global.deemphasize
+			, &global.just_the_toc, &global.just_the_toc
+			, &global.scsi_silent, &global.scsi_silent
+
+			, &global.cddbp_server, &global.cddbp_port
+			, &global.scanbus
+			, &global.dev_name, &global.dev_name, &global.dev_name
+			, &global.aux_name, &global.aux_name
+			, &int_name, &int_name
+			, &audio_type, &audio_type
+
+			, &oendianess, &oendianess
+			, &cendianess, &cendianess
+			, &global.userspeed, &global.userspeed
+
+			, &global.playback_rate, &global.playback_rate
+			, &global.md5blocksize, &global.md5blocksize
+			, &global.useroverlap, &global.useroverlap
+			, &user_sound_device, &user_sound_device
+
+			, &cddbp, &cddbp
+			, &channels, &channels
+			, &bits, &bits
+			, &irate, &irate
+			, &global.gui, &global.gui
+
+			, &divider, &divider
+			, &trackspec, &trackspec
+			, &cd_index, &cd_index
+			, &duration, &duration
+			, &sector_offset, &sector_offset
+
+			, &global.nsectors, &global.nsectors
+			, handle_verbose_opts, &userverbose
+			, handle_verbose_opts, &userverbose
+			, &global.buffers, &global.buffers
+
+			, &stereo, &stereo
+			, &mono, &mono
+			, &waitforsignal, &waitforsignal
+			, &global.echo, &global.echo
+			, &global.quiet, &global.quiet
+			, &domax, &domax
+
+			) < 0) {
+		errmsgno(EX_BAD, "Bad Option: %s.\n", cav[0]);
+		fputs ("use 'cdda2wav -help' to get more information.\n", stderr);
+		exit (SYNTAX_ERROR);
+	}
+	if (getfiles(&cac, &cav, opts) == 0)
+		/* No more file type arguments */;
+	moreargs = cav - argv;
+	if (version) {
+		fputs ("cdda2wav version ", stderr);
+		fputs (VERSION, stderr);
+		fputs ("\n"
+          "NOTE: modified version of the cdrkit suite, differs from the original\n", stderr);
+		exit (NO_ERROR);
+	}
+	if (help) {
+		usage();
+	}
+	if (!global.scanbus)
+		cdr_defaults(&global.dev_name, NULL, NULL, NULL); 
+	if (dump_rates) {	/* list available rates */
+		int ii;
+
+		fputs("\
+Available rates are:\n\
+Rate   Divider      Rate   Divider      Rate   Divider      Rate   Divider\n\
+"			, stderr );
+		for (ii = 1; ii <= 44100 / 880 / 2; ii++) {
+			long i2 = ii;
+			fprintf(stderr, "%7.1f  %2ld         %7.1f  %2ld.5       ",
+	        		44100.0/i2, i2, 44100.0/(i2+0.5), i2);
+			i2 += 25;
+			fprintf(stderr, "%7.1f  %2ld         %7.1f  %2ld.5\n",
+        			44100.0/i2, i2, 44100.0/(i2+0.5), i2);
+			i2 -= 25;
+		}
+		exit(NO_ERROR);
+	}
+	if (channels) {
+		if (*channels == 's') {
+			global.channels = 2;
+			global.swapchannels = 1;
+		} else {
+			global.channels = strtol(channels, NULL, 10);
+		}
+	}
+	if (irate >= 0) {
+		rate = irate;
+	}
+	if (divider) {
+		double divider_d;
+		divider_d = strtod(divider , NULL);
+		if (divider_d > 0.0) {
+			rate = 44100.0 / divider_d;
+		} else {
+			fputs("E option -divider requires a nonzero, positive argument.\nSee -dump-rates.", stderr);
+			exit(SYNTAX_ERROR);
+		}
+	}
+	if (trackspec) {
+		char * endptr;
+		char * endptr2;
+		track = strtoul(trackspec, &endptr, 10 );
+		endtrack = strtoul(endptr, &endptr2, 10 );
+		if (endptr2 == endptr) {
+			endtrack = track;
+		} else if (track == endtrack) {
+			bulk = -1;
+		}
+	}
+	if (duration) {
+		char *end_ptr = NULL;
+		rectime = strtod(duration, &end_ptr );
+		if (*end_ptr == 'f') {
+			rectime = rectime / 75.0;
+			/* TODO: add an absolute end of recording. */
+#if	0
+		} else if (*end_ptr == 'F') {
+			rectime = rectime / 75.0;
+#endif
+		} else if (*end_ptr != '\0') {
+			rectime = -1.0;
+		}
+	}
+	if (oendianess) {
+		if (strcasecmp(oendianess, "little") == 0) {
+			global.outputendianess = LITTLE;
+		} else if (strcasecmp(oendianess, "big") == 0) {
+			global.outputendianess = BIG;
+		} else {
+			usage2("wrong parameter '%s' for option -E", oendianess);
+		}
+	}
+	if (cendianess) {
+		if (strcasecmp(cendianess, "little") == 0) {
+			littleendian = 1;
+		} else if (strcasecmp(cendianess, "big") == 0) {
+			littleendian = 0;
+		} else if (strcasecmp(cendianess, "guess") == 0) {
+			littleendian = -2;
+		} else {
+			usage2("wrong parameter '%s' for option -C", cendianess);
+		}
+	}
+	if (cddbp >= 0) {
+		global.cddbp = 1 + cddbp;
+	}
+	if (stereo) {
+		global.channels = 2;
+	}
+	if (mono) {
+		global.channels = 1;
+        	global.need_hostorder = 1;
+	}
+	if (global.echo) {
+#ifdef	ECHO_TO_SOUNDCARD
+		if (global.playback_rate != 100) {
+		        RestrictPlaybackRate( global.playback_rate );
+		}
+       		global.need_hostorder = 1;
+#else
+		fprintf(stderr, "There is no sound support compiled into %s.\n",argv[0]);
+		global.echo = 0;
+#endif
+	}
+	if (global.quiet) {
+		global.verbose = 0;
+	}
+	if (domax) {
+		global.channels = 2; bits = 16; rate = 44100;
+	}
+	if (global.findminmax) {
+	        global.need_hostorder = 1;
+	}
+	if (global.deemphasize) {
+	        global.need_hostorder = 1;
+	}
+	if (global.just_the_toc) {
+		global.verbose = SHOW_MAX;
+		bulk = 1;
+	}
+	if (global.gui) {
+#ifdef	Thomas_will_es
+		global.no_file = 1;
+		global.no_infofile = 1;
+		global.verbose = SHOW_MAX;
+#endif
+		global.no_cddbfile = 1;
+	}
+	if (global.no_file) {
+		global.no_infofile = 1;
+		global.no_cddbfile = 1;
+	}
+	if (global.no_infofile) {
+		global.no_cddbfile = 1;
+	}
+	if (global.md5blocksize) {
+#ifdef	MD5_SIGNATURES
+		fputs("MD5 signatures are currently broken! Sorry\n", stderr);
+#else
+		fputs("The option MD5 signatures is not configured!\n", stderr);
+#endif
+	}
+	if (user_sound_device) {
+#ifndef	ECHO_TO_SOUNDCARD
+		fputs("There is no sound support configured!\n", stderr);
+#endif
+	}
+	if (global.paranoia_selected) {
+		global.useroverlap = 0;
+	}
+	if (userverbose >= 0) {
+		global.verbose = userverbose;
+	}
+}
+
+  /* check all parameters */
+  if (global.buffers < 1) {
+    usage2("Incorrect buffer setting: %d", global.buffers);
+  }
+
+  if (global.nsectors < 1) {
+    usage2("Incorrect nsectors setting: %d", global.nsectors);
+  }
+
+  if (global.verbose < 0 || global.verbose > SHOW_MAX) {
+    usage2("Incorrect verbose level setting: %d",global.verbose);
+  }
+  if (global.verbose == 0) global.quiet = 1;
+
+  if ( rectime < 0.0 ) {
+    usage2("Incorrect recording time setting: %d.%02d",
+			(int)rectime, (int)(rectime*100+0.5) % 100);
+  }
+
+  if ( global.channels != 1 && global.channels != 2 ) {
+    usage2("Incorrect channel setting: %d",global.channels);
+  }
+
+  if ( bits != 8 && bits != 12 && bits != 16 ) {
+    usage2("Incorrect bits_per_sample setting: %d",bits);
+  }
+
+  if ( rate < 827.0 || rate > 44100.0 ) {
+    usage2("Incorrect sample rate setting: %d.%02d",
+	(int)rate, ((int)rate*100) % 100);
+  }
+
+  int_part = (double)(long) (2*44100.0 / rate);
+  
+  if (2*44100.0 / rate - int_part >= 0.5 ) {
+      int_part += 1.0;
+      fprintf( stderr, "Nearest available sample rate is %d.%02d Hertz\n",
+	      2*44100 / (int)int_part,
+	      (2*4410000 / (int)int_part) % 100);
+  }
+  Halved = ((int) int_part) & 1;
+  rate = 2*44100.0 / int_part;
+  undersampling = (int) int_part / 2.0;
+  samples_to_do = undersampling;
+
+  if (!strcmp((char *)int_name,"generic_scsi"))
+      interface = GENERIC_SCSI;
+  else if (!strcmp((char *)int_name,"cooked_ioctl"))
+      interface = COOKED_IOCTL;
+  else  {
+    usage2("Incorrect interface setting: %s",int_name);
+  }
+
+  /* check * init audio file */
+  if (!strncmp(audio_type,"wav",3)) {
+    global.audio_out = &wavsound;
+  } else if (!strncmp(audio_type, "sun", 3) || !strncmp(audio_type, "au", 2)) {
+    /* Enhanced compatibility */
+    audio_type = "au";
+    global.audio_out = &sunsound;
+  } else if (!strncmp(audio_type, "cdr", 3) || 
+             !strncmp(audio_type, "raw", 3)) {
+    global.audio_out = &rawsound;
+  } else if (!strncmp(audio_type, "aiff", 4)) {
+    global.audio_out = &aiffsound;
+  } else if (!strncmp(audio_type, "aifc", 4)) {
+    global.audio_out = &aifcsound;
+#ifdef USE_LAME
+  } else if (!strncmp(audio_type, "mp3", 3)) {
+    global.audio_out = &mp3sound;
+    if (!global.quiet) {
+	unsigned char Lame_version[20];
+
+	fetch_lame_version(Lame_version);
+	fprintf(stderr, "Using LAME version %s.\n", Lame_version);
+    }
+    if (bits < 9) {
+	bits = 16;
+	fprintf(stderr, "Warning: sample size forced to 16 bit for MP3 format.\n");
+    }
+#endif /* USE_LAME */
+  } else {
+    usage2("Incorrect audio type setting: %3s", audio_type);
+  }
+
+  if (bulk == -1) bulk = 0;
+
+  global.need_big_endian = global.audio_out->need_big_endian;
+  if (global.outputendianess != NONE)
+    global.need_big_endian = global.outputendianess == BIG;
+
+  if (global.no_file) global.fname_base[0] = '\0';
+
+  if (!bulk) {
+    strcat(global.fname_base, ".");
+    strcat(global.fname_base, audio_type);
+  }
+
+  /* If we need to calculate with samples or write them to a soundcard,
+   * we need a conversion to host byte order.
+   */ 
+  if (global.channels != 2 
+      || bits != 16
+      || rate != 44100)
+	global.need_hostorder = 1;
+
+  /* Bad hack!!
+   * Remove for release 2.0
+   * this is a bug compatibility feature.
+   */
+  if (global.gui && global.verbose == SHOW_TOC)
+	global.verbose |= SHOW_STARTPOSITIONS | SHOW_SUMMARY | SHOW_TITLES;
+
+  /*
+   * all options processed.
+   * Now a file name per track may follow 
+   */
+  argc2 = argc3 = argc - moreargs;
+  argv2 = argv + moreargs;
+  if ( moreargs < argc ) {
+    if (!strcmp(argv[moreargs],"-")) {
+#ifdef	NEED_O_BINARY
+      setmode(fileno(stdout), O_BINARY);
+#endif
+      global.audio = dup (fileno(stdout));
+      strncpy( global.fname_base, "standard_output", sizeof(global.fname_base) );
+      global.fname_base[sizeof(global.fname_base)-1]=0;
+    } else if (!is_fifo(argv[moreargs])) {
+	/* we do have at least one argument */
+	global.multiname = 1;
+    }
+  }
+
+#define SETSIGHAND(PROC, SIG, SIGNAME) if (signal(SIG, PROC) == SIG_ERR) \
+	{ fprintf(stderr, "cannot set signal %s handler\n", SIGNAME); exit(SETSIG_ERROR); }
+    SETSIGHAND(exit_wrapper, SIGINT, "SIGINT")
+    SETSIGHAND(exit_wrapper, SIGQUIT, "SIGQUIT")
+    SETSIGHAND(exit_wrapper, SIGTERM, "SIGTERM")
+    SETSIGHAND(exit_wrapper, SIGHUP, "SIGHUP")
+
+    SETSIGHAND(set_nonforked, SIGPIPE, "SIGPIPE")
+
+  /* setup interface and open cdrom device */
+  /* request sychronization facilities and shared memory */
+  SetupInterface( );
+
+  /* use global.useroverlap to set our overlap */
+  if (global.useroverlap != -1)
+	global.overlap = global.useroverlap;
+
+  /* check for more valid option combinations */
+
+  if (global.nsectors < 1+global.overlap) {
+	fprintf( stderr, "Warning: Setting #nsectors to minimum of %d, due to jitter correction!\n", global.overlap+1);
+	  global.nsectors = global.overlap+1;
+  }
+
+  if (global.overlap > 0 && global.buffers < 2) {
+	fprintf( stderr, "Warning: Setting #buffers to minimum of 2, due to jitter correction!\n");
+	  global.buffers = 2;
+  }
+
+    /* Value of 'nsectors' must be defined here */
+
+    global.shmsize = 0;
+#ifdef	USE_PARANOIA
+    while (global.shmsize < sizeof (struct paranoia_statistics))
+		global.shmsize += global.pagesize;
+#endif
+    global.shmsize += 10*global.pagesize;	/* XXX Der Speicherfehler ist nicht in libparanoia sondern in cdda2wav :-( */
+    global.shmsize += HEADER_SIZE + ENTRY_SIZE_PAGE_AL * global.buffers;
+
+#if	defined (HAVE_FORK_AND_SHAREDMEM)
+	/*
+	 * The (void *) cast is to avoid a GCC warning like:
+	 * warning: dereferencing type-punned pointer will break strict-aliasing rules
+	 * which does not apply to this code. (void *) introduces a compatible
+	 * intermediate type in the cast list.
+	 */
+    he_fill_buffer = request_shm_sem(global.shmsize, (unsigned char **)(void *)&he_fill_buffer);
+    if (he_fill_buffer == NULL) {
+	fprintf( stderr, "no shared memory available!\n");
+	exit(SHMMEM_ERROR);
+    }
+#else /* do not have fork() and shared memory */
+    he_fill_buffer = malloc(global.shmsize);
+    if (he_fill_buffer == NULL) {
+	fprintf( stderr, "no buffer memory available!\n");
+	exit(NOMEM_ERROR);
+    }
+#endif
+#ifdef	USE_PARANOIA
+    {
+	int	i = 0;
+
+	para_stat = (struct paranoia_statistics *)he_fill_buffer;
+	while (i < sizeof (struct paranoia_statistics)) {
+			i += global.pagesize;
+			he_fill_buffer += global.pagesize;
+			global.shmsize -= global.pagesize;
+	}
+    }
+#endif
+
+    if (global.verbose != 0)
+   	 fprintf(stderr,
+   		 "%u bytes buffer memory requested, %d buffers, %d sectors\n",
+   		 global.shmsize, global.buffers, global.nsectors);
+
+    /* initialize pointers into shared memory segment */
+    last_buffer = he_fill_buffer + 1;
+    total_segments_read = (unsigned long *) (last_buffer + 1);
+    total_segments_written = total_segments_read + 1;
+    child_waits = (int *) (total_segments_written + 1);
+    parent_waits = child_waits + 1;
+    in_lendian = parent_waits + 1;
+    eorecording = in_lendian + 1;
+    *total_segments_read = *total_segments_written = 0;
+    nSamplesToDo = (unsigned long *)(eorecording + 1);
+    *eorecording = 0;
+    *in_lendian = global.in_lendian;
+
+    set_total_buffers(global.buffers, sem_id);
+
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+  atexit ( free_sem );
+#endif
+
+  /*
+   * set input endian default
+   */
+  if (littleendian != -1)
+    *in_lendian = littleendian;
+
+  /* get table of contents */
+  cdtracks = ReadToc();
+  if (cdtracks == 0) {
+    fprintf(stderr, "No track in table of contents! Aborting...\n");
+    exit(MEDIA_ERROR);
+  }
+
+  calc_cddb_id();
+  calc_cdindex_id();
+
+#if	1
+  Check_Toc();
+#endif
+
+  if (ReadTocText != NULL && FirstAudioTrack () != -1) {
+	ReadTocText(get_scsi_p());
+	handle_cdtext();
+  }
+  if ( global.verbose == SHOW_JUSTAUDIOTRACKS ) {
+    unsigned int z;
+
+    for (z = 0; z < cdtracks; z++)
+	if (Get_Datatrack(z) == 0)
+	  printf("%02d\t%06ld\n", Get_Tracknumber(z), Get_AudioStartSector(z));
+    exit(NO_ERROR);
+  }
+
+  if ( global.verbose != 0 ) {
+    fputs( "#Cdda2wav version ", stderr );
+    fputs( VERSION, stderr );
+#if defined USE_POSIX_PRIORITY_SCHEDULING || defined HAVE_SYS_PRIOCNTL_H
+    fputs( ", real time sched.", stderr );
+#endif
+#if defined ECHO_TO_SOUNDCARD
+    fputs( ", soundcard", stderr );
+#endif
+#if defined USE_PARANOIA
+    fputs( ", libparanoia", stderr );
+#endif
+    fputs( " support\n", stderr );
+  }
+
+  FixupTOC(cdtracks + 1);
+
+#if	0
+  if (!global.paranoia_selected) {
+    fprintf(stderr, "NICE\n");
+    /* try to get some extra kicks */
+    priv_on();
+    needroot(0);
+#if defined HAVE_SETPRIORITY
+    setpriority(PRIO_PROCESS, 0, -20);
+#else
+# if defined(HAVE_NICE) && (HAVE_NICE == 1)
+    nice(-20);
+# endif
+#endif
+    priv_off();
+    dontneedroot();
+  }
+#endif
+
+  /* switch cdrom to audio mode */
+  EnableCdda (get_scsi_p(), 1, CD_FRAMESIZE_RAW);
+
+  atexit ( CloseAll );
+
+  DisplayToc();
+  if ( FirstAudioTrack () == -1 ) {
+    if (no_disguised_audiotracks()) {
+      FatalError ( "This disk has no audio tracks\n" );
+    }
+  }
+
+  Read_MCN_ISRC();
+
+  /* check if start track is in range */
+  if ( track < 1 || track > cdtracks ) {
+    usage2("Incorrect start track setting: %d",track);
+  }
+
+  /* check if end track is in range */
+  if ( endtrack < track || endtrack > cdtracks ) {
+    usage2("Incorrect end track setting: %ld",endtrack);
+  }
+
+  do {
+    lSector = Get_AudioStartSector ( track );
+    lSector_p1 = Get_EndSector ( track ) + 1;
+
+    if ( lSector < 0 ) {
+      if ( bulk == 0 ) {
+        FatalError ( "Track %d not found\n", track );
+      } else {
+        fprintf(stderr, "Skipping data track %d...\n", track);
+	if (endtrack == track) endtrack++;
+        track++;
+      }
+    }
+  } while (bulk != 0 && track <= cdtracks && lSector < 0);
+
+  if ((global.illleadout_cd == 0 || global.reads_illleadout != 0) && cd_index != -1) {
+    if (global.verbose && !global.quiet) {
+      global.verbose |= SHOW_INDICES;
+    }
+    sector_offset += ScanIndices( track, cd_index, bulk );
+  } else {
+    cd_index = 1;
+    if (global.deemphasize || (global.verbose & SHOW_INDICES)) {
+      ScanIndices( track, cd_index, bulk );
+    }
+  }
+
+  lSector += sector_offset;
+  /* check against end sector of track */
+  if ( lSector >= lSector_p1 ) {
+    fprintf(stderr, "W Sector offset %lu exceeds track size (ignored)\n", sector_offset );
+    lSector -= sector_offset;
+  }
+
+  if ( lSector < 0L ) {
+    fputs( "Negative start sector! Set to zero.\n", stderr );
+    lSector = 0L;
+  }
+
+  lSector_p2 = Get_LastSectorOnCd( track );
+  if (bulk == 1 && track == endtrack && rectime == 0.0)
+     rectime = 99999.0;
+  if ( rectime == 0.0 ) {
+    /* set time to track time */
+    *nSamplesToDo = (lSector_p1 - lSector) * CD_FRAMESAMPLES;
+    rectime = (lSector_p1 - lSector) / 75.0;
+    if (CheckTrackrange( track, endtrack) == 1) {
+      lSector_p2 = Get_EndSector ( endtrack ) + 1;
+
+      if (lSector_p2 >= 0) {
+        rectime = (lSector_p2 - lSector) / 75.0;
+        *nSamplesToDo = (long)(rectime*44100.0 + 0.5);
+      } else {
+        fputs( "End track is no valid audio track (ignored)\n", stderr );
+      }
+    } else {
+      fputs( "Track range does not consist of audio tracks only (ignored)\n", stderr );
+    }
+  } else {
+    /* Prepare the maximum recording duration.
+     * It is defined as the biggest amount of
+     * adjacent audio sectors beginning with the
+     * specified track/index/offset. */
+
+    if ( rectime > (lSector_p2 - lSector) / 75.0 ) {
+      rectime = (lSector_p2 - lSector) / 75.0;
+      lSector_p1 = lSector_p2;
+    }
+
+    /* calculate # of samples to read */
+    *nSamplesToDo = (long)(rectime*44100.0 + 0.5);
+  }
+
+  global.OutSampleSize = (1+bits/12);
+  if (*nSamplesToDo/undersampling == 0L) {
+      usage2("Time interval is too short. Choose a duration greater than %d.%02d secs!", 
+	       undersampling/44100, (int)(undersampling/44100) % 100);
+  }
+  if ( moreargs < argc ) {
+    if (!strcmp(argv[moreargs],"-") || is_fifo(argv[moreargs])) {
+      /*
+       * pipe mode
+       */
+      if (bulk == 1) {
+        fprintf(stderr, "W Bulk mode is disabled while outputting to a %spipe\n",
+		is_fifo(argv[moreargs]) ? "named " : "");
+        bulk = 0;
+      }
+      global.no_cddbfile = 1;
+    }
+  }
+  if (global.no_infofile == 0) {
+    global.no_infofile = 1;
+    if (global.channels == 1 || bits != 16 || rate != 44100) {
+      fprintf(stderr, "W Sample conversions disable generation of info files!\n");
+    } else if (waitforsignal == 1) {
+      fprintf(stderr, "W Option -w 'wait for signal' disables generation of info files!\n");
+    } else if (sector_offset != 0) {
+      fprintf(stderr, "W Using an start offset (option -o) disables generation of info files!\n");
+    } else if (!bulk &&
+      !((lSector == Get_AudioStartSector(track)) &&
+        ((long)(lSector + rectime*75.0 + 0.5) == Get_EndSector(track) + 1))) {
+      fprintf(stderr, "W Duration is not set for complete tracks (option -d), this disables generation\n  of info files!\n");
+    } else {
+      global.no_infofile = 0;
+    }
+  }
+
+  SamplesToWrite = *nSamplesToDo*2/(int)int_part;
+
+  {
+	int first = FirstAudioTrack();
+	tracks_included = Get_Track(
+	      (unsigned) (lSector + *nSamplesToDo/CD_FRAMESAMPLES -1))
+				     - max((int)track,first) +1;
+  }
+
+  if (global.multiname != 0 && moreargs + tracks_included > argc) {
+	global.multiname = 0;
+  }
+
+  if ( !waitforsignal ) {
+
+#ifdef INFOFILES
+      if (!global.no_infofile) {
+	int i;
+
+	for (i = track; i < (int)track + tracks_included; i++) {
+		unsigned minsec, maxsec;
+	        char *tmp_fname;
+
+	        /* build next filename */
+
+	        tmp_fname = get_next_name();
+	        if (tmp_fname != NULL)
+		  strncpy( global.fname_base, tmp_fname, sizeof(global.fname_base)-8 );
+ 		global.fname_base[sizeof(global.fname_base)-1]=0;
+		minsec = max(lSector, Get_AudioStartSector(i));
+		maxsec = min(lSector + rectime*75.0 + 0.5, 1+Get_EndSector(i));
+		if ((int)minsec == Get_AudioStartSector(i) &&
+		    (int)maxsec == 1+Get_EndSector(i)) {
+			write_info_file(global.fname_base,i,(maxsec-minsec)*CD_FRAMESAMPLES, bulk && global.multiname == 0);
+		} else {
+			fprintf(stderr,
+				 "Partial length copy for track %d, no info file will be generated for this track!\n", i);
+		}
+		if (!bulk) break;
+	}
+	reset_name_iterator();
+      }
+#endif
+
+  }
+
+  if (global.just_the_toc) exit(NO_ERROR);
+
+#ifdef  ECHO_TO_SOUNDCARD
+  if (user_sound_device[0] != '\0') {
+      set_snd_device(user_sound_device);
+  }
+  init_soundcard(rate, bits);
+#endif /* ECHO_TO_SOUNDCARD */
+
+  if (global.userspeed > -1)
+     global.speed = global.userspeed;
+
+  if (global.speed != 0 && SelectSpeed != NULL) {
+     SelectSpeed(get_scsi_p(), global.speed);
+  }
+
+  current_track = track;
+
+  if ( !global.no_file ) {
+    {
+      char *myfname;
+
+      myfname = get_next_name();
+
+      if (myfname != NULL) {
+        strncpy( global.fname_base, myfname, sizeof(global.fname_base)-8 );
+        global.fname_base[sizeof(global.fname_base)-1]=0;
+      }
+    }
+
+    /* strip audio_type extension */
+    {
+      char *cp = global.fname_base;
+
+      cp = strrchr(cp, '.');
+      if (cp == NULL) {
+	cp = global.fname_base + strlen(global.fname_base);
+      }
+      *cp = '\0';
+    }
+    if (bulk && global.multiname == 0) {
+      sprintf(fname, "%s_%02u.%s",global.fname_base,current_track,audio_type);
+    } else {
+      sprintf(fname, "%s.%s",global.fname_base,audio_type);
+    }
+
+    OpenAudio( fname, rate, bits, global.channels, 
+	      (unsigned)(SamplesToWrite*global.OutSampleSize*global.channels),
+		global.audio_out);
+  }
+
+  global.Remainder = (75 % global.nsectors)+1;
+
+  global.sh_bits = 16 - bits;		/* shift counter */
+
+  global.iloop = *nSamplesToDo;
+  if (Halved && (global.iloop&1))
+      global.iloop += 2;
+
+  BeginAtSample = lSector * CD_FRAMESAMPLES;
+
+#if	1
+	if ( (global.verbose & SHOW_SUMMARY) && !global.just_the_toc &&
+	     (global.reads_illleadout == 0 ||
+	      lSector+*nSamplesToDo/CD_FRAMESAMPLES
+	       <= (unsigned) Get_AudioStartSector(cdtracks-1))) {
+
+		fprintf(stderr, "samplefile size will be %lu bytes.\n",
+			global.audio_out->GetHdrSize() +
+			global.audio_out->InSizeToOutSize(SamplesToWrite*global.OutSampleSize*global.channels)  ); 
+		fprintf (stderr, "recording %d.%04d seconds %s with %d bits @ %5d.%01d Hz"
+			,(int)rectime , (int)(rectime * 10000) % 10000,
+			global.channels == 1 ? "mono":"stereo", bits, (int)rate, (int)(rate*10)%10);
+		if (!global.no_file && *global.fname_base)
+			fprintf(stderr, " ->'%s'...", global.fname_base );
+		fputs("\n", stderr);
+	}
+#endif
+
+#if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
+#else
+	init_pipes();
+#endif
+
+#ifdef	USE_PARANOIA
+	if (global.paranoia_selected) {
+		long paranoia_mode;
+
+		global.cdp = paranoia_init(get_scsi_p(), global.nsectors);
+
+		if (global.paranoia_parms.overlap >= 0) {
+			int	overlap = global.paranoia_parms.overlap;
+
+			if (overlap > global.nsectors - 1) 
+				overlap = global.nsectors - 1;
+			paranoia_overlapset(global.cdp, overlap);
+		}
+		/*
+		 * Default to a  minimum of dynamic overlapping == 0.5 sectors.
+		 * If we don't do this, we get the default from libparanoia
+		 * which is approx. 0.1.
+		 */
+		if (global.paranoia_parms.mindynoverlap < 0)
+			paranoia_dynoverlapset(global.cdp, CD_FRAMEWORDS/2, -1);
+		paranoia_dynoverlapset(global.cdp,
+			global.paranoia_parms.mindynoverlap * CD_FRAMEWORDS,
+			global.paranoia_parms.maxdynoverlap * CD_FRAMEWORDS);
+
+		paranoia_mode = PARANOIA_MODE_FULL ^ PARANOIA_MODE_NEVERSKIP;
+
+		if (global.paranoia_parms.disable_paranoia) {
+			paranoia_mode = PARANOIA_MODE_DISABLE;
+		}
+		if (global.paranoia_parms.disable_extra_paranoia) {
+			paranoia_mode |= PARANOIA_MODE_OVERLAP;
+			paranoia_mode &= ~PARANOIA_MODE_VERIFY;
+		}
+		/* not yet implemented */
+		if (global.paranoia_parms.disable_scratch_detect) {
+			paranoia_mode &= ~(PARANOIA_MODE_SCRATCH|PARANOIA_MODE_REPAIR);
+		}
+		/* not yet implemented */
+		if (global.paranoia_parms.disable_scratch_repair) {
+			paranoia_mode &= ~PARANOIA_MODE_REPAIR;
+		}
+
+		paranoia_modeset(global.cdp, paranoia_mode);
+		if (global.verbose)
+			fprintf(stderr, "using lib paranoia for reading.\n");
+		paranoia_seek(global.cdp, lSector, SEEK_SET);
+		paranoia_reset();
+	}
+#endif
+#if defined(HAVE_FORK_AND_SHAREDMEM)
+
+	/* Everything is set up. Now fork and let one process read cdda sectors
+	   and let the other one store them in a wav file */
+
+	/* forking */
+	child_pid = fork();
+	if (child_pid > 0 && global.gui > 0 && global.verbose > 0)
+		fprintf( stderr, "child pid is %d\n", child_pid);
+
+	/*********************** fork **************************************/
+	if (child_pid == 0) {
+		/* child WRITER section */
+
+#ifdef	HAVE_AREAS
+		/* Under BeOS a fork() with shared memory does not work as
+		 * it does under System V Rel. 4. The mapping of the child
+		 * works with copy on write semantics, so changes do not propagate
+		 * back and forth. The existing mapping has to be deleted
+		 * and replaced by an clone without copy on write semantics.
+		 * This is done with clone_area(...,B_CLONE_ADDRESS,...).
+		 * Thanks to file support.c from the postgreSQL project.
+		 */
+		area_info inf;
+		int32 cook = 0;
+		/* iterate over all mappings to find our shared memory mapping. */
+		while (get_next_area_info(0, &cook, &inf) == B_OK)
+		{
+			/* check the name of the mapping. */
+			if (!strcmp(inf.name, AREA_NAME))
+			{
+				void *area_address;
+				area_id area_parent;
+
+				/* kill the cow mapping. */
+				area_address = inf.address;
+				if (B_OK != delete_area(inf.area))
+				{
+					fprintf(stderr, "delete_area: no valid area.\n");
+					exit(SHMMEM_ERROR);
+				}
+				/* get the parent mapping. */
+				area_parent = find_area(inf.name);
+				if (area_parent == B_NAME_NOT_FOUND)
+				{
+					fprintf(stderr, "find_area: no such area name.\n");
+					exit(SHMMEM_ERROR);
+				}
+				/* clone the parent mapping without cow. */
+				if (B_OK > clone_area("shm_child", &area_address, B_CLONE_ADDRESS,
+					B_READ_AREA | B_WRITE_AREA, area_parent))
+				{
+					fprintf(stderr,"clone_area failed\n");
+					exit(SHMMEM_ERROR);
+				}
+			}
+		}
+#endif
+#ifdef	__EMX__
+		if (DosGetSharedMem(he_fill_buffer, 3)) {
+			comerr("DosGetSharedMem() failed.\n");
+		}
+#endif
+		global.have_forked = 1;
+		forked_write();
+#ifdef	__EMX__
+		DosFreeMem(he_fill_buffer);
+		_exit(NO_ERROR);
+		/* NOTREACHED */
+#endif
+		exit_wrapper(NO_ERROR);
+		/* NOTREACHED */
+	} else if (child_pid > 0) {
+		/* parent READER section */
+    
+		global.have_forked = 1;
+		switch_to_realtime_priority();
+
+		forked_read();
+#ifdef	HAVE_AREAS
+		{
+			area_id aid;
+			aid = find_area(AREA_NAME);
+			if (aid < B_OK) {
+				comerrno(aid, "find_area() failed.\n");
+			}
+			delete_area(aid);
+		}
+#endif
+#ifdef	__EMX__
+		DosFreeMem(he_fill_buffer);
+#endif
+		exit_wrapper(NO_ERROR);
+		/* NOTREACHED */
+	} else
+		perror("fork error.");
+
+#endif
+	/* version without fork */
+	{
+		global.have_forked = 0;
+#if	0
+		if (!global.paranoia_selected) {
+			fprintf(stderr, "REAL\n");
+			switch_to_realtime_priority();
+		}
+#endif
+		fprintf(stderr, "a nonforking version is running...\n");
+		nonforked_loop();
+		exit_wrapper(NO_ERROR);
+		/* NOTREACHED */
+	}
+#ifdef	USE_PARANOIA
+	if (global.paranoia_selected)
+		paranoia_free(global.cdp);
+#endif
+
+	return 0;
+}

Copied: cdrkit/trunk/icedax/icedax.h (from rev 435, cdrkit/trunk/icedax/cdda2wav.h)
===================================================================
--- cdrkit/trunk/icedax/cdda2wav.h	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/icedax.h	2006-11-23 19:26:47 UTC (rev 436)
@@ -0,0 +1,150 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)icedax.h	1.4 00/02/13 Copyright 1998,1999,2000 Heiko Eissfeldt */
+/***
+ * CopyPolicy: GNU Public License 2 applies
+ * Copyright (C) by Heiko Eissfeldt
+ *
+ * prototypes from cdda2wav.c
+ */
+
+#ifdef max
+#undef max
+#endif
+#ifdef min
+#undef min
+#endif
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+
+/* verbose levels */
+#define SHOW_TOC	1
+#define SHOW_SUMMARY	2
+#define SHOW_INDICES	4
+#define SHOW_MCN	8
+#define SHOW_ISRC	16
+#define SHOW_STARTPOSITIONS	32
+#define SHOW_TITLES	64
+#define SHOW_JUSTAUDIOTRACKS	128
+#define SHOW_MAX	255
+
+/* Endianess */
+#define GUESS (-2)
+#define NONE (-1)
+#define LITTLE 0
+#define BIG 1
+
+void FatalError(const char *szMessage, ...);
+void AnalyzeQchannel(unsigned frame);
+long SamplesNeeded(long amount, long undersampling);
+unsigned int get_current_track(void);
+
+#if defined (sun) && !defined(SVR4)
+#define  atexit(f) on_exit(f, 0)
+#endif
+
+#ifndef	_LINUX_CDROM_H
+#define	_LINUX_CDROM_H
+
+/*
+ * some fix numbers
+ */
+#define CD_MINS             74 /* max. minutes per CD, not really a limit */
+#define CD_SECS             60 /* seconds per minute */
+#define CD_FRAMES           75 /* frames per second */
+
+#define CD_SYNC_SIZE        12 /* 12 sync bytes per raw data frame, not transfered by the drive */
+#define CD_HEAD_SIZE         4 /* header (address) bytes per raw data frame */
+#define CD_SUBHEAD_SIZE      8 /* subheader bytes per raw XA data frame */
+#define CD_XA_HEAD        (CD_HEAD_SIZE+CD_SUBHEAD_SIZE) /* "before data" part of raw XA frame */
+#define CD_XA_SYNC_HEAD   (CD_SYNC_SIZE+CD_XA_HEAD)/* sync bytes + header of XA frame */
+
+#define CD_FRAMESIZE      2048 /* bytes per frame, "cooked" mode */
+#define CD_FRAMESIZE_RAW  2352 /* bytes per frame, "raw" mode */
+/* most drives don't deliver everything: */
+#define CD_FRAMESIZE_RAW1 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE) /* 2340 */
+#define CD_FRAMESIZE_RAW0 (CD_FRAMESIZE_RAW-CD_SYNC_SIZE-CD_HEAD_SIZE) /* 2336 */
+/* Optics drive also has a 'read all' mode: */
+#define CD_FRAMESIZE_RAWER 2646 /* bytes per frame */
+
+#define CD_EDC_SIZE         4 /* bytes EDC per most raw data frame types */
+#define CD_ZERO_SIZE        8 /* bytes zero per yellow book mode 1 frame */
+#define CD_ECC_SIZE       276 /* bytes ECC per most raw data frame types */
+#define CD_XA_TAIL        (CD_EDC_SIZE+CD_ECC_SIZE) /* "after data" part of raw XA frame */
+
+#define CD_FRAMESIZE_SUB    96 /* subchannel data "frame" size */
+#define CD_MSF_OFFSET      150 /* MSF numbering offset of first frame */
+
+#define CD_CHUNK_SIZE       24 /* lowest-level "data bytes piece" */
+#define CD_NUM_OF_CHUNKS    98 /* chunks per frame */
+
+#define CD_FRAMESIZE_XA CD_FRAMESIZE_RAW1 /* obsolete name */
+#define CD_BLOCK_OFFSET    CD_MSF_OFFSET /* obsolete name */
+
+/*
+ * the raw frame layout:
+ *
+ * - audio (red):                  | audio_sample_bytes |
+ *                                 |        2352        |
+ *
+ * - data (yellow, mode1):         | sync - head - data - EDC - zero - ECC |
+ *                                 |  12  -   4  - 2048 -  4  -   8  - 276 |
+ *
+ * - data (yellow, mode2):         | sync - head - data |
+ *                                 |  12  -   4  - 2336 |
+ *
+ * - XA data (green, mode2 form1): | sync - head - sub - data - EDC - ECC |
+ *                                 |  12  -   4  -  8  - 2048 -  4  - 276 |
+ *
+ * - XA data (green, mode2 form2): | sync - head - sub - data - EDC |
+ *                                 |  12  -   4  -  8  - 2324 -  4  |
+ */
+
+
+/*
+ * CD-ROM address types (cdrom_tocentry.cdte_format)
+ */
+#if	!defined CDROM_LBA
+#define	CDROM_LBA 0x01 /* "logical block": first frame is #0 */
+#define	CDROM_MSF 0x02 /* "minute-second-frame": binary, not bcd here! */
+#endif
+/*
+ * bit to tell whether track is data or audio (cdrom_tocentry.cdte_ctrl)
+ */
+#define	CDROM_DATA_TRACK	0x04
+
+/*
+ * The leadout track is always 0xAA, regardless of # of tracks on disc
+ */
+#define	CDROM_LEADOUT	0xAA
+
+/*
+ * audio states (from SCSI-2, but seen with other drives, too)
+ */
+#define	CDROM_AUDIO_INVALID	0x00	/* audio status not supported */
+#define	CDROM_AUDIO_PLAY	0x11	/* audio play operation in progress */
+#define	CDROM_AUDIO_PAUSED	0x12	/* audio play operation paused */
+#define	CDROM_AUDIO_COMPLETED	0x13	/* audio play successfully completed */
+#define	CDROM_AUDIO_ERROR	0x14	/* audio play stopped due to error */
+#define	CDROM_AUDIO_NO_STATUS	0x15	/* no current audio status to return */
+
+#ifdef FIVETWELVE
+#define	CDROM_MODE1_SIZE	512
+#else
+#define	CDROM_MODE1_SIZE	2048
+#endif /*FIVETWELVE*/
+#define	CDROM_MODE2_SIZE	2336
+
+#endif
+

Modified: cdrkit/trunk/icedax/interface.c
===================================================================
--- cdrkit/trunk/icedax/interface.c	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/interface.c	2006-11-23 19:26:47 UTC (rev 436)
@@ -81,7 +81,7 @@
 #include "mytype.h"
 #include "byteorder.h"
 #include "interface.h"
-#include "cdda2wav.h"
+#include "icedax.h"
 #include "semshm.h"
 #include "setuid.h"
 #include "ringbuff.h"

Modified: cdrkit/trunk/icedax/ioctl.c
===================================================================
--- cdrkit/trunk/icedax/ioctl.c	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/ioctl.c	2006-11-23 19:26:47 UTC (rev 436)
@@ -62,7 +62,7 @@
 #include "byteorder.h"
 #include "interface.h"
 #include "toc.h"
-#include "cdda2wav.h"
+#include "icedax.h"
 #include "ioctl.h"
 #include "global.h"
 #include "exitcodes.h"

Modified: cdrkit/trunk/icedax/resample.c
===================================================================
--- cdrkit/trunk/icedax/resample.c	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/resample.c	2006-11-23 19:26:47 UTC (rev 436)
@@ -47,7 +47,7 @@
 #include <usal/scsitransp.h>
 
 #include "mytype.h"
-#include "cdda2wav.h"
+#include "icedax.h"
 #include "interface.h"
 #include "byteorder.h"
 #include "ringbuff.h"

Modified: cdrkit/trunk/icedax/scsi_cmds.c
===================================================================
--- cdrkit/trunk/icedax/scsi_cmds.c	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/scsi_cmds.c	2006-11-23 19:26:47 UTC (rev 436)
@@ -44,7 +44,7 @@
 #include <usal/scsitransp.h>
 
 #include "mytype.h"
-#include "cdda2wav.h"
+#include "icedax.h"
 #include "interface.h"
 #include "byteorder.h"
 #include "global.h"

Modified: cdrkit/trunk/icedax/toc.c
===================================================================
--- cdrkit/trunk/icedax/toc.c	2006-11-23 19:19:33 UTC (rev 435)
+++ cdrkit/trunk/icedax/toc.c	2006-11-23 19:26:47 UTC (rev 436)
@@ -64,7 +64,7 @@
 #include "mytype.h"
 #include "byteorder.h"
 #include "interface.h"
-#include "cdda2wav.h"
+#include "icedax.h"
 #include "global.h"
 #include "sha.h"
 #include "base64.h"




More information about the Debburn-changes mailing list