📄 innxmit.c
字号:
} 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 + -