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.