int main( int argc, char **argv ) { npost_param_t param; int ret = npost_parse( argc, argv, ¶m ); if ( ret < 0 ) { printf( "Error parsing commandline arguments.\n" ); exit(1); } // First try to make just one connection, and see if it fails int testfd = 0; signal( SIGPIPE, SIG_IGN ); ret = nntp_connect( &testfd, param.server, param.port, param.username, param.password ); if( ret == CONNECT_FAILURE ) { printf( "Failed to make even a single connection! Exiting...\n" ); return -1; } nntp_logoff( &testfd ); // Initialize a handle to be used by the threads npost_t h; memcpy( &h, ¶m, sizeof(npost_param_t) ); h.threads = NULL; h.head = NULL; h.tail = NULL; h.mut = malloc( sizeof(pthread_mutex_t) ); pthread_mutex_init( h.mut, NULL); h.cond_list_empty = malloc( sizeof(pthread_cond_t) ); pthread_cond_init( h.cond_list_empty, NULL ); // Let's add parts to the queue! size_t blocksize = YENC_LINE_LENGTH * param.lines; for( int f = 0; f < param.n_split_files; f++ ) { diskfile_t *df = ¶m.split_files[f]; crc32_file( df ); int parts = (param.split_files[f].filesize + blocksize - 1) / blocksize; for( int p = 0; p < parts; p++ ) { if( h.head == NULL ) { h.head = malloc( sizeof(npost_item_t) ); h.tail = h.head; } else { h.tail->next = malloc( sizeof(npost_item_t) ); h.tail = h.tail->next; } h.tail->filenum = f; h.tail->partnum = p; h.tail->next = NULL; } } // Initialize the threads, and give each thread its own copy of the handle h.threads = malloc( param.threads * sizeof(pthread_t) ); for ( int i = 0; i < param.threads; i++ ) pthread_create( &h.threads[i], NULL, poster_thread, &h ); for( int i = 0; i < param.threads; i++ ) pthread_join( h.threads[i], NULL ); // free all the mallocs! free( h.threads ); pthread_mutex_destroy( h.mut ); free( h.mut ); pthread_cond_destroy( h.cond_list_empty ); free( h.cond_list_empty ); free( param.server ); free( param.username ); free( param.password ); free( param.name ); free( param.email ); free( param.newsgroups ); free( param.comment ); for ( int i = 0; i < param.n_input_files; i++ ) { free( param.input_files[i].filename_in ); free( param.input_files[i].filename_out ); } free( param.input_files ); for ( int i = 0; i < param.n_split_files; i++ ) { free( param.split_files[i].filename_in ); free( param.split_files[i].filename_out ); } free( param.split_files ); return 0; }
/* * Scan for new news available at the nntp server. */ void ScanNews(void) { List *art = NULL; POverview tmp, old; FILE *pAreas; char *sAreas; struct msgareashdr Msgshdr; struct msgareas Msgs; IsDoing((char *)"Scan News"); if (nntp_connect() == -1) { WriteError("Can't connect to newsserver"); return; } if (get_xoverview()) { return; } if (!do_quiet) { mbse_colour(LIGHTGREEN, BLACK); printf("Scan for new news articles\n"); } sAreas = calloc(PATH_MAX, sizeof(char)); snprintf(sAreas, PATH_MAX, "%s/etc/mareas.data", getenv("MBSE_ROOT")); if(( pAreas = fopen (sAreas, "r")) == NULL) { WriteError("$Can't open Messages Areas File."); return; } fread(&Msgshdr, sizeof(Msgshdr), 1, pAreas); while (fread(&Msgs, Msgshdr.recsize, 1, pAreas) == 1) { fseek(pAreas, Msgshdr.syssize, SEEK_CUR); #ifdef USE_NEWSGATE if ((Msgs.Active) && strlen(Msgs.Newsgroup)) { #else if ((Msgs.Active) && strlen(Msgs.Newsgroup) && (Msgs.Type == NEWS)) { #endif if (IsSema((char *)"upsalarm")) { Syslog('+', "Detected upsalarm semafore, aborting newsscan"); break; } Syslog('m', "Scan newsgroup: %s", Msgs.Newsgroup); if (!do_quiet) { mbse_colour(CYAN, BLACK); printf("\r%-40s", Msgs.Newsgroup); fflush(stdout); } Nopper(); if (do_one_group(&art, Msgs.Newsgroup, Msgs.Tag, Msgs.MaxArticles) == RETVAL_ERROR) break; /* * To be safe, update the dupes database after each area. */ CloseDupes(); } } fclose(pAreas); free(sAreas); for (tmp = xoverview; tmp; tmp = old) { old = tmp->next; if (tmp->header) free(tmp->header); if (tmp->field) free(tmp->field); free(tmp); } nntp_close(); do_flush = TRUE; if (!do_quiet) printf("\r \r"); } int do_one_group(List **art, char *grpname, char *ftntag, int maxarticles) { List *tmp; char temp[128], *resp; int retval, fetched = 0; int total, start, end; Syslog('m', "do_one_group(%s, %s)", grpname, ftntag); IsDoing((char *)"Scan %s", grpname); snprintf(temp, 128, "GROUP %s\r\n", grpname); nntp_send(temp); resp = nntp_receive(); retval = atoi(strtok(resp, " ")); if (retval == 480) { /* * We must login */ if (nntp_auth() == FALSE) { WriteError("Authorisation failure"); nntp_close(); return RETVAL_NOAUTH; } nntp_send(temp); resp = nntp_receive(); retval = atoi(strtok(resp, " ")); } if (retval != 211) { if (retval == 411) { WriteError("No such newsgroup: %s", grpname); return RETVAL_UNEXPECTEDANS; } WriteError("Unknown response %d to GROUP command", retval); return RETVAL_ERROR; } total = atol(strtok(NULL, " ")); start = atol(strtok(NULL, " ")); end = atol(strtok(NULL, " '\0'")); Syslog('m', "GROUP total %d, start %d, end %d, max %d", total, start, end, maxarticles); if ((maxarticles) && (total > maxarticles)) { start = end - maxarticles; total = maxarticles; Syslog('m', "NEW: total %d, start %d, end %d", total, start, end); } if (!total) { Syslog('+', "Fetched 0 articles from %s", grpname); return RETVAL_NOARTICLES; } retval = get_xover(grpname, start, end, art); if (retval != RETVAL_OK) { tidy_artlist(art); return retval; } if (!do_learn) { for (tmp = *art; tmp; tmp = tmp->next) { if (!tmp->isdupe) { /* * If the message isn't a dupe, it must be new for us. */ get_article(tmp->msgid, ftntag); fetched++; } } } tidy_artlist(art); if ((maxarticles) && (fetched == maxarticles)) Syslog('!', "Warning: the max. articles value in newsgroup %s might be to low", grpname); Syslog('+', "Fetched %d article%s from %s", fetched, (fetched == 1) ? "":"s", grpname); return RETVAL_OK; }
void * poster_thread( void *arg ) { npost_t *h = (npost_t *)arg; // Allocate buffers char *buffer; int ret; npost_item_t *item; int sockfd = -1; while( 1 ) { // Connect when necessary while( sockfd <= 0 ) { ret = nntp_connect( &sockfd, h->param.server, h->param.port, h->param.username, h->param.password ); if( ret == CONNECT_FAILURE ) return NULL; else if (ret == CONNECT_TRY_AGAIN_LATER ) { ret = conditional_sleep( h ); if( ret == 0 ) // Article list is empty return NULL; } } // Get an article to post pthread_mutex_lock(h->mut); item = h->head; if( h->head == NULL ) { // We're done pthread_cond_broadcast( h->cond_list_empty ); pthread_mutex_unlock(h->mut); break; } h->head = h->head->next; pthread_mutex_unlock(h->mut); // Post the article printf( "**** Posting! sockfd: %2d, filenum: %2d, partnum: %3d *****\n", sockfd, item->filenum, item->partnum ); size_t bytes_to_post = npost_get_part( &h->param, item->filenum, item->partnum, &buffer ); ret = nntp_post( sockfd, buffer, bytes_to_post ); free( buffer ); if( ret < 0 ) { // Put the article back in the queue as something went wrong item->next = NULL; pthread_mutex_lock(h->mut); if( h->head == NULL ) h->head = item; else h->tail->next = item; h->tail = item; pthread_mutex_unlock(h->mut); } // Depending on what went wrong, we either try again later, or kill ourselves if( ret == POST_TRY_LATER ) { nntp_logoff( tid, &sockfd ); int retval = conditional_sleep( h ); if( retval == 0 ) // Article list is empty return NULL; } else if ( ret == POST_FATAL_ERROR ) return NULL; // If posting went succesfully, free this item if( ret == 0 ) free( item ); } nntp_logoff( &sockfd ); return NULL; }