Annotation of src/usr.bin/cdio/cdio.c, Revision 1.27
1.25 espie 1: /* $OpenBSD: cdio.c,v 1.24 2002/04/18 20:18:31 espie Exp $ */
1.1 downsj 2: /*
3: * Compact Disc Control Utility by Serge V. Vakulenko <vak@cronyx.ru>.
4: * Based on the non-X based CD player by Jean-Marc Zucconi and
5: * Andrey A. Chernov.
6: *
7: * Fixed and further modified on 5-Sep-1995 by Jukka Ukkonen <jau@funet.fi>.
8: *
9: * 11-Sep-1995: Jukka A. Ukkonen <jau@funet.fi>
10: * A couple of further fixes to my own earlier "fixes".
11: *
12: * 18-Sep-1995: Jukka A. Ukkonen <jau@funet.fi>
13: * Added an ability to specify addresses relative to the
14: * beginning of a track. This is in fact a variation of
15: * doing the simple play_msf() call.
16: *
17: * 11-Oct-1995: Serge V.Vakulenko <vak@cronyx.ru>
18: * New eject algorithm.
19: * Some code style reformatting.
20: *
21: * $FreeBSD: cdcontrol.c,v 1.13 1996/06/25 21:01:27 ache Exp $
22: */
23:
1.27 ! fgsch 24: #include <sys/param.h>
! 25: #include <sys/file.h>
! 26: #include <sys/cdio.h>
! 27: #include <sys/ioctl.h>
! 28:
1.1 downsj 29: #include <ctype.h>
1.17 espie 30: #include <err.h>
31: #include <errno.h>
1.1 downsj 32: #include <stdio.h>
33: #include <stdlib.h>
34: #include <string.h>
35: #include <unistd.h>
1.27 ! fgsch 36: #include <histedit.h>
1.1 downsj 37: #include <util.h>
1.17 espie 38: #include <vis.h>
1.27 ! fgsch 39:
1.24 espie 40: #include "extern.h"
1.1 downsj 41:
42: #define ASTS_INVALID 0x00 /* Audio status byte not valid */
43: #define ASTS_PLAYING 0x11 /* Audio play operation in progress */
44: #define ASTS_PAUSED 0x12 /* Audio play operation paused */
45: #define ASTS_COMPLETED 0x13 /* Audio play operation successfully completed */
46: #define ASTS_ERROR 0x14 /* Audio play operation stopped due to error */
47: #define ASTS_VOID 0x15 /* No current audio status to return */
48:
49: #ifndef DEFAULT_CD_DRIVE
1.3 deraadt 50: # define DEFAULT_CD_DRIVE "cd0"
1.1 downsj 51: #endif
52:
53: #define CMD_DEBUG 1
1.9 millert 54: #define CMD_DEVICE 2
55: #define CMD_EJECT 3
56: #define CMD_HELP 4
57: #define CMD_INFO 5
58: #define CMD_PAUSE 6
59: #define CMD_PLAY 7
60: #define CMD_QUIT 8
61: #define CMD_RESUME 9
62: #define CMD_STOP 10
63: #define CMD_VOLUME 11
64: #define CMD_CLOSE 12
65: #define CMD_RESET 13
66: #define CMD_SET 14
67: #define CMD_STATUS 15
68: #define CMD_NEXT 16
69: #define CMD_PREV 17
70: #define CMD_REPLAY 18
1.24 espie 71: #define CMD_CDDB 19
1.25 espie 72: #define CMD_CDID 20
1.1 downsj 73:
74: struct cmdtab {
75: int command;
76: char *name;
1.24 espie 77: unsigned int min;
1.1 downsj 78: char *args;
79: } cmdtab[] = {
80: { CMD_CLOSE, "close", 1, "" },
81: { CMD_DEBUG, "debug", 1, "on | off" },
1.9 millert 82: { CMD_DEVICE, "device", 1, "devname" },
1.1 downsj 83: { CMD_EJECT, "eject", 1, "" },
84: { CMD_HELP, "?", 1, 0 },
85: { CMD_HELP, "help", 1, "" },
86: { CMD_INFO, "info", 1, "" },
1.5 angelos 87: { CMD_NEXT, "next", 1, "" },
1.1 downsj 88: { CMD_PAUSE, "pause", 2, "" },
89: { CMD_PLAY, "play", 1, "min1:sec1[.fram1] [min2:sec2[.fram2]]" },
90: { CMD_PLAY, "play", 1, "track1[.index1] [track2[.index2]]" },
91: { CMD_PLAY, "play", 1, "tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]]" },
92: { CMD_PLAY, "play", 1, "[#block [len]]" },
1.5 angelos 93: { CMD_PREV, "previous", 2, "" },
1.1 downsj 94: { CMD_QUIT, "quit", 1, "" },
95: { CMD_RESET, "reset", 4, "" },
96: { CMD_RESUME, "resume", 1, "" },
1.6 angelos 97: { CMD_REPLAY, "replay", 3, "" },
1.1 downsj 98: { CMD_SET, "set", 2, "msf | lba" },
99: { CMD_STATUS, "status", 1, "" },
100: { CMD_STOP, "stop", 3, "" },
101: { CMD_VOLUME, "volume", 1, "<l> <r> | left | right | mute | mono | stereo" },
1.25 espie 102: { CMD_CDDB, "cddbinfo", 2, "[n]" },
1.26 fgsch 103: { CMD_CDID, "cdid", 3, "" },
1.24 espie 104: { 0, 0, 0, 0}
1.1 downsj 105: };
106:
1.11 csapuntz 107: struct cd_toc_entry *toc_buffer;
1.1 downsj 108:
109: char *cdname;
110: int fd = -1;
111: int verbose = 1;
112: int msf = 1;
1.24 espie 113: const char *cddb_host;
114: char **track_names;
1.1 downsj 115:
1.27 ! fgsch 116: EditLine *el = NULL; /* line-editing structure */
! 117: History *hist = NULL; /* line-editing history */
! 118: void switch_el(void);
! 119:
1.1 downsj 120: extern char *__progname;
121:
1.19 millert 122: int setvol(int, int);
123: int read_toc_entrys(int);
124: int play_msf(int, int, int, int, int, int);
125: int play_track(int, int, int, int);
126: int get_vol(int *, int *);
127: int status(int *, int *, int *, int *);
128: int open_cd(char *);
129: int play(char *arg);
130: int info(char *arg);
1.24 espie 131: int cddbinfo(char *arg);
1.19 millert 132: int pstatus(char *arg);
133: int play_next(char *arg);
134: int play_prev(char *arg);
135: int play_same(char *arg);
136: char *input(int *);
1.27 ! fgsch 137: char *prompt(void);
1.24 espie 138: void prtrack(struct cd_toc_entry *e, int lastflag, char *name);
1.20 millert 139: void lba2msf(unsigned long lba, u_char *m, u_char *s, u_char *f);
1.19 millert 140: unsigned int msf2lba(u_char m, u_char s, u_char f);
141: int play_blocks(int blk, int len);
142: int run(int cmd, char *arg);
143: char *parse(char *buf, int *cmd);
1.23 espie 144: void help(void);
145: void usage(void);
146: char *strstatus(int);
1.25 espie 147: int cdid(void);
1.1 downsj 148:
1.18 deraadt 149: void
150: help()
1.1 downsj 151: {
152: struct cmdtab *c;
153: char *s, n;
154: int i;
155:
156: for (c=cmdtab; c->name; ++c) {
157: if (! c->args)
158: continue;
159: printf("\t");
160: for (i = c->min, s = c->name; *s; s++, i--) {
161: if (i > 0)
162: n = toupper(*s);
163: else
164: n = *s;
165: putchar(n);
166: }
167: if (*c->args)
1.18 deraadt 168: printf(" %s", c->args);
169: printf("\n");
1.1 downsj 170: }
1.18 deraadt 171: printf("\n\tThe word \"play\" is not required for the play commands.\n");
172: printf("\tThe plain target address is taken as a synonym for play.\n");
1.1 downsj 173: }
174:
1.18 deraadt 175: void
176: usage()
1.1 downsj 177: {
1.18 deraadt 178: fprintf(stderr, "usage: %s [-sv] [-f device] [command args ...]\n",
179: __progname);
180: exit(1);
1.1 downsj 181: }
182:
1.18 deraadt 183: int
1.24 espie 184: main(int argc, char **argv)
1.1 downsj 185: {
186: int cmd;
187: char *arg;
188:
1.18 deraadt 189: cdname = getenv("DISC");
1.1 downsj 190: if (! cdname)
1.18 deraadt 191: cdname = getenv("CDROM");
1.1 downsj 192:
1.24 espie 193: cddb_host = getenv("CDDB");
194: if (!cddb_host)
195: cddb_host = "freedb.freedb.org";
196:
1.1 downsj 197: for (;;) {
1.24 espie 198: switch (getopt(argc, argv, "svd:f:")) {
1.22 espie 199: case -1:
1.1 downsj 200: break;
201: case 's':
202: verbose = 0;
203: continue;
204: case 'v':
205: verbose = 2;
206: continue;
207: case 'f':
208: cdname = optarg;
209: continue;
1.24 espie 210: case 'd':
211: cddb_host = optarg;
212: continue;
1.1 downsj 213: default:
1.18 deraadt 214: usage();
1.1 downsj 215: }
216: break;
217: }
218: argc -= optind;
219: argv += optind;
220:
1.18 deraadt 221: if (argc > 0 && ! strcasecmp(*argv, "help"))
222: usage();
1.1 downsj 223:
224: if (! cdname) {
225: cdname = DEFAULT_CD_DRIVE;
1.18 deraadt 226: fprintf(stderr,
227: "No CD device name specified. Defaulting to %s.\n", cdname);
1.1 downsj 228: }
229:
230: if (argc > 0) {
231: char buf[80], *p;
232: int len;
233:
234: for (p=buf; argc-->0; ++argv) {
1.18 deraadt 235: len = strlen(*argv);
1.1 downsj 236:
237: if (p + len >= buf + sizeof (buf) - 1)
1.18 deraadt 238: usage();
1.1 downsj 239:
240: if (p > buf)
241: *p++ = ' ';
242:
1.18 deraadt 243: strcpy(p, *argv); /* ok */
1.1 downsj 244: p += len;
245: }
246: *p = 0;
1.18 deraadt 247: arg = parse(buf, &cmd);
248: return (run(cmd, arg));
1.1 downsj 249: }
250:
251: if (verbose == 1)
1.18 deraadt 252: verbose = isatty(0);
1.1 downsj 253:
254: if (verbose) {
1.18 deraadt 255: printf("Compact Disc Control utility, version %s\n", VERSION);
256: printf("Type `?' for command list\n\n");
1.1 downsj 257: }
258:
1.27 ! fgsch 259: switch_el();
! 260:
1.1 downsj 261: for (;;) {
1.18 deraadt 262: arg = input(&cmd);
263: if (run(cmd, arg) < 0) {
1.1 downsj 264: if (verbose)
1.18 deraadt 265: warn(NULL);
266: close(fd);
1.1 downsj 267: fd = -1;
268: }
1.18 deraadt 269: fflush(stdout);
1.1 downsj 270: }
271: }
272:
1.18 deraadt 273: int
1.24 espie 274: run(int cmd, char *arg)
1.1 downsj 275: {
276: int l, r, rc;
1.9 millert 277: static char newcdname[MAXPATHLEN];
1.1 downsj 278:
279: switch (cmd) {
280:
281: case CMD_QUIT:
1.27 ! fgsch 282: switch_el();
1.18 deraadt 283: exit(0);
1.1 downsj 284:
285: case CMD_INFO:
1.18 deraadt 286: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 287: return (0);
288:
1.18 deraadt 289: return info(arg);
1.1 downsj 290:
1.24 espie 291: case CMD_CDDB:
292: if (fd < 0 && ! open_cd(cdname))
293: return (0);
294:
295: return cddbinfo(arg);
296:
1.25 espie 297: case CMD_CDID:
298: if (fd < 0 && ! open_cd(cdname))
299: return (0);
300: return cdid();
301:
1.1 downsj 302: case CMD_STATUS:
1.18 deraadt 303: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 304: return (0);
305:
1.18 deraadt 306: return pstatus(arg);
1.1 downsj 307:
308: case CMD_PAUSE:
1.18 deraadt 309: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 310: return (0);
311:
1.18 deraadt 312: return ioctl(fd, CDIOCPAUSE);
1.1 downsj 313:
314: case CMD_RESUME:
1.18 deraadt 315: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 316: return (0);
317:
1.18 deraadt 318: return ioctl(fd, CDIOCRESUME);
1.1 downsj 319:
320: case CMD_STOP:
1.18 deraadt 321: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 322: return (0);
323:
1.18 deraadt 324: rc = ioctl(fd, CDIOCSTOP);
1.1 downsj 325:
1.18 deraadt 326: (void) ioctl(fd, CDIOCALLOW);
1.1 downsj 327:
328: return (rc);
329:
330: case CMD_RESET:
1.18 deraadt 331: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 332: return (0);
333:
1.18 deraadt 334: rc = ioctl(fd, CDIOCRESET);
1.1 downsj 335: if (rc < 0)
336: return rc;
337: close(fd);
338: fd = -1;
339: return (0);
340:
341: case CMD_DEBUG:
1.18 deraadt 342: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 343: return (0);
344:
1.18 deraadt 345: if (! strcasecmp(arg, "on"))
346: return ioctl(fd, CDIOCSETDEBUG);
1.1 downsj 347:
1.18 deraadt 348: if (! strcasecmp(arg, "off"))
349: return ioctl(fd, CDIOCCLRDEBUG);
1.1 downsj 350:
1.18 deraadt 351: printf("%s: Invalid command arguments\n", __progname);
1.1 downsj 352:
353: return (0);
354:
1.9 millert 355: case CMD_DEVICE:
356: /* close old device */
357: if (fd > -1) {
1.18 deraadt 358: (void) ioctl(fd, CDIOCALLOW);
1.9 millert 359: close(fd);
360: fd = -1;
361: }
362:
363: /* open new device */
1.18 deraadt 364: if (!open_cd(arg))
1.9 millert 365: return (0);
1.16 lebel 366: (void) strlcpy(newcdname, arg, sizeof(newcdname));
1.9 millert 367: cdname = newcdname;
368: return (1);
369:
1.1 downsj 370: case CMD_EJECT:
1.18 deraadt 371: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 372: return (0);
373:
1.18 deraadt 374: (void) ioctl(fd, CDIOCALLOW);
375: rc = ioctl(fd, CDIOCEJECT);
1.1 downsj 376: if (rc < 0)
377: return (rc);
378: #if defined(__OpenBSD__)
379: close(fd);
380: fd = -1;
381: #endif
1.24 espie 382: if (track_names)
383: free_names(track_names);
384: track_names = NULL;
1.1 downsj 385: return (0);
386:
387: case CMD_CLOSE:
388: #if defined(CDIOCCLOSE)
1.18 deraadt 389: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 390: return (0);
391:
1.18 deraadt 392: (void) ioctl(fd, CDIOCALLOW);
393: rc = ioctl(fd, CDIOCCLOSE);
1.1 downsj 394: if (rc < 0)
395: return (rc);
396: close(fd);
397: fd = -1;
398: return (0);
399: #else
1.18 deraadt 400: printf("%s: Command not yet supported\n", __progname);
1.1 downsj 401: return (0);
402: #endif
403:
404: case CMD_PLAY:
1.18 deraadt 405: if (fd < 0 && ! open_cd(cdname))
1.1 downsj 406: return (0);
407:
1.18 deraadt 408: while (isspace(*arg))
1.1 downsj 409: arg++;
410:
1.18 deraadt 411: return play(arg);
1.1 downsj 412:
413: case CMD_SET:
1.18 deraadt 414: if (!strcasecmp(arg, "msf"))
1.1 downsj 415: msf = 1;
1.18 deraadt 416: else if (!strcasecmp(arg, "lba"))
1.1 downsj 417: msf = 0;
418: else
1.18 deraadt 419: printf("%s: Invalid command arguments\n", __progname);
1.1 downsj 420: return (0);
421:
422: case CMD_VOLUME:
1.18 deraadt 423: if (fd < 0 && !open_cd(cdname))
1.1 downsj 424: return (0);
425:
1.18 deraadt 426: if (!strncasecmp(arg, "left", strlen(arg)))
427: return ioctl(fd, CDIOCSETLEFT);
1.1 downsj 428:
1.18 deraadt 429: if (!strncasecmp(arg, "right", strlen(arg)))
430: return ioctl(fd, CDIOCSETRIGHT);
1.1 downsj 431:
1.18 deraadt 432: if (!strncasecmp(arg, "mono", strlen(arg)))
433: return ioctl(fd, CDIOCSETMONO);
1.1 downsj 434:
1.18 deraadt 435: if (!strncasecmp(arg, "stereo", strlen(arg)))
436: return ioctl(fd, CDIOCSETSTEREO);
1.1 downsj 437:
1.18 deraadt 438: if (!strncasecmp(arg, "mute", strlen(arg)))
439: return ioctl(fd, CDIOCSETMUTE);
1.1 downsj 440:
1.18 deraadt 441: if (2 != sscanf(arg, "%d %d", &l, &r)) {
442: printf("%s: Invalid command arguments\n", __progname);
1.1 downsj 443: return (0);
444: }
445:
1.18 deraadt 446: return setvol(l, r);
1.1 downsj 447:
1.18 deraadt 448: case CMD_NEXT:
449: if (fd < 0 && ! open_cd(cdname))
450: return (0);
1.5 angelos 451:
1.18 deraadt 452: return play_next(arg);
1.5 angelos 453:
1.18 deraadt 454: case CMD_PREV:
455: if (fd < 0 && ! open_cd(cdname))
456: return (0);
1.5 angelos 457:
1.18 deraadt 458: return play_prev(arg);
1.5 angelos 459:
1.6 angelos 460: case CMD_REPLAY:
1.18 deraadt 461: if (fd < 0 && ! open_cd(cdname))
1.6 angelos 462: return 0;
463:
1.18 deraadt 464: return play_same(arg);
1.1 downsj 465: default:
466: case CMD_HELP:
1.18 deraadt 467: help();
1.1 downsj 468: return (0);
469:
470: }
471: }
472:
1.18 deraadt 473: int
1.24 espie 474: play(char *arg)
1.1 downsj 475: {
476: struct ioc_toc_header h;
477: int rc, n, start, end = 0, istart = 1, iend = 1;
478:
1.18 deraadt 479: rc = ioctl(fd, CDIOREADTOCHEADER, &h);
1.1 downsj 480:
481: if (rc < 0)
482: return (rc);
483:
484: n = h.ending_track - h.starting_track + 1;
1.18 deraadt 485: rc = read_toc_entrys((n + 1) * sizeof (struct cd_toc_entry));
1.1 downsj 486:
487: if (rc < 0)
488: return (rc);
489:
490: if (! arg || ! *arg) {
491: /* Play the whole disc */
1.18 deraadt 492:
1.10 csapuntz 493: return (play_track(h.starting_track, 1,
1.18 deraadt 494: h.ending_track, 1));
1.1 downsj 495: }
496:
1.18 deraadt 497: if (strchr(arg, '#')) {
1.1 downsj 498: /* Play block #blk [ len ] */
499: int blk, len = 0;
500:
1.18 deraadt 501: if (2 != sscanf(arg, "#%d%d", &blk, &len) &&
502: 1 != sscanf(arg, "#%d", &blk))
1.1 downsj 503: goto Clean_up;
504:
505: if (len == 0) {
506: if (msf)
1.18 deraadt 507: len = msf2lba(toc_buffer[n].addr.msf.minute,
508: toc_buffer[n].addr.msf.second,
509: toc_buffer[n].addr.msf.frame) - blk;
1.1 downsj 510: else
511: len = ntohl(toc_buffer[n].addr.lba) - blk;
512: }
1.18 deraadt 513: return play_blocks(blk, len);
1.1 downsj 514: }
515:
1.18 deraadt 516: if (strchr(arg, ':')) {
1.1 downsj 517: /*
518: * Play MSF m1:s1 [ .f1 ] [ m2:s2 [ .f2 ] ]
519: *
520: * Will now also undestand timed addresses relative
521: * to the beginning of a track in the form...
522: *
523: * tr1 m1:s1[.f1] [[tr2] [m2:s2[.f2]]]
524: */
1.24 espie 525: int tr1, tr2;
526: unsigned int m1, m2, s1, s2, f1, f2;
1.1 downsj 527: unsigned char tm, ts, tf;
528:
529: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 530: if (8 == sscanf(arg, "%d %d:%d.%d %d %d:%d.%d",
1.1 downsj 531: &tr1, &m1, &s1, &f1, &tr2, &m2, &s2, &f2))
532: goto Play_Relative_Addresses;
533:
534: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 535: if (7 == sscanf(arg, "%d %d:%d %d %d:%d.%d",
1.1 downsj 536: &tr1, &m1, &s1, &tr2, &m2, &s2, &f2))
537: goto Play_Relative_Addresses;
538:
539: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 540: if (7 == sscanf(arg, "%d %d:%d.%d %d %d:%d",
1.1 downsj 541: &tr1, &m1, &s1, &f1, &tr2, &m2, &s2))
542: goto Play_Relative_Addresses;
543:
544: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 545: if (7 == sscanf(arg, "%d %d:%d.%d %d:%d.%d",
1.1 downsj 546: &tr1, &m1, &s1, &f1, &m2, &s2, &f2))
547: goto Play_Relative_Addresses;
548:
549: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 550: if (6 == sscanf(arg, "%d %d:%d.%d %d:%d",
1.1 downsj 551: &tr1, &m1, &s1, &f1, &m2, &s2))
552: goto Play_Relative_Addresses;
553:
554: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 555: if (6 == sscanf(arg, "%d %d:%d %d:%d.%d",
1.1 downsj 556: &tr1, &m1, &s1, &m2, &s2, &f2))
557: goto Play_Relative_Addresses;
558:
559: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 560: if (6 == sscanf(arg, "%d %d:%d.%d %d %d",
1.1 downsj 561: &tr1, &m1, &s1, &f1, &tr2, &m2))
562: goto Play_Relative_Addresses;
563:
564: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 565: if (5 == sscanf(arg, "%d %d:%d %d:%d", &tr1, &m1, &s1, &m2, &s2))
1.1 downsj 566: goto Play_Relative_Addresses;
567:
568: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 569: if (5 == sscanf(arg, "%d %d:%d %d %d",
1.1 downsj 570: &tr1, &m1, &s1, &tr2, &m2))
571: goto Play_Relative_Addresses;
572:
573: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 574: if (5 == sscanf(arg, "%d %d:%d.%d %d",
1.1 downsj 575: &tr1, &m1, &s1, &f1, &tr2))
576: goto Play_Relative_Addresses;
577:
578: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 579: if (4 == sscanf(arg, "%d %d:%d %d", &tr1, &m1, &s1, &tr2))
1.1 downsj 580: goto Play_Relative_Addresses;
581:
582: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 583: if (4 == sscanf(arg, "%d %d:%d.%d", &tr1, &m1, &s1, &f1))
1.1 downsj 584: goto Play_Relative_Addresses;
585:
586: tr2 = m2 = s2 = f2 = f1 = 0;
1.18 deraadt 587: if (3 == sscanf(arg, "%d %d:%d", &tr1, &m1, &s1))
1.1 downsj 588: goto Play_Relative_Addresses;
589:
590: tr2 = m2 = s2 = f2 = f1 = 0;
591: goto Try_Absolute_Timed_Addresses;
592:
593: Play_Relative_Addresses:
1.24 espie 594: if (tr1 <= 0)
1.1 downsj 595: tr1 = 1;
596: else if (tr1 > n)
597: tr1 = n;
598:
599: if (msf) {
600: tm = toc_buffer[tr1].addr.msf.minute;
601: ts = toc_buffer[tr1].addr.msf.second;
602: tf = toc_buffer[tr1].addr.msf.frame;
603: } else
604: lba2msf(ntohl(toc_buffer[tr1].addr.lba),
605: &tm, &ts, &tf);
606: if ((m1 > tm)
607: || ((m1 == tm)
608: && ((s1 > ts)
609: || ((s1 == ts)
610: && (f1 > tf))))) {
1.18 deraadt 611: printf("Track %d is not that long.\n", tr1);
1.1 downsj 612: return (0);
613: }
614:
615: tr1--;
616:
617: f1 += tf;
618: if (f1 >= 75) {
619: s1 += f1 / 75;
620: f1 %= 75;
621: }
622:
623: s1 += ts;
624: if (s1 >= 60) {
625: m1 += s1 / 60;
626: s1 %= 60;
627: }
628:
629: m1 += tm;
630:
1.24 espie 631: if (tr2 <= 0) {
1.1 downsj 632: if (m2 || s2 || f2) {
633: tr2 = tr1;
634: f2 += f1;
635: if (f2 >= 75) {
636: s2 += f2 / 75;
637: f2 %= 75;
638: }
639:
640: s2 += s1;
641: if (s2 > 60) {
642: m2 += s2 / 60;
643: s2 %= 60;
644: }
645:
646: m2 += m1;
647: } else {
648: tr2 = n;
649: if (msf) {
650: m2 = toc_buffer[n].addr.msf.minute;
651: s2 = toc_buffer[n].addr.msf.second;
652: f2 = toc_buffer[n].addr.msf.frame;
653: } else {
654: lba2msf(ntohl(toc_buffer[n].addr.lba),
655: &tm, &ts, &tf);
656: m2 = tm;
657: s2 = ts;
658: f2 = tf;
659: }
660: }
661: } else if (tr2 > n) {
662: tr2 = n;
663: m2 = s2 = f2 = 0;
664: } else {
665: if (m2 || s2 || f2)
666: tr2--;
667: if (msf) {
668: tm = toc_buffer[tr2].addr.msf.minute;
669: ts = toc_buffer[tr2].addr.msf.second;
670: tf = toc_buffer[tr2].addr.msf.frame;
671: } else
672: lba2msf(ntohl(toc_buffer[tr2].addr.lba),
673: &tm, &ts, &tf);
674: f2 += tf;
675: if (f2 >= 75) {
676: s2 += f2 / 75;
677: f2 %= 75;
678: }
679:
680: s2 += ts;
681: if (s2 > 60) {
682: m2 += s2 / 60;
683: s2 %= 60;
684: }
685:
686: m2 += tm;
687: }
688:
689: if (msf) {
690: tm = toc_buffer[n].addr.msf.minute;
691: ts = toc_buffer[n].addr.msf.second;
692: tf = toc_buffer[n].addr.msf.frame;
693: } else
694: lba2msf(ntohl(toc_buffer[n].addr.lba),
695: &tm, &ts, &tf);
696: if ((tr2 < n)
697: && ((m2 > tm)
698: || ((m2 == tm)
699: && ((s2 > ts)
700: || ((s2 == ts)
701: && (f2 > tf)))))) {
1.18 deraadt 702: printf("The playing time of the disc is not that long.\n");
1.1 downsj 703: return (0);
704: }
1.18 deraadt 705: return (play_msf(m1, s1, f1, m2, s2, f2));
1.1 downsj 706:
707: Try_Absolute_Timed_Addresses:
1.18 deraadt 708: if (6 != sscanf(arg, "%d:%d.%d%d:%d.%d",
709: &m1, &s1, &f1, &m2, &s2, &f2) &&
710: 5 != sscanf(arg, "%d:%d.%d%d:%d", &m1, &s1, &f1, &m2, &s2) &&
711: 5 != sscanf(arg, "%d:%d%d:%d.%d", &m1, &s1, &m2, &s2, &f2) &&
712: 3 != sscanf(arg, "%d:%d.%d", &m1, &s1, &f1) &&
713: 4 != sscanf(arg, "%d:%d%d:%d", &m1, &s1, &m2, &s2) &&
714: 2 != sscanf(arg, "%d:%d", &m1, &s1))
1.1 downsj 715: goto Clean_up;
716:
717: if (m2 == 0) {
718: if (msf) {
719: m2 = toc_buffer[n].addr.msf.minute;
720: s2 = toc_buffer[n].addr.msf.second;
721: f2 = toc_buffer[n].addr.msf.frame;
722: } else {
723: lba2msf(ntohl(toc_buffer[n].addr.lba),
724: &tm, &ts, &tf);
725: m2 = tm;
726: s2 = ts;
727: f2 = tf;
728: }
729: }
1.18 deraadt 730: return play_msf(m1, s1, f1, m2, s2, f2);
1.1 downsj 731: }
732:
733: /*
734: * Play track trk1 [ .idx1 ] [ trk2 [ .idx2 ] ]
735: */
1.18 deraadt 736: if (4 != sscanf(arg, "%d.%d%d.%d", &start, &istart, &end, &iend) &&
737: 3 != sscanf(arg, "%d.%d%d", &start, &istart, &end) &&
738: 3 != sscanf(arg, "%d%d.%d", &start, &end, &iend) &&
739: 2 != sscanf(arg, "%d.%d", &start, &istart) &&
740: 2 != sscanf(arg, "%d%d", &start, &end) &&
741: 1 != sscanf(arg, "%d", &start))
1.1 downsj 742: goto Clean_up;
743:
744: if (end == 0)
1.10 csapuntz 745: end = h.ending_track;
1.18 deraadt 746: return (play_track(start, istart, end, iend));
1.1 downsj 747:
748: Clean_up:
1.18 deraadt 749: printf("%s: Invalid command arguments\n", __progname);
1.5 angelos 750: return (0);
751: }
752:
1.18 deraadt 753: int
1.24 espie 754: play_prev(char *arg)
1.5 angelos 755: {
1.18 deraadt 756: int trk, min, sec, frm, rc;
757: struct ioc_toc_header h;
1.5 angelos 758:
1.18 deraadt 759: if (status(&trk, &min, &sec, &frm) >= 0) {
760: trk--;
1.5 angelos 761:
1.18 deraadt 762: rc = ioctl(fd, CDIOREADTOCHEADER, &h);
763: if (rc < 0) {
764: warn("getting toc header");
765: return (rc);
766: }
1.5 angelos 767:
1.18 deraadt 768: if (trk < h.starting_track)
769: return play_track(h.starting_track, 1,
770: h.ending_track + 1, 1);
771: return play_track(trk, 1, h.ending_track, 1);
772: }
1.6 angelos 773:
1.18 deraadt 774: return (0);
1.6 angelos 775: }
776:
1.18 deraadt 777: int
1.24 espie 778: play_same(char *arg)
1.6 angelos 779: {
1.18 deraadt 780: int trk, min, sec, frm, rc;
781: struct ioc_toc_header h;
1.6 angelos 782:
1.18 deraadt 783: if (status (&trk, &min, &sec, &frm) >= 0) {
784: rc = ioctl(fd, CDIOREADTOCHEADER, &h);
785: if (rc < 0) {
786: warn("getting toc header");
787: return (rc);
788: }
1.5 angelos 789:
1.18 deraadt 790: return play_track(trk, 1, h.ending_track, 1);
791: }
1.5 angelos 792:
1.18 deraadt 793: return (0);
1.5 angelos 794: }
795:
1.18 deraadt 796: int
1.24 espie 797: play_next(char *arg)
1.5 angelos 798: {
799: int trk, min, sec, frm, rc;
800: struct ioc_toc_header h;
801:
1.18 deraadt 802: if (status(&trk, &min, &sec, &frm) >= 0) {
1.5 angelos 803: trk++;
1.18 deraadt 804: rc = ioctl(fd, CDIOREADTOCHEADER, &h);
805: if (rc < 0) {
806: warn("getting toc header");
1.5 angelos 807: return (rc);
808: }
809:
1.18 deraadt 810: if (trk > h.ending_track) {
1.5 angelos 811: printf("%s: end of CD\n", __progname);
812:
1.18 deraadt 813: rc = ioctl(fd, CDIOCSTOP);
1.5 angelos 814:
1.18 deraadt 815: (void) ioctl(fd, CDIOCALLOW);
1.5 angelos 816:
817: return (rc);
818: }
819:
1.18 deraadt 820: return play_track(trk, 1, h.ending_track, 1);
1.5 angelos 821: }
822:
1.1 downsj 823: return (0);
824: }
825:
1.18 deraadt 826: char *
1.24 espie 827: strstatus(int sts)
1.1 downsj 828: {
829: switch (sts) {
1.18 deraadt 830: case ASTS_INVALID:
831: return ("invalid");
832: case ASTS_PLAYING:
833: return ("playing");
834: case ASTS_PAUSED:
835: return ("paused");
836: case ASTS_COMPLETED:
837: return ("completed");
838: case ASTS_ERROR:
839: return ("error");
840: case ASTS_VOID:
841: return ("void");
842: default:
843: return ("??");
1.1 downsj 844: }
845: }
846:
1.18 deraadt 847: int
1.24 espie 848: pstatus(char *arg)
1.1 downsj 849: {
850: struct ioc_vol v;
851: struct ioc_read_subchannel ss;
852: struct cd_sub_channel_info data;
853: int rc, trk, m, s, f;
1.17 espie 854: char vis_catalog[1 + 4 * 15];
1.1 downsj 855:
1.18 deraadt 856: rc = status(&trk, &m, &s, &f);
1.9 millert 857: if (rc >= 0) {
1.24 espie 858: if (verbose) {
859: if (track_names)
860: printf("Audio status = %d<%s>, "
861: "current track = %d (%s)\n"
862: "\tcurrent position = %d:%02d.%02d\n",
863: rc, strstatus(rc), trk,
864: trk ? track_names[trk-1] : "", m, s, f);
865: else
866: printf("Audio status = %d<%s>, "
867: "current track = %d, "
868: "current position = %d:%02d.%02d\n",
869: rc, strstatus(rc), trk, m, s, f);
870: } else
1.18 deraadt 871: printf("%d %d %d:%02d.%02d\n", rc, trk, m, s, f);
1.9 millert 872: } else
1.18 deraadt 873: printf("No current status info available\n");
1.1 downsj 874:
1.18 deraadt 875: bzero(&ss, sizeof (ss));
1.1 downsj 876: ss.data = &data;
877: ss.data_len = sizeof (data);
878: ss.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT;
879: ss.data_format = CD_MEDIA_CATALOG;
1.18 deraadt 880: rc = ioctl(fd, CDIOCREADSUBCHANNEL, (char *) &ss);
1.1 downsj 881: if (rc >= 0) {
882: printf("Media catalog is %sactive",
883: ss.data->what.media_catalog.mc_valid ? "": "in");
884: if (ss.data->what.media_catalog.mc_valid &&
1.17 espie 885: ss.data->what.media_catalog.mc_number[0]) {
886: strvisx(vis_catalog,
887: ss.data->what.media_catalog.mc_number,
888: 15, VIS_SAFE);
889: printf(", number \"%.15s\"", vis_catalog);
890: }
1.1 downsj 891: putchar('\n');
892: } else
893: printf("No media catalog info available\n");
894:
1.18 deraadt 895: rc = ioctl(fd, CDIOCGETVOL, &v);
1.9 millert 896: if (rc >= 0) {
1.1 downsj 897: if (verbose)
1.18 deraadt 898: printf("Left volume = %d, right volume = %d\n",
1.1 downsj 899: v.vol[0], v.vol[1]);
900: else
1.18 deraadt 901: printf("%d %d\n", v.vol[0], v.vol[1]);
1.9 millert 902: } else
1.18 deraadt 903: printf("No volume level info available\n");
1.1 downsj 904: return(0);
1.25 espie 905: }
906:
907: int
908: cdid()
909: {
910: unsigned long id;
911: struct ioc_toc_header h;
912: int rc, n;
913:
914: rc = ioctl(fd, CDIOREADTOCHEADER, &h);
915: if (rc == -1) {
916: warn("getting toc header");
917: return (rc);
918: }
919:
920: n = h.ending_track - h.starting_track + 1;
921: rc = read_toc_entrys((n + 1) * sizeof (struct cd_toc_entry));
922: if (rc < 0)
923: return (rc);
924:
925: id = cddb_discid(n, toc_buffer);
926: if (id) {
927: if (verbose)
928: printf("CDID=");
929: printf("%08lx\n", id);
930: }
931: return id ? 0 : 1;
1.1 downsj 932: }
933:
1.18 deraadt 934: int
1.24 espie 935: info(char *arg)
1.1 downsj 936: {
937: struct ioc_toc_header h;
938: int rc, i, n;
939:
1.18 deraadt 940: rc = ioctl(fd, CDIOREADTOCHEADER, &h);
1.1 downsj 941: if (rc >= 0) {
942: if (verbose)
1.18 deraadt 943: printf("Starting track = %d, ending track = %d, TOC size = %d bytes\n",
944: h.starting_track, h.ending_track, h.len);
1.1 downsj 945: else
1.18 deraadt 946: printf("%d %d %d\n", h.starting_track,
947: h.ending_track, h.len);
1.1 downsj 948: } else {
1.18 deraadt 949: warn("getting toc header");
1.1 downsj 950: return (rc);
951: }
952:
953: n = h.ending_track - h.starting_track + 1;
1.18 deraadt 954: rc = read_toc_entrys((n + 1) * sizeof (struct cd_toc_entry));
1.1 downsj 955: if (rc < 0)
956: return (rc);
957:
958: if (verbose) {
1.18 deraadt 959: printf("track start duration block length type\n");
960: printf("-------------------------------------------------\n");
1.1 downsj 961: }
962:
963: for (i = 0; i < n; i++) {
1.18 deraadt 964: printf("%5d ", toc_buffer[i].track);
1.24 espie 965: prtrack(toc_buffer + i, 0, NULL);
966: }
967: printf("%5d ", toc_buffer[n].track);
968: prtrack(toc_buffer + n, 1, NULL);
969: return (0);
970: }
971:
972: int
973: cddbinfo(char *arg)
974: {
975: struct ioc_toc_header h;
976: int rc, i, n;
977:
978: rc = ioctl(fd, CDIOREADTOCHEADER, &h);
979: if (rc == -1) {
980: warn("getting toc header");
981: return (rc);
982: }
983:
984: n = h.ending_track - h.starting_track + 1;
985: rc = read_toc_entrys((n + 1) * sizeof (struct cd_toc_entry));
986: if (rc < 0)
987: return (rc);
988:
989: if (track_names)
990: free_names(track_names);
991: track_names = NULL;
992:
993: track_names = cddb(cddb_host, n, toc_buffer, arg);
994: if (!track_names)
995: return(0);
996:
997: printf("-------------------------------------------------\n");
998:
999: for (i = 0; i < n; i++) {
1000: printf("%5d ", toc_buffer[i].track);
1001: prtrack(toc_buffer + i, 0, track_names[i]);
1.1 downsj 1002: }
1.18 deraadt 1003: printf("%5d ", toc_buffer[n].track);
1.24 espie 1004: prtrack(toc_buffer + n, 1, "");
1.1 downsj 1005: return (0);
1006: }
1007:
1.18 deraadt 1008: void
1.24 espie 1009: lba2msf(unsigned long lba, u_char *m, u_char *s, u_char *f)
1.1 downsj 1010: {
1.18 deraadt 1011: lba += 150; /* block start offset */
1012: lba &= 0xffffff; /* negative lbas use only 24 bits */
1.1 downsj 1013: *m = lba / (60 * 75);
1014: lba %= (60 * 75);
1015: *s = lba / 75;
1016: *f = lba % 75;
1017: }
1018:
1.18 deraadt 1019: unsigned int
1.23 espie 1020: msf2lba(u_char m, u_char s, u_char f)
1.1 downsj 1021: {
1022: return (((m * 60) + s) * 75 + f) - 150;
1023: }
1024:
1.24 espie 1025: unsigned long
1026: entry2time(struct cd_toc_entry *e)
1027: {
1028: int block;
1029: u_char m, s, f;
1030:
1031: if (msf) {
1032: return (e->addr.msf.minute * 60 + e->addr.msf.second);
1033: } else {
1034: block = ntohl(e->addr.lba);
1035: lba2msf(block, &m, &s, &f);
1036: return (m*60+s);
1037: }
1038: }
1039:
1040: unsigned long
1041: entry2frames(struct cd_toc_entry *e)
1042: {
1043: int block;
1044: unsigned char m, s, f;
1045:
1046: if (msf) {
1047: return e->addr.msf.frame + e->addr.msf.second * 75 +
1048: e->addr.msf.minute * 60 * 75;
1049: } else {
1050: block = ntohl(e->addr.lba);
1051: lba2msf(block, &m, &s, &f);
1052: return f + s * 75 + m * 60 * 75;
1053: }
1054: }
1055:
1.18 deraadt 1056: void
1.24 espie 1057: prtrack(struct cd_toc_entry *e, int lastflag, char *name)
1.1 downsj 1058: {
1059: int block, next, len;
1060: u_char m, s, f;
1061:
1062: if (msf) {
1.24 espie 1063: if (!name || lastflag)
1064: /* Print track start */
1065: printf("%2d:%02d.%02d ", e->addr.msf.minute,
1066: e->addr.msf.second, e->addr.msf.frame);
1.1 downsj 1067:
1.18 deraadt 1068: block = msf2lba(e->addr.msf.minute, e->addr.msf.second,
1.1 downsj 1069: e->addr.msf.frame);
1070: } else {
1071: block = ntohl(e->addr.lba);
1.24 espie 1072: if (!name || lastflag) {
1073: lba2msf(block, &m, &s, &f);
1074: /* Print track start */
1075: printf("%2d:%02d.%02d ", m, s, f);
1076: }
1.1 downsj 1077: }
1078: if (lastflag) {
1.24 espie 1079: if (!name)
1080: /* Last track -- print block */
1081: printf(" - %6d - -\n", block);
1082: else
1083: printf("\n");
1.1 downsj 1084: return;
1085: }
1086:
1087: if (msf)
1.18 deraadt 1088: next = msf2lba(e[1].addr.msf.minute, e[1].addr.msf.second,
1.1 downsj 1089: e[1].addr.msf.frame);
1090: else
1091: next = ntohl(e[1].addr.lba);
1092: len = next - block;
1.18 deraadt 1093: lba2msf(len, &m, &s, &f);
1.1 downsj 1094:
1.24 espie 1095: if (name)
1096: printf("%2d:%02d.%02d %s\n", m, s, f, name);
1.1 downsj 1097: /* Print duration, block, length, type */
1.24 espie 1098: else
1099: printf("%2d:%02d.%02d %6d %6d %5s\n", m, s, f, block, len,
1100: (e->control & 4) ? "data" : "audio");
1.1 downsj 1101: }
1102:
1.18 deraadt 1103: int
1.24 espie 1104: play_track(int tstart, int istart, int tend, int iend)
1.1 downsj 1105: {
1106: struct ioc_play_track t;
1107:
1108: t.start_track = tstart;
1109: t.start_index = istart;
1110: t.end_track = tend;
1111: t.end_index = iend;
1112:
1.18 deraadt 1113: return ioctl(fd, CDIOCPLAYTRACKS, &t);
1.1 downsj 1114: }
1115:
1.18 deraadt 1116: int
1.24 espie 1117: play_blocks(int blk, int len)
1.1 downsj 1118: {
1119: struct ioc_play_blocks t;
1120:
1121: t.blk = blk;
1122: t.len = len;
1123:
1.18 deraadt 1124: return ioctl(fd, CDIOCPLAYBLOCKS, &t);
1.1 downsj 1125: }
1126:
1.18 deraadt 1127: int
1.24 espie 1128: setvol(int left, int right)
1.1 downsj 1129: {
1130: struct ioc_vol v;
1131:
1132: v.vol[0] = left;
1133: v.vol[1] = right;
1134: v.vol[2] = 0;
1135: v.vol[3] = 0;
1136:
1.18 deraadt 1137: return ioctl(fd, CDIOCSETVOL, &v);
1.1 downsj 1138: }
1139:
1.18 deraadt 1140: int
1.24 espie 1141: read_toc_entrys(int len)
1.1 downsj 1142: {
1143: struct ioc_read_toc_entry t;
1.11 csapuntz 1144:
1145: if (toc_buffer) {
1.18 deraadt 1146: free(toc_buffer);
1147: toc_buffer = 0;
1.11 csapuntz 1148: }
1149:
1.18 deraadt 1150: toc_buffer = malloc(len);
1.11 csapuntz 1151:
1152: if (!toc_buffer) {
1.18 deraadt 1153: errno = ENOMEM;
1154: return (-1);
1.11 csapuntz 1155: }
1.1 downsj 1156:
1157: t.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT;
1158: t.starting_track = 0;
1159: t.data_len = len;
1160: t.data = toc_buffer;
1161:
1.18 deraadt 1162: return (ioctl(fd, CDIOREADTOCENTRYS, (char *) &t));
1.1 downsj 1163: }
1164:
1.18 deraadt 1165: int
1.24 espie 1166: play_msf(int start_m, int start_s, int start_f, int end_m, int end_s, int end_f)
1.1 downsj 1167: {
1.18 deraadt 1168: struct ioc_play_msf a;
1.1 downsj 1169:
1170: a.start_m = start_m;
1171: a.start_s = start_s;
1172: a.start_f = start_f;
1173: a.end_m = end_m;
1174: a.end_s = end_s;
1175: a.end_f = end_f;
1176:
1.18 deraadt 1177: return ioctl(fd, CDIOCPLAYMSF, (char *) &a);
1.1 downsj 1178: }
1179:
1.21 espie 1180: int
1.24 espie 1181: status(int *trk, int *min, int *sec, int *frame)
1.1 downsj 1182: {
1183: struct ioc_read_subchannel s;
1184: struct cd_sub_channel_info data;
1185: u_char mm, ss, ff;
1186:
1.18 deraadt 1187: bzero(&s, sizeof (s));
1.1 downsj 1188: s.data = &data;
1189: s.data_len = sizeof (data);
1190: s.address_format = msf ? CD_MSF_FORMAT : CD_LBA_FORMAT;
1191: s.data_format = CD_CURRENT_POSITION;
1192:
1.18 deraadt 1193: if (ioctl(fd, CDIOCREADSUBCHANNEL, (char *) &s) < 0)
1.1 downsj 1194: return -1;
1195:
1196: *trk = s.data->what.position.track_number;
1197: if (msf) {
1198: *min = s.data->what.position.reladdr.msf.minute;
1199: *sec = s.data->what.position.reladdr.msf.second;
1200: *frame = s.data->what.position.reladdr.msf.frame;
1201: } else {
1202: lba2msf(ntohl(s.data->what.position.reladdr.lba),
1.18 deraadt 1203: &mm, &ss, &ff);
1.1 downsj 1204: *min = mm;
1205: *sec = ss;
1206: *frame = ff;
1207: }
1208:
1209: return s.data->header.audio_status;
1210: }
1211:
1.18 deraadt 1212: char *
1.24 espie 1213: input(int *cmd)
1.1 downsj 1214: {
1.27 ! fgsch 1215: char *buf;
! 1216: int siz = 0;
1.1 downsj 1217: char *p;
1218:
1219: do {
1.27 ! fgsch 1220: if ((buf = (char *) el_gets(el, &siz)) == NULL || !siz) {
1.1 downsj 1221: *cmd = CMD_QUIT;
1.18 deraadt 1222: fprintf(stderr, "\r\n");
1.1 downsj 1223: return (0);
1224: }
1.27 ! fgsch 1225: if (strlen(buf) > 1)
! 1226: history(hist, H_ENTER, buf);
1.18 deraadt 1227: p = parse(buf, cmd);
1228: } while (!p);
1.1 downsj 1229: return (p);
1230: }
1231:
1.18 deraadt 1232: char *
1.24 espie 1233: parse(char *buf, int *cmd)
1.1 downsj 1234: {
1235: struct cmdtab *c;
1236: char *p;
1237: int len;
1238:
1.18 deraadt 1239: for (p=buf; isspace(*p); p++)
1.1 downsj 1240: continue;
1241:
1.18 deraadt 1242: if (isdigit(*p) || (p[0] == '#' && isdigit(p[1]))) {
1.1 downsj 1243: *cmd = CMD_PLAY;
1244: return (p);
1245: }
1246:
1.18 deraadt 1247: for (buf = p; *p && ! isspace(*p); p++)
1.1 downsj 1248: continue;
1249:
1250: len = p - buf;
1251: if (! len)
1252: return (0);
1253:
1.18 deraadt 1254: if (*p) { /* It must be a spacing character! */
1.1 downsj 1255: char *q;
1256:
1257: *p++ = 0;
1258: for (q=p; *q && *q != '\n' && *q != '\r'; q++)
1259: continue;
1260: *q = 0;
1261: }
1262:
1263: *cmd = -1;
1264: for (c=cmdtab; c->name; ++c) {
1265: /* Is it an exact match? */
1.18 deraadt 1266: if (! strcasecmp(buf, c->name)) {
1.1 downsj 1267: *cmd = c->command;
1268: break;
1269: }
1270:
1271: /* Try short hand forms then... */
1.18 deraadt 1272: if (len >= c->min && ! strncasecmp(buf, c->name, len)) {
1.1 downsj 1273: if (*cmd != -1 && *cmd != c->command) {
1.18 deraadt 1274: fprintf(stderr, "Ambiguous command\n");
1.1 downsj 1275: return (0);
1276: }
1277: *cmd = c->command;
1278: }
1279: }
1280:
1281: if (*cmd == -1) {
1.18 deraadt 1282: fprintf(stderr, "%s: Invalid command, enter ``help'' for commands.\n",
1283: __progname);
1.1 downsj 1284: return (0);
1285: }
1286:
1.18 deraadt 1287: while (isspace(*p))
1.1 downsj 1288: p++;
1289: return p;
1290: }
1291:
1.18 deraadt 1292: int
1.24 espie 1293: open_cd(char *dev)
1.1 downsj 1294: {
1.9 millert 1295: char *realdev;
1.12 millert 1296: int tries;
1.1 downsj 1297:
1298: if (fd > -1)
1299: return (1);
1300:
1.12 millert 1301: for (tries = 0; fd < 0 && tries < 10; tries++) {
1302: fd = opendev(dev, O_RDONLY, OPENDEV_PART, &realdev);
1303: if (fd < 0) {
1304: if (errno == ENXIO) {
1305: /* ENXIO has an overloaded meaning here.
1306: * The original "Device not configured" should
1307: * be interpreted as "No disc in drive %s". */
1.18 deraadt 1308: warnx("No disc in drive %s.", realdev);
1.12 millert 1309: return (0);
1310: } else if (errno != EIO) {
1311: /* EIO may simply mean the device is not ready
1312: * yet which is common with CD changers. */
1.18 deraadt 1313: warn("Can't open %s", realdev);
1.12 millert 1314: return (0);
1315: }
1316: }
1.18 deraadt 1317: sleep(1);
1.12 millert 1318: }
1.1 downsj 1319: if (fd < 0) {
1.18 deraadt 1320: warn("Can't open %s", realdev);
1.9 millert 1321: return (0);
1.1 downsj 1322: }
1323: return (1);
1.27 ! fgsch 1324: }
! 1325:
! 1326: char *
! 1327: prompt(void)
! 1328: {
! 1329: return (verbose ? "cdio> " : "");
! 1330: }
! 1331:
! 1332: void
! 1333: switch_el(void)
! 1334: {
! 1335: if (el == NULL && hist == NULL) {
! 1336: el = el_init(__progname, stdin, stdout);
! 1337: hist = history_init();
! 1338: history(hist, H_EVENT, 100);
! 1339: el_set(el, EL_HIST, history, hist);
! 1340: el_set(el, EL_EDITOR, "emacs");
! 1341: el_set(el, EL_PROMPT, prompt);
! 1342: el_set(el, EL_SIGNAL, 1);
! 1343: el_source(el, NULL);
! 1344:
! 1345: } else {
! 1346: if (hist != NULL) {
! 1347: history_end(hist);
! 1348: hist = NULL;
! 1349: }
! 1350: if (el != NULL) {
! 1351: el_end(el);
! 1352: el = NULL;
! 1353: }
! 1354: }
1.1 downsj 1355: }