📄 cddb.c
字号:
/* * Author strongly advices against using this code, or a part of it, * in an application designed to run on any Microsoft(tm) platform. * * See doc/README for more information about COPYING terms. */#include "mcd.h"#include <limits.h>#define BUFSIZE 1024 /* complete lines of server must fit ! */char port[6], ip[16];static short cddb_parseentry(struct mcd *cd);static int cddb_getserver(const char *ipport, char *ip, char *port);static int cddb_opensocket(char *ip, char *port);static int cddb_readsocket(char *s, int size, int *socket);static short cddb_abort(struct he *h);/* searches a local entry, success returns 0 (needs CDB_PATH!)*/static short cddb_parseentry(struct mcd *cd) { char *fn=malloc(sizeof(char)*PATH_MAX); int p=0,tr=0,len,fd; /* p=parse;tr=track */ char ch; len=_snprintf(fn,PATH_MAX-1,"%s/%08x", getenv("CDDB_PATH"),cd_discid(&cd[0])); fn[len]='\0'; if ((fd=open(fn,O_RDONLY))<0) { free(fn); return -1; /* no entry (mostly *g*) */ } len=0; while (len+=read(fd,&ch,1)>0) { fn[len-1]=ch; if (ch=='\n'||ch=='\r') { /* next one */ p=1;fn[len-1]='\0';len=0; } if (p) { /* parse line */ if (!strncmp(fn, "DTITLE=", 7)) str_ncpy(cd->t[0].name, fn+7, str_len(fn)); if (!strncmp(fn, "TTITLE", 6)) str_ncpy(cd->t[++tr].name, fn+8+(int)(tr/10), str_len(fn)); p=0; } } /* while() */ free(fn); return 0;}/* gets server from environment, 0 means success (not always correct, but libc-stuff is to big) */static int cddb_getserver(const char *ipport, char *ip, char *port) { register const char *s=ipport; register int i; if (!s) return -1; for (i=0;*s && *s!=':';s++,i++) ip[i]=*s; /* shall be an ip :} */ if (i>15) return -1; /* 12+3 */ ip[i]='\0';s++; for (i=0;*s;s++,i++) port[i]=*s; if (i>5) return -1; port[i]='\0'; return 0;}/* close connection to server */static short cddb_abort(struct he *h) { write(h->fd,"quit\n",5); close(h->fd); free(h->msg); return CDDB_NOENT;}/* returns socket of server */static int cddb_opensocket(char *ip, char *port) { struct sockaddr_in addr; int sockfd; if ((sockfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))<0) return -1; addr.sin_family=AF_INET; addr.sin_port=htons(atoi(port)); addr.sin_addr.s_addr=inet_addr(ip); if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr))<0) return -1; return sockfd;}/* XXX + warning, can lock the programm, if server is ugly */static int cddb_readsocket(char *s, int size, int *socket) { int i=0,r; char c; while ((r=recv(*socket, &c, 1, 0))>0) { if (i==size) break; s[i++]=c; if (c=='\r') break; /* \r\n -> '\n' after while */ } if (r<0) return r; recv(*socket, &c, 1, 0); s[i]='\0';return i;}/* the global call, fills cd->t[].name, returns CDDB_MODES (mcd.h) */int cddb_getentries(struct mcd *cd) { char *hostname=getenv("HOSTNAME"); char *logname=getenv("LOGNAME"); char tmp[16]; /* tracks to str */ struct he h; int len,i; /* if this is not set, we do nothing! */ if (getenv("CDDB_PATH")==NULL) return CDDB_NOENT; /* if local entry is here, we take it */ if (!cddb_parseentry(&cd[0])) return CDDB_LOCAL; /* now, lets get new entry (handles only exact matches) */ if ((cddb_getserver(getenv("CDDB_SERVER"),ip,port)<0) || ((h.fd=cddb_opensocket(ip,port))<0) || /* can't connect */ (hostname==NULL) || (logname==NULL)) /* kiss */ return CDDB_NOENT; h.msg=malloc(sizeof(char)*BUFSIZE+1); if (!h.msg) return CDDB_NOENT; /* small implementation of this protocoll (l8er more?) */ /* 201 foobar server version ready */ if ((len=cddb_readsocket(h.msg, BUFSIZE, &h.fd))<0) return cddb_abort(&h); if (strncmp("201",h.msg,3)) return cddb_abort(&h); len=_snprintf(h.msg,BUFSIZE,"cddb hello %s %s mcd %s\n", logname,hostname,MCD_VERSION); write(h.fd,h.msg,len); /* 200 Hello and welcome user@hostname running mcd version */ if ((len=cddb_readsocket(h.msg, BUFSIZE, &h.fd))<0) return cddb_abort(&h); if (strncmp("200",h.msg,3)) return cddb_abort(&h); len=_snprintf(h.msg,BUFSIZE,"cddb query %08x %d ", cd_discid(&cd[0]),cd->title[1]); for (i=1;i<=cd->title[1];i++) { len+=_snprintf(tmp, 15, "%d ", cd->t[i].cddb); strncat(h.msg,tmp,str_len(tmp)); } len+=_snprintf(tmp, 15, "%d\n", cd->t[0].cddb); strncat(h.msg,tmp,str_len(tmp)); write(h.fd,h.msg,len); /* 200 rock a90c9d0c Queen / Innuendo */ if ((len=cddb_readsocket(h.msg, BUFSIZE, &h.fd))<0) return cddb_abort(&h); if (strncmp("200",h.msg,3)) return cddb_abort(&h); for (i=0;h.msg[i+4]!=' ';i++) tmp[i]=h.msg[i+4]; /* 200 foobar' ' */ tmp[i]='\0'; len=_snprintf(h.msg,BUFSIZE,"cddb read %s %08x\n", tmp,cd_discid(&cd[0])); write(h.fd,h.msg,len); /* 210 rock a90c9d0c CD database entry follows (until terminating `.') */ if ((len=cddb_readsocket(h.msg, BUFSIZE, &h.fd))<0) return cddb_abort(&h); if (strncmp("210",h.msg,3)) return cddb_abort(&h); len=_snprintf(h.msg,BUFSIZE,"%s/%08x",getenv("CDDB_PATH"),cd_discid(&cd[0])); i=open(h.msg,O_WRONLY|O_CREAT,CDDB_CREATMODE); while ((len=cddb_readsocket(h.msg, BUFSIZE, &h.fd))>0 && (h.msg[0]!='.')) { write(i,h.msg,len-1); /* [len]='\r' */ write(i,"\n",1); } if (len<0) return cddb_abort(&h); close(i); /* 230 foobar Goodbye. */ write(h.fd,"quit\n",5); /* last recv() isn't usefull, but seems correct :) */ if ((len=cddb_readsocket(h.msg, BUFSIZE, &h.fd))<0) return cddb_abort(&h); if (strncmp("230",h.msg,3)) return cddb_abort(&h); close(h.fd); free(h.msg); if (!cddb_parseentry(&cd[0])) return CDDB_REMOTE; return CDDB_NOENT;}/*TODO:201 whisky.wu-wien.ac.at CDDBP server v1.4b42PL0 ready at Sat Jul 28 01:08:01 2001cddb hello mcmilk darkwood mcd 0.3b200 Hello and welcome mcmilk@darkwood running mcd 0.3b.cddb query 8910cf1c 28 182 11982 26962 40150 54342 65580 76077 85992 95200 108477 123820 135037 145632 157072 167537187660 199132 206732 218450 228770 240150 248750 260525 268050 275925 287920 305385 311842 4305211 Found inexact matches, list follows (until terminating `.')rock 7510961c B鰄se Onkelz / Der Nette Mann + Demosrock 9f10d71c B鰄se Onkelz / Der nette Mann & Demosrock 9711051c B鰄se Onkelz / Der nette Mann....quit*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -