1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12 
13 /* @(#)auinfo.c	1.23 04/03/01 Copyright 1998-2004 J. Schilling */
14 /*
15  *	Copyright (c) 1998-2004 J. Schilling
16  */
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License version 2
20  * as published by the Free Software Foundation.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License along with
28  * this program; see the file COPYING.  If not, write to the Free Software
29  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31 
32 #include <mconfig.h>
33 #include <stdxlib.h>
34 #include <unixstd.h>
35 #include <statdefs.h>
36 #include <stdio.h>
37 #include <standard.h>
38 #include <strdefs.h>
39 #include <deflts.h>
40 #include <utypes.h>
41 #include <schily.h>
42 
43 #include "cdtext.h"
44 #include "wodim.h"
45 
46 extern	int	debug;
47 extern	int	xdebug;
48 
49 BOOL			auinfosize(char *name, track_t *trackp);
50 void			auinfo(char *name, int track, track_t *trackp);
51 textptr_t 	*gettextptr(int track, track_t *trackp);
52 static char *savestr(char *name);
53 static char *readtag(char *name);
54 static char *readtstr(char *name);
55 void			setmcn(char *mcn, track_t *trackp);
56 static void	isrc_illchar(char *isrc, int c);
57 void			setisrc(char *isrc, track_t *trackp);
58 void			setindex(char *tindex, track_t *trackp);
59 
60 #ifdef	XXX
61 int
main(int argc,char * argv[])62 main(int argc, char *argv[])
63 {
64 /*	auinfo("/etc/default/cdrecord");*/
65 /*	auinfo("/mnt2/CD3/audio_01.inf");*/
66 	auinfo("/mnt2/CD3/audio_01.wav");
67 }
68 #endif
69 
70 BOOL
auinfosize(char * name,track_t * trackp)71 auinfosize(char *name, track_t *trackp)
72 {
73 	const	char	*p;
74 	const	char	*tlp;
75 	struct stat	sb;
76 	long		secs;
77 	long		nsamples;
78 	Llong		tracksize;
79 
80 	if (!is_audio(trackp))
81 		return (FALSE);
82 
83 	if ((trackp->flags & TI_USEINFO) == 0)
84 		return (FALSE);
85 
86 	if ((p = strrchr(name, '.')) == NULL)
87 		return (FALSE);
88 	if (!streql(p, ".inf") && !streql(p, ".INF"))
89 		return (FALSE);
90 
91 	/*
92 	 * First check if a bad guy tries to call auinfosize()
93 	 * while STDIN_FILENO is a TTY.
94 	 */
95 	if (isatty(STDIN_FILENO)) {
96 		errmsgno(EX_BAD,
97 			"WARNING: Stdin is connected to a terminal.\n");
98 		return (FALSE);
99 	}
100 
101 	if (stat(name, &sb) < 0)	/* *.inf file not found		*/
102 		return (FALSE);
103 
104 	if (sb.st_size > 10000)		/* Too large for a *.inf file	*/
105 		return (FALSE);
106 
107 	if (cfg_open(name) < 0)	/* Cannot open *.inf file	*/
108 		return (FALSE);
109 
110 	tlp = p = readtag("Tracklength");
111 	if (p == NULL) {		/* Tracklength= Tag not found	*/
112 		errmsgno(EX_BAD,
113 			"WARNING: %s does not contain a 'Tracklength=' tag.\n",
114 			name);
115 		cfg_close();
116 		return (FALSE);
117 	}
118 
119 	p = astol(p, &secs);
120 	if (*p != '\0' && *p != ',') {
121 		errmsgno(EX_BAD,
122 			"WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n",
123 			name, tlp);
124 		cfg_close();
125 		return (FALSE);
126 	}
127 	if (*p == ',')
128 		p++;
129 	p = astol(p, &nsamples);
130 	if (*p != '\0') {
131 		errmsgno(EX_BAD,
132 			"WARNING: %s: 'Tracklength=' contains illegal parameter '%s'.\n",
133 			name, tlp);
134 		cfg_close();
135 		return (FALSE);
136 	}
137 	tracksize = (secs * 2352) + (nsamples * 4);
138 	if (xdebug > 0) {
139 		fprintf(stderr, "%s: Tracksize %lld bytes (%ld sectors, %ld samples)\n",
140 			name, tracksize, secs, nsamples);
141 	}
142 	trackp->itracksize = tracksize;
143 	cfg_close();
144 	return (TRUE);
145 }
146 
147 void
auinfo(char * name,int track,track_t * trackp)148 auinfo(char *name, int track, track_t *trackp)
149 {
150 	char	infname[1024];
151 	char	*p;
152 	track_t	*tp = &trackp[track];
153 	textptr_t *txp;
154 	long	l;
155 	long	tno = -1;
156 	BOOL	isdao = !is_tao(&trackp[0]);
157 
158 	strncpy(infname, name, sizeof (infname)-1);
159 	infname[sizeof (infname)-1] = '\0';
160 	p = strrchr(infname, '.');
161 	if (p != 0 && &p[4] < &name[sizeof (infname)]) {
162 		strcpy(&p[1], "inf");
163 	}
164 
165 	if (cfg_open(infname) == 0) {
166 
167 		p = readtstr("CDINDEX_DISCID");
168 		p = readtag("CDDB_DISKID");
169 
170 		p = readtag("MCN");
171 		if (p && *p) {
172 			setmcn(p, &trackp[0]);
173 			txp = gettextptr(0, trackp); /* MCN is isrc for trk 0*/
174 			txp->tc_isrc = savestr(p);
175 		}
176 
177 		p = readtag("ISRC");
178 		if (p && *p) {
179 			setisrc(p, &trackp[track]);
180 			txp = gettextptr(track, trackp);
181 			txp->tc_isrc = savestr(p);
182 		}
183 
184 		p = readtstr("Albumperformer");
185 		if (p && *p) {
186 			txp = gettextptr(0, trackp); /* Album perf. in trk 0*/
187 			txp->tc_performer = savestr(p);
188 		}
189 		p = readtstr("Performer");
190 		if (p && *p) {
191 			txp = gettextptr(track, trackp);
192 			txp->tc_performer = savestr(p);
193 		}
194 		p = readtstr("Albumtitle");
195 		if (p && *p) {
196 			txp = gettextptr(0, trackp); /* Album title in trk 0*/
197 			txp->tc_title = savestr(p);
198 		}
199 		p = readtstr("Tracktitle");
200 		if (p && *p) {
201 			txp = gettextptr(track, trackp);
202 			txp->tc_title = savestr(p);
203 		}
204 		p = readtstr("Songwriter");
205 		if (p && *p) {
206 			txp = gettextptr(track, trackp);
207 			txp->tc_songwriter = savestr(p);
208 		}
209 		p = readtstr("Composer");
210 		if (p && *p) {
211 			txp = gettextptr(track, trackp);
212 			txp->tc_composer = savestr(p);
213 		}
214 		p = readtstr("Arranger");
215 		if (p && *p) {
216 			txp = gettextptr(track, trackp);
217 			txp->tc_arranger = savestr(p);
218 		}
219 		p = readtstr("Message");
220 		if (p && *p) {
221 			txp = gettextptr(track, trackp);
222 			txp->tc_message = savestr(p);
223 		}
224 		p = readtstr("Diskid");
225 		if (p && *p) {
226 			txp = gettextptr(0, trackp); /* Disk id is in trk 0*/
227 			txp->tc_title = savestr(p);
228 		}
229 		p = readtstr("Closed_info");
230 		if (p && *p) {
231 			txp = gettextptr(track, trackp);
232 			txp->tc_closed_info = savestr(p);
233 		}
234 
235 		p = readtag("Tracknumber");
236 		if (p && isdao)
237 			astol(p, &tno);
238 
239 		p = readtag("Trackstart");
240 		if (p && isdao) {
241 			l = -1L;
242 			astol(p, &l);
243 			if (track == 1 && tno == 1 && l > 0) {
244 				trackp[1].pregapsize = 150 + l;
245 				printf("Track1 Start: '%s' (%ld)\n", p, l);
246 			}
247 		}
248 
249 		p = readtag("Tracklength");
250 
251 		p = readtag("Pre-emphasis");
252 		if (p && *p) {
253 			if (strncmp(p, "yes", 3) == 0) {
254 				tp->flags |= TI_PREEMP;
255 				if ((tp->tracktype & TOC_MASK) == TOC_DA)
256 					tp->sectype = SECT_AUDIO_PRE;
257 
258 			} else if (strncmp(p, "no", 2) == 0) {
259 				tp->flags &= ~TI_PREEMP;
260 				if ((tp->tracktype & TOC_MASK) == TOC_DA)
261 					tp->sectype = SECT_AUDIO_NOPRE;
262 			}
263 		}
264 
265 		p = readtag("Channels");
266 		p = readtag("Copy_permitted");
267 		if (p && *p) {
268 			/*
269 			 * -useinfo always wins
270 			 */
271 			tp->flags &= ~(TI_COPY|TI_SCMS);
272 
273 			if (strncmp(p, "yes", 3) == 0)
274 				tp->flags |= TI_COPY;
275 			else if (strncmp(p, "no", 2) == 0)
276 				tp->flags |= TI_SCMS;
277 			else if (strncmp(p, "once", 2) == 0)
278 				tp->flags &= ~(TI_COPY|TI_SCMS);
279 		}
280 		p = readtag("Endianess");
281 		p = readtag("Index");
282 		if (p && *p && isdao)
283 			setindex(p, &trackp[track]);
284 
285 		p = readtag("Index0");
286 		if (p && isdao) {
287 			Llong ts;
288 			Llong ps;
289 
290 			l = -2L;
291 			astol(p, &l);
292 			if (l == -1) {
293 				trackp[track+1].pregapsize = 0;
294 			} else if (l > 0) {
295 				ts = tp->itracksize / tp->isecsize;
296 				ps = ts - l;
297 				if (ps > 0)
298 					trackp[track+1].pregapsize = ps;
299 			}
300 		}
301 	}
302 
303 }
304 
305 textptr_t *
gettextptr(int track,track_t * trackp)306 gettextptr(int track, track_t *trackp)
307 {
308 	register textptr_t *txp;
309 
310 	txp = (textptr_t *)trackp[track].text;
311 	if (txp == NULL) {
312 		txp = malloc(sizeof (textptr_t));
313 		if (txp == NULL)
314 			comerr("Cannot malloc CD-Text structure.\n");
315 		fillbytes(txp, sizeof (textptr_t), '\0');
316 		trackp[track].text = txp;
317 	}
318 	return (txp);
319 }
320 
321 static char *
savestr(char * str)322 savestr(char *str)
323 {
324 	char	*ret;
325 
326 	ret = malloc(strlen(str)+1);
327 	if (ret)
328 		strcpy(ret, str);
329 	else
330 		comerr("Cannot malloc auinfo string.\n");
331 	return (ret);
332 }
333 
334 static char *
readtag(char * name)335 readtag(char *name)
336 {
337 	register char	*p;
338 
339   p = cfg_get(name);
340   if (debug)
341      printf("%s	'%s'\n", name, p);
342   return (p);
343 }
344 
345 static char *
readtstr(char * name)346 readtstr(char *name)
347 {
348 	register char	*p;
349 	register char	*p2;
350 
351 	p = readtag(name);
352 	if (p && *p == '\'') {
353 		p2 = ++p;
354 		while (*p2 != '\0')
355 			p2++;
356 		while (p2 > p && *p2 != '\'')
357 			p2--;
358 		*p2 = '\0';
359 		if (debug)
360 			printf("%s	'%s'\n", name, p);
361 	}
362 	return (p);
363 }
364 
365 /*
366  * Media catalog number is a 13 digit number.
367  */
368 void
setmcn(char * mcn,track_t * trackp)369 setmcn(char *mcn, track_t *trackp)
370 {
371 	register char	*p;
372 
373 	if (strlen(mcn) != 13)
374 		comerrno(EX_BAD, "MCN '%s' has illegal length.\n", mcn);
375 
376 	for (p = mcn; *p; p++) {
377 		if (*p < '0' || *p > '9')
378 			comerrno(EX_BAD, "MCN '%s' contains illegal character '%c'.\n", mcn, *p);
379 	}
380 	p = malloc(14);
381 	strcpy(p, mcn);
382 	trackp->isrc = p;
383 
384 	if (debug)
385 		printf("Track %d MCN: '%s'\n", (int)trackp->trackno, trackp->isrc);
386 }
387 
388 static	char	upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
389 
390 static void
isrc_illchar(char * isrc,int c)391 isrc_illchar(char *isrc, int c)
392 {
393 	errmsgno(EX_BAD, "ISRC '%s' contains illegal character '%c'.\n", isrc, c);
394 }
395 
396 /*
397  * ISRC is 12 Byte:
398  *
399  *	Country code   'C' (alpha)	  2 Bytes
400  *	Owner code     'O' (alphanumeric) 3 Bytes
401  *	Year of record 'Y' (numeric)	  2 Bytes
402  *	Serial number  'S' (numeric)	  5 Bytes
403  *
404  *	CC-OOO-YY-SSSSS
405  */
406 void
setisrc(char * isrc,track_t * trackp)407 setisrc(char *isrc, track_t *trackp)
408 {
409 	char	ibuf[13];
410 	char	*ip;
411 	char	*p;
412 	int	i;
413 	int	len;
414 
415 	if ((len = strlen(isrc)) != 12) {
416 		for (p = isrc, i = 0; *p; p++) {
417 			if (*p == '-')
418 				i++;
419 		}
420 		if (((len - i) != 12) || i > 3)
421 			comerrno(EX_BAD, "ISRC '%s' has illegal length.\n", isrc);
422 	}
423 
424 	/*
425 	 * The country code.
426 	 */
427 	for (p = isrc, ip = ibuf, i = 0; i < 2; p++, i++) {
428 		*ip++ = *p;
429 		if (!strchr(upper, *p)) {
430 /*			goto illchar;*/
431 			/*
432 			 * Flag numbers but accept them.
433 			 */
434 			isrc_illchar(isrc, *p);
435 			if (*p >= '0' && *p <= '9')
436 				continue;
437 			exit(EX_BAD);
438 		}
439 	}
440 	if (*p == '-')
441 		p++;
442 
443 	/*
444 	 * The owner code.
445 	 */
446 	for (i = 0; i < 3; p++, i++) {
447 		*ip++ = *p;
448 		if (strchr(upper, *p))
449 			continue;
450 		if (*p >= '0' && *p <= '9')
451 			continue;
452 		goto illchar;
453 	}
454 	if (*p == '-')
455 		p++;
456 
457 	/*
458 	 * The Year and the recording number (2 + 5 numbers).
459 	 */
460 	for (i = 0; i < 7; p++, i++) {
461 		*ip++ = *p;
462 		if (*p >= '0' && *p <= '9')
463 			continue;
464 		if (*p == '-' && i == 2) {
465 			ip--;
466 			i--;
467 			continue;
468 		}
469 		goto illchar;
470 	}
471 	*ip = '\0';
472 	p = malloc(13);
473 	strcpy(p, ibuf);
474 	trackp->isrc = p;
475 
476 	if (debug)
477 		printf("Track %d ISRC: '%s'\n", (int)trackp->trackno, trackp->isrc);
478 	return;
479 illchar:
480 	isrc_illchar(isrc, *p);
481 	exit(EX_BAD);
482 }
483 
484 void
setindex(char * tindex,track_t * trackp)485 setindex(char *tindex, track_t *trackp)
486 {
487 	char	*p;
488 	int	i;
489 	int	nindex;
490 	long	idx;
491 	long	*idxlist;
492 
493 	idxlist = malloc(100*sizeof (long));
494 	p = tindex;
495 	idxlist[0] = 0;
496 	i = 0;
497 	while (*p) {
498 		p = astol(p, &idx);
499 		if (*p != '\0' && *p != ' ' && *p != '\t' && *p != ',')
500 			goto illchar;
501 		i++;
502 		if (i > 99)
503 			comerrno(EX_BAD, "Too many indices for track %d\n", (int)trackp->trackno);
504 		idxlist[i] = idx;
505 		if (*p == ',')
506 			p++;
507 		while (*p == ' ' || *p == '\t')
508 			p++;
509 	}
510 	nindex = i;
511 
512 	if (debug)
513 		printf("Track %d %d Index: '%s'\n", (int)trackp->trackno, i, tindex);
514 
515 	if (debug) {
516 		for (i = 0; i <= nindex; i++)
517 			printf("%d: %ld\n", i, idxlist[i]);
518 	}
519 
520 	trackp->nindex = nindex;
521 	trackp->tindex = idxlist;
522 	return;
523 illchar:
524 	comerrno(EX_BAD, "Index '%s' contains illegal character '%c'.\n", tindex, *p);
525 }
526