This is nntp-com.c in view mode; [Download] [Up]
/* $Id$ */ #ifdef NNTPNEWS #include "bbs.h" #include <netinet/in.h> extern void nntp_alrmhandler(int); static sigjmp_buf nntp_sigalrmenv; int nntp_connect(newsstattyp *newsstat, const confrecordtyp *confrecord) { int response; char line[NNTP_STRLEN+1]; newsstat->can_post = FALSE; newsstat->is_connected = FALSE; if (nntp_socket(newsstat,confrecord) < 0) { bgerror("nntp_connect","NNTP connection failed"); return -1; } response = nntp_getresponse(line,NNTP_STRLEN,newsstat); switch (response) { case OK_CANPOST: newsstat->can_post = TRUE; break; case OK_NOPOST: newsstat->can_post = FALSE; break; default: return -1; } newsstat->is_connected = TRUE; newsstat->group_is_set = FALSE; return 0; } int nntp_socket(newsstattyp *newsstat, const confrecordtyp *confrecord) { int s, n, cnt; char **sap; struct sockaddr_in sin; struct hostent *hostentp; struct servent *servp; if ((hostentp=gethostbyname(confrecord->nntpserver)) == NULL) { bgerror("nntp_socket","host %s: unknown",confrecord->nntpserver); return -1; } strcpy(newsstat->server,hostentp->h_name); if ((servp=getservbyname("nntp","tcp")) == NULL) { bgerror("nntp_socket","nntp/tcp: unknown service"); return -1; } BZERO(&sin, sizeof(sin)); sin.sin_family = hostentp->h_addrtype; sin.sin_port = servp->s_port; for (sap=hostentp->h_addr_list; sap && *sap; sap++) { s = socket(hostentp->h_addrtype, SOCK_STREAM, 0); if (s < 0) { bgerror("nntp_socket","socket: %m"); return -1; } memcpy((char *)&sin.sin_addr, *sap, hostentp->h_length); cnt = 0; #ifdef NNTP_CONNECT_TIMEOUT if (sigsetjmp(nntp_sigalrmenv,(int)FALSE) == 0) { setsighandler(SIGALRM, nntp_alrmhandler); } else { cnt++; } alarm(NNTP_CONNECT_TIMEOUT); n = -1; if (cnt < 3) n = connect(s, (struct sockaddr *)&sin, sizeof(sin)); alarm(0); setsighandler(SIGALRM, SIG_IGN); #else n = connect(s, (struct sockaddr *)&sin, sizeof(sin)); #endif if (n == 0) break; close(s); if (n < 0) { bgerror("nntp_socket","connection to NNTP server %s failed", newsstat->server); } s = -1; } newsstat->sock = s; return s; } void nntp_close(newsstattyp *newsstat) { if (newsstat->is_connected && ! newsstat->nntp_failed) { nntp_ask(NULL,newsstat,"QUIT"); } close(newsstat->sock); newsstat->is_connected = FALSE; return; } int nntp_ask(char *answer, newsstattyp *newsstat, const char *fmt, ...) { int response; char str[NNTP_STRLEN+1]; va_list ap; *str = '\0'; va_start(ap, fmt); if (vfstrlen(fmt,ap) < NNTP_STRLEN-2) { vsprintf(str,fmt,ap); } va_end(ap); if (*str == '\0' || nntp_putline(str,newsstat) < 0) return -1; response = nntp_getresponse(answer==NULL ? str : answer,NNTP_STRLEN,newsstat); if (response == ERR_GOODBYE || response > ERR_COMMAND) { newsstat->nntp_failed = TRUE; newsstat->group_is_set = FALSE; nntp_close(newsstat); } return response; } char *nntp_copytext(SIZE_T *len, newsstattyp *newsstat) { int n, nlines; char *buf, *bp, *sp, *bufsafe, str[NNTP_STRLEN+1]; if ((buf=(char *)malloc(ALLOCSTEPSIZE)) == NULL) { bgerror("nntp_copytext","malloc: %m"); return NULL; } n = 1; bp = buf; nlines = 0; *len = 0; while (nntp_getline(str,NNTP_STRLEN,newsstat) >= 0) { sp = str; if (*sp == '.') { sp++; if (*sp == '\0') { if (nlines <= 0) { free(buf); return NULL; } *bp = '\0'; return buf; } } while (*sp != '\0') { if (bp - buf > n*ALLOCSTEPSIZE-3) { n++; bufsafe = buf; if ((buf=(char *)realloc((void *)buf,n*ALLOCSTEPSIZE)) == NULL) { bgerror("nntp_copytext","realloc: %m"); free(bufsafe); return NULL; } bp += buf - bufsafe; } *bp++ = *sp++; (*len)++; } *bp++ = '\n'; (*len)++; nlines++; } free(buf); return NULL; } int nntp_getline(char *string, SIZE_T size, newsstattyp *newsstat) { static int p=0, len=0; int k = 0; static char inbuf[NNTP_STRLEN+1]; char c; do { if (p == len) { len = read(newsstat->sock,inbuf,size > NNTP_STRLEN ? NNTP_STRLEN : size); p = 0; if (len < 0) return -1; } c = inbuf[p++]; string[k++] = c; } while (c != '\n' && k < size-1); string[k] = '\0'; size = strlen(string); size = size > 2 ? size -2 : 0; string[size] = '\0'; strmaxcpy(newsstat->lastretstr,string,NNTP_STRLEN); return size; } int nntp_getresponse(char *string, SIZE_T size, newsstattyp *newsstat) { if (nntp_getline(string,size,newsstat) < 0) return -1; return isdigit(*string) ? atoi(string) : 0; } int nntp_putline(const char *string, const newsstattyp *newsstat) { char outbuf[NNTP_STRLEN+1]; strmaxcpy(outbuf,string,NNTP_STRLEN-2); strcat(outbuf,"\r\n"); return write(newsstat->sock,outbuf,strlen(outbuf)); } #ifdef NNTP_CONNECT_TIMEOUT void nntp_alrmhandler(int sig) { siglongjmp(nntp_sigalrmenv,1); } #endif /* NNTP_CONNECT_TIMEOUT */ #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.