⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 innxmit.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	if (*p == '\0')	    InHeaders = FALSE;	if (InHeaders || MimeArticle == MTnotmime) {	    if (!REMwrite(p, QIOlength(qp))) {	        (void)fprintf(stderr, "Can't send \"%s\", %s\n",		        Article, strerror(errno));	        return FALSE;	    }	}	else {	    switch (MimeArticle) {	    default:	    case MTbase64:		ok = FALSE;		break;	    case MTquotedprintable:		ok = REMwriteQuoted(p, QIOlength(qp));		break;	    }	    if (!ok) {		(void)fprintf(stderr, "Can't send \"%s\", %s\n",			Article, strerror(errno));		return FALSE;	    }	}	if (GotInterrupt)	    Interrupted(Article, MessageID);    }    if (!REMflush()) {	(void)fprintf(stderr, "Can't end \"%s\", %s\n",		Article, strerror(errno));	return FALSE;    }    if (Debug)	(void)fprintf(stderr, "> [ article ]%s\n",	     MimeArticle == MTnotmime ? "" : " (Mime: quoted-printable)");    /* Write the terminator. */    if (write(ToServer, TERM, STRLEN(TERM)) != STRLEN(TERM)) {	(void)fprintf(stderr, "Can't end \"%s\", %s\n",		Article, strerror(errno));	return FALSE;    }    if (GotInterrupt)	Interrupted(Article, MessageID);    if (Debug)	(void)fprintf(stderr, "> .\n");    /* What did the remote site say? */    if (!REMread(buff, (int)sizeof buff)) {	(void)fprintf(stderr, "No reply after sending \"%s\", %s\n",		Article, strerror(errno));	return FALSE;    }    if (GotInterrupt)	Interrupted(Article, MessageID);    if (Debug)	(void)fprintf(stderr, "< %s", buff);    /* Parse the reply. */    switch (atoi(buff)) {    default:	(void)fprintf(stderr, "Unknown reply after \"%s\" -- %s",		Article, buff);	if (DoRequeue)	    Requeue(Article, MessageID);	break;    case NNTP_RESENDIT_VAL:    case NNTP_GOODBYE_VAL:	syslog(L_NOTICE, GOT_RESENDIT, REMhost, MessageID, REMclean(buff));	Requeue(Article, MessageID);	break;    case NNTP_TOOKIT_VAL:	STATaccepted++;	break;    case NNTP_REJECTIT_VAL:	STATrejected++;	break;    }    /* Article sent, or we requeued it. */    return TRUE;}/***  Get the Message-ID header from an open article.*/STATIC char *GetMessageID(qp)    register QIOSTATE	*qp;{    static char		HDR[] = "Message-ID:";    static char		buff[DBZMAXKEY + 1];    register char	*p;    while ((p = QIOread(qp)) != NULL)	if ((*p == 'M' && EQn(p, HDR, STRLEN(HDR)))	 || ((*p == 'M' || *p == 'm') && caseEQn(p, HDR, STRLEN(HDR)))) {	    /* Found the header -- skip whitespace. */	    for (p += STRLEN(HDR); ISWHITE(*p); p++)		continue;	    if (*p == '\0' || (int)strlen(p) > DBZMAXKEY)		/* Header is empty or too long. */		break;	    (void)strcpy(buff, p);	    return buff;	}    return NULL;}/***  Get the MIME Content headers from an open article.*/STATIC voidGetMimeHeaders(qp, Encodingp, Typep)    register QIOSTATE	*qp;    register char	**Encodingp;    register char	**Typep;{    static char		ENC_HDR[] = "Content-Transfer-Encoding:";    static char		TYPE_HDR[] = "Content-Type:";    static char		Encoding[SMBUF + 1];    static char		ContentType[SMBUF + 1];    register char	*p;    for (*Encodingp = *Typep = NULL; (p = QIOread(qp)) != NULL && *p; ) {	if (*p != 'C' && *p != 'c')	    continue;	if (caseEQn(p, ENC_HDR, STRLEN(ENC_HDR))) {	    for (p += STRLEN(ENC_HDR); ISWHITE(*p); p++)		continue;	    if (*p == '\0' || (int)strlen(p) > sizeof Encoding)		/* Header is empty or too long. */		continue;	    (void)strcpy(Encoding, p);	    *Encodingp = Encoding;	    if (*Typep)		break;	}	else if (caseEQn(p, TYPE_HDR, STRLEN(TYPE_HDR))) {	    for (p += STRLEN(TYPE_HDR); ISWHITE(*p); p++)		continue;	    if (*p == '\0' || (int)strlen(p) > sizeof ContentType)		/* Header is empty or too long. */		break;	    (void)strcpy(ContentType, p);	    /* Strip off any subtype part. */	    for (p = ContentType; *p; p++)		if (*p == '/' || *p == ';') {		    *p = '\0';		    break;		}	    *Typep = ContentType;	    if (*Encodingp)		break;	}    }}/***  Mark that we got interrupted.*/STATIC SIGHANDLERCATCHinterrupt(s)    int		s;{    GotInterrupt = TRUE;    /* Let two interrupts kill us. */    (void)signal(s, SIG_DFL);}/***  Mark that the alarm went off.*//* ARGSUSED0 */STATIC SIGHANDLERCATCHalarm(s)    int		s;{    GotAlarm = TRUE;    if (JMPyes)	longjmp(JMPwhere, 1);}/***  Print a usage message and exit.*/STATIC NORETURNUsage(){    (void)fprintf(stderr,	"Usage: innxmit [-a] [-d] [-M] [-p] [-r] [-S] [-t#] [-T#] host file\n");    exit(1);}intmain(ac, av)    int			ac;    char		*av[];{    static char		SPOOL[] = _PATH_SPOOL;    static char		BATCHDIR[] = _PATH_BATCHDIR;    static char		SKIPPING[] = "Skipping \"%s\" --%s?\n";    register int	i;    register char	*p;    register QIOSTATE	*qp;    TIMEINFO		Now;    FILE		*From;    FILE		*To;    char		buff[NNTP_STRLEN];    char		*AltSpool;    char		*Article;    char		*ContentEncoding;    char		*ContentType;    char		*MessageID;    char		*AltPath;    SIGHANDLER		(*old)();    unsigned int	ConnectTimeout;    unsigned int	TotalTimeout;    /* Set defaults. */    ConnectTimeout = 0;    TotalTimeout = 0;    AltSpool = NULL;    (void)umask(NEWSUMASK);    /* Parse JCL. */    while ((i = getopt(ac, av, "A:adMprSt:T:v")) != EOF)	switch (i) {	default:	    Usage();	    /* NOTREACHED */	case 'A':	    AltSpool = optarg;	    AltPath = NEW(char, SPOOLNAMEBUFF + strlen(AltSpool));	    break;	case 'a':	    AlwaysRewrite = TRUE;	    break;	case 'd':	    Debug = TRUE;	    break;	case 'M':	    Mime = TRUE;	    break;	case 'p':	    AlwaysRewrite = TRUE;	    Purging = TRUE;	    break;	case 'r':	    DoRequeue = FALSE;	    break;	case 'S':	    Slavish = TRUE;	    break;	case 't':	    ConnectTimeout = atoi(optarg);	    break;	case 'T':	    TotalTimeout = atoi(optarg);	    break;	case 'v':	    STATprint = TRUE;	    break;	}    ac -= optind;    av += optind;    /* Parse arguments; host and filename. */    if (ac != 2)	Usage();    REMhost = av[0];    BATCHname = av[1];    if (chdir(SPOOL) < 0) {	(void)fprintf(stderr, "Can't cd to \"%s\", %s\n",		SPOOL, strerror(errno));	exit(1);    }    (void)openlog("innxmit", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);    /* Open the batch file and lock others out. */    if (BATCHname[0] != '/') {	BATCHname = NEW(char, STRLEN(BATCHDIR) + 1 + strlen(av[1]) + 1);	(void)sprintf(BATCHname, "%s/%s", BATCHDIR, av[1]);    }    if ((i = open(BATCHname, O_RDWR)) < 0     || (BATCHqp = QIOfdopen(i, QIO_BUFFER)) == NULL) {	(void)fprintf(stderr, "Can't open \"%s\", %s\n",		BATCHname, strerror(errno));	exit(1);    }    if (LockFile(QIOfileno(BATCHqp), TRUE) < 0) {#if	defined(EWOULDBLOCK)	if (errno == EWOULDBLOCK)	    exit(0);#endif	/* defined(EWOULDBLOCK) */	(void)fprintf(stderr, "Can't lock \"%s\", %s\n",		BATCHname, strerror(errno));	exit(1);    }    /* Get a temporary name in the same directory as the batch file. */    p = strrchr(BATCHname, '/');    BATCHtemp = NEW(char, strlen(BATCHname) + STRLEN("/bchXXXXXX") + 1);    *p = '\0';    (void)sprintf(BATCHtemp, "%s/bchXXXXXX", BATCHname);    *p = '/';    /* Set up buffer used by REMwrite. */    REMbuffer = NEW(char, OUTPUT_BUFFER_SIZE);    REMbuffend = &REMbuffer[OUTPUT_BUFFER_SIZE];    REMbuffptr = REMbuffer;    /* Start timing. */    if (GetTimeInfo(&Now) < 0) {	(void)fprintf(stderr, "Can't get time, %s\n", strerror(errno));	exit(1);    }    STATbegin = TIMEINFOasDOUBLE(Now);    if (!Purging) {	/* Open a connection to the remote server. */	if (ConnectTimeout) {	    GotAlarm = FALSE;	    old = signal(SIGALRM, CATCHalarm);	    (void)alarm(ConnectTimeout);	    JMPyes = TRUE;	    if (setjmp(JMPwhere)) {		(void)fprintf(stderr, "Can't connect to %s, timed out\n",			REMhost);		exit(1);	    }	}	if (NNTPconnect(REMhost, &From, &To, buff) < 0 || GotAlarm) {	    i = errno;	    (void)fprintf(stderr, "Can't connect to %s, %s\n",		    REMhost, buff[0] ? REMclean(buff) : strerror(errno));	    if (GotAlarm)		syslog(L_NOTICE, CANT_CONNECT, REMhost, "timeout");	    else		syslog(L_NOTICE, CANT_CONNECT, REMhost,		    buff[0] ? REMclean(buff) : strerror(i));	    exit(1);	}	if (Debug)	    (void)fprintf(stderr, "< %s\n", REMclean(buff));	if (NNTPsendpassword(REMhost, From, To) < 0 || GotAlarm) {	    i = errno;	    (void)fprintf(stderr, "Can't authenticate with %s, %s\n",		    REMhost, strerror(errno));	    syslog(L_ERROR, CANT_AUTHENTICATE,		REMhost, GotAlarm ? "timeout" : strerror(i));	    /* Don't send quit; we want the remote to print a message. */	    exit(1);	}	if (ConnectTimeout) {	    (void)alarm(0);	    (void)signal(SIGALRM, old);	    JMPyes = FALSE;	}	/* We no longer need standard I/O. */	FromServer = fileno(From);	ToServer = fileno(To);    }    /* Set up signal handlers. */    (void)signal(SIGHUP, CATCHinterrupt);    (void)signal(SIGINT, CATCHinterrupt);    (void)signal(SIGTERM, CATCHinterrupt);    (void)signal(SIGPIPE, SIG_IGN);    if (TotalTimeout) {	(void)alarm(TotalTimeout);	(void)signal(SIGALRM, CATCHalarm);    }    /* Main processing loop. */    GotInterrupt = FALSE;    GotAlarm = FALSE;    for (Article = NULL, MessageID = NULL; ; ) {	if (GotAlarm) {	    (void)fprintf(stderr, "Timed out\n");	    /* Don't resend the current article. */	    RequeueRestAndExit((char *)NULL, (char *)NULL);	}	if (GotInterrupt)	    Interrupted(Article, MessageID);	if ((Article = QIOread(BATCHqp)) == NULL) {	    if (QIOerror(BATCHqp)) {		(void)fprintf(stderr, "Can't read \"%s\", %s\n",			BATCHname, strerror(errno));		ExitWithStats(1);	    }	    if (QIOtoolong(BATCHqp)) {		(void)fprintf(stderr, "Skipping long line in \"%s\"\n",			BATCHname);		(void)QIOread(BATCHqp);		continue;	    }	    /* Normal EOF -- we're done. */	    QIOclose(BATCHqp);	    break;	}	/* Split the line into possibly two fields. */	if (Article[0] == '/'	 && Article[STRLEN(SPOOL)] == '/'	 && EQn(Article, SPOOL, STRLEN(SPOOL)))	    Article += STRLEN(SPOOL) + 1;	if ((MessageID = strchr(Article, ' ')) != NULL) {	    *MessageID++ = '\0';	    if (!Slavish) {		if (*MessageID != '<'		 || (p = strrchr(MessageID, '>')) == NULL		 || *++p != '\0') {		    (void)fprintf(stderr, "Ignoring line \"%s %s...\"\n",			Article, MessageID);		    continue;		}		*p = '\0';	    }	}	if (*Article == '\0') {	    (void)fprintf(stderr, "Empty filename for \"%s\" in \"%s\"\n",		    MessageID, BATCHname);	    /* We could do a history lookup. */	    continue;	}	if (Purging && MessageID != NULL && !Expired(MessageID)) {	    Requeue(Article, MessageID);	    continue;	}	/* Open the article. */	if ((qp = QIOopen(Article, QIO_BUFFER)) == NULL	 && AltSpool	 && *Article != '/') {	    (void)sprintf(AltPath, "%s/%s", AltSpool, Article);	    qp = QIOopen(AltPath, QIO_BUFFER);	}	if (qp == NULL) {	    switch (errno) {	    default:		(void)fprintf(stderr, "Requeue \"%s\", %s\n",			Article, strerror(errno));		Requeue(Article, MessageID);		break;	    case ENOENT:		/* Cancelled or expired.  We could look the file up		 * in the history database and see if it does exist. */		break;	    case ENOTDIR:		(void)fprintf(stderr, SKIPPING, Article, "mangled");		break;	    }	    continue;	}	if (Purging) {	    QIOclose(qp);	    Requeue(Article, MessageID);	    continue;	}	/* Get the Message-ID from the article if we need to. */	if (MessageID == NULL) {	    if ((MessageID = GetMessageID(qp)) == NULL) {		(void)fprintf(stderr, SKIPPING, Article, "no Message-ID");		QIOclose(qp);		continue;	    }	    if (QIOrewind(qp) < 0) {		(void)fprintf(stderr, "Can't rewind \"%s\", %s -- requeue\n",			Article, strerror(errno));		QIOclose(qp);		Requeue(Article, (char *)NULL);		continue;	    }	}	if (Mime == TRUE) {	    MimeArticle = MTnotmime;	    GetMimeHeaders(qp, &ContentEncoding, &ContentType);	    if (QIOrewind(qp) < 0) {		(void)fprintf(stderr, "Can't rewind \"%s\", %s -- requeue\n",			Article, strerror(errno));		QIOclose(qp);		Requeue(Article, (char *)NULL);		continue;	    }	    if (ContentEncoding 	     && (caseEQ(ContentEncoding, "binary")	      || caseEQ(ContentEncoding, "8bit")))		if (ContentType == NULL || caseEQ(ContentType, "text"))		    MimeArticle = MTquotedprintable;		else		    /* Shouldbe MTbase64, but not implemented yet. */		    MimeArticle = MTnotmime;	}	if (GotInterrupt)	    Interrupted(Article, MessageID);	/* Offer the article. */	(void)sprintf(buff, "%s %s", Slavish ? "xreplic" : "ihave", MessageID);	if (!REMwrite(buff, (int)strlen(buff))) {	    (void)fprintf(stderr, "Can't offer article, %s\n",		    strerror(errno));	    QIOclose(qp);	    RequeueRestAndExit(Article, MessageID);	}	STAToffered++;	if (Debug)	    (void)fprintf(stderr, "> %s\n", buff);	if (GotInterrupt)	    Interrupted(Article, MessageID);	/* Does he want it? */	if (!REMread(buff, (int)sizeof buff)) {	    (void)fprintf(stderr, "No reply to ihave, %s\n", strerror(errno));	    QIOclose(qp);	    RequeueRestAndExit(Article, MessageID);	}	if (GotInterrupt)	    Interrupted(Article, MessageID);	if (Debug)	    (void)fprintf(stderr, "< %s", buff);	/* Parse the reply. */	switch (atoi(buff)) {	default:	    (void)fprintf(stderr, "Unknown reply to \"%s\" -- %s",		    Article, buff);	    if (DoRequeue)		Requeue(Article, MessageID);	    break;	case NNTP_RESENDIT_VAL:	case NNTP_GOODBYE_VAL:	    /* Most likely out of space -- no point in continuing. */	    syslog(L_NOTICE, IHAVE_FAIL, REMhost, REMclean(buff));	    RequeueRestAndExit(Article, MessageID);	    /* NOTREACHED */	case NNTP_SENDIT_VAL:	    if (!REMsendarticle(Article, MessageID, qp))		RequeueRestAndExit(Article, MessageID);	    break;	case NNTP_SYNTAX_VAL:	case NNTP_HAVEIT_VAL:	    STATrefused++;	    break;#if	defined(NNTP_SENDIT_LATER)	case NNTP_SENDIT_LATER_VAL:	    Requeue(Article, MessageID);	    break;#endif	/* defined(NNTP_SENDIT_LATER) */	}	QIOclose(qp);    }    if (BATCHfp != NULL)	/* We requeued something, so close the temp file. */	CloseAndRename();    else if (unlink(BATCHname) < 0 && errno != ENOENT)	(void)fprintf(stderr, "Can't remove \"%s\", %s\n",		BATCHtemp, strerror(errno));    ExitWithStats(0);    /* NOTREACHED */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -