1 /*
2 	io.c
3 	All the functions that interact with hardware and subprocesses
4 	and file IO.
5 	28.3.99 tn
6 */
7 
8 #ifdef HAVE_CONFIG_H
9 # include <config.h>
10 #endif
11 
12 #include "largefile.h"
13 #include "gettext.h"
14 
15 #include <stdio.h>
16 #include <string.h>
17 #include <strings.h>
18 #include <stdlib.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <signal.h>
26 #include <time.h>
27 #if defined(linux) || defined(__FreeBSD__)
28 # include <sys/soundcard.h>
29 # include <sys/ioctl.h>
30 #endif
31 #if defined(sun) || defined(__OpenBSD__)
32 # include <sys/ioctl.h>
33 # include <sys/audioio.h>
34 #endif
35 #ifdef aix
36 #include <sys/audio.h>
37 #endif
38 #ifdef hpux
39 # ifndef hpux_alib
40 #  include <sys/audio.h>
41 # endif
42 #endif
43 #if defined(__sgi)
44 #include <dmedia/audio.h>
45 #endif
46 
47 #if ENABLE_NLS
48 # define _(String) gettext (String)
49 # define N_(String) gettext_noop (String)
50 #else
51 # define _(String) (String)
52 # define N_(String) (String)
53 #endif
54 #define GTK_ENABLE_BROKEN
55 
56 #include <gtk/gtk.h>
57 #include <gdk/gdk.h>
58 #include <glib.h>
59 #include "xcdrdata.h"
60 #include "xcdroast.h"
61 #include "main.h"
62 
63 writerreader_devices_t **writerreaderdevs;
64 gchar **alt_scsidevices;
65 cd_info_t cdinfo;
66 track_info_t **trackinfo;
67 writer_driver_t **drivers;
68 writer_driver_t **blankmodes;
69 write_track_param_t writeparams;
70 gchar xcdroast_version_loaded[MAXLINE];
71 gint read_done;
72 gint read_abort_mark;
73 
74 static gint scsicount;
75 static gint busnr;
76 static gint tocstate;
77 static gint tocnr;
78 static gint drvcount;
79 static gint dfrun;
80 static gint readcdda_callback;
81 static gint readcdda_callback2;
82 static gint readcdda_callback3;
83 static gint read_output_ctrl;
84 static gint read_tracknr;
85 static gchar readtrack_info_string[1024];
86 static gfloat pct_so_far, pct_this_track;
87 static pid_t mkisofs_pid;
88 static pid_t readcdda_pid, readcdda_pid2;
89 static gint readcd_startsector, readcd_endsector;
90 static gint readerr_count;
91 static gint matchnr;
92 static gint cddb_in;
93 static gchar cdinfo_cddb_title_bak[MAXLINE];
94 static gint cd_is_still_the_same;
95 static gint cdrecord_stdin, cdrecord_reload;
96 static gint delete_count, delete_start, delete_all;
97 static gint msinfo_nr1, msinfo_nr2;
98 static gint cdrtimer, count_mmaperror, checkmedium_found;
99 static time_t cdrcmdtimer;
100 static GtkWidget *getcdtoc_atapi_timeout_dialog;
101 
102 extern gint debug;
103 extern gint dialog_done2, dialog_done, dialog_done3;
104 extern setup_data_t setupdata;
105 extern track_read_set_t trackreadset;
106 extern current_set_t curset;
107 extern gchar *system_platform;
108 extern GtkWidget *toplevel;
109 extern GtkWidget *viewmode_dialog;
110 extern GtkWidget *readtrack_info_label, *readtrack_textview;
111 extern GtkWidget *readtrack_pbar1, *readtrack_pbar2, *readtrack_pbar3;
112 extern GtkWidget *readtrack_pbar4, *readtrack_spd;
113 extern GtkWidget *readtrack_small_info, *readtrack_small_info2;
114 extern gchar hostname[MAXLINE];
115 extern gchar username[MAXLINE];
116 extern gchar sharedir[MAXLINE];
117 extern gchar configdir[MAXLINE];
118 extern gchar prefixdir[MAXLINE];
119 extern GtkWidget *cddb_info_label;
120 extern GtkCList *cddb_clist;
121 extern master_param_t masterparam;
122 extern gchar **charset_types;
123 extern gchar *master_fname1;
124 extern gchar *master_fname2;
125 extern GdkFont *fixedfont;
126 extern gint support_ontheflyaudio;
127 
128 static void verify_readcd_err(gpointer pid, gint source, GdkInputCondition cond);
129 static void read_write_out(gpointer data, gint source, GdkInputCondition cond);
130 static gint getdevicecap(gchar *dev, gint *readmax, gint *cdrmax, gint *dvdmax, gint *iscdr, gint *isdvdrom, gint *isdvdr);
131 static gint check_medium_loaded(gint devnr);
132 static gint get_cdrecord_toc(gint devnr);
133 static void remove_tmp_writetracks_tocfile(gchar *tocfile);
134 static void edit_xinf_for_cd_text2(gchar *infname, gchar *title, gchar *artist, gchar *cdtitle, gchar *cdartist);
135 static pid_t full_dpl_pipe3(gint *out, gint *in, gint *err, gchar *cmd,
136 	gint use_socketpair);
137 
138 
139 /* convert device-type-names back to numeric */
140 /* -1 means unknown */
141 
get_scsi_type(gchar * type)142 static gint get_scsi_type(gchar *type) {
143 
144 	if (strcmp(type,"Disk") == 0) {
145 		return 0;
146 	}
147 	if (strcmp(type,"Tape") == 0) {
148 		return 1;
149 	}
150 	if (strcmp(type,"Printer") == 0) {
151 		return 2;
152 	}
153 	if (strcmp(type,"Processor") == 0) {
154 		return 3;
155 	}
156 	if (strcmp(type,"WORM") == 0) {
157 		return 4;
158 	}
159 	if (strcmp(type,"CD-ROM") == 0) {
160 		return 5;
161 	}
162 	if (strcmp(type,"Scanner") == 0) {
163 		return 6;
164 	}
165 	if (strcmp(type,"Optical Storage") == 0) {
166 		return 7;
167 	}
168 	if (strcmp(type,"Juke Box") == 0) {
169 		return 8;
170 	}
171 	if (strcmp(type,"Communication") == 0) {
172 		return 9;
173 	}
174 
175 	return -1;
176 }
177 
178 
179 /* convert the scsi-type-number back to string */
180 
181 #if 0
182 static void get_scsi_type_string(gchar *str, gint type,  gint removeable) {
183 
184 	switch(type) {
185 	case 0:
186 		if (removeable == 0) {
187 			strcpy(str,_("Disk"));
188 		} else {
189 			strcpy(str,_("Removable Disk"));
190 		}
191 		break;
192 	case 1:
193 		strcpy(str,_("Tape"));
194 		break;
195 	case 2:
196 		strcpy(str,_("Printer"));
197 		break;
198 	case 3:
199 		strcpy(str,_("Processor/Scanner"));
200 		break;
201 	case 4:
202 		strcpy(str,_("WORM"));
203 		break;
204 	case 5:
205 		strcpy(str,_("CD-ROM"));
206 		break;
207 	case 6:
208 		strcpy(str,_("Scanner"));
209 		break;
210 	case 7:
211 		strcpy(str,_("Optical Storage"));
212 		break;
213 	case 8:
214 		strcpy(str,_("Juke Box"));
215 		break;
216 	case 9:
217 		strcpy(str,_("Communication"));
218 		break;
219 	default:
220 		strcpy(str,"");
221 		break;
222 	}
223 }
224 #endif
225 
226 
get_cur_audioread_speed()227 static gint get_cur_audioread_speed() {
228 gint i;
229 	i = get_writerreaderdevs_index(curset.reader_devnr);
230 	return (writerreaderdevs[i]->audioread_speed);
231 }
232 
get_cur_audioread_overlap()233 static gint get_cur_audioread_overlap() {
234 gint i;
235 	i = get_writerreaderdevs_index(curset.reader_devnr);
236 	return (writerreaderdevs[i]->audioread_overlap);
237 }
238 
get_cur_audioread_sectorburst()239 static gint get_cur_audioread_sectorburst() {
240 gint i;
241 	i = get_writerreaderdevs_index(curset.reader_devnr);
242 	return (writerreaderdevs[i]->audioread_sectorburst);
243 }
244 
get_cur_audioread_useparanoia()245 static gint get_cur_audioread_useparanoia() {
246 gint i;
247 	i = get_writerreaderdevs_index(curset.reader_devnr);
248 	return (writerreaderdevs[i]->audioread_useparanoia);
249 }
250 
get_cur_audioread_paranoiaretries()251 static gint get_cur_audioread_paranoiaretries() {
252 gint i;
253 	i = get_writerreaderdevs_index(curset.reader_devnr);
254 	return (writerreaderdevs[i]->audioread_paranoiaretries);
255 }
256 
get_cur_writer_speed()257 static gint get_cur_writer_speed() {
258 gint i;
259 	i = get_writerreaderdevs_index(curset.writer_devnr);
260 	return (writerreaderdevs[i]->writer_speed);
261 }
262 
get_cur_writer_fifo()263 static gint get_cur_writer_fifo() {
264 gint i;
265 	i = get_writerreaderdevs_index(curset.writer_devnr);
266 	return (writerreaderdevs[i]->writer_fifo);
267 }
268 
get_cur_writemode()269 static gint get_cur_writemode() {
270 gint i;
271 	i = get_writerreaderdevs_index(curset.writer_devnr);
272 	return (writerreaderdevs[i]->writer_mode);
273 }
274 
get_cur_writer_drvmode()275 static gint get_cur_writer_drvmode() {
276 gint i;
277 	i = get_writerreaderdevs_index(curset.writer_devnr);
278 	return (writerreaderdevs[i]->writer_drvmode);
279 }
280 
281 
282 /* look in given string for "' '" and return index to it */
283 /* return -1 if not found */
284 
look_for_scan_delimitor(gchar * str)285 static gint look_for_scan_delimitor(gchar *str) {
286 gint i;
287 
288 	for(i = 0; i < strlen(str)-2; i++) {
289 
290 		if (str[i] == '\'' && str[i+1] == ' ' && str[i+2] == '\'') {
291 			return i;
292 		}
293 	}
294 	return -1;
295 }
296 
297 
298 /* look in given string for "' " and return index to it */
299 /* return -1 if not found */
300 
look_for_scan_delimitor2(gchar * str)301 static gint look_for_scan_delimitor2(gchar *str) {
302 gint i;
303 
304 	for(i = 0; i < strlen(str)-1; i++) {
305 
306 		if (str[i] == '\'' && str[i+1] == ' ') {
307 			return i;
308 		}
309 	}
310 	return -1;
311 }
312 
313 
314 /* interpret output of -scanbus and sort into memory structure */
315 /* if idx != -1 then we run in manual-device-mode */
316 
parse_scan(gchar * line,gint idx,gint transport,scsi_devices_t ** scsidevices)317 static void parse_scan(gchar *line, gint idx, gint transport, scsi_devices_t **scsidevices) {
318 gchar tmp[MAXLINE];
319 gchar tmp2[MAXLINE];
320 gchar *p1, *p2;
321 gint s_id;
322 gchar s_vendor[9];
323 gchar s_model[17];
324 gchar s_rev[5];
325 gint s_removable;
326 gint s_type;
327 gint next;
328 
329 	/* skip header */
330 	if (strncmp(line,"Cdrecord",8) == 0) {
331 		return;
332 	}
333 #if 0
334 	if (strncmp(line,"devname",7) == 0 ) {
335 		/* set current scsibus nr */
336 		strcpy(tmp,line+7);
337 		p1=strtok(tmp,":");
338 		/* now tmp2 contains the current busnr as string */
339 		devname = strdup(p1);
340 		return;
341 	}
342 #endif
343        if (strncmp(line,"scsibus",7) == 0 ) {
344                 /* set current scsibus nr */
345                 strcpy(tmp,line+7);
346                 p1=strtok(tmp,":");
347                 strcpy(tmp2,p1);
348                 /* now tmp2 contains the current busnr as string */
349                 busnr = atoi(tmp2);
350                 return;
351         }
352 
353 
354 	/* a line with an error message? */
355 	/* get_spawn_path(CDRECORD,tmp); */
356 	strcpy(tmp,"cdrecord: ");
357 	if (strncmp(line, tmp, strlen(tmp)) == 0) {
358 		return;
359 	}
360 
361 	/* a line with device-info found (by checking for ")")*/
362 	p1 = index(line,')');
363 	if (p1 != NULL && !strstr(line,")\"") &&
364 	   (strstr(line,"\t") || line[0] == ' ')) {
365 		strip_string(line);
366 
367 		/* get scsi-id */
368 		p1=strtok(line,")");
369 		if (!p1) return;
370 
371 		strcpy(tmp,p1);
372 		strcpy(tmp2,p1);
373 		/* look for last tab or last space in tmp and remove
374 		   everything before */
375 		p1=rindex(tmp2,'\t');
376 		p2=rindex(tmp2,' ');
377 		if (p1 > p2) {
378 			/* last interesting char was a tab - cut here */
379 			if (p1 != NULL) {
380 				strcpy(tmp,p1+1);
381 			}
382 		} else {
383 			/* last interesting char was a space - cut here */
384 			if (p2 != NULL) {
385 				strcpy(tmp,p2+1);
386 			}
387 		}
388 		s_id = atoi(tmp);
389 
390 		/* strip host-id from scsi-id-number */
391 		s_id = s_id % 100;
392 
393 		p1=strtok(NULL,"'");
394 		if (p1 == NULL) {
395 			g_warning("cdrecord scanbus error: Try to remove all media from your CD-ROM drives before starting X-CD-Roast.\n");
396 			return;
397 		}
398 
399 		strcpy(tmp,p1);
400 		strip_string(tmp);
401 
402 		if (*tmp == '*') {
403 			/* no device found */
404 			return;
405 		}
406 
407 		if (*tmp == 'H') {
408 			/* HOST ADAPTER found */
409 			/* treat as no device for now */
410 			return;
411 		}
412 
413 		/* get full rest of line */
414 		p1=strtok(NULL,"");
415 		if (!p1) return;
416 		strcpy(tmp,p1);
417 
418 		if (*tmp == '\'') {
419 			/* empty device found? ignore */
420 			return;
421 		}
422 
423 		/* e.g. tmp=YAMAHA  ' 'CRW8424S        ' '1.0j' */
424 		/* get vendor */
425 		next = look_for_scan_delimitor(tmp);
426 		if (next < 0) {
427 			g_error("cdrecord -scanbus output syntax error\n");
428 		}
429 
430 		strcpy(s_vendor,"        ");
431 		if (next <= 8) {
432 			strncpy(s_vendor,tmp,next);
433 		} else {
434 			/* strip if to long */
435 			strncpy(s_vendor,tmp,8);
436 		}
437 		s_vendor[8] = '\0';
438 
439 		/* get model */
440 		strcpy(tmp2,tmp+next+3);
441 		strcpy(tmp,tmp2);
442 		next = look_for_scan_delimitor(tmp);
443 		if (next < 0) {
444 			g_error("cdrecord -scanbus output syntax error\n");
445 		}
446 		strcpy(s_model,"                ");
447 		if (next <= 16) {
448 			strncpy(s_model,tmp,next);
449 		} else {
450 			strncpy(s_model,tmp,16);
451 		}
452 		s_model[16] = '\0';
453 
454 		/* get revision */
455 		strcpy(tmp2,tmp+next+3);
456 		strcpy(tmp,tmp2);
457 		next = look_for_scan_delimitor2(tmp);
458 		if (next < 0) {
459 			g_error("cdrecord -scanbus output syntax error\n");
460 		}
461 		strcpy(s_rev,"    ");
462 		if (next <= 4) {
463 			strncpy(s_rev,tmp,next);
464 		} else {
465 			strncpy(s_rev,tmp,4);
466 		}
467 		s_rev[4] = '\0';
468 
469 		/* get type */
470 		strcpy(tmp2,tmp+next+2);
471 		strcpy(tmp,tmp2);
472 		strip_string(tmp);
473 
474 		if (strncmp(tmp,"Removable",9) == 0) {
475 			s_removable = 1;
476 			strcpy(tmp2,tmp+10);
477 			strcpy(tmp,tmp2);
478 		} else {
479 			s_removable = 0;
480 		}
481 
482 		s_type = get_scsi_type(tmp);
483 
484 		/* allocate and fill structure */
485 		scsidevices[scsicount]=g_new(scsi_devices_t,1);
486 		if (idx == -1) {
487 			/* autoscan mode */
488 			scsidevices[scsicount]->devnr =
489 				transport*1024+busnr*32+s_id;
490 			scsidevices[scsicount]->alt_dev = -1;
491 		} else {
492 			/* manual mode */
493 			scsidevices[scsicount]->devnr = idx;
494 			scsidevices[scsicount]->alt_dev = idx;
495 		}
496 
497 		scsidevices[scsicount]->sector_size = DATASECTORSIZE;
498 		scsidevices[scsicount]->transport = transport;
499 		scsidevices[scsicount]->bus = busnr;
500 		scsidevices[scsicount]->id = s_id;
501 		strcpy(scsidevices[scsicount]->vendor,s_vendor);
502 		strcpy(scsidevices[scsicount]->model,s_model);
503 		strcpy(scsidevices[scsicount]->rev,s_rev);
504 		scsidevices[scsicount]->removable = s_removable;
505 		scsidevices[scsicount]->type = s_type;
506 
507 		scsicount++;
508 		if (scsicount >= MAXDEVICES) {
509 			g_error("Error: More than %d devices scanned\n",MAXDEVICES);
510 		}
511 	}
512 }
513 
514 
515 /* print memory-structure with scsidevices (debug purposes) */
516 #if 0
517 static void print_scsidevices(scsi_devices_t **scsidevices) {
518 gint count;
519 
520 	dodebug(2,"------ cdrecord scsidevices-structure -----\n");
521 	count = 0;
522 	while(scsidevices[count] != NULL) {
523 		dodebug(2,"devnr=%d %d:%d %s %s %s %d,%d (alt: %d) (ssize: %d)\n",
524 			scsidevices[count]->devnr,
525 			scsidevices[count]->bus,
526 			scsidevices[count]->id,
527 			scsidevices[count]->vendor,
528 			scsidevices[count]->model,
529 			scsidevices[count]->rev,
530 			scsidevices[count]->removable,
531 			scsidevices[count]->type,
532 			scsidevices[count]->alt_dev,
533 			scsidevices[count]->sector_size);
534 
535 		count++;
536 	}
537 }
538 #endif
539 
print_writerreaderdevs()540 static void print_writerreaderdevs() {
541 gint count;
542 
543 	dodebug(2,"------ cdrecord writerreaderdevs-structure -----\n");
544 	count = 0;
545 	while(writerreaderdevs[count] != NULL) {
546 		dodebug(2, "devnr=%d (%s) [%s %s %s] (ssize: %d)\n",
547 			writerreaderdevs[count]->devnr,
548 			writerreaderdevs[count]->devicestr,
549 			writerreaderdevs[count]->vendor,
550 			writerreaderdevs[count]->model,
551 			writerreaderdevs[count]->rev,
552 			writerreaderdevs[count]->sector_size);
553 		dodebug(2, "  readmax: %d, cdrmax: %d, dvdmax: %d, is_cdrwriter: %d, is_dvdreader: %d, is_dvdwriter: %d\n",
554 			writerreaderdevs[count]->writer_readmaxspeed,
555 			writerreaderdevs[count]->writer_cdrmaxspeed,
556 			writerreaderdevs[count]->writer_dvdmaxspeed,
557 			writerreaderdevs[count]->is_cdrwriter,
558 			writerreaderdevs[count]->is_dvdreader,
559 			writerreaderdevs[count]->is_dvdwriter,
560 			writerreaderdevs[count]->sector_size);
561 		dodebug(2, "  writer_flags: %s\n",
562 			writerreaderdevs[count]->writer_flags);
563 		dodebug(2, "  writer_modes: %s\n",
564 			writerreaderdevs[count]->writer_modes);
565 
566 		count++;
567 	}
568 }
569 
570 
571 /* create a new writer/reader entry */
572 
add_writerreader(scsi_devices_t * scsidev,gchar * transport,GtkWidget * txt)573 static gint add_writerreader(scsi_devices_t *scsidev, gchar *transport, GtkWidget *txt) {
574 gchar tmp[MAXLINE];
575 gchar tmp2[MAXLINE];
576 gchar drvflags[MAXLINE], drvmodes[MAXLINE];
577 gint readmax, cdrmax, dvdmax, iscdr, isdvdr, isdvdrom;
578 gint count;
579 gint mmap_error;
580 gint i;
581 static const gchar *writemodes[] = WRITE_MODES;
582 
583 	/* first search last entry of writerreader struct */
584 	count = 0;
585 	while(writerreaderdevs[count] != NULL) {
586 		if (count == MAXDEVICES-1) {
587 			return 0;
588 		}
589 		count++;
590 	}
591 
592 	/* only add type WORM and CD-ROM types */
593 	if (scsidev->type != 4 && scsidev->type != 5) {
594 		return 0;
595 	}
596 
597 	/* build device string */
598 	if (scsidev->alt_dev == -1) {
599 		g_snprintf(tmp,MAXLINE,"%s%d,%d,%d",
600 			transport, scsidev->bus, scsidev->id, 0);
601 	} else {
602 		strncpy(tmp, transport, MAXLINE);
603 	}
604 
605 	/* check if this device already exists */
606 	if (get_writerreaderdevs_index_from_devstr(tmp) != -1) {
607 		if (txt) {
608 			g_snprintf(tmp2,MAXLINE,"([%s] %s %s %s)\n",
609 				tmp, scsidev->vendor,
610 				scsidev->model, scsidev->rev);
611 			convert_for_gtk2_textwidget(tmp2);
612                	 	gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp2, strlen(tmp2));
613                 	wait_and_process_events();
614 		}
615 		return 0;
616 	}
617 
618 	/* create a new entry */
619 	writerreaderdevs[count]=g_new0(writerreader_devices_t,1);
620 	writerreaderdevs[count]->devnr = scsidev->devnr;
621 	writerreaderdevs[count]->devicestr = g_strdup(tmp);
622 	strncpy(writerreaderdevs[count]->vendor, scsidev->vendor,9);
623 	strncpy(writerreaderdevs[count]->model, scsidev->model,17);
624 	strncpy(writerreaderdevs[count]->rev, scsidev->rev,5);
625 	writerreaderdevs[count]->sector_size = scsidev->sector_size;
626 
627 	getmodesflags(tmp, drvflags, drvmodes);
628 	writerreaderdevs[count]->writer_flags = g_strdup(drvflags);
629 	writerreaderdevs[count]->writer_modes = g_strdup(drvmodes);
630 
631 	/* get more detailed information about this device */
632         mmap_error=getdevicecap(tmp, &readmax, &cdrmax, &dvdmax, &iscdr, &isdvdrom, &isdvdr);
633 	writerreaderdevs[count]->writer_readmaxspeed = readmax;
634 	writerreaderdevs[count]->writer_cdrmaxspeed = cdrmax;
635 	writerreaderdevs[count]->writer_dvdmaxspeed = dvdmax;
636 	writerreaderdevs[count]->is_cdrwriter = iscdr;
637 	writerreaderdevs[count]->is_dvdreader = isdvdrom;
638 	writerreaderdevs[count]->is_dvdwriter = isdvdr;
639 
640 
641 	/* workaround for non-mcc drives */
642 	if (writerreaderdevs[count]->is_cdrwriter == 0) {
643 		/* not detected as writer, but got write modes? */
644 		if (strlen(drvmodes) > 0) {
645 			/* assume its really a writer then */
646 			writerreaderdevs[count]->is_cdrwriter = 1;
647 		}
648 	}
649 
650 	/* set defaults for other fields */
651 	writerreaderdevs[count]->writer_drvmode = -1;
652 	writerreaderdevs[count]->writer_speed = cdrmax;
653 	writerreaderdevs[count]->writer_fifo = 4096;
654 
655 	/* get the first supported mode for that writer */
656 	i = 0;
657 	while (writemodes[i]) {
658 		if (writemode_supported(i, scsidev->devnr)) {
659 			writerreaderdevs[count]->writer_mode = i;
660 			break;
661 		}
662 		i++;
663 	}
664 
665 	writerreaderdevs[count]->audioread_interface = 0;
666 	writerreaderdevs[count]->audioread_speed = readmax;
667 	writerreaderdevs[count]->audioread_overlap = 0;
668 	writerreaderdevs[count]->audioread_sectorburst = 75;
669 	writerreaderdevs[count]->audioread_useparanoia = 0;
670 	writerreaderdevs[count]->audioread_paranoiaretries = 20;
671 
672 	/* add to dialog window */
673         if (txt) {
674 		g_snprintf(tmp2,MAXLINE,"[%s] %s %s %s\n",
675 			tmp, scsidev->vendor,
676 			scsidev->model, scsidev->rev);
677 		convert_for_gtk2_textwidget(tmp2);
678                 gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp2, strlen(tmp2));
679                 wait_and_process_events();
680 	}
681 
682 	return mmap_error;
683 }
684 
685 
686 /* does scan for a single device only */
687 /* return 1 when new device was found */
688 
scanbus_single(gchar * dev,gint newdevnr,GtkWidget * txt)689 static gint scanbus_single(gchar *dev, gint newdevnr, GtkWidget *txt) {
690 gchar line[MAXLINE];
691 gchar tmp[MAXLINE];
692 gchar tmp2[MAXLINE];
693 FILE *fpin;
694 scsi_devices_t **scsidevices;
695 gint found;
696 
697 	scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
698 	scsicount = 0;
699 
700 	get_wrap_path_cdrecord(line);
701 
702 	/* make sure we escape any critical chars in input */
703 	strncpy(tmp2,dev,MAXLINE);
704 	convert_escape(tmp2);
705 
706 	g_snprintf(tmp,MAXLINE," -scanbus dev= \"%s\" 2>&1",tmp2);
707 	strcat(line,tmp);
708 
709 	dodebug(1, "calling: %s\n", line);
710         if ((fpin = popen(line,"r")) == NULL) {
711                 g_error("popen error\n");
712         }
713 
714         for (;;) {
715                 if (fgets(line,MAXLINE,fpin) == NULL)
716                         break;
717 		dodebug(10,"scanbus: %s",line);
718                 parse_scan(line, newdevnr, 0, scsidevices);
719         }
720 
721         if (pclose(fpin) == -1) {
722                 g_error("pclose error\n");
723         }
724 
725 	found = 0;
726 	if (scsidevices[0]) {
727 		add_writerreader(scsidevices[0], dev, txt);
728 		g_free(scsidevices[0]);
729 		found = 1;
730 	}
731 	g_free(scsidevices);
732 
733 	return found;
734 }
735 
736 
737 #if (defined(__MACH__) && defined(__APPLE__))
738 
739 /* interpret output of -inq and sort into memory structure */
740 /* if idx != -1 then we run in manual-device-mode */
741 
parse_inq(gchar * line,gint idx,scsi_devices_t ** scsidevices)742 static void parse_inq(gchar *line, gint idx, scsi_devices_t **scsidevices) {
743 gchar tmp[MAXLINE];
744 gchar tmp2[MAXLINE];
745 gchar *p;
746 gchar s_vendor[9];
747 gchar s_model[17];
748 gchar s_rev[5];
749 gint s_removable;
750 gint s_type;
751 
752 
753 	if (strncmp("Device type",line,11) == 0) {
754 		p = strtok(line,":");
755 		if (p) {
756 			p = strtok(NULL,"");
757 			if (p) {
758 				strcpy(tmp,p);
759 				strip_string(tmp);
760 				if (strncmp(tmp,"Removable",9) == 0) {
761 					s_removable = 1;
762 					strcpy(tmp2,tmp+10);
763 					strcpy(tmp,tmp2);
764 				} else {
765 					s_removable = 0;
766 				}
767 
768 				s_type = get_scsi_type(tmp);
769 
770 				/* allocate entry now */
771 				scsidevices[scsicount]=g_new(scsi_devices_t,1);
772 				scsidevices[scsicount]->sector_size = DATASECTORSIZE;
773 				scsidevices[scsicount]->devnr = idx;
774 				scsidevices[scsicount]->alt_dev = idx;
775 				scsidevices[scsicount]->transport = 0;
776 				scsidevices[scsicount]->bus = 0;
777 				scsidevices[scsicount]->id = idx;
778 				scsidevices[scsicount]->removable = s_removable;
779 				scsidevices[scsicount]->type = s_type;
780 			}
781 		}
782 	}
783 
784 	if (strncmp("Vendor_info",line,11) == 0) {
785 		p = strtok(line,":");
786 		if (p) {
787 			p = strtok(NULL,"");
788 			if (p) {
789 				strcpy(tmp2,p);
790 				extract_singlequoted(tmp2);
791 
792 				strcpy(s_vendor,"        ");
793 				if (strlen(tmp2) <= 8) {
794 					strncpy(s_vendor,tmp2,strlen(tmp2));
795 				} else {
796 					/* strip if to long */
797 					strncpy(s_vendor,tmp2,8);
798 				}
799 				s_vendor[8] = '\0';
800 
801 				if (scsidevices[scsicount]) {
802 					strcpy(scsidevices[scsicount]->vendor,s_vendor);
803 				}
804 			}
805 		}
806 	}
807 
808 	if (strncmp("Identifikation",line,14) == 0) {
809 		p = strtok(line,":");
810 		if (p) {
811 			p = strtok(NULL,"");
812 			if (p) {
813 				strcpy(tmp2,p);
814 				extract_singlequoted(tmp2);
815 
816 				strcpy(s_model,"                ");
817 				if (strlen(tmp2) <= 16) {
818 					strncpy(s_model,tmp2,strlen(tmp2));
819 				} else {
820 					strncpy(s_model,tmp2,16);
821 				}
822 				s_model[16] = '\0';
823 
824 				if (scsidevices[scsicount]) {
825 					strcpy(scsidevices[scsicount]->model,s_model);
826 				}
827 			}
828 		}
829 	}
830 
831 	if (strncmp("Revision",line,8) == 0) {
832 		p = strtok(line,":");
833 		if (p) {
834 			p = strtok(NULL,"");
835 			if (p) {
836 				strcpy(tmp2,p);
837 				extract_singlequoted(tmp2);
838 
839 				strcpy(s_rev,"    ");
840 				if (strlen(tmp2) <= 4) {
841 					strncpy(s_rev,tmp2,strlen(tmp2));
842 				} else {
843 					strncpy(s_rev,tmp2,4);
844 				}
845 				s_rev[4] = '\0';
846 
847 				if (scsidevices[scsicount]) {
848 					strcpy(scsidevices[scsicount]->rev,s_rev);
849 					scsicount++;
850 				}
851 			}
852 		}
853 	}
854 
855 	if (scsicount >= MAXDEVICES) {
856 		g_error("Error: More than %d devices scanned\n",MAXDEVICES);
857 	}
858 }
859 
860 
861 /* does scan for a single device only via inq call (osX) */
862 
scanbus_via_inq(gchar * dev,gint newdevnr,GtkWidget * txt)863 static gint scanbus_via_inq(gchar *dev, gint newdevnr, GtkWidget *txt) {
864 gchar line[MAXLINE];
865 gchar tmp[MAXLINE];
866 gchar tmp2[MAXLINE];
867 FILE *fpin;
868 scsi_devices_t **scsidevices;
869 gint found;
870 
871         scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
872         scsicount = 0;
873 
874 	get_wrap_path_cdrecord(line);
875 
876 	/* make sure we escape any critical chars in input */
877 	strncpy(tmp2,dev,MAXLINE);
878 	convert_escape(tmp2);
879 
880 	g_snprintf(tmp,MAXLINE," -inq dev= \"%s\" 2>&1",tmp2);
881 	strcat(line,tmp);
882 
883 	dodebug(1, "calling: %s\n", line);
884         if ((fpin = popen(line,"r")) == NULL) {
885                 g_error("popen error\n");
886         }
887 
888         for (;;) {
889                 if (fgets(line,MAXLINE,fpin) == NULL)
890                         break;
891 		dodebug(10,"scanbus: %s",line);
892                 parse_inq(line, newdevnr, scsidevices);
893         }
894 
895         if (pclose(fpin) == -1) {
896                 g_error("pclose error\n");
897         }
898 
899         found = 0;
900         if (scsidevices[0]) {
901                 add_writerreader(scsidevices[0], dev, txt);
902                 g_free(scsidevices[0]);
903                 found = 1;
904         }
905         g_free(scsidevices);
906 
907         return found;
908 }
909 
910 #endif
911 
912 /* scanbus scsi */
913 
scan_traditional(GtkWidget * txt)914 static void scan_traditional(GtkWidget *txt) {
915 gchar line[MAXLINE];
916 FILE *fpin;
917 gint count, errcount, ret;
918 scsi_devices_t **scsidevices;
919 
920 	scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
921 	scsicount = 0;
922 
923 	/* traditional scanning first */
924 	get_wrap_path_cdrecord(line);
925 	strcat(line," -scanbus 2>&1");
926 
927 	dodebug(1, "calling: %s\n", line);
928         if ((fpin = popen(line,"r")) == NULL) {
929                 g_error("popen error\n");
930         }
931 
932         for (;;) {
933                 if (fgets(line,MAXLINE,fpin) == NULL)
934                         break;
935 		dodebug(10,"scanbus: %s",line);
936                 parse_scan(line, -1, 0, scsidevices);
937         }
938 
939         if (pclose(fpin) == -1) {
940                 g_error("pclose error\n");
941         }
942 
943 	/* add the found devices to the writerreader structure */
944 	count = 0;
945 	errcount = 0;
946 	while(scsidevices[count] != NULL) {
947 		errcount+=add_writerreader(scsidevices[count],"", txt);
948 		g_free(scsidevices[count]);
949 		count++;
950 	}
951 	g_free(scsidevices);
952 
953 	/* historic mmap error check */
954 	if (errcount > 0) {
955                 ret = show_dialog(ICO_WARN, _("Warning: The cdrtools binaries you have installed are\nnot compatible with your system. You will NOT be\nable to read or write CDs. Please read the FAQ\non www.xcdroast.org for more information."), T_ANYWAY, _("Exit"), NULL, 1);
956                 if (ret == 1)
957                         gtk_exit(1);
958 	}
959 }
960 
961 
962 /* alternative transport method scanning */
963 /* valid transport choices for now: ATAPI USCSI REMOTE */
964 
scan_other(gchar * transport,gint transid,GtkWidget * txt)965 static gint scan_other(gchar *transport, gint transid, GtkWidget *txt) {
966 gchar line[MAXLINE];
967 gchar tmp[MAXLINE];
968 FILE *fpin;
969 gint count;
970 scsi_devices_t **scsidevices;
971 
972 	scsidevices = g_new0(scsi_devices_t *, MAXDEVICES);
973 	scsicount = 0;
974 
975 	get_wrap_path_cdrecord(line);
976 	g_snprintf(tmp,MAXLINE," dev=%s -scanbus 2>&1", transport);
977 	strcat(line, tmp);
978 
979 	dodebug(1, "calling: %s\n", line);
980        	if ((fpin = popen(line,"r")) == NULL) {
981                	 g_error("popen error\n");
982        	}
983 
984         for (;;) {
985          	if (fgets(line,MAXLINE,fpin) == NULL)
986                        	break;
987 		dodebug(10,"scanbus (%s): %s", transport, line);
988                	parse_scan(line, -1, transid, scsidevices);
989        	}
990 
991        	if (pclose(fpin) == -1) {
992                	g_error("pclose error\n");
993        	}
994 
995 	/* add the found devices to the writerreader structure */
996 	count = 0;
997 	g_snprintf(tmp,MAXLINE,"%s:", transport);
998 	while(scsidevices[count] != NULL) {
999 		add_writerreader(scsidevices[count], tmp, txt);
1000 		g_free(scsidevices[count]);
1001 		count++;
1002 	}
1003 	g_free(scsidevices);
1004 
1005 	return count;
1006 }
1007 
1008 
1009 /* new scanbus version */
1010 
scanbus_new(GtkWidget * txt,gint scanparam)1011 void scanbus_new(GtkWidget *txt, gint scanparam) {
1012 gchar tmp[MAXLINE];
1013 GdkFont *boldfont;
1014 gint doscanbus;
1015 gint i, devnr;
1016 
1017 	/* allocate memory */
1018 	if (!writerreaderdevs) {
1019 		writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
1020 	}
1021 
1022 	boldfont = get_some_font(BOLDFONT);
1023 	doscanbus = 1;
1024 
1025 	/* output status texts? */
1026 	if (txt) {
1027 		strncpy(tmp,_("Starting to scan for devices...\n"), MAXLINE);
1028 		convert_for_gtk2_textwidget(tmp);
1029 		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1030 		wait_and_process_events();
1031 	}
1032 
1033 	/* check if we have to do full scanbus, or only partial */
1034 	if (alt_scsidevices[0] != NULL) {
1035 		i = 0;
1036 		while (alt_scsidevices[i] != NULL) {
1037 			/* look for a free device number (greater 8192) */
1038 			for (devnr = 8192; devnr < 8192 + MAXDEVICES; devnr++) {
1039 				if (get_writerreaderdevs_index(devnr) == -1) {
1040 					break;
1041 				}
1042 			}
1043 			scanbus_single(alt_scsidevices[i], devnr, txt);
1044 			i++;
1045 		}
1046 
1047 		/* trigger not to scan the bus any futher */
1048 		doscanbus = 0;
1049 	}
1050 
1051 #if (defined(__MACH__) && defined(__APPLE__))
1052 
1053 	/* special handling for osX */
1054 	/* try fixed list of devices */
1055 	alt_scsidevices[0] = g_strdup("IOCompactDiscServices");
1056 	alt_scsidevices[1] = g_strdup("IOCompactDiscServices/2");
1057 	alt_scsidevices[2] = g_strdup("IOCompactDiscServices/3");
1058 	alt_scsidevices[3] = g_strdup("IODVDServices");
1059 	alt_scsidevices[4] = g_strdup("IODVDServices/2");
1060 	alt_scsidevices[5] = g_strdup("IODVDServices/3");
1061 
1062 	i = 0;
1063 	while (alt_scsidevices[i] != NULL) {
1064 		scanbus_via_inq(alt_scsidevices[i], 4096+i, txt);
1065 		i++;
1066 	}
1067 
1068 	/* trigger not to scan the bus any futher */
1069 	doscanbus = 0;
1070 #endif
1071 
1072 	if (doscanbus) {
1073 		/* scan for scsi devices */
1074 		scan_traditional(txt);
1075 
1076 		/* scan for alternatives */
1077 #if defined(linux)
1078 		if (scanparam) {
1079 			scan_other("ATA", 1, txt);
1080 		}
1081 #endif
1082 #if defined(sun)
1083 		if (scanparam) {
1084 			scan_other("USCSI", 2, txt);
1085 		}
1086 #endif
1087 	}
1088 
1089 	if (txt) {
1090 		strncpy(tmp,_("Scan finished.\n"), MAXLINE);
1091 		convert_for_gtk2_textwidget(tmp);
1092 		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1093 		wait_and_process_events();
1094 	}
1095 
1096 	gdk_font_unref(boldfont);
1097 
1098 
1099 	if (debug) print_writerreaderdevs();
1100 
1101 }
1102 
1103 
1104 
1105 /* scan for remote scsi devices */
1106 
scanbus_rscsi(gchar * devstr,GtkWidget * txt)1107 void scanbus_rscsi(gchar *devstr, GtkWidget *txt) {
1108 gchar tmp[MAXLINE];
1109 GdkFont *boldfont;
1110 gint found;
1111 gint i, highest;
1112 
1113 	/* allocate memory */
1114 	if (!writerreaderdevs) {
1115 		writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
1116 	}
1117 
1118 	boldfont = get_some_font(BOLDFONT);
1119 
1120 	/* output status texts? */
1121 	if (txt) {
1122 		strncpy(tmp,_("Starting to scan for remote devices...\n"), MAXLINE);
1123 		convert_for_gtk2_textwidget(tmp);
1124 		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1125 		wait_and_process_events();
1126 	}
1127 
1128 	/* look for highest free devnr - but at least a multiple of 16384 */
1129 	i = 0;
1130 	highest = -1;
1131 	while(writerreaderdevs[i] != NULL) {
1132 		if (writerreaderdevs[i]->devnr > highest) {
1133 			highest = writerreaderdevs[i]->devnr;
1134 		}
1135 		i++;
1136 	}
1137 	highest++;
1138 
1139 	/* when we scan multiple times always arange a new block to play safe */
1140 	highest = ((highest/16384)+1)*16384;
1141 
1142 	found = scan_other(devstr, highest/1024, txt);
1143 
1144 	if (txt) {
1145 		if (found == 0) {
1146 			strncpy(tmp,_("No devices found - check your remote scsi setup.\n"), MAXLINE);
1147 			convert_for_gtk2_textwidget(tmp);
1148 			gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp, strlen(tmp));
1149 		}
1150 		strncpy(tmp,_("Scan finished.\n"), MAXLINE);
1151 		convert_for_gtk2_textwidget(tmp);
1152 		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1153 		wait_and_process_events();
1154 	}
1155 
1156 	gdk_font_unref(boldfont);
1157 
1158 
1159 	if (debug) print_writerreaderdevs();
1160 }
1161 
1162 
1163 /* special version where we scan only for a single device */
1164 
scanbus_new_single(gchar * devstr,GtkWidget * txt)1165 void scanbus_new_single(gchar *devstr, GtkWidget *txt) {
1166 gchar tmp[MAXLINE];
1167 GdkFont *boldfont;
1168 gint devnr, found;
1169 
1170 	/* allocate memory */
1171 	if (!writerreaderdevs) {
1172 		writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
1173 	}
1174 
1175 	boldfont = get_some_font(BOLDFONT);
1176 
1177 	/* output status texts? */
1178 	if (txt) {
1179 		strncpy(tmp,_("Starting to scan for devices...\n"), MAXLINE);
1180 		convert_for_gtk2_textwidget(tmp);
1181 		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1182 		wait_and_process_events();
1183 	}
1184 
1185 	/* look for a free device number (greater 8192) */
1186 	for (devnr = 8192; devnr < 8192 + MAXDEVICES; devnr++) {
1187 		if (get_writerreaderdevs_index(devnr) == -1) {
1188 			break;
1189 		}
1190 	}
1191 	found = scanbus_single(devstr, devnr, txt);
1192 
1193 	if (txt) {
1194 		if (!found) {
1195 			strncpy(tmp,_("Device not found.\n"), MAXLINE);
1196 			convert_for_gtk2_textwidget(tmp);
1197 			gtk_text_insert(GTK_TEXT(txt), NULL, NULL, NULL, tmp, strlen(tmp));
1198 		}
1199 		strncpy(tmp,_("Scan finished.\n"), MAXLINE);
1200 		convert_for_gtk2_textwidget(tmp);
1201 		gtk_text_insert(GTK_TEXT(txt), boldfont, NULL, NULL, tmp, strlen(tmp));
1202 		wait_and_process_events();
1203 	}
1204 
1205 	gdk_font_unref(boldfont);
1206 
1207 
1208 	if (debug) print_writerreaderdevs();
1209 }
1210 
1211 
1212 /* interpret output of driver=help and sort into memory structure */
1213 
parse_driver(gchar * line)1214 static void parse_driver(gchar *line) {
1215 gchar tmp[MAXLINE];
1216 gchar tmp2[MAXLINE];
1217 gchar drv[MAXLINE];
1218 gchar *p1;
1219 gint n;
1220 	if (strncmp(line,"Driver types:",13) != 0 ) {
1221 
1222 		strcpy(tmp,line);
1223 		p1=strtok(tmp," ");
1224 		strcpy(drv,p1);
1225 		/* now drv contains the driver name */
1226 
1227 		p1=strtok(NULL,"");
1228 		strcpy(tmp2,p1);
1229 		strip_string(tmp2);
1230 		/* now tmp2 contains the description */
1231 
1232 		/* cut "driver for" away */
1233 		if (strncmp(tmp2,"driver for ",11) == 0 ){
1234 			strcpy(tmp,tmp2+11);
1235 			strcpy(tmp2,tmp);
1236 		}
1237 
1238 		/* allocate structure */
1239 		drivers[drvcount]=g_new(writer_driver_t,1);
1240 
1241 		n = strlen(drv)+1;
1242 		drivers[drvcount]->driver=g_new(gchar,n);
1243 		strcpy(drivers[drvcount]->driver,drv);
1244 
1245 		n = strlen(tmp2)+1;
1246 		drivers[drvcount]->desc=g_new(gchar,n);
1247 		strcpy(drivers[drvcount]->desc,tmp2);
1248 
1249 		drvcount++;
1250 		if (drvcount >= MAXDRIVERS) {
1251 			g_error("Error: More than %d writer devices found\n",MAXDRIVERS);
1252 		}
1253 	}
1254 }
1255 
1256 
1257 /* print memory-structure with drivers (debug purposes) */
1258 
print_drivers()1259 static void print_drivers() {
1260 gint count;
1261 
1262 	dodebug(2,"------ cdrecord drivers-structure -----\n");
1263 	count = 0;
1264 	while(drivers[count] != NULL) {
1265 		dodebug(2, "%s:%s\n",
1266 			drivers[count]->driver,
1267 			drivers[count]->desc);
1268 
1269 		count++;
1270 	}
1271 }
1272 
1273 
1274 /* call cdrecord driver=help */
1275 
scandrivers()1276 void scandrivers() {
1277 gchar line[MAXLINE];
1278 FILE *fpin;
1279 
1280 	/* allocate memory */
1281 	drivers = g_new0(writer_driver_t *,MAXDRIVERS);
1282 	drvcount = 0;
1283 
1284 	get_wrap_path_cdrecord(line);
1285 	strcat(line," driver=help 2>&1");
1286 
1287 	dodebug(1, "calling: %s\n", line);
1288         if ((fpin = popen(line,"r")) == NULL) {
1289                 g_error("popen error\n");
1290         }
1291 
1292         for (;;) {
1293                 if (fgets(line,MAXLINE,fpin) == NULL)
1294                         break;
1295 		dodebug(10, "driverlist: %s",line);
1296                 parse_driver(line);
1297         }
1298 
1299         if (pclose(fpin) == -1) {
1300                 g_error("pclose error\n");
1301         }
1302 
1303 	if (debug) print_drivers();
1304 }
1305 
1306 
1307 /* print memory-structure with charsets (debug purposes) */
1308 
print_charsets()1309 static void print_charsets() {
1310 gint count;
1311 gchar tmp[MAXLINE];
1312 
1313 	dodebug(2,"------ mkisofs-charsets-structure -----\n");
1314 	count = 0;
1315 	strcpy(tmp,"");
1316 	while(charset_types[count] != NULL) {
1317 
1318 		strcat(tmp,charset_types[count]);
1319 
1320 		if ((count+1) % 6) {
1321 			strcat(tmp, ", ");
1322 		} else {
1323 			dodebug(2, "%s\n", tmp);
1324 			strcpy(tmp,"");
1325 		}
1326 		count++;
1327 	}
1328 	if (strcmp(tmp,"") != 0)
1329 		dodebug(2, "%s\n", tmp);
1330 }
1331 
1332 
1333 /* call mkisofs -input-charset help */
1334 
scancharsets()1335 void scancharsets() {
1336 gchar line[MAXLINE];
1337 FILE *fpin;
1338 gint start,count,backcount;
1339 gchar **tmp_types;
1340 
1341 	/* allocate memory */
1342 	charset_types = g_new0(gchar *,MAXCHARSETS+1);
1343 	tmp_types = g_new0(gchar *,MAXCHARSETS+1);
1344 
1345 	start = 0;
1346 	count = 0;
1347 
1348 	get_wrap_path("MKISOFS",line);
1349 	strcat(line," -input-charset help 2>&1");
1350 
1351 	dodebug(1, "calling: %s\n", line);
1352         if ((fpin = popen(line,"r")) == NULL) {
1353                 g_error("popen error\n");
1354         }
1355 
1356         for (;;) {
1357                 if (fgets(line,MAXLINE,fpin) == NULL)
1358                         break;
1359 		/* wait for Known charsets.... line */
1360 		if (strncmp("Known",line,5) == 0) {
1361 			start = 1;
1362 			continue;
1363 		}
1364 		if (start) {
1365 			dodebug(10, "mkisofs charsets: %s",line);
1366 
1367 			tmp_types[count] = g_strdup(strip_string(line));
1368 			count++;
1369 			if (count >= MAXCHARSETS) {
1370 				g_error("Error: More than %d input charsets found\n",MAXCHARSETS);
1371 			}
1372 		}
1373         }
1374 
1375 	tmp_types[count] = g_strdup("default");
1376 
1377         if (pclose(fpin) == -1) {
1378                 g_error("pclose error\n");
1379         }
1380 
1381 	/* now the types list is reversed, make it right */
1382 	backcount = count;
1383 	count = 0;
1384 	while(backcount >= 0) {
1385 		charset_types[count] = tmp_types[backcount];
1386 		count++;
1387 		backcount--;
1388 	}
1389 	g_free(tmp_types);
1390 
1391 	if (debug) print_charsets();
1392 }
1393 
1394 
1395 /* call cdrecord -prcap to get some device information */
1396 /* also checks for mmap errors and return 1 if one occured */
1397 
getdevicecap(gchar * dev,gint * readmax,gint * cdrmax,gint * dvdmax,gint * iscdr,gint * isdvdrom,gint * isdvdr)1398 static gint getdevicecap(gchar *dev, gint *readmax, gint *cdrmax, gint *dvdmax, gint *iscdr, gint *isdvdrom, gint *isdvdr) {
1399 gchar tmp[MAXLINE];
1400 gchar line[MAXLINE];
1401 gint tmpnr, errcount;
1402 FILE *fpin;
1403 gchar *p;
1404 
1405 	/* set reasonable defaults */
1406 	*readmax = 0;
1407 	*cdrmax = 0;
1408 	*dvdmax = 0;
1409 	*iscdr = 0;
1410 	*isdvdr = 0;
1411 	*isdvdrom = 0;
1412 
1413         if (!dev) return 0;
1414 
1415         get_wrap_path_cdrecord(tmp);
1416         g_snprintf(line, MAXLINE, "%s dev= \"%s\" -prcap 2>&1", tmp, dev);
1417 
1418         dodebug(1, "calling: %s\n", line);
1419         if ((fpin = popen(line,"r")) == NULL) {
1420                 g_error("popen error\n");
1421         }
1422 
1423 	errcount = 0;
1424         for (;;) {
1425                 if (fgets(line,MAXLINE,fpin) == NULL)
1426                         break;
1427                 dodebug(10, "prcap: %s",line);
1428 
1429                 /* line with mmap error? */
1430                 if (strstr(line,"annot get mmap for")) {
1431                         errcount++;
1432                 }
1433 
1434 		if (strstr(line, "Does write CD-R media")) {
1435 			*iscdr = 1;
1436 		}
1437 		if (strstr(line, "Does read DVD-ROM media")) {
1438 			*isdvdrom = 1;
1439 		}
1440 		if (strstr(line, "Does write DVD-R media")) {
1441 			*isdvdr = 1;
1442 		}
1443 		if (strstr(line, "Maximum read  speed:")) {
1444 			p = strtok(line,"(");
1445 			if (p) {
1446 				p = strtok(NULL,")");
1447 				if (p) {
1448 					strcpy(tmp,p);
1449 					sscanf(tmp,"CD %3dx, DVD %3d",
1450 						readmax, &tmpnr);
1451 				}
1452 			}
1453 		} else
1454 		if (strstr(line, "Maximum write speed:")) {
1455 			p = strtok(line,"(");
1456 			if (p) {
1457 				p = strtok(NULL,")");
1458 				if (p) {
1459 					strcpy(tmp,p);
1460 					sscanf(tmp,"CD %3dx, DVD %3d",
1461 						cdrmax, dvdmax);
1462 				}
1463 			}
1464 		}
1465 	}
1466 
1467         if (pclose(fpin) == -1) {
1468                 g_error("pclose error\n");
1469         }
1470 
1471         if (errcount > 0) {
1472                 return 1;
1473         } else {
1474                 return 0;
1475         }
1476 }
1477 
1478 
1479 /* get driverflags and modes from drive */
1480 
getmodesflags(gchar * dev,gchar * drvflags,gchar * drvmodes)1481 void getmodesflags(gchar *dev, gchar *drvflags, gchar *drvmodes) {
1482 gchar tmp[MAXLINE];
1483 gchar line[MAXLINE];
1484 FILE *fpin;
1485 gchar *p;
1486 
1487 	strcpy(drvflags,"");
1488 	strcpy(drvmodes,"");
1489 
1490         if (!dev) return;
1491 
1492         get_wrap_path("CDRECORD", tmp);
1493         g_snprintf(line, MAXLINE, "%s dev= \"%s\" -v -checkdrive 2>&1", tmp, dev);
1494 
1495         dodebug(1, "calling: %s\n", line);
1496         if ((fpin = popen(line,"r")) == NULL) {
1497                 g_error("popen error\n");
1498         }
1499         for (;;) {
1500                 if (fgets(line,MAXLINE,fpin) == NULL)
1501                         break;
1502                 dodebug(10, "checkdrive: %s",line);
1503 
1504 		if (strstr(line, "Driver flags   :")) {
1505 			p = strtok(line,":");
1506 			if (p) {
1507 				p = strtok(NULL,"");
1508 				if (p) {
1509 					strncpy(tmp,p,MAXLINE);
1510 					strip_string(tmp);
1511 					strncpy(drvflags,tmp,MAXLINE);
1512 				}
1513 			}
1514 		} else
1515 		if (strstr(line, "Supported modes:")) {
1516 			p = strtok(line,":");
1517 			if (p) {
1518 				p = strtok(NULL,"");
1519 				if (p) {
1520 					strncpy(tmp,p,MAXLINE);
1521 					strip_string(tmp);
1522 					strncpy(drvmodes,tmp,MAXLINE);
1523 				}
1524 			}
1525 		}
1526 	}
1527 
1528         if (pclose(fpin) == -1) {
1529                 g_error("pclose error\n");
1530         }
1531 }
1532 
1533 
parse_freespace(gchar * line,gchar * fs)1534 static gint parse_freespace(gchar *line, gchar *fs) {
1535 gchar tmp[MAXLINE];
1536 gchar *p1;
1537 
1538 	/* skip first line(s) */
1539 	if (index(line,'/')) {
1540 	        strcpy(tmp,line);
1541 #if defined (aix)
1542 		/* filesystem label */
1543 		p1=strtok(tmp," ");
1544 		if (fs != NULL) {
1545 		     /* get the filesystem */
1546 		     strcpy(fs,p1);
1547 		}
1548 		/* size of filesystem */
1549 		p1=strtok(NULL," ");
1550 		if (p1 == NULL) {
1551 			g_error("df -k output syntax error\n");
1552 		}
1553 		/* available blocks */
1554 		p1=strtok(NULL," ");
1555 		if (p1 == NULL) {
1556 			g_error("df -k output syntax error\n");
1557 		}
1558 		return (atoi(p1));
1559 #elif defined (hpux)
1560 		/* mountpoint */
1561 		p1=strtok(tmp,"(");
1562 		if (p1 == NULL) {
1563 			g_error("df -b output syntax error\n");
1564 		}
1565 		/* filesystem label */
1566 		p1=strtok(NULL,")");
1567 		if (fs != NULL) {
1568 		     /* get the filesystem - avoid "(" at the beginning */
1569 		     strcpy(fs,p1);
1570 		}
1571 		/* size in kb */
1572 		p1=strtok(NULL,": ");
1573 		if (p1 == NULL) {
1574 			g_error("df -b output syntax error\n");
1575 		}
1576 		return (atoi(p1));
1577 #else
1578 
1579 		/* skip the first 4 fields in output to come to "available" */
1580 
1581 		/* are we handling the first line of two?*/
1582 		p1=strtok(tmp," ");
1583 
1584 		if (dfrun == 0) {
1585 			if (fs != NULL) {
1586 				/* get the filesystem */
1587 				strcpy(fs,p1);
1588 			}
1589 
1590 			p1=strtok(NULL," ");
1591 			if (p1 == NULL) {
1592 				/* ok..output splitted on two lines */
1593 				dfrun = 1;
1594 				return -1;
1595 			}
1596 		}
1597 		p1=strtok(NULL," ");
1598 		if (p1 == NULL) {
1599 			g_error("df -k output syntax error\n");
1600 		}
1601 		p1=strtok(NULL," ");
1602 		if (p1 == NULL) {
1603 			g_error("df -k output syntax error\n");
1604 		}
1605 		return (atoi(p1));
1606 #endif
1607 	}
1608 	return -1;
1609 }
1610 
1611 
1612 /* get free diskspace. return in 1024byte blocks or -1 if not valid */
1613 /* return filesystem if not set to NULL */
1614 /* will handle if output is in two lines...like when the filesystem
1615    output is longer that 20 chars - e.g. on nfs-links */
1616 /* will handle df-output like:
1617 
1618 (Solaris)
1619 Filesystem            kbytes    used   avail capacity  Mounted on
1620 fileserv:/export/home
1621                      17502608 11609120 5718464    67%    /export/home
1622 
1623 OR
1624 
1625 (Linux)
1626 Filesystem         1024-blocks  Used Available Capacity Mounted on
1627 /dev/sda3            2494898 1606489   759428     68%   /
1628 
1629 Syst�me de
1630 fichiers          1K-blocs    Utilis� Disponible U.% Mont� sur
1631 /dev/hda6             10080488   8043456   1524964  85% /
1632 
1633 OR
1634 
1635 (AIX)
1636 Filesystem    1024-blocks      Free %Used    Iused %Iused Mounted on
1637 /dev/hd4             8192      2968   64%     1319    33% /
1638 /dev/hd2           573440     31644   95%    22280    16% /usr
1639 
1640 OR
1641 
1642 (HP-UXs df -b)
1643 /tmp                   (/dev/vg00/lvol4       ) :   188158 Kbytes free
1644 /usr                   (/dev/vg00/lvol5       ) :   286696 Kbytes free
1645 
1646 
1647 */
1648 
get_free_space(gchar * path,gchar * filesystem)1649 gint get_free_space(gchar *path, gchar *filesystem) {
1650 gchar line[MAXLINE];
1651 FILE *fpin;
1652 gint space;
1653 
1654 	space = -1;
1655 	dfrun = 0;
1656 
1657 	if (is_directory(path) != 1) {
1658 		return -1;
1659 	}
1660 
1661 	if (stat_file(DF)) {
1662 		strcpy(line,DF);
1663 		strcat(line," \"");
1664 		strcat(line,path);
1665 		strcat(line,"\"");
1666 	} else {
1667 		strcpy(line,DF2);
1668 		strcat(line," \"");
1669 		strcat(line,path);
1670 		strcat(line,"\"");
1671 	}
1672 
1673 	dodebug(1, "calling: %s\n", line);
1674         if ((fpin = popen(line,"r")) == NULL) {
1675                 g_error("popen error\n");
1676         }
1677 
1678         for (;;) {
1679                 if (fgets(line,MAXLINE,fpin) == NULL)
1680                         break;
1681 		dodebug(10,"df: %s",line);
1682                 space = parse_freespace(line,filesystem);
1683         }
1684 
1685         if (pclose(fpin) == -1) {
1686                 g_error("pclose error\n");
1687         }
1688 
1689 	if (filesystem != NULL) {
1690 		dodebug(2, "filesystem lookup for %s = %d blocks, fs = %s\n",
1691 			path, space, filesystem);
1692 	} else {
1693 		dodebug(2, "filesystem lookup for %s = %d blocks, fs = %s\n",
1694 			path, space, "(NULL)");
1695 	}
1696 
1697 	return space;
1698 }
1699 
1700 
1701 /* get a list of all audio-devices found on a system. This has to be
1702    done platform dependent */
1703 
get_dsp_devices()1704 GList *get_dsp_devices() {
1705 GList *dsp;
1706 GList *loop;
1707 #if !(defined(__MACH__) && defined(__APPLE__))
1708 struct stat buf;
1709 #endif
1710 
1711 #if defined(sun) || defined(aix) || defined(__OpenBSD__)
1712 gchar *audiodev;
1713 #endif
1714 	dsp = NULL;
1715 
1716 #if defined(linux) || defined(__FreeBSD__)
1717 	/* for linux check if /dev/dsp or /dev/dsp1 exist */
1718 
1719 	if (stat("/dev/dsp",&buf) == 0) {
1720 		dsp = g_list_append(dsp,"/dev/dsp");
1721 	}
1722 	if (stat("/dev/dsp1",&buf) == 0) {
1723 		dsp = g_list_append(dsp,"/dev/dsp1");
1724 	}
1725 #endif
1726 #if defined(sun) || defined(__OpenBSD__)
1727 	/* check if the user has any special audio-hardware running,
1728 	   which set the AUDIODEV-environment-variable */
1729 	audiodev = getenv("AUDIODEV");
1730 	if (audiodev != NULL) {
1731 
1732 		if (stat(audiodev,&buf) == 0) {
1733 			dsp = g_list_append(dsp,g_strdup(audiodev));
1734 		}
1735 	} else {
1736 		audiodev = "";
1737 	}
1738 	if (strcmp(audiodev,"/dev/audio") != 0) {
1739 
1740 		if (stat("/dev/audio",&buf) == 0) {
1741 			dsp = g_list_append(dsp,"/dev/audio");
1742 		}
1743 	}
1744 #endif
1745 #ifdef aix
1746        audiodev = getenv ("AUDIODEV");
1747        if (audiodev != NULL) {
1748 
1749                if (stat (audiodev, &buf) == 0) {
1750                        dsp = g_list_append (dsp, g_strdup(audiodev));
1751                }
1752        }
1753        /* Try to use the device of a machine with PCI bus */
1754         if (stat ("/dev/paud0/1", &buf) == 0) {
1755                dsp = g_list_append (dsp, "/dev/paud0/1");
1756        }
1757         /* Try to use the device of a machine with MCA bus */
1758         if (stat ("/dev/baud0/1", &buf) == 0) {
1759                dsp = g_list_append (dsp, "/dev/baud0/1");
1760        }
1761 #endif
1762 #ifdef hpux
1763 # ifndef hpux_alib
1764 
1765        /* for HP-UX check if /dev/audio exists - I've never seen */
1766        /* other audio devices under HP-UX                        */
1767 
1768        if (stat("/dev/audio",&buf) == 0) {
1769                dsp = g_list_append(dsp,"/dev/audio");
1770        }
1771 # else
1772        /* for HP-UX with the Alib we dont need to check if the    */
1773        /* device exists - we actually do not know even the device */
1774        dsp = g_list_append(dsp,"AUDIO ENVIRONMENT");
1775 # endif
1776 #endif
1777 
1778 #if (defined(__MACH__) && defined(__APPLE__))
1779 
1780 	/* on macosX we always should have the build-in-audio device */
1781        dsp = g_list_append(dsp,"Apple CoreAudio");
1782 #endif
1783 
1784 #if defined(__sgi)
1785 {
1786        int     i, rv;
1787        ALvalue devs [16];
1788        ALpv    q [1];
1789        char    devLabel [32];
1790 
1791        /*
1792         * Fetch the list of available output audio devices.
1793         */
1794        q[0].param = AL_TYPE;
1795        q[0].value.i = AL_OUTPUT_DEVICE_TYPE;
1796        if ((rv = alQueryValues(AL_SYSTEM, AL_DEVICES, devs, 16, q, 1)) >= 0) {
1797 
1798                for (i = 0; i < rv; i++) {
1799                        q[0].param = AL_LABEL;
1800                        q[0].value.ptr = devLabel;
1801                        q[0].sizeIn = 32;
1802                        alGetParams(devs[i].i, q, 1);
1803                        if (alIsSubtype(AL_DEVICE_TYPE, devs[i].i)) {
1804                                dsp = g_list_append(dsp, g_strdup(devLabel));
1805                        }
1806                }
1807        }
1808 }
1809 #endif
1810 
1811 	/* do some debug output */
1812 	if (debug) {
1813 		loop = g_list_first(dsp);
1814 		while(loop) {
1815 			if (loop->data != NULL)
1816 				dodebug(10, "dspscan: %s\n",
1817 					(gchar *) loop->data);
1818 			loop = loop->next;
1819 		}
1820 	}
1821 
1822 	return g_list_first(dsp);
1823 }
1824 
1825 
1826 /* take a dsp-device and find the fitting mixer-device */
1827 
gen_mix_from_dspdev(gchar * dsp,gchar * ret)1828 gchar *gen_mix_from_dspdev(gchar *dsp, gchar *ret) {
1829 #if !(defined(__MACH__) && defined(__APPLE__))
1830 gchar tmp[MAXLINE];
1831 # ifndef aix
1832 struct stat buf;
1833 # endif
1834 #endif
1835 #if defined(linux) || defined(__FreeBSD__)
1836 gchar tmp2[MAXLINE];
1837 #endif
1838 
1839 	strcpy(ret,"");
1840 
1841 #if defined(linux) || defined(__FreeBSD__)
1842 
1843 	if (strncmp(dsp,"/dev/dsp",8) == 0) {
1844 		strcpy(tmp,dsp+8);
1845 		g_snprintf(tmp2,MAXLINE,"/dev/mixer%s",tmp);
1846 
1847 		/* does device exist? */
1848 		if (stat(tmp2,&buf) == 0) {
1849 			strcpy(ret,tmp2);
1850 		}
1851 	}
1852 #endif
1853 #if defined(sun) || defined(__OpenBSD__)
1854 
1855 	g_snprintf(tmp,MAXLINE,"%s%s",dsp,"ctl");
1856 
1857 		/* does device exist? */
1858 		if (stat(tmp,&buf) == 0) {
1859 			strcpy(ret,tmp);
1860 		}
1861 #endif
1862 #ifdef aix
1863        /* The gain will be set via ioctl and the usual */
1864         /* output device                                */
1865        g_snprintf(tmp,MAXLINE,"%s",dsp);
1866        strcpy(ret,tmp);
1867 #endif
1868 #ifdef hpux
1869 # ifndef hpux_alib
1870 	g_snprintf(tmp,MAXLINE,"%s%s",dsp,"Ctl");
1871 
1872 	/* does device exist? */
1873 	if (stat(tmp,&buf) == 0) {
1874 	        strcpy(ret,tmp);
1875 	}
1876 # else
1877 	/* We have no control or mixer device -> all is */
1878 	/* done via the Aserver-daemon and its API      */
1879 	strcpy(ret, "ASERVER");
1880 # endif
1881 #endif
1882 
1883 	dodebug(10, "mixer: %s\n", ret);
1884 	return ret;
1885 }
1886 
1887 
1888 /* call uname -a to get a nice system-id-string */
1889 
get_uname_info(gchar * str)1890 gchar *get_uname_info(gchar *str) {
1891 FILE *fpin;
1892 
1893 	if (stat_file(UNAME)) {
1894 		dodebug(1, "calling: %s\n", UNAME);
1895        		if ((fpin = popen(UNAME,"r")) == NULL) {
1896                 	g_error("popen error\n");
1897 		}
1898         } else {
1899 		dodebug(1, "calling: %s\n", UNAME2);
1900        		if ((fpin = popen(UNAME2,"r")) == NULL) {
1901                 	g_error("popen error\n");
1902 		}
1903 	}
1904 
1905 	strcpy(str,"");
1906 	fgets(str,MAXLINE,fpin);
1907 
1908         if (pclose(fpin) == -1) {
1909                 g_error("pclose error\n");
1910         }
1911 
1912 	dodebug(10, "uname: %s\n", str);
1913 
1914 	return str;
1915 }
1916 
1917 
1918 /* Save the setup-configuration to a file - all strings are converted
1919    in a printable form first:  return 0 if ok, or 1 on error */
1920 
save_setup_config(gchar * confdir,gchar * fname)1921 gint save_setup_config(gchar *confdir, gchar *fname) {
1922 FILE *fd;
1923 gchar tmp[MAXLINE];
1924 gchar tmp2[MAXLINE];
1925 GList *loop;
1926 gint count;
1927 
1928 	/* no confdir? treat path absolute */
1929 	if (strcmp(confdir,"") == 0) {
1930 		strncpy(tmp,fname,MAXLINE);
1931 	} else {
1932 
1933 		/* now check if the confdir exists */
1934 		if (!is_directory(confdir)) {
1935 			/* try to create directory */
1936 			mkdir(confdir, 0700);
1937 			dodebug(2, "trying to mkdir %s\n", confdir);
1938 		}
1939 
1940 		g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
1941 	}
1942 
1943 	dodebug(1, "Opening %s for writing\n", tmp);
1944 	dolog(3, "Saving config file %s\n", tmp);
1945 
1946 	fd = fopen(tmp,"w");
1947 
1948 	if (fd == NULL) {
1949 		/* error opening file */
1950 		return 1;
1951 	}
1952 
1953 	/* write the config-file header */
1954 	fputs("#\n",fd);
1955 	g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Configuration-File\n",XCDROAST_VERSION);
1956 	fputs(tmp,fd);
1957 	fputs("#\n",fd);
1958 	fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
1959 	fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
1960 	fputs("#\n\n",fd);
1961 
1962 	/* write data */
1963 	g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
1964 	fputs(tmp,fd);
1965 	g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
1966 	fputs(tmp,fd);
1967 	g_snprintf(tmp,MAXLINE,"WRITER_DEVNR = %d\n",setupdata.writer_devnr);
1968 	fputs(tmp,fd);
1969 	g_snprintf(tmp,MAXLINE,"READER_DEVNR = %d\n",setupdata.reader_devnr);
1970 	fputs(tmp,fd);
1971 
1972 	fputs("#\n",fd);
1973 
1974 	/* write hardware structure */
1975 	count = 0;
1976 	while(writerreaderdevs[count] != NULL) {
1977 
1978 		g_snprintf(tmp,MAXLINE,"WRITERREADER_DEVNR = %d\n",writerreaderdevs[count]->devnr);
1979 		fputs(tmp,fd);
1980 
1981 		strcpy(tmp2,writerreaderdevs[count]->devicestr);
1982 		g_snprintf(tmp,MAXLINE,"WRITERREADER_DEVICESTR = \"%s\"\n",convert_escape(tmp2));
1983 		fputs(tmp,fd);
1984 
1985 		strcpy(tmp2,writerreaderdevs[count]->vendor);
1986 		g_snprintf(tmp,MAXLINE,"WRITERREADER_VENDOR = \"%s\"\n",convert_escape(tmp2));
1987 		fputs(tmp,fd);
1988 		strcpy(tmp2,writerreaderdevs[count]->model);
1989 		g_snprintf(tmp,MAXLINE,"WRITERREADER_MODEL = \"%s\"\n",convert_escape(tmp2));
1990 		fputs(tmp,fd);
1991 		strcpy(tmp2,writerreaderdevs[count]->rev);
1992 		g_snprintf(tmp,MAXLINE,"WRITERREADER_REV = \"%s\"\n",convert_escape(tmp2));
1993 		fputs(tmp,fd);
1994 
1995 		g_snprintf(tmp,MAXLINE,"WRITERREADER_READMAXSPEED = %d\n",writerreaderdevs[count]->writer_readmaxspeed);
1996 		fputs(tmp,fd);
1997 		g_snprintf(tmp,MAXLINE,"WRITERREADER_CDRMAXSPEED = %d\n",writerreaderdevs[count]->writer_cdrmaxspeed);
1998 		fputs(tmp,fd);
1999 		g_snprintf(tmp,MAXLINE,"WRITERREADER_DVDMAXSPEED = %d\n",writerreaderdevs[count]->writer_dvdmaxspeed);
2000 		fputs(tmp,fd);
2001 
2002 		strcpy(tmp2,writerreaderdevs[count]->writer_flags);
2003 		g_snprintf(tmp,MAXLINE,"WRITERREADER_WRITER_FLAGS = \"%s\"\n",convert_escape(tmp2));
2004 		fputs(tmp,fd);
2005 		strcpy(tmp2,writerreaderdevs[count]->writer_modes);
2006 		g_snprintf(tmp,MAXLINE,"WRITERREADER_WRITER_MODES = \"%s\"\n",convert_escape(tmp2));
2007 		fputs(tmp,fd);
2008 
2009 		g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_CDRWRITER = %d\n",writerreaderdevs[count]->is_cdrwriter);
2010 		fputs(tmp,fd);
2011 		g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_DVDWRITER = %d\n",writerreaderdevs[count]->is_dvdwriter);
2012 		fputs(tmp,fd);
2013 		g_snprintf(tmp,MAXLINE,"WRITERREADER_IS_DVDREADER = %d\n",writerreaderdevs[count]->is_dvdreader);
2014 		fputs(tmp,fd);
2015 		g_snprintf(tmp,MAXLINE,"WRITERREADER_SECTOR_SIZE = %d\n",writerreaderdevs[count]->sector_size);
2016 		fputs(tmp,fd);
2017 
2018 		g_snprintf(tmp,MAXLINE,"WRITERREADER_DRVMODE = %d\n",writerreaderdevs[count]->writer_drvmode);
2019 		fputs(tmp,fd);
2020 		g_snprintf(tmp,MAXLINE,"WRITERREADER_MODE = %d\n",writerreaderdevs[count]->writer_mode);
2021 		fputs(tmp,fd);
2022 		g_snprintf(tmp,MAXLINE,"WRITERREADER_SPEED = %d\n",writerreaderdevs[count]->writer_speed);
2023 		fputs(tmp,fd);
2024 		g_snprintf(tmp,MAXLINE,"WRITERREADER_FIFO = %d\n",writerreaderdevs[count]->writer_fifo);
2025 		fputs(tmp,fd);
2026 		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_INTERFACE = %d\n",writerreaderdevs[count]->audioread_interface);
2027 		fputs(tmp,fd);
2028 		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_SPEED = %d\n",writerreaderdevs[count]->audioread_speed);
2029 		fputs(tmp,fd);
2030 		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_OVERLAP = %d\n",writerreaderdevs[count]->audioread_overlap);
2031 		fputs(tmp,fd);
2032 		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_SECTORBURST = %d\n",writerreaderdevs[count]->audioread_sectorburst);
2033 		fputs(tmp,fd);
2034 		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_USEPARANOIA = %d\n",writerreaderdevs[count]->audioread_useparanoia);
2035 		fputs(tmp,fd);
2036 		g_snprintf(tmp,MAXLINE,"WRITERREADER_AUDIOREAD_PARANOIARETRIES = %d\n",writerreaderdevs[count]->audioread_paranoiaretries);
2037 		fputs(tmp,fd);
2038 
2039 
2040 		fputs("#\n",fd);
2041 		count++;
2042 	}
2043 
2044 	loop = g_list_first(setupdata.image_dirs);
2045 	while(loop) {
2046 		strcpy(tmp2,(gchar *)loop->data);
2047 		g_snprintf(tmp,MAXLINE,"IMAGE_DIRS = \"%s\"\n",convert_escape(tmp2));
2048 		fputs(tmp,fd);
2049 		loop = loop->next;
2050 	}
2051 
2052 	strcpy(tmp2,setupdata.dsp_device);
2053 	g_snprintf(tmp,MAXLINE,"DSP_DEVICE = \"%s\"\n",convert_escape(tmp2));
2054 	fputs(tmp,fd);
2055 	strcpy(tmp2,setupdata.mix_device);
2056 	g_snprintf(tmp,MAXLINE,"MIX_DEVICE = \"%s\"\n",convert_escape(tmp2));
2057 	fputs(tmp,fd);
2058 	g_snprintf(tmp,MAXLINE,"NOTIFY_VIA = %d\n",setupdata.notify_via);
2059 	fputs(tmp,fd);
2060 	g_snprintf(tmp,MAXLINE,"NOTIFY_AT = %d\n",setupdata.notify_at);
2061 	fputs(tmp,fd);
2062 
2063 	strcpy(tmp2,setupdata.cddb_host);
2064 	g_snprintf(tmp,MAXLINE,"CDDB_HOST = \"%s\"\n",convert_escape(tmp2));
2065 	fputs(tmp,fd);
2066 	g_snprintf(tmp,MAXLINE,"CDDB_PORT = %d\n",setupdata.cddb_port);
2067 	fputs(tmp,fd);
2068 	strcpy(tmp2,setupdata.cddb_proxy_host);
2069 	g_snprintf(tmp,MAXLINE,"CDDB_PROXY_HOST = \"%s\"\n",convert_escape(tmp2));
2070 	fputs(tmp,fd);
2071 	g_snprintf(tmp,MAXLINE,"CDDB_PROXY_PORT = %d\n",setupdata.cddb_proxy_port);
2072 	fputs(tmp,fd);
2073 	g_snprintf(tmp,MAXLINE,"CDDB_USE_HTTP = %d\n",setupdata.cddb_use_http);
2074 	fputs(tmp,fd);
2075 	g_snprintf(tmp,MAXLINE,"CDDB_USE_PROXY = %d\n",setupdata.cddb_use_proxy);
2076 	fputs(tmp,fd);
2077 
2078 	strcpy(tmp2,setupdata.logfile);
2079 	g_snprintf(tmp,MAXLINE,"LOGFILE = \"%s\"\n",convert_escape(tmp2));
2080 	fputs(tmp,fd);
2081 	g_snprintf(tmp,MAXLINE,"LOGLEVEL = %d\n",setupdata.loglevel);
2082 	fputs(tmp,fd);
2083 
2084 	strcpy(tmp2,setupdata.language);
2085 	g_snprintf(tmp,MAXLINE,"LANGUAGE = \"%s\"\n",convert_escape(tmp2));
2086 	fputs(tmp,fd);
2087 
2088 	g_snprintf(tmp,MAXLINE,"OPTION_TOOLTIPS = %d\n",setupdata.option_tooltips);
2089 	fputs(tmp,fd);
2090 	g_snprintf(tmp,MAXLINE,"OPTION_AUTORAISE = %d\n",setupdata.option_autoraise);
2091 	fputs(tmp,fd);
2092 	g_snprintf(tmp,MAXLINE,"OPTION_SAVEPOS = %d\n",setupdata.option_savepos);
2093 	fputs(tmp,fd);
2094 	g_snprintf(tmp,MAXLINE,"OPTION_PERSONIMAGE = %d\n",setupdata.option_personimage);
2095 	fputs(tmp,fd);
2096 	g_snprintf(tmp,MAXLINE,"OPTION_OVERWRITEWARN = %d\n",setupdata.option_overwritewarn);
2097 	fputs(tmp,fd);
2098 	g_snprintf(tmp,MAXLINE,"OPTION_AUTODELETE = %d\n",setupdata.option_autodelete);
2099 	fputs(tmp,fd);
2100 	g_snprintf(tmp,MAXLINE,"OPTION_TITLEPROGRESS = %d\n",setupdata.option_titleprogress);
2101 	fputs(tmp,fd);
2102 	g_snprintf(tmp,MAXLINE,"OPTION_DISPLAYCDTEXT = %d\n",setupdata.option_displaycdtext);
2103 	fputs(tmp,fd);
2104 	g_snprintf(tmp,MAXLINE,"OPTION_SELECTIONMODE = %d\n",setupdata.option_selectionmode);
2105 	fputs(tmp,fd);
2106 
2107 	strcpy(tmp2,setupdata.ProDVDkey);
2108 	g_snprintf(tmp,MAXLINE,"PRODVD_KEY = \"%s\"\n",convert_escape(tmp2));
2109 	fputs(tmp,fd);
2110 
2111 	/* save geometry data? */
2112 	if (setupdata.option_savepos) {
2113 		g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_X = %d\n", setupdata.mainwindow.x);
2114 		fputs(tmp,fd);
2115 		g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_Y = %d\n", setupdata.mainwindow.y);
2116 		fputs(tmp,fd);
2117 		g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_WIDTH = %d\n", setupdata.mainwindow.width);
2118 		fputs(tmp,fd);
2119 		g_snprintf(tmp,MAXLINE,"GEOMETRY_MAINWINDOW_HEIGHT = %d\n", setupdata.mainwindow.height);
2120 		fputs(tmp,fd);
2121 
2122 		g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_X = %d\n", setupdata.burnwindow.x);
2123 		fputs(tmp,fd);
2124 		g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_Y = %d\n", setupdata.burnwindow.y);
2125 		fputs(tmp,fd);
2126 		g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_WIDTH = %d\n", setupdata.burnwindow.width);
2127 		fputs(tmp,fd);
2128 		g_snprintf(tmp,MAXLINE,"GEOMETRY_BURNWINDOW_HEIGHT = %d\n", setupdata.burnwindow.height);
2129 		fputs(tmp,fd);
2130 	}
2131 
2132 	/* do save the following information only when root */
2133 	if (isroot()) {
2134 
2135 		g_snprintf(tmp,MAXLINE,"ROOT_USERS_ACCESS = %d\n",setupdata.root_users_access);
2136 		fputs(tmp,fd);
2137 
2138 		loop = g_list_first(setupdata.root_users_lists);
2139 		while(loop) {
2140 			strcpy(tmp2,(gchar *)loop->data);
2141 			g_snprintf(tmp,MAXLINE,"ROOT_USERS_LISTS = \"%s\"\n",convert_escape(tmp2));
2142 			fputs(tmp,fd);
2143 			loop = loop->next;
2144 		}
2145 
2146 		g_snprintf(tmp,MAXLINE,"ROOT_HOSTS_ACCESS = %d\n",setupdata.root_hosts_access);
2147 		fputs(tmp,fd);
2148 
2149 		loop = g_list_first(setupdata.root_hosts_lists);
2150 		while(loop) {
2151 			strcpy(tmp2,(gchar *)loop->data);
2152 			g_snprintf(tmp,MAXLINE,"ROOT_HOSTS_LISTS = \"%s\"\n",convert_escape(tmp2));
2153 			fputs(tmp,fd);
2154 			loop = loop->next;
2155 		}
2156 
2157 		g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_WRITER = %d\n",setupdata.root_option_change_writer);
2158 		fputs(tmp,fd);
2159 		g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_WRITEPARAM = %d\n",setupdata.root_option_change_writeparam);
2160 		fputs(tmp,fd);
2161 		g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_READER = %d\n",setupdata.root_option_change_reader);
2162 		fputs(tmp,fd);
2163 		g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_READPARAM = %d\n",setupdata.root_option_change_readparam);
2164 		fputs(tmp,fd);
2165 		g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_IMAGEDIRS = %d\n",setupdata.root_option_change_imagedirs);
2166 		fputs(tmp,fd);
2167 		g_snprintf(tmp,MAXLINE,"ROOT_OPTION_CHANGE_LOGOPTIONS = %d\n",setupdata.root_option_change_logoptions);
2168 		fputs(tmp,fd);
2169 	}
2170 
2171 	if (fclose(fd) != 0) {
2172 		/* error closing file */
2173 		return 1;
2174 	}
2175 
2176 	return 0;
2177 }
2178 
2179 
2180 /* Load the setup-configuration
2181    return 0 if ok, or 1 on error */
2182 /* when rootconf is set, load all from file, else only what we are
2183    allow */
2184 
load_setup_config(gchar * fname,gint rootconf)2185 gint load_setup_config(gchar *fname, gint rootconf) {
2186 FILE *fd;
2187 gchar line[MAXLINE];
2188 gchar id[MAXLINE];
2189 gchar value[MAXLINE];
2190 gchar tmp[MAXLINE];
2191 GList *tmp_image_dirs;
2192 gint count, i, newadded;
2193 
2194 	/* allocate memory if required */
2195 	if (!writerreaderdevs) {
2196 		writerreaderdevs = g_new0(writerreader_devices_t *, MAXDEVICES);
2197 	}
2198 
2199 	count = -1;
2200 	newadded = 0;
2201 	tmp_image_dirs = NULL;
2202 
2203 	/* prepare some data */
2204 	if (rootconf) {
2205 		free_glist(&setupdata.image_dirs);
2206 	}
2207 	if (rootconf) {
2208 		free_glist(&setupdata.root_users_lists);
2209 		free_glist(&setupdata.root_hosts_lists);
2210 	}
2211 
2212 	dodebug(1, "Opening config file %s for reading\n", fname);
2213 	dolog(3, "Loading config file %s\n", fname);
2214 
2215 	if ((fd = fopen(fname,"r")) == NULL) {
2216 		/* error opening file */
2217 		return 1;
2218 	}
2219 
2220 	for (;;) {
2221 		if (fgets(line,MAXLINE,fd) == NULL)
2222 			break;
2223 
2224 		/* special case here to protect pro-dvd-key */
2225 		if (strstr(line, "PRODVD_KEY") && strlen(line) > 50) {
2226 			strncpy(tmp,line,50);
2227 			tmp[50] = '\0';
2228 			dodebug(10,"config: %s...\n", tmp);
2229 		} else {
2230 			dodebug(10,"config: %s", line);
2231 		}
2232 
2233 		/* skip empty or hashed lines */
2234 		strip_string(line);
2235 		if (*line == '#' || *line == '\0')
2236 			continue;
2237 
2238                 /* parse lines */
2239 		if (parse_config_line(line,id,value)) {
2240                 	g_error("syntax error in config-file\n");
2241 		}
2242 
2243 		if (strcmp("VERSION",id) == 0) {
2244 			strcpy(xcdroast_version_loaded,value);
2245 		}
2246 		if (strcmp("PLATFORM",id) == 0) {
2247 			;
2248 		}
2249 
2250 		if (rootconf || setupdata.root_option_change_writer) {
2251 			if (strcmp("WRITER_DEVNR",id) == 0) {
2252 				setupdata.writer_devnr = atoi(value);
2253 			}
2254 		}
2255 		if (rootconf || setupdata.root_option_change_reader) {
2256 			if (strcmp("READER_DEVNR",id) == 0) {
2257 				setupdata.reader_devnr = atoi(value);
2258 			}
2259 		}
2260 
2261 		/* marker for a new device - must be first entry! */
2262 		if (strcmp("WRITERREADER_DEVNR",id) == 0) {
2263 			i = get_writerreaderdevs_index(atoi(value));
2264 
2265 			if (i == -1) {
2266 				/* new device */
2267 				if (rootconf || (setupdata.root_option_change_writer &&
2268                 			setupdata.root_option_change_reader)) {
2269 
2270 						count = get_last_writerreaderdevs_index() +1;
2271 						writerreaderdevs[count]=g_new0(writerreader_devices_t,1);
2272 						writerreaderdevs[count]->devnr = atoi(value);
2273 						newadded = 1;
2274 				} else {
2275 					/* no permission to add a new device */
2276 					/* ignore */
2277 					count = -1;
2278 					newadded = 0;
2279 				}
2280 			} else {
2281 				/* we seen such a device already */
2282 				count = i;
2283 				newadded = 0;
2284 			}
2285 		}
2286 
2287 		/* only load such data for newly allocated devices */
2288 		if (newadded) {
2289 
2290 			if (strcmp("WRITERREADER_DEVICESTR",id) == 0) {
2291 				if (count >= 0 && writerreaderdevs[count]) {
2292 					writerreaderdevs[count]->devicestr = g_strdup(value);
2293 				}
2294 			}
2295 			if (strcmp("WRITERREADER_VENDOR",id) == 0) {
2296 				if (count >= 0 && writerreaderdevs[count]) {
2297 					strncpy(writerreaderdevs[count]->vendor, value, 9);
2298 				}
2299 			}
2300 			if (strcmp("WRITERREADER_MODEL",id) == 0) {
2301 				if (count >= 0 && writerreaderdevs[count]) {
2302 					strncpy(writerreaderdevs[count]->model, value, 17);
2303 				}
2304 			}
2305 			if (strcmp("WRITERREADER_REV",id) == 0) {
2306 				if (count >= 0 && writerreaderdevs[count]) {
2307 					strncpy(writerreaderdevs[count]->rev, value, 5);
2308 				}
2309 			}
2310 			if (strcmp("WRITERREADER_READMAXSPEED",id) == 0) {
2311 				if (count >= 0 && writerreaderdevs[count]) {
2312 					writerreaderdevs[count]->writer_readmaxspeed = atoi(value);
2313 				}
2314 			}
2315 			if (strcmp("WRITERREADER_CDRMAXSPEED",id) == 0) {
2316 				if (count >= 0 && writerreaderdevs[count]) {
2317 					writerreaderdevs[count]->writer_cdrmaxspeed = atoi(value);
2318 				}
2319 			}
2320 			if (strcmp("WRITERREADER_DVDMAXSPEED",id) == 0) {
2321 				if (count >= 0 && writerreaderdevs[count]) {
2322 					writerreaderdevs[count]->writer_dvdmaxspeed = atoi(value);
2323 				}
2324 			}
2325 			if (strcmp("WRITERREADER_WRITER_FLAGS",id) == 0) {
2326 				if (count >= 0 && writerreaderdevs[count]) {
2327 					writerreaderdevs[count]->writer_flags = g_strdup(value);
2328 				}
2329 			}
2330 			if (strcmp("WRITERREADER_WRITER_MODES",id) == 0) {
2331 				if (count >= 0 && writerreaderdevs[count]) {
2332 					writerreaderdevs[count]->writer_modes = g_strdup(value);
2333 				}
2334 			}
2335 			if (strcmp("WRITERREADER_IS_CDRWRITER",id) == 0) {
2336 				if (count >= 0 && writerreaderdevs[count]) {
2337 					writerreaderdevs[count]->is_cdrwriter = atoi(value);
2338 				}
2339 			}
2340 			if (strcmp("WRITERREADER_IS_DVDREADER",id) == 0) {
2341 				if (count >= 0 && writerreaderdevs[count]) {
2342 					writerreaderdevs[count]->is_dvdreader = atoi(value);
2343 				}
2344 			}
2345 			if (strcmp("WRITERREADER_IS_DVDWRITER",id) == 0) {
2346 				if (count >= 0 && writerreaderdevs[count]) {
2347 					writerreaderdevs[count]->is_dvdwriter = atoi(value);
2348 				}
2349 			}
2350 			if (strcmp("WRITERREADER_SECTOR_SIZE",id) == 0) {
2351 				if (count >= 0 && writerreaderdevs[count]) {
2352 					writerreaderdevs[count]->sector_size = atoi(value);
2353 				}
2354 			}
2355 		}
2356 
2357 		if (rootconf || newadded || setupdata.root_option_change_writeparam) {
2358 
2359 			if (strcmp("WRITERREADER_DRVMODE",id) == 0) {
2360 				if (count >= 0 && writerreaderdevs[count]) {
2361 					writerreaderdevs[count]->writer_drvmode = atoi(value);
2362 				}
2363 			}
2364 			if (strcmp("WRITERREADER_MODE",id) == 0) {
2365 				if (count >= 0 && writerreaderdevs[count]) {
2366 					writerreaderdevs[count]->writer_mode = atoi(value);
2367 				}
2368 			}
2369 			if (strcmp("WRITERREADER_SPEED",id) == 0) {
2370 				if (count >= 0 && writerreaderdevs[count]) {
2371 					writerreaderdevs[count]->writer_speed = atoi(value);
2372 				}
2373 			}
2374 			if (strcmp("WRITERREADER_FIFO",id) == 0) {
2375 				if (count >= 0 && writerreaderdevs[count]) {
2376 					writerreaderdevs[count]->writer_fifo = atoi(value);
2377 				}
2378 			}
2379 		}
2380 
2381 		if (rootconf || newadded || setupdata.root_option_change_readparam) {
2382 
2383 			if (strcmp("WRITERREADER_AUDIOREAD_INTERFACE",id) == 0) {
2384 				if (count >= 0 && writerreaderdevs[count]) {
2385 					writerreaderdevs[count]->audioread_interface = atoi(value);
2386 				}
2387 			}
2388 			if (strcmp("WRITERREADER_AUDIOREAD_SPEED",id) == 0) {
2389 				if (count >= 0 && writerreaderdevs[count]) {
2390 					writerreaderdevs[count]->audioread_speed = atoi(value);
2391 				}
2392 			}
2393 			if (strcmp("WRITERREADER_AUDIOREAD_OVERLAP",id) == 0) {
2394 				if (count >= 0 && writerreaderdevs[count]) {
2395 					writerreaderdevs[count]->audioread_overlap = atoi(value);
2396 				}
2397 			}
2398 			if (strcmp("WRITERREADER_AUDIOREAD_SECTORBURST",id) == 0) {
2399 				if (count >= 0 && writerreaderdevs[count]) {
2400 					writerreaderdevs[count]->audioread_sectorburst = atoi(value);
2401 				}
2402 			}
2403 			if (strcmp("WRITERREADER_AUDIOREAD_USEPARANOIA",id) == 0) {
2404 				if (count >= 0 && writerreaderdevs[count]) {
2405 					writerreaderdevs[count]->audioread_useparanoia = atoi(value);
2406 				}
2407 			}
2408 			if (strcmp("WRITERREADER_AUDIOREAD_PARANOIARETRIES",id) == 0) {
2409 				if (count >= 0 && writerreaderdevs[count]) {
2410 					writerreaderdevs[count]->audioread_paranoiaretries = atoi(value);
2411 				}
2412 			}
2413 		}
2414 
2415 		if (rootconf) {
2416 			if (strcmp("IMAGE_DIRS",id) == 0) {
2417 				setupdata.image_dirs = g_list_append(setupdata.image_dirs, g_strdup(value));
2418 			}
2419 		} else {
2420 			/* user config - load to tmp list */
2421 			if (strcmp("IMAGE_DIRS",id) == 0) {
2422 				tmp_image_dirs = g_list_append(tmp_image_dirs, g_strdup(value));
2423 			}
2424 		}
2425 		if (strcmp("DSP_DEVICE",id) == 0) {
2426 			g_free(setupdata.dsp_device);
2427 			setupdata.dsp_device = g_strdup(value);
2428 		}
2429 		if (strcmp("MIX_DEVICE",id) == 0) {
2430 			g_free(setupdata.mix_device);
2431 			setupdata.mix_device = g_strdup(value);
2432 		}
2433 		if (strcmp("NOTIFY_VIA",id) == 0) {
2434 			setupdata.notify_via = atoi(value);
2435 		}
2436 		if (strcmp("NOTIFY_AT",id) == 0) {
2437 			setupdata.notify_at = atoi(value);
2438 		}
2439 
2440 		if (strcmp("CDDB_HOST",id) == 0) {
2441 			g_free(setupdata.cddb_host);
2442 			setupdata.cddb_host = g_strdup(value);
2443 		}
2444 		if (strcmp("CDDB_PORT",id) == 0) {
2445 			setupdata.cddb_port = atoi(value);
2446 		}
2447 		if (strcmp("CDDB_PROXY_HOST",id) == 0) {
2448 			g_free(setupdata.cddb_proxy_host);
2449 			setupdata.cddb_proxy_host = g_strdup(value);
2450 		}
2451 		if (strcmp("CDDB_PROXY_PORT",id) == 0) {
2452 			setupdata.cddb_proxy_port = atoi(value);
2453 		}
2454 		if (strcmp("CDDB_USE_HTTP",id) == 0) {
2455 			setupdata.cddb_use_http = atoi(value);
2456 		}
2457 		if (strcmp("CDDB_USE_PROXY",id) == 0) {
2458 			setupdata.cddb_use_proxy = atoi(value);
2459 		}
2460 
2461 		if (rootconf || setupdata.root_option_change_logoptions) {
2462 			if (strcmp("LOGFILE",id) == 0) {
2463 				g_free(setupdata.logfile);
2464 				setupdata.logfile = g_strdup(value);
2465 			}
2466 			if (strcmp("LOGLEVEL",id) == 0) {
2467 				setupdata.loglevel = atoi(value);
2468 			}
2469 		}
2470 
2471 		if (strcmp("LANGUAGE",id) == 0) {
2472 			g_free(setupdata.language);
2473 			setupdata.language = g_strdup(value);
2474 
2475 			/* check if that value is an integer */
2476 			if (atoi(value) != 0 || strcmp(value,"0") == 0) {
2477 				/* it is, so set empty language */
2478 				/* (we want to be backward compatible) */
2479 				g_free(setupdata.language);
2480 				setupdata.language = g_strdup("");
2481 			}
2482 		}
2483 
2484 		if (strcmp("OPTION_TOOLTIPS",id) == 0) {
2485 			setupdata.option_tooltips = atoi(value);
2486 		}
2487 		if (strcmp("OPTION_AUTORAISE",id) == 0) {
2488 			setupdata.option_autoraise = atoi(value);
2489 		}
2490 		if (strcmp("OPTION_SAVEPOS",id) == 0) {
2491 			setupdata.option_savepos = atoi(value);
2492 		}
2493 		if (strcmp("OPTION_PERSONIMAGE",id) == 0) {
2494 			setupdata.option_personimage = atoi(value);
2495 		}
2496 		if (strcmp("OPTION_OVERWRITEWARN",id) == 0) {
2497 			setupdata.option_overwritewarn = atoi(value);
2498 		}
2499 		if (strcmp("OPTION_AUTODELETE",id) == 0) {
2500 			setupdata.option_autodelete = atoi(value);
2501 		}
2502 		if (strcmp("OPTION_TITLEPROGRESS",id) == 0) {
2503 			setupdata.option_titleprogress = atoi(value);
2504 		}
2505 		if (strcmp("OPTION_DISPLAYCDTEXT",id) == 0) {
2506 			setupdata.option_displaycdtext = atoi(value);
2507 		}
2508 		if (strcmp("OPTION_SELECTIONMODE",id) == 0) {
2509 			setupdata.option_selectionmode = atoi(value);
2510 		}
2511 		if (strcmp("PRODVD_KEY",id) == 0) {
2512 			/* dont overwrite evtuelly set value with empty key */
2513 			if (strcmp(value,"") != 0) {
2514 				g_free(setupdata.ProDVDkey);
2515 				setupdata.ProDVDkey = g_strdup(value);
2516 			}
2517 		}
2518 		if (setupdata.option_savepos) {
2519 			if (strcmp("GEOMETRY_MAINWINDOW_X",id) == 0) {
2520 				setupdata.mainwindow.x = atoi(value);
2521 			}
2522 			if (strcmp("GEOMETRY_MAINWINDOW_Y",id) == 0) {
2523 				setupdata.mainwindow.y = atoi(value);
2524 			}
2525 			if (strcmp("GEOMETRY_MAINWINDOW_WIDTH",id) == 0) {
2526 				setupdata.mainwindow.width = atoi(value);
2527 			}
2528 			if (strcmp("GEOMETRY_MAINWINDOW_HEIGHT",id) == 0) {
2529 				setupdata.mainwindow.height = atoi(value);
2530 			}
2531 
2532 			if (strcmp("GEOMETRY_BURNWINDOW_X",id) == 0) {
2533 				setupdata.burnwindow.x = atoi(value);
2534 			}
2535 			if (strcmp("GEOMETRY_BURNWINDOW_Y",id) == 0) {
2536 				setupdata.burnwindow.y = atoi(value);
2537 			}
2538 			if (strcmp("GEOMETRY_BURNWINDOW_WIDTH",id) == 0) {
2539 				setupdata.burnwindow.width = atoi(value);
2540 			}
2541 			if (strcmp("GEOMETRY_BURNWINDOW_HEIGHT",id) == 0) {
2542 				setupdata.burnwindow.height = atoi(value);
2543 			}
2544 		}
2545 
2546 		/* do load the following information only when root */
2547 		if (rootconf) {
2548 			if (strcmp("ROOT_USERS_ACCESS",id) == 0) {
2549 				setupdata.root_users_access = atoi(value);
2550 			}
2551 			if (strcmp("ROOT_USERS_LISTS",id) == 0) {
2552 				setupdata.root_users_lists = g_list_append(setupdata.root_users_lists, g_strdup(value));
2553 			}
2554 			if (strcmp("ROOT_HOSTS_ACCESS",id) == 0) {
2555 				setupdata.root_hosts_access = atoi(value);
2556 			}
2557 			if (strcmp("ROOT_HOSTS_LISTS",id) == 0) {
2558 				setupdata.root_hosts_lists = g_list_append(setupdata.root_hosts_lists, g_strdup(value));
2559 			}
2560 
2561 			if (strcmp("ROOT_OPTION_CHANGE_WRITER",id) == 0) {
2562 				setupdata.root_option_change_writer = atoi(value);
2563 			}
2564 			if (strcmp("ROOT_OPTION_CHANGE_WRITEPARAM",id) == 0) {
2565 				setupdata.root_option_change_writeparam = atoi(value);
2566 			}
2567 			if (strcmp("ROOT_OPTION_CHANGE_READER",id) == 0) {
2568 				setupdata.root_option_change_reader = atoi(value);
2569 			}
2570 			if (strcmp("ROOT_OPTION_CHANGE_READPARAM",id) == 0) {
2571 				setupdata.root_option_change_readparam = atoi(value);
2572 			}
2573 			if (strcmp("ROOT_OPTION_CHANGE_IMAGEDIRS",id) == 0) {
2574 				setupdata.root_option_change_imagedirs = atoi(value);
2575 			}
2576 			if (strcmp("ROOT_OPTION_CHANGE_LOGOPTIONS",id) == 0) {
2577 				setupdata.root_option_change_logoptions = atoi(value);
2578 			}
2579 		}
2580 	}
2581 	/* now handle image dirs */
2582 	if (!rootconf) {
2583 		/* are we allowed to change image dirs? */
2584 		if (setupdata.root_option_change_imagedirs) {
2585 			/* had we configured some yet? */
2586 			if (g_list_length(tmp_image_dirs) > 0) {
2587 				/* use user one */
2588 				copy_glist(&setupdata.image_dirs,
2589 					tmp_image_dirs);
2590 			}
2591 		}
2592 	}
2593 
2594 	/* free temporary list */
2595 	free_glist(&tmp_image_dirs);
2596 
2597 	if (fclose(fd) != 0) {
2598 		/* error closing file */
2599 		return 1;
2600 	}
2601 
2602 	return 0;
2603 }
2604 
2605 
2606 /* parse a detailed toc line */
2607 
parse_toc_line(gchar * line)2608 static void parse_toc_line(gchar *line) {
2609 gchar tmp[MAXLINE];
2610 gchar tmp2[MAXLINE];
2611 gchar tmp3[MAXLINE];
2612 gchar old_cddb_title[MAXLINE];
2613 gchar old_cdtext_title[MAXLINE];
2614 gchar old_cdtext_artist[MAXLINE];
2615 gchar *p1;
2616 gint min,sec,frm;
2617 gint ret;
2618 
2619 	/* to much tracks? */
2620 	if (tocnr >= MAXTRACKS) {
2621 		g_error("over %d tracks in toc\n",MAXTRACKS);
2622 	}
2623 
2624 	strcpy(old_cddb_title,"");
2625 	strcpy(old_cdtext_title,"");
2626 	strcpy(old_cdtext_artist,"");
2627 
2628 	/* allocate memory for new line (free first old memory)*/
2629 	if (trackinfo[tocnr] != NULL) {
2630 		g_free(trackinfo[tocnr]->volname);
2631 
2632 		/* backup old cdtext */
2633 		if (trackinfo[tocnr]->title) {
2634 			strncpy(old_cdtext_title, trackinfo[tocnr]->title, MAXLINE);
2635 		}
2636 		g_free(trackinfo[tocnr]->title);
2637 		/* backup old cdtext */
2638 		if (trackinfo[tocnr]->artist) {
2639 			strncpy(old_cdtext_artist, trackinfo[tocnr]->artist, MAXLINE);
2640 		}
2641 		g_free(trackinfo[tocnr]->artist);
2642 
2643 		/* backup old cddb-title  */
2644 		if (trackinfo[tocnr]->cddb_ttitle != NULL) {
2645 			strncpy(old_cddb_title, trackinfo[tocnr]->cddb_ttitle, MAXLINE);
2646 		}
2647 		g_free(trackinfo[tocnr]->cddb_ttitle);
2648 		g_free(trackinfo[tocnr]);
2649 	}
2650 	trackinfo[tocnr] = g_new0(track_info_t,1);
2651 
2652 	/* when the cd is still the same as last time, restore cddb-title */
2653 	if (cd_is_still_the_same == 1) {
2654 		/* got a backuped title? */
2655 		if (strcmp(old_cddb_title,"") != 0) {
2656 			trackinfo[tocnr]->cddb_ttitle = g_strdup(old_cddb_title);
2657 		}
2658 	}
2659 
2660 	/* now we are prepared to fill structure */
2661 	strcpy(tmp,line+1);
2662 	p1 = strtok(tmp,":");
2663 	if (p1 == NULL) {
2664 		g_error("Unexpected output in cdda2wav toc-output\n");
2665 	}
2666 	trackinfo[tocnr]->track_nr = atoi(p1);
2667 	trackinfo[tocnr]->isosize = -1;
2668 
2669 	/* reststring into tmp2 - strip to remove leading spaces */
2670 	p1 = strtok(NULL,"");
2671 	strcpy(tmp2,p1);
2672 	strip_string(tmp2);
2673 
2674 	p1 = strtok(tmp2," ");
2675 	trackinfo[tocnr]->start_sec = atoi(p1);
2676 
2677 	p1 = strtok(NULL,"");
2678 	if (p1 == NULL) {
2679 		g_error("Unexpected output in cdda2wav toc-output\n");
2680 	}
2681 	strcpy(tmp,p1);
2682 	strip_string(tmp);
2683 
2684 	/* now get tracklength - convert to frames */
2685 	p1 = strtok(tmp," ");
2686 	sscanf(p1,"%d:%d.%d",&min,&sec,&frm);
2687 	trackinfo[tocnr]->size = (min*60+sec)*75 + frm;
2688 
2689 	/* tracktype */
2690 	p1 = strtok(NULL," ");
2691 	if (strncmp(p1,"data",4) == 0) {
2692 		/* data-track */
2693 		trackinfo[tocnr]->type = 0;
2694 
2695 		p1 = strtok(NULL," ");
2696 		if (strncmp(p1,"uninterrupted",13) == 0) {
2697 			trackinfo[tocnr]->rec_type = 1;
2698 		} else {
2699 			trackinfo[tocnr]->rec_type = 0;
2700 		}
2701 
2702 		p1 = strtok(NULL," ");
2703 		if (strncmp(p1,"copydenied",10) == 0) {
2704 			trackinfo[tocnr]->copyperm = 0;
2705 		} else {
2706 			trackinfo[tocnr]->copyperm = 1;
2707 		}
2708 		if (cd_is_still_the_same == 1) {
2709 			/* use cached cd-text */
2710 			trackinfo[tocnr]->title = g_strdup(old_cdtext_title);
2711 			trackinfo[tocnr]->artist = g_strdup(old_cdtext_artist);
2712 		}
2713 	} else {
2714 		/* audio-track */
2715 		trackinfo[tocnr]->type = 1;
2716 
2717 		p1 = strtok(NULL," ");
2718 		if (strncmp(p1,"linear",6) == 0) {
2719 			trackinfo[tocnr]->preemp = 0;
2720 		} else {
2721 			trackinfo[tocnr]->preemp = 1;
2722 		}
2723 
2724 		p1 = strtok(NULL," ");
2725 		if (strncmp(p1,"copydenied",10) == 0) {
2726 			trackinfo[tocnr]->copyperm = 0;
2727 		} else {
2728 			trackinfo[tocnr]->copyperm = 1;
2729 		}
2730 
2731 		p1 = strtok(NULL," ");
2732 		if (strncmp(p1,"stereo",6) == 0) {
2733 			trackinfo[tocnr]->stereo = 1;
2734 		} else {
2735 			trackinfo[tocnr]->stereo = 0;
2736 		}
2737 
2738 		p1 = strtok(NULL," ");
2739 		p1 = strtok(NULL,"");
2740 		if (p1) {
2741 			strcpy(tmp2,p1);
2742 			strip_string(tmp2);
2743 			ret = decode_title_artist(tmp2,tmp,tmp3);
2744 			if (ret != 0) {
2745 				g_error("got unexpected artist/title\n");
2746 			}
2747 
2748 			if (cd_is_still_the_same == 1) {
2749 				if (tmp[0] == '\0') {
2750 					/* no new data, use cached */
2751 					trackinfo[tocnr]->title = g_strdup(old_cdtext_title);
2752 				}  else {
2753 					trackinfo[tocnr]->title = g_strdup(tmp);
2754 				}
2755 				if (tmp3[0] == '\0') {
2756 					/* no new data, use cached */
2757 					trackinfo[tocnr]->artist = g_strdup(old_cdtext_artist);
2758 				} else {
2759 					trackinfo[tocnr]->artist = g_strdup(tmp3);
2760 				}
2761 			} else {
2762 				trackinfo[tocnr]->title = g_strdup(tmp);
2763 				trackinfo[tocnr]->artist = g_strdup(tmp3);
2764 			}
2765 		} else {
2766 			trackinfo[tocnr]->title = g_strdup("");
2767 			trackinfo[tocnr]->artist = g_strdup("");
2768 		}
2769 	}
2770 
2771 
2772 	tocnr++;
2773 }
2774 
2775 
2776 /* print memory-structure with toc-data (debug purposes) */
2777 
print_cdinfo()2778 static void print_cdinfo() {
2779 gint i;
2780 gchar *p1, *p2, *p3, *p4;
2781 gchar tmp[] = "(NULL)";
2782 
2783 	dodebug(2,"------ cdinfo-structure -----\n");
2784 	dodebug(2,"nr_tracks: %d\n",cdinfo.nr_tracks);
2785 	dodebug(2,"total_size: %d\n",cdinfo.total_size);
2786 	dodebug(2,"cddb_discid: %s\n",cdinfo.cddb_discid);
2787 	dodebug(2,"have_cdtext: %d, have_cdextra: %d\n",cdinfo.have_cdtext,
2788 		 cdinfo.have_cdextra);
2789 	if (cdinfo.title != NULL && cdinfo.artist != NULL) {
2790 		dodebug(2,"title/artist: %s/%s\n",cdinfo.title,cdinfo.artist);
2791 	} else {
2792 		dodebug(2,"title/artist: (NULL)/(NULL)\n");
2793 	}
2794 	if (cdinfo.cddb_dtitle != NULL) {
2795 		dodebug(2,"cddb_dtitle: %s\n",cdinfo.cddb_dtitle);
2796 	} else {
2797 		dodebug(2,"cddb_dtitle: (NULL)\n");
2798 	}
2799 	dodebug(2,"leadout: %d\n", cdinfo.leadout);
2800 
2801 	for (i = 0; i < cdinfo.nr_tracks; i++) {
2802 
2803 		dodebug(2,"track: %d start: %d size: %d\n",trackinfo[i]->track_nr,
2804 			trackinfo[i]->start_sec, trackinfo[i]->size);
2805 		dodebug(2,"       type: %d, rec_type: %d, preemp: %d, copyperm: %d, stereo: %d\n",
2806 			trackinfo[i]->type, trackinfo[i]->rec_type,
2807 			trackinfo[i]->preemp, trackinfo[i]->copyperm,
2808 			trackinfo[i]->stereo);
2809 		/* check if we have any null-pointers lying around */
2810 		p1 = trackinfo[i]->title;
2811 		p2 = trackinfo[i]->artist;
2812 		p3 = trackinfo[i]->cddb_ttitle;
2813 		p4 = trackinfo[i]->volname;
2814 		if (p1 == NULL) p1 = tmp;
2815 		if (p2 == NULL) p2 = tmp;
2816 		if (p3 == NULL) p3 = tmp;
2817 		if (p4 == NULL) p4 = tmp;
2818 
2819 		dodebug(2,"       title/artist: %s/%s cddb_title: %s volname: %s\n",
2820 			p1, p2, p3, p4);
2821 	}
2822 }
2823 
2824 
2825 /* interpret line for line the output of cdda2wav */
2826 
parse_toc(gchar * line)2827 static gint parse_toc(gchar *line) {
2828 gchar tmp[MAXLINE];
2829 gchar tmp2[MAXLINE];
2830 gchar tmp3[MAXLINE];
2831 gchar *p,*p1;
2832 gint min,sec,frm;
2833 gint ret;
2834 gint mmaperror;
2835 
2836 	mmaperror = 0;
2837 
2838 	/* initial state */
2839 	if (tocstate == 0) {
2840 		/* mmap error? */
2841 		if (strstr(line,"annot get mmap for")) {
2842 			mmaperror = 1;
2843 		}
2844 
2845 		/* first look for "Tracks" line */
2846 		if (strncmp(line,"Tracks:",7) == 0) {
2847 			strcpy(tmp,line+7);
2848 			p1 = strtok(tmp," ");
2849 			strcpy(tmp2,p1);
2850 			cdinfo.nr_tracks = atoi(tmp2);
2851 			p1 = strtok(NULL,"");
2852 			strcpy(tmp2,p1);
2853 			sscanf(tmp2,"%d:%d.%d",&min,&sec,&frm);
2854 			cdinfo.total_size = (min*60+sec)*75 + frm;
2855 		}
2856 		if (strncmp(line,"CDINDEX",7) == 0) {
2857 			/* we dont support cdindex right now */
2858 			;
2859 		}
2860 		if (strncmp(line,"CDDB",4) == 0) {
2861 			strcpy(tmp,line+15);
2862 			strip_string(tmp);
2863 			strcpy(cdinfo.cddb_discid,tmp);
2864 
2865 			/* check if the cd we have in the drive is the same
2866 			   as the last cd we got */
2867 			if (strcmp(cdinfo_cddb_title_bak, cdinfo.cddb_discid) == 0) {
2868 				cd_is_still_the_same = 1;
2869 			}
2870 
2871 			/* finished with state 0 */
2872 			tocstate = 1;
2873 		}
2874 
2875 		/* get next line from output */
2876 		return mmaperror;
2877 	}
2878 
2879 	/* cd-text state */
2880 	if (tocstate == 1) {
2881 		if (strncmp(line,"CD-Text: detected",17) == 0) {
2882 			cdinfo.have_cdtext = 1;
2883 		}
2884 		if (strncmp(line,"CD-Text: not detected",21) == 0) {
2885 			cdinfo.have_cdtext = 0;
2886 		}
2887 
2888 		/* ignore any cd-text-output for now */
2889 		;
2890 
2891 		if (strncmp(line,"CD-Extra: ",10) == 0) {
2892 			/* see this as endmarker of cd-text section */
2893 			tocstate = 2;
2894 		}
2895 
2896 		/* dont return here because we may need the current line */
2897 	}
2898 
2899 	/* cd-extra state */
2900 	if (tocstate == 2) {
2901 		if (strncmp(line,"CD-Extra: detected",18) == 0) {
2902 			cdinfo.have_cdextra = 1;
2903 		}
2904 		if (strncmp(line,"CD-Extra: not detected",22) == 0) {
2905 			cdinfo.have_cdextra = 0;
2906 		}
2907 
2908 		/* ignore any cd-extra-output for now */
2909 		;
2910 
2911 		if (strstr(line,"Album title:") != NULL) {
2912 			/* see this as endmarker of cd-extra section */
2913 			tocstate = 3;
2914 		}
2915 		/* dont return here because we may need the current line */
2916 	}
2917 
2918 	/* toc-listing mode */
2919 	if (tocstate == 3) {
2920 		if ((p = strstr(line,"Album title:")) != NULL) {
2921 			strcpy(tmp,p+13);
2922 			strip_string(tmp);
2923 			ret = decode_title_artist(tmp,tmp2,tmp3);
2924 			if (ret != 0) {
2925 				g_error("got unexpected artist/title\n");
2926 			}
2927 			g_free(cdinfo.title);
2928 			cdinfo.title = g_strdup(tmp2);
2929 			g_free(cdinfo.artist);
2930 			cdinfo.artist = g_strdup(tmp3);
2931 		}
2932 
2933 		/* now the most complex part: the toc-list itself */
2934 		if (line[0] == 'T' && line[3] == ':') {
2935 			parse_toc_line(line);
2936 		}
2937 
2938 		if (strncmp(line,"Leadout:",8) == 0) {
2939 			strcpy(tmp,line+8);
2940 			strip_string(tmp);
2941 			cdinfo.leadout = atoi(tmp);
2942 		}
2943 	}
2944 
2945 	return 0;
2946 }
2947 
2948 
2949 /* called when reading the TOC of ATAPI cdroms takes to long */
2950 
getcdtoc_atapi_timeout_func(gpointer data)2951 static gint getcdtoc_atapi_timeout_func(gpointer data) {
2952 
2953 	getcdtoc_atapi_timeout_dialog = show_dialog_wait(ICO_INFO,
2954 		_("Checking drive for a medium.\n\nUsing scsi-emulation for that drive would speed up\nthis considerably. Please note that inserting a\nmedium would also reduce the wait time."));
2955 
2956 	return (FALSE);
2957 }
2958 
2959 
getcdtoc_out(gpointer data,gint source,GdkInputCondition cond)2960 static void getcdtoc_out(gpointer data, gint source, GdkInputCondition cond) {
2961 gint n;
2962 gint ret;
2963 gchar line[MAXLINE];
2964 
2965 
2966         /* read output of getcdtoc */
2967         n = read_line_wait(source, line, MAXLINE);
2968 
2969         /* getcdtoc finished */
2970         if (n <= 0) {
2971                 gtk_input_remove(readcdda_callback);
2972 
2973                 /* pick up return status of child */
2974                 wait(&ret);
2975 
2976                 /* tell our caller that we are done here */
2977                 read_done = WEXITSTATUS(ret);
2978 
2979                 return;
2980         }
2981 
2982 	dodebug(10,"readtoc: %s\n", line);
2983 
2984 	count_mmaperror += parse_toc(line);
2985 }
2986 
2987 
2988 /* call cdda2wav -J to get the cd-toc */
2989 /* add ATAPI long-delay warning window */
2990 
get_cd_toc(gint devnr)2991 void get_cd_toc(gint devnr) {
2992 gchar line[MAXLINE];
2993 gchar tmp[MAXLINE];
2994 gchar tmp2[MAXLINE];
2995 gint ret, dvdsize, read_out;
2996 gchar old_cdtext_title[MAXLINE];
2997 gchar old_cdtext_artist[MAXLINE];
2998 gint getcdtoc_timeout;
2999 
3000 	/* get bus,id,lun string */
3001 	if (convert_devnr2busid(devnr,tmp) != 0) {
3002 		g_error("non existing cdrom?");
3003 	}
3004 
3005 	getcdtoc_atapi_timeout_dialog = NULL;
3006 	getcdtoc_timeout = 0;
3007 
3008 	/* ATAPI device? (only on linux) */
3009 	if (strstr(tmp, "ATAPI")) {
3010 		/* if it does take longer than 5 seconds, display warning */
3011 		getcdtoc_timeout = gtk_timeout_add(5000,
3012 			getcdtoc_atapi_timeout_func, NULL);
3013 	}
3014 
3015 	/* check if cd is loaded */
3016 	if (!check_medium_loaded(devnr)) {
3017 		/* not loaded */
3018 		cdinfo.nr_tracks = -1;
3019 
3020 		if (getcdtoc_timeout) {
3021 			/* remove timeout, if it did not kick in yet */
3022 			gtk_timeout_remove(getcdtoc_timeout);
3023 		}
3024 		if (getcdtoc_atapi_timeout_dialog) {
3025 			/* and remove the dialog wait window */
3026 			show_dialog_wait_remove(getcdtoc_atapi_timeout_dialog);
3027 		}
3028 
3029 		return;
3030 	}
3031 
3032 	cdinfo.have_cdtext = -1;
3033 	cdinfo.have_cdextra = -1;
3034 	cdinfo.nr_tracks = -1;
3035 
3036 	read_done = 999;
3037 	tocstate = 0;
3038 	tocnr = 0;
3039 	cd_is_still_the_same = 0;
3040 	count_mmaperror = 0;
3041 
3042 
3043 	/* backup cddb-value to check if the new cd is the same as
3044 	   the last we read */
3045 	strncpy(cdinfo_cddb_title_bak, cdinfo.cddb_discid, MAXLINE);
3046 
3047 	/* backup current cd-text album info */
3048 	if (cdinfo.title) {
3049 		strncpy(old_cdtext_title, cdinfo.title, MAXLINE);
3050 	} else {
3051 		strcpy(old_cdtext_title, "");
3052 	}
3053 	if (cdinfo.artist) {
3054 		strncpy(old_cdtext_artist, cdinfo.artist, MAXLINE);
3055 	} else {
3056 		strcpy(old_cdtext_artist, "");
3057 	}
3058 
3059 	/* build command line */
3060 	get_wrap_path("CDDA2WAV",tmp2);
3061 	g_snprintf(line,MAXLINE,"%s -D \"%s\" -J -g -Q -H -v toc,summary,sectors,titles", tmp2,tmp);
3062 
3063 	dodebug(1,"spawning: %s\n", line);
3064 
3065         readcdda_pid = full_dpl_pipe3(NULL,NULL,&read_out,line,0);
3066         readcdda_pid2 = -1;
3067 
3068 	fcntl(read_out, F_SETFL, O_NONBLOCK);
3069 
3070         readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
3071                 (GdkInputFunction) getcdtoc_out, NULL);
3072 
3073         /* now wait until toc is read */
3074         while (read_done == 999) {
3075                 wait_and_process_events();
3076         }
3077 
3078         close(read_out);
3079 
3080 	ret = read_done;
3081 
3082 	/* error while reading tracks? */
3083 	if (ret != 0 && cdinfo.nr_tracks != tocnr) {
3084 		cdinfo.nr_tracks = -2;
3085 	}
3086 
3087 	/* cd loaded but not readable = empty recordable? */
3088 	if (ret != 0 && cdinfo.nr_tracks < 1 ) {
3089 		cdinfo.nr_tracks = -2;
3090 	}
3091 
3092 	/* if cd changed, clear out cddb_dtitle */
3093 	if (cd_is_still_the_same == 0) {
3094 		g_free(cdinfo.cddb_dtitle);
3095 		cdinfo.cddb_dtitle = NULL;
3096 	} else {
3097 		/* cd stayed the same, restore album cd-text */
3098 		if (cdinfo.title[0] == '\0' && old_cdtext_title[0] != '\0') {
3099 			g_free(cdinfo.title);
3100 			cdinfo.title = g_strdup(old_cdtext_title);
3101 		}
3102 		if (cdinfo.artist[0] == '\0' && old_cdtext_artist[0] != '\0') {
3103 			g_free(cdinfo.artist);
3104 			cdinfo.artist = g_strdup(old_cdtext_artist);
3105 		}
3106 	}
3107 
3108 	/* now a workaround for a broken cdda2wav when it comes to
3109 	   read the toc of a DVD - use cdrecord -toc instead */
3110 	if (cdinfo.nr_tracks == 1 && (cdinfo.leadout == 1151850 || cdinfo.leadout == 1151849 || cdinfo.leadout == 449849)) {
3111 		/* this is slow, so only use it in that rare case */
3112 		dvdsize = get_cdrecord_toc(devnr);
3113 		if (dvdsize > 0) {
3114 			/* overwrite faulty values by the real ones */
3115 			cdinfo.leadout = dvdsize;
3116 			trackinfo[0]->size = dvdsize;
3117 
3118 			/* 1152000 is 256:00.00 which is not right */
3119 			/* 449999 is  100:00.00 -1 frame */
3120 /*			if (cdinfo.total_size == 1152000 || cdinfo.total_size == 1151999 || cdinfo.total_size == 449999) {
3121 				cdinfo.total_size = dvdsize + 150;
3122 			} */
3123 			cdinfo.total_size = dvdsize + 150;
3124 		}
3125 	}
3126 
3127 	/* have we hit the mmap error? */
3128 	if (count_mmaperror > 0) {
3129                 ret = show_dialog(ICO_WARN, _("Warning: The cdrtools binaries you have installed are\nnot compatible with your system. You will NOT be\nable to read or write CDs. Please read the FAQ\non www.xcdroast.org for more information."), T_ANYWAY, _("Exit"), NULL, 1);
3130                 if (ret == 1)
3131                         gtk_exit(1);
3132 	}
3133 
3134 	if (getcdtoc_timeout) {
3135 		/* remove timeout, if it did not kick in yet */
3136 		gtk_timeout_remove(getcdtoc_timeout);
3137 	}
3138 	if (getcdtoc_atapi_timeout_dialog) {
3139 		/* and remove the dialog wait window */
3140 		show_dialog_wait_remove(getcdtoc_atapi_timeout_dialog);
3141 	}
3142 
3143 	if (debug) print_cdinfo();
3144 
3145 }
3146 
3147 
3148 /* start subprocess and reroute stdin and stdout */
3149 /* use /bin/sh to spawn subprocess */
3150 
full_dpl_pipe_shell(gint * out,gint * in,gchar * cmd)3151 pid_t full_dpl_pipe_shell(gint *out, gint *in, gchar *cmd) {
3152 gint fd1[2], fd2[2];
3153 pid_t pid;
3154 
3155 	if (pipe(fd1) <0 || pipe(fd2) <0) {
3156 		g_error("pipe error\n");
3157 	}
3158 
3159 	if (( pid = fork()) < 0) {
3160 		g_error("fork error\n");
3161 	} else
3162 	if (pid > 0) {
3163 		/* parent */
3164 		close(fd1[0]);
3165 		close(fd2[1]);
3166 
3167 		/* return new stdout/stdin of child */
3168 		if (in != NULL)
3169 			*in = fd1[1];
3170 		else
3171 			close(fd1[1]);
3172 
3173 		if (out != NULL)
3174 			*out = fd2[0];
3175 		else
3176 			close(fd2[0]);
3177 
3178 	} else {
3179 
3180 		/* needed for correct rights in nonroot mode */
3181 		/* fix_guid(); */
3182 
3183 		/* child */
3184 		close(fd1[1]);
3185 		close(fd2[0]);
3186 
3187 		/* reroute stdin from child */
3188 		if (fd1[0] != STDIN_FILENO) {
3189 			if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO) {
3190 				g_error("dup2 error on stdin\n");
3191 			}
3192 			close(fd1[0]);
3193 		}
3194 		/* reroute stdout from child */
3195 		if (fd2[1] != STDOUT_FILENO) {
3196 			if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO) {
3197 				g_error("dup2 error on stdout\n");
3198 			}
3199 			close(fd2[1]);
3200 		}
3201 
3202 		/* startup child */
3203 		if (execl("/bin/sh", "sh", "-c", cmd ,(void *)NULL) < 0) {
3204 			g_error("execl error\n");
3205 		}
3206 
3207 	}
3208 
3209 	return(pid);
3210 }
3211 
3212 
3213 /* rebuild a cmdline-string into a list of arguments..handle quotes and
3214    escaped chars nicely */
3215 
rebuild_cmdline(char ** arglist,gchar * cmd,gchar * callpath)3216 static void rebuild_cmdline(char **arglist, gchar *cmd, gchar *callpath) {
3217 gchar tmp[MAXLINE*10];
3218 gchar *p;
3219 gint n, count, start, in_quotes;
3220 gchar oldc, c;
3221 
3222 	n = 0;
3223 	count = 0;
3224 	start = 0;
3225 	in_quotes = 0;
3226 	oldc = '\0';
3227 	for (n = 0; n <= strlen(cmd); n++) {
3228 		c = cmd[n];
3229 
3230 		/* quotes found? search for closing quote */
3231 		/* ignore escaped quotes */
3232 		if (c == '\"' && oldc != '\\') {
3233 			if (in_quotes == 0) {
3234 				in_quotes = 1;
3235 			} else {
3236 				/* end-quote found */
3237 				in_quotes = 0;
3238 			}
3239 		}
3240 		oldc = c;
3241 
3242 		/* space is delimitor between args */
3243 		if (in_quotes == 0 && (c == ' ' || c == '\0')) {
3244 			strncpy(tmp,cmd+start,n-start);
3245 			tmp[n-start] = '\0';
3246 
3247 			/* skip empty args */
3248 			if (n-start == 0) {
3249 				continue;
3250 			}
3251 			strip_string(tmp);
3252 
3253 			/* tmp does contain now our substr -
3254 			   remove surrounding quotes if any and
3255 			   remove any escaped-chars */
3256 			if (tmp[0] == '\"') {
3257 				p = tmp + 1;
3258 			} else {
3259 				p = tmp;
3260 			}
3261 
3262 			if (tmp[strlen(tmp)-1] == '\"') {
3263 				tmp[strlen(tmp)-1] = '\0';
3264 			}
3265 			escape_parse(p);
3266 
3267 			/* empty unquoted string? skip */
3268 			if (p == tmp && strcmp(p,"") == 0) {
3269 				continue;
3270 			}
3271 
3272 			arglist[count] = g_strdup(p);
3273 			count++;
3274 			start = n+1;
3275 		}
3276 
3277 		if (count >= MAXPIPEARGS) {
3278 			g_error("Error: More than %d cmd arguments given\n",MAXPIPEARGS);
3279 		}
3280 	}
3281 
3282 	/* now remove path from first argument */
3283 	strncpy(callpath,arglist[0], MAXLINE);
3284 	strncpy(tmp,arglist[0], MAXLINE*10);
3285 	p = rindex(tmp,'/');
3286 	if (p != NULL) {
3287 		g_free(arglist[0]);
3288 		arglist[0] = g_strdup(p+1);
3289 	}
3290 
3291 	/* now arglist is finished */
3292 
3293 	/* output generated argument-list */
3294 	if (debug) {
3295 		dodebug(11,"----- created argument array for execv -----\n");
3296 		count = 0;
3297 		dodebug(11,":%s:\n",callpath);
3298 		while(arglist[count]) {
3299 			dodebug(11,":%s:\n",arglist[count]);
3300 			count++;
3301 		}
3302 	}
3303 }
3304 
3305 
3306 
3307 /* create a bidirectional pipe */
3308 
my_s_pipe(gint fd[2],gint use_socketpair)3309 static gint my_s_pipe(gint fd[2], gint use_socketpair) {
3310 
3311 	if (use_socketpair == 1) {
3312 #if defined(HAVE_SOCKETPAIR) && HAVE_SOCKETPAIR == 1
3313 		return (socketpair(AF_UNIX, SOCK_STREAM, 0, fd));
3314 #else
3315 		/* socketpair not available - fallback */
3316 		return (pipe(fd));
3317 #endif
3318 	} else {
3319 		return (pipe(fd));
3320 	}
3321 }
3322 
3323 
3324 /* start subprocess and reroute stdin, stderr and stdout */
3325 /* does NOT use the shell as spawner */
3326 
full_dpl_pipe3(gint * out,gint * in,gint * err,gchar * cmd,gint use_socketpair)3327 static pid_t full_dpl_pipe3(gint *out, gint *in, gint *err, gchar *cmd,
3328 	gint use_socketpair) {
3329 gint fd1[2], fd2[2], fd3[2];
3330 gchar **arglist;
3331 gchar callpath[MAXLINE];
3332 pid_t pid;
3333 gint count;
3334 
3335 	/* rebuild cmdline to array of args for execv */
3336 	arglist = g_new0(gchar *, MAXPIPEARGS);
3337 	rebuild_cmdline(arglist, cmd, callpath);
3338 
3339 	/* do the pipe-stuff */
3340 	if (my_s_pipe(fd1, use_socketpair) < 0 ||
3341 	    my_s_pipe(fd2, use_socketpair) < 0 ||
3342 	    my_s_pipe(fd3, use_socketpair) < 0) {
3343 		g_error("pipe error\n");
3344 	}
3345 
3346 	if (( pid = fork()) < 0) {
3347 		g_error("fork error\n");
3348 	} else
3349 	if (pid > 0) {
3350 		/* parent */
3351 		close(fd1[0]);
3352 		close(fd2[1]);
3353 		close(fd3[1]);
3354 
3355 		/* return new stdout/stdin/stderr of child */
3356 		if (in != NULL)
3357 			*in = fd1[1];
3358 		else
3359 			close(fd1[1]);
3360 
3361 		if (out != NULL)
3362 			*out = fd2[0];
3363 		else
3364 			close(fd2[0]);
3365 
3366 		if (err != NULL)
3367 			*err = fd3[0];
3368 		else
3369 			close(fd3[0]);
3370 	} else {
3371 
3372 		/* needed for correct rights in nonroot mode */
3373 		/* fix_guid(); */
3374 
3375 		/* child */
3376 		close(fd1[1]);
3377 		close(fd2[0]);
3378 		close(fd3[0]);
3379 
3380 		/* reroute stdin from child */
3381 		if (fd1[0] != STDIN_FILENO) {
3382 			if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO) {
3383 				g_error("dup2 error on stdin\n");
3384 			}
3385 			close(fd1[0]);
3386 		}
3387 		/* reroute stdout from child */
3388 		if (fd2[1] != STDOUT_FILENO) {
3389 			if (dup2(fd2[1], STDOUT_FILENO) != STDOUT_FILENO) {
3390 				g_error("dup2 error on stdout\n");
3391 			}
3392 			close(fd2[1]);
3393 		}
3394 		/* reroute stderr from child */
3395 		if (fd3[1] != STDERR_FILENO) {
3396 			if (dup2(fd3[1], STDERR_FILENO) != STDERR_FILENO) {
3397 				g_error("dup2 error on stderr\n");
3398 			}
3399 			close(fd3[1]);
3400 		}
3401 
3402 		/* startup child */
3403 		if (execv(callpath,arglist) < 0) {
3404 			g_error("execv error\n");
3405 		}
3406 
3407 	}
3408 
3409 	/* free arglist */
3410 	count = 0;
3411 	while(arglist[count]) {
3412 		g_free(arglist[count]);
3413 		count++;
3414 	}
3415 	g_free(arglist);
3416 
3417 	return(pid);
3418 }
3419 
3420 
3421 /* start two subprocesses and connect stdout of the first with stdin
3422    of the second (proc1 | proc2) and reroute stdin and stderr of the
3423    first and stdout and stderr of the second */
3424 /* returns pidnr1 and pidnr2 */
3425 
full_dpl_pipe4(pid_t * pidnr1,pid_t * pidnr2,gint * in1,gint * err1,gchar * cmd,gint * out2,gint * err2,gchar * cmd2,gint use_socketpair)3426 static void full_dpl_pipe4(pid_t *pidnr1, pid_t *pidnr2, gint *in1, gint *err1,
3427 		    gchar *cmd, gint *out2, gint *err2, gchar *cmd2,
3428 		    gint use_socketpair) {
3429 gint fd1[2], fd2[2], fd3[2], fd4[2], pipefd[2];
3430 gchar **arglist;
3431 gchar **arglist2;
3432 gchar callpath[MAXLINE];
3433 gchar callpath2[MAXLINE];
3434 pid_t pid, pid2;
3435 gint count;
3436 
3437 	/* rebuild cmdline to array of args for execv */
3438 	arglist = g_new0(gchar *, MAXPIPEARGS);
3439 	arglist2 = g_new0(gchar *, MAXPIPEARGS);
3440 	rebuild_cmdline(arglist, cmd, callpath);
3441 	rebuild_cmdline(arglist2, cmd2, callpath2);
3442 
3443 	/* do the pipe-stuff */
3444 	if (my_s_pipe(fd1, use_socketpair) < 0 ||
3445 	    my_s_pipe(fd2, use_socketpair) < 0 ||
3446 	    my_s_pipe(fd3, use_socketpair) < 0 ||
3447 	    my_s_pipe(fd4, use_socketpair) < 0 ||
3448 	    my_s_pipe(pipefd, use_socketpair) < 0) {
3449 		g_error("pipe error\n");
3450 	}
3451 
3452 	/* fork for first process */
3453 	if (( pid = fork()) < 0) {
3454 		g_error("fork error\n");
3455 	} else
3456 	if (pid > 0) {
3457 		/* parent */
3458 		close(fd1[0]);
3459 		close(fd2[1]);
3460 		close(pipefd[1]);
3461 
3462 		/* return new fds of child */
3463 		if (in1 != NULL)
3464 			*in1 = fd1[1];
3465 		else
3466 			close(fd1[1]);
3467 
3468 		if (err1 != NULL)
3469 			*err1 = fd2[0];
3470 		else
3471 			close(fd2[0]);
3472 
3473 	} else {
3474 		/* needed for correct rights in nonroot mode */
3475 		/* fix_guid(); */
3476 
3477 		/* child */
3478 		close(fd1[1]);
3479 		close(fd2[0]);
3480 		close(pipefd[0]);
3481 
3482 		/* reroute stdin from child */
3483 		if (fd1[0] != STDIN_FILENO) {
3484 			if (dup2(fd1[0], STDIN_FILENO) != STDIN_FILENO) {
3485 				g_error("dup2 error on stdin\n");
3486 			}
3487 			close(fd1[0]);
3488 		}
3489 
3490 		/* reroute stderr from child */
3491 		if (fd2[1] != STDERR_FILENO) {
3492 			if (dup2(fd2[1], STDERR_FILENO) != STDERR_FILENO) {
3493 				g_error("dup2 error on stderr\n");
3494 			}
3495 			close(fd2[1]);
3496 		}
3497 
3498 		/* reroute stdout from child to second child */
3499 		if (pipefd[1] != STDOUT_FILENO) {
3500 			if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO) {
3501 				g_error("dup2 error on stdout\n");
3502 			}
3503 			close(pipefd[1]);
3504 		}
3505 
3506 		/* startup first child */
3507 		if (execv(callpath,arglist) < 0) {
3508 			g_error("execv error\n");
3509 		}
3510 	}
3511 
3512 
3513 	/* fork for second process */
3514 	if (( pid2 = fork()) < 0) {
3515 		g_error("fork error\n");
3516 	} else
3517 	if (pid2 > 0) {
3518 		/* parent */
3519 		close(fd3[1]);
3520 		close(fd4[1]);
3521 		close(pipefd[0]);
3522 
3523 		/* return new fds of child */
3524 		if (out2 != NULL)
3525 			*out2 = fd3[0];
3526 		else
3527 			close(fd3[0]);
3528 
3529 		if (err2 != NULL)
3530 			*err2 = fd4[0];
3531 		else
3532 			close(fd4[0]);
3533 
3534 	} else {
3535 
3536 		/* needed for correct rights in nonroot mode */
3537 		/* fix_guid(); */
3538 
3539 		/* child */
3540 		close(fd3[0]);
3541 		close(fd4[0]);
3542 		close(pipefd[1]);
3543 
3544 		/* reroute stdin from first child */
3545 		if (pipefd[0] != STDIN_FILENO) {
3546 			if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
3547 				g_error("dup2 error on stdin\n");
3548 			}
3549 			close(pipefd[0]);
3550 		}
3551 
3552 		/* reroute stderr from child */
3553 		if (fd4[1] != STDERR_FILENO) {
3554 			if (dup2(fd4[1], STDERR_FILENO) != STDERR_FILENO) {
3555 				g_error("dup2 error on stdout\n");
3556 			}
3557 			close(fd4[1]);
3558 		}
3559 
3560 		/* reroute stdout from child to second child */
3561 		if (fd3[1] != STDOUT_FILENO) {
3562 			if (dup2(fd3[1], STDOUT_FILENO) != STDOUT_FILENO) {
3563 				g_error("dup2 error on stdout\n");
3564 			}
3565 			close(fd3[1]);
3566 		}
3567 
3568 		/* startup second child */
3569 		if (execv(callpath2,arglist2) < 0) {
3570 			g_error("execv error\n");
3571 		}
3572 	}
3573 
3574 	/* free arglists */
3575 	count = 0;
3576 	while(arglist[count]) {
3577 		g_free(arglist[count]);
3578 		count++;
3579 	}
3580 	g_free(arglist);
3581 	count = 0;
3582 	while(arglist2[count]) {
3583 		g_free(arglist2[count]);
3584 		count++;
3585 	}
3586 	g_free(arglist2);
3587 
3588 	/* return pids by call by reference */
3589 	*pidnr1 = pid;
3590 	*pidnr2 = pid2;
3591 }
3592 
3593 
3594 /* get the master-volume */
3595 /* return val 0..100 or -1 or error */
3596 
query_mixer()3597 gint query_mixer() {
3598 #if !(defined(__MACH__) && defined(__APPLE__))
3599 gint mix;
3600 #endif
3601 #if defined(linux) || defined(__FreeBSD__)
3602 gint val;
3603 #endif
3604 #if defined(sun) || defined(__OpenBSD__)
3605 audio_info_t ainfo;
3606 #endif
3607 #ifdef hpux
3608 # ifndef hpux_alib
3609 struct audio_gain again;
3610 # endif
3611 #endif
3612 
3613 
3614 	if (strcmp(setupdata.mix_device,"") == 0) {
3615 		/* no mixer found - ignore */
3616 		return -1;
3617 	}
3618 
3619 #if defined(linux) || defined(__FreeBSD__)
3620 
3621 	dodebug(10,"quering mixer %s\n", setupdata.mix_device);
3622 	mix = open(setupdata.mix_device, O_RDWR);
3623 	if (mix < 0) {
3624 		g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3625 		return -1;
3626 	}
3627 
3628 	if (ioctl(mix,MIXER_READ(0),&val) == -1) {
3629 		g_warning("Error reading mixer\n");
3630 		return -1;
3631 	}
3632 
3633 	close(mix);
3634 
3635 	/* average val of both channels */
3636 	return ((val & 0x7f) + ((val >> 8) & 0x7f))/2;
3637 
3638 #endif
3639 #if defined(sun) || defined(__OpenBSD__)
3640 
3641 	dodebug(10,"quering mixer %s\n", setupdata.mix_device);
3642 	mix = open(setupdata.mix_device, O_RDONLY);
3643 	if (mix < 0) {
3644 		g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3645 		return -1;
3646 	}
3647 
3648 	if (ioctl(mix, AUDIO_GETINFO, &ainfo) == -1) {
3649 		g_warning("Error reading mixer\n");
3650 		return -1;
3651 	}
3652 
3653 	close(mix);
3654 
3655 	return ((gint) ((gfloat) ainfo.play.gain / 2.55));
3656 
3657 #endif
3658 #ifdef aix
3659        /* Due we are using the raw aix audio api, we    */
3660        /* are not able to query the gain settings :-(   */
3661        /* set the gain to the max. value and return 100 */
3662        memset ( & achange, '\0', sizeof (achange));
3663        memset ( & acontrol, '\0', sizeof (acontrol));
3664 
3665        /* Initialise with the max gain =2147418112      */
3666        achange.balance        = 0x3fff0000;
3667        achange.balance_delay  = 0;
3668        achange.volume         = 2147418112;
3669        achange.volume_delay   = 0;
3670        achange.input          = AUDIO_IGNORE;
3671        achange.output         = AUDIO_IGNORE;
3672        achange.output         = AUDIO_IGNORE;
3673        achange.treble         = AUDIO_IGNORE;
3674        achange.bass           = AUDIO_IGNORE;
3675        achange.pitch          = AUDIO_IGNORE;
3676        achange.monitor        = AUDIO_IGNORE;
3677        achange.dev_info       = (char *) NULL;
3678        acontrol.ioctl_request = AUDIO_CHANGE;
3679        acontrol.position      = 0;
3680        acontrol.request_info  = (char *) & achange;
3681 
3682        if ((mix = open(setupdata.mix_device, O_RDONLY)) == -1) {
3683                 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3684                 return -1;
3685         }
3686        if (ioctl (mix, AUDIO_CONTROL, & acontrol) == -1) {
3687                g_warning("Error reading mixer\n");
3688                return -1;
3689        }
3690        close(mix);
3691 
3692        return (100);
3693 #endif
3694 #ifdef hpux
3695 # ifndef hpux_alib
3696         dodebug(10,"quering mixer %s\n", setupdata.mix_device);
3697 	if ((mix = open(setupdata.mix_device, O_RDONLY)) == -1) {
3698                 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3699                 return -1;
3700         }
3701 	if (ioctl(mix, AUDIO_GET_GAINS, &again) == -1) {
3702                 g_warning("Error reading mixer\n");
3703 		return -1;
3704 	}
3705 	close(mix);
3706 	return ((gint) ((gfloat) (again.transmit_gain - AUDIO_OFF_GAIN)
3707 			/ (gfloat) (AUDIO_MAX_GAIN - AUDIO_OFF_GAIN) * 100.0));
3708 # else
3709 	/* The audio tranmission gains are set by some */
3710 	/* environment variables or a fancy program    */
3711 	/* like the AudioCP                            */
3712 	return (0);
3713 # endif
3714 #endif
3715 
3716 	return 0;
3717 }
3718 
3719 
3720 /* set the master-volume */
3721 /* returns 0 on ok, -1 on error */
3722 
set_mixer(gint val)3723 gint set_mixer(gint val) {
3724 #if !(defined(__MACH__) && defined(__APPLE__))
3725 gint mix;
3726 #endif
3727 #if defined(sun) || defined(__OpenBSD__)
3728 audio_info_t ainfo;
3729 #endif
3730 #ifdef aix
3731 audio_change   achange;
3732 audio_control  acontrol;
3733 #endif
3734 #ifdef hpux
3735 # ifndef hpux_alib
3736 struct audio_gain again;
3737 # endif
3738 #endif
3739 
3740 	if (strcmp(setupdata.mix_device,"") == 0) {
3741 		/* no mixer found - ignore */
3742 		return -1;
3743 	}
3744 
3745 #if defined(linux) || defined(__FreeBSD__)
3746 
3747 	dodebug(10,"setting mixer %s to %d\n", setupdata.mix_device, val);
3748 	mix = open(setupdata.mix_device, O_RDWR);
3749 	if (mix < 0) {
3750 		g_warning("Can't open mixer-device\n");
3751 		return -1;
3752 	}
3753 
3754 	val |= val << 8;
3755 	if (ioctl(mix, MIXER_WRITE(0), &val) == -1) {
3756 		g_warning("Error writing mixer\n");
3757 		return -1;
3758 	}
3759 
3760 	close(mix);
3761 
3762 #endif
3763 #if defined(sun) || defined(__OpenBSD__)
3764 
3765 	dodebug(10,"setting mixer %s to %d\n", setupdata.mix_device, val);
3766 	mix = open(setupdata.mix_device, O_WRONLY);
3767 	if (mix < 0) {
3768 		g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3769 		return -1;
3770 	}
3771 
3772 	AUDIO_INITINFO(&ainfo);
3773 	ainfo.play.gain = (gint) (2.55 * (gfloat) val);
3774 
3775 	if (ioctl(mix, AUDIO_SETINFO, &ainfo) == -1) {
3776 		g_warning("Error writing mixer\n");
3777 		return -1;
3778 	}
3779 
3780 	close(mix);
3781 #endif
3782 #ifdef aix
3783        memset ( & achange, '\0', sizeof (achange));
3784        memset ( & acontrol, '\0', sizeof (acontrol));
3785 
3786        /* Initialise with the max gain =2147418112      */
3787        achange.balance        = AUDIO_IGNORE;
3788        achange.balance_delay  = AUDIO_IGNORE;
3789        achange.volume         = (long) (21474181.12 * (gfloat) val);
3790        achange.volume_delay   = 0;
3791        achange.input          = AUDIO_IGNORE;
3792        achange.output         = AUDIO_IGNORE;
3793        achange.output         = AUDIO_IGNORE;
3794        achange.treble         = AUDIO_IGNORE;
3795        achange.bass           = AUDIO_IGNORE;
3796        achange.pitch          = AUDIO_IGNORE;
3797        achange.monitor        = AUDIO_IGNORE;
3798        achange.dev_info       = (char *) NULL;
3799        acontrol.ioctl_request = AUDIO_CHANGE;
3800        acontrol.position      = 0;
3801        acontrol.request_info  = (char *) & achange;
3802 
3803        if ((mix = open(setupdata.mix_device, O_RDONLY)) == -1) {
3804                 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3805                 return -1;
3806         }
3807        if (ioctl (mix, AUDIO_CONTROL, & acontrol) == -1) {
3808                g_warning("Error reading mixer\n");
3809                return -1;
3810        }
3811        close (mix);
3812 #endif
3813 #ifdef hpux
3814 # ifndef hpux_alib
3815         dodebug(10,"setting mixer %s to %d\n", setupdata.mix_device, val);
3816 	if ((mix = open(setupdata.mix_device, O_RDWR)) == -1) {
3817                 g_warning("Can't open mixer-device %s\n", setupdata.mix_device);
3818                 return -1;
3819         }
3820 	/* Query the receive/transmit/monitor gains */
3821 	again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
3822 	ioctl(mix,AUDIO_GET_GAINS,&again);
3823 
3824 	/* Calculate the new transmit gain */
3825 	again.cgain[0].transmit_gain = AUDIO_OFF_GAIN
3826 	        + (gfloat) ((AUDIO_MAX_GAIN - AUDIO_OFF_GAIN) * val) * 0.01;
3827 	again.cgain[1].transmit_gain = again.cgain[0].transmit_gain;
3828 	again.channel_mask = AUDIO_CHANNEL_0 | AUDIO_CHANNEL_1;
3829 
3830 	/* Set the new gains (only transmit gain actually changed) */
3831 	if (ioctl(mix, AUDIO_SET_GAINS, &again) == -1) {
3832 	        g_warning("Error setting audio gain\n");
3833                 return -1;
3834 	}
3835 	close(mix);
3836 # else
3837 	/* The audio tranmission gains are set by some */
3838 	/* environment variables or a fancy program    */
3839 	/* like the AudioCP                            */
3840 	return 0;
3841 # endif
3842 #endif
3843 
3844 	return 0;
3845 }
3846 
3847 
3848 /* send SIGINT to a cdda2wav/readcd/cdrecord process (btw to its child)
3849    and hope that it terminates at it own */
3850 
kill_readcdda()3851 void kill_readcdda() {
3852 
3853 	/* stop any timers watching for cdrecord output */
3854 	if (cdrtimer) {
3855 		gtk_timeout_remove(cdrtimer);
3856 		cdrtimer = 0;
3857 	}
3858 
3859 	if (readcdda_pid != -1) {
3860 
3861 		dodebug(2,"sending SIGINT to %d\n", (gint) readcdda_pid);
3862 		kill(readcdda_pid, SIGINT);
3863 	}
3864 	if (readcdda_pid2 != -1) {
3865 
3866 		dodebug(2,"sending SIGINT to %d\n", (gint) readcdda_pid2);
3867 		kill(readcdda_pid2, SIGINT);
3868 	}
3869 }
3870 
3871 
3872 /* in bulk mode update the info-label of read tracks */
3873 
update_bulk_readlabel()3874 static void update_bulk_readlabel() {
3875 gchar tmp[MAXLINE];
3876 gchar tmp2[MAXLINE];
3877 gint frms;
3878 
3879 	frms = writeparams.frames[read_tracknr];
3880 	convert_frames2mbminstring(frms, tmp);
3881 	g_snprintf(tmp2,MAXLINE,_("Reading audio track %d/%d [%s]"), read_tracknr,
3882 			writeparams.nrtracks, tmp);
3883 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), tmp2);
3884 }
3885 
3886 
3887 /* parse output of cdda2wav and update sliders */
3888 
read_cdda2wav_out(gpointer data,gint source,GdkInputCondition cond)3889 static void read_cdda2wav_out(gpointer data, gint source, GdkInputCondition cond) {
3890 gint n;
3891 gint ret;
3892 gchar line[MAXLINE];
3893 gchar tmp[MAXLINE];
3894 gchar tmp2[MAXLINE];
3895 gchar *p;
3896 gint val, tnr, bulk;
3897 gfloat pval, pval2;
3898 
3899 	/* called for bulk or not? */
3900 	bulk = GPOINTER_TO_INT(data);
3901 
3902 	/* read output of cdda */
3903 	n = read_line(source, line, MAXLINE);
3904 
3905 	/* cdda-finished? */
3906 	if (n <= 0) {
3907 		gtk_input_remove(readcdda_callback);
3908 
3909 		/* pick up return status of child */
3910 		wait(&ret);
3911 
3912 		/* tell our caller that we are done here */
3913 		read_done = WEXITSTATUS(ret);
3914 		return;
3915 	}
3916 
3917 	strip_string(line);
3918 	dodebug(10,"cdda2wav: %s\n", line);
3919 
3920 	/* scanning for indexes? */
3921 	if (strncmp(line,"index scan:", 11) == 0) {
3922 		strcpy(tmp,line+11);
3923 		p = strtok(tmp,".");
3924 		if (p != NULL) {
3925 			tnr = atoi(p);
3926 		} else {
3927 			tnr = 0;
3928 		}
3929 		g_snprintf(tmp,MAXLINE,_("Scanning track %d for indices..."),tnr);
3930 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
3931 	}
3932 
3933 	/* found indices? */
3934 	if (strncmp(line,"track", 5) == 0) {
3935 		strcpy(tmp,line);
3936 		/* just output until first comma - looks nicer */
3937 		p = strtok(tmp,",");
3938 		if (p != NULL) {
3939 			strcpy(tmp2,p);
3940 		} else {
3941 			strcpy(tmp2,tmp);
3942 		}
3943 		strcat(tmp2,"\n");
3944 		convert_for_gtk2_textwidget(tmp2);
3945 		gtk_text_insert(GTK_TEXT(readtrack_textview),
3946 			fixedfont,NULL,NULL, tmp2, strlen(tmp2));
3947 	}
3948 
3949 	/* scanning for MCN? */
3950 	if (strncmp(line,"scanning for MCN", 16) == 0) {
3951 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Scanning for MCN (Media Catalog Number)..."));
3952 	}
3953 
3954 	/* scanning for ISRC? */
3955 	if (strncmp(line,"scanning for ISRCs:", 19) == 0) {
3956 		strcpy(tmp,line+20);
3957 		p = strtok(tmp,".");
3958 		if (p != NULL) {
3959 			tnr = atoi(p);
3960 		} else {
3961 			tnr = 0;
3962 		}
3963 		g_snprintf(tmp,MAXLINE,_("Scanning track %d for ISRC..."),tnr);
3964 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
3965 	}
3966 
3967 	/* done with scanning? */
3968 	if (strncmp(line,"recording", 9) == 0) {
3969 		if (bulk == 0) {
3970 			/* restore original info text */
3971 			gtk_label_set_text(GTK_LABEL(readtrack_info_label),
3972 				readtrack_info_string);
3973 		} else {
3974 			update_bulk_readlabel();
3975 		}
3976 	}
3977 
3978 	/* look for a percent value */
3979 	if (line[strlen(line)-1] == '%') {
3980 		/* skip leading linefeed if any */
3981 		if (line[0] == '\r')
3982 			line[0] = ' ';
3983 
3984 		/* look for last space */
3985 		p = rindex(line,' ');
3986 		if (p != NULL)
3987 			strcpy(tmp,p);
3988 		else
3989 			strcpy(tmp,line);
3990 
3991 		tmp[strlen(tmp)-1] = '\0';
3992 		strip_string(tmp);
3993 		val = atoi(tmp);
3994 		pval = (gfloat)val/100;
3995 		if (pval > 1.0) pval = 1.0;
3996 		gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1),
3997 			pval);
3998 
3999 		/* now calculate how much percent he have at all */
4000 		if (bulk == 0) {
4001 			pval2 = (pct_so_far + (pval * pct_this_track)) /100;
4002 			if (pval2 > 1.0) pval2 = 1.0;
4003 		} else {
4004 			pval2 = (writeparams.pct_so_far_arr[read_tracknr] +
4005 				(pval * writeparams.pct_this_track_arr[read_tracknr]))/100;
4006 		}
4007 
4008 		gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar2),
4009 			pval2);
4010 		set_xcdr_title(toplevel, viewmode_dialog, (gint)(pval2*100+0.5));
4011 
4012 		/* now update info for small view */
4013 		g_snprintf(tmp,MAXLINE,"%d%% / %d%%",(gint)(pval*100+0.5),
4014 			   (gint)(pval2*100+0.5));
4015 		gtk_label_set_text(GTK_LABEL(readtrack_small_info2),tmp);
4016 
4017 		return;
4018 	}
4019 
4020 	/* track successfully recorded? */
4021 	if (strlen(line) > strlen("successfully recorded")) {
4022 		strcpy(tmp, line+strlen(line)-strlen("successfully recorded"));
4023 		if (strcmp(tmp, "successfully recorded") == 0 ||
4024 		    strcmp(tmp, "recorded successfully") == 0) {
4025 			gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1), 1.0);
4026 			/* look for last % */
4027 			p = rindex(line,'%');
4028 			if (p != NULL) {
4029 				strcpy(tmp,p+1);
4030 				strip_string(tmp);
4031 			} else
4032 				strcpy(tmp,line);
4033 
4034 			/* strips the 100% value from the string */
4035 			strip_string(tmp);
4036 			strcpy(line,tmp);
4037 
4038 			if (bulk == 1) {
4039 				/* in bulkmode this means we switched tracks */
4040 				read_tracknr++;
4041 				update_bulk_readlabel();
4042 			}
4043 		}
4044 	}
4045 
4046 	/* get subprocess pid */
4047 	if (strncmp(line,"child pid", 9) == 0) {
4048 		strcpy(tmp, line+12);
4049 		readcdda_pid= (pid_t) atoi(tmp);
4050 		return;
4051 	}
4052 
4053 	/* error-text? do display these in the next block */
4054 	if (strncmp(line,"Error",5) == 0 || strstr(line,"open audio sample file") != NULL) {
4055 		read_output_ctrl = 1;
4056 	}
4057 
4058 	/* forward most other output to textview-window */
4059 	if (strncmp(line,"record",6) == 0 || read_output_ctrl == 1) {
4060 		read_output_ctrl = 1;
4061 		/* skip lines that do not interest us */
4062 		if (strncmp(line,"percent_done",12) == 0) {
4063 			return;
4064 		}
4065 		if (strncmp(line,"overlap:min",11) == 0) {
4066 			return;
4067 		}
4068 		strcat(line,"\n");
4069 		convert_for_gtk2_textwidget(line);
4070 		gtk_text_insert(GTK_TEXT(readtrack_textview),
4071 			fixedfont,NULL,NULL, line, strlen(line));
4072 	}
4073 }
4074 
4075 
4076 /* parse dummy output of cdda2wav */
4077 /* output stdout of cdda2wav where never should any data be delivered */
4078 
read_cdda2wav_dummyout(gpointer data,gint source,GdkInputCondition cond)4079 static void read_cdda2wav_dummyout(gpointer data, gint source, GdkInputCondition cond) {
4080 gint n;
4081 gchar line[MAXLINE];
4082 
4083 	/* read output of cdda */
4084 	n = read_line(source, line, MAXLINE);
4085 
4086 	/* cdda-finished? */
4087 	if (n <= 0) {
4088 		gtk_input_remove(readcdda_callback2);
4089 		return;
4090 	}
4091 
4092 	strcat(line,"\n");
4093 	convert_for_gtk2_textwidget(line);
4094 	gtk_text_insert(GTK_TEXT(readtrack_textview),
4095 			fixedfont,NULL,NULL, line, strlen(line));
4096 }
4097 
4098 
4099 /* call cdda2wav to read an audio-track
4100    return 0 on success, 1 on error */
4101 
read_audio_track(gint devnr,gint starttrack,gint endtrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)4102 gint read_audio_track(gint devnr, gint starttrack, gint endtrack, gint kbyte,
4103 		      gchar *fname, gint startoffset, gint endoffset,
4104 		      gint nrtracks, gfloat percent, gfloat percent_done,
4105 		      gint viewtrack) {
4106 gchar cmd[MAXLINE];
4107 gchar tmp[MAXLINE];
4108 gchar tmp2[MAXLINE];
4109 gchar tmp3[MAXLINE];
4110 gchar tmp4[MAXLINE];
4111 gchar tmp5[MAXLINE];
4112 gchar tmp6[MAXLINE];
4113 gchar tmpfname[MAXLINE];
4114 gint read_in, read_out, read_dummy;
4115 
4116 	/* if another read running, ignore */
4117 	if (read_done == 999) {
4118 		return -1;
4119 	}
4120 
4121 	/* no filename given? */
4122 	if (fname == NULL) {
4123 		return 1;
4124 	}
4125 	strncpy(tmpfname, fname, MAXLINE);
4126 
4127 	/* mark our read-process as running */
4128 	read_done = 999;
4129 	read_output_ctrl = 0;
4130 	readcdda_pid = -1;
4131 	readcdda_pid2 = -1;
4132 	read_abort_mark = 0;
4133 
4134 	/* set info-label */
4135 	convert_kbytes2mbminstring(kbyte, tmp);
4136 	g_snprintf(tmp2,MAXLINE,_("Reading audio track %d/%d [%s]"), viewtrack, nrtracks, tmp);
4137 	gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
4138 	strcpy(readtrack_info_string, tmp2);
4139 
4140 	g_snprintf(tmp2,MAXLINE,_("Reading %d/%d:"), viewtrack, nrtracks);
4141 	gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
4142 
4143 	/* get bus,id,lun string */
4144 	if (convert_devnr2busid(devnr,tmp) != 0) {
4145 		g_error("non existing cdrom?");
4146 	}
4147 
4148 	/* some stuff to have our slider moving smoothly no matter how
4149 	   big the tracks are */
4150 	pct_so_far = percent_done;
4151 	pct_this_track = percent;
4152 
4153 	/* build command line */
4154 	if (endtrack != 0) {
4155 		g_snprintf(tmp2,MAXLINE,"%d+%d",starttrack,endtrack);
4156 	} else {
4157 		g_snprintf(tmp2,MAXLINE,"%d",starttrack);
4158 	}
4159 
4160 	/* set speed only when not zero */
4161 	if (get_cur_audioread_speed() > 0) {
4162 		g_snprintf(tmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
4163 	} else {
4164 		strcpy(tmp3,"");
4165 	}
4166 
4167 	/* have to scan for indexes? */
4168 	if (curset.indexscan != 0) {
4169 		strcpy(tmp4,"-i 1 -v all");
4170 	} else {
4171 		strcpy(tmp4,"-v toc,summary,sectors,titles");
4172 	}
4173 
4174 
4175 	if (get_cur_audioread_useparanoia()) {
4176 		g_snprintf(tmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
4177 	} else {
4178 		strcpy(tmp6,"");
4179 	}
4180 
4181 	get_wrap_path("CDDA2WAV",tmp5);
4182 	g_snprintf(cmd,MAXLINE,
4183 		   "%s -D \"%s\" -g -O wav -t %s %s %s -P %d -n %d %s \"%s\"",
4184 		   tmp5,tmp,tmp2,tmp3,tmp4,
4185 		   get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
4186 		   tmp6,
4187 		   convert_escape(tmpfname));
4188 
4189 	dodebug(1, "spawning: %s\n",cmd);
4190 	dolog(2,"Read audio track %s\n", fname);
4191 	dolog(3,"Executing: %s\n",cmd);
4192 
4193 	/* start child and get new fds */
4194 	readcdda_pid = full_dpl_pipe3(&read_dummy,&read_in,&read_out,cmd,0);
4195 	readcdda_pid2 = -1;
4196 
4197 	/* set output to nonblocking - otherwise our callback would block */
4198 	fcntl(read_out, F_SETFL, O_NONBLOCK);
4199 	fcntl(read_dummy, F_SETFL, O_NONBLOCK);
4200 
4201 	/* catch output of child */
4202 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4203 		(GdkInputFunction) read_cdda2wav_out, GINT_TO_POINTER(0));
4204 	readcdda_callback2 = gdk_input_add(read_dummy, GDK_INPUT_READ,
4205 		(GdkInputFunction) read_cdda2wav_dummyout,NULL);
4206 
4207 	/* now wait until track is read */
4208 	while (read_done == 999) {
4209 		wait_and_process_events();
4210 	}
4211 
4212 	close(read_out);
4213 	close(read_in);
4214 	close(read_dummy);
4215 
4216 	gtk_text_insert(GTK_TEXT(readtrack_textview),
4217 		fixedfont,NULL,NULL, "\n", 1);
4218 
4219 	/* error while reading? */
4220 	if (read_done != 0 && read_abort_mark == 0) {
4221 		g_snprintf(tmp,MAXLINE,_("Error reading audio track %d/%d"), starttrack, nrtracks);
4222 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
4223 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Read-Error:"));
4224 		return 1;
4225 	}
4226 	/* aborted? */
4227 	if (read_abort_mark == 1) {
4228 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Read aborted..."));
4229 		return 1;
4230 	}
4231 
4232 	return 0;
4233 }
4234 
4235 
4236 /* call cdda2wav to read all audio tracks from a cd */
4237 
start_bulk_read_action(gint devnr,gfloat percent_done,gint startnr)4238 gint start_bulk_read_action(gint devnr, gfloat percent_done, gint startnr) {
4239 GList *loop;
4240 track_read_param_t *trackparam;
4241 char tmp[MAXLINE];
4242 char tmptmp[MAXLINE];
4243 char tmp3[MAXLINE];
4244 char tmp4[MAXLINE];
4245 char tmp5[MAXLINE];
4246 char tmp6[MAXLINE];
4247 char cmd[MAXLINE*10];  /* extra big buffer for very long cdrecord options */
4248 gint read_in, read_out, read_dummy;
4249 gint tracknr;
4250 
4251         /* if another read running, ignore */
4252         if (read_done == 999) {
4253                 return -1;
4254         }
4255 
4256         /* mark our read-process as running */
4257         read_done = 999;
4258         read_output_ctrl = 0;
4259 	pct_so_far = percent_done;
4260 	read_tracknr = startnr;
4261         readcdda_pid = -1;
4262 	readcdda_pid2 = -1;
4263         read_abort_mark = 0;
4264 
4265 	/* init track-label */
4266 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Reader..."));
4267 	strcpy(readtrack_info_string, "");
4268 
4269         /* reset writeparams-arrays */
4270 	/* lets reuse this structure - even when we just read now */
4271         g_free(writeparams.tracktype);
4272         g_free(writeparams.frames);
4273         g_free(writeparams.pct_so_far_arr);
4274         g_free(writeparams.pct_this_track_arr);
4275         writeparams.tracktype = g_new0(gint,MAXTRACKS);
4276         writeparams.frames = g_new0(gint,MAXTRACKS);
4277         writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
4278         writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
4279         writeparams.nrtracks = 0;
4280         writeparams.simulation = curset.writesimul;
4281 
4282         /* get bus,id,lun string */
4283         if (convert_devnr2busid(devnr,tmp) != 0) {
4284                 g_error("non existing cdrom?");
4285         }
4286 
4287         /* set speed only when not zero */
4288         if (get_cur_audioread_speed() > 0) {
4289                 g_snprintf(tmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
4290         } else {
4291                 strcpy(tmp3,"");
4292         }
4293 
4294         /* have to scan for indexes? */
4295         if (curset.indexscan != 0) {
4296                 strcpy(tmp4,"-v all");
4297         } else {
4298                 strcpy(tmp4,"-v toc,summary,sectors,titles");
4299         }
4300 
4301 	if (get_cur_audioread_useparanoia()) {
4302 		g_snprintf(tmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
4303 	} else {
4304 		strcpy(tmp6,"");
4305 	}
4306 
4307 	get_wrap_path("CDDA2WAV",tmp5);
4308         g_snprintf(cmd,MAXLINE,
4309                    "%s -D \"%s\" -g -O wav %s %s -P %d -n %d %s -B",
4310                    tmp5,tmp,tmp3,tmp4,
4311 		   get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
4312 		   tmp6);
4313 
4314 	tracknr = startnr;
4315 	/* now add all track-filenames (only audio) */
4316         loop = g_list_first(trackreadset.trackparams);
4317         while(loop) {
4318                 trackparam = loop->data;
4319                 if (trackparam->trackfile != NULL &&
4320 	            trackparam->tracktype == 1) {
4321 			strcpy(tmptmp, trackparam->trackfile);
4322                         g_snprintf(tmp, MAXLINE, " \"%s\"",
4323                                 convert_escape(tmptmp));
4324                         strcat(cmd, tmp);
4325 
4326 			/* fill up percent values for percentbar */
4327 			writeparams.tracktype[tracknr] = trackparam->tracktype;
4328 			writeparams.frames[tracknr] = trackparam->frames;
4329 			writeparams.pct_this_track_arr[tracknr] = trackparam->percent;
4330 			writeparams.pct_so_far_arr[tracknr] = pct_so_far;
4331 			pct_so_far += trackparam->percent;
4332 			writeparams.nrtracks++;
4333 			tracknr++;
4334 
4335                 }
4336                 loop = loop->next;
4337         }
4338 	/* correct full nr of tracks (so we have the full count of tracks) */
4339 	writeparams.nrtracks+=startnr-1;
4340 
4341         dodebug(1, "spawning: %s\n",cmd);
4342         dolog(2,"Read all audio tracks\n");
4343         dolog(3,"Executing: %s\n",cmd);
4344 
4345         /* start child and get new fds */
4346         readcdda_pid = full_dpl_pipe3(&read_dummy,&read_in,&read_out,cmd,0);
4347 	readcdda_pid2 = -1;
4348 
4349         /* set output to nonblocking - otherwise our callback would block */
4350         fcntl(read_out, F_SETFL, O_NONBLOCK);
4351 
4352         /* catch output of child */
4353         readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4354                 (GdkInputFunction) read_cdda2wav_out, GINT_TO_POINTER(1));
4355 	readcdda_callback2 = gdk_input_add(read_dummy, GDK_INPUT_READ,
4356 		(GdkInputFunction) read_cdda2wav_dummyout,NULL);
4357 
4358         /* now wait until track is read */
4359         while (read_done == 999) {
4360                 wait_and_process_events();
4361         }
4362 
4363         close(read_out);
4364         close(read_in);
4365 	close(read_dummy);
4366 
4367         gtk_text_insert(GTK_TEXT(readtrack_textview),
4368                 fixedfont,NULL,NULL, "\n", 1);
4369 
4370         /* error while reading? */
4371         if (read_done != 0 && read_abort_mark == 0) {
4372                 g_snprintf(tmp,MAXLINE,_("Error reading audio track %d/%d"), read_tracknr,
4373 			writeparams.nrtracks);
4374                 gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
4375                 gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Read-Error:"));
4376                 return 1;
4377         }
4378         /* aborted? */
4379         if (read_abort_mark == 1) {
4380                 gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Read aborted..."));
4381                 return 1;
4382         }
4383 
4384 	return 0;
4385 }
4386 
4387 
4388 /* parse output of readcd and update sliders */
4389 
read_readcd_out(gpointer data,gint source,GdkInputCondition cond)4390 static void read_readcd_out(gpointer data, gint source, GdkInputCondition cond) {
4391 gint n;
4392 gint ret;
4393 gchar line[MAXLINE];
4394 gchar tmp[MAXLINE];
4395 gchar tmp2[MAXLINE];
4396 gint val;
4397 gfloat pval, pval2;
4398 
4399 	/* read output of readcd */
4400 	n = read_line(source, line, MAXLINE);
4401 
4402 	/* readcd-finished? */
4403 	if (n <= 0) {
4404 		gtk_input_remove(readcdda_callback);
4405 
4406 		/* pick up return status of child */
4407 		wait(&ret);
4408 
4409 		/* tell our caller that we are done here */
4410 		if (WEXITSTATUS(ret) == 0 && read_output_ctrl == 0) {
4411 			/* readcd does return status 0 when killed - override */
4412 			read_done = 1;
4413 		} else {
4414 			read_done = WEXITSTATUS(ret);
4415 		}
4416 		return;
4417 	}
4418 
4419 	dodebug(10,"readcd: %s\n", line);
4420 
4421 	/* look for end value */
4422 	if (strncmp(line,"end:",4) == 0) {
4423 		strcpy(tmp,line+4);
4424 		strip_string(tmp);
4425 		readcd_endsector = atoi(tmp);
4426 		return;
4427 	}
4428 
4429 	/* look for a percent value */
4430 	if (strncmp(line,"addr:",5) == 0) {
4431 		/* skip leading linefeed if any */
4432 		if (line[0] == '\r')
4433 			strcpy(tmp,line+6);
4434 		else
4435 			strcpy(tmp,line+5);
4436 
4437 		strip_string(tmp);
4438 		strcpy(tmp2,strtok(tmp," "));
4439 		val = atoi(tmp2) - readcd_startsector;
4440 
4441 		/* if not set yet, do nothing */
4442 		if (readcd_endsector == 0)
4443 			return;
4444 
4445 		pval = (gfloat)val/(gfloat)(readcd_endsector - readcd_startsector);
4446 		if (pval > 1.0) pval = 1.0;
4447 
4448 		gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1),
4449 			pval);
4450 
4451 		/* now calculate how much percent he has at all */
4452 		pval2 = (pct_so_far + (pval * pct_this_track)) /100;
4453 		if (pval2 > 1.0) pval2 = 1.0;
4454 		gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar2),
4455 			pval2);
4456 		set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval2*100+0.5));
4457 
4458 		/* now update info for small view */
4459 		g_snprintf(tmp,MAXLINE,"%d%% / %d%%",(gint)(pval*100+0.5),
4460 			   (gint)(pval2*100+0.5));
4461 		gtk_label_set_text(GTK_LABEL(readtrack_small_info2),tmp);
4462 
4463 		return;
4464 	}
4465 
4466 	/* look if last expected line from readcd came */
4467 	if (strncmp(line,"Read",4) == 0) {
4468 		/* ok...now we can expect that we were not aborted */
4469 		if (read_output_ctrl != 2) {
4470 			read_output_ctrl = 1;
4471 		}
4472 	}
4473 
4474 	/* look if we got an read error */
4475 	if (line[0] == '.') {
4476 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Failed to read sector - retrying"));
4477 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Retrying..."));
4478 	}
4479 
4480 	/* now look if the got an error which could not corrected */
4481 	if (strstr(line,"not corrected")) {
4482 		read_output_ctrl = 2;
4483 	}
4484 
4485 	/* write error on disk? */
4486 	if (strstr(line,"annot write")) {
4487 		read_output_ctrl = 2;
4488 	}
4489 
4490         /* some blocked output of tracks came through */
4491         if (strstr(line, " cnt: ")) {
4492                 /* kick it */
4493                 return;
4494         }
4495 
4496 	/* forward most other output to textview-window */
4497 	strcat(line,"\n");
4498 	convert_for_gtk2_textwidget(line);
4499 	gtk_text_insert(GTK_TEXT(readtrack_textview),
4500 		fixedfont,NULL,NULL, line, strlen(line));
4501 }
4502 
4503 
4504 /* call readcd to read a data-track
4505    return 0 on success, 1 on error */
4506 
read_data_track(gint devnr,gint starttrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)4507 gint read_data_track(gint devnr, gint starttrack, gint kbyte,
4508 		      gchar *fname, gint startoffset, gint endoffset,
4509 		      gint nrtracks, gfloat percent, gfloat percent_done,
4510 		      gint viewtrack) {
4511 gchar cmd[MAXLINE];
4512 gchar tmp[MAXLINE];
4513 gchar tmptmp[MAXLINE];
4514 gchar tmp2[MAXLINE];
4515 gchar tmp3[MAXLINE];
4516 gint read_in, read_out, sectsize;
4517 
4518 	/* if another read running, ignore */
4519 	if (read_done == 999) {
4520 		return -1;
4521 	}
4522 
4523 	/* no filename given? */
4524 	if (fname == NULL) {
4525 		return 1;
4526 	}
4527 
4528 	/* mark our read-process as running */
4529 	read_done = 999;
4530 	readcdda_pid = -1;
4531 	readcdda_pid2 = -1;
4532 	read_output_ctrl = 0;
4533 	readcd_startsector = startoffset;
4534 	readcd_endsector = 0;
4535 	read_abort_mark = 0;
4536 
4537 	/* set info-label */
4538 	convert_kbytes2mbminstring(kbyte, tmp);
4539 	g_snprintf(tmp2,MAXLINE,_("Reading data track %d/%d [%s]"), viewtrack, nrtracks, tmp);
4540 	gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
4541 
4542 	g_snprintf(tmp2,MAXLINE,_("Reading %d/%d:"), viewtrack, nrtracks);
4543 	gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
4544 
4545 	/* get bus,id,lun string */
4546 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
4547 		g_error("non existing cdrom?");
4548 	}
4549 
4550 	/* some stuff to have our slider moving smoothly no matter how
4551 	   big the tracks are */
4552 	pct_so_far = percent_done;
4553 	pct_this_track = percent;
4554 
4555         /* now check which sectorsize we got */
4556         sectsize = get_sectorsize(devnr);
4557 	if (sectsize == 2352) {
4558 		/* workaround for buggy drives */
4559         	endoffset = ((endoffset * DATASECTORSIZE) / sectsize) + 1;
4560 	}
4561 
4562 	get_wrap_path("READCD",tmp3);
4563 	strcpy(tmptmp,fname);
4564 	g_snprintf(cmd,MAXLINE,
4565 		   "%s %s sectors=%d-%d -s retries=32 f= \"%s\"",
4566 		   tmp3, tmp, startoffset, endoffset,
4567 		   convert_escape(tmptmp));
4568 	dodebug(1, "spawning: %s\n",cmd);
4569 	dolog(2,"Read data track %s\n", fname);
4570 	dolog(3,"Executing: %s\n",cmd);
4571 
4572 	/* start child and get new fds */
4573 	readcdda_pid = full_dpl_pipe3(NULL,&read_in,&read_out,cmd,0);
4574 	readcdda_pid2 = -1;
4575 
4576 	/* set output to nonblocking - otherwise our callback would block */
4577 	fcntl(read_out, F_SETFL, O_NONBLOCK);
4578 
4579 	/* catch output of child */
4580 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4581 		(GdkInputFunction) read_readcd_out, NULL);
4582 
4583 	/* now wait until track is read */
4584 	while (read_done == 999) {
4585 		wait_and_process_events();
4586 	}
4587 
4588 	close(read_out);
4589 	close(read_in);
4590 
4591 	gtk_text_insert(GTK_TEXT(readtrack_textview),
4592 		fixedfont,NULL,NULL, "\n", 1);
4593 
4594 	/* error while reading? */
4595 	if ((read_done != 0 && read_abort_mark == 0) || read_output_ctrl == 2) {
4596 		g_snprintf(tmp,MAXLINE,_("Error reading data track %d/%d"), starttrack, nrtracks);
4597 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
4598 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Read-Error:"));
4599 		return 1;
4600 	}
4601 	/* aborted? */
4602 	if (read_abort_mark == 1) {
4603 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),_("Read aborted..."));
4604 		return 1;
4605 	}
4606 
4607 	return 0;
4608 }
4609 
4610 
checkmedium_out(gpointer data,gint source,GdkInputCondition cond)4611 static void checkmedium_out(gpointer data, gint source, GdkInputCondition cond) {
4612 gint n;
4613 gint ret, devnr, sectsize;
4614 gchar tmp[MAXLINE];
4615 gchar line[MAXLINE];
4616 gchar *p;
4617 
4618 
4619         /* read output of readcd */
4620         n = read_line(source, line, MAXLINE);
4621 
4622         /* readcd finished */
4623         if (n <= 0) {
4624                 gtk_input_remove(readcdda_callback);
4625 
4626                 /* pick up return status of child */
4627                 wait(&ret);
4628 
4629                 /* tell our caller that we are done here */
4630                 read_done = WEXITSTATUS(ret);
4631 
4632                 return;
4633         }
4634 
4635 	dodebug(10,"check_medium_loaded: %s\n", line);
4636 
4637 	/* got the message that no medium is present?
4638 	   in this case, ignore return code */
4639 	if (strstr(line,"medium not present")) {
4640 		checkmedium_found = 1;
4641 	}
4642 	if (strstr(line,"Device not ready")) {
4643                 checkmedium_found = 1;
4644         }
4645 
4646         /* get a line about sectorsize? */
4647         if (strstr(line,"Sectorsize:")) {
4648                 /* extract the bytes given there */
4649                 strcpy(tmp,line+12);
4650                 p = strtok(tmp," ");
4651                 if (p) {
4652                         sectsize = atoi(p);
4653                         dodebug(10,"-> Detected sectorsize of %d bytes\n", sectsize);
4654 			devnr = GPOINTER_TO_INT(data);
4655                         set_sectorsize(devnr,sectsize);
4656                 }
4657         }
4658 }
4659 
4660 
4661 /* checks if a disk is loaded in drive
4662    return 0 if not, 1 if loaded and ready */
4663 
check_medium_loaded(gint devnr)4664 static gint check_medium_loaded(gint devnr) {
4665 gchar tmp[MAXLINE];
4666 gchar tmp2[MAXLINE];
4667 gchar line[MAXLINE];
4668 gint read_out;
4669 
4670 	checkmedium_found = 0;
4671 	read_done = 999;
4672 
4673 	/* get bus,id,lun string */
4674 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
4675 		g_error("non existing cdrom?");
4676 	}
4677 
4678 	/* build command line */
4679 	get_wrap_path("READCD",tmp2);
4680 	g_snprintf(line,MAXLINE,"%s %s f=- sectors=0-0",
4681 		tmp2,tmp);
4682 
4683 	dodebug(1, "spawning: %s\n", line);
4684 
4685         readcdda_pid = full_dpl_pipe3(NULL,NULL,&read_out,line,0);
4686         readcdda_pid2 = -1;
4687 
4688         readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
4689                 (GdkInputFunction) checkmedium_out, GINT_TO_POINTER(devnr));
4690 
4691         /* now wait until toc is read */
4692         while (read_done == 999) {
4693                 wait_and_process_events();
4694         }
4695 
4696         close(read_out);
4697 
4698 	dodebug(10, "medium loaded return code: %d\n", read_done);
4699 
4700 	if (read_done == 0 && checkmedium_found == 0)
4701 		return 1;
4702 	else
4703 		return 0;
4704 }
4705 
4706 
4707 /* save the contents of a text-widget to a file
4708    return 0 on success, 1 on error */
4709 
save_text2file(char * fname,GtkWidget * txt)4710 gint save_text2file(char *fname, GtkWidget *txt) {
4711 gchar *buf;
4712 gint n;
4713 gint fd;
4714 
4715 	/* get text from textwidget */
4716 	n = gtk_text_get_length(GTK_TEXT(txt));
4717 	buf = gtk_editable_get_chars(GTK_EDITABLE(txt),0,n);
4718 
4719 	dodebug(2, "saving extended output to %s\n", fname);
4720 	dolog(3, "Saving extended output to %s\n", fname);
4721 
4722 	/* write to file */
4723 	fd = open(fname,O_WRONLY | O_CREAT);
4724 	if (fd < 0) {
4725 		g_warning("Can't open file %s for writing\n",fname);
4726 		return 1;
4727 	}
4728 
4729 	if (write(fd,buf,n) != n) {
4730 		g_warning("Can't write file %s\n",fname);
4731 		return 1;
4732 	}
4733 
4734 	g_free(buf);
4735 	close(fd);
4736 	chmod(fname,0644);
4737 
4738 	return 0;
4739 }
4740 
4741 
4742 /* write the toc-file when copying full CDs */
4743 
write_copy_cd_toc_file(gchar * tocfile)4744 gint write_copy_cd_toc_file(gchar *tocfile) {
4745 GList *loop;
4746 track_read_param_t *trackparam;
4747 FILE *fd;
4748 time_t acttime;
4749 gchar timestr[MAXLINE];
4750 gint tracknr;
4751 gchar tmp[MAXLINE];
4752 gchar tmp2[MAXLINE];
4753 
4754 	if (tocfile == NULL) return 1;
4755 
4756 	dodebug(2, "writing cd toc file %s\n", tocfile);
4757 
4758         /* is a link? */
4759         if (check_islink(tocfile, NULL)) {
4760         	g_warning("Warning, won't overwrite a link at %s\n", tocfile);
4761 		return 1;
4762         }
4763 
4764 	/* write to file */
4765 	fd = fopen(tocfile,"w");
4766 
4767 	if (fd == NULL) {
4768 		g_warning("Can't open file %s for writing\n",tocfile);
4769 		return 1;
4770 	}
4771 
4772 	/* get current time */
4773 	acttime = time((time_t *) 0);
4774 	strcpy(timestr,ctime(&acttime));
4775 	timestr[strlen(timestr)-1] = '\0';
4776 
4777 	/* write header */
4778 
4779 	fputs("#\n",fd);
4780 	g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - TOC-File\n",XCDROAST_VERSION);
4781 	fputs(tmp,fd);
4782 	g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
4783 	fputs(tmp,fd);
4784 	g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
4785 	fputs(tmp,fd);
4786 	fputs("#\n",fd);
4787 
4788 	/* write disk-info */
4789 
4790 	convert_frames2minstring(cdinfo.total_size, tmp2);
4791 	g_snprintf(tmp,MAXLINE,"# Tracks: %d [%s]\n",
4792 		cdinfo.nr_tracks, tmp2);
4793 	fputs(tmp,fd);
4794 	if (cdinfo.title && cdinfo.artist) {
4795 		g_snprintf(tmp,MAXLINE,"# title/artist: %s / %s\n",
4796 			cdinfo.title, cdinfo.artist);
4797 		fputs(tmp,fd);
4798 	}
4799 	if (cdinfo.cddb_dtitle != NULL) {
4800 		g_snprintf(tmp,MAXLINE,"# cddb: %s\n", cdinfo.cddb_dtitle);
4801 		fputs(tmp,fd);
4802 	}
4803 	fputs("#\n",fd);
4804 
4805 	/* generate disk-title */
4806 	if (cdinfo.cddb_dtitle != NULL) {
4807 		strcpy(tmp2,cdinfo.cddb_dtitle);
4808 		g_snprintf(tmp,MAXLINE,"cdtitle = \"%s\"\n", convert_escape(tmp2));
4809 	} else
4810 	if (cdinfo.title && cdinfo.artist && cdinfo.title[0] != '\0') {
4811 		g_snprintf(tmp2,MAXLINE,"%s / %s",
4812 			cdinfo.title, cdinfo.artist);
4813 		g_snprintf(tmp,MAXLINE,"cdtitle = \"%s\"\n", convert_escape(tmp2));
4814 	} else {
4815 		/* no title available? */
4816 		/* if data-track get track-label (better than nothing) */
4817 		/* get first track */
4818 		loop = g_list_first(trackreadset.trackparams);
4819 		if (loop) {
4820 			trackparam = loop->data;
4821 			tracknr = trackparam->trackinfo_index;
4822 			if (trackinfo[tracknr]->title != NULL) {
4823 				strcpy(tmp2,trackinfo[tracknr]->title);
4824 			} else {
4825 				strcpy(tmp2,"");
4826 			}
4827 			g_snprintf(tmp,MAXLINE,"cdtitle = \"%s\"\n",
4828 				convert_escape(tmp2));
4829 		} else {
4830 			g_snprintf(tmp,MAXLINE,"cdtitle = \"\"\n");
4831 		}
4832 	}
4833 	fputs(tmp,fd);
4834 	g_snprintf(tmp,MAXLINE,"cdsize = %d\n",cdinfo.total_size);
4835 	fputs(tmp,fd);
4836 	g_snprintf(tmp,MAXLINE,"discid = \"%s\"\n",cdinfo.cddb_discid);
4837 	fputs(tmp,fd);
4838 
4839 
4840 	/* write a section for each track */
4841 
4842 	loop = g_list_first(trackreadset.trackparams);
4843 	while (loop) {
4844 		trackparam = loop->data;
4845 
4846 		tracknr = trackparam->trackinfo_index;
4847 
4848 		/* make sure to get some NULLs wasted */
4849 		if (trackinfo[tracknr]->title == NULL) {
4850 			trackinfo[tracknr]->title = g_strdup("");
4851 		}
4852 		if (trackinfo[tracknr]->artist == NULL) {
4853 			trackinfo[tracknr]->artist = g_strdup("");
4854 		}
4855 
4856 		fputs("\n",fd);
4857 		if (trackinfo[tracknr]->type == 0) {
4858 			convert_frames2mbstring(trackinfo[tracknr]->size, tmp2);
4859 			g_snprintf(tmp,MAXLINE,"# data: %s [%"LL_FORMAT" bytes / %s]\n",
4860 				trackinfo[tracknr]->title,
4861 				(gint64) trackinfo[tracknr]->size * DATASECTORSIZE,
4862 				tmp2);
4863 			fputs(tmp,fd);
4864 		} else {
4865 			convert_frames2minstring(trackinfo[tracknr]->size, tmp2);
4866 			g_snprintf(tmp,MAXLINE,"# audio: %s / %s [%"LL_FORMAT" bytes / %s]\n",
4867 				trackinfo[tracknr]->title,
4868 				trackinfo[tracknr]->artist,
4869 				(gint64) trackinfo[tracknr]->size * CDDAFRAME, tmp2);
4870 			fputs(tmp,fd);
4871 			if (trackinfo[tracknr]->cddb_ttitle != NULL) {
4872 				g_snprintf(tmp,MAXLINE,"# cddb: %s\n",
4873 					trackinfo[tracknr]->cddb_ttitle);
4874 				fputs(tmp,fd);
4875 			}
4876 		}
4877 
4878 		g_snprintf(tmp,MAXLINE,"track = %02d\n", trackparam->starttrack);
4879 		fputs(tmp,fd);
4880 		g_snprintf(tmp,MAXLINE,"type = %d\n", trackinfo[tracknr]->type);
4881 		fputs(tmp,fd);
4882 		g_snprintf(tmp,MAXLINE,"size = %d\n", trackinfo[tracknr]->size);
4883 		fputs(tmp,fd);
4884 		g_snprintf(tmp,MAXLINE,"startsec = %d\n", trackinfo[tracknr]->start_sec);
4885 		fputs(tmp,fd);
4886 
4887 		if (trackparam->trackfile != NULL) {
4888 			strcpy(tmp2, trackparam->trackfile);
4889 		} else {
4890 			strcpy(tmp2,"");
4891 		}
4892 		g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",
4893 			convert_escape(tmp2));
4894 		fputs(tmp,fd);
4895 
4896 		loop = loop->next;
4897 	}
4898 
4899 	if (fclose(fd) != 0) {
4900 		/* error closing file */
4901 		return 1;
4902 	}
4903 
4904 	return 0;
4905 }
4906 
4907 
4908 /* print trackparams-structure for debug reasons */
4909 
print_trackreadset()4910 void print_trackreadset() {
4911 GList *loop;
4912 track_read_param_t *trackparam;
4913 
4914 	dodebug(2,"------ trackreadset-structure -----\n");
4915 	dodebug(2,"nrtracks: %d\n",trackreadset.nrtracks);
4916 	dodebug(2,"cdsize: %d\n",trackreadset.cdsize);
4917 	dodebug(2,"tocfile: %s\n",trackreadset.tocfile);
4918 	dodebug(2,"cdtitle: %s\n",trackreadset.cdtitle);
4919 
4920 	loop = g_list_first(trackreadset.trackparams);
4921 	while(loop) {
4922 		trackparam = loop->data;
4923 		dodebug(2,"\ntrackinfo_index: %d\n", trackparam->trackinfo_index);
4924 		dodebug(2,"starttrack: %d\n", trackparam->starttrack);
4925 		dodebug(2,"endtrack: %d\n", trackparam->endtrack);
4926 		dodebug(2,"tracktype: %d\n", trackparam->tracktype);
4927 		dodebug(2,"start_sec: %d\n", trackparam->start_sec);
4928 		dodebug(2,"startoffset: %d\n", trackparam->startoffset);
4929 		dodebug(2,"endoffset: %d\n", trackparam->endoffset);
4930 		dodebug(2,"percent: %f\n", trackparam->percent);
4931 		dodebug(2,"kbyte: %d\n", trackparam->kbyte);
4932 		dodebug(2,"frames: %d\n", trackparam->frames);
4933 		if (trackparam->trackfile != NULL) {
4934 			dodebug(2,"trackfile: %s\n", trackparam->trackfile);
4935 		} else {
4936 			dodebug(2,"trackfile: (NULL)\n");
4937 		}
4938 		loop = loop->next;
4939 	}
4940 }
4941 
4942 
4943 /* read the toc-file when copying full CDs */
4944 
read_copy_cd_toc_file(gchar * tocfile)4945 gint read_copy_cd_toc_file(gchar *tocfile) {
4946 FILE *fd;
4947 GList *loop;
4948 track_read_param_t *trackparam;
4949 gchar line[MAXLINE];
4950 gchar id[MAXLINE];
4951 gchar value[MAXLINE];
4952 gint cdsize;
4953 gfloat per;
4954 
4955 	/* keep compiler shut about uninitialized warning */
4956 	trackparam = NULL;
4957 
4958 	/* prepare trackreadset for refilling */
4959 	loop = g_list_first(trackreadset.trackparams);
4960 	while (loop) {
4961 		trackparam = loop->data;
4962 		g_free(trackparam->trackfile);
4963 		g_free(trackparam);
4964 		loop = loop->next;
4965 	}
4966 	g_list_free(trackreadset.trackparams);
4967 	trackreadset.trackparams = NULL;
4968 
4969 	trackreadset.nrtracks = 0;
4970 	trackreadset.cdsize = 0;
4971 	cdsize = 0;
4972 	g_free(trackreadset.tocfile);
4973 	trackreadset.tocfile=g_strdup(tocfile);
4974 	g_free(trackreadset.cdtitle);
4975 	trackreadset.cdtitle = g_strdup("");
4976 
4977 	dodebug(2, "reading cd toc file %s\n", tocfile);
4978 	/* open file */
4979 	fd = fopen(tocfile,"r");
4980 
4981 	if (fd == NULL) {
4982 		g_warning("Can't open file %s for reading\n",tocfile);
4983 		return 1;
4984 	}
4985 
4986 	for (;;) {
4987 		if (fgets(line,MAXLINE,fd) == NULL)
4988 			break;
4989 
4990 		dodebug(10,"read tocfile: %s", line);
4991 		/* skip empty or hashed lines */
4992 		strip_string(line);
4993 		if (*line == '#' || *line == '\0')
4994 			continue;
4995 
4996                 /* parse lines */
4997 		if (parse_config_line(line,id,value)) {
4998 			dodebug(10,"invalid line in tocfile");
4999 			fclose(fd);
5000 			return 1;
5001 		}
5002 
5003 		if (strcmp("cdtitle",id) == 0) {
5004 			g_free(trackreadset.cdtitle);
5005 			trackreadset.cdtitle = g_strdup(value);
5006 		}
5007 		if (strcmp("discid",id) == 0) {
5008 			g_free(trackreadset.cd_discid);
5009 			trackreadset.cd_discid = g_strdup(value);
5010 		}
5011 		if (strcmp("cdsize",id) == 0) {
5012 			trackreadset.cdsize = atoi(value);
5013 		}
5014 		if (strcmp("track",id) == 0) {
5015 			/* allocate memory */
5016 			trackparam = g_new0(track_read_param_t,1);
5017 			trackparam->trackinfo_index = -1;
5018 			trackparam->starttrack = atoi(value);
5019 			trackparam->endtrack = 0;
5020 			trackreadset.nrtracks++;
5021 		}
5022 		if (strcmp("type",id) == 0) {
5023 			trackparam->tracktype = atoi(value);
5024 		}
5025 		if (strcmp("size",id) == 0) {
5026 			trackparam->frames = atoi(value);
5027 			cdsize += trackparam->frames;
5028 		}
5029 		if (strcmp("startsec",id) == 0) {
5030 			trackparam->start_sec = atoi(value);
5031 		}
5032 		if (strcmp("file",id) == 0) {
5033 			g_free(trackparam->trackfile);
5034 			trackparam->trackfile = g_strdup(value);
5035 
5036 			trackreadset.trackparams = g_list_append(
5037 				trackreadset.trackparams, trackparam);
5038 		}
5039 
5040 	}
5041 
5042 	if (fclose(fd) != 0) {
5043 		/* error closing file */
5044 		return 1;
5045 	}
5046 
5047 	/* ok..all data read - now calculate the percentages */
5048 	loop = g_list_first(trackreadset.trackparams);
5049 	while(loop) {
5050 		trackparam = loop->data;
5051 		per = (gfloat)trackparam->frames / cdsize;
5052 		trackparam->percent = per;
5053 
5054 		loop = loop->next;
5055 	}
5056 
5057 	if (debug > 1)
5058 		print_trackreadset();
5059 
5060 	return 0;
5061 }
5062 
5063 
5064 /* write the info-file for each read track */
5065 
write_inf_file(track_read_param_t * trackparam)5066 gint write_inf_file(track_read_param_t *trackparam) {
5067 FILE *fd;
5068 time_t acttime;
5069 gchar timestr[MAXLINE];
5070 gchar tmp[MAXLINE];
5071 gchar tmp2[MAXLINE];
5072 gchar *p;
5073 gint tracknr;
5074 
5075 	/* get current time */
5076 	acttime = time((time_t *) 0);
5077 	strcpy(timestr,ctime(&acttime));
5078 	timestr[strlen(timestr)-1] = '\0';
5079 
5080 	if (trackparam->trackfile == NULL) {
5081 		return 1;
5082 	}
5083 
5084 	/* generate filename */
5085 	/* (remove extension and put .xinf there) */
5086 	strncpy(tmp,trackparam->trackfile,MAXLINE - 4);
5087 	p = rindex(tmp,'.');
5088 	if (!p) return 1;
5089 	*p = '\0';
5090 	strcpy(tmp2,tmp);
5091 	strcat(tmp2,XCDROAST_INFO_EXT);
5092 
5093 	dodebug(1,"writing inffile %s\n", tmp2);
5094 
5095         /* is a link? */
5096         if (check_islink(tmp2, NULL)) {
5097         	g_warning("Warning, won't overwrite a link at %s\n", tmp2);
5098 		return 1;
5099         }
5100 
5101 	/* write to file */
5102 	fd = fopen(tmp2,"w");
5103 
5104 	if (fd == NULL) {
5105 		g_warning("Can't open file %s for writing\n",tmp2);
5106 		return 1;
5107 	}
5108 
5109 	/* write header */
5110 	fputs("#\n",fd);
5111 	g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - INF-File\n",XCDROAST_VERSION);
5112 	fputs(tmp,fd);
5113 	g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
5114 	fputs(tmp,fd);
5115 	g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
5116 	fputs(tmp,fd);
5117 	fputs("#\n",fd);
5118 
5119 	tracknr = trackparam->trackinfo_index;
5120 
5121 	g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",trackparam->trackfile);
5122 	fputs(tmp,fd);
5123 	g_snprintf(tmp,MAXLINE,"track = %d of %d\n",
5124 			trackinfo[tracknr]->track_nr,
5125 			cdinfo.nr_tracks);
5126 	fputs(tmp,fd);
5127 	if (trackinfo[tracknr]->title) {
5128 		strcpy(tmp2,trackinfo[tracknr]->title);
5129 	} else {
5130 		strcpy(tmp2,"");
5131 	}
5132 	g_snprintf(tmp,MAXLINE,"title = \"%s\"\n",convert_escape(tmp2));
5133 	fputs(tmp,fd);
5134 	if (trackinfo[tracknr]->artist) {
5135 		strcpy(tmp2,trackinfo[tracknr]->artist);
5136 	} else {
5137 		strcpy(tmp2,"");
5138 	}
5139 	g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n",convert_escape(tmp2));
5140 	fputs(tmp,fd);
5141 	if (trackinfo[tracknr]->cddb_ttitle != NULL) {
5142 		strcpy(tmp2,trackinfo[tracknr]->cddb_ttitle);
5143 		g_snprintf(tmp,MAXLINE,"cddb_ttitle = \"%s\"\n",
5144 			convert_escape(tmp2));
5145 		fputs(tmp,fd);
5146 	}
5147 	g_snprintf(tmp,MAXLINE,"size = %d\n", trackinfo[tracknr]->size);
5148 	fputs(tmp,fd);
5149 	g_snprintf(tmp,MAXLINE,"type = %d\n", trackinfo[tracknr]->type);
5150 	fputs(tmp,fd);
5151 	g_snprintf(tmp,MAXLINE,"rec_type = %d\n", trackinfo[tracknr]->rec_type);
5152 	fputs(tmp,fd);
5153 	g_snprintf(tmp,MAXLINE,"preemp = %d\n", trackinfo[tracknr]->preemp);
5154 	fputs(tmp,fd);
5155 	g_snprintf(tmp,MAXLINE,"copyperm = %d\n", trackinfo[tracknr]->copyperm);
5156 	fputs(tmp,fd);
5157 	g_snprintf(tmp,MAXLINE,"stereo = %d\n", trackinfo[tracknr]->stereo);
5158 	fputs(tmp,fd);
5159 	fputs("# from CD:\n",fd);
5160 	if (cdinfo.title) {
5161 		strcpy(tmp2,cdinfo.title);
5162 	} else {
5163 		strcpy(tmp2,"");
5164 	}
5165 	g_snprintf(tmp,MAXLINE,"cd_title = \"%s\"\n",convert_escape(tmp2));
5166 	fputs(tmp,fd);
5167 	if (cdinfo.artist) {
5168 		strcpy(tmp2,cdinfo.artist);
5169 	} else {
5170 		strcpy(tmp2,"");
5171 	}
5172 	g_snprintf(tmp,MAXLINE,"cd_artist = \"%s\"\n",convert_escape(tmp2));
5173 	fputs(tmp,fd);
5174 	if (cdinfo.cddb_dtitle != NULL) {
5175 		strncpy(tmp2,cdinfo.cddb_dtitle, MAXLINE);
5176 		g_snprintf(tmp,MAXLINE,"cd_cddb_dtitle = \"%s\"\n",
5177 			convert_escape(tmp2));
5178 		fputs(tmp,fd);
5179 	}
5180 
5181 	strncpy(tmp2,cdinfo.cddb_discid, MAXLINE);
5182 	g_snprintf(tmp,MAXLINE,"cd_discid = \"%s\"\n",
5183 		convert_escape(tmp2));
5184 	fputs(tmp,fd);
5185 
5186 	if (fclose(fd) != 0) {
5187 		/* error closing file */
5188 		return 1;
5189 	}
5190 
5191 	return 0;
5192 }
5193 
5194 
5195 /* read the titles/artists from an inf-file */
5196 
get_inf_tracktitle(gchar * path,image_files_t * entry)5197 gint get_inf_tracktitle(gchar *path, image_files_t *entry) {
5198 FILE *fd;
5199 gchar line[MAXLINE];
5200 gchar id[MAXLINE];
5201 gchar value[MAXLINE];
5202 gchar tmp[MAXLINE];
5203 gchar tmp2[MAXLINE];
5204 gchar *p;
5205 gint istoc;
5206 
5207 	/* generate filename */
5208 	/* (remove extension and put .inf there) */
5209 	istoc = 0;
5210 	strncpy(tmp,path,MAXLINE - 4);
5211 	p = rindex(tmp,'.');
5212 	if (!p) return 1;
5213 	if (strcmp(p,".toc") == 0) {
5214 		/* we are currently handling a toc file */
5215 		istoc = 1;
5216 	}
5217 	*p = '\0';
5218 	strcpy(tmp2,tmp);
5219 	strcat(tmp2,XCDROAST_INFO_EXT);
5220 
5221 	if (istoc)
5222 		strcpy(tmp2,path);
5223 
5224 	dodebug(1, "reading titles from %s\n", tmp2);
5225 
5226 	if ((fd = fopen(tmp2,"r")) == NULL) {
5227 		return 1;
5228 	}
5229 
5230 	for (;;) {
5231 		if (fgets(line,MAXLINE,fd) == NULL)
5232 			break;
5233 
5234 		dodebug(10,"inffile: %s", line);
5235 
5236 		/* skip empty or hashed lines */
5237 		strip_string(line);
5238 		if (*line == '#' || *line == '\0')
5239 			continue;
5240 
5241                 /* parse lines */
5242 		if (parse_config_line(line,id,value)) {
5243 			dodebug(10,"invalid line in infofile");
5244 			fclose(fd);
5245 			return 1;
5246 		}
5247 
5248 		/* if we are handling a toc file only the title entry
5249 		   is interesting */
5250 		if (istoc) {
5251 			if (strcmp("cdtitle",id) == 0) {
5252 				g_free(entry->cddb_ttitle);
5253 				entry->cddb_ttitle = g_strdup(value);
5254 				break;
5255 			}
5256 		}
5257 
5258 		if (strcmp("track",id) == 0) {
5259 			/* extract track nr */
5260 			p = strtok(value," ");
5261 			if (p != NULL) {
5262 				entry->from_track = atoi(p);
5263 			}
5264 		}
5265 
5266 		if (strcmp("title",id) == 0) {
5267 			g_free(entry->title);
5268 			entry->title = g_strdup(value);
5269 		}
5270 		if (strcmp("artist",id) == 0) {
5271 			g_free(entry->artist);
5272 			entry->artist = g_strdup(value);
5273 		}
5274 		if (strcmp("cddb_ttitle",id) == 0) {
5275 			g_free(entry->cddb_ttitle);
5276 			entry->cddb_ttitle = g_strdup(value);
5277 		}
5278 		if (strcmp("cd_discid",id) == 0) {
5279 			g_free(entry->cd_discid);
5280 			entry->cd_discid = g_strdup(value);
5281 		}
5282 		if (strcmp("last_session_start",id) == 0) {
5283 			entry->last_session_start = atoi(value);
5284 		}
5285 		if (strcmp("next_session_start",id) == 0) {
5286 			entry->next_session_start = atoi(value);
5287 		}
5288 	}
5289 
5290 	if (fclose(fd) != 0) {
5291 		return 1;
5292 	}
5293 
5294 	return 0;
5295 }
5296 
5297 
5298 /* call cdrecord -prcap */
5299 
fill_device_info(gint devnr,GtkWidget * txt)5300 void fill_device_info(gint devnr, GtkWidget *txt) {
5301 gchar line[MAXLINE];
5302 gchar tmp[MAXLINE];
5303 gchar tmp2[MAXLINE];
5304 gchar tmp3[MAXLINE];
5305 FILE *fpin;
5306 gchar *p;
5307 gint errcount;
5308 
5309 	/* get bus,id,lun string */
5310 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5311 		g_error("non existing cdrom?");
5312 	}
5313 
5314 	/* build command line */
5315 	get_wrap_path_cdrecord(tmp3);
5316 	g_snprintf(line,MAXLINE,"%s %s -prcap 2>&1",
5317 		tmp3,tmp);
5318 
5319 	dodebug(1, "calling: %s\n", line);
5320 	dolog(3, "Executing: %s\n", line);
5321 
5322         if ((fpin = popen(line,"r")) == NULL) {
5323                 g_error("popen error\n");
5324         }
5325 
5326 	errcount = 0;
5327         for (;;) {
5328                 if (fgets(line,MAXLINE,fpin) == NULL)
5329                         break;
5330 		strcpy(tmp,line);
5331 
5332 		dodebug(10, "prcap: %s", line);
5333 
5334 		/* error condition? */
5335 		p = strtok(tmp,":");
5336 		if (p != NULL) {
5337 			p = strtok(NULL,"");
5338 			if (p != NULL) {
5339 				strcpy(tmp2,p);
5340 				strip_string(tmp2);
5341 				if (strncmp(tmp2,"I/O error",9) == 0) {
5342 					errcount++;
5343 					/* more then once an i/o-error? */
5344 					if (errcount > 1)
5345 						break;
5346 				}
5347 			}
5348 		}
5349 		convert_for_gtk2_textwidget(line);
5350 		gtk_text_insert(GTK_TEXT(txt),
5351 			fixedfont,NULL,NULL, line, strlen(line));
5352         }
5353 
5354         if (pclose(fpin) == -1) {
5355                 g_error("pclose error\n");
5356         }
5357 }
5358 
5359 
5360 /* eject CD in drive */
5361 
eject_cd(gint devnr)5362 void eject_cd(gint devnr) {
5363 gchar line[MAXLINE];
5364 gchar tmp[MAXLINE];
5365 gchar tmp2[MAXLINE];
5366 gchar tmp3[MAXLINE];
5367 FILE *fpin;
5368 gchar *p;
5369 gint errcount;
5370 
5371 	/* get bus,id,lun string */
5372 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5373 		g_error("non existing cdrom?");
5374 	}
5375 
5376 	/* build command line */
5377 	get_wrap_path_cdrecord(tmp3);
5378 	g_snprintf(line,MAXLINE,"%s %s -eject 2>&1",
5379 		tmp3,tmp);
5380 
5381 	dodebug(1, "calling: %s\n", line);
5382 
5383         if ((fpin = popen(line,"r")) == NULL) {
5384                 g_error("popen error\n");
5385         }
5386 
5387 	/* do actually nothing here ... */
5388 	errcount = 0;
5389         for (;;) {
5390                 if (fgets(line,MAXLINE,fpin) == NULL)
5391                         break;
5392 		strcpy(tmp,line);
5393 
5394 		/* error condition? */
5395 		p = strtok(tmp,":");
5396 		if (p != NULL) {
5397 			p = strtok(NULL,"");
5398 			if (p != NULL) {
5399 				strcpy(tmp2,p);
5400 				strip_string(tmp2);
5401 				if (strncmp(tmp2,"I/O error",9) == 0) {
5402 					errcount++;
5403 					/* more then once an i/o-error? */
5404 					if (errcount > 1)
5405 						break;
5406 				}
5407 			}
5408 		}
5409         }
5410 
5411         if (pclose(fpin) == -1) {
5412                 g_error("pclose error\n");
5413         }
5414 }
5415 
5416 
5417 /* load CD in drive */
5418 
load_cd(gint devnr)5419 void load_cd(gint devnr) {
5420 gchar line[MAXLINE];
5421 gchar tmp[MAXLINE];
5422 gchar tmp2[MAXLINE];
5423 gchar tmp3[MAXLINE];
5424 FILE *fpin;
5425 gchar *p;
5426 gint errcount;
5427 
5428 	/* get bus,id,lun string */
5429 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5430 		g_error("non existing cdrom?");
5431 	}
5432 
5433 	/* build command line */
5434 	get_wrap_path_cdrecord(tmp3);
5435 	g_snprintf(line,MAXLINE,"%s %s -load 2>&1",
5436 		tmp3,tmp);
5437 
5438 	dodebug(1, "calling: %s\n", line);
5439 
5440         if ((fpin = popen(line,"r")) == NULL) {
5441                 g_error("popen error\n");
5442         }
5443 
5444 	/* do actually nothing here ... */
5445 	errcount = 0;
5446         for (;;) {
5447                 if (fgets(line,MAXLINE,fpin) == NULL)
5448                         break;
5449 		strcpy(tmp,line);
5450 
5451 		/* error condition? */
5452 		p = strtok(tmp,":");
5453 		if (p != NULL) {
5454 			p = strtok(NULL,"");
5455 			if (p != NULL) {
5456 				strcpy(tmp2,p);
5457 				strip_string(tmp2);
5458 				if (strncmp(tmp2,"I/O error",9) == 0) {
5459 					errcount++;
5460 					/* more then once an i/o-error? */
5461 					if (errcount > 1)
5462 						break;
5463 				}
5464 			}
5465 		}
5466         }
5467 
5468         if (pclose(fpin) == -1) {
5469                 g_error("pclose error\n");
5470         }
5471 }
5472 
5473 
5474 /* use cdrecord to get the leadout of a TOC */
5475 /* (used for DVDs where cddawav fails ) */
5476 
get_cdrecord_toc(gint devnr)5477 static gint get_cdrecord_toc(gint devnr) {
5478 gchar line[MAXLINE];
5479 gchar tmp[MAXLINE];
5480 gchar tmp2[MAXLINE];
5481 gchar tmp3[MAXLINE];
5482 gchar *p;
5483 FILE *fpin;
5484 gint found;
5485 
5486 	/* get bus,id,lun string */
5487 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5488 		g_error("non existing cdrom?");
5489 	}
5490 
5491 	found = 0;
5492 
5493 	/* build command line */
5494 	get_wrap_path_cdrecord(tmp3);
5495 	g_snprintf(line,MAXLINE,"%s %s -toc 2>&1",
5496 		tmp3,tmp);
5497 
5498 	dodebug(1, "calling: %s\n", line);
5499 
5500         if ((fpin = popen(line,"r")) == NULL) {
5501                 g_error("popen error\n");
5502         }
5503 
5504         for (;;) {
5505                 if (fgets(line,MAXLINE,fpin) == NULL)
5506                         break;
5507 		strcpy(tmp,line);
5508 		dodebug(10, "cdrecord -toc: %s", line);
5509         }
5510 
5511         if (pclose(fpin) == -1) {
5512                 g_error("pclose error\n");
5513         }
5514 
5515 	/* tmp is now the last line of the output */
5516 	if (strncmp(tmp,"track:lout", 10) == 0) {
5517 
5518 		/* extract leadout sector */
5519 		p = strtok(tmp,"(");
5520 		if (p) {
5521 			strncpy(tmp2,p,MAXLINE);
5522 			p = rindex(tmp2,':');
5523 			if (p) {
5524 				strcpy(tmp,p+1);
5525 				strip_string(tmp);
5526 				found = atoi(tmp);
5527 			}
5528 		}
5529 	}
5530 
5531 	return found;
5532 }
5533 
5534 
5535 /* call cdrecord -atip */
5536 
get_atip_info(gint devnr,GtkWidget * txt)5537 void get_atip_info(gint devnr, GtkWidget *txt) {
5538 gchar line[MAXLINE];
5539 gchar tmp[MAXLINE];
5540 gchar tmp2[MAXLINE];
5541 gchar tmp3[MAXLINE];
5542 gchar *p;
5543 FILE *fpin;
5544 gint found_atip,errcount;
5545 
5546 	found_atip = 0;
5547 
5548 	/* get bus,id,lun string */
5549 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5550 		g_error("non existing cdrom?");
5551 	}
5552 
5553        	get_wrap_path("CDRECORD", tmp3);
5554 	g_snprintf(line,MAXLINE,"%s %s -atip 2>&1",
5555 		tmp3,tmp);
5556 
5557 	dodebug(1,"calling: %s\n", line);
5558 	dolog(3, "Executing: %s\n", line);
5559 
5560         if ((fpin = popen(line,"r")) == NULL) {
5561                 g_error("popen error\n");
5562         }
5563 
5564 	/* syntax for dvd-atip is different */
5565 	if (is_dvdwriter(curset.writer_devnr)) {
5566 		found_atip = 1;
5567 	}
5568 
5569 	errcount = 0;
5570         for (;;) {
5571                 if (fgets(line,MAXLINE,fpin) == NULL)
5572                         break;
5573 		strcpy(tmp,line);
5574 
5575 		dodebug(10,"atip: %s", line),
5576 
5577 		/* error condition? */
5578 		p = strtok(tmp,":");
5579 		if (p != NULL) {
5580 			p = strtok(NULL,"");
5581 			if (p != NULL) {
5582 				strcpy(tmp2,p);
5583 				strip_string(tmp2);
5584 				if (strncmp(tmp2,"I/O error",9) == 0) {
5585 					errcount++;
5586 					/* more then once an i/o-error? */
5587 					if (errcount > 1)
5588 						break;
5589 				}
5590 			}
5591 		}
5592 
5593 		/* look for atip-signature */
5594 		if (strncmp(line,"ATIP",4) == 0) {
5595 			found_atip = 1;
5596 		}
5597 		if (found_atip) {
5598 			gtk_text_insert(GTK_TEXT(txt),
5599 				fixedfont,NULL,NULL, line, strlen(line));
5600 		}
5601         }
5602 
5603 	/* no atip-information available? */
5604 	if (found_atip == 0) {
5605 		/* generate error-message */
5606 		strncpy(line,_("\nNo ATIP-Information available.\n\n(Possible reasons: No CD-R/RW loaded or your device\n does not support reading ATIP info)"),MAXLINE);
5607 		convert_for_gtk2_textwidget(line);
5608 		gtk_text_insert(GTK_TEXT(txt),
5609 			NULL,NULL,NULL, line, strlen(line));
5610 	}
5611 
5612         if (pclose(fpin) == -1) {
5613                 g_error("pclose error\n");
5614         }
5615 }
5616 
5617 
5618 /* get output of cdrecord -msinfo */
5619 
read_msinfo_out(gpointer data,gint source,GdkInputCondition cond)5620 static void read_msinfo_out(gpointer data, gint source, GdkInputCondition cond) {
5621 gint n;
5622 gint ret;
5623 gchar line[MAXLINE];
5624 gchar tmp[MAXLINE];
5625 gint nr1, nr2;
5626 gchar *p;
5627 
5628         n = read_line(source, line, MAXLINE);
5629 
5630         /* finished? */
5631         if (n <= 0) {
5632                 gtk_input_remove(readcdda_callback);
5633                 gtk_input_remove(readcdda_callback2);
5634 
5635                 /* pick up return status of child */
5636 		wait(&ret);
5637 
5638                 read_done = WEXITSTATUS(ret);
5639 
5640 		dodebug(10,"Finished in read_msinfo_out with status: %d\n",
5641 			read_done);
5642 		return;
5643 	}
5644 
5645         dodebug(10, "msinfo (stdout): %s\n", line);
5646 
5647          /* look for the reload media command */
5648          if (strcmp(line,"Re-load disk and hit <CR>") == 0) {
5649                 cdrecord_reload = 1;
5650 		return;
5651 	}
5652 
5653 	strcpy(tmp, line);
5654 
5655 	/* parse msinfo output */
5656 	p = strtok(tmp,",");
5657 	if (p) {
5658 		nr1 = atoi(p);
5659 		p = strtok(NULL,"");
5660 		if (p) {
5661 			nr2 = atoi(p);
5662 
5663 			/* if parsing was sucessful use new values */
5664 			msinfo_nr1 = nr1;
5665 			msinfo_nr2 = nr2;
5666 		}
5667 	}
5668 }
5669 
5670 
5671 /* get output of cdrecord -msinfo (stderr) */
5672 
read_msinfo_stderr(gpointer data,gint source,GdkInputCondition cond)5673 static void read_msinfo_stderr(gpointer data, gint source, GdkInputCondition cond) {
5674 gint n;
5675 gint ret;
5676 gchar line[MAXLINE];
5677 
5678 
5679 	n = read_line(source, line, MAXLINE);
5680 
5681         /* finished? */
5682         if (n <= 0) {
5683                 gtk_input_remove(readcdda_callback);
5684                 gtk_input_remove(readcdda_callback2);
5685 
5686                 /* pick up return status of child */
5687                 wait(&ret);
5688 
5689                 read_done = WEXITSTATUS(ret);
5690 
5691 		return;
5692 	}
5693 
5694 	dodebug(10, "msinfo (stderr): %s\n", line);
5695 }
5696 
5697 
5698 /* call cdrecord -msinfo */
5699 /* returns the start sector and the next writeable adress */
5700 /* or both values -1 when no offset could be found...*/
5701 
get_msinfo_info(gint devnr,gint * nr1,gint * nr2)5702 void get_msinfo_info(gint devnr, gint *nr1, gint *nr2) {
5703 gchar line[MAXLINE];
5704 gchar tmp[MAXLINE];
5705 gchar tmp3[MAXLINE];
5706 gint read_out, read_err;
5707 
5708         /* if another msinfo running, ignore */
5709         if (read_done == 999) {
5710                 return;
5711         }
5712 
5713         /* mark our msinfo-process as running */
5714         read_done = 999;
5715         read_output_ctrl = 0;
5716         readerr_count = 0;
5717         cdrecord_reload = 0;
5718 	msinfo_nr1 = -1;
5719 	msinfo_nr2 = -1;
5720 
5721 	/* get bus,id,lun string */
5722 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5723 		g_error("non existing cdrom?");
5724 	}
5725 
5726 	/* build command line */
5727 	get_wrap_path_cdrecord(tmp3);
5728 	g_snprintf(line,MAXLINE,"%s %s -msinfo",
5729 		tmp3,tmp);
5730 
5731 	dodebug(1,"calling: %s\n", line);
5732 	dolog(3, "Executing: %s\n", line);
5733 
5734 	readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,line,1);
5735 	readcdda_pid2 = -1;
5736 
5737         fcntl(read_out, F_SETFL, O_NONBLOCK);
5738         fcntl(read_err, F_SETFL, O_NONBLOCK);
5739 
5740         readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
5741                 (GdkInputFunction) read_msinfo_out, NULL);
5742         readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
5743                 (GdkInputFunction) read_msinfo_stderr, NULL);
5744 
5745         /* now wait until msinfo is finished */
5746         while (read_done == 999) {
5747                 wait_and_process_events();
5748 
5749                 /* check if writer is waiting for reload medium */
5750                 if (cdrecord_reload > 0) {
5751                         cdrecord_reload = 0;
5752                         show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
5753 
5754                         /* now send CR to cdrecord to let it continue */
5755                         if (write(cdrecord_stdin, "\n", 1) != 1) {
5756                                 g_warning("write error to cdrecord pipe\n");
5757                         }
5758                 }
5759 
5760 	}
5761 
5762         close(read_err);
5763         close(read_out);
5764 	close(cdrecord_stdin);
5765 
5766 	dodebug(2,"received msinfo: %d,%d\n", msinfo_nr1, msinfo_nr2);
5767 
5768 	/* workaround for drives reporting 0,0 instead of -1,-1 */
5769 	if (msinfo_nr1 == 0 && msinfo_nr2 == 0) {
5770 		msinfo_nr1 = -1;
5771 		msinfo_nr2 = -1;
5772 	}
5773 
5774 	*nr1 = msinfo_nr1;
5775 	*nr2 = msinfo_nr2;
5776 }
5777 
5778 
5779 /* interpret output of blank=help and sort into memory structure */
5780 
parse_blankmode(gchar * line)5781 static void parse_blankmode(gchar *line) {
5782 gchar tmp[MAXLINE];
5783 gchar tmp2[MAXLINE];
5784 gchar drv[MAXLINE];
5785 gchar *p1;
5786 gint n;
5787 
5788 	if (strncmp(line,"Blanking options:",17) != 0 ) {
5789 
5790 		strcpy(tmp,line);
5791 		strip_string(tmp);
5792 
5793 		p1=strtok(tmp," \t");
5794 		strcpy(drv,p1);
5795 		/* now drv contains the driver name */
5796 
5797 		p1=strtok(NULL,"");
5798 		strcpy(tmp2,p1);
5799 		strip_string(tmp2);
5800 		/* now tmp2 contains the description */
5801 
5802 		/* now get the description of last mode to ensure
5803 		   we dont have double modes */
5804 		if (drvcount != 0) {
5805 			if (strcmp(tmp2,blankmodes[drvcount-1]->desc) == 0) {
5806 				/* double drive mode - ignore */
5807 				return;
5808 			}
5809 		}
5810 
5811 		/* allocate structure */
5812 		blankmodes[drvcount]=g_new(writer_driver_t,1);
5813 
5814 		n = strlen(drv)+1;
5815 		blankmodes[drvcount]->driver=g_new(gchar,n);
5816 		strcpy(blankmodes[drvcount]->driver,drv);
5817 
5818 		n = strlen(tmp2)+1;
5819 		blankmodes[drvcount]->desc=g_new(gchar,n);
5820 		strcpy(blankmodes[drvcount]->desc,tmp2);
5821 
5822 		drvcount++;
5823 		if (drvcount >= MAXBLANKMODES) {
5824 			g_error("Error: More than %d blank modes found\n",
5825 				MAXBLANKMODES);
5826 		}
5827 	}
5828 }
5829 
5830 
5831 /* print memory-structure with drivers (debug purposes) */
5832 
print_blankmodes()5833 static void print_blankmodes() {
5834 gint count;
5835 
5836 	dodebug(2,"--------- cdrecord blankmodes-structure --------\n");
5837 	count = 0;
5838 	while(blankmodes[count] != NULL) {
5839 		dodebug(2,"%s:%s\n",
5840 			blankmodes[count]->driver,
5841 			blankmodes[count]->desc);
5842 
5843 		count++;
5844 	}
5845 }
5846 
5847 
5848 /* call cdrecord blank=help */
5849 
scanblankmodes()5850 void scanblankmodes() {
5851 gchar line[MAXLINE];
5852 FILE *fpin;
5853 
5854 	/* allocate memory */
5855 	blankmodes = g_new0(writer_driver_t *,MAXBLANKMODES);
5856 	drvcount = 0;
5857 
5858 	get_wrap_path_cdrecord(line);
5859 	strcat(line," blank=help 2>&1");
5860 
5861 	dodebug(1, "calling: %s\n", line);
5862 
5863         if ((fpin = popen(line,"r")) == NULL) {
5864                 g_error("popen error\n");
5865         }
5866 
5867         for (;;) {
5868                 if (fgets(line,MAXLINE,fpin) == NULL)
5869                         break;
5870 		dodebug(10, "blankmodes: %s", line);
5871                 parse_blankmode(line);
5872         }
5873 
5874         if (pclose(fpin) == -1) {
5875                 g_error("pclose error\n");
5876         }
5877 
5878 
5879 	if (debug) print_blankmodes();
5880 }
5881 
5882 
5883 /* open a file and read one sector into a memory-buffer */
5884 /* return 1 on success */
5885 
read_info_sector_from_file(gchar * isoname,gchar * buf,gint bsize)5886 gint read_info_sector_from_file(gchar *isoname, gchar *buf, gint bsize) {
5887 gint fd;
5888 
5889 	dodebug(1, "read iso header from %s\n", isoname);
5890 
5891 	fd = open (isoname, O_RDONLY, 0);
5892 	if (fd == -1) {
5893 		return 0;
5894 	}
5895 
5896 	/* forward to info-sector */
5897 	if(lseek(fd, 32768, SEEK_SET) < 0) {
5898 		close(fd);
5899 		return 0;
5900 	}
5901 
5902 	/* read one sector */
5903 	if (read(fd, buf, bsize) != bsize) {
5904 		close(fd);
5905 		return 0;
5906 	}
5907 
5908 	close(fd);
5909 	return 1;
5910 }
5911 
5912 
5913 /* call readcd to read the info-sector from a data-track into a
5914    memory buffer. return 1 if all ok */
5915 
read_info_sector_from_dev(gint devnr,gchar * buf,gint bsize,gint startsector)5916 gint read_info_sector_from_dev(gint devnr, gchar *buf, gint bsize, gint startsector) {
5917 gchar tmp[MAXLINE];
5918 gchar tmp2[MAXLINE];
5919 gchar cmd[MAXLINE];
5920 FILE *fpin;
5921 gint s1, s2;
5922 
5923 	/* get bus,id,lun string */
5924 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
5925 		g_error("non existing cdrom?");
5926 	}
5927 
5928         s1 = startsector+16;
5929         s2 = startsector+17;
5930 
5931 	/* build command-line */
5932 	get_wrap_path("READCD",tmp2);
5933 	g_snprintf(cmd,MAXLINE,"%s %s sectors=%d-%d -s f=- 2>/dev/null",
5934 		tmp2, tmp, s1, s2);
5935 
5936 	dodebug(1, "calling: %s\n", cmd);
5937 
5938 	if ((fpin = popen(cmd,"r")) == NULL) {
5939 		g_error("popen error\n");
5940 	}
5941 
5942 	/* read into buffer */
5943 	if (fread(buf, bsize, 1, fpin) != 1) {
5944 		pclose(fpin);
5945 		return 0;
5946 	}
5947 
5948 	if (pclose(fpin) == -1) {
5949 		g_error("pclose error\n");
5950 	}
5951 
5952 	return 1;
5953 }
5954 
5955 
5956 /* get output of cdrecord -blank */
5957 
read_blank_out(gpointer data,gint source,GdkInputCondition cond)5958 static void read_blank_out(gpointer data, gint source, GdkInputCondition cond) {
5959 gint n;
5960 gint ret;
5961 gchar line[MAXLINE];
5962 gchar tmp[MAXLINE];
5963 
5964         n = read_line(source, line, MAXLINE);
5965 
5966 	/* finished? */
5967 	if (n <= 0) {
5968 
5969 		gtk_input_remove(readcdda_callback);
5970 		gtk_input_remove(readcdda_callback2);
5971 
5972 		/* pick up return status of child */
5973 		wait(&ret);
5974 
5975 		read_done = WEXITSTATUS(ret);
5976 
5977 		/* perhaps the are-you-sure-you-want-to-abort dialog
5978 		   is still running? remove to be sure we can continue */
5979 		if (dialog_done == 999) {
5980 			dialog_done = -1;
5981 		}
5982 
5983 		/* or cdrecord died by signal? e.g. SIGALRM */
5984 		if (WIFSIGNALED(ret) && read_done == 0) {
5985 
5986 			/* most likely invalid prodvd key */
5987 			if (curset.isProDVD) {
5988 				strncpy(tmp, "\nReceived ALARM from cdrecord-ProDVD. Aborting blank...\nInvalid ProDVD key?\n", MAXLINE);
5989 
5990 				convert_for_gtk2_textwidget(tmp);
5991 				gtk_text_insert(GTK_TEXT(readtrack_textview),
5992 					fixedfont,NULL,NULL,tmp, strlen(tmp));
5993 				read_done = 1;
5994 			}
5995 		}
5996 
5997                 dodebug(10,"Finished in read_blank_out with status: %d\n",
5998                         read_done);
5999 		return;
6000 	}
6001 
6002 	dodebug(10, "blank (stdout): %s\n", line);
6003 
6004         strip_string(line);
6005 
6006          /* look for the reload media command */
6007          if (strcmp(line,"Re-load disk and hit <CR>") == 0) {
6008                  cdrecord_reload = 1;
6009                  /* if there was a fileselector running, cancel it */
6010                  dialog_done3 = -1;
6011                  return;
6012          }
6013 
6014 	/* skip all lines that end with "seconds." */
6015 	if (n > 8) {
6016 		if (strstr(line, "seconds.")) {
6017 			return;
6018 		}
6019 	}
6020 
6021 	strcpy(tmp,line);
6022 	strcat(tmp,"\n");
6023 
6024 	convert_for_gtk2_textwidget(tmp);
6025 	gtk_text_insert(GTK_TEXT(readtrack_textview),
6026 		fixedfont,NULL,NULL,tmp, strlen(tmp));
6027 
6028 }
6029 
6030 
6031 /* get output of cdrecord -blank (stderr) */
6032 
read_blank_stderr(gpointer data,gint source,GdkInputCondition cond)6033 static void read_blank_stderr(gpointer data, gint source, GdkInputCondition cond) {
6034 gint n;
6035 gint ret;
6036 gchar line[MAXLINE];
6037 gchar tmp[MAXLINE];
6038 gchar tmp2[MAXLINE];
6039 gchar *p;
6040 
6041 	n = read_line(source, line, MAXLINE);
6042 
6043 	/* finished? */
6044 	if (n <= 0) {
6045 
6046                	gtk_input_remove(readcdda_callback);
6047                	gtk_input_remove(readcdda_callback2);
6048 
6049                	/* pick up return status of child */
6050                	wait(&ret);
6051 
6052                	read_done = WEXITSTATUS(ret);
6053 
6054                	/* perhaps the are-you-sure-you-want-to-abort dialog
6055                    is still running? remove to be sure we can continue */
6056                	if (dialog_done == 999) {
6057                        	dialog_done = -1;
6058                	}
6059 
6060                 dodebug(10,"Finished in read_blank_stderr with status: %d\n",
6061                         read_done);
6062 
6063 		return;
6064 	}
6065 
6066 	dodebug(10, "blank (stderr): %s\n", line);
6067 
6068 	/* check if we have an medium-i/o-error */
6069 	strcpy(tmp,line);
6070 	p = strtok(tmp,":");
6071 	if (p != NULL) {
6072 		p = strtok(NULL,"");
6073 		if (p != NULL) {
6074 			strcpy(tmp2,p);
6075 			strip_string(tmp2);
6076 			if (strncmp(tmp2,"I/O error",9) == 0) {
6077 				readerr_count++;
6078 				/* more then once an i/o-error? */
6079 				if (readerr_count > 1) {
6080 					kill_readcdda();
6081 					dialog_done2 = 999;
6082 					read_output_ctrl = 2;
6083 				}
6084 			}
6085 		}
6086 	}
6087 
6088 	/* check if we got an error because of no disk */
6089 	if (n > 21) {
6090 		strcpy(tmp, line+(strlen(line)-21));
6091 		if (strcmp(tmp, "No disk / Wrong disk!") == 0) {
6092 			/* mark we got no disk */
6093 			read_output_ctrl = 2;
6094 		}
6095 	}
6096 
6097 	strcpy(tmp,line);
6098 	strcat(tmp,"\n");
6099 
6100 	convert_for_gtk2_textwidget(tmp);
6101 	gtk_text_insert(GTK_TEXT(readtrack_textview),
6102 		fixedfont,NULL,NULL,tmp, strlen(tmp));
6103 
6104 }
6105 
6106 
6107 /* call cdrecord -blank */
6108 
start_blanking_process(gint devnr,GtkWidget * text_window)6109 gint start_blanking_process(gint devnr, GtkWidget *text_window) {
6110 char tmp[MAXLINE];
6111 char tmp2[MAXLINE];
6112 char tmp3[MAXLINE];
6113 char tmp4[MAXLINE];
6114 char tmp5[MAXLINE];
6115 char tmp6[MAXLINE];
6116 char cmd[MAXLINE];
6117 gint read_out, read_err;
6118 gint ret;
6119 
6120 	/* if another blank running, ignore */
6121 	if (read_done == 999) {
6122 		return -1;
6123 	}
6124 
6125 	/* mark our blanking-process as running */
6126 	read_done = 999;
6127 	read_output_ctrl = 0;
6128 	readerr_count = 0;
6129 	cdrecord_reload = 0;
6130 
6131 	/* save text-window */
6132 	readtrack_textview = text_window;
6133 
6134 	/* get bus,id,lun string */
6135 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
6136 		g_error("non existing cdrom?");
6137 	}
6138 
6139 	/* get blankmode and settings */
6140 	strcpy(tmp2, blankmodes[curset.blankmode]->driver);
6141 
6142 	strcpy(tmp3,"");
6143 	if (curset.blank_force) {
6144 		strcat(tmp3, "-force ");
6145 	}
6146 	if (curset.blank_eject) {
6147 		strcat(tmp3, "-eject ");
6148 	}
6149         if (curset.writeignsize == 1) {
6150                 strcat(tmp3,"-ignsize ");
6151         }
6152         if (curset.writeimmed == 1) {
6153                 strcat(tmp3,"-immed ");
6154         }
6155 
6156         if (get_cur_writer_speed() >= 0) {
6157                 g_snprintf(tmp4,MAXLINE,"speed=%d ", get_cur_writer_speed());
6158                 strcat(tmp3, tmp4);
6159         }
6160 
6161         get_wrap_path("CDRECORD", tmp5);
6162 
6163 	g_snprintf(cmd, MAXLINE,
6164 		"%s %s gracetime=%d -v %sblank=%s",
6165 		tmp5, tmp, get_gracetime(), tmp3, tmp2);
6166 
6167 	dodebug(1, "spawning: %s\n",cmd);
6168 	dolog(1, "Blanking CD with mode %s\n",tmp2);
6169 	dolog(3, "Executing: %s\n", cmd);
6170 
6171 	readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,cmd,1);
6172 	readcdda_pid2 = -1;
6173 
6174 	fcntl(read_out, F_SETFL, O_NONBLOCK);
6175 	fcntl(read_err, F_SETFL, O_NONBLOCK);
6176 
6177 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
6178 		(GdkInputFunction) read_blank_out, NULL);
6179 	readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
6180 		(GdkInputFunction) read_blank_stderr, NULL);
6181 
6182 	/* now wait until blank is finished */
6183 	while (read_done == 999) {
6184 		wait_and_process_events();
6185 
6186                 /* check if writer is waiting for reload medium */
6187                 if (cdrecord_reload > 0) {
6188                         cdrecord_reload = 0;
6189                         show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
6190 
6191                         /* now send CR to cdrecord to let it continue */
6192                         if (write(cdrecord_stdin, "\n", 1) != 1) {
6193                                 g_warning("write error to cdrecord pipe\n");
6194                         }
6195                 }
6196 
6197 		/* check if somebody clicked on cancel */
6198 		if (dialog_done2 != 999) {
6199 			ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
6200 				T_YES, T_NO, NULL, 1);
6201 			if (ret == 0) {
6202 			 	/* really abort */
6203 				kill_readcdda();
6204 				/* mark we aborted */
6205 				read_output_ctrl = 1;
6206 				dialog_done2 = 999;
6207 			} else {
6208 				/* not abort - undo button press */
6209 				dialog_done2 = 999;
6210 			}
6211 		}
6212 	}
6213 
6214 	close(read_err);
6215 	close(read_out);
6216 	close(cdrecord_stdin);
6217 
6218 	/* no disk */
6219 	if (read_output_ctrl == 2) {
6220 		gtk_text_insert(GTK_TEXT(readtrack_textview),
6221 			fixedfont,NULL,NULL,"\n",1);
6222 
6223 		strncpy(tmp6, _("No disk or wrong disk loaded."), MAXLINE);
6224 		convert_for_gtk2_textwidget(tmp6);
6225 		gtk_text_insert(GTK_TEXT(readtrack_textview),
6226 			fixedfont,NULL,NULL,tmp6,strlen(tmp6));
6227 		gtk_text_insert(GTK_TEXT(readtrack_textview),
6228 			fixedfont,NULL,NULL,"\n\n",2);
6229 	}
6230 
6231 	/* error while blanking */
6232 	if (read_done != 0) {
6233 		return 1;
6234 	}
6235 
6236 	/* we killed the process */
6237 	if (read_output_ctrl == 1) {
6238 		return 2;
6239 	}
6240 
6241 	return 0;
6242 }
6243 
6244 
6245 /* a timer function to see if there is output from cdrecord within a given
6246    time */
6247 
cdrtimer_callback(gpointer data)6248 static gint cdrtimer_callback(gpointer data) {
6249 time_t acttime;
6250 gint diff;
6251 gint ret;
6252 
6253 	/* how many time passed since the last output of cdrecord? */
6254 	acttime = time((time_t *) 0);
6255 	diff = (gint) (acttime - cdrcmdtimer);
6256 
6257 	/* we counting down seconds, but not receiving output since over 5? */
6258 	if (diff > 5) {
6259 		gtk_timeout_remove(cdrtimer);
6260 		cdrtimer = 0;
6261 
6262 		dodebug(10,"cdrecord.prodvd output-timer run out - assume termination.\n");
6263 		/* force termination of cdrecord.prodvd */
6264 		read_write_out(NULL, -1, 0);
6265 
6266 		/* if mkisofs is marked as running, kill it too */
6267 		if (mkisofs_pid != -1) {
6268 			dodebug(2,"sending SIGINT to mkisofs (pid %d)\n",
6269 				(gint) mkisofs_pid);
6270 			kill(mkisofs_pid, SIGINT);
6271                 	waitpid(mkisofs_pid, &ret, 0);
6272 		}
6273 
6274 		return(FALSE);
6275 	}
6276 
6277     	return(TRUE);
6278 }
6279 
6280 
6281 /* special case to try to get some last output from stderr after
6282    cdrecord terminated */
6283 
read_write_stderr_last(gint source)6284 static void read_write_stderr_last(gint source) {
6285 gint n;
6286 gchar line[MAXLINE];
6287 gchar tmp[MAXLINE];
6288 
6289 	/* get as many output left in the pipe as possible */
6290 	while (1) {
6291 		n = read_line(source, line, MAXLINE);
6292 
6293 		if (n <= 0) {
6294 			/* pipe empty */
6295 			return;
6296 		}
6297 
6298 		dodebug(10,"cdrecord (stderr-last): %s\n", line);
6299 
6300 		strcpy(tmp,line);
6301 		strcat(tmp,"\n");
6302 
6303 		convert_for_gtk2_textwidget(tmp);
6304 		gtk_text_insert(GTK_TEXT(readtrack_textview),
6305 			fixedfont,NULL,NULL,tmp, strlen(tmp));
6306 	}
6307 }
6308 
6309 
6310 /* get output of cdrecord */
6311 
read_write_out(gpointer data,gint source,GdkInputCondition cond)6312 static void read_write_out(gpointer data, gint source, GdkInputCondition cond) {
6313 gint n;
6314 gint ret;
6315 gchar line[MAXLINE];
6316 gchar tmp[MAXLINE];
6317 gchar tmp2[MAXLINE];
6318 gchar *p, *p2;
6319 gint tnr, donemb, fullmb, fifoval, intbufval;
6320 gfloat pval, pval2, pval3, pval4, avgspd;
6321 static gint writecompleted;
6322 gint cdrecord_stderr;
6323 
6324 	if (source != -1) {
6325 		n = read_line(source, line, MAXLINE);
6326 	} else {
6327 		/* force finish */
6328 		n = -1;
6329 	}
6330 
6331 	/* finished? */
6332 	if (n <= 0) {
6333 		if (data) {
6334 			/* try to get some last output from stderr */
6335 			cdrecord_stderr = GPOINTER_TO_INT(data);
6336 			read_write_stderr_last(cdrecord_stderr);
6337 		}
6338 
6339 		dodebug(10,"cdrecord (stdout): EOF\n");
6340 		gtk_input_remove(readcdda_callback);
6341 		gtk_input_remove(readcdda_callback2);
6342 
6343 		/* pick up return status of child */
6344 		waitpid((pid_t)readcdda_pid, &ret, WNOHANG);
6345 
6346 		read_done = WEXITSTATUS(ret);
6347 
6348 		if (writecompleted == 1 && read_done == 0) {
6349 			/* set total progress bar to 100% */
6350 			gtk_progress_set_percentage(
6351 				GTK_PROGRESS(readtrack_pbar2), 1.0);
6352 			set_xcdr_title(toplevel,viewmode_dialog,100);
6353 
6354 			/* and small view too */
6355 			g_snprintf(tmp,MAXLINE,"%d%% / %d%%",100,100);
6356 			gtk_label_set_text(
6357 				GTK_LABEL(readtrack_small_info2),tmp);
6358 		}
6359 
6360 		/* perhaps the are-you-sure-you-want-to-abort dialog
6361 		   is still running? remove to be sure we can continue */
6362 		if (dialog_done == 999) {
6363 			dialog_done = -1;
6364 		}
6365 
6366 		/* or cdrecord died by signal? e.g. SIGALRM */
6367 		if (WIFSIGNALED(ret) && read_done == 0) {
6368 
6369 			/* most likely invalid prodvd key */
6370 			if (curset.isProDVD && curset.cdrtype > 1000) {
6371 				read_done = 2;
6372 			}
6373 		}
6374 
6375                 dodebug(10,"Finished in read_write_out with status: %d\n",
6376                         read_done);
6377 		return;
6378 	}
6379 
6380 	dodebug(10,"cdrecord (stdout): %s\n", line);
6381 	cdrcmdtimer = time((time_t *) 0);
6382 
6383 	strip_string(line);
6384 
6385 	/* look for the reload media command */
6386 	if (strcmp(line,"Re-load disk and hit <CR>") == 0) {
6387 		cdrecord_reload = 1;
6388 		/* if there was a fileselector running, cancel it */
6389 		dialog_done3 = -1;
6390 		return;
6391 	}
6392 
6393 	/* cdrecord will wait for SIGUSR1 while waiting for reload? */
6394 	if (strstr(line, "send SIGUSR1 to continue")) {
6395                 cdrecord_reload = 2;
6396 		return;
6397 	}
6398 
6399 	/* prodvd and beginning to write soon? */
6400 	if (curset.isProDVD && curset.cdrtype > 1000) {
6401 		if (strstr(line,"Last chance to quit")) {
6402 			cdrtimer = gtk_timeout_add(1000,
6403 					cdrtimer_callback, NULL);
6404 		}
6405 
6406 		/* if we get that far, we are sure we are over the key
6407 		   check */
6408 		if (strstr(line,"1 second")) {
6409 			if (cdrtimer) {
6410 				gtk_timeout_remove(cdrtimer);
6411 				cdrtimer = 0;
6412 			}
6413 		}
6414 	}
6415 
6416 	/* skip all lines that contain "seconds." */
6417 	if (n > 8) {
6418 		if (strstr(line, "seconds.")) {
6419 			/* mark we are now ready to rumble */
6420 			read_output_ctrl = 3;
6421 
6422 			/* starting the write here */
6423 			writecompleted = 0;
6424 			return;
6425 		}
6426 	}
6427 
6428 	/* track lines */
6429 	if (read_output_ctrl > 0 && strncmp(line,"Track",5) == 0 &&
6430 		!strstr(line,"audio") && !strstr(line,"data")) {
6431 
6432 		/* parser */
6433 		avgspd = 0.0;
6434 		strcpy(tmp, line+6);
6435 		p = strtok(tmp,":");
6436 		if (p == NULL) return;
6437 		tnr = atoi(p);
6438 		p = strtok(NULL," ");
6439 		if (p == NULL) return;
6440 		if ((strncmp(p,"Total",5) != 0) &&
6441 		    (strncmp(p,"writing",7) != 0)) {
6442 			/* not the Total bytes written line? */
6443 			donemb = atoi(p);
6444 
6445 			p = strtok(NULL," ");
6446 			p = strtok(NULL," ");
6447 			if (p == NULL) return;
6448 			fullmb = atoi(p);
6449 
6450 			p = strtok(NULL,"%");
6451 			p2 = strtok(NULL,"");
6452 			if (p2 == NULL) {
6453 				/* no fifo value available - start of track */
6454 				fifoval = 0;
6455 				intbufval = 0;
6456 				avgspd = 0.0;
6457 				if (writeparams.tracktype[tnr] == 0) {
6458 					/* data track */
6459 					convert_frames2mbstring(
6460 						writeparams.frames[tnr],tmp);
6461 					g_snprintf(tmp2,MAXLINE, _("Writing data track %d/%d [%s]"),
6462 						tnr,
6463 						writeparams.nrtracks, tmp);
6464 					if (writeparams.simulation)
6465 						strcat(tmp2,_(" [Simulation]"));
6466 					gtk_label_set_text(
6467 						GTK_LABEL(readtrack_info_label),
6468 						tmp2);
6469 				} else {
6470 					/* audio track */
6471 					convert_frames2minstring(
6472 						writeparams.frames[tnr],tmp);
6473 					g_snprintf(tmp2,MAXLINE, _("Writing audio track %d/%d [%s]"),
6474 						tnr,
6475 						writeparams.nrtracks, tmp);
6476 					if (writeparams.simulation)
6477 						strcat(tmp2,_(" [Simulation]"));
6478 					gtk_label_set_text(
6479 						GTK_LABEL(readtrack_info_label),
6480 						tmp2);
6481 				}
6482 				/* small view label */
6483 				g_snprintf(tmp2,MAXLINE, _("Writing %d/%d:"),
6484 					tnr, writeparams.nrtracks);
6485 				gtk_label_set_text(
6486 					GTK_LABEL(readtrack_small_info),tmp2);
6487 			} else {
6488 				/* extract fifo value */
6489 				strcpy(tmp2,p);
6490 				p = rindex(tmp2,' ');
6491 				if (p == NULL) return;
6492 				fifoval = atoi(p);
6493 
6494 				/* extract buf/spd value */
6495 				strcpy(tmp2,p2);
6496 				p = strtok(tmp2,"%");
6497 				if (p) {
6498 					p2 = strtok(NULL,"");
6499 					strcpy(tmp,p);
6500 					p = rindex(tmp,' ');
6501 					if (p == NULL) return;
6502 					if (strstr(tmp, "buf")) {
6503 						intbufval = atoi(p);
6504 					} else {
6505 						/* no buf value? speed next */
6506 						intbufval = 0;
6507 						strcpy(tmp2,tmp);
6508 						p2 = tmp2;
6509 					}
6510 					if (p2) {
6511 						strcpy(tmp,p2);
6512 						p = strtok(tmp,"x");
6513 						if (p) {
6514 							strcpy(tmp2,p);
6515 							p = rindex(tmp2,' ');
6516 							if (p == NULL) return;
6517 							avgspd = (gfloat)atof(p);
6518 						}
6519 					}
6520 				} else {
6521 					intbufval = 0;
6522 					avgspd = 0.0;
6523 				}
6524 			}
6525 			/* done with parsing */
6526 
6527 			/* calculate current track progressbar values */
6528 			if (fullmb != 0) {
6529 				pval = (gfloat)donemb/(gfloat)fullmb;
6530 				if (pval > 1.0) pval = 1.0;
6531 
6532 				gtk_progress_set_percentage(
6533 					GTK_PROGRESS(readtrack_pbar1), pval);
6534 			} else {
6535 				pval = 0.0;
6536 			}
6537 
6538 			/* calculate total track progressbar */
6539 			pval2 = (writeparams.pct_so_far_arr[tnr] +
6540 				(pval * writeparams.pct_this_track_arr[tnr]));
6541 			/* go only up to 99% */
6542 			if (pval2 >= 0.99) pval2 = 0.99;
6543 
6544 			if (writeparams.nrtracks != 1) {
6545 				gtk_progress_set_percentage(
6546 					GTK_PROGRESS(readtrack_pbar2), pval2);
6547 				set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval2*100+0.5));
6548 			} else {
6549 				/* just one track? total is the same as track */
6550 				if (pval < 1.0) {
6551 					gtk_progress_set_percentage(
6552 						GTK_PROGRESS(readtrack_pbar2),
6553 						pval);
6554 					set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval*100+0.5));
6555 				} else {
6556 					gtk_progress_set_percentage(
6557 						GTK_PROGRESS(readtrack_pbar2),
6558 						0.99);
6559 					set_xcdr_title(toplevel,viewmode_dialog,99);
6560 				}
6561 			}
6562 
6563 			/* fifo value */
6564 			pval3 = (gfloat)fifoval /100;
6565 			if (pval3 > 1.0) pval3 = 1.0;
6566 			gtk_progress_set_percentage(
6567 				GTK_PROGRESS(readtrack_pbar3), pval3);
6568 
6569 			/* add internal buffer and average speed too */
6570 			pval4 = (gfloat)intbufval /100;
6571 			if (pval4 > 1.0) pval4 = 1.0;
6572 			gtk_progress_set_percentage(
6573 				GTK_PROGRESS(readtrack_pbar4), pval4);
6574 
6575 			if (avgspd > 0.0) {
6576 				g_snprintf(tmp,MAXLINE,"%.1fx",avgspd);
6577 				gtk_label_set_text(GTK_LABEL(readtrack_spd), tmp);
6578 			}
6579 
6580 			/* now update info for small view */
6581 			g_snprintf(tmp,MAXLINE,"%d%% / %d%%",
6582 				(gint)(pval*100+0.5), (gint)(pval2*100+0.5));
6583 			gtk_label_set_text(
6584 				GTK_LABEL(readtrack_small_info2),tmp);
6585 
6586 			return;
6587 		}
6588 	}
6589 
6590 	/* fixating */
6591 	if (strncmp(line,"Fixating...",11) == 0) {
6592 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Fixating..."));
6593 		/* ok, write is finished I guess */
6594 		writecompleted = 1;
6595 	}
6596 
6597 	/* avg speed line */
6598 	if (strncmp(line,"Average write speed", 19) == 0) {
6599 		strcpy(tmp,line);
6600 		p = strtok(tmp,"x");
6601 		if (p) {
6602 			strcpy(tmp2,p);
6603 			p = rindex(tmp2,' ');
6604 			if (p) {
6605 				avgspd = (gfloat)atof(p);
6606 				g_snprintf(tmp,MAXLINE,"%.1fx",avgspd);
6607 				gtk_label_set_text(GTK_LABEL(readtrack_spd), tmp);
6608 			}
6609 		}
6610 	}
6611 
6612 	strcpy(tmp,line);
6613 	strcat(tmp,"\n");
6614 
6615 	convert_for_gtk2_textwidget(tmp);
6616 	gtk_text_insert(GTK_TEXT(readtrack_textview),
6617 		fixedfont,NULL,NULL,tmp, strlen(tmp));
6618 
6619 }
6620 
6621 
read_write_stderr(gpointer data,gint source,GdkInputCondition cond)6622 static void read_write_stderr (gpointer data, gint source, GdkInputCondition cond) {
6623 gint n;
6624 gint ret;
6625 gchar line[MAXLINE];
6626 gchar tmp[MAXLINE];
6627 gchar tmp2[MAXLINE];
6628 gchar *p;
6629 
6630 	n = read_line(source, line, MAXLINE);
6631 
6632 	/* finished? */
6633 	if (n <= 0) {
6634                 dodebug(10,"cdrecord (stderr): EOF\n");
6635                 gtk_input_remove(readcdda_callback);
6636                 gtk_input_remove(readcdda_callback2);
6637 
6638                 /* pick up return status of child */
6639                 waitpid((pid_t)readcdda_pid, &ret, WNOHANG);
6640 
6641                 read_done = WEXITSTATUS(ret);
6642 
6643                 /* perhaps the are-you-sure-you-want-to-abort dialog
6644                    is still running? remove to be sure we can continue */
6645                 if (dialog_done == 999) {
6646                         dialog_done = -1;
6647                 }
6648 
6649 		return;
6650 	}
6651 
6652 	dodebug(10,"cdrecord (stderr): %s\n", line);
6653 
6654 	/* check if we have an medium-i/o-error */
6655 	strcpy(tmp,line);
6656 	p = strtok(tmp,":");
6657 	if (p != NULL) {
6658 		p = strtok(NULL,"");
6659 		if (p != NULL) {
6660 			strcpy(tmp2,p);
6661 			strip_string(tmp2);
6662 			if (strncmp(tmp2,"I/O error",9) == 0) {
6663 				readerr_count++;
6664 				/* more then once an i/o-error? */
6665 				if (readerr_count > 1) {
6666 					kill_readcdda();
6667 					dialog_done2 = 999;
6668 					read_output_ctrl = 2;
6669 				}
6670 			}
6671 			/* check also if cannot send CUE sheet */
6672 			if (strncmp(tmp2,"Cannot send CUE sheet", 21) == 0) {
6673 				read_output_ctrl = 4;
6674 			}
6675 			/* check for common error on TAO only devices */
6676 			if (strncmp(tmp2,"Cannot open new session.",24) == 0 && get_cur_writemode() == 0) {
6677 				read_output_ctrl = 4;
6678 			}
6679 			/* check Medium error/buffer underrun */
6680 			if (strncmp(tmp2,"Input/output error",18) == 0) {
6681 				read_output_ctrl = 5;
6682 			}
6683 		}
6684 	}
6685 
6686 
6687 	/* check if we got an error because of no disk */
6688 	if (n > 21) {
6689 		strcpy(tmp, line+(strlen(line)-21));
6690 		if (strcmp(tmp, "No disk / Wrong disk!") == 0) {
6691 			/* mark we got no disk */
6692 			read_output_ctrl = 2;
6693 		}
6694 	}
6695 
6696 	strcpy(tmp,line);
6697 	strcat(tmp,"\n");
6698 
6699 	convert_for_gtk2_textwidget(tmp);
6700 	gtk_text_insert(GTK_TEXT(readtrack_textview),
6701 		fixedfont,NULL,NULL,tmp, strlen(tmp));
6702 }
6703 
6704 
6705 /* display an error when useing prodvd and cdrecord aborts */
6706 
display_invalid_prodvdkey()6707 static void display_invalid_prodvdkey() {
6708 
6709 	if (curset.isProDVD && curset.cdrtype > 1000) {
6710 		show_dialog(ICO_WARN, _("cdrecord-ProDVD terminated.\n\nMost likely because you have entered\nan invalid key. Please check if it is correct."), T_OK, NULL, NULL, 0);
6711 	}
6712 }
6713 
6714 
6715 /* call cdrecord to write some tracks */
6716 
start_write_action(gint devnr)6717 gint start_write_action(gint devnr) {
6718 GList *loop;
6719 track_read_param_t *trackparam;
6720 gchar tmp[MAXLINE];
6721 gchar tmptmp[MAXLINE];
6722 gchar tmp2[MAXLINE];
6723 gchar tmp3[MAXLINE];
6724 gchar cmd[MAXLINE*10];  /* extra big buffer for very long cdrecord options */
6725 gchar outcmd[MAXLINE];
6726 gint read_out, read_err;
6727 gint ret, tracknr;
6728 gint varirec_on, tmp_writer_speed;
6729 gint wrmode;
6730 
6731 	/* if another write running, ignore */
6732 	if (read_done == 999) {
6733 		return -1;
6734 	}
6735 
6736 	/* mark our write-process as running */
6737 	read_done = 999;
6738 	read_output_ctrl = 0;
6739 	pct_so_far = 0.0;
6740 	cdrecord_reload = 0;
6741 	cdrtimer = 0;
6742 
6743 	strcpy(outcmd,"");
6744 
6745 	/* set info label */
6746 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
6747 
6748 	/* reset writeparams-arrays */
6749 	g_free(writeparams.tracktype);
6750 	g_free(writeparams.frames);
6751 	g_free(writeparams.pct_so_far_arr);
6752 	g_free(writeparams.pct_this_track_arr);
6753 	writeparams.tracktype = g_new0(gint,MAXTRACKS);
6754 	writeparams.frames = g_new0(gint,MAXTRACKS);
6755 	writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
6756 	writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
6757 	writeparams.nrtracks = 0;
6758 	writeparams.simulation = curset.writesimul;
6759 
6760 	/* get bus,id,lun string */
6761 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
6762 		g_error("non existing cdrom?");
6763 	}
6764 
6765 	/* get driveropts */
6766 	varirec_on = do_driveropts(tmp3, curset.writer_devnr);
6767 
6768 	/* build command line */
6769 	get_wrap_path_cdrecord(tmp2);
6770 	g_snprintf(cmd, MAXLINE*10,
6771 		"%s %s gracetime=%d fs=%dk %s -v -useinfo",
6772 		tmp2, tmp, get_gracetime(), get_cur_writer_fifo(), tmp3);
6773 
6774 	if (get_cur_writer_drvmode() >= 0) {
6775 		if (drivers[get_cur_writer_drvmode()] != NULL) {
6776 			g_snprintf(tmp,MAXLINE," driver=%s",
6777 				drivers[get_cur_writer_drvmode()]->driver);
6778 			strcat(cmd,tmp);
6779 		}
6780 	}
6781 
6782 	/* special case with varirec - always use 4x here */
6783 	if (varirec_on) {
6784 		tmp_writer_speed = 4;
6785 	} else {
6786 		tmp_writer_speed = get_cur_writer_speed();
6787 	}
6788 	if (get_cur_writer_speed() >= 0) {
6789 		g_snprintf(tmp,MAXLINE," speed=%d", tmp_writer_speed);
6790 		strcat(cmd, tmp);
6791 	}
6792 
6793 	if (curset.multisession == 0) {
6794 		wrmode = get_cur_writemode();
6795 		if (wrmode == 0) {
6796 			strcat(cmd," -dao");
6797 		}
6798 		if (wrmode == 2) {
6799 			strcat(cmd," defpregap=0");
6800 		}
6801 		if (wrmode == 3) {
6802 			strcat(cmd," -raw96r");
6803 		}
6804 		if (wrmode == 4) {
6805 			strcat(cmd," -raw96p");
6806 		}
6807 		if (wrmode == 5) {
6808 			strcat(cmd," -raw16");
6809 		}
6810 	}
6811 
6812 	if (curset.writesimul == 1) {
6813 		strcat(cmd," -dummy");
6814 	}
6815 	if (curset.writeeject == 1) {
6816 		strcat(cmd," -eject");
6817 	}
6818 	if (curset.nofixate == 1) {
6819 		strcat(cmd," -nofix");
6820 	}
6821 	if (curset.multisession == 1) {
6822 		if (is_a_sony(devnr)) {
6823 			strcat(cmd," -multi -data");
6824 		} else {
6825 			strcat(cmd," -multi");
6826 		}
6827 	}
6828 	if (curset.writepad == 1) {
6829 		strcat(cmd," -pad");
6830 	}
6831 	if (curset.writeswap == 1) {
6832 		strcat(cmd," -swab");
6833 	}
6834 	if (curset.writeoverburn == 1) {
6835 		strcat(cmd," -overburn");
6836 	}
6837 	if (curset.writeignsize == 1) {
6838 		strcat(cmd," -ignsize");
6839 	}
6840 	if (curset.writeimmed == 1) {
6841 		strcat(cmd," -immed");
6842 	}
6843 	if (curset.writecdtext == 1) {
6844 		strcat(cmd," -text");
6845 	}
6846 
6847 	/* now loop through all tracks to write */
6848 	loop = g_list_first(trackreadset.trackparams);
6849 	while(loop) {
6850 		trackparam = loop->data;
6851 
6852 		if (trackparam->tracktype == 0) {
6853 			/* datatrack */
6854 			strcat(cmd," -data");
6855 		} else {
6856 			/* audiotrack */
6857 			strcat(cmd," -audio");
6858 		}
6859 		if (trackparam->trackfile != NULL) {
6860 			strcpy(tmptmp, trackparam->trackfile);
6861 			g_snprintf(tmp, MAXLINE, " \"%s\"",
6862 				convert_escape(tmptmp));
6863 			strcat(cmd, tmp);
6864 		}
6865 
6866 		/* save partial command line to view in progress window */
6867 		if (strcmp(outcmd,"") == 0) {
6868 			g_snprintf(outcmd, MAXLINE,"Calling: %s ...\n\n", cmd);
6869 		}
6870 
6871 		/* fill up percent values for nice progressbar movement */
6872 		tracknr = trackparam->starttrack;
6873 		writeparams.tracktype[tracknr] = trackparam->tracktype;
6874 		writeparams.frames[tracknr] = trackparam->frames;
6875 		writeparams.pct_this_track_arr[tracknr] = trackparam->percent;
6876 		writeparams.pct_so_far_arr[tracknr] = pct_so_far;
6877 		pct_so_far += trackparam->percent;
6878 		writeparams.nrtracks++;
6879 
6880 		loop = loop->next;
6881 	}
6882 
6883 	dodebug(1, "spawning: %s\n",cmd);
6884 	dolog(1,"Write CD with %d tracks\n", writeparams.nrtracks);
6885 	dolog(3,"Executing: %s\n", cmd);
6886 
6887 	/* output command to get better debug output */
6888 	gtk_text_insert(GTK_TEXT(readtrack_textview),
6889 		fixedfont,NULL,NULL,outcmd, strlen(outcmd));
6890 
6891 	/* yes...command line is done */
6892 	readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,cmd,1);
6893 	readcdda_pid2 = -1;
6894 	mkisofs_pid = -1;
6895 
6896 	fcntl(read_out, F_SETFL, O_NONBLOCK);
6897 	fcntl(read_err, F_SETFL, O_NONBLOCK);
6898 
6899 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
6900 		(GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err));
6901 	readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
6902 		(GdkInputFunction) read_write_stderr, NULL);
6903 
6904 	/* now wait until write is finished */
6905 	while (read_done == 999) {
6906 		wait_and_process_events();
6907 
6908 		/* check if writer is waiting for reload medium */
6909 		if (cdrecord_reload > 0) {
6910 			cdrecord_reload = 0;
6911 			show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
6912 
6913 			/* now send CR to cdrecord to let it continue */
6914 			if (write(cdrecord_stdin, "\n", 1) != 1) {
6915 				g_warning("write error to cdrecord pipe\n");
6916 			}
6917 		}
6918 
6919 		/* check if somebody clicked on cancel */
6920 		if (dialog_done2 != 999) {
6921 			ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
6922 				T_YES, T_NO, NULL, 1);
6923 			if (ret == 0) {
6924 				/* really abort */
6925 				kill_readcdda();
6926 				/* mark we aborted */
6927 				read_output_ctrl = 1;
6928 				dialog_done2 = 999;
6929 			} else {
6930 				/* not abort - undo button press */
6931 				dialog_done2 = 999;
6932 			}
6933 		}
6934 	}
6935 
6936 	close(read_err);
6937 	close(read_out);
6938 	close(cdrecord_stdin);
6939 
6940 	/* no disk */
6941 	if (read_output_ctrl == 2) {
6942 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
6943 		return 1;
6944 	}
6945 	/* cannot send cue sheet */
6946 	if (read_output_ctrl == 4) {
6947 		show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
6948 	}
6949 
6950 	/* aborted write ? */
6951 	if (read_output_ctrl == 1) {
6952 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
6953 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
6954 		return 1;
6955 	}
6956 
6957 	/* error while writing ?*/
6958 	if (read_done != 0 || read_output_ctrl == 5) {
6959 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
6960 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
6961 		if (read_done == 2) {
6962 			/* invalid cdrecord key - show window */
6963 			display_invalid_prodvdkey();
6964 		}
6965 		return 1;
6966 	} else {
6967 		/* all ok */
6968 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
6969 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
6970 		return 0;
6971 	}
6972 }
6973 
6974 
6975 /* call cdda2wav to only create temporary .inf files - and let xcdroast
6976    patch CD-Text data into them if requested */
6977 
create_onthefly_inf_files(gint devnr)6978 static void create_onthefly_inf_files(gint devnr) {
6979 GList *loop;
6980 track_read_param_t *trackparam;
6981 char tmp[MAXLINE];
6982 char tmptmp[MAXLINE];
6983 char tmp4[MAXLINE];
6984 char tmp5[MAXLINE];
6985 char line[MAXLINE];
6986 char cmd[MAXLINE*10];  /* extra big buffer for very long cdrecord options */
6987 FILE *fpin;
6988 gint ret, i, orgcdtextused;
6989 gchar title[MAXLINE], artist[MAXLINE];
6990 gchar cdtitle[MAXLINE], cdartist[MAXLINE];
6991 
6992         /* get bus,id,lun string */
6993         if (convert_devnr2busid(devnr,tmp) != 0) {
6994                 g_error("non existing cdrom?");
6995         }
6996 
6997         /* have to scan for indexes? */
6998         if (curset.indexscan != 0) {
6999                 strcpy(tmp4,"-v all");
7000         } else {
7001                 strcpy(tmp4,"-v toc,summary,sectors,titles");
7002         }
7003 
7004         get_wrap_path("CDDA2WAV",tmp5);
7005         g_snprintf(cmd,MAXLINE,
7006                    "%s -D \"%s\" %s -info-only -B", tmp5,tmp,tmp4);
7007 
7008         /* now add all track-filenames (only audio) */
7009         loop = g_list_first(trackreadset.trackparams);
7010         while(loop) {
7011                 trackparam = loop->data;
7012                 if (trackparam->trackfile != NULL &&
7013                     trackparam->tracktype == 1) {
7014                         strcpy(tmptmp, trackparam->trackfile);
7015                         g_snprintf(tmp, MAXLINE, " \"%s\"",
7016                                 convert_escape(tmptmp));
7017                         strcat(cmd, tmp);
7018 		}
7019                 loop = loop->next;
7020         }
7021 	strcat(cmd, " 2>&1");
7022 
7023         dodebug(1,"calling: %s\n", cmd);
7024         if ((fpin = popen(cmd,"r")) == NULL) {
7025                 g_error("popen error\n");
7026         }
7027 
7028         for (;;) {
7029                 if (fgets(line,MAXLINE,fpin) == NULL)
7030                         break;
7031                 dodebug(10,"cdda2wav_info_only: %s", line);
7032         }
7033 
7034         ret = pclose(fpin);
7035         if (ret == -1) {
7036                 g_error("pclose error\n");
7037         }
7038 
7039 	/* info files now (hopefully) created */
7040 
7041 	/* check for invalid mcn or isrc infoormation */
7042         loop = g_list_first(trackreadset.trackparams);
7043         while(loop) {
7044                 trackparam = loop->data;
7045                 if (trackparam->trackfile != NULL &&
7046                     trackparam->tracktype == 1) {
7047 
7048 			/* silently fix any broken .inf file */
7049 			if (check_valid_isrc_mcn(trackparam->trackfile)) {
7050 				clear_isrc_mcn_from_inffile(trackparam->trackfile);
7051 			}
7052 		}
7053 		loop = loop->next;
7054 	}
7055 
7056 	/* patch updated cd-text info */
7057 	if (curset.writecdtext) {
7058 
7059 		/* get title and artist for the given CD */
7060 	        strcpy(cdtitle,"");
7061         	strcpy(cdartist,"");
7062 		orgcdtextused = 0;
7063                 if (setupdata.option_displaycdtext) {
7064                        if (cdinfo.title && cdinfo.artist && cdinfo.title[0] != '\0') {
7065                                 strncpy(cdtitle, cdinfo.title, MAXLINE);
7066                                 strncpy(cdartist, cdinfo.artist, MAXLINE);
7067                                 orgcdtextused = 1;
7068                         }
7069                 }
7070                 if (orgcdtextused == 0) {
7071                         if (cdinfo.cddb_dtitle) {
7072                                 get_artist_and_title_from_cddb(cdinfo.cddb_dtitle,
7073                                 cdartist, cdtitle);
7074                         } else {
7075                                 /* try cd-text as fallback */
7076                                 if (cdinfo.title && cdinfo.artist &&
7077                                     cdinfo.title[0] != '\0') {
7078                                         strncpy(cdtitle, cdinfo.title, MAXLINE);
7079                                         strncpy(cdartist, cdinfo.artist, MAXLINE);                                }
7080                         }
7081                 }
7082 
7083 /*
7084 		g_print("cdtitle/artist %s %s\n", cdtitle, cdartist);
7085 */
7086         	loop = g_list_first(trackreadset.trackparams);
7087 	        while(loop) {
7088         	        trackparam = loop->data;
7089 	                if (trackparam->trackfile != NULL &&
7090                 	    trackparam->tracktype == 1) {
7091 
7092 				/* get the cd-text data */
7093 				i = trackparam->trackinfo_index;
7094 		                strcpy(title,"");
7095               		  	strcpy(artist,"");
7096                	 		orgcdtextused = 0;
7097                 		if (setupdata.option_displaycdtext) {
7098                         		if (trackinfo[i]->title != NULL &&
7099                             		    trackinfo[i]->title[0] != '\0' ) {
7100                                 		/* cd-text found.. use it */
7101                                 		strncpy(title, trackinfo[i]->title, MAXLINE);
7102                                 		orgcdtextused = 1;
7103                         		}
7104                         		if (trackinfo[i]->artist != NULL &&
7105                             			trackinfo[i]->artist[0] != '\0' ) {
7106                                 		strncpy(artist, trackinfo[i]->artist, MAXLINE);
7107                         		}
7108                 		}
7109 		                /* no cd-text in use? try cddb */
7110 		                if (orgcdtextused == 0) {
7111                         		if (trackinfo[i]->cddb_ttitle != NULL) {
7112                                 		/* use cddb-information */
7113                                 		strncpy(title, trackinfo[i]->cddb_ttitle,
7114                                         		MAXLINE);
7115                         		} else {
7116                                 		/* fall back to try cd-text again */
7117                                 		if (trackinfo[i]->title != NULL &&
7118                                     		trackinfo[i]->title[0] != '\0' ) {
7119                                         		strncpy(title, trackinfo[i]->title, MAXLINE);
7120                                 		}
7121                                 		if (trackinfo[i]->artist != NULL &&
7122                                     		    trackinfo[i]->artist[0] != '\0' ) {
7123                                         		strncpy(artist, trackinfo[i]->artist, MAXLINE);
7124                                 		}
7125                         		}
7126                 		}
7127 
7128 				/* now we have all cd-text info for the given track */
7129 				edit_xinf_for_cd_text2(trackparam->trackfile, title, artist, cdtitle, cdartist);
7130 
7131 			}
7132 			loop = loop->next;
7133 		}
7134 	}
7135 }
7136 
7137 
7138 /* after the on-the-fly write remove the temporary-inf files again */
7139 
remove_onthefly_inf_files()7140 static void remove_onthefly_inf_files() {
7141 GList *loop;
7142 track_read_param_t *trackparam;
7143 char tmptmp[MAXLINE];
7144 
7145         loop = g_list_first(trackreadset.trackparams);
7146         while(loop) {
7147                 trackparam = loop->data;
7148                 if (trackparam->trackfile != NULL &&
7149                     trackparam->tracktype == 1) {
7150                         strcpy(tmptmp, trackparam->trackfile);
7151 			remove_tmp_writetracks_tocfile(tmptmp);
7152 		}
7153                 loop = loop->next;
7154         }
7155 }
7156 
7157 
7158 /* call cdrecord to write a cd on the fly */
7159 /* works currently only for cds with a single data-track and pure
7160    audio CDs */
7161 
start_write_onthefly_action(gint read_devnr,gint write_devnr)7162 gint start_write_onthefly_action(gint read_devnr, gint write_devnr) {
7163 GList *loop;
7164 track_read_param_t *trackparam;
7165 gchar tmp[MAXLINE];
7166 gchar tmp2[MAXLINE];
7167 gchar tmp3[MAXLINE];
7168 gchar tmp4[MAXLINE];
7169 gchar atmp3[MAXLINE];
7170 gchar tmptmp[MAXLINE];
7171 gchar atmp6[MAXLINE];
7172 gchar cmd[MAXLINE*10];  /* extra big buffer for very long cdrecord options */
7173 gchar cmd2[MAXLINE*10];
7174 gchar outcmd[MAXLINE];
7175 gchar tmpprefix[MAXLINE];
7176 gint read_out, read_err, read_err2;
7177 gint ret, tracknr, i;
7178 pid_t pid1, pid2;
7179 gint endsector, sectsize;
7180 gint varirec_on, tmp_writer_speed;
7181 gint wrmode;
7182 gint datacount, audiocount;
7183 gint isaudiocd;
7184 gfloat per;
7185 
7186 	/* if another write running, ignore */
7187 	if (read_done == 999) {
7188 		return -1;
7189 	}
7190 
7191 	/* what we got to do here? */
7192 	datacount = 0;
7193 	audiocount = 0;
7194 	isaudiocd = 0;
7195         for (i = 0; i < cdinfo.nr_tracks; i++) {
7196                 if (trackinfo[i]->type == 0) {
7197                         datacount++;
7198                 } else {
7199                         audiocount++;
7200                 }
7201         }
7202 	if (datacount == 0 && audiocount > 0) {
7203 		isaudiocd = 1;
7204 	}
7205 	/* special case - cd extra? */
7206 	if (datacount == 1 && audiocount > 0 && trackinfo[0]->type == 1) {
7207 		/* treat just like an audio cd - ignore data track */
7208 		isaudiocd = 1;
7209 	}
7210 
7211 	/* fetch a prefix we might need */
7212 	generate_tmp_prefix_name(tmpprefix);
7213 
7214 	/* audio on the fly - rebuild our structure for the tracks to read */
7215 	if (isaudiocd) {
7216 
7217 		clear_trackreadset();
7218 		trackreadset.nrtracks = cdinfo.nr_tracks;
7219 
7220 		/* create a list of temporary track files */
7221 		for(i=0; i<cdinfo.nr_tracks; i++) {
7222 
7223 			trackparam = g_new0(track_read_param_t,1);
7224 			trackparam->trackinfo_index = i;
7225 			trackparam->starttrack = trackinfo[i]->track_nr;
7226 			trackparam->endtrack = 0;
7227 			trackparam->tracktype = trackinfo[i]->type;
7228 			per = (gfloat)trackinfo[i]->size * 100.0  / cdinfo.total_size;
7229 			trackparam->percent = per/100.0;
7230 			trackparam->frames = trackinfo[i]->size;
7231 
7232 			g_snprintf(tmp,MAXLINE, "%s-%02d.inf",
7233 				tmpprefix, i);
7234 			trackparam->trackfile = g_strdup(tmp);
7235 
7236 			trackreadset.trackparams = g_list_append(
7237 				trackreadset.trackparams, trackparam);
7238 		}
7239 
7240 		create_onthefly_inf_files(read_devnr);
7241 	}
7242 
7243 	/* mark our write-process as running */
7244 	read_done = 999;
7245 	read_output_ctrl = 0;
7246 	pct_so_far = 0.0;
7247 	cdrecord_reload = 0;
7248 	cdrtimer = 0;
7249 	endsector = 0;
7250 	sectsize = 0;
7251 	strcpy(outcmd,"");
7252 
7253 	/* set info label */
7254 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
7255 
7256 	/* reset writeparams-arrays */
7257 	g_free(writeparams.tracktype);
7258 	g_free(writeparams.frames);
7259 	g_free(writeparams.pct_so_far_arr);
7260 	g_free(writeparams.pct_this_track_arr);
7261 	writeparams.tracktype = g_new0(gint,MAXTRACKS);
7262 	writeparams.frames = g_new0(gint,MAXTRACKS);
7263 	writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
7264 	writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
7265 	writeparams.nrtracks = 0;
7266 	writeparams.simulation = curset.writesimul;
7267 
7268 
7269 	/* build command line of readprocess */
7270 
7271 
7272 	if (!isaudiocd) {
7273 
7274 		/* get bus,id,lun string */
7275 		if (convert_devnr2busid_dev(read_devnr,tmp) != 0) {
7276 			g_error("non existing cdrom?");
7277 		}
7278 		/* because we have only a single track on the cd this is our
7279 	   	   endsector to read */
7280 		endsector = cdinfo.leadout - 2;
7281 
7282 	        sectsize = get_sectorsize(read_devnr);
7283 		if (sectsize == 2352) {
7284 			/* workaround for buggy drives */
7285 	       	 	endsector = ((endsector * DATASECTORSIZE) / sectsize) + 1;
7286 		}
7287 
7288 		get_wrap_path("READCD", tmp2);
7289 		g_snprintf(cmd,MAXLINE,
7290 			"%s %s sectors=0-%d -s f=-",
7291 			tmp2, tmp, endsector);
7292 
7293 	} else {
7294 		/* audio CD */
7295 
7296 	        /* get bus,id,lun string */
7297 	        if (convert_devnr2busid(read_devnr,tmp) != 0) {
7298        	         	g_error("non existing cdrom?");
7299         	}
7300 
7301 	        /* set speed only when not zero */
7302        	 	if (get_cur_audioread_speed() > 0) {
7303                 	g_snprintf(atmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
7304 		} else {
7305                 	strcpy(atmp3,"");
7306         	}
7307 	        if (get_cur_audioread_useparanoia()) {
7308                 	g_snprintf(atmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
7309         	} else {
7310                 	strcpy(atmp6,"");
7311         	}
7312 
7313 	        get_wrap_path("CDDA2WAV", tmp2);
7314 	        g_snprintf(cmd,MAXLINE,
7315                    "%s -D \"%s\" -g -Oraw %s -P %d -n %d %s -no-infofile -B -",
7316                    tmp2,tmp,atmp3,
7317                    get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
7318                    atmp6);
7319 	}
7320 
7321 
7322 	/* build command line of write process */
7323 
7324 	/* get bus,id,lun string */
7325 	if (convert_devnr2busid_dev(write_devnr,tmp) != 0) {
7326 		g_error("non existing cdrom?");
7327 	}
7328 
7329 	/* get driveropts */
7330 	varirec_on = do_driveropts(tmp4, curset.writer_devnr);
7331 
7332 	get_wrap_path_cdrecord(tmp3);
7333 	g_snprintf(cmd2, MAXLINE*10,
7334 		"%s %s gracetime=%d fs=%dk %s -v -useinfo",
7335 		tmp3, tmp, get_gracetime(), get_cur_writer_fifo(), tmp4);
7336 
7337 	if (get_cur_writer_drvmode() >= 0) {
7338 		if (drivers[get_cur_writer_drvmode()] != NULL) {
7339 			g_snprintf(tmp,MAXLINE," driver=%s",
7340 				drivers[get_cur_writer_drvmode()]->driver);
7341 			strcat(cmd2,tmp);
7342 		}
7343 	}
7344 
7345 	/* special case with varirec - always use 4x here */
7346 	if (varirec_on) {
7347 		tmp_writer_speed = 4;
7348 	} else {
7349 		tmp_writer_speed = get_cur_writer_speed();
7350 	}
7351 	if (get_cur_writer_speed() >= 0) {
7352 		g_snprintf(tmp,MAXLINE," speed=%d", tmp_writer_speed);
7353 		strcat(cmd2, tmp);
7354 	}
7355 	if (curset.multisession == 0) {
7356 		wrmode = get_cur_writemode();
7357 		if (wrmode == 0) {
7358 			strcat(cmd2," -dao");
7359 		}
7360 		if (wrmode == 2) {
7361 			strcat(cmd2," defpregap=0");
7362 		}
7363 		if (wrmode == 3) {
7364 			strcat(cmd2," -raw96r");
7365 		}
7366 		if (wrmode == 4) {
7367 			strcat(cmd2," -raw96p");
7368 		}
7369 		if (wrmode == 5) {
7370 			strcat(cmd2," -raw16");
7371 		}
7372 	}
7373 	if (curset.writesimul == 1) {
7374 		strcat(cmd2," -dummy");
7375 	}
7376 	if (curset.writeeject == 1) {
7377 		strcat(cmd2," -eject");
7378 	}
7379 	if (curset.nofixate == 1) {
7380 		strcat(cmd2," -nofix");
7381 	}
7382 #if 0
7383 		/* allow multisession only for data */
7384 		if (curset.multisession == 1) {
7385 			if (is_a_sony(write_devnr)) {
7386 				strcat(cmd2," -multi -data");
7387 			} else {
7388 				strcat(cmd2," -multi");
7389 			}
7390 		}
7391 #endif
7392 	if (curset.writepad == 1) {
7393 		strcat(cmd2," -pad");
7394 	}
7395 	if (curset.writeswap == 1) {
7396 		strcat(cmd2," -swab");
7397 	}
7398 	if (curset.writeoverburn == 1) {
7399 		strcat(cmd2," -overburn");
7400 	}
7401 	if (curset.writeignsize == 1) {
7402 		strcat(cmd2," -ignsize");
7403 	}
7404 	if (curset.writeimmed == 1) {
7405 		strcat(cmd2," -immed");
7406 	}
7407 	if (curset.writecdtext == 1) {
7408 		strcat(cmd2," -text");
7409 	}
7410 
7411 	if (!isaudiocd) {
7412 		/* now add track-specification: one data track, known length */
7413  	       if (sectsize == SUNDATASECTORSIZE) {
7414        	         	g_snprintf(tmp, MAXLINE, " tsize=%db", endsector);
7415         	} else {
7416                 	g_snprintf(tmp, MAXLINE, " tsize=%ds", endsector);
7417         	}
7418 
7419 		strcat(cmd2, tmp);
7420 		strcat(cmd2," -waiti -data -");
7421 
7422 		/* fill up percent values for nice progressbar movement */
7423 		tracknr = 1;
7424 		writeparams.tracktype[tracknr] = 0; /* data */
7425 		writeparams.frames[tracknr] = endsector;
7426 		writeparams.pct_this_track_arr[tracknr] = 1.0;
7427 		writeparams.pct_so_far_arr[tracknr] = 0.0;
7428 		writeparams.nrtracks = 1;
7429 
7430 	} else {
7431 
7432 		strcat(cmd2," -waiti -audio");
7433 
7434 		/* audio mode - add info-file list */
7435 	        loop = g_list_first(trackreadset.trackparams);
7436         	while(loop) {
7437                 	trackparam = loop->data;
7438                 	if (trackparam->trackfile != NULL &&
7439                     	    trackparam->tracktype == 1) {
7440                         	strcpy(tmptmp, trackparam->trackfile);
7441                         	g_snprintf(tmp, MAXLINE, " \"%s\"",
7442                                 	convert_escape(tmptmp));
7443                         	strcat(cmd2, tmp);
7444 			}
7445 			/* fill up percent values for nice progressbar movement */
7446 			tracknr = trackparam->starttrack;
7447 			writeparams.tracktype[tracknr] = trackparam->tracktype;
7448 			writeparams.frames[tracknr] = trackparam->frames;
7449 			writeparams.pct_this_track_arr[tracknr] = trackparam->percent;
7450 			writeparams.pct_so_far_arr[tracknr] = pct_so_far;
7451 			pct_so_far += trackparam->percent;
7452 			writeparams.nrtracks++;
7453 
7454 			loop = loop->next;
7455 		}
7456 
7457 	}
7458 
7459 	/* save partial command line to view in progress window */
7460 	g_snprintf(outcmd, MAXLINE,"Calling: %s\n\n", cmd2);
7461 
7462 	dodebug(1, "spawning: %s | %s \n",cmd, cmd2);
7463 	dolog(1,"Write CD on the fly\n");
7464 	dolog(3,"Executing: %s | %s\n", cmd, cmd2);
7465 
7466 	/* output command to get better debug output */
7467 	gtk_text_insert(GTK_TEXT(readtrack_textview),
7468 		fixedfont,NULL,NULL,outcmd, strlen(outcmd));
7469 
7470 	/* yes...command line is done */
7471 	full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,&read_err2,cmd2,1);
7472 	mkisofs_pid = -1;
7473 	readcdda_pid = pid2;
7474 	readcdda_pid2 = pid1;
7475 
7476 	fcntl(read_out, F_SETFL, O_NONBLOCK);
7477 	fcntl(read_err, F_SETFL, O_NONBLOCK);
7478 	fcntl(read_err2, F_SETFL, O_NONBLOCK);
7479 
7480 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
7481 		(GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err2));
7482 	readcdda_callback2 = gdk_input_add(read_err2, GDK_INPUT_READ,
7483 		(GdkInputFunction) read_write_stderr, NULL);
7484 	readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
7485 		(GdkInputFunction) verify_readcd_err, GINT_TO_POINTER(pid1));
7486 
7487 	/* now wait until write is finished */
7488 	while (read_done == 999) {
7489 		wait_and_process_events();
7490 
7491 		/* check if writer is waiting for reload medium */
7492 		if (cdrecord_reload > 0) {
7493 			show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
7494 
7495 			/* now send CR to cdrecord to let it continue */
7496 			if (cdrecord_reload == 1) {
7497 				if (write(read_err2, "\n", 1) != 1) {
7498 					g_warning("write error to cdrecord pipe\n");
7499 				}
7500 			}
7501 
7502 			/* cdrecord also accepts a SIGUSR1 to continue */
7503 			/* send wakeup signal */
7504 			if (cdrecord_reload == 2) {
7505 				dodebug(1,"Sending SIGUSR1 to cdrecord (pid: %d) after reload.\n", (gint) pid2);
7506 				kill(pid2, SIGUSR1);
7507 			}
7508 			cdrecord_reload = 0;
7509 		}
7510 
7511 		/* check if somebody clicked on cancel */
7512 		if (dialog_done2 != 999) {
7513 			ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
7514 				T_YES, T_NO, NULL, 1);
7515 			if (ret == 0) {
7516 				/* really abort */
7517 				kill_readcdda();
7518 				/* mark we aborted */
7519 				read_output_ctrl = 1;
7520 				dialog_done2 = 999;
7521 			} else {
7522 				/* not abort - undo button press */
7523 				dialog_done2 = 999;
7524 			}
7525 		}
7526 	}
7527 
7528 	close(read_err2);
7529 	close(read_err);
7530 	close(read_out);
7531 
7532 	/* remove temporary inf files */
7533 	if (isaudiocd) {
7534 		remove_onthefly_inf_files();
7535 	}
7536 
7537 	/* no disk */
7538 	if (read_output_ctrl == 2) {
7539 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
7540 		return 1;
7541 	}
7542 
7543 	/* cannot send cue sheet */
7544 	if (read_output_ctrl == 4) {
7545 		show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
7546 	}
7547 
7548 	/* aborted write ? */
7549 	if (read_output_ctrl == 1) {
7550 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
7551 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7552 		return 1;
7553 	}
7554 
7555 	/* error while reading ?*/
7556 	if (read_done != 0 || read_output_ctrl == 5) {
7557 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
7558 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7559                 if (read_done == 2) {
7560                         /* invalid cdrecord key - show window */
7561 			display_invalid_prodvdkey();
7562                 }
7563 		return 1;
7564 	} else {
7565 		/* all ok */
7566 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
7567 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
7568 		return 0;
7569 	}
7570 }
7571 
7572 
7573 /* call cdrecord to fixate a disk */
7574 
start_write_fixate_only(gint devnr)7575 gint start_write_fixate_only(gint devnr) {
7576 char tmp[MAXLINE];
7577 char tmp2[MAXLINE];
7578 char cmd[MAXLINE*10];  /* extra big buffer for very long cdrecord options */
7579 gint read_out, read_err;
7580 gint ret;
7581 gint wrmode;
7582 
7583 	/* if another write running, ignore */
7584 	if (read_done == 999) {
7585 		return -1;
7586 	}
7587 
7588 	/* mark our write-process as running */
7589 	read_done = 999;
7590 	read_output_ctrl = 0;
7591 	pct_so_far = 0.0;
7592 	cdrecord_reload = 0;
7593 	cdrtimer = 0;
7594 
7595 	/* set info label */
7596 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
7597 
7598 	/* get bus,id,lun string */
7599 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
7600 		g_error("non existing cdrom?");
7601 	}
7602 
7603 	/* build command line */
7604 	get_wrap_path_cdrecord(tmp2);
7605 	g_snprintf(cmd, MAXLINE*10,
7606 		"%s %s gracetime=%d -v -fix", tmp2, tmp, get_gracetime());
7607 
7608 	if (get_cur_writer_drvmode() >= 0) {
7609 		if (drivers[get_cur_writer_drvmode()] != NULL) {
7610 			g_snprintf(tmp,MAXLINE," driver=%s",
7611 				drivers[get_cur_writer_drvmode()]->driver);
7612 			strcat(cmd,tmp);
7613 		}
7614 	}
7615 
7616 	if (get_cur_writer_speed() >= 0) {
7617 		g_snprintf(tmp,MAXLINE," speed=%d", get_cur_writer_speed());
7618 		strcat(cmd, tmp);
7619 	}
7620 	if (curset.multisession == 0) {
7621 		wrmode = get_cur_writemode();
7622 		if (wrmode == 0) {
7623 			strcat(cmd," -dao");
7624 		}
7625 		if (wrmode == 2) {
7626 			strcat(cmd," defpregap=0");
7627 		}
7628 		if (wrmode == 3) {
7629 			strcat(cmd," -raw96r");
7630 		}
7631 		if (wrmode == 4) {
7632 			strcat(cmd," -raw96p");
7633 		}
7634 		if (wrmode == 5) {
7635 			strcat(cmd," -raw16");
7636 		}
7637 	}
7638 	if (curset.writesimul == 1) {
7639 		strcat(cmd," -dummy");
7640 	}
7641 	if (curset.writeeject == 1) {
7642 		strcat(cmd," -eject");
7643 	}
7644 	if (curset.multisession == 1) {
7645 		strcat(cmd," -multi");
7646 	}
7647         if (curset.writeignsize == 1) {
7648                 strcat(cmd," -ignsize");
7649         }
7650         if (curset.writeimmed == 1) {
7651                 strcat(cmd," -immed");
7652         }
7653 
7654 	dodebug(1, "spawning: %s\n",cmd);
7655 	dolog(1,"Fixate CD\n");
7656 	dolog(3,"Executing: %s\n", cmd);
7657 
7658 	/* yes...command line is done */
7659 	readcdda_pid = full_dpl_pipe3(&read_out,&cdrecord_stdin,&read_err,cmd,1);
7660 	readcdda_pid2 = -1;
7661 	mkisofs_pid = -1;
7662 
7663 	fcntl(read_out, F_SETFL, O_NONBLOCK);
7664 	fcntl(read_err, F_SETFL, O_NONBLOCK);
7665 
7666 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
7667 		(GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err));
7668 	readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
7669 		(GdkInputFunction) read_write_stderr, NULL);
7670 
7671 	/* now wait until write is finished */
7672 	while (read_done == 999) {
7673 		wait_and_process_events();
7674 
7675 		/* check if writer is waiting for reload medium */
7676 		if (cdrecord_reload > 0) {
7677 			cdrecord_reload = 0;
7678 			show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
7679 
7680 			/* now send CR to cdrecord to let it continue */
7681 			if (write(cdrecord_stdin, "\n", 1) != 1) {
7682 				g_warning("write error to cdrecord pipe\n");
7683 			}
7684 		}
7685 
7686 		/* check if somebody clicked on cancel */
7687 		if (dialog_done2 != 999) {
7688 			ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
7689 				T_YES, T_NO, NULL, 1);
7690 			if (ret == 0) {
7691 				/* really abort */
7692 				kill_readcdda();
7693 				/* mark we aborted */
7694 				read_output_ctrl = 1;
7695 				dialog_done2 = 999;
7696 			} else {
7697 				/* not abort - undo button press */
7698 				dialog_done2 = 999;
7699 			}
7700 		}
7701 	}
7702 
7703 	close(read_err);
7704 	close(read_out);
7705 	close(cdrecord_stdin);
7706 
7707 	/* no disk */
7708 	if (read_output_ctrl == 2) {
7709 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
7710 		return 1;
7711 	}
7712 	/* cannot send cue sheet */
7713 	if (read_output_ctrl == 4) {
7714 		show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
7715 	}
7716 
7717 	/* aborted write ? */
7718 	if (read_output_ctrl == 1) {
7719 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
7720 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7721 		return 1;
7722 	}
7723 
7724 	/* error while reading ?*/
7725 	if (read_done != 0 || read_output_ctrl == 5) {
7726 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
7727 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
7728                 if (read_done == 2) {
7729                         /* invalid cdrecord key - show window */
7730 			display_invalid_prodvdkey();
7731                 }
7732 		return 1;
7733 	} else {
7734 		/* all ok */
7735 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
7736 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
7737 		return 0;
7738 	}
7739 }
7740 
7741 
7742 /* parse output of rmtool and update sliders and textbox */
7743 
read_delete_out(gpointer data,gint source,GdkInputCondition cond)7744 static void read_delete_out(gpointer data, gint source, GdkInputCondition cond) {
7745 gint n;
7746 gint ret;
7747 gchar line[MAXLINE];
7748 gchar tmp[MAXLINE];
7749 gint val;
7750 gfloat pval;
7751 
7752 	/* read output of readcd */
7753 	n = read_line(source, line, MAXLINE);
7754 
7755 	/* delete finished */
7756 	if (n <= 0) {
7757 		gtk_input_remove(readcdda_callback);
7758 
7759 		/* pick up return status of child */
7760 		wait(&ret);
7761 
7762 		/* tell our caller that we are done here */
7763 		if (WEXITSTATUS(ret) == 0 && read_output_ctrl != 100) {
7764 			/* aborted */
7765 			read_done = 2;
7766 		} else {
7767 			read_done = WEXITSTATUS(ret);
7768 		}
7769 		return;
7770 	}
7771 
7772 	dodebug(10,"rmtool: %s\n", line);
7773 
7774 	/* look for a percent value */
7775 	if (line[strlen(line)-1] == '%') {
7776 		strcpy(tmp,line);
7777 		tmp[strlen(tmp)-1] = '\0';
7778 		strip_string(tmp);
7779 		val = atoi(tmp);
7780 		read_output_ctrl = val;
7781 		pval = (gfloat)val/100;
7782 		pval = (pval*delete_count + delete_start) /delete_all;
7783 		if (pval > 1.0) pval = 1.0;
7784 		gtk_progress_set_percentage(
7785 			GTK_PROGRESS(readtrack_pbar1), pval);
7786 		set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval*100+0.5));
7787 		return;
7788 	}
7789 
7790 	strcat(line,"\n");
7791 	convert_for_gtk2_textwidget(line);
7792 	gtk_text_insert(GTK_TEXT(readtrack_textview),
7793 		fixedfont,NULL,NULL, line, strlen(line));
7794 
7795 }
7796 
7797 
7798 /* does do the real deletion of some files */
7799 
do_delete_files(gchar * cmd,gint count,gint start,gint all)7800 static gint do_delete_files(gchar *cmd, gint count, gint start, gint all) {
7801 gint read_out;
7802 
7803 	/* set some global vars we need for progress-bar */
7804 	delete_count = count;
7805 	delete_start = start;
7806 	delete_all = all;
7807 
7808 	dodebug(1,"spawning: %s\n",cmd);
7809 	dolog(2,"Deleting %d files\n", count);
7810 	dolog(3,"Executing: %s\n", cmd);
7811 
7812 	readcdda_pid = full_dpl_pipe3(&read_out,NULL,NULL,cmd,0);
7813 	readcdda_pid2 = -1;
7814 
7815 	fcntl(read_out, F_SETFL, O_NONBLOCK);
7816 
7817 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
7818 		(GdkInputFunction) read_delete_out, NULL);
7819 
7820 
7821 	/* now wait until tracks are deleted */
7822 	while (read_done == 999) {
7823 		wait_and_process_events();
7824 	}
7825 
7826 	close(read_out);
7827 
7828 	return read_done;
7829 }
7830 
7831 
7832 /* do delete some tracks from the HD */
7833 /* do split the bulk in pieces of 50 files...to ensure there is no
7834    overrun of shell-arguments */
7835 
start_delete_action(GList * delfiles)7836 gint start_delete_action(GList *delfiles) {
7837 GList *loop;
7838 gchar *fname;
7839 gint length, broke;
7840 gint count,lastcount;
7841 gchar tmp[MAXLINE];
7842 gchar tmptmp[MAXLINE];
7843 gchar tmp2[MAXLINE];
7844 gchar infname[MAXLINE];
7845 gchar infname2[MAXLINE];
7846 char orgcmd[MAXLINE];
7847 char cmd[MAXLINE*10];
7848 gchar *p;
7849 
7850 	/* if another delete running, ignore */
7851 	if (read_done == 999) {
7852 		return -1;
7853 	}
7854 
7855 	read_done = 999;
7856 	read_output_ctrl = 0;
7857 	lastcount = 0;
7858 	broke = 0;
7859 
7860 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Deleting tracks..."));
7861 
7862 	/* build of command line */
7863 	g_snprintf(orgcmd,MAXLINE,"%s/%s ", sharedir, RMTOOL);
7864 	strcpy(cmd,orgcmd);
7865 
7866 	length = g_list_length(delfiles);
7867 	count = 0;
7868 
7869 	loop = g_list_first(delfiles);
7870 	while(loop) {
7871 		fname = (gchar *)loop->data;
7872 
7873 		/* remove extension and put .inf there */
7874 		strncpy(tmp,fname,MAXLINE - 4);
7875 		p = rindex(tmp,'.');
7876 		if (p == NULL) return -1;
7877 		strcpy(tmp2,p);
7878 		*p = '\0';
7879 		if (strcmp(tmp2,".toc") == 0) {
7880 			strcpy(tmptmp,fname);
7881 			g_snprintf(tmp2, MAXLINE, "\"%s\" ",
7882 				convert_escape(tmptmp));
7883 		} else {
7884 			strcpy(infname,tmp);
7885 			strcat(infname,XCDROAST_INFO_EXT);
7886 			strcpy(infname2,tmp);
7887 			strcat(infname2,CDDA2WAV_INFO_EXT);
7888 			strcpy(tmptmp,fname);
7889 			g_snprintf(tmp2, MAXLINE, "\"%s\" \"%s\" \"%s\" ",
7890 				convert_escape(tmptmp),
7891 				convert_escape(infname),
7892 				convert_escape(infname2));
7893 		}
7894 		strcat(cmd,tmp2);
7895 
7896 		count++;
7897 		if (count%50 == 0) {
7898 			/* part of commandline complete */
7899 			read_done = do_delete_files(cmd, count-lastcount, lastcount, length);
7900 			lastcount = count;
7901 			strcpy(cmd,orgcmd);
7902 
7903 			/* this run was successful? */
7904 			if (read_done == 0) {
7905 				read_done = 999;
7906 				read_output_ctrl = 0;
7907 			} else {
7908 				broke = 1;
7909 				break;
7910 			}
7911 		}
7912 		loop = loop->next;
7913 	}
7914 
7915 	/* any parts left over? (and no error before) */
7916 	if (count%50 != 0 && broke == 0) {
7917 			/* part of commandline complete */
7918 			read_done = do_delete_files(cmd, count-lastcount, lastcount, length);
7919 	}
7920 
7921 	/* all ok? */
7922 	if (read_done == 0) {
7923 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Delete successful"));
7924 	} else
7925 	if (read_done == 2) {
7926 		/* delete canceled */
7927 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Delete aborted..."));
7928 	} else {
7929 		/* some error */
7930 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error deleting tracks"));
7931 	}
7932 
7933 	return 0;
7934 }
7935 
7936 
7937 /* parse output of verfify-tool and update sliders */
7938 
verify_readcd_out(gpointer pid,gint source,GdkInputCondition cond)7939 static void verify_readcd_out(gpointer pid, gint source, GdkInputCondition cond) {
7940 gint n;
7941 gint ret;
7942 gchar line[MAXLINE];
7943 gchar tmp[MAXLINE];
7944 gint val;
7945 gfloat pval, pval2;
7946 
7947 	/* read output of vrfytool  */
7948 	n = read_line(source, line, MAXLINE);
7949 
7950 	/* readcd-finished? */
7951 	if (n <= 0) {
7952 		gtk_input_remove(readcdda_callback);
7953 
7954 		/* pick up return status of child */
7955 		waitpid((pid_t)GPOINTER_TO_INT(pid), &ret, WNOHANG);
7956 
7957 		/* tell our caller that we are done here */
7958 		read_done = WEXITSTATUS(ret);
7959 		return;
7960 	}
7961 
7962 	dodebug(10,"vry-readcd (stdout): %s\n", line);
7963 
7964 	/* look for a percent value */
7965 	if (line[strlen(line)-1] == '%') {
7966 
7967 		strcpy(tmp,line);
7968 		tmp[strlen(tmp)-1] = '\0';
7969 		strip_string(tmp);
7970 		val = atoi(tmp);
7971 
7972 		pval = (gfloat)val/100;
7973 		if (pval > 1.0) pval = 1.0;
7974 
7975 		gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar1),
7976 			pval);
7977 
7978 		/* now calculate how much percent he has at all */
7979 		pval2 = (pct_so_far + (pval * pct_this_track));
7980 		if (pval2 > 1.0) pval2 = 1.0;
7981 		gtk_progress_set_percentage(GTK_PROGRESS(readtrack_pbar2),
7982 			pval2);
7983 		set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval2*100+0.5));
7984 
7985 		/* now update info for small view */
7986 		g_snprintf(tmp,MAXLINE,"%d%% / %d%%",(gint)(pval*100+0.5),
7987 			   (gint)(pval2*100+0.5));
7988 		gtk_label_set_text(GTK_LABEL(readtrack_small_info2),tmp);
7989 
7990 		return;
7991 	}
7992 
7993 	/* forward all other output to textview-window */
7994 	strcat(line,"\n");
7995 	convert_for_gtk2_textwidget(line);
7996 	gtk_text_insert(GTK_TEXT(readtrack_textview),
7997 		fixedfont,NULL,NULL, line, strlen(line));
7998 }
7999 
8000 
8001 /* do just swallow all output we get from stderr... and wait if the
8002    process terminated */
8003 
verify_readcd_err(gpointer pid,gint source,GdkInputCondition cond)8004 static void verify_readcd_err(gpointer pid, gint source, GdkInputCondition cond) {
8005 gint n;
8006 gint ret;
8007 gchar line[MAXLINE];
8008 
8009 	/* read output of vrfytool */
8010 	n = read_line(source, line, MAXLINE);
8011 
8012 	/* readcd-finished? */
8013 	if (n <= 0) {
8014 		gtk_input_remove(readcdda_callback3);
8015 
8016                 /* pick up return status of child */
8017 		waitpid((pid_t)GPOINTER_TO_INT(pid), &ret, WNOHANG);
8018 
8019                 dodebug(10,"Finished in verify_readcd_err\n");
8020 
8021 		return;
8022 	}
8023 
8024 	dodebug(10,"readcd/cdda2wav (stderr): %s\n", line);
8025 }
8026 
8027 
8028 /* does call readcd | vrfytool to do verifying */
8029 
verify_data_track(gint devnr,gint starttrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)8030 gint verify_data_track(gint devnr, gint starttrack, gint kbyte,
8031 		      gchar *fname, gint startoffset, gint endoffset,
8032 		      gint nrtracks, gfloat percent, gfloat percent_done,
8033 		      gint viewtrack) {
8034 gchar cmd[MAXLINE];
8035 gchar cmd2[MAXLINE];
8036 gchar tmp[MAXLINE];
8037 gchar tmptmp[MAXLINE];
8038 gchar tmp2[MAXLINE];
8039 gchar tmp3[MAXLINE];
8040 gint read_out, read_err, sectsize;
8041 pid_t pid1, pid2;
8042 
8043 	/* if another read running, ignore */
8044 	if (read_done == 999) {
8045 		return -1;
8046 	}
8047 
8048 	/* no filename given? */
8049 	if (fname == NULL) {
8050 		return 1;
8051 	}
8052 
8053 	/* mark our read-process as running */
8054 	read_done = 999;
8055 	readcdda_pid = -1;
8056 	readcdda_pid2 = -1;
8057 	read_output_ctrl = 0;
8058 	read_abort_mark = 0;
8059 
8060 	/* set info-label */
8061 	convert_kbytes2mbminstring(kbyte, tmp);
8062 	g_snprintf(tmp2,MAXLINE,_("Verifying data track %d/%d [%s]"), viewtrack, nrtracks, tmp);
8063 	gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
8064 
8065 	g_snprintf(tmp2,MAXLINE,_("Verifying %d/%d:"), viewtrack, nrtracks);
8066 	gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
8067 
8068 	/* get bus,id,lun string */
8069 	if (convert_devnr2busid_dev(devnr,tmp) != 0) {
8070 		g_error("non existing cdrom?");
8071 	}
8072 
8073 	/* some stuff to have our slider moving smoothly no matter how
8074 	   big the tracks are */
8075 	pct_so_far = percent_done;
8076 	pct_this_track = percent;
8077 
8078         /* now check which sectorsize we got */
8079         sectsize = get_sectorsize(devnr);
8080 	if (sectsize == 2352) {
8081 		/* workaround for buggy drives */
8082         	endoffset = ((endoffset * DATASECTORSIZE) / sectsize) + 1;
8083 	}
8084 
8085 	get_wrap_path("READCD", tmp3);
8086 	g_snprintf(cmd,MAXLINE,
8087 		   "%s %s sectors=%d-%d -s f=-",
8088 		   tmp3, tmp, startoffset, endoffset);
8089 
8090 	strcpy(tmptmp, fname);
8091 
8092 	/* always verify in 512 bytes blocks */
8093 	g_snprintf(cmd2,MAXLINE,"%s/%s -b \"%s\" -",
8094 		   sharedir, VRFYTOOL, convert_escape(tmptmp));
8095 
8096 	dodebug(1, "spawning: %s | %s\n",cmd,cmd2);
8097 	dolog(2, "Verify data track %s\n", fname);
8098 	dolog(3, "Executing: %s | %s\n", cmd, cmd2);
8099 
8100 	/* start childs and get new fds */
8101 	full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,NULL,cmd2,0);
8102 	readcdda_pid = pid1;
8103 	readcdda_pid2 = -1;
8104 
8105 	/* set output to nonblocking - otherwise our callback would block */
8106 	fcntl(read_out, F_SETFL, O_NONBLOCK);
8107 	fcntl(read_err, F_SETFL, O_NONBLOCK);
8108 
8109 	/* catch output of child */
8110 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
8111 		(GdkInputFunction) verify_readcd_out, GINT_TO_POINTER(pid2));
8112 	readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
8113 		(GdkInputFunction) verify_readcd_err, GINT_TO_POINTER(pid1));
8114 
8115 	/* now wait until track is read */
8116 	while (read_done == 999) {
8117 		wait_and_process_events();
8118 	}
8119 
8120 	close(read_out);
8121 	close(read_err);
8122 
8123 	gtk_text_insert(GTK_TEXT(readtrack_textview),
8124 		fixedfont,NULL,NULL, "\n", 1);
8125 
8126 	/* error while reading? */
8127 	if (read_done != 0 && read_abort_mark == 0) {
8128 		g_snprintf(tmp,MAXLINE,_("Verifying data track %d/%d failed"), starttrack, nrtracks);
8129 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
8130 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Verify-Error:"));
8131 		return 1;
8132 	}
8133 	/* compare aborted? */
8134 	if (read_abort_mark != 0) {
8135 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Verify aborted..."));
8136 		return 2;
8137 	}
8138 
8139 	return 0;
8140 }
8141 
8142 
8143 /* does call cdda2wav | vrfytool to do verifying */
8144 
verify_audio_track(gint devnr,gint starttrack,gint endtrack,gint kbyte,gchar * fname,gint startoffset,gint endoffset,gint nrtracks,gfloat percent,gfloat percent_done,gint viewtrack)8145 gint verify_audio_track(gint devnr, gint starttrack, gint endtrack, gint kbyte,
8146 		      gchar *fname, gint startoffset, gint endoffset,
8147 		      gint nrtracks, gfloat percent, gfloat percent_done,
8148 		      gint viewtrack) {
8149 gchar cmd[MAXLINE];
8150 gchar cmd2[MAXLINE];
8151 gchar tmp[MAXLINE];
8152 gchar tmptmp[MAXLINE];
8153 gchar tmp2[MAXLINE];
8154 gchar tmp3[MAXLINE];
8155 gchar tmp4[MAXLINE];
8156 gchar tmp6[MAXLINE];
8157 gint read_out, read_err;
8158 pid_t pid1, pid2;
8159 
8160 	/* if another read running, ignore */
8161 	if (read_done == 999) {
8162 		return -1;
8163 	}
8164 
8165 	/* no filename given? */
8166 	if (fname == NULL) {
8167 		return 1;
8168 	}
8169 
8170 	/* mark our read-process as running */
8171 	read_done = 999;
8172 	readcdda_pid = -1;
8173 	readcdda_pid2 = -1;
8174 	read_output_ctrl = 0;
8175 	read_abort_mark = 0;
8176 
8177 	/* set info-label */
8178 	convert_kbytes2mbminstring(kbyte, tmp);
8179 	g_snprintf(tmp2,MAXLINE,_("Verifying audio track %d/%d [%s]"), viewtrack, nrtracks, tmp);
8180 	gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
8181 
8182 	g_snprintf(tmp2,MAXLINE,_("Verifying %d/%d:"), viewtrack, nrtracks);
8183 	gtk_label_set_text(GTK_LABEL(readtrack_small_info),tmp2);
8184 
8185 	/* get bus,id,lun string */
8186 	if (convert_devnr2busid(devnr,tmp) != 0) {
8187 		g_error("non existing cdrom?");
8188 	}
8189 
8190 	/* some stuff to have our slider moving smoothly no matter how
8191 	   big the tracks are */
8192 	pct_so_far = percent_done;
8193 	pct_this_track = percent;
8194 
8195 	/* build command line */
8196 	if (endtrack != 0) {
8197 		g_snprintf(tmp2,MAXLINE,"%d+%d",starttrack,endtrack);
8198 	} else {
8199 		g_snprintf(tmp2,MAXLINE,"%d",starttrack);
8200 	}
8201 
8202 	/* set speed only when not zero */
8203 	if (get_cur_audioread_speed() > 0) {
8204 		g_snprintf(tmp3,MAXLINE,"-S %d", get_cur_audioread_speed());
8205 	} else {
8206 		strcpy(tmp3,"");
8207 	}
8208 
8209 	if (get_cur_audioread_useparanoia()) {
8210 		g_snprintf(tmp6, MAXLINE, "-paranoia -paraopts=retries=%d", get_cur_audioread_paranoiaretries());
8211 	} else {
8212 		strcpy(tmp6,"");
8213 	}
8214 
8215 	get_wrap_path("CDDA2WAV", tmp4);
8216 	g_snprintf(cmd,MAXLINE,
8217 		  "%s -D \"%s\" -g -H -v toc -O wav -t %s %s -P %d -n %d %s -",
8218 		  tmp4,tmp,tmp2,tmp3,
8219 		  get_cur_audioread_overlap(), get_cur_audioread_sectorburst(),
8220 		  tmp6);
8221 
8222 	strcpy(tmptmp,fname);
8223 	g_snprintf(cmd2,MAXLINE,"%s/%s -a \"%s\" -",
8224 		   sharedir, VRFYTOOL, convert_escape(tmptmp));
8225 
8226 	dodebug(1, "spawning: %s | %s\n",cmd,cmd2);
8227 	dolog(2, "Verify audio track %s\n", fname);
8228 	dolog(3, "Executing: %s | %s\n", cmd, cmd2);
8229 
8230 	/* start childs and get new fds */
8231 	full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,NULL,cmd2,0);
8232 	readcdda_pid = pid1;
8233 	readcdda_pid2 = -1;
8234 
8235 	/* set output to nonblocking - otherwise our callback would block */
8236 	fcntl(read_out, F_SETFL, O_NONBLOCK);
8237 	fcntl(read_err, F_SETFL, O_NONBLOCK);
8238 
8239 	/* catch output of child */
8240 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
8241 		(GdkInputFunction) verify_readcd_out, GINT_TO_POINTER(pid2));
8242 	readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
8243 		(GdkInputFunction) verify_readcd_err, GINT_TO_POINTER(pid1));
8244 
8245 	/* now wait until track is read */
8246 	while (read_done == 999) {
8247 		wait_and_process_events();
8248 	}
8249 
8250 	close(read_out);
8251 	close(read_err);
8252 
8253 	gtk_text_insert(GTK_TEXT(readtrack_textview),
8254 		fixedfont,NULL,NULL, "\n", 1);
8255 
8256 	/* error while reading? */
8257 	if (read_done != 0 && read_abort_mark == 0) {
8258 		g_snprintf(tmp,MAXLINE,_("Verifying audio track %d/%d failed"), starttrack, nrtracks);
8259 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp);
8260 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Verify-Error:"));
8261 		return 1;
8262 	}
8263 	/* compare aborted? */
8264 	if (read_abort_mark != 0) {
8265 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Verify aborted..."));
8266 		return 2;
8267 	}
8268 
8269 	return 0;
8270 }
8271 
8272 
8273 /* parse output of cddbtool and update textbox */
8274 
read_cddbtool_out(gpointer data,gint source,GdkInputCondition cond)8275 static void read_cddbtool_out(gpointer data, gint source, GdkInputCondition cond) {
8276 gint n;
8277 gint ret;
8278 gint code, mode;
8279 gchar line[MAXLINE];
8280 gchar tmp[MAXLINE];
8281 gchar *p;
8282 gchar *rowdata[1];
8283 
8284 	/* mode 0 for cd, mode 1 for tocfile, mode 2 for on-the-fly */
8285 	mode = GPOINTER_TO_INT(data);
8286 
8287 	/* read output of readcd */
8288 	n = read_line(source, line, MAXLINE);
8289 
8290 	/* cddbtool finished */
8291 	if (n <= 0) {
8292 		gtk_input_remove(readcdda_callback);
8293 
8294 		/* pick up return status of child */
8295 		wait(&ret);
8296 
8297 		read_done = WEXITSTATUS(ret);
8298 		return;
8299 	}
8300 
8301 	dodebug(10, "cddbtool: %s\n", line);
8302 
8303 	/* got we the number of matches? */
8304 	if (line[0] == '%') {
8305 		strcpy(tmp,line+1);
8306 		matchnr = atoi(tmp);
8307 		return;
8308 	}
8309 
8310 	/* got we a entry for the match list? */
8311 	if (line[0] == '#') {
8312 		/* end-delimitor found */
8313 		if (strncmp(line,"#--",3) == 0) {
8314 			/* now see if we have only one match - preselect */
8315 			if (matchnr == 1) {
8316 				gtk_clist_select_row(cddb_clist,0,0);
8317 			}
8318 			return;
8319 		}
8320 		/* add this to the clist */
8321 		strcpy(tmp,line);
8322 		if (extract_quoted(tmp) != 0)
8323 			return;
8324 
8325 		/* now add decoded string to clist */
8326 		rowdata[0] = convert_for_gtk2(tmp);
8327 		gtk_clist_append(cddb_clist,rowdata);
8328 		return;
8329 	}
8330 
8331 	/* get output id of read line */
8332 	strcpy(tmp,line);
8333 	p = strtok(tmp,":");
8334 	if (p == NULL) {
8335 		return;
8336 	}
8337 	code = atoi(p);
8338 
8339 	strcpy(tmp,"");
8340 
8341 	/* display fitting text */
8342 	switch(code) {
8343 	case 0:
8344 		g_snprintf(tmp,MAXLINE,_("Connecting to %s:%d"),
8345 			setupdata.cddb_host, setupdata.cddb_port);
8346 		break;
8347 	case 1:
8348 		strcpy(tmp,_("Connect ok: Sending handshake"));
8349 		break;
8350 	case 2:
8351 		strcpy(tmp,_("Sending CDDB-query"));
8352 		break;
8353 	case 3:
8354 		strcpy(tmp,_("No matches found - unknown CD"));
8355 		break;
8356 	case 4:
8357 		/* close matches */
8358 		if (matchnr == 1) {
8359 			strcpy(tmp,_("Found one close match"));
8360 		} else {
8361 			g_snprintf(tmp,MAXLINE,_("Found %d close matches - Please select"), matchnr);
8362 		}
8363 		break;
8364 	case 5:
8365 		/* exact matches */
8366 		if (matchnr == 1) {
8367 			strcpy(tmp,_("Found one exact match"));
8368 		} else {
8369 			g_snprintf(tmp,MAXLINE,_("Found %d exact matches - Please select"), matchnr);
8370 		}
8371 		break;
8372 	case 6:
8373 		strcpy(tmp,_("Requesting data - Please wait"));
8374 		break;
8375 	case 7:
8376 		/* got disc-title */
8377 		strcpy(tmp,line);
8378 		if (extract_quoted(tmp) != 0)
8379 			return;
8380 
8381 		/* we want title first, then artist */
8382 		if (mode == 0) {
8383 			switch_artist_title(tmp);
8384 			g_free(cdinfo.cddb_dtitle);
8385 			cdinfo.cddb_dtitle = g_strdup(tmp);
8386 
8387 			dolog(3, "CDDB lookup done for %s\n", cdinfo.cddb_dtitle);
8388 		} else {
8389 			cdtext_set_dtitle(tmp);
8390 			dolog(3, "CDDB lookup done for %s\n", tmp);
8391 		}
8392 
8393 		/* recycle matchnr-var as track-counter */
8394 		matchnr = 0;
8395 
8396 		return;
8397 	case 8:
8398 		/* got track-title */
8399 		strcpy(tmp,line);
8400 		if (extract_quoted(tmp) != 0)
8401 			return;
8402 
8403 		if (mode == 0) {
8404 			if (matchnr >= cdinfo.nr_tracks) {
8405 				g_warning("invalid track count from cddb-server\n");
8406 				return;
8407 			}
8408 
8409 			g_free(trackinfo[matchnr]->cddb_ttitle);
8410 			trackinfo[matchnr]->cddb_ttitle = g_strdup(tmp);
8411 		} else {
8412 			cdtext_set_ttitle(tmp, matchnr+1);
8413 		}
8414 		matchnr++;
8415 		return;
8416 
8417 	/* Error-codes */
8418 	case -1:
8419 		strcpy(tmp,_("Error: Hostname lookup failure"));
8420 		break;
8421 	case -2:
8422 		strcpy(tmp,_("Error: Can't open stream socket"));
8423 		break;
8424 	case -3:
8425 		strcpy(tmp,_("Error: Connection refused"));
8426 		break;
8427 	case -4:
8428 		strcpy(tmp,_("Error: No response from server"));
8429 		break;
8430 	case -5:
8431 		strcpy(tmp,_("Error: No answer within timeout"));
8432 		break;
8433 	case -6:
8434 		strcpy(tmp,_("Handshake failed - No valid CDDB-server?"));
8435 		break;
8436 	case -7:
8437 		strcpy(tmp,_("Error: CDDB-query failed"));
8438 		break;
8439 	case -8:
8440 		strcpy(tmp,_("Error: CDDB-read failed"));
8441 		break;
8442 	case -9:
8443 		strcpy(tmp,_("Warning: CDDB-logout failed"));
8444 		break;
8445 	case -10:
8446 		strcpy(tmp,_("Error: CDDB write error on socket"));
8447 		break;
8448 	case -11:
8449 		strcpy(tmp,_("Error: CDDB read error on socket"));
8450 		break;
8451 	}
8452 
8453 	gtk_label_set_text(GTK_LABEL(cddb_info_label), tmp);
8454 }
8455 
8456 
8457 /* do lookup the cddb-database */
8458 /* mode = 0, cddb lookup based on CD
8459    mode = 1, cddb lookup based on toc-file
8460    mode = 2, cddb lookup based on CD but called from edit-cdtext */
8461 
start_cddb_lookup_action(gint mode)8462 gint start_cddb_lookup_action(gint mode) {
8463 gchar tmp[MAXLINE];
8464 gchar tmp2[MAXLINE];
8465 gchar tmp_cddbhost[MAXLINE];
8466 gchar tmp_cddbproxy[MAXLINE];
8467 char cmd[MAXLINE];
8468 track_read_param_t *trackparam;
8469 GList *loop;
8470 gint read_out;
8471 gint i;
8472 
8473 	/* if another lookup running, ignore */
8474 	if (read_done == 999) {
8475 		return -1;
8476 	}
8477 
8478 	read_done = 999;
8479 	read_output_ctrl = 0;
8480 	matchnr = 0;
8481 
8482 	/* build of command line */
8483 	if (mode == 0 || mode == 2) {
8484 		g_snprintf(tmp,MAXLINE,"cddb query %s %d ",
8485 			cdinfo.cddb_discid, cdinfo.nr_tracks);
8486 		for (i = 0; i < cdinfo.nr_tracks; i++) {
8487 			g_snprintf(tmp2,MAXLINE,"%d ",
8488 				trackinfo[i]->start_sec + 150);
8489 			strcat(tmp,tmp2);
8490 		}
8491 		g_snprintf(tmp2,MAXLINE,"%d",cdinfo.total_size / 75);
8492 		strcat(tmp,tmp2);
8493 	} else {
8494 		/* get data from toc file */
8495 		g_snprintf(tmp,MAXLINE,"cddb query %s %d ",
8496 			trackreadset.cd_discid, trackreadset.nrtracks);
8497 		loop = g_list_first(trackreadset.trackparams);
8498 		for (i = 0; i < trackreadset.nrtracks; i++) {
8499 			trackparam = loop->data;
8500 			if (trackparam) {
8501 				g_snprintf(tmp2,MAXLINE,"%d ",
8502 					trackparam->start_sec + 150);
8503 				strcat(tmp,tmp2);
8504 			} else {
8505 				g_warning("trackreadset corruption detected.\n");
8506 			}
8507 			loop = loop->next;
8508 		}
8509 		g_snprintf(tmp2,MAXLINE,"%d",trackreadset.cdsize / 75);
8510 		strcat(tmp,tmp2);
8511 	}
8512 
8513 	strncpy(tmp_cddbhost, setupdata.cddb_host, MAXLINE);
8514 	convert_escape(tmp_cddbhost);
8515 	strncpy(tmp_cddbproxy, setupdata.cddb_proxy_host, MAXLINE);
8516 	convert_escape(tmp_cddbproxy);
8517 
8518 	if (setupdata.cddb_use_http == 0) {
8519 	  	g_snprintf(cmd,MAXLINE,
8520 		"%s/%s -s \"%s\" -p %d -u \"%s\" -h \"%s\" -q \"%s\"",
8521 		sharedir, CDDBTOOL, tmp_cddbhost, setupdata.cddb_port,
8522 		username, hostname, tmp);
8523 	} else {
8524 		/* we want to use http */
8525 		if (setupdata.cddb_use_proxy == 0) {
8526 			/* but no proxy */
8527 	  		g_snprintf(cmd,MAXLINE,
8528 			"%s/%s -s \"%s\" -u \"%s\" -h \"%s\" -H -q \"%s\"",
8529 			sharedir, CDDBTOOL, tmp_cddbhost,
8530 			username, hostname, tmp);
8531 		} else {
8532 			/* http with proxy */
8533 	  		g_snprintf(cmd,MAXLINE,
8534 			"%s/%s -s \"%s\" -u \"%s\" -h \"%s\" -U \"%s\" -P %d -q \"%s\"",
8535 			sharedir, CDDBTOOL, tmp_cddbhost,
8536 			username, hostname, tmp_cddbproxy,
8537 			setupdata.cddb_proxy_port, tmp);
8538 		}
8539 	}
8540 	dodebug(1, "spawning: %s\n",cmd);
8541 	if (mode == 0 || mode == 2) {
8542 		dolog(2, "CDDB lookup for discid %s\n", cdinfo.cddb_discid);
8543 	} else {
8544 		dolog(2, "CDDB lookup for discid %s (from toc-file)\n", trackreadset.cd_discid);
8545 	}
8546 	dolog(3, "Executing: %s\n", cmd);
8547 
8548 	readcdda_pid = full_dpl_pipe3(&read_out,&cddb_in,NULL,cmd,0);
8549 	readcdda_pid2 = -1;
8550 
8551 	fcntl(read_out, F_SETFL, O_NONBLOCK);
8552 
8553 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
8554 		(GdkInputFunction) read_cddbtool_out, GINT_TO_POINTER(mode));
8555 
8556 
8557 	/* now wait until track is read */
8558 	while (read_done == 999) {
8559 		wait_and_process_events();
8560 	}
8561 
8562 	close(read_out);
8563 	close(cddb_in);
8564 
8565 	return read_done;
8566 }
8567 
8568 
8569 /* the user selected a specific row on cddb-window */
8570 
continue_cddb_lookup_action(gint match)8571 gint continue_cddb_lookup_action(gint match) {
8572 gchar tmp[MAXLINE];
8573 
8574 	dodebug(2, "sending %d to cddbtool\n", match);
8575 
8576 	/* send this match back to our cddbtool-process */
8577 	g_snprintf(tmp,MAXLINE,"%d\n",match);
8578 	if (write(cddb_in, tmp, strlen(tmp)) != strlen(tmp)) {
8579 		g_warning("write error to cddbtool pipe\n");
8580 		return 1;
8581 	}
8582 	return 0;
8583 }
8584 
8585 
8586 /* call wavplay test.wav */
8587 
test_dspdevice_play()8588 void test_dspdevice_play() {
8589 gchar line[MAXLINE];
8590 FILE *fpin;
8591 
8592 	/* allocate memory */
8593 	g_snprintf(line,MAXLINE,"%s/%s -d \"%s\" \"%s/%s\" 2>&1", sharedir,
8594 			WAVPLAY, setupdata.dsp_device, sharedir, DSPTESTSOUND);
8595 
8596 	dodebug(1, "calling: %s\n", line);
8597 
8598         if ((fpin = popen(line,"r")) == NULL) {
8599                 g_error("popen error\n");
8600         }
8601 
8602         for (;;) {
8603                 if (fgets(line,MAXLINE,fpin) == NULL)
8604                         break;
8605 		dodebug(10, "dsptest: %s", line);
8606         }
8607 
8608         if (pclose(fpin) == -1) {
8609                 g_error("pclose error\n");
8610         }
8611 
8612 }
8613 
8614 
8615 /* Save the current iso-options to a file - all strings are converted
8616    in a printable form first:  return 0 if ok, or 1 on error */
8617 
save_isooptions_file(gchar * confdir,gchar * fname)8618 gint save_isooptions_file(gchar *confdir, gchar *fname) {
8619 FILE *fd;
8620 gchar tmp[MAXLINE];
8621 gint i;
8622 
8623         /* now check if the confdir exists */
8624         if (!is_directory(confdir)) {
8625                 /* try to create directory */
8626                 mkdir(confdir, 0700);
8627                 dodebug(2, "trying to mkdir %s\n", confdir);
8628         }
8629 
8630 	g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
8631 
8632         dodebug(1, "Opening %s for writing\n", tmp);
8633         dolog(3, "Saving isooptions file %s\n", tmp);
8634 
8635         fd = fopen(tmp,"w");
8636 
8637         if (fd == NULL) {
8638                 /* error opening file */
8639                 return 1;
8640         }
8641 
8642         /* write the config-file header */
8643         fputs("#\n",fd);
8644         g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Iso-Options-File\n",XCDROAST_VERSION);
8645         fputs(tmp,fd);
8646         fputs("#\n",fd);
8647         fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
8648         fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
8649         fputs("#\n\n",fd);
8650 
8651         /* write data */
8652         g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
8653         fputs(tmp,fd);
8654         g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
8655         fputs(tmp,fd);
8656 
8657 	for (i=0; i<24; i++) {
8658 		g_snprintf(tmp,MAXLINE,"OPT_%d = %d\n", i,
8659 			masterparam.opt[i]);
8660         	fputs(tmp,fd);
8661 	}
8662 
8663         g_snprintf(tmp,MAXLINE,"IN_CHARSET = \"%s\"\n",
8664 		charset_types[masterparam.charset]);
8665         fputs(tmp,fd);
8666         g_snprintf(tmp,MAXLINE,"OUT_CHARSET = \"%s\"\n",
8667 		charset_types[masterparam.outcharset]);
8668         fputs(tmp,fd);
8669 
8670 	g_snprintf(tmp,MAXLINE,"SHOW_ONLY_DIRS = %d\n",
8671 			masterparam.show_only_dirs);
8672        	fputs(tmp,fd);
8673 	g_snprintf(tmp,MAXLINE,"SHOW_HIDDEN_FILES = %d\n",
8674 			masterparam.show_hidden_files);
8675        	fputs(tmp,fd);
8676 
8677         if (fclose(fd) != 0) {
8678                 /* error closing file */
8679                 return 1;
8680         }
8681 
8682         return 0;
8683 }
8684 
8685 
8686 /* Load the iso-options-default file
8687    return 0 if ok, or 1 on error */
8688 
load_isooptions_file(gchar * fname)8689 gint load_isooptions_file(gchar *fname) {
8690 FILE *fd;
8691 gchar line[MAXLINE];
8692 gchar id[MAXLINE];
8693 gchar value[MAXLINE];
8694 gchar tmp[MAXLINE];
8695 gint optval, optnr, i;
8696 
8697         if ((fd = fopen(fname,"r")) == NULL) {
8698                 /* error opening file */
8699         	dodebug(1, "Failed to open iso options file %s\n", fname);
8700         	dolog(3, "Failed loading iso options file %s\n", fname);
8701                 return 1;
8702         }
8703 
8704         dodebug(1, "Opening iso options file %s for reading\n", fname);
8705         dolog(3, "Loading iso options file %s\n", fname);
8706 
8707         for (;;) {
8708                 if (fgets(line,MAXLINE,fd) == NULL)
8709                         break;
8710 
8711                 dodebug(10,"isooptions: %s", line),
8712 
8713                 /* skip empty or hashed lines */
8714                 strip_string(line);
8715                 if (*line == '#' || *line == '\0')
8716                         continue;
8717 
8718                 /* parse lines */
8719 		if (parse_config_line(line,id,value)) {
8720                 	g_error("syntax error in isooptions-file\n");
8721 		}
8722 
8723 		if (strncmp("OPT_",id,4) == 0) {
8724 			strcpy(tmp,id+4);
8725 			optnr = atoi(tmp);
8726 			optval = atoi(value);
8727 			if (optnr < 24)
8728 				masterparam.opt[optnr] = optval;
8729 		}
8730 
8731                 if (strncmp("IN_CHARSET",id,7) == 0) {
8732                         masterparam.charset = 0;
8733                         i = 0;
8734                         while (charset_types[i] != NULL) {
8735                                 if (strcmp(charset_types[i],value) == 0) {
8736                                         masterparam.charset = i;
8737                                         break;
8738                                 }
8739                                 i++;
8740                         }
8741                 }
8742                 if (strncmp("OUT_CHARSET",id,7) == 0) {
8743                         masterparam.outcharset = 0;
8744                         i = 0;
8745                         while (charset_types[i] != NULL) {
8746                                 if (strcmp(charset_types[i],value) == 0) {
8747                                         masterparam.outcharset = i;
8748                                         break;
8749                                 }
8750                                 i++;
8751                         }
8752                 }
8753 
8754 		if (strcmp("SHOW_ONLY_DIRS",id) == 0) {
8755 			masterparam.show_only_dirs = atoi(value);
8756 		}
8757 		if (strcmp("SHOW_HIDDEN_FILES",id) == 0) {
8758 			masterparam.show_hidden_files = atoi(value);
8759 		}
8760 
8761 	}
8762 
8763         if (fclose(fd) != 0) {
8764                 /* error closing file */
8765                 return 1;
8766         }
8767 
8768         return 0;
8769 }
8770 
8771 
8772 /* Save the current iso-headers to a file - all strings are converted
8773    in a printable form first:  return 0 if ok, or 1 on error */
8774 
save_isoheaders_file(gchar * confdir,gchar * fname)8775 gint save_isoheaders_file(gchar *confdir, gchar *fname) {
8776 FILE *fd;
8777 gchar tmp[MAXLINE];
8778 gchar tmp2[MAXLINE];
8779 
8780         /* now check if the confdir exists */
8781         if (!is_directory(confdir)) {
8782                 /* try to create directory */
8783                 mkdir(confdir, 0700);
8784                 dodebug(2, "trying to mkdir %s\n", confdir);
8785         }
8786 
8787 	g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
8788 
8789         dodebug(1, "Opening %s for writing\n", tmp);
8790         dolog(3, "Saving isoheaders file %s\n", tmp);
8791 
8792         fd = fopen(tmp,"w");
8793 
8794         if (fd == NULL) {
8795                 /* error opening file */
8796                 return 1;
8797         }
8798 
8799         /* write the config-file header */
8800         fputs("#\n",fd);
8801         g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Iso-Headers-File\n",XCDROAST_VERSION);
8802         fputs(tmp,fd);
8803         fputs("#\n",fd);
8804         fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
8805         fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
8806         fputs("#\n\n",fd);
8807 
8808         /* write data */
8809         g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
8810         fputs(tmp,fd);
8811         g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
8812         fputs(tmp,fd);
8813 
8814 	strcpy(tmp2,masterparam.publisher);
8815 	g_snprintf(tmp,MAXLINE,"PUBLISHER = \"%s\"\n",convert_escape(tmp2));
8816 	fputs(tmp,fd);
8817 	strcpy(tmp2,masterparam.preparer);
8818 	g_snprintf(tmp,MAXLINE,"PREPARER = \"%s\"\n",convert_escape(tmp2));
8819 	fputs(tmp,fd);
8820 	/*
8821 	strcpy(tmp2,masterparam.application);
8822 	g_snprintf(tmp,MAXLINE,"APPLICATION = \"%s\"\n",convert_escape(tmp2));
8823 	fputs(tmp,fd);
8824 	*/
8825 	strcpy(tmp2,masterparam.abstract);
8826 	g_snprintf(tmp,MAXLINE,"ABSTRACT = \"%s\"\n",convert_escape(tmp2));
8827 	fputs(tmp,fd);
8828 	strcpy(tmp2,masterparam.biblio);
8829 	g_snprintf(tmp,MAXLINE,"BIBLIO = \"%s\"\n",convert_escape(tmp2));
8830 	fputs(tmp,fd);
8831 	strcpy(tmp2,masterparam.copyright);
8832 	g_snprintf(tmp,MAXLINE,"COPYRIGHT = \"%s\"\n",convert_escape(tmp2));
8833 	fputs(tmp,fd);
8834 
8835         if (fclose(fd) != 0) {
8836                 /* error closing file */
8837                 return 1;
8838         }
8839 
8840         return 0;
8841 }
8842 
8843 
8844 /* Load the iso-headers-default file
8845    return 0 if ok, or 1 on error */
8846 
load_isoheaders_file(gchar * fname)8847 gint load_isoheaders_file(gchar *fname) {
8848 FILE *fd;
8849 gchar line[MAXLINE];
8850 gchar id[MAXLINE];
8851 gchar value[MAXLINE];
8852 
8853         if ((fd = fopen(fname,"r")) == NULL) {
8854                 /* error opening file */
8855         	dodebug(1, "Failed to open iso headers file %s\n", fname);
8856         	dolog(3, "Failed loading iso headers file %s\n", fname);
8857                 return 1;
8858         }
8859 
8860         dodebug(1, "Opening iso headers file %s for reading\n", fname);
8861         dolog(3, "Loading iso headers file %s\n", fname);
8862 
8863         for (;;) {
8864                 if (fgets(line,MAXLINE,fd) == NULL)
8865                         break;
8866 
8867                 dodebug(10,"isoheaders: %s", line),
8868 
8869                 /* skip empty or hashed lines */
8870                 strip_string(line);
8871                 if (*line == '#' || *line == '\0')
8872                         continue;
8873 
8874                 /* parse lines */
8875 		if (parse_config_line(line,id,value)) {
8876                 	g_error("syntax error in isoheaders-file\n");
8877 		}
8878 
8879 		if (strcmp("PUBLISHER",id) == 0) {
8880 			g_free(masterparam.publisher);
8881 			masterparam.publisher = g_strdup(value);
8882 		}
8883 		if (strcmp("PREPARER",id) == 0) {
8884 			g_free(masterparam.preparer);
8885 			masterparam.preparer = g_strdup(value);
8886 		}
8887 		if (strcmp("APPLICATION",id) == 0) {
8888 			g_free(masterparam.application);
8889 			masterparam.application = g_strdup(value);
8890 		}
8891 		if (strcmp("ABSTRACT",id) == 0) {
8892 			g_free(masterparam.abstract);
8893 			masterparam.abstract = g_strdup(value);
8894 		}
8895 		if (strcmp("BIBLIO",id) == 0) {
8896 			g_free(masterparam.biblio);
8897 			masterparam.biblio = g_strdup(value);
8898 		}
8899 		if (strcmp("COPYRIGHT",id) == 0) {
8900 			g_free(masterparam.copyright);
8901 			masterparam.copyright = g_strdup(value);
8902 		}
8903 	}
8904 
8905         if (fclose(fd) != 0) {
8906                 /* error closing file */
8907                 return 1;
8908         }
8909 
8910         return 0;
8911 }
8912 
8913 
8914 /* print master dirs and excludes (debug purposes) */
8915 
print_master_dirs()8916 static void print_master_dirs() {
8917 GList *loop;
8918 mstr_redirect_t *mstr;
8919 gchar *p;
8920 
8921 	dodebug(2,"------ directories to master -----\n");
8922 	loop = g_list_first(masterparam.mstr_redir);
8923 	while (loop) {
8924 		mstr = (mstr_redirect_t *) loop->data;
8925 
8926 		if (mstr) {
8927 			if (mstr->mstr_path && !mstr->redir_path) {
8928 				dodebug(2,"master-dir: %s\n", mstr->mstr_path);
8929 			}
8930 			if (mstr->mstr_path && mstr->redir_path) {
8931 				dodebug(2,"master-dir: %s -> %s\n",
8932 					mstr->mstr_path, mstr->redir_path);
8933 			}
8934 		}
8935 		loop = loop->next;
8936 	}
8937 
8938 	dodebug(2,"------ directories to excluded from master -----\n");
8939 	loop = g_list_first(masterparam.exclude_paths);
8940 	while (loop) {
8941 		p = (gchar *)loop->data;
8942 		if (p) {
8943 			dodebug(2,"master-exclude: %s\n", p);
8944 		}
8945 		loop = loop->next;
8946 	}
8947 }
8948 
8949 
8950 /* build mkisofs-commandline */
8951 
build_mkisofs_cmdline(gchar * ret,gint printsize,gchar * outfile,gint verbose)8952 static void build_mkisofs_cmdline(gchar *ret, gint printsize, gchar *outfile, gint verbose) {
8953 gchar line[MAXLINE*10];
8954 gchar tmp[MAXLINE];
8955 gchar tmp2[MAXLINE];
8956 gchar tmp3[MAXLINE];
8957 gchar tmp34[MAXLINE];
8958 gchar tmp35[MAXLINE];
8959 gchar tmp4[MAXLINE];
8960 gchar tmp5[MAXLINE];
8961 gchar tmp6[MAXLINE];
8962 gchar tmp7[MAXLINE];
8963 gchar tmptmp[MAXLINE];
8964 gchar tmptmp2[MAXLINE];
8965 gchar tmptmp3[MAXLINE];
8966 GList *loop;
8967 mstr_redirect_t *mstr;
8968 gchar *p;
8969 FILE *fd;
8970 gint pathcount;
8971 
8972 	/* check first if we got our temporary files? */
8973 	if (!master_fname1 || !master_fname2) {
8974 		g_warning("no temporary files for master? aborting...\n");
8975 
8976 		/* return some command that will fail eventually gracefully */
8977 		strcpy(ret, "false");
8978 		return;
8979 	}
8980 
8981 	if (debug > 1) {
8982 		print_master_dirs();
8983 	}
8984 
8985 	get_wrap_path("MKISOFS",tmp);
8986 
8987 	/* extract iso-options */
8988 	if (verbose) {
8989 		strcpy(tmp2,"-gui -v ");
8990 	} else {
8991 		strcpy(tmp2," ");
8992 	}
8993 
8994 	if (masterparam.opt[0]) {
8995 		strcat(tmp2,"-r ");
8996 	}
8997 	if (masterparam.opt[1]) {
8998                 strcat(tmp2,"-J ");
8999 	}
9000 	if (masterparam.charset != 0) {
9001                 strcat(tmp2,"-input-charset ");
9002                 strcat(tmp2,charset_types[masterparam.charset]);
9003                 strcat(tmp2," ");
9004 	}
9005 	if (masterparam.outcharset != 0) {
9006                 strcat(tmp2,"-output-charset ");
9007                 strcat(tmp2,charset_types[masterparam.outcharset]);
9008                 strcat(tmp2," ");
9009 	}
9010 	if (masterparam.opt[2]) {
9011 		strcat(tmp2,"-R ");
9012 	}
9013 	if (masterparam.opt[3]) {
9014 		strcat(tmp2,"-f ");
9015 	}
9016 	if (masterparam.opt[4]) {
9017 		strcat(tmp2,"-l ");
9018 	}
9019 	if (masterparam.opt[5]) {
9020 		strcat(tmp2,"-T ");
9021 	}
9022 	if (masterparam.opt[6]) {
9023 		strcat(tmp2,"-D ");
9024 	}
9025 	if (masterparam.opt[7]) {
9026 		strcat(tmp2,"-allow-leading-dots ");
9027 	}
9028 	if (masterparam.opt[8]) {
9029 		strcat(tmp2,"-d ");
9030 	}
9031 	if (masterparam.opt[9]) {
9032 		strcat(tmp2,"-N ");
9033 	}
9034 	if (masterparam.opt[10]) {
9035 		strcat(tmp2,"-U ");
9036 	}
9037 	if (masterparam.opt[11]) {
9038 		strcat(tmp2,"-no-bak ");
9039 	}
9040 	if (masterparam.opt[12]) {
9041 		strcat(tmp2,"-hide-rr-moved ");
9042 	}
9043 	if (masterparam.opt[13]) {
9044 		strcat(tmp2,"-hide-joliet-trans-tbl ");
9045 	}
9046 	if (masterparam.opt[14]) {
9047 		strcat(tmp2,"-no-rr ");
9048 	}
9049         if (masterparam.opt[15]) {
9050                 strcat(tmp2,"-no-iso-translate ");
9051         }
9052         if (masterparam.opt[16]) {
9053                 strcat(tmp2,"-joliet-long ");
9054         }
9055         if (masterparam.opt[17]) {
9056                 strcat(tmp2,"-allow-lowercase ");
9057         }
9058         if (masterparam.opt[18]) {
9059                 strcat(tmp2,"-allow-multidot ");
9060         }
9061         if (masterparam.opt[19]) {
9062                 strcat(tmp2,"-max-iso9660-filenames ");
9063         }
9064         if (masterparam.opt[20]) {
9065                 strcat(tmp2,"-relaxed-filenames ");
9066         }
9067         if (masterparam.opt[21]) {
9068                 strcat(tmp2,"-dvd-video ");
9069         }
9070         if (masterparam.opt[23] > 0) {
9071 		g_snprintf(tmptmp3,MAXLINE,"-iso-level %d ",
9072 			masterparam.opt[23]);
9073                 strcat(tmp2,tmptmp3);
9074         }
9075 
9076 	if (printsize) {
9077 		strcat(tmp2,"-print-size ");
9078 	}
9079 
9080 	/* extract bootable stuff */
9081 	strcpy(tmp3,"");
9082 
9083 	if (masterparam.bootable == 1) {
9084 		/* el torito */
9085 		if (masterparam.boot_image && masterparam.boot_catalog) {
9086 			strcpy(tmptmp, masterparam.boot_image);
9087 			strcpy(tmptmp2, masterparam.boot_catalog);
9088 			g_snprintf(tmp3,MAXLINE,"-b \"%s\" -c \"%s\"",
9089 				convert_escape(tmptmp),
9090 				convert_escape(tmptmp2));
9091 
9092 			switch(masterparam.boot_type) {
9093 			case 1:
9094 				strcat(tmp3," -hard-disk-boot");
9095 				break;
9096 			case 2:
9097 				strcat(tmp3," -no-emul-boot");
9098 				if (masterparam.boot_load_size >= 0) {
9099 					g_snprintf(tmptmp,MAXLINE," -boot-load-size %d", masterparam.boot_load_size);
9100 					strcat(tmp3, tmptmp);
9101 				}
9102 				break;
9103 			case 3:
9104 				strcat(tmp3," -no-boot");
9105 				break;
9106 			default:
9107 				break;
9108 			}
9109 
9110 			if (masterparam.boot_info_table) {
9111 				strcat(tmp3," -boot-info-table");
9112 			}
9113 		}
9114 	}
9115 	if (masterparam.bootable == 2) {
9116 		/* sparc boot */
9117 		if (masterparam.sparc_boot) {
9118 			strcpy(tmptmp, masterparam.sparc_boot);
9119 			g_snprintf(tmp3,MAXLINE,"-B \"%s\"",
9120 				convert_escape(tmptmp));
9121 		}
9122 	}
9123 
9124 	/* multisession info */
9125 	strcpy(tmp35,"");
9126 
9127 	if (curset.multisession == 1) {
9128 		if (masterparam.next_session_start != -1) {
9129 
9130 			if (convert_devnr2busid(curset.writer_devnr,tmp34) != 0) {
9131 				g_error("failed to get devicenr for writer in build_mkisofs_cmdline\n");
9132 			}
9133 
9134 			/* appending a session to an audio CD? */
9135 			if (cdinfo.nr_tracks > 0 && trackinfo[0]->type == 1) {
9136 				/* dont import old session */
9137 				g_snprintf(tmp35,MAXLINE,"-C %d,%d ",
9138 					masterparam.last_session_start,
9139 					masterparam.next_session_start);
9140 			} else {
9141 			        g_snprintf(tmp35,MAXLINE,"-C %d,%d -M \"%s\"",
9142 					masterparam.last_session_start,
9143 					masterparam.next_session_start,
9144 					tmp34);
9145 			}
9146 		}
9147 	}
9148 
9149 	/* extract headers */
9150 	strcpy(tmp4,"");
9151 
9152 	if (masterparam.volid) {
9153 		strcpy(tmptmp, masterparam.volid);
9154 		g_snprintf(tmp5,MAXLINE,"-V \"%s\" ",
9155 			convert_escape(tmptmp));
9156 		strcat(tmp4,tmp5);
9157 	}
9158 	if (masterparam.publisher) {
9159 		strcpy(tmptmp, masterparam.publisher);
9160 		g_snprintf(tmp5,MAXLINE,"-publisher \"%s\" ",
9161 			convert_escape(tmptmp));
9162 		strcat(tmp4,tmp5);
9163 	}
9164 	if (masterparam.preparer) {
9165 		strcpy(tmptmp, masterparam.preparer);
9166 		g_snprintf(tmp5,MAXLINE,"-preparer \"%s\" ",
9167 			convert_escape(tmptmp));
9168 		strcat(tmp4,tmp5);
9169 	}
9170 	/*
9171 	if (masterparam.application) {
9172 		strcpy(tmptmp, masterparam.application);
9173 		g_snprintf(tmp5,MAXLINE,"-A \"%s\" ",
9174 			convert_escape(tmptmp));
9175 		strcat(tmp4,tmp5);
9176 	}
9177 	*/
9178 	if (masterparam.abstract) {
9179 		strcpy(tmptmp, masterparam.abstract);
9180 		g_snprintf(tmp5,MAXLINE,"-abstract \"%s\" ",
9181 			convert_escape(tmptmp));
9182 		strcat(tmp4,tmp5);
9183 	}
9184 	if (masterparam.biblio) {
9185 		strcpy(tmptmp, masterparam.biblio);
9186 		g_snprintf(tmp5,MAXLINE,"-biblio \"%s\" ",
9187 			convert_escape(tmptmp));
9188 		strcat(tmp4,tmp5);
9189 	}
9190 	if (masterparam.copyright) {
9191 		strcpy(tmptmp, masterparam.copyright);
9192 		g_snprintf(tmp5,MAXLINE,"-copyright \"%s\" ",
9193 			convert_escape(tmptmp));
9194 		strcat(tmp4,tmp5);
9195 	}
9196 
9197 	/* now the excluded directories */
9198 	/* write to temporary file */
9199 	strcpy(tmp6,"");
9200 
9201 	fd = fopen(master_fname2,"w");
9202 	if (!fd) {
9203 		g_warning("failed to open %s for writing! aborting...\n",
9204 			master_fname2);
9205 		strcpy(ret,"false");
9206 		return;
9207 	}
9208 
9209 	loop = g_list_first(masterparam.exclude_paths);
9210         while (loop) {
9211 		p = (gchar *)loop->data;
9212 		if (p) {
9213 			strcpy(tmptmp,p);
9214 			g_snprintf(tmp5,MAXLINE,"%s\n",
9215 				convert_escape(tmptmp));
9216 			fputs(tmp5,fd);
9217 		}
9218                 loop = loop->next;
9219         }
9220 	fclose(fd);
9221 
9222 	/* if we actually got excludes, add the tmp-excl file */
9223 	if (g_list_length(masterparam.exclude_paths) != 0) {
9224 		strcpy(tmptmp,master_fname2);
9225 		g_snprintf(tmp5,MAXLINE,"-exclude-list \"%s\" ",
9226 			convert_escape(tmptmp));
9227 		strcat(tmp6,tmp5);
9228 	}
9229 
9230 	/* output-file given? */
9231 	if (outfile) {
9232 		strcpy(tmptmp,outfile);
9233 		g_snprintf(tmp5,MAXLINE,"-o \"%s\" ",
9234 			convert_escape(tmptmp));
9235 		strcat(tmp6,tmp5);
9236 	}
9237 
9238 	/* the last are the master-paths with redirects */
9239 	strcpy(tmp7,"");
9240 
9241 	fd = fopen(master_fname1,"w");
9242 	if (!fd) {
9243 		g_warning("failed to open %s for writing! aborting...\n",
9244 			master_fname1);
9245 		strcpy(ret,"false");
9246 		return;
9247 	}
9248 
9249 	/* the first path is to be added on the command line..all others
9250 	   to temporary file */
9251 	pathcount = 0;
9252         loop = g_list_first(masterparam.mstr_redir);
9253         while (loop) {
9254                 mstr = (mstr_redirect_t *) loop->data;
9255 		if (mstr) {
9256                         if (mstr->mstr_path && !mstr->redir_path) {
9257 				/* no redir available */
9258 				strcpy(tmptmp,mstr->mstr_path);
9259 				if (pathcount == 0) {
9260 					g_snprintf(tmp5,MAXLINE,"\"%s\" ",
9261 						convert_escape3(tmptmp));
9262 					strcat(tmp7,tmp5);
9263 				} else {
9264 					/* write to file */
9265 					g_snprintf(tmp5,MAXLINE,"%s\n",
9266 						convert_escape2(tmptmp));
9267 					fputs(tmp5,fd);
9268 				}
9269 			}
9270 			if (mstr->mstr_path && mstr->redir_path) {
9271 				strcpy(tmptmp,mstr->mstr_path);
9272 				strcpy(tmptmp2,mstr->redir_path);
9273 				if (pathcount == 0) {
9274 					g_snprintf(tmp5,MAXLINE,"\"%s=%s\" ",
9275 						convert_escape3(tmptmp2),
9276 						convert_escape3(tmptmp));
9277 					strcat(tmp7,tmp5);
9278 				} else {
9279 					/* write to file */
9280 					g_snprintf(tmp5,MAXLINE,"%s=%s\n",
9281 						convert_escape2(tmptmp2),
9282 						convert_escape2(tmptmp));
9283 					fputs(tmp5,fd);
9284 				}
9285 			}
9286 			pathcount++;
9287 		}
9288                 loop = loop->next;
9289         }
9290 	fclose(fd);
9291 
9292 	/* if we got more than one path add master-file */
9293 	if (g_list_length(masterparam.mstr_redir) > 1) {
9294 		strcpy(tmptmp,master_fname1);
9295 		g_snprintf(tmp5,MAXLINE,"-path-list \"%s\" ",
9296 			convert_escape(tmptmp));
9297 		strcat(tmp6,tmp5);
9298 	}
9299 
9300 	/* now put all together */
9301 	g_snprintf(line,MAXLINE*10, "%s %s %s %s %s %s -graft-points %s",
9302 		tmp, tmp2, tmp3, tmp35, tmp4, tmp6, tmp7);
9303 
9304 	strcpy(ret,line);
9305 }
9306 
9307 
9308 /* get output of mkisofs  */
9309 
read_mkisofs_out(gpointer data,gint source,GdkInputCondition cond)9310 static void read_mkisofs_out(gpointer data, gint source, GdkInputCondition cond) {
9311 gint n;
9312 gchar line[MAXLINE];
9313 gchar tmp[MAXLINE];
9314 
9315 	n = read_line(source, line, MAXLINE);
9316 
9317 	/* finished? */
9318 	if (n <= 0) {
9319 		return;
9320 	}
9321 
9322 	dodebug(10, "mkisofs (stdout): %s\n", line);
9323 
9324 
9325 	strcpy(tmp,line);
9326 	strcat(tmp,"\n");
9327 
9328 	convert_for_gtk2_textwidget(tmp);
9329 	gtk_text_insert(GTK_TEXT(readtrack_textview),
9330 		fixedfont,NULL,NULL,tmp, strlen(tmp));
9331 }
9332 
9333 
9334 /* get output of mkisofs (stderr) */
9335 
read_mkisofs_stderr(gpointer data,gint source,GdkInputCondition cond)9336 static void read_mkisofs_stderr(gpointer data, gint source, GdkInputCondition cond) {
9337 gint n;
9338 gint ret;
9339 gchar line[MAXLINE];
9340 gchar tmp[MAXLINE];
9341 gchar *p;
9342 
9343 	n = read_line(source, line, MAXLINE);
9344 
9345 	/* finished? */
9346 	if (n <= 0) {
9347 		gtk_input_remove(readcdda_callback);
9348 		gtk_input_remove(readcdda_callback2);
9349 
9350 		/* pick up return status of child */
9351 		wait(&ret);
9352 
9353 		read_done = WEXITSTATUS(ret);
9354 
9355 		return;
9356 	}
9357 
9358 	dodebug(10, "mkisofs (stderr): %s\n", line);
9359 
9360 	if (strncmp(line, "Total extents",13) == 0) {
9361 		strcpy(tmp,line);
9362 		p = strtok(tmp,"=");
9363 		if (p) {
9364 			p = strtok(NULL,"");
9365 			if (p) {
9366 				masterparam.session_size = atoi(p);
9367 			}
9368 		}
9369 	}
9370 
9371 	strcpy(tmp,line);
9372 	strcat(tmp,"\n");
9373 
9374 	convert_for_gtk2_textwidget(tmp);
9375 	gtk_text_insert(GTK_TEXT(readtrack_textview),
9376 		fixedfont,NULL,NULL,tmp, strlen(tmp));
9377 
9378 }
9379 
9380 
9381 /* call mkisofs -print-size */
9382 
fill_mkisofs_check_info(GtkWidget * text_window)9383 gint fill_mkisofs_check_info(GtkWidget *text_window) {
9384 gchar cmd[MAXLINE*10];
9385 gint read_out, read_err;
9386 gchar tmp[MAXLINE];
9387 
9388 	/* if another process running, ignore */
9389 	if (read_done == 999) {
9390 		return -1;
9391 	}
9392 
9393 	/* mark our process as running */
9394 	read_done = 999;
9395 	read_output_ctrl = 0;
9396 	readerr_count = 0;
9397 
9398 	/* be sure to overwrite old value */
9399 	masterparam.session_size = 0;
9400 
9401 	/* save text-window */
9402 	readtrack_textview = text_window;
9403 
9404 	/* get commandline */
9405 	build_mkisofs_cmdline(cmd,1,NULL,masterparam.opt[22]);
9406 
9407 	dodebug(1, "spawning: %s\n",cmd);
9408 	dolog(1, "Getting size of mkisofs-image\n");
9409 	dolog(3, "Executing: %s\n", cmd);
9410 
9411 	readcdda_pid = full_dpl_pipe3(&read_out,NULL,&read_err,cmd,0);
9412 	readcdda_pid2 = -1;
9413 
9414 	fcntl(read_out, F_SETFL, O_NONBLOCK);
9415 	fcntl(read_err, F_SETFL, O_NONBLOCK);
9416 
9417 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
9418 		(GdkInputFunction) read_mkisofs_out, NULL);
9419 	readcdda_callback2 = gdk_input_add(read_err, GDK_INPUT_READ,
9420 		(GdkInputFunction) read_mkisofs_stderr, NULL);
9421 
9422 	/* now wait until get_size is finished */
9423 	while (read_done == 999) {
9424 		wait_and_process_events();
9425 
9426 		/* check if somebody clicked on cancel */
9427 		if (dialog_done != 999) {
9428 				kill_readcdda();
9429 				/* mark we aborted */
9430 				read_output_ctrl = 1;
9431 				dialog_done = 999;
9432 		}
9433 	}
9434 
9435 	close(read_err);
9436 	close(read_out);
9437 
9438 
9439 	/* we killed the process */
9440 	if (read_output_ctrl == 1) {
9441 		strncpy(tmp, _("\nScanning aborted!\n"), MAXLINE);
9442 		convert_for_gtk2_textwidget(tmp);
9443 		gtk_text_insert(GTK_TEXT(readtrack_textview),
9444 			fixedfont,NULL,NULL,tmp, strlen(tmp));
9445 		return 2;
9446 	}
9447 
9448 	return 0;
9449 }
9450 
9451 
9452 /* get output of mkisofs */
9453 
read_master_out(gpointer data,gint source,GdkInputCondition cond)9454 static void read_master_out(gpointer data, gint source, GdkInputCondition cond) {
9455 gint n;
9456 gint ret;
9457 gchar line[MAXLINE];
9458 gchar tmp[MAXLINE];
9459 gchar tmp2[MAXLINE];
9460 gchar *p, *p2;
9461 gfloat pval;
9462 
9463         n = read_line(source, line, MAXLINE);
9464 
9465         /* finished? */
9466         if (n <= 0) {
9467 		gtk_input_remove(readcdda_callback);
9468 
9469                 /* pick up return status of child */
9470                 wait(&ret);
9471 
9472                 read_done = WEXITSTATUS(ret);
9473                 return;
9474         }
9475 
9476         dodebug(10,"mkisofs: %s\n", line);
9477 
9478 	/* see if we finished with mastering - set to 100% */
9479 	if (strncmp(line,"Total translation table size", 28) == 0) {
9480 		gtk_progress_set_percentage( GTK_PROGRESS(readtrack_pbar1),
9481 						1.0);
9482 		set_xcdr_title(toplevel,viewmode_dialog,100);
9483 		gtk_label_set_text(GTK_LABEL(readtrack_small_info2),
9484 						"100%");
9485 		/* mark we are really finished */
9486 		read_output_ctrl = 3;
9487 	}
9488 
9489 	/* we are finished with scanning directories - update infotext */
9490 	if (read_output_ctrl == 1) {
9491 		/* update only once */
9492 		read_output_ctrl = 2;
9493 
9494 		convert_kbytes2mbstring(masterparam.session_size * 2, tmp);
9495 		g_snprintf(tmp2,MAXLINE,_("Mastering data track [%s]"), tmp);
9496 		gtk_label_set_text(GTK_LABEL(readtrack_info_label),tmp2);
9497 
9498 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Mastering:"));
9499 	}
9500 
9501 
9502 	/* see if we got a percentage value and set progress bar */
9503 	strcpy(tmp,line);
9504 	p = strtok(tmp,",");
9505 	if (p != NULL) {
9506 		p2 = strtok(NULL,"");
9507 		if (p2 != NULL) {
9508 			strcpy(tmp2,p2);
9509 			strip_string(tmp2);
9510 			if (strncmp(tmp2,"estimate finish",15) == 0) {
9511 				/* ok..its a percentage line */
9512 				if (read_output_ctrl == 0) {
9513 					read_output_ctrl = 1;
9514 				}
9515 				strcpy(tmp2,p);
9516 				p = strtok(tmp2,"%");
9517 				if (p != NULL) {
9518 					strcpy(tmp,p);
9519 					pval = atof(tmp);
9520 					pval = pval/100;
9521 					if (pval > 1.0) pval = 1.0;
9522 					gtk_progress_set_percentage(
9523 						GTK_PROGRESS(readtrack_pbar1),
9524 						pval);
9525 					set_xcdr_title(toplevel,viewmode_dialog,(gint)(pval*100+0.5));
9526 					/* update small view */
9527 					g_snprintf(tmp,MAXLINE,"%d%%",
9528 						(gint)(pval*100+0.5));
9529 					gtk_label_set_text(
9530 					   GTK_LABEL(readtrack_small_info2),
9531 						tmp);
9532 					return;
9533 				}
9534 			}
9535 		}
9536 	}
9537 
9538         /* forward most other output to textview-window */
9539         strcat(line,"\n");
9540         gtk_text_insert(GTK_TEXT(readtrack_textview),
9541                 fixedfont,NULL,NULL, line, strlen(line));
9542 
9543 }
9544 
9545 
9546 /* call mkisofs to master a image */
9547 
start_master_action()9548 gint start_master_action() {
9549 char cmd[MAXLINE*10];  /* extra big buffer for very long cdrecord options */
9550 gint read_dummy, read_err;
9551 
9552 	/* if another write running, ignore */
9553 	if (read_done == 999) {
9554 		return -1;
9555 	}
9556 
9557 	/* mark our write-process as running */
9558 	read_done = 999;
9559 	read_output_ctrl = 0;
9560 	read_abort_mark = 0;
9561 
9562 	/* set info label */
9563 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Scanning master directories..."));
9564 
9565 	/* build command line */
9566 	build_mkisofs_cmdline(cmd, 0, masterparam.image_filename, masterparam.opt[22]);
9567 
9568 	dodebug(1, "spawning: %s\n",cmd);
9569 	dolog(1,"Master image %s\n", masterparam.image_filename);
9570 	dolog(3,"Executing: %s\n", cmd);
9571 
9572 	/* yes...command line is done */
9573 	readcdda_pid = full_dpl_pipe3(&read_dummy,NULL,&read_err,cmd,0);
9574 	readcdda_pid2 = -1;
9575 
9576 	fcntl(read_dummy, F_SETFL, O_NONBLOCK);
9577 	fcntl(read_err, F_SETFL, O_NONBLOCK);
9578 
9579 	readcdda_callback = gdk_input_add(read_err, GDK_INPUT_READ,
9580 		(GdkInputFunction) read_master_out, NULL);
9581 	readcdda_callback2 = gdk_input_add(read_dummy, GDK_INPUT_READ,
9582 		(GdkInputFunction) read_cdda2wav_dummyout, NULL);
9583 
9584 	/* now wait until write is finished */
9585 	while (read_done == 999) {
9586 		wait_and_process_events();
9587 	}
9588 
9589 	close(read_err);
9590 	close(read_dummy);
9591 
9592 	/* aborted master ? */
9593 	if (read_abort_mark == 1) {
9594 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Mastering aborted..."));
9595 		return 1;
9596 	}
9597 
9598 	/* all ok? */
9599 	if (read_done == 0 && read_output_ctrl == 3) {
9600 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Mastering successful"));
9601 	} else {
9602 		/* some error? */
9603 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error mastering data track"));
9604 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Master-Error:"));
9605 	}
9606 
9607 	return 0;
9608 }
9609 
9610 
9611 /* do just swallow all output we get from stderr... and wait if the
9612    process terminated */
9613 
mkisofs_err(gpointer pid,gint source,GdkInputCondition cond)9614 static void mkisofs_err(gpointer pid, gint source, GdkInputCondition cond) {
9615 gint n;
9616 gint ret;
9617 gchar line[MAXLINE];
9618 
9619 	n = read_line(source, line, MAXLINE);
9620 
9621 	/* readcd-finished? */
9622 	if (n <= 0) {
9623 		gtk_input_remove(readcdda_callback3);
9624 
9625                 /* pick up return status of child */
9626 		waitpid((pid_t)GPOINTER_TO_INT(pid), &ret, WNOHANG);
9627 
9628 		dodebug(10,"Finished in mkisofs_err\n");
9629 
9630 		return;
9631 	}
9632 
9633 	dodebug(10,"mkisofs (stderr): %s\n", line);
9634 }
9635 
9636 
9637 
9638 /* call cdrecord to write a master-image on the fly */
9639 
start_onthefly_master_action(gint write_devnr)9640 gint start_onthefly_master_action(gint write_devnr) {
9641 gchar tmp[MAXLINE];
9642 gchar tmp3[MAXLINE];
9643 gchar tmp4[MAXLINE];
9644 gchar cmd[MAXLINE*10];  /* extra big buffer for very long mkisofs options */
9645 gchar cmd2[MAXLINE*10];
9646 gchar outcmd[MAXLINE];
9647 gint read_out, read_err, read_err2;
9648 gint ret, tracknr;
9649 pid_t pid1, pid2;
9650 gint varirec_on, tmp_writer_speed;
9651 gint wrmode;
9652 
9653 	/* if another write running, ignore */
9654 	if (read_done == 999) {
9655 		return -1;
9656 	}
9657 
9658 	/* mark our write-process as running */
9659 	read_done = 999;
9660 	read_output_ctrl = 0;
9661 	pct_so_far = 0.0;
9662 	cdrecord_reload = 0;
9663 	cdrtimer = 0;
9664 
9665 	strcpy(outcmd,"");
9666 
9667 	/* set info label */
9668 	gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Initializing CD-Writer..."));
9669 
9670 	/* reset writeparams-arrays */
9671 	g_free(writeparams.tracktype);
9672 	g_free(writeparams.frames);
9673 	g_free(writeparams.pct_so_far_arr);
9674 	g_free(writeparams.pct_this_track_arr);
9675 	writeparams.tracktype = g_new0(gint,MAXTRACKS);
9676 	writeparams.frames = g_new0(gint,MAXTRACKS);
9677 	writeparams.pct_so_far_arr = g_new0(gfloat,MAXTRACKS);
9678 	writeparams.pct_this_track_arr = g_new0(gfloat,MAXTRACKS);
9679 	writeparams.nrtracks = 0;
9680 	writeparams.simulation = curset.writesimul;
9681 
9682 	/* build command line of masterprocess */
9683 	build_mkisofs_cmdline(cmd, 0, NULL, 0);
9684 
9685 	/* build command line of write process */
9686 
9687 	/* get bus,id,lun string */
9688 	if (convert_devnr2busid_dev(write_devnr,tmp) != 0) {
9689 		g_error("non existing cdrom?");
9690 	}
9691 
9692 	/* get driveropts */
9693 	varirec_on = do_driveropts(tmp4, curset.writer_devnr);
9694 
9695 	get_wrap_path_cdrecord(tmp3);
9696 	g_snprintf(cmd2, MAXLINE*10,
9697 		"%s %s gracetime=%d fs=%dk -v %s ",
9698 		tmp3, tmp, get_gracetime(), get_cur_writer_fifo(), tmp4);
9699 
9700 	if (get_cur_writer_drvmode() >= 0) {
9701 		if (drivers[get_cur_writer_drvmode()] != NULL) {
9702 			g_snprintf(tmp,MAXLINE," driver=%s",
9703 				drivers[get_cur_writer_drvmode()]->driver);
9704 			strcat(cmd2,tmp);
9705 		}
9706 	}
9707 
9708         /* special case with varirec - always use 4x here */
9709         if (varirec_on) {
9710                 tmp_writer_speed = 4;
9711         } else {
9712                 tmp_writer_speed = get_cur_writer_speed();
9713         }
9714 
9715 	if (get_cur_writer_speed() >= 0) {
9716 		g_snprintf(tmp,MAXLINE," speed=%d", tmp_writer_speed);
9717 		strcat(cmd2, tmp);
9718 	}
9719 
9720 	/* Ignore write-mode in multisession-mode */
9721 	if (curset.multisession == 0) {
9722 		wrmode = get_cur_writemode();
9723 		if (wrmode == 0) {
9724 			strcat(cmd2," -dao");
9725 		}
9726 		if (wrmode == 2) {
9727 			strcat(cmd2," defpregap=0");
9728 		}
9729 		if (wrmode == 3) {
9730 			strcat(cmd2," -raw96r");
9731 		}
9732 		if (wrmode == 4) {
9733 			strcat(cmd2," -raw96p");
9734 		}
9735 		if (wrmode == 5) {
9736 			strcat(cmd2," -raw16");
9737 		}
9738 	}
9739 
9740 	if (curset.writesimul == 1) {
9741 		strcat(cmd2," -dummy");
9742 	}
9743 	if (curset.writeeject == 1) {
9744 		strcat(cmd2," -eject");
9745 	}
9746 	if (curset.nofixate == 1) {
9747 		strcat(cmd2," -nofix");
9748 	}
9749 	if (curset.multisession == 1) {
9750 		if (is_a_sony(write_devnr)) {
9751 			strcat(cmd2," -multi -data");
9752 		} else {
9753 			strcat(cmd2," -multi");
9754 		}
9755 	}
9756 	if (curset.writepad == 1) {
9757 		strcat(cmd2," -pad");
9758 	}
9759 	if (curset.writeswap == 1) {
9760 		strcat(cmd2," -swab");
9761 	}
9762 	if (curset.writeoverburn == 1) {
9763 		strcat(cmd2," -overburn");
9764 	}
9765 	if (curset.writeignsize == 1) {
9766 		strcat(cmd2," -ignsize");
9767 	}
9768 	if (curset.writeimmed == 1) {
9769 		strcat(cmd2," -immed");
9770 	}
9771 
9772 	/* now add track-specification: one data track */
9773 	g_snprintf(tmp, MAXLINE, " -waiti tsize=%ds",
9774 		masterparam.session_size);
9775 	strcat(cmd2, tmp);
9776 	strcat(cmd2," -");
9777 
9778 	/* save command line to view in progress window */
9779 	g_snprintf(outcmd,MAXLINE, "Calling: %s\n\n", cmd2);
9780 
9781 	/* fill up percent values for nice progressbar movement */
9782 	tracknr = 1;
9783 	writeparams.tracktype[tracknr] = 0; /* data */
9784 	writeparams.frames[tracknr] = masterparam.session_size;
9785 	writeparams.pct_this_track_arr[tracknr] = 1.0;
9786 	writeparams.pct_so_far_arr[tracknr] = 0.0;
9787 	writeparams.nrtracks = 1;
9788 
9789 	dodebug(1, "spawning: %s | %s \n",cmd, cmd2);
9790 	dolog(1,"Master CD on the fly\n");
9791 	dolog(3,"Executing: %s | %s\n", cmd, cmd2);
9792 
9793 	/* output command to get better debug output */
9794 	gtk_text_insert(GTK_TEXT(readtrack_textview),
9795 		fixedfont,NULL,NULL,outcmd, strlen(outcmd));
9796 
9797 	/* yes...command line is done */
9798 	full_dpl_pipe4(&pid1,&pid2,NULL,&read_err,cmd,&read_out,&read_err2,cmd2,0);
9799 	mkisofs_pid = pid1;
9800 	readcdda_pid = pid2;
9801 	readcdda_pid2 = -1;
9802 
9803 	fcntl(read_out, F_SETFL, O_NONBLOCK);
9804 	fcntl(read_err, F_SETFL, O_NONBLOCK);
9805 	fcntl(read_err2, F_SETFL, O_NONBLOCK);
9806 
9807 	readcdda_callback = gdk_input_add(read_out, GDK_INPUT_READ,
9808 		(GdkInputFunction) read_write_out, GINT_TO_POINTER(read_err2));
9809 	readcdda_callback2 = gdk_input_add(read_err2, GDK_INPUT_READ,
9810 		(GdkInputFunction) read_write_stderr, NULL);
9811 	readcdda_callback3 = gdk_input_add(read_err, GDK_INPUT_READ,
9812 		(GdkInputFunction) mkisofs_err, GINT_TO_POINTER(pid1));
9813 
9814 	/* now wait until write is finished */
9815 	while (read_done == 999) {
9816 		wait_and_process_events();
9817 
9818 		/* check if writer is waiting for reload medium */
9819 		if (cdrecord_reload > 0) {
9820 			show_dialog(ICO_WARN, _("Please reload the CD-R in the writer"), T_OK, NULL, NULL, -1);
9821 
9822 			/* now send CR to cdrecord to let it continue */
9823 			if (cdrecord_reload == 1) {
9824 				if (write(read_err2, "\n", 1) != 1) {
9825 					g_warning("write error to cdrecord pipe\n");
9826 				}
9827 			}
9828 
9829 			/* cdrecord also accepts a SIGUSR1 to continue */
9830 			/* send wakeup signal */
9831 			if (cdrecord_reload == 2) {
9832 				dodebug(1,"Sending SIGUSR1 to cdrecord (pid: %d) after reload.\n", (gint) pid2);
9833 				kill(pid2, SIGUSR1);
9834 			}
9835 			cdrecord_reload = 0;
9836 		}
9837 
9838 		/* check if somebody clicked on cancel */
9839 		if (dialog_done2 != 999) {
9840 			ret = show_dialog(ICO_WARN, _("Are you sure you want to abort the writing?\nAborting may damage the CD-RW and may require that you have\nto power-cycle the burner to get working again."),
9841 				T_YES, T_NO, NULL, 1);
9842 			if (ret == 0) {
9843 				/* really abort */
9844 				kill_readcdda();
9845 				/* mark we aborted */
9846 				read_output_ctrl = 1;
9847 				dialog_done2 = 999;
9848 			} else {
9849 				/* not abort - undo button press */
9850 				dialog_done2 = 999;
9851 			}
9852 		}
9853 	}
9854 
9855 	close(read_err2);
9856 	close(read_err);
9857 	close(read_out);
9858 
9859 	/* no disk */
9860 	if (read_output_ctrl == 2) {
9861 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("No disk or wrong disk loaded."));
9862 		return 1;
9863 	}
9864 
9865 	/* cannot send cue sheet */
9866 	if (read_output_ctrl == 4) {
9867 		show_dialog(ICO_WARN,_("Your CD-Writer did not accept the CUE sheet needed for\nDAO writing. This could mean that cdrecord does not support DAO\nwith your writer. Select TAO mode and try again."),T_OK, NULL, NULL, 0);
9868 	}
9869 
9870 	/* aborted write ? */
9871 	if (read_output_ctrl == 1) {
9872 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Writing aborted..."));
9873 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
9874 		return 1;
9875 	}
9876 
9877 	/* error while reading ?*/
9878 	if (read_done != 0 || read_output_ctrl == 5) {
9879 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Error writing tracks"));
9880 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Write-Error:"));
9881                 if (read_done == 2) {
9882                         /* invalid cdrecord key - show window */
9883 			display_invalid_prodvdkey();
9884                 }
9885 		return 1;
9886 	} else {
9887 		/* all ok */
9888 		gtk_label_set_text(GTK_LABEL(readtrack_info_label), _("Tracks successfully written"));
9889 		gtk_label_set_text(GTK_LABEL(readtrack_small_info),_("Successful:"));
9890 		return 0;
9891 	}
9892 }
9893 
9894 
9895 /* check the version of cdrecord */
9896 /* return 1 if not correct (to old) */
9897 
check_version_cdrecord(gchar * match,gchar * found,gint * isProDVD)9898 gint check_version_cdrecord(gchar *match, gchar *found, gint *isProDVD) {
9899 gchar line[MAXLINE];
9900 gchar vline[MAXLINE];
9901 gchar ver[MAXLINE];
9902 FILE *fpin;
9903 gchar *p;
9904 
9905 	*isProDVD = 0;
9906 	strcpy(ver,"");
9907 	get_wrap_path("CDRECORD",line);
9908 	strcat(line," -version 2>/dev/null");
9909 
9910 	dodebug(1, "calling: %s\n", line);
9911         if ((fpin = popen(line,"r")) == NULL) {
9912                 g_error("popen error\n");
9913         }
9914 
9915 	strcpy(line,"");
9916 	strcpy(vline,"");
9917         for (;;) {
9918                 if (fgets(line,MAXLINE,fpin) == NULL)
9919                         break;
9920 		dodebug(10,"got: %s",line);
9921 
9922 		/* only get first line */
9923 		if (strcmp(vline,"") == 0) {
9924 			strncpy(vline, line, MAXLINE);
9925 		}
9926 		if (strstr(line, "This version is an unofficial (modified) version with DVD support")) {
9927 			dodebug(1, "WARNING: Inoffical cdrecord version found!\n", line);
9928 			*isProDVD = 1;
9929 		}
9930         }
9931 
9932         if (pclose(fpin) == -1) {
9933                 g_error("pclose error\n");
9934         }
9935 
9936 	if (strcmp(vline,"") == 0 || strstr(vline,"sh:") != NULL) {
9937 		/* failed to open - permission denied */
9938 		return 2;
9939 	}
9940 
9941 	/* now line contains the version string of cdrecord */
9942 	/* try to extract the version number */
9943 
9944 	p = strstr(vline,"release");
9945 	if (p != NULL) {
9946 		p = strtok(p+8, " ");
9947 		if (p != NULL) {
9948 			strcpy(ver,p);
9949 		}
9950 	} else {
9951 		p = strstr(vline, "ProDVD");
9952 		if (p != NULL) {
9953 			*isProDVD = 1;
9954 			p = strtok(p, " ");
9955 			if (p != NULL) {
9956 			  p = strtok(NULL, " ");
9957 			  if (p != NULL) {
9958 				strcpy(ver,p);
9959 			  }
9960 			}
9961 		}
9962 		if (strcmp(ver,"") == 0) {
9963 			p = strstr(vline,"Cdrecord");
9964 			if (p != NULL) {
9965 				p = strtok(p+7, " ");
9966 				if (p != NULL) {
9967 					p = strtok(NULL, " ");
9968 					if (p) {
9969 						strcpy(ver,p);
9970 					}
9971 				}
9972 			}
9973 		}
9974 	}
9975 
9976 	/* not even a version-string found */
9977 	if (strcmp(ver,"") == 0) {
9978 		strcpy(found,"-unknown-");
9979 		return 1;
9980 	}
9981 
9982 	/* check if the version is new enough to support
9983 	   on the fly audio */
9984 	if (compare_versions(ver,CDRECORD_VERSION_WITH_ONTHFLYAUDIO) >= 0) {
9985 		support_ontheflyaudio = 1;
9986 	}
9987 
9988 	/* now compare the version string */
9989 	if (compare_versions(ver,match) >= 0) {
9990 		strcpy(found,ver);
9991 		return 0;
9992 	} else {
9993 		strcpy(found,ver);
9994 		return 1;
9995 	}
9996 }
9997 
9998 /* check the version of mkisofs */
9999 /* return 1 if not correct (to old) */
10000 
check_version_mkisofs(gchar * match,gchar * found)10001 gint check_version_mkisofs(gchar *match, gchar *found) {
10002 gchar line[MAXLINE];
10003 gchar ver[MAXLINE];
10004 FILE *fpin;
10005 gchar *p;
10006 
10007 	strcpy(ver,"");
10008 	get_wrap_path("MKISOFS",line);
10009 	strcat(line," -version 2>/dev/null");
10010 
10011 	dodebug(1, "calling: %s\n", line);
10012         if ((fpin = popen(line,"r")) == NULL) {
10013                 g_error("popen error\n");
10014         }
10015 
10016 	strcpy(line,"");
10017         for (;;) {
10018                 if (fgets(line,MAXLINE,fpin) == NULL)
10019                         break;
10020 		dodebug(10,"got: %s",line);
10021         }
10022 
10023         if (pclose(fpin) == -1) {
10024                 g_error("pclose error\n");
10025         }
10026 
10027 	if (strcmp(line,"") == 0 || strstr(line,"sh:") != NULL) {
10028 		/* failed to open - permission denied */
10029 		return 2;
10030 	}
10031 
10032 
10033 	/* now line contains the version string of mkisofs */
10034 	/* try to extract the version number */
10035 
10036 	p = strstr(line,"mkisofs");
10037 	if (p != NULL) {
10038 		p = strtok(p+8, " ");
10039 		if (p != NULL) {
10040 			strcpy(ver,p);
10041 		}
10042 	}
10043 
10044 	/* not even a version-string found */
10045 	if (strcmp(ver,"") == 0) {
10046 		strcpy(found,"-unknown-");
10047 		return 1;
10048 	}
10049 
10050 	/* now compare the version string */
10051 	if (compare_versions(ver,match) >= 0) {
10052 		strcpy(found,ver);
10053 		return 0;
10054 	} else {
10055 		strcpy(found,ver);
10056 		return 1;
10057 	}
10058 }
10059 
10060 /* check the version of cdda2wav */
10061 /* return 1 if not correct (to old) */
10062 
check_version_cdda2wav(gchar * match,gchar * found)10063 gint check_version_cdda2wav(gchar *match, gchar *found) {
10064 gchar line[MAXLINE];
10065 gchar vline[MAXLINE];
10066 gchar ver[MAXLINE];
10067 FILE *fpin;
10068 gchar *p;
10069 
10070 	strcpy(ver,"");
10071 	get_wrap_path("CDDA2WAV",line);
10072 	strcat(line," -version 2>&1");
10073 
10074 	dodebug(1, "calling: %s\n", line);
10075         if ((fpin = popen(line,"r")) == NULL) {
10076                 g_error("popen error\n");
10077         }
10078 
10079 	strcpy(line,"");
10080 	strcpy(vline,"");
10081         for (;;) {
10082                 if (fgets(line,MAXLINE,fpin) == NULL)
10083                         break;
10084 		dodebug(10,"got: %s",line);
10085 
10086 	        /* only get first line */
10087         	if (strcmp(vline,"") == 0) {
10088                 	strncpy(vline, line, MAXLINE);
10089         	}
10090         }
10091 
10092         if (pclose(fpin) == -1) {
10093                 g_error("pclose error\n");
10094         }
10095 
10096 	if (strcmp(vline,"") == 0 || strstr(vline,"sh:") != NULL) {
10097 		/* failed to open - permission denied */
10098 		return 2;
10099 	}
10100 
10101 	/* now vline contains the version string of cdda2wav */
10102 	/* try to extract the version number */
10103 
10104 	p = strstr(vline,"version");
10105 	if (p != NULL) {
10106 		p = strtok(p+8, " _");
10107 		if (p != NULL) {
10108 			strcpy(ver,p);
10109 		}
10110 	} else {
10111 		p = strstr(vline,"cdda2wav");
10112 		if (p != NULL) {
10113 			p = strtok(p+9, " ");
10114 			if (p != NULL) {
10115 				strcpy(ver,p);
10116 			}
10117 		}
10118 	}
10119 
10120 	/* not even a version-string found */
10121 	if (strcmp(ver,"") == 0) {
10122 		strcpy(found,"-unknown-");
10123 		return 1;
10124 	}
10125 
10126 	/* now compare the version string */
10127 	if (compare_versions(ver,match) >= 0) {
10128 		strcpy(found,ver);
10129 		return 0;
10130 	} else {
10131 		strcpy(found,ver);
10132 		return 1;
10133 	}
10134 }
10135 
10136 
10137 /* check the version of readcd */
10138 /* return 1 if not correct (to old) */
10139 
check_version_readcd(gchar * match,gchar * found)10140 gint check_version_readcd(gchar *match, gchar *found) {
10141 gchar line[MAXLINE];
10142 gchar ver[MAXLINE];
10143 FILE *fpin;
10144 gchar *p;
10145 
10146 	strcpy(ver,"");
10147 	get_wrap_path("READCD",line);
10148 	strcat(line," -version 2>/dev/null");
10149 
10150 	dodebug(1, "calling: %s\n", line);
10151         if ((fpin = popen(line,"r")) == NULL) {
10152                 g_error("popen error\n");
10153         }
10154 
10155 	strcpy(line,"");
10156         for (;;) {
10157                 if (fgets(line,MAXLINE,fpin) == NULL)
10158                         break;
10159 		dodebug(10,"got: %s",line);
10160         }
10161 
10162         if (pclose(fpin) == -1) {
10163                 g_error("pclose error\n");
10164         }
10165 
10166 	if (strcmp(line,"") == 0 || strstr(line,"sh:") != NULL) {
10167 		/* failed to open - permission denied */
10168 		return 2;
10169 	}
10170 
10171 
10172 	/* now line contains the version string of readcd */
10173 	/* try to extract the version number */
10174 
10175 	p = strstr(line,"readcd");
10176 	if (p != NULL) {
10177 		p = strtok(p+7, " ");
10178 		if (p != NULL) {
10179 			strcpy(ver,p);
10180 		}
10181 	}
10182 
10183 	/* not even a version-string found */
10184 	if (strcmp(ver,"") == 0) {
10185 		strcpy(found,"-unknown-");
10186 		return 1;
10187 	}
10188 
10189 	/* now compare the version string */
10190 	if (compare_versions(ver,match) >= 0) {
10191 		strcpy(found,ver);
10192 		return 0;
10193 	} else {
10194 		strcpy(found,ver);
10195 		return 1;
10196 	}
10197 }
10198 
10199 
10200 /* check the version of the wrapper */
10201 /* return 1 if not correct */
10202 /* return 2 if user denied */
10203 /* return 3 if rootconfig unreadable */
10204 
check_version_wrapper(gchar * tmp)10205 gint check_version_wrapper(gchar *tmp) {
10206 gchar line[MAXLINE];
10207 gchar xcdrver[MAXLINE];
10208 gchar sharever[MAXLINE];
10209 gchar prefixver[MAXLINE];
10210 FILE *fpin;
10211 gint ret;
10212 gint unreadable;
10213 
10214 	strcpy(xcdrver,"-unknown-");
10215 	strcpy(sharever,"-unknown-");
10216 	strcpy(prefixver,"-unknown-");
10217 	strncpy(line,tmp, MAXLINE);
10218 	strcat(line," -V");
10219 	ret = 0;
10220 	unreadable = 0;
10221 
10222 	dodebug(1, "calling: %s\n", line);
10223         if ((fpin = popen(line,"r")) == NULL) {
10224                 g_error("popen error\n");
10225         }
10226 
10227 	strcpy(line,"");
10228         for (;;) {
10229                 if (fgets(line,MAXLINE,fpin) == NULL)
10230                         break;
10231 		dodebug(10,"got: %s",line);
10232 
10233 		if (strncmp(line,"X-CD-Roast ", 11) == 0) {
10234 			strcpy(xcdrver,line+11);
10235 		}
10236 		if (strncmp(line,"sharedir: ", 10) == 0) {
10237 			strcpy(sharever,line+10);
10238 		}
10239 		if (strncmp(line,"prefixdir: ", 11) == 0) {
10240 			strcpy(prefixver,line+11);
10241 		}
10242 		if (strncmp(line,"Warning: rootconfig unreadable", 30) == 0) {
10243 			unreadable = 1;
10244 		}
10245         }
10246 
10247         if (pclose(fpin) == -1) {
10248                 g_error("pclose error\n");
10249         }
10250 
10251 	strip_string(xcdrver);
10252 	strip_string(sharever);
10253 	strip_string(prefixver);
10254 
10255 	if (strcmp(xcdrver,"ACCESS DENIED") == 0) {
10256 		return 2;
10257 	}
10258 	if (unreadable) {
10259 		return 3;
10260 	}
10261 	if (strcmp(xcdrver,XCDROAST_VERSION) != 0) {
10262 		fprintf(stderr, "CRITICAL: Wrapper %s from\n\tVersion %s instead of %s\n",
10263 			tmp, xcdrver, XCDROAST_VERSION);
10264 		ret = 1;
10265 	}
10266 	if (strcmp(sharever,sharedir) != 0) {
10267 		fprintf(stderr, "WARNING: Wrapper %s configured\n\tsharedir %s instead of %s\n",
10268 			tmp, sharever, sharedir);
10269 		ret = 0;
10270 	}
10271 	if (strcmp(prefixver,prefixdir) != 0) {
10272 		fprintf(stderr, "CRITICAL: Wrapper %s configured\n\tprefixdir %s instead of %s\n",
10273 			tmp, prefixver, prefixdir);
10274 		ret = 1;
10275 	}
10276 
10277 	return ret;
10278 }
10279 
10280 
10281 /* check if this user is allowed to write in the given directory */
10282 /* uses the wrapper to have real conditions */
10283 /* return 0 if writeable, 1 if not */
10284 
is_dir_writeable(gchar * dir)10285 gint is_dir_writeable(gchar *dir) {
10286 gchar line[MAXLINE];
10287 gchar tmp[MAXLINE];
10288 FILE *fpin;
10289 gint stat;
10290 
10291 	get_wrap_path("WRITETEST", tmp);
10292 	g_snprintf(line,MAXLINE,"%s \"%s\"", tmp, dir);
10293 
10294 	dodebug(1, "calling: %s\n", line);
10295         if ((fpin = popen(line,"r")) == NULL) {
10296                 g_error("popen error\n");
10297         }
10298 
10299         for (;;) {
10300                 if (fgets(line,MAXLINE,fpin) == NULL)
10301                         break;
10302         }
10303 
10304 	stat = pclose(fpin);
10305         if (stat == -1) {
10306                 g_error("pclose error\n");
10307         }
10308 
10309 	return (WEXITSTATUS(stat));
10310 }
10311 
10312 
10313 /* return the commands to use to activate non-root-mode */
10314 /* return 0 if all checks ok */
10315 
get_commands_to_change_nrm(gchar * ret,gint mode)10316 gint get_commands_to_change_nrm(gchar *ret, gint mode) {
10317 gchar tmp[MAXLINE];
10318 gchar bin[MAXLINE];
10319 gint groupaddok;
10320 gchar cmd_chown[MAXLINE], cmd_chmod[MAXLINE];
10321 #if 0
10322 gchar cmd_chgrp[MAXLINE];
10323 nonroot_flags_t *entry;
10324 GList *nrs_vals, *loop;
10325 gchar tmp2[MAXLINE];
10326 #endif
10327 
10328 	strcpy(ret,"");
10329 	groupaddok = 0;
10330 
10331 	/* check if basic commands are available */
10332 	get_chown_cmd(cmd_chown);
10333 	if (cmd_chown[0] == '\0') {
10334 		strcat(ret,"\nError: No chown command found");
10335 		return 1;
10336 	}
10337 
10338 #if 0
10339 	get_chgrp_cmd(cmd_chgrp);
10340 	if (cmd_chgrp[0] == '\0') {
10341 		strcat(ret,"\nError: No chgrp command found");
10342 		return 1;
10343 	}
10344 #endif
10345 
10346 	get_chmod_cmd(cmd_chmod);
10347 	if (cmd_chmod[0] == '\0') {
10348 		strcat(ret,"\nError: No chmod command found");
10349 		return 1;
10350 	}
10351 
10352 	/* activate non-root-mode */
10353 	if (mode == 0) {
10354 #if 0
10355 	 /* check if we need to create a group for the wrapper */
10356 	 if (!check_group_exists(NONROOTMODEGROUP)) {
10357 		/* we have to create a group here */
10358 		if (stat(GROUPADD,&buf) == 0) {
10359 			if (buf.st_mode & S_IEXEC) {
10360 				/* groupadd exists and is an exectable */
10361 				groupaddok = 1;
10362 			}
10363 		}
10364 		if (!groupaddok) {
10365 			g_snprintf(tmp,MAXLINE,_("Warning: No \"groupadd\" command found on your system.\n - Edit \"/etc/group\" and add a group \"%s\" manually.\n    Please try again then."), NONROOTMODEGROUP);
10366 			strcat(ret,tmp);
10367 			/* abort, without group its no way for us */
10368 			return 1;
10369 		} else {
10370 			/* create command to create new group */
10371 #if defined(__FreeBSD__)
10372 			g_snprintf(tmp,MAXLINE,"%s groupadd -n %s\n", GROUPADD, NONROOTMODEGROUP);
10373 #else
10374 			g_snprintf(tmp,MAXLINE,"%s %s\n", GROUPADD, NONROOTMODEGROUP);
10375 #endif
10376 			strcat(ret,tmp);
10377 		}
10378 	 }
10379 #endif
10380 
10381 	 /* set the correct permissions to the wrapper */
10382 	 g_snprintf(bin,MAXLINE,"%s/%s", sharedir, WRAPPER);
10383 	 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10384 	 strcat(ret,tmp);
10385 #if 0
10386 	 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10387 	 strcat(ret,tmp);
10388 #endif
10389 	 /* old nonroot mode - 2755 */
10390 	 g_snprintf(tmp,MAXLINE,"%s 4755 %s\n", cmd_chmod, bin);
10391 	 strcat(ret,tmp);
10392 
10393 
10394 #if 0
10395 	 /* set correct permissions for cdrtools */
10396 	 get_spawn_path(CDRECORD,bin);
10397 	 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10398 	 strcat(ret,tmp);
10399 	 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10400 	 strcat(ret,tmp);
10401 	 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10402 	 strcat(ret,tmp);
10403 
10404 	 get_spawn_path(CDRECORDPRODVD,bin);
10405 	 if (is_file(bin)) {
10406 	 	g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10407 	 	strcat(ret,tmp);
10408 	 	g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10409 	 	strcat(ret,tmp);
10410 	 	g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10411 	 	strcat(ret,tmp);
10412 	 }
10413 
10414 	 get_spawn_path(MKISOFS,bin);
10415 	 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10416 	 strcat(ret,tmp);
10417 	 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10418 	 strcat(ret,tmp);
10419 	 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10420 	 strcat(ret,tmp);
10421 
10422 	 get_spawn_path(READCD,bin);
10423 	 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10424 	 strcat(ret,tmp);
10425 	 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10426 	 strcat(ret,tmp);
10427 	 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10428 	 strcat(ret,tmp);
10429 
10430 	 get_spawn_path(CDDA2WAV,bin);
10431 	 g_snprintf(tmp,MAXLINE,"%s root %s\n", cmd_chown, bin);
10432 	 strcat(ret,tmp);
10433 	 g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp, NONROOTMODEGROUP, bin);
10434 	 strcat(ret,tmp);
10435 	 g_snprintf(tmp,MAXLINE,"%s 4710 %s\n", cmd_chmod, bin);
10436 	 strcat(ret,tmp);
10437 #endif
10438 
10439 	} else {
10440 		/* deactivate non-root-mode */
10441 
10442 #if 0
10443 		nrs_vals = NULL;
10444 		/* try to load original flags from file */
10445 		load_nonrootvalues(configdir, NONROOTBAK, &nrs_vals);
10446 
10447 		/* loop through all values */
10448 		loop = g_list_first(nrs_vals);
10449 		while(loop) {
10450 			entry = (nonroot_flags_t *)loop->data;
10451 
10452 			return_user_name(entry->uid, tmp2);
10453 	 		g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chown,
10454 				tmp2, entry->path);
10455 	 		strcat(ret,tmp);
10456 			return_group_name(entry->gid, tmp2);
10457 	 		g_snprintf(tmp,MAXLINE,"%s %s %s\n", cmd_chgrp,
10458 				tmp2, entry->path);
10459 	 		strcat(ret,tmp);
10460 	 		g_snprintf(tmp,MAXLINE,"%s %o %s\n", cmd_chmod,
10461 				(gint) entry->mode, entry->path);
10462 	 		strcat(ret,tmp);
10463 
10464 			loop = loop->next;
10465 		}
10466 		free_nonrootvalues(&nrs_vals);
10467 #endif
10468 	 	g_snprintf(bin,MAXLINE,"%s/%s", sharedir, WRAPPER);
10469 	 	g_snprintf(tmp,MAXLINE,"%s 755 %s\n", cmd_chmod, bin);
10470 	 	strcat(ret,tmp);
10471 	}
10472 	return 0;
10473 }
10474 
10475 
10476 /* save the current file owners and permissions to a file */
10477 #if 0
10478 gint save_current_nonrootvalues(gchar *confdir, gchar *fname) {
10479 gchar bin[MAXLINE];
10480 gchar tmp[MAXLINE];
10481 gchar share[MAXLINE];
10482 struct stat buf;
10483 uid_t uid;
10484 gid_t gid;
10485 mode_t mode;
10486 FILE *fd;
10487 
10488 	/* make sharedir absolute if is not yet */
10489 	if (sharedir[0] != '/') {
10490 		getcwd(tmp,MAXLINE);
10491 		g_snprintf(share,MAXLINE,"%s/%s", tmp, sharedir);
10492 	} else {
10493 		strcpy(share,sharedir);
10494 	}
10495 
10496 	/* first create directory to store nonrootconfig */
10497 	if (!is_directory(confdir)) {
10498 		/* try to create directory */
10499 		mkdir(confdir, 0700);
10500 		dodebug(2, "trying to mkdir %s\n", confdir);
10501 	}
10502 	g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
10503 
10504 	dodebug(1, "Opening %s for writing\n", tmp);
10505 
10506 	fd = fopen(tmp,"w");
10507 	if (fd == NULL) {
10508 		/* error opening file */
10509 		return 1;
10510 	}
10511 
10512 	/* write the config-file header */
10513 	fputs("#\n",fd);
10514 	g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Non-Root-Mode Configuration\n",XCDROAST_VERSION);
10515 	fputs(tmp,fd);
10516 	fputs("#\n",fd);
10517 	fputs("# Contains the files with their flags before they got changed\n",fd);
10518 	fputs("# by X-CD-Roast Non-Root-Mode activation.\n", fd);
10519 	fputs("# Used to restore the original values when disabling Non-Root-Mode.\n",fd);
10520 	fputs("#\n",fd);
10521 
10522 	/* get details about the wrapper */
10523 	g_snprintf(bin,MAXLINE,"%s/%s", share, WRAPPER);
10524 	if (stat(bin,&buf) == 0) {
10525 		uid = buf.st_uid;
10526 		gid = buf.st_gid;
10527 		mode = buf.st_mode & 07777;
10528 
10529 		g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin,
10530 			(gint) uid, (gint) gid, (gint) mode);
10531 		fputs(tmp,fd);
10532 	}
10533 
10534 	/* now the cdrtools - make path absolute */
10535 	get_spawn_path(CDRECORD,bin);
10536 	if (bin[0] != '/') {
10537 		getcwd(tmp,MAXLINE);
10538 		g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10539 	} else {
10540 		strcpy(bin2,bin);
10541 	}
10542 	if (stat(bin2,&buf) == 0) {
10543 		uid = buf.st_uid;
10544 		gid = buf.st_gid;
10545 		mode = buf.st_mode & 07777;
10546 
10547 		g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10548 			(gint) uid, (gint) gid, (gint) mode);
10549 		fputs(tmp,fd);
10550 	}
10551 
10552 	get_spawn_path(MKISOFS,bin);
10553 	if (bin[0] != '/') {
10554 		getcwd(tmp,MAXLINE);
10555 		g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10556 	} else {
10557 		strcpy(bin2,bin);
10558 	}
10559 	if (stat(bin2,&buf) == 0) {
10560 		uid = buf.st_uid;
10561 		gid = buf.st_gid;
10562 		mode = buf.st_mode & 07777;
10563 
10564 		g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10565 			(gint) uid, (gint) gid, (gint) mode);
10566 		fputs(tmp,fd);
10567 	}
10568 
10569 	get_spawn_path(READCD,bin);
10570 	if (bin[0] != '/') {
10571 		getcwd(tmp,MAXLINE);
10572 		g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10573 	} else {
10574 		strcpy(bin2,bin);
10575 	}
10576 	if (stat(bin2,&buf) == 0) {
10577 		uid = buf.st_uid;
10578 		gid = buf.st_gid;
10579 		mode = buf.st_mode & 07777;
10580 
10581 		g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10582 			(gint) uid, (gint) gid, (gint) mode);
10583 		fputs(tmp,fd);
10584 	}
10585 
10586 	get_spawn_path(CDDA2WAV,bin);
10587 	if (bin[0] != '/') {
10588 		getcwd(tmp,MAXLINE);
10589 		g_snprintf(bin2,MAXLINE,"%s/%s", tmp, bin);
10590 	} else {
10591 		strcpy(bin2,bin);
10592 	}
10593 	if (stat(bin2,&buf) == 0) {
10594 		uid = buf.st_uid;
10595 		gid = buf.st_gid;
10596 		mode = buf.st_mode & 07777;
10597 
10598 		g_snprintf(tmp,MAXLINE,"%s: %d %d 0%o\n", bin2,
10599 			(gint) uid, (gint) gid, (gint) mode);
10600 		fputs(tmp,fd);
10601 	}
10602 	if (fclose(fd) != 0) {
10603 		/* error closing file */
10604 		return 1;
10605 	}
10606 
10607 	return 0;
10608 
10609 }
10610 #endif
10611 
10612 
10613 /* run a simple non-output-command and return exit status */
10614 
simple_exec(gchar * cmd)10615 gint simple_exec(gchar *cmd) {
10616 gchar line[MAXLINE];
10617 FILE *fpin;
10618 gint stat;
10619 
10620 	dodebug(1, "calling: %s\n", cmd);
10621         if ((fpin = popen(cmd,"r")) == NULL) {
10622                 g_error("popen error\n");
10623         }
10624 
10625         for (;;) {
10626                 if (fgets(line,MAXLINE,fpin) == NULL)
10627                         break;
10628         }
10629 
10630 	stat = pclose(fpin);
10631         if (stat == -1) {
10632 		return -1;
10633         }
10634 
10635 	return (WEXITSTATUS(stat));
10636 }
10637 
10638 
10639 /* load nonroot-values from file */
10640 /* if some values not found, generate default */
10641 
10642 #if 0
10643 
10644 gint load_nonrootvalues(gchar *confdir, gchar *fname, GList **ret) {
10645 gchar tmp[MAXLINE];
10646 gchar line[MAXLINE];
10647 gchar path[MAXLINE];
10648 FILE *fd;
10649 gchar *p;
10650 gint uid, gid, mode;
10651 gint foundwrapper, foundcdrecord, foundmkisofs, foundcdda2wav, foundreadcd;
10652 
10653 	foundwrapper = 0;
10654 	foundcdrecord = 0;
10655 	foundmkisofs = 0;
10656 	foundcdda2wav = 0;
10657 	foundreadcd = 0;
10658 
10659 	g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
10660 
10661 	/* open file */
10662         if ((fd = fopen(tmp,"r")) != NULL) {
10663 
10664          dodebug(1, "Opened %s for reading\n", tmp);
10665 
10666 
10667          for (;;) {
10668                 if (fgets(line,MAXLINE,fd) == NULL)
10669                         break;
10670 
10671                 dodebug(10,"non-root-values: %s", line),
10672 
10673                 /* skip empty or hashed lines */
10674                 strip_string(line);
10675                 if (*line == '#' || *line == '\0')
10676                         continue;
10677 
10678 		uid = -1;
10679 		gid = -1;
10680 		mode = -1;
10681 
10682 		/* extract path */
10683 		strncpy(path,line,MAXLINE);
10684 		p = rindex(path,':');
10685 		if (p) {
10686 			*p = '\0';
10687 
10688 			strncpy(tmp, p+1, MAXLINE);
10689 			strip_string(tmp);
10690 
10691 			/* extract uid, gid and mode */
10692 			p = strtok(tmp," ");
10693 			if (p) {
10694 				uid = atoi(p);
10695 				p = strtok(NULL," ");
10696 				if (p) {
10697 					gid = atoi(p);
10698 					p = strtok(NULL,"");
10699 					if (p) {
10700 						mode = strtol(p, (char **)NULL,  8);
10701 					}
10702 				}
10703 			}
10704 		} else {
10705 			*path = '\0';
10706 		}
10707 
10708 		/* all data extracted successfully? */
10709 		if (*path != '\0' && uid != -1 && gid != -1 && mode != -1) {
10710 
10711 			add_to_nonrootvalues(ret, path, uid, gid, mode);
10712 
10713 			/* check what entry we just added */
10714 			if (strstr(path, WRAPPER)) {
10715 				foundwrapper = 1;
10716 			}
10717 			if (strstr(path, CDRECORD)) {
10718 				foundcdrecord = 1;
10719 			}
10720 			if (strstr(path, MKISOFS)) {
10721 				foundmkisofs = 1;
10722 			}
10723 			if (strstr(path, READCD)) {
10724 				foundreadcd = 1;
10725 			}
10726 			if (strstr(path, CDDA2WAV)) {
10727 				foundcdda2wav = 1;
10728 			}
10729 		}
10730 
10731 	 }
10732 
10733 	 fclose(fd);
10734 	}
10735 
10736 	/* now we read the file (or not, if it was not found) and add
10737 	   default values for any things we are missing */
10738 	if (!foundwrapper) {
10739 		g_snprintf(path,MAXLINE,"%s/%s", sharedir, WRAPPER);
10740 		add_to_nonrootvalues(ret, path, 0, 0, 0755);
10741 	}
10742 	if (!foundcdrecord) {
10743 		get_spawn_path(CDRECORD,path);
10744 		add_to_nonrootvalues(ret, path, 0, 0, 0755);
10745 	}
10746 	if (!foundmkisofs) {
10747 		get_spawn_path(MKISOFS,path);
10748 		add_to_nonrootvalues(ret, path, 0, 0, 0755);
10749 	}
10750 	if (!foundreadcd) {
10751 		get_spawn_path(READCD,path);
10752 		add_to_nonrootvalues(ret, path, 0, 0, 0755);
10753 	}
10754 	if (!foundcdda2wav) {
10755 		get_spawn_path(CDDA2WAV,path);
10756 		add_to_nonrootvalues(ret, path, 0, 0, 0755);
10757 	}
10758 
10759 	return 0;
10760 }
10761 #endif
10762 
10763 /* reads the .xinf file for a given track and writes a new .inf file
10764    with the updated cd-text information */
10765 
edit_xinf_for_cd_text(gchar * trackfile,gchar * tocfile)10766 void edit_xinf_for_cd_text(gchar *trackfile, gchar *tocfile) {
10767 gchar xinfname[MAXLINE], infname[MAXLINE];
10768 gchar tmp[MAXLINE];
10769 gchar *p;
10770 FILE *fd;
10771 gchar line[MAXLINE];
10772 gchar id[MAXLINE];
10773 gchar value[MAXLINE];
10774 gchar title[MAXLINE], artist[MAXLINE], cddbtitle[MAXLINE];
10775 gchar cdtitle[MAXLINE], cdartist[MAXLINE];
10776 
10777 /*
10778 	g_print("tocfile: %s, file: %s\n", tocfile, trackfile);
10779 */
10780 
10781 	/* generate xinf and inf filenames */
10782 	strncpy(tmp,trackfile,MAXLINE - 4);
10783 	p = rindex(tmp,'.');
10784 	if (!p) return;
10785 	*p = '\0';
10786 	strcpy(xinfname,tmp);
10787 	strcpy(infname,tmp);
10788 	strcat(xinfname,XCDROAST_INFO_EXT);
10789 	strcat(infname,".inf");
10790 
10791 	dodebug(10, "reading cdtext from %s\n", xinfname);
10792 
10793 	if ((fd = fopen(xinfname,"r")) == NULL) {
10794 		return;
10795 	}
10796 
10797 	strcpy(title,"");
10798 	strcpy(artist,"");
10799 	strcpy(cddbtitle,"");
10800 
10801 	for (;;) {
10802 		if (fgets(line,MAXLINE,fd) == NULL)
10803 			break;
10804 
10805 		/* skip empty or hashed lines */
10806 		strip_string(line);
10807 		if (*line == '#' || *line == '\0')
10808 			continue;
10809 
10810                 /* parse lines */
10811 		if (parse_config_line(line,id,value)) {
10812 			dodebug(10,"invalid line in infofile");
10813 			fclose(fd);
10814 			return;
10815 		}
10816 
10817 		if (strcmp("title",id) == 0) {
10818 			strncpy(title, value, MAXLINE);
10819 		}
10820 		if (strcmp("artist",id) == 0) {
10821 			strncpy(artist, value, MAXLINE);
10822 		}
10823 		if (strcmp("cddb_ttitle",id) == 0) {
10824 			strncpy(cddbtitle, value, MAXLINE);
10825 		}
10826 	}
10827 
10828 	if (fclose(fd) != 0) {
10829 		return;
10830 	}
10831 
10832 
10833 	/* decide if we use cddb info rather than cd-text info? */
10834 	if (strcmp(title,"") == 0) {
10835 		if (strcmp(cddbtitle,"") != 0) {
10836 			/* no title, but cddb given */
10837 			strncpy(title, cddbtitle, MAXLINE);
10838 		}
10839 	}
10840 
10841 	strcpy(cdtitle,"");
10842 	strcpy(cdartist,"");
10843 
10844 	/* now read toc file for cd-title/artist */
10845 	if (strcmp(tocfile,"-") != 0) {
10846 		dodebug(10, "reading cdtext from %s\n", tocfile);
10847 
10848 		fd = fopen(tocfile,"r");
10849 
10850 		if (fd) {
10851 			for (;;) {
10852 				if (fgets(line,MAXLINE,fd) == NULL)
10853 					break;
10854 
10855 				/* skip empty or hashed lines */
10856 				strip_string(line);
10857 				if (*line == '#' || *line == '\0')
10858 					continue;
10859 
10860                 		/* parse lines */
10861 				if (parse_config_line(line,id,value)) {
10862 					dodebug(10,"invalid line in toc");
10863 					fclose(fd);
10864 					return;
10865 				}
10866 				if (strcmp("cdtitle",id) == 0) {
10867 					strncpy(tmp, value, MAXLINE);
10868 					get_artist_and_title_from_cddb(
10869 						tmp, cdartist, cdtitle);
10870 				}
10871 			}
10872 			fclose(fd);
10873 		}
10874 	}
10875 
10876 	/* now we have read all the info from the xinf and toc file */
10877 
10878 	/* edit the original .inf file */
10879 	edit_xinf_for_cd_text2(infname, title, artist, cdtitle, cdartist);
10880 }
10881 
10882 
10883 /* patch the given cd-text information the the inffile */
10884 
edit_xinf_for_cd_text2(gchar * infname,gchar * title,gchar * artist,gchar * cdtitle,gchar * cdartist)10885 static void edit_xinf_for_cd_text2(gchar *infname, gchar *title, gchar *artist, gchar *cdtitle, gchar *cdartist) {
10886 gchar tmpinfname[MAXLINE];
10887 gchar tmp[MAXLINE];
10888 gchar line[MAXLINE];
10889 FILE *fd, *fd2;
10890 gchar timestr[MAXLINE];
10891 gint found, found2, found3, found4;
10892 time_t acttime;
10893 
10894 	dodebug(10, "cd-text info: %s, %s, %s, %s\n", title, artist, cdtitle, cdartist);
10895 
10896 	/* get current time */
10897 	acttime = time((time_t *) 0);
10898 	strcpy(timestr,ctime(&acttime));
10899 	timestr[strlen(timestr)-1] = '\0';
10900 
10901 	g_snprintf(tmpinfname,MAXLINE,"%s-%d", infname, (gint) getpid());
10902 
10903 	/* now modify the original inf file */
10904 	fd = fopen(infname,"r");
10905 	if (!fd) {
10906 		/* no inf file? - generate one */
10907 		fd2 = fopen(infname,"w");
10908 		if (!fd2) return;
10909 
10910 		/* write releveant data to new inf file */
10911 		g_snprintf(tmp,MAXLINE,"#created by X-CD-Roast %s at %s\n", XCDROAST_VERSION, timestr);
10912 		fputs(tmp, fd2);
10913 		fputs("#\n",fd2);
10914 
10915 		g_snprintf(tmp,MAXLINE,"Performer=\t'%s'\n", artist);
10916 		fputs(tmp, fd2);
10917 
10918 		g_snprintf(tmp,MAXLINE,"Albumtitle=\t'%s'\n", cdtitle);
10919 		fputs(tmp, fd2);
10920 
10921 		g_snprintf(tmp,MAXLINE,"Tracktitle=\t'%s'\n", title);
10922 		fputs(tmp, fd2);
10923 
10924 		g_snprintf(tmp,MAXLINE,"Albumperformer=\t'%s'\n", cdartist);
10925 		fputs(tmp, fd2);
10926 
10927 		fclose(fd2);
10928 
10929 		dodebug(10, "created cd-text-info as %s\n", infname);
10930 	} else {
10931 		/* inf file openend - open now tmpfile */
10932 		fd2 = fopen(tmpinfname,"w");
10933 		if (!fd2) {
10934 			fclose(fd);
10935 			return;
10936 		}
10937 
10938 		found = 0;
10939 		found2 = 0;
10940 		found3 = 0;
10941 		found4 = 0;
10942 
10943 		for (;;) {
10944 			if (fgets(line,MAXLINE,fd) == NULL)
10945 				break;
10946 
10947 			/* write modifcation date of xcdroast in new file */
10948 			if (strncmp(line,"#created", 8) == 0) {
10949 				fputs(line, fd2);
10950 				g_snprintf(tmp,MAXLINE,"#modified by X-CD-Roast %s at %s\n", XCDROAST_VERSION, timestr);
10951 				fputs(tmp, fd2);
10952 				continue;
10953 			}
10954 
10955 			/* skip old modfied lines */
10956 			if (strncmp(line,"#modified by X-CD-Roast", 23) == 0) {
10957 				continue;
10958 			}
10959 
10960 			/* replace performer */
10961 			if (strncmp(line,"Performer=", 10) == 0) {
10962 				g_snprintf(tmp,MAXLINE,"Performer=\t'%s'\n", artist);
10963 				fputs(tmp, fd2);
10964 				found = 1;
10965 				continue;
10966 			}
10967 
10968 			/* replace title */
10969 			if (strncmp(line,"Tracktitle=", 11) == 0) {
10970 				g_snprintf(tmp,MAXLINE,"Tracktitle=\t'%s'\n", title);
10971 				fputs(tmp, fd2);
10972 				found2 = 1;
10973 				continue;
10974 			}
10975 
10976 			/* replace albumtitle */
10977 			if (strncmp(line,"Albumtitle=", 11) == 0) {
10978 				g_snprintf(tmp,MAXLINE,"Albumtitle=\t'%s'\n", cdtitle);
10979 				fputs(tmp, fd2);
10980 				found3 = 1;
10981 				continue;
10982 			}
10983 
10984 			/* replace albumperformer */
10985 			if (strncmp(line,"Albumperformer=", 11) == 0) {
10986 				g_snprintf(tmp,MAXLINE,"Albumperformer=\t'%s'\n", cdartist);
10987 				fputs(tmp, fd2);
10988 				found4 = 1;
10989 				continue;
10990 			}
10991 
10992 			fputs(line,fd2);
10993 		}
10994 
10995 		/* could not replace all the original lines? add any
10996 		   missing now */
10997 		if (found == 0) {
10998 			g_snprintf(tmp,MAXLINE,"Performer=\t'%s'\n", artist);
10999 			fputs(tmp, fd2);
11000 		}
11001 		if (found3 == 0) {
11002 			g_snprintf(tmp,MAXLINE,"Albumtitle=\t'%s'\n", cdtitle);
11003 			fputs(tmp, fd2);
11004 		}
11005 		if (found2 == 0) {
11006 			g_snprintf(tmp,MAXLINE,"Tracktitle=\t'%s'\n", title);
11007 			fputs(tmp, fd2);
11008 		}
11009 		if (found4 == 0) {
11010 			g_snprintf(tmp,MAXLINE,"Albumperformer=\t'%s'\n", cdartist);
11011 			fputs(tmp, fd2);
11012 		}
11013 
11014 		fclose(fd2);
11015 		fclose(fd);
11016 
11017 		/* now move the temporary file over the original inf file */
11018 		move_textfile(tmpinfname, infname);
11019 
11020 		dodebug(10, "modified cd-text-info in %s\n", infname);
11021 	}
11022 
11023 }
11024 
11025 
11026 /* does overwrite the artist and title information in the given toc file */
11027 
edit_title_artist_in_toc_file(gchar * tocfile,gchar * title,gchar * artist)11028 void edit_title_artist_in_toc_file(gchar *tocfile, gchar *title, gchar *artist) {
11029 FILE *fd, *fd2;
11030 gchar line[MAXLINE];
11031 gchar tmp[MAXLINE];
11032 gchar tmptitle[MAXLINE];
11033 gchar tmpartist[MAXLINE];
11034 gchar tmptocfile[MAXLINE];
11035 gint found;
11036 struct stat buf;
11037 
11038 	/* check first if file exists before overwriting it */
11039 	if (lstat(tocfile, &buf) == 0) {
11040 
11041 		/* file real and owner is also yourself? */
11042 		if (buf.st_uid != getuid() || S_ISLNK(buf.st_mode)) {
11043 			dodebug(1, "cannot edit tocfile %s, because file already exists and it belongs not to us, or is a link\n", tocfile);
11044 			return;
11045 		}
11046 	}
11047 
11048 	found = 0;
11049 	g_snprintf(tmptocfile,MAXLINE,"%s-%d", tocfile, (gint) getpid());
11050 
11051 	dodebug(10, "updating toc file %s with new title/artist\n", tocfile);
11052 
11053 	/* open toc file for reading */
11054         if ((fd = fopen(tocfile,"r")) == NULL) {
11055 		/* no file? */
11056                 return;
11057         }
11058 
11059 	/* open temporary tocfile to copy */
11060         if ((fd2 = fopen(tmptocfile,"w")) == NULL) {
11061 		/* no file? */
11062 		fclose(fd);
11063                 return;
11064         }
11065 
11066 	/* copy all lines and change the one with the cdtitle */
11067         for (;;) {
11068                 if (fgets(line,MAXLINE,fd) == NULL)
11069                         break;
11070 
11071 		/* replace the line with the cdtitle */
11072 		if (strncmp(line,"cdtitle", 7) == 0) {
11073 			strncpy(tmptitle, title, MAXLINE);
11074 			strncpy(tmpartist, artist, MAXLINE);
11075 			g_snprintf(tmp,MAXLINE,"cdtitle = \"%s / %s\"\n", convert_escape(tmptitle), convert_escape(tmpartist));
11076 			fputs(tmp, fd2);
11077 			found = 1;
11078 			continue;
11079 		}
11080 
11081 		fputs(line,fd2);
11082 	}
11083 
11084 	/* no line with cdtitle found? */
11085 	if (found == 0) {
11086 		/* add it */
11087 		g_snprintf(tmp,MAXLINE,"cdtitle = \"%s / %s\"\n", title, artist);
11088 		fputs(tmp, fd2);
11089 	}
11090 	fclose(fd2);
11091 	fclose(fd);
11092 
11093         /* now move the temporary file over the original inf file */
11094         move_textfile(tmptocfile, tocfile);
11095 
11096 }
11097 
11098 
11099 /* edits or creates a xinf file with updated information of title and artist */
11100 
edit_title_artist_in_xinf_file(gchar * trackfile,gchar * title,gchar * artist)11101 void edit_title_artist_in_xinf_file(gchar *trackfile, gchar *title, gchar *artist) {
11102 FILE *fd, *fd2;
11103 gchar line[MAXLINE];
11104 gchar tmp[MAXLINE];
11105 gchar tmptitle[MAXLINE];
11106 gchar tmpartist[MAXLINE];
11107 gchar xinfname[MAXLINE];
11108 gchar tmpxinfname[MAXLINE];
11109 gint found, found2;
11110 gchar *p;
11111 time_t acttime;
11112 gchar timestr[MAXLINE];
11113 
11114         /* get current time */
11115         acttime = time((time_t *) 0);
11116         strcpy(timestr,ctime(&acttime));
11117         timestr[strlen(timestr)-1] = '\0';
11118 
11119 	found = 0;
11120 	found2 = 0;
11121 
11122         strncpy(tmp,trackfile,MAXLINE - 4);
11123         p = rindex(tmp,'.');
11124         if (!p) return;
11125         *p = '\0';
11126         strcpy(xinfname,tmp);
11127         strcat(xinfname,XCDROAST_INFO_EXT);
11128         g_snprintf(tmpxinfname,MAXLINE,"%s-%d", xinfname, (gint) getpid());
11129 
11130 	/* try to open the xinf file */
11131         if ((fd = fopen(xinfname,"r")) == NULL) {
11132 		/* no such file? try to create a new */
11133 		fd = fopen(xinfname,"w");
11134 		if (!fd) return;
11135 
11136 		dodebug(10, "creating xinf-file %s with new title/artist\n", xinfname);
11137 
11138 	        /* write header */
11139 	        fputs("#\n",fd);
11140        		g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - INF-File\n",XCDROAST_VERSION);
11141 		fputs(tmp,fd);
11142        		g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11143         	fputs(tmp,fd);
11144         	g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11145         	fputs(tmp,fd);
11146         	fputs("#\n",fd);
11147 
11148 	        g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",trackfile);
11149 	        fputs(tmp,fd);
11150 		strncpy(tmptitle, title, MAXLINE);
11151 	        g_snprintf(tmp,MAXLINE,"title = \"%s\"\n",convert_escape(tmptitle));
11152 	        fputs(tmp,fd);
11153 		strncpy(tmpartist, artist, MAXLINE);
11154 	        g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n",convert_escape(tmpartist));
11155      	   	fputs(tmp,fd);
11156 
11157 		fclose(fd);
11158 		return;
11159         }
11160 
11161         /* open temporary xinffile to copy */
11162         if ((fd2 = fopen(tmpxinfname,"w")) == NULL) {
11163                 /* no file? */
11164                 fclose(fd);
11165                 return;
11166         }
11167 
11168         /* copy a lines and change the one with the cdtitle */
11169         for (;;) {
11170                 if (fgets(line,MAXLINE,fd) == NULL)
11171                         break;
11172 
11173                 /* replace the line with the title */
11174                 if (strncmp(line,"title", 5) == 0) {
11175 			strncpy(tmptitle, title, MAXLINE);
11176                         g_snprintf(tmp,MAXLINE,"title = \"%s\"\n", convert_escape(tmptitle));
11177                         fputs(tmp, fd2);
11178                         found = 1;
11179                         continue;
11180                 }
11181 
11182                 /* replace the line with the artist */
11183                 if (strncmp(line,"artist", 6) == 0) {
11184 			strncpy(tmpartist, artist, MAXLINE);
11185                         g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n", convert_escape(tmpartist));
11186                         fputs(tmp, fd2);
11187                         found2 = 1;
11188                         continue;
11189                 }
11190 
11191                 fputs(line,fd2);
11192         }
11193 
11194 	/* lines missing? add them */
11195 	if (found == 0) {
11196 		strncpy(tmptitle, title, MAXLINE);
11197         	g_snprintf(tmp,MAXLINE,"title = \"%s\"\n", convert_escape(tmptitle));
11198                 fputs(tmp, fd2);
11199 	}
11200 	if (found2 == 0) {
11201 		strncpy(tmpartist, artist, MAXLINE);
11202         	g_snprintf(tmp,MAXLINE,"artist = \"%s\"\n", convert_escape(tmpartist));
11203         	fputs(tmp, fd2);
11204 	}
11205 
11206         fclose(fd2);
11207         fclose(fd);
11208 
11209 	dodebug(10, "updated xinf-file %s with new title/artist\n", xinfname);
11210 
11211         /* now move the temporary file over the original inf file */
11212         move_textfile(tmpxinfname, xinfname);
11213 }
11214 
11215 
11216 /* will write a temporary toc file just to save the album title and performer
11217    of the tracks to be written in the write-tracks menu */
11218 
create_tmp_writetracks_tocfile(gchar * tocfile)11219 gint create_tmp_writetracks_tocfile(gchar *tocfile) {
11220 FILE *fd;
11221 time_t acttime;
11222 gchar timestr[MAXLINE];
11223 gchar tmp[MAXLINE];
11224 struct stat buf;
11225 
11226 	if (tocfile == NULL) return 1;
11227 
11228 	/* check first if file exists before overwriting it */
11229 	if (lstat(tocfile, &buf) == 0) {
11230 
11231 		/* file real and owner is also yourself? */
11232 		if (buf.st_uid != getuid() || S_ISLNK(buf.st_mode)) {
11233 			dodebug(1, "cannot create temporary tocfile %s, because file already exists and it belongs not to us, or is a link\n", tocfile);
11234 			return 1;
11235 		}
11236 	}
11237 
11238 	dodebug(8, "creating temporary tocfile %s\n", tocfile);
11239 	fd = fopen(tocfile,"w");
11240 
11241         if (fd == NULL) {
11242                 g_warning("Can't open file %s for writing\n",tocfile);
11243                 return 1;
11244         }
11245 
11246         /* get current time */
11247         acttime = time((time_t *) 0);
11248         strcpy(timestr,ctime(&acttime));
11249         timestr[strlen(timestr)-1] = '\0';
11250 
11251         /* write header */
11252         fputs("#\n",fd);
11253         g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - temporary TOC-File\n",XCDROAST_VERSION);
11254         fputs(tmp,fd);
11255         g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11256         fputs(tmp,fd);
11257         g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11258         fputs(tmp,fd);
11259         fputs("#\n",fd);
11260 
11261 	/* write empty cdtitle */
11262 	g_snprintf(tmp,MAXLINE,"cdtitle = \"\"\n");
11263         fputs(tmp,fd);
11264 
11265 	fclose(fd);
11266 
11267 	return 0;
11268 }
11269 
11270 
11271 /* removes the temporary tocfile again */
11272 /* makes plenty of security checks to remove only a "sane" file */
11273 
remove_tmp_writetracks_tocfile(gchar * tocfile)11274 static void remove_tmp_writetracks_tocfile(gchar *tocfile) {
11275 struct stat buf;
11276 
11277 	/* check first if file exists before delting it */
11278 	if (lstat(tocfile, &buf) == 0) {
11279 
11280 		/* file real and owner is also yourself? */
11281 		if (buf.st_uid == getuid() && !S_ISLNK(buf.st_mode)) {
11282 
11283 			dodebug(2, "removing temporary file %s\n", tocfile);
11284 			unlink(tocfile);
11285 		} else {
11286 			g_warning("Trying to remove file %s which does not belong us or is a link!\n", tocfile);
11287 		}
11288 	}
11289 }
11290 
11291 
11292 /* just read the line with the cdtitle from a tocfile and returns it */
11293 
get_cdtitle_from_tmp_tocfile(gchar * tocfile,gchar * cdtitle)11294 void get_cdtitle_from_tmp_tocfile(gchar *tocfile, gchar *cdtitle) {
11295 FILE *fd;
11296 gchar line[MAXLINE];
11297 gchar id[MAXLINE];
11298 gchar value[MAXLINE];
11299 
11300 	strcpy(cdtitle, "");
11301 
11302 	dodebug(2, "reading temporary toc file %s\n", tocfile);
11303         fd = fopen(tocfile,"r");
11304 
11305         if (fd == NULL) {
11306 		return;
11307         }
11308 
11309         for (;;) {
11310                 if (fgets(line,MAXLINE,fd) == NULL)
11311                         break;
11312 
11313                 dodebug(10,"read tocfile: %s", line);
11314                 /* skip empty or hashed lines */
11315                 strip_string(line);
11316                 if (*line == '#' || *line == '\0')
11317                         continue;
11318 
11319                 /* parse lines */
11320                 if (parse_config_line(line,id,value)) {
11321                         dodebug(10,"invalid line in tocfile");
11322                         fclose(fd);
11323                         return;
11324                 }
11325 
11326                 if (strcmp("cdtitle",id) == 0) {
11327                         strncpy(cdtitle, value, MAXLINE);
11328                 }
11329 	}
11330 
11331 	fclose(fd);
11332 }
11333 
11334 
11335 /* saves the current list of paths to master to a file */
11336 
save_master_list(gchar * fname)11337 gint save_master_list(gchar *fname) {
11338 FILE *fd;
11339 gchar tmp[MAXLINE];
11340 gchar tmpexcl[MAXLINE];
11341 gchar tmppath1[MAXLINE];
11342 gchar tmppath2[MAXLINE];
11343 struct stat buf;
11344 gint ret;
11345 time_t acttime;
11346 gchar timestr[MAXLINE];
11347 mstr_redirect_t *mstr;
11348 gchar *excl;
11349 GList *loop;
11350 
11351 	/* first check if this file does already exist */
11352 	if (lstat(fname, &buf) == 0) {
11353 		g_snprintf(tmp,1024,_("File %s already exists.\nAre you sure you want to overwrite it?"), fname);
11354 		ret = show_dialog(ICO_WARN, tmp, T_OK, T_CANCEL, NULL, 1);
11355 		if (ret == 1) {
11356 			return -1;
11357 		}
11358 	}
11359 
11360 	dodebug(1, "Opening %s for writing (master paths)\n", fname);
11361 
11362         fd = fopen(fname,"w");
11363         if (fd == NULL) {
11364                 /* error opening file */
11365                 return 1;
11366         }
11367 
11368         /* get current time */
11369         acttime = time((time_t *) 0);
11370         strcpy(timestr,ctime(&acttime));
11371         timestr[strlen(timestr)-1] = '\0';
11372 
11373         /* write header */
11374 
11375         fputs("#\n",fd);
11376         g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - Master-Paths\n",XCDROAST_VERSION);
11377 	fputs(tmp,fd);
11378         g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11379         fputs(tmp,fd);
11380         g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11381         fputs(tmp,fd);
11382         fputs("#\n",fd);
11383 
11384 	/* get all paths */
11385 	loop = g_list_first(masterparam.mstr_redir);
11386 	while (loop) {
11387                 mstr = (mstr_redirect_t *) loop->data;
11388                 if (mstr) {
11389 			if (mstr->mstr_path && !mstr->redir_path) {
11390 				strncpy(tmppath1, mstr->mstr_path, MAXLINE);
11391 				g_snprintf(tmp,MAXLINE,"ADD1 = \"%s\"\n", convert_escape(tmppath1));
11392 			} else
11393 			if (mstr->mstr_path && mstr->redir_path) {
11394 				strncpy(tmppath1, mstr->mstr_path, MAXLINE);
11395 				strncpy(tmppath2, mstr->redir_path, MAXLINE);
11396 				g_snprintf(tmp,MAXLINE,"ADD2 = \"%s\",\"%s\"\n", convert_escape(tmppath1), convert_escape(tmppath2));
11397 			}
11398         		fputs(tmp,fd);
11399 		}
11400 		loop = loop->next;
11401 	}
11402 
11403         /* get exclude-dirs */
11404         loop = g_list_first(masterparam.exclude_paths);
11405         while (loop) {
11406                 excl = (gchar *)loop->data;
11407 		if (excl) {
11408 			strncpy(tmpexcl, excl, MAXLINE);
11409 			g_snprintf(tmp,MAXLINE,"EXCL = \"%s\"\n", convert_escape(tmpexcl));
11410         		fputs(tmp,fd);
11411 		}
11412 		loop = loop->next;
11413 	}
11414 
11415         if (fclose(fd) != 0) {
11416                 /* error closing file */
11417                 return 1;
11418         }
11419 
11420 	return 0;
11421 }
11422 
11423 
11424 /* loads the master-paths from a file */
11425 
load_master_list(gchar * fname)11426 gint load_master_list(gchar *fname) {
11427 FILE *fd;
11428 gchar line[MAXLINE];
11429 gchar id[MAXLINE];
11430 gchar value[MAXLINE];
11431 gchar value2[MAXLINE];
11432 mstr_redirect_t *mstr;
11433 
11434 	dodebug(1, "Opening config file %s for reading (master paths)\n", fname);
11435 
11436         if ((fd = fopen(fname,"r")) == NULL) {
11437                 /* error opening file */
11438                 return 1;
11439         }
11440 
11441 	/* could open the file, now clear the master data */
11442 	clear_mstr_glist(&masterparam.mstr_redir);
11443 	free_glist(&masterparam.exclude_paths);
11444 
11445 
11446         for (;;) {
11447                 if (fgets(line,MAXLINE,fd) == NULL)
11448                         break;
11449 
11450                 dodebug(10,"master-paths: %s", line),
11451 
11452                 /* skip empty or hashed lines */
11453                 strip_string(line);
11454                 if (*line == '#' || *line == '\0')
11455                         continue;
11456 
11457                 /* parse lines */
11458 		if (parse_config_line(line,id,value)) {
11459                 	g_warning("syntax error in master-paths-file\n");
11460 			continue;
11461 		}
11462 
11463 		if (strcmp("ADD1", id) == 0) {
11464 			if (strcmp(value,"") != 0) {
11465 				/* add this value to the list */
11466 				mstr = g_new0(mstr_redirect_t,1);
11467 				mstr->mstr_path = g_strdup(value);
11468 				masterparam.mstr_redir = g_list_append(masterparam.mstr_redir, mstr);
11469 			}
11470 		}
11471 		if (strcmp("ADD2", id) == 0) {
11472 			parse_config_line2(line,id,value,value2);
11473 			if (strcmp(value,"") != 0) {
11474 				/* add this value to the list */
11475 				mstr = g_new0(mstr_redirect_t,1);
11476 				mstr->mstr_path = g_strdup(value);
11477 				masterparam.mstr_redir = g_list_append(masterparam.mstr_redir, mstr);
11478 				/* add add redirection if given */
11479 				if (strcmp(value2,"") != 0) {
11480 					add_redir_mstr_glist(
11481 						&masterparam.mstr_redir,
11482 						value, value2);
11483 				}
11484 			}
11485 		}
11486 		if (strcmp("EXCL", id) == 0) {
11487 			if (strcmp(value,"") != 0) {
11488 				/* add exclude */
11489 				masterparam.exclude_paths = g_list_append(
11490                         		masterparam.exclude_paths,
11491 					g_strdup(value));
11492 			}
11493 		}
11494 	}
11495 
11496         if (fclose(fd) != 0) {
11497                 /* error closing file */
11498                 return 1;
11499         }
11500 
11501         return 0;
11502 }
11503 
11504 
11505 /* writes an info-file with the multisession-information after a
11506    track was mastered */
11507 
write_inf_file_for_master(gchar * fname,gint tracknr)11508 gint write_inf_file_for_master(gchar *fname, gint tracknr) {
11509 FILE *fd;
11510 time_t acttime;
11511 gchar timestr[MAXLINE];
11512 gchar tmp[MAXLINE];
11513 gchar tmp2[MAXLINE];
11514 gchar *p;
11515 
11516 	/* get current time */
11517 	acttime = time((time_t *) 0);
11518 	strcpy(timestr,ctime(&acttime));
11519 	timestr[strlen(timestr)-1] = '\0';
11520 
11521 	if (!fname || !*fname) {
11522 		return 1;
11523 	}
11524 
11525 	/* generate filename */
11526 	/* (remove extension and put .xinf there) */
11527 	strncpy(tmp,fname,MAXLINE -4);
11528 	p = rindex(tmp,'.');
11529 	if (!p) return 1;
11530 	*p = '\0';
11531 	strcpy(tmp2,tmp);
11532 	strcat(tmp2,XCDROAST_INFO_EXT);
11533 
11534 	dodebug(1,"writing inffile %s\n", tmp2);
11535 
11536         /* is a link? */
11537         if (check_islink(tmp2, NULL)) {
11538         	g_warning("Warning, won't overwrite a link at %s\n", tmp2);
11539 		return 1;
11540         }
11541 
11542 	/* write to file */
11543 	fd = fopen(tmp2,"w");
11544 
11545 	if (fd == NULL) {
11546 		g_warning("Can't open file %s for writing\n",tmp2);
11547 		return 1;
11548 	}
11549 
11550 	/* write header */
11551 	fputs("#\n",fd);
11552 	g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s - INF-File\n",XCDROAST_VERSION);
11553 	fputs(tmp,fd);
11554 	g_snprintf(tmp,MAXLINE,"# created: %s\n", timestr);
11555 	fputs(tmp,fd);
11556 	g_snprintf(tmp,MAXLINE,"# by: %s@%s\n", username, hostname);
11557 	fputs(tmp,fd);
11558 	fputs("#\n",fd);
11559 
11560 	g_snprintf(tmp,MAXLINE,"file = \"%s\"\n",fname);
11561 	fputs(tmp,fd);
11562 	g_snprintf(tmp,MAXLINE,"track = %d of %d\n",
11563 			tracknr, tracknr);
11564 	fputs(tmp,fd);
11565 
11566 	g_snprintf(tmp,MAXLINE,"size = %d\n", masterparam.session_size);
11567 	fputs(tmp,fd);
11568 	g_snprintf(tmp,MAXLINE,"type = %d\n", 0);
11569 	fputs(tmp,fd);
11570 	g_snprintf(tmp,MAXLINE,"last_session_start = %d\n", masterparam.last_session_start);
11571 	fputs(tmp,fd);
11572 	g_snprintf(tmp,MAXLINE,"next_session_start = %d\n", masterparam.next_session_start);
11573 	fputs(tmp,fd);
11574 
11575 	if (fclose(fd) != 0) {
11576 		/* error closing file */
11577 		return 1;
11578 	}
11579 
11580 	return 0;
11581 }
11582 
11583 
11584 /* Save the current write-options to a file
11585    return 0 if ok, or 1 on error */
11586 
save_writeoptions_file(gchar * confdir,gchar * fname)11587 gint save_writeoptions_file(gchar *confdir, gchar *fname) {
11588 FILE *fd;
11589 gchar tmp[MAXLINE];
11590 
11591         /* now check if the confdir exists */
11592         if (!is_directory(confdir)) {
11593                 /* try to create directory */
11594                 mkdir(confdir, 0700);
11595                 dodebug(2, "trying to mkdir %s\n", confdir);
11596         }
11597 
11598 	g_snprintf(tmp,MAXLINE,"%s/%s", confdir, fname);
11599 
11600         dodebug(1, "Opening %s for writing\n", tmp);
11601         dolog(3, "Saving write-options file %s\n", tmp);
11602 
11603         fd = fopen(tmp,"w");
11604 
11605         if (fd == NULL) {
11606                 /* error opening file */
11607                 return 1;
11608         }
11609 
11610         /* write the config-file header */
11611         fputs("#\n",fd);
11612         g_snprintf(tmp,MAXLINE,"# X-CD-Roast %s Write-Options-File\n",XCDROAST_VERSION);
11613         fputs(tmp,fd);
11614         fputs("#\n",fd);
11615         fputs("# Automatically created by the X-CD-Roast-Setup\n",fd);
11616         fputs("# Don't edit! (Unless you REALLY know what you are doing)\n",fd);
11617         fputs("#\n\n",fd);
11618 
11619         /* write data */
11620         g_snprintf(tmp,MAXLINE,"VERSION = \"%s\"\n",XCDROAST_VERSION);
11621         fputs(tmp,fd);
11622         g_snprintf(tmp,MAXLINE,"PLATFORM = \"%s\"\n",system_platform);
11623         fputs(tmp,fd);
11624 
11625 	g_snprintf(tmp,MAXLINE,"WRITE_SIMUL = %d\n", curset.writesimul);
11626         fputs(tmp,fd);
11627 	g_snprintf(tmp,MAXLINE,"WRITE_EJECT = %d\n", curset.writeeject);
11628         fputs(tmp,fd);
11629 	g_snprintf(tmp,MAXLINE,"WRITE_PAD = %d\n", curset.writepad);
11630         fputs(tmp,fd);
11631 	g_snprintf(tmp,MAXLINE,"WRITE_SWAP = %d\n", curset.writeswap);
11632         fputs(tmp,fd);
11633 	g_snprintf(tmp,MAXLINE,"WRITE_NOFIXATE = %d\n", curset.nofixate);
11634         fputs(tmp,fd);
11635 	g_snprintf(tmp,MAXLINE,"WRITE_CDTEXT = %d\n", curset.writecdtext);
11636         fputs(tmp,fd);
11637 	g_snprintf(tmp,MAXLINE,"WRITE_OVERBURN = %d\n", curset.writeoverburn);
11638         fputs(tmp,fd);
11639 	g_snprintf(tmp,MAXLINE,"WRITE_BURNFREE = %d\n", curset.writeburnfree);
11640         fputs(tmp,fd);
11641 	g_snprintf(tmp,MAXLINE,"WRITE_AUDIOMASTER = %d\n", curset.writeaudiomaster);
11642         fputs(tmp,fd);
11643 	g_snprintf(tmp,MAXLINE,"WRITE_FORCESPEED = %d\n", curset.writeforcespeed);
11644         fputs(tmp,fd);
11645 	g_snprintf(tmp,MAXLINE,"WRITE_VARIREC = %d\n", curset.writevarirec);
11646         fputs(tmp,fd);
11647 	g_snprintf(tmp,MAXLINE,"WRITE_IGNSIZE = %d\n", curset.writeignsize);
11648         fputs(tmp,fd);
11649 	g_snprintf(tmp,MAXLINE,"WRITE_IMMED = %d\n", curset.writeimmed);
11650         fputs(tmp,fd);
11651 
11652         if (fclose(fd) != 0) {
11653                 /* error closing file */
11654                 return 1;
11655         }
11656 
11657         return 0;
11658 }
11659 
11660 
11661 /* Load the write-options-default file
11662    return 0 if ok, or 1 on error */
11663 
load_writeoptions_file(gchar * fname)11664 gint load_writeoptions_file(gchar *fname) {
11665 FILE *fd;
11666 gchar line[MAXLINE];
11667 gchar id[MAXLINE];
11668 gchar value[MAXLINE];
11669 
11670         if ((fd = fopen(fname,"r")) == NULL) {
11671                 /* error opening file */
11672         	dodebug(1, "Failed to open write options file %s\n", fname);
11673         	dolog(3, "Failed loading write options file %s\n", fname);
11674                 return 1;
11675         }
11676 
11677         dodebug(1, "Opening write options file %s for reading\n", fname);
11678         dolog(3, "Loading write options file %s\n", fname);
11679 
11680         for (;;) {
11681                 if (fgets(line,MAXLINE,fd) == NULL)
11682                         break;
11683 
11684                 dodebug(10,"isooptions: %s", line),
11685 
11686                 /* skip empty or hashed lines */
11687                 strip_string(line);
11688                 if (*line == '#' || *line == '\0')
11689                         continue;
11690 
11691                 /* parse lines */
11692 		if (parse_config_line(line,id,value)) {
11693                 	g_error("syntax error in isooptions-file\n");
11694 		}
11695 
11696 		if (strcmp("WRITE_SIMUL", id) == 0) {
11697 			curset.writesimul = atoi(value);
11698 		}
11699 		if (strcmp("WRITE_EJECT", id) == 0) {
11700 			curset.writeeject = atoi(value);
11701 		}
11702 		if (strcmp("WRITE_PAD", id) == 0) {
11703 			curset.writepad = atoi(value);
11704 		}
11705 		if (strcmp("WRITE_SWAP", id) == 0) {
11706 			curset.writeswap = atoi(value);
11707 		}
11708 		if (strcmp("WRITE_NOFIXATE", id) == 0) {
11709 			curset.nofixate = atoi(value);
11710 		}
11711 		if (strcmp("WRITE_CDTEXT", id) == 0) {
11712 			curset.writecdtext = atoi(value);
11713 		}
11714 		if (strcmp("WRITE_OVERBURN", id) == 0) {
11715 			curset.writeoverburn = atoi(value);
11716 		}
11717 		if (strcmp("WRITE_BURNFREE", id) == 0) {
11718 			curset.writeburnfree = atoi(value);
11719 		}
11720 		if (strcmp("WRITE_AUDIOMASTER", id) == 0) {
11721 			curset.writeaudiomaster = atoi(value);
11722 		}
11723 		if (strcmp("WRITE_FORCESPEED", id) == 0) {
11724 			curset.writeforcespeed = atoi(value);
11725 		}
11726 		if (strcmp("WRITE_VARIREC", id) == 0) {
11727 			curset.writevarirec = atoi(value);
11728 		}
11729 		if (strcmp("WRITE_IGNSIZE", id) == 0) {
11730 			curset.writeignsize = atoi(value);
11731 		}
11732 		if (strcmp("WRITE_IMMED", id) == 0) {
11733 			curset.writeimmed = atoi(value);
11734 		}
11735 	}
11736 
11737         if (fclose(fd) != 0) {
11738                 /* error closing file */
11739                 return 1;
11740         }
11741 
11742         return 0;
11743 }
11744 
11745 
11746 /* remove the temporarary toc files */
11747 
remove_tmp_xcdr_files()11748 void remove_tmp_xcdr_files() {
11749 gchar tmptoc[MAXLINE];
11750 
11751         /* delete tmp masterfiles first */
11752         generate_tmp_tocfile_name(tmptoc);
11753         remove_tmp_writetracks_tocfile(tmptoc);
11754         if (master_fname1) {
11755                 remove_tmp_writetracks_tocfile(master_fname1);
11756                 g_free(master_fname1);
11757                 master_fname1 = NULL;
11758         }
11759         if (master_fname2) {
11760                 remove_tmp_writetracks_tocfile(master_fname2);
11761                 g_free(master_fname2);
11762                 master_fname2 = NULL;
11763         }
11764 }
11765 
11766 
11767 /* used on OS X only - find out the pid of the autodiskmount daemon */
11768 /* return -1 when not found */
11769 
get_autodiskmount_pid()11770 gint get_autodiskmount_pid() {
11771 gchar line[MAXLINE];
11772 FILE *fpin;
11773 gchar *p;
11774 gint pid;
11775 
11776 	g_snprintf(line,MAXLINE,"/bin/ps -ax | /usr/bin/fgrep autodiskmount");
11777 
11778 	dodebug(1, "calling: %s\n", line);
11779         if ((fpin = popen(line,"r")) == NULL) {
11780                 g_error("popen error\n");
11781         }
11782 
11783 	pid = -1;
11784         for (;;) {
11785                 if (fgets(line,MAXLINE,fpin) == NULL)
11786                         break;
11787 		strip_string(line);
11788 
11789 		/* line found that not contains grep? should be the one */
11790 		if (!strstr(line, "grep")) {
11791 			p = strtok(line, " \t");
11792 			if (p && pid == -1) {
11793 				/* save first match */
11794 				pid = atoi(p);
11795 			}
11796 		}
11797         }
11798 
11799         if (pclose(fpin) == -1) {
11800                 g_error("pclose error\n");
11801         }
11802 
11803 	return pid;
11804 }
11805 
11806 
11807 /* run a single command with sudo and return the exitstatus. */
11808 
run_sudo_command(gchar * cmd)11809 gint run_sudo_command(gchar *cmd) {
11810 gchar line[MAXLINE], tmp[MAXLINE];
11811 FILE *fpin;
11812 gint stat,ret;
11813 
11814 	g_snprintf(line, MAXLINE, "%s -S %s", SUDO, cmd);
11815 
11816         if ((fpin = popen(line,"w")) == NULL) {
11817                 g_error("popen error\n");
11818         }
11819 
11820 	/* send password */
11821 	g_snprintf(tmp, MAXLINE, "%s\n", curset.sudo_passwd);
11822 	fputs(tmp, fpin);
11823 
11824 	/* command should be executed as root now */
11825 
11826 	ret = pclose(fpin);
11827 	stat = WEXITSTATUS(ret);
11828 
11829         dodebug(1, "Executed command \"%s\" with sudo. (exitstatus %d)\n", cmd, stat);
11830 
11831 	return stat;
11832 }
11833 
11834 
11835 /* check .inf file for a given audio track for invalid ISRC and MCN entries */
11836 /* return 0 when all ok (or file not found), 1 when invalid data found */
11837 
check_valid_isrc_mcn(gchar * tname)11838 gint check_valid_isrc_mcn(gchar *tname) {
11839 gchar tmp[MAXLINE];
11840 gchar tmp2[MAXLINE];
11841 gchar line[MAXLINE];
11842 gchar id[MAXLINE];
11843 gchar value[MAXLINE];
11844 gchar *p;
11845 FILE *fd;
11846 gint errfound;
11847 
11848 	errfound = 0;
11849 
11850 	/* generate filename of .inf file */
11851         strncpy(tmp,tname,MAXLINE - 3);
11852         p = rindex(tmp,'.');
11853         if (!p) return 0;
11854         *p = '\0';
11855         strcpy(tmp2,tmp);
11856         strcat(tmp2,".inf");
11857 
11858 	if ((fd = fopen(tmp2,"r")) == NULL) {
11859 		/* file not found or readable - thats ok */
11860 		return 0;
11861 	}
11862 
11863 	dodebug(11, "Checking %s for invalid ISRC or MCN\n", tmp2);
11864 
11865         for (;;) {
11866                 if (fgets(line,MAXLINE,fd) == NULL)
11867                         break;
11868 
11869                 /* skip empty or hashed lines */
11870                 strip_string(line);
11871                 if (*line == '#' || *line == '\0')
11872                         continue;
11873 
11874                 if (parse_config_line(line,id,value)) {
11875 			continue;
11876 		}
11877 
11878 		if (strcmp("MCN",id) == 0) {
11879 			errfound += verify_mcn(value);
11880 		}
11881 		if (strcmp("ISRC",id) == 0) {
11882 			errfound += verify_isrc(value);
11883 		}
11884 	}
11885 
11886 	fclose(fd);
11887 
11888 	if (errfound > 0) {
11889 		/* invalid data found */
11890 		return 1;
11891 	} else {
11892 		return 0;
11893 	}
11894 }
11895 
11896 
11897 /* comment the ISRC and MCN numbers in a given track inf file */
11898 /* return 0 if we were able to do so, 1 on error */
11899 
clear_isrc_mcn_from_inffile(gchar * tname)11900 gint clear_isrc_mcn_from_inffile(gchar *tname) {
11901 gchar tmp[MAXLINE];
11902 gchar tmp2[MAXLINE];
11903 gchar tmpname[MAXLINE];
11904 gchar line[MAXLINE];
11905 gchar *p;
11906 FILE *fd, *fd2;
11907 gint stat;
11908 time_t acttime;
11909 gchar timestr[MAXLINE];
11910 
11911 	/* get current time */
11912 	acttime = time((time_t *) 0);
11913 	strcpy(timestr,ctime(&acttime));
11914 	timestr[strlen(timestr)-1] = '\0';
11915 
11916 	/* generate filename of .inf file */
11917         strncpy(tmp,tname,MAXLINE - 3);
11918         p = rindex(tmp,'.');
11919         if (!p) return 0;
11920         *p = '\0';
11921         strcpy(tmp2,tmp);
11922         strcat(tmp2,".inf");
11923 	g_snprintf(tmpname,MAXLINE,"%s-%d", tmp2, (gint) getpid());
11924 
11925         /* try to open the inf file */
11926         if ((fd = fopen(tmp2,"r")) == NULL) {
11927 		/* no source file - thats ok */
11928 		return 0;
11929 	}
11930 
11931 	/* create temporary file */
11932         if ((fd2 = fopen(tmpname,"w")) == NULL) {
11933                 fclose(fd);
11934 		/* we couldnt create the working copy? report error */
11935                 return 1;
11936         }
11937 
11938         /* copy a lines and change the one with ISRC and MCN */
11939         for (;;) {
11940                 if (fgets(line,MAXLINE,fd) == NULL)
11941                         break;
11942 
11943 		/* write modifcation date of xcdroast in new file */
11944 		if (strncmp(line,"#created", 8) == 0) {
11945 			fputs(line, fd2);
11946 			g_snprintf(tmp,MAXLINE,"#modified by X-CD-Roast %s at %s\n", XCDROAST_VERSION, timestr);
11947 			fputs(tmp, fd2);
11948 			continue;
11949 		}
11950 
11951 		/* skip old modfied lines */
11952 		if (strncmp(line,"#modified by X-CD-Roast", 23) == 0) {
11953 			continue;
11954 		}
11955 
11956                 if (strncmp(line,"ISRC=", 5) == 0) {
11957                         g_snprintf(tmp,MAXLINE,"# %s", line);
11958                         fputs(tmp, fd2);
11959                         continue;
11960                 }
11961                 if (strncmp(line,"MCN=", 4) == 0) {
11962                         g_snprintf(tmp,MAXLINE,"# %s", line);
11963                         fputs(tmp, fd2);
11964                         continue;
11965                 }
11966 
11967 		fputs(line,fd2);
11968 	}
11969 
11970 	/* finished modified copy */
11971         fclose(fd2);
11972         fclose(fd);
11973 
11974 	dodebug(10, "cleared inf-file %s from invalid ISRC or MCN id\n", tmp2);
11975 
11976         /* now move the temporary file over the original inf file */
11977         stat = move_textfile(tmpname, tmp2);
11978 
11979 	if (stat == 1) {
11980 		/* remove temporary file if move failed */
11981 		unlink(tmpname);
11982 	}
11983 
11984 	return stat;
11985 }
11986 
11987