/* * Copy me if you can. * by 20h * * I can. * capso */ #include #include #include #define SHOUTSZ 512 int debug = 1; char * read_line(int s) { char *ret; int l; ret = nil; l = 0; while((ret = realloc(ret, ++l)) != nil && read(s, &ret[l - 1], 1) > 0 && l < 1024) { if(l > 1) { if(ret[l - 1] == '\n') { ret[l - 1] = '\0'; if(ret[l - 2] == '\r') ret[l - 2] = '\0'; return ret; } } } if(ret != nil) free(ret); return nil; } int read_httphdr(int s) { int blksz = 0; char *ret, *n; while((ret = read_line(s)) != nil && ret[0] != '\0'){ if(debug) fprint(2, "dbg: %s\n", ret); if(!strncmp(ret, "icy-metaint", 11)) /* match */ { n = strchr(ret, ':') + 1; /* atoi handles space */ blksz = atoi(n); } free(ret); } return blksz; } int read_pls(int fd, char **host, char **port, char **path) { char *ret, *h, *a; while((ret = read_line(fd)) != nil && ret[0] != '\0') { if(!strncmp(ret, "File", 4)) { h = strchr(ret + 13, ':'); if(h == nil) { *port = strdup("8000"); h = ret + 13; } else { *h++ = '\0'; } a = strchr(h, '/'); if(a != nil) { *a++ = '\0'; } else { *path = strdup(""); } *host = strdup(ret + 13); if(*port == nil) *port = strdup(h); if(*path == nil) *path = strdup(a); free(ret); return 0; } free(ret); } return 1; } char* read_title(Biobuf *in) { char buf[4096]; int size; Bread(in, buf, 1); if(*buf == 0) return ""; size = (*buf&0xff) * 16; Bread(in, buf, size); buf[size+1] = '\0'; return buf; /* parse it with awk(1) */ } void shoutcast(int fd, char *path) { Biobuf in; int l, osz, sz, data, blksz; char buf[SHOUTSZ], *s; data = 0; fprint(fd, "GET /%s HTTP/1.0\r\n", path); fprint(fd, "User-Agent: streamget/1st\r\n"); fprint(fd, "Icy-MetaData:1\r\n"); fprint(fd, "\r\n"); blksz = read_httphdr(fd); osz = sz = (blksz < SHOUTSZ) ? blksz : SHOUTSZ; Binit(&in, fd, OREAD); while((l = Bread(&in, buf, sz)) > 0){ data += l; if((blksz - data) < osz) sz = blksz - data; if(data == blksz) { data = 0; sz = osz; s = read_title(&in); if(strlen(s) > 0) fprint(2, "%s\n", s); } write(1, buf, l); } } void main(void) { int fd; char *path, *host, *port; host = port = path = nil; if(read_pls(0, &host, &port, &path)) { print("Wrong pls format.\n"); exits(0); } fd = dial(netmkaddr(host, "tcp", port), 0, 0, 0); if(fd < 0) { perror("dial: %r"); exits(0); } free(host); free(port); shoutcast(fd, path); exits(0); }