void plD_state_xfig(PLStream *pls, PLINT op) { switch (op) { case PLSTATE_WIDTH: flushbuffer(pls); firstline = 1; curwid = pls->width < 1 ? 1: pls->width; break; case PLSTATE_COLOR0: flushbuffer(pls); curcol = pls->icol0 + XFIG_COLBASE; break; case PLSTATE_COLOR1: flushbuffer(pls); curcol = pls->icol1 + XFIG_COLBASE + pls->ncol0; break; case PLSTATE_CMAP0: stcmap0(pls); break; case PLSTATE_CMAP1: stcmap1(pls); break; } }
void bufwrite1(char *p, int n){ for( ; --n >= 0; ){ if(&buffer[N] == bufptr) flushbuffer(); *bufptr++ = *p++; } }
void plD_tidy_xfig(PLStream *pls) { flushbuffer(pls); free((void *) buffptr); fclose(pls->OutFile); }
void plD_bop_xfig(PLStream *pls) { PLDev *dev = (PLDev *) pls->dev; dev->xold = PL_UNDEFINED; dev->yold = PL_UNDEFINED; firstline = 1; if (!pls->termin) plGetFam(pls); pls->famadv = 1; pls->page++; offset += offset_inc; flushbuffer(pls); /* create background FIXME -- sync with orientation in header and pls->diorot */ curcol = XFIG_COLBASE; /* colormap entry 0, background */ fprintf(pls->OutFile, "2 1 0 1 %d %d 50 0 20 0.0 0 0 -1 0 0 5\n", curcol, curcol ); fprintf(pls->OutFile, "%d %d %d %d %d %d %d %d %d %d\n", 0, offset, 0, (int) (FIGY * dev->yscale_dev) + offset, (int) (FIGX * dev->xscale_dev), (int) (FIGY * dev->yscale_dev) + offset, (int) (FIGX * dev->xscale_dev), offset, 0, offset); }
void plD_esc_xfig(PLStream *pls, PLINT op, void *ptr) { PLDev *dev = pls->dev; int i, npts; switch (op) { case PLESC_FILL: npts = pls->dev_npts; if (npts > PL_MAXPOLY) plexit("FillPolygonCmd: Too many points in polygon\n"); flushbuffer(pls); fprintf(pls->OutFile, "2 1 0 1 %d %d 50 0 20 0.0 0 0 0 0 0 %d\n", curcol, curcol, npts); for (i = 0; i < npts; i++) fprintf(pls->OutFile,"%d %d ", pls->dev_x[i], offset + dev->ymax * (int)dev->xscale_dev - pls->dev_y[i]); fprintf(pls->OutFile, "\n"); break; case PLESC_HAS_TEXT: proc_str(pls, ptr); break; } }
void plD_line_ntk(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { if (xold == x1a && yold == y1a) { xold = xb[curpts] = x2a; yold = yb[curpts] = y2a; curpts++; } else { flushbuffer(pls); xb[curpts] = x1a; yb[curpts] = y1a; curpts++; xold = xb[curpts] = x2a; yold = yb[curpts] = y2a; curpts++; } if (curpts == NPTS) { fprintf(stderr,"\nflush: %d ", curpts); flushbuffer(pls); } }
static void output_rendered_buffer(char *buffer) { /* Output to stdout only if -q param is not specified */ if (quiet_level == MAX_LOGLEVEL) flushbuffer(buffer, stdout); /* Exit if should not continue at all. */ if (logging == TRUE) { FILE *log_handle; log_handle = find_logfile_handle(); if (log_handle != NULL) { strip_ansi(buffer); flushbuffer(buffer, log_handle); } } }
void send_fileheader(int sid, int cacheable, int status, char *title, char *extra_header, char *mime_type, int length, time_t mod) { char timebuf[100]; time_t now; if (status) { conn[sid].dat->out_status=status; } else { conn[sid].dat->out_status=200; } if (strcasestr(conn[sid].dat->in_Protocol, "HTTP/1.1")!=NULL) { snprintf(conn[sid].dat->out_Protocol, sizeof(conn[sid].dat->out_Protocol)-1, "HTTP/1.1"); } else { snprintf(conn[sid].dat->out_Protocol, sizeof(conn[sid].dat->out_Protocol)-1, "HTTP/1.0"); } if (strcasecmp(conn[sid].dat->in_Connection, "Keep-Alive")==0) { snprintf(conn[sid].dat->out_Connection, sizeof(conn[sid].dat->out_Connection)-1, "Keep-Alive"); } else { snprintf(conn[sid].dat->out_Connection, sizeof(conn[sid].dat->out_Connection)-1, "Close"); } // Nutscrape and Mozilla don't know what a f*****g keepalive is if ((strcasestr(conn[sid].dat->in_UserAgent, "MSIE")==NULL)) { snprintf(conn[sid].dat->out_Connection, sizeof(conn[sid].dat->out_Connection)-1, "Close"); } prints("%s %d OK\r\n", conn[sid].dat->out_Protocol, conn[sid].dat->out_status); prints("Connection: %s\r\n", conn[sid].dat->out_Connection); prints("Server: %s\r\n", SERVER_NAME); if ((length>=0)&&(status!=304)) { prints("Content-Length: %d\r\n", length); } now=time((time_t*)0); strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now)); prints("Date: %s\r\n", timebuf); if (mod!=(time_t)-1) { strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&mod)); prints("Last-Modified: %s\r\n", timebuf); } if (cacheable) { now=time((time_t*)0)+604800; strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now)); prints("Expires: %s\r\n", timebuf); prints("Cache-Control: public\r\n"); prints("Pragma: public\r\n"); } else { now=time((time_t*)0); strftime(timebuf, sizeof(timebuf), RFC1123FMT, gmtime(&now)); prints("Expires: %s\r\n", timebuf); prints("Cache-Control: no-store\r\n"); prints("Pragma: no-cache\r\n"); } if (extra_header!=(char*)0) { prints("Content-Type: %s\r\n\r\n", mime_type); } else { prints("Content-Type: text/html\r\n\r\n"); } conn[sid].dat->out_headdone=1; flushbuffer(sid); }
void clear() { int i; for (i = 0; i < MAXLEDS; i++) { ledbuffer[i].r = 0; ledbuffer[i].g = 0; ledbuffer[i].b = 0; } flushbuffer(); usleep(800); }
void plD_state_ntk(PLStream *pls, PLINT op) { switch (op) { case PLSTATE_COLOR0: case PLSTATE_COLOR1: flushbuffer(pls); sprintf(curcolor, "#%02x%02x%02x", pls->curcolor.r, pls->curcolor.g , pls->curcolor.b); break; } }
void printerror(int sid, int status, char* title, char* text) { send_header(sid, 0, 200, "OK", "1", "text/html", -1, -1); prints("<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n", status, title); prints("<BODY BGCOLOR=#F0F0F0 TEXT=#000000 LINK=#0000FF ALINK=#0000FF VLINK=#0000FF>\n"); prints("<H1>%d %s</H1>\n", status, title); prints("%s\n", text); prints("<HR>\n<ADDRESS>%s</ADDRESS>\n</BODY></HTML>\n", SERVER_NAME); conn[sid].dat->out_bodydone=1; flushbuffer(sid); closeconnect(sid, 1); return; }
void bufwrite2(char *p, int n){ for(;n > 0;){ int k, rem; if(bufptr == &(buffer[N])) flushbuffer(); rem = N - (bufptr - buffer); k = n > rem? rem: n; memcpy(bufptr, p, k); bufptr += k; p += k; n -= k; } }
/* * function: report() * purpose: to report a packet * recieves: the source ip, the destination ip, the prefix number * the packet type */ void report(unsigned int src, unsigned int dst, unsigned char type, unsigned short srcport, unsigned short dstport) { if ((src & NETMASK) == NETBASE) { buffer->data[buffer->count].local = src & ~NETMASK; buffer->data[buffer->count].remote = dst; buffer->data[buffer->count].incoming = 0; if (type == 6 || type == 17) { buffer->data[buffer->count].localport = srcport; buffer->data[buffer->count].remoteport = dstport; } } else if ((dst & NETMASK) == NETBASE) { buffer->data[buffer->count].local = dst & ~NETMASK; buffer->data[buffer->count].remote = src; buffer->data[buffer->count].incoming = 1; if (type == 6 || type == 17) { buffer->data[buffer->count].localport = dstport; buffer->data[buffer->count].remoteport = srcport; } } else /* ignore the packet */ return; if (type == 6) //tcp buffer->data[buffer->count].packet = TCP; else if (type == 17) buffer->data[buffer->count].packet = UDP; else { buffer->data[buffer->count].packet = OTHER; buffer->data[buffer->count].localport = 0; buffer->data[buffer->count].remoteport = 0; } //* printf("saw flow from xx.xx.%i.%i\n", (buffer->data[buffer->count].local & 0x0000ff00) >> 8, buffer->data[buffer->count].local & 0x000000ff); // */ buffer->count++; if (buffer->count >= MAXINDEX || lastupdate + MINRATE < gettime()) flushbuffer(); }
void ctrl_icecrystals(int secs) { int nsdelay = 1000000/60; time_t start = time(NULL); time_t now; IceCrystalsMode ice(MAXLEDS); ice.init(); time(&start); while (1) { ice.loop(&ledbuffer[0]); flushbuffer(); now = time(NULL); if (start + secs < now) break; usleep(nsdelay); } }
void ctrl_twocolorwave(int secs, struct rgb background, struct rgb wave) { int nsdelay = 1000000/60; time_t start = time(NULL); time_t now; TwoColorWave red(MAXLEDS); red.init(background, wave); time(&start); while (1) { red.loop(&ledbuffer[0]); flushbuffer(); now = time(NULL); if (start + secs < now) break; usleep(nsdelay); } }
void plD_line_xfig(PLStream *pls, short x1a, short y1a, short x2a, short y2a) { PLDev *dev = (PLDev *) pls->dev; int xx1 = x1a, yy1 = y1a, xx2 = x2a, yy2 = y2a; short *tempptr; /* If starting point of this line is the same as the ending point of */ /* the previous line then don't raise the pen. (This really speeds up */ /* plotting and reduces the size of the file. */ if (firstline) { count = 0; *(buffptr + count++) = xx1; *(buffptr + count++) = yy1; *(buffptr + count++) = xx2; *(buffptr + count++) = yy2; firstline = 0; } else if (xx1 == dev->xold && yy1 == dev->yold) { if (count + 2 >= bufflen) { bufflen += 2 * BSIZE; tempptr = (short *) realloc((void *) buffptr, bufflen * sizeof(short)); if (tempptr == NULL) { free((void *) buffptr); plexit("Out of memory!"); } buffptr = tempptr; } *(buffptr + count++) = xx2; *(buffptr + count++) = yy2; } else { flushbuffer(pls); *(buffptr + count++) = xx1; *(buffptr + count++) = yy1; *(buffptr + count++) = xx2; *(buffptr + count++) = yy2; } dev->xold = xx2; dev->yold = yy2; }
void xp1(int *nerr) { int n; char *kptext, kret[9]; int l1dttm, lany, lbotaxsave, lbottcsave, lframesave, ltitlsave, ltoptcsave, lwait, lxgrdsave, lxlabsave, lxlims, lylabsave, lprint = FALSE , ltry = FALSE ; int i, jdfl, jdfl1, jdfl2, jfr, jperfr, n1dttm[6], ncret, nfr, nlcx, nlcy, nperfr, num, notused; float tmax, tmaxj, tmin, tminj, toff[MDFL], ypdel, ypmxsave; static int lrel = FALSE; static int lperpl = FALSE; static int nperpl = 3; static char kwait[9] = "Waiting$"; float *const Toff = &toff[0] - 1; /*===================================================================== * PURPOSE: To execute the action command P1. * This command makes a multi-trace, multi-window plot. *===================================================================== * OUTPUT ARGUMENTS: * nerr: Error return flag. Set to 0 if no error occurred. * Potential error numbers: 1001, 1504. *===================================================================== * MODULE/LEVEL: gam/2 *===================================================================== * GLOBAL INPUT: * mach: * dfm: ndfl, sacmem * hdr: begin, ennd, delta * gem: lbotax, lbottc, ltopax, ltoptc, lxlab, lylab, ltitl, * lxgrd, ypmn, ypmx, chht, tsdef * gam: kgddef *===================================================================== * SUBROUTINES CALLED: *===================================================================== * MODIFICATION HISTORY: * 970908: Modified response to ddttm. maf * 970723: Commented out an if statement to fix a bug which kept * p1 relative from functioning when xlim was set. maf * 970130: Added arguments to dispid() to plot file number. maf * 910607: Move stmt label 8888 back to where it was. * Changed gots to goto plrest after call to plsave. * Error condition before lframesave goes to return. (wct). * 910607: Added call to zgetgd when no graphics device specified. * Changed call to begindevice to begindevices. (wct) * 910220: Move stmt label 8888, so lframe etc. are restored on err exit * 880411: Axes annotation now controlled by GEM variables. * 850321: Now displaying REL offset below FILEID. * 821228: Added calls to DISPID, DISPPK and PLHOME. * 821122: Added check for bad date fields. * Fixed bug involving titles and PP option. * 820823: Fixed bug involving extra x axes when using PP option. * 820721: Changed to newest set of parsing and checking functions. * 811228: Deleted call to ZCLIP. * 810120: Changed to output message retrieval from disk. * 800920: Added PERPLOT option. * Fixed bug in REL/ABS option. * 800905: Pick and file id options to new DISPLAY command. * 800618: Added pick display capability to this plot. *===================================================================== * DOCUMENTED/REVIEWED: *===================================================================== */ /* PROCEDURE: */ /* Errors before plsave have to avoid going to execute plrest. */ *nerr = 0; /* PARSING PHASE: */ /* - Loop on each token in command: */ while ( lcmore( nerr ) ){ /* -- "PERPLOT ON/OFF/n": change number of files plotted per frame. */ if( lklogi( "PERPLOT$",9, &lperpl, &nperpl ) ) { /* do nothing */ } /* -- "RELATIVE/ABSOLUTE": change method of displaying time on x axis. */ else if( lclog2( "RELATIVE$",10, "ABSOLUTE$",10, &lrel ) ) { /* do nothing */ } /* if PRINT option is tried, get printer name */ else if ( ltry ) { lcchar ( MAXPRNTRNAMELEN , kmgem.kptrName , MAXPRNTRNAMELEN+1 , ¬used ) ; terminate ( kmgem.kptrName ) ; if ( !lprint ) kmgem.kptrName[0] = '\0' ; ltry = FALSE ; } /* -- "PRINT": print the final product */ else if( lckey( "PRINT#$", 8 ) ) { ltry = TRUE ; if ( cmgdm.lbegf ) { setmsg ( "WARNING" , 2403 ) ; outmsg () ; clrmsg () ; } else { lprint = TRUE ; } } /* -- Bad syntax. */ else{ cfmt( "ILLEGAL OPTION:",17 ); cresp(); } } /* end while */ /* - The above loop is over when one of two conditions has been met: * (1) An error in parsing has occurred. In this case NERR is > 0 . * (2) All the tokens in the command have been successfully parsed. */ if( *nerr != 0 ) goto L_8888; /* CHECKING PHASE: */ /* - Check for null data file list. */ vflist( nerr ); if( *nerr != 0 ) goto L_8888; /* - Check to make sure all files are time series files. */ vftime( nerr ); if( *nerr != 0 ){ aplmsg( "Use PLOTSP command to plot spectral data.",42 ); goto L_8888; } /* - If no graphics device is open, try to open the default device. */ getstatus( "ANY", &lany ); if( !lany ){ zgetgd( kmgam.kgddef,9 ); begindevices( kmgam.kgddef,9, 1, nerr ); if( *nerr != 0 ) goto L_8888; } /* EXECUTION PHASE: */ /* - Save current plot and x limit attributes. * - Error after plsave have to go to execute plrest. */ plsave(); /* initialize plot offsets */ for ( i=0; i<MDFL; i++) toff[i] = 0.0; /* - Set up specific options that apply only to this plot. */ lbotaxsave = cmgem.axis[BOTTOM].annotate; lbottcsave = cmgem.axis[BOTTOM].ticks; ltoptcsave = cmgem.axis[TOP].ticks; cmgem.axis[BOTTOM].ticks = FALSE; cmgem.axis[BOTTOM].annotate = FALSE; lxlabsave = cmgem.xlabel.on; lylabsave = cmgem.ylabel.on; ltitlsave = cmgem.title.on; lxgrdsave = cmgem.lxgrd; cmgem.xlabel.on = FALSE; cmgem.ylabel.on = FALSE; cmgem.title.on = FALSE; cmgem.lxgrd = FALSE; /* - Set up y window for each subplot. */ if( lperpl ){ nfr = (cmdfm.ndfl - 1)/nperpl + 1; nperfr = nperpl; } else{ nfr = 1; nperfr = cmdfm.ndfl; } ypdel = (cmgem.plot.ymax - cmgem.plot.ymin)/(float)( nperfr ); /* - Check WAIT option. This is on when: * -- A wait request has been made. * -- An active device (normally the user's terminal) is on. */ if( cmgam.lwaitr ) getstatus( "ACTIVE", &lwait ); else lwait = FALSE; /* - Loop on number of frames: */ jdfl1 = 1; ypmxsave = cmgem.plot.ymax; lframesave = cmgem.lframe; for( jfr = 1; jfr <= nfr; jfr++ ){ /* set cmgem.lframe FALSE for each pass through loop, because endframe() sets it back to TRUE for the next pass. */ cmgem.lframe = FALSE; /* -- No wait after last frame. */ if( jfr == nfr && !cmgam.lwaite ) lwait = FALSE; /* -- Loop on data files in each frame: */ jdfl2 = min( cmdfm.ndfl, jdfl1 + nperfr - 1 ); /* -- Determine time limits for x axis of this frame. * (Correct for any differences in GMT reference time.) */ getfil( jdfl1, TRUE, &num, &nlcy, &nlcx, nerr ); if( *nerr != 0 ) goto L_7777; jperfr = 1; getxlm( &lxlims, &tmin, &tmax ); /* if( !lxlims ){ commented out to allow relative mode when xlim is set. maf 970723 */ if( lrel ){ tmax = tmax - tmin; Toff[jperfr] = -tmin; tmin = 0.; } else{ copyi( nzdttm, n1dttm, 6 ); l1dttm = ldttm( n1dttm ); Toff[jperfr] = 0.; } for( jdfl = jdfl1 + 1; jdfl <= jdfl2; jdfl++ ){ jperfr = jperfr + 1; getfil( jdfl, TRUE, &num, &nlcy, &nlcx, nerr ); if( *nerr != 0 ) goto L_7777; getxlm( &lxlims, &tminj, &tmaxj ); if( lrel ){ tmax = fmax( tmax, tmaxj - tminj ); Toff[jperfr] = -tminj; } else{ if( l1dttm && ldttm( nzdttm ) ){ ddttm( nzdttm, n1dttm, &Toff[jperfr] ); /* if it starts 2 days after the first file, plot relative. maf 970908 */ if ( fabs ( Toff[jperfr] ) > TWODAYS ) Toff[jperfr] = 0 ; } else{ Toff[jperfr] = 0.; } tmin = fmin( tmin, tminj + Toff[jperfr] ); tmax = fmax( tmax, tmaxj + Toff[jperfr] ); } /* end else associated with if ( lrel ) */ } /* end for( jdfl = jdfl1 + 1; jdfl <= jdfl2; jdfl++ ) */ /* } end if ( !lxlims ) commented out to allow relative mode when xlim is set. maf 970723 */ /* - Check range of time limits to avoid errors that could occur * later during plotting. * if( fabs( tmax - tmin ) > (float)( MLARGE ) ){ *nerr = 1504; setmsg( "ERROR", *nerr ); goto L_7777; } */ /* - Set x axis plot limits. */ cmgem.lxlim = TRUE; cmgem.ximn = tmin; cmgem.ximx = tmax; if( lframesave ){ beginframe( lprint , nerr ); if( *nerr != 0 ) goto L_7777; getvspace( &cmgem.view.xmin, &cmgem.view.xmax, &cmgem.view.ymin, &cmgem.view.ymax ); } jperfr = 0; cmgem.tsdef = fmin( cmgem.tsdef, (cmgem.view.ymax - cmgem.view.ymin)/(8.0* (float)( nperfr )) ); cmgam.tsfid = cmgem.tsdef; cmgam.tspk = cmgem.tsdef; cmgem.tsaxis = cmgem.tsdef; for( jdfl = jdfl1; jdfl <= jdfl2; jdfl++ ){ jperfr = jperfr + 1; cmgem.plot.ymin = cmgem.plot.ymax - ypdel; /* --- Get pointers to this file's location in memory. */ getfil( jdfl, TRUE, &num, &nlcy, &nlcx, nerr ); if( *nerr != 0 ) goto L_7777; /* --- Set up x axis data values. */ if( *leven ){ cmgem.xgen.on = TRUE; cmgem.xgen.delta = *delta; cmgem.xgen.first = *begin + Toff[jperfr]; } else{ cmgem.xgen.on = FALSE; } /* --- Set up y axis plot limits. */ getylm( &cmgem.lylim, &cmgem.yimn, &cmgem.yimx ); /* --- Plot this file. */ pl2d( cmmem.sacmem[nlcx], cmmem.sacmem[nlcy], num, 1, 1, nerr ); if( *nerr != 0 ) goto L_7777; /* --- Plot picks and fileid. */ disppk( Toff[jperfr] ); /* --- Add a label with offset time if this is a REL plot. */ kptext = NULL; n = 0; if( lrel && cmgam.lfidrq ){ asprintf(&kptext, "OFFSET: %10.3e", -Toff[jperfr] ); n = 1; } dispid( cmgam.lfinorq , jdfl, n, &kptext ); if(kptext) { free(kptext); kptext = NULL; } cmgem.plot.ymax = cmgem.plot.ymin; } /* -- Draw bottom x axis. */ cmgem.axis[BOTTOM].annotate = lbotaxsave; cmgem.axis[BOTTOM].ticks = lbottcsave; cmgem.axis[TOP].ticks = ltoptcsave; cmgem.lxgrd = lxgrdsave; cmgem.uplot.ymax = ypmxsave*cmgem.view.ymax; cmgem.chht = cmgem.tsaxis; cmgem.chwid = cmgem.txrat*cmgem.chht; settextsize( cmgem.chwid, cmgem.chht ); if( cmgem.ixint == AXIS_LINEAR ){ xlinax(); } else if( cmgem.ixint == AXIS_LOG ){ xlogax(); } /* -- Draw axes labels and title. */ if( lxlabsave ) centxt( kmgem.kxlab,145, cmgem.xlabel.len, cmgem.xlabel.pos, cmgem.xlabel.text_size ); if( lylabsave ) centxt( kmgem.kylab,145, cmgem.ylabel.len, cmgem.ylabel.pos, cmgem.ylabel.text_size ); if( ltitlsave ) centxt( kmgem.ktitl,145, cmgem.title.len, cmgem.title.pos, cmgem.title.text_size ); /* -- Home cursor, advance frame and restore some GEM parameters. */ plhome(); if( lframesave ) endframe( FALSE , nerr ); else flushbuffer( nerr ); cmgem.plot.ymax = ypmxsave; cmgem.axis[BOTTOM].annotate = FALSE; cmgem.axis[BOTTOM].ticks = FALSE; /* -- Wait for user prompt before plotting next frame if appropriate. */ if( lwait ){ zgpmsg( kwait,9, kret,9 ); ncret = indexb( kret,9 ); upcase( kret, ncret, kret,9 ); if( kret[0] == 'K' ) goto L_7777; if( kret[0] == 'G' ) lwait = FALSE; } jdfl1 = jdfl2 + 1; } /* end for ( jfr ) */ /* - Restore plot and x limit attributes. Return. */ L_7777: plrest(); cmgam.tsfid = cmgem.tsdef; cmgam.tspk = cmgem.tsdef; cmgem.tsaxis = cmgem.tsdef; cmgem.plot.ymax = ypmxsave; cmgem.axis[BOTTOM].annotate = lbotaxsave; cmgem.axis[BOTTOM].ticks = lbottcsave; cmgem.lframe = lframesave; L_8888: return; } /* end of function */
int dcc_process(uschar **listptr) { int sep = 0; uschar *list = *listptr; FILE *data_file; uschar *dcc_daemon_ip = US""; uschar *dcc_default_ip_option = US"127.0.0.1"; uschar *dcc_ip_option = US""; uschar *dcc_helo_option = US"localhost"; uschar *dcc_reject_message = US"Rejected by DCC"; uschar *xtra_hdrs = NULL; /* from local_scan */ int i, j, k, c, retval, sockfd, resp, line; unsigned int portnr; struct sockaddr_un serv_addr; struct sockaddr_in serv_addr_in; struct hostent *ipaddress; uschar sockpath[128]; uschar sockip[40], client_ip[40]; uschar opts[128]; uschar rcpt[128], from[128]; uschar sendbuf[4096]; uschar recvbuf[4096]; uschar dcc_return_text[1024]; uschar mbox_path[1024]; uschar message_subdir[2]; struct header_line *dcchdr; uschar *dcc_acl_options; uschar dcc_acl_options_buffer[10]; uschar dcc_xtra_hdrs[1024]; /* grep 1st option */ if ((dcc_acl_options = string_nextinlist(&list, &sep, dcc_acl_options_buffer, sizeof(dcc_acl_options_buffer))) != NULL) { /* parse 1st option */ if ( (strcmpic(dcc_acl_options,US"false") == 0) || (Ustrcmp(dcc_acl_options,"0") == 0) ) { /* explicitly no matching */ return FAIL; }; /* special cases (match anything except empty) */ if ( (strcmpic(dcc_acl_options,US"true") == 0) || (Ustrcmp(dcc_acl_options,"*") == 0) || (Ustrcmp(dcc_acl_options,"1") == 0) ) { dcc_acl_options = dcc_acl_options; }; } else { /* empty means "don't match anything" */ return FAIL; }; sep = 0; /* if we scanned this message last time, just return */ if ( dcc_ok ) return dcc_rc; /* open the spooled body */ message_subdir[1] = '\0'; for (i = 0; i < 2; i++) { message_subdir[0] = (split_spool_directory == (i == 0))? message_id[5] : 0; sprintf(CS mbox_path, "%s/input/%s/%s-D", spool_directory, message_subdir, message_id); data_file = Ufopen(mbox_path,"rb"); if (data_file != NULL) break; }; if (data_file == NULL) { /* error while spooling */ log_write(0, LOG_MAIN|LOG_PANIC, "dcc acl condition: error while opening spool file"); return DEFER; }; /* Initialize the variables */ bzero(sockip,sizeof(sockip)); if (dccifd_address) { if (dccifd_address[0] == '/') Ustrncpy(sockpath, dccifd_address, sizeof(sockpath)); else if( sscanf(CS dccifd_address, "%s %u", sockip, &portnr) != 2) { log_write(0, LOG_MAIN, "dcc acl condition: warning - invalid dccifd address: '%s'", dccifd_address); (void)fclose(data_file); return DEFER; } } /* opts is what we send as dccifd options - see man dccifd */ /* We don't support any other option than 'header' so just copy that */ bzero(opts,sizeof(opts)); Ustrncpy(opts, "header", sizeof(opts)-1); Ustrncpy(client_ip, dcc_ip_option, sizeof(client_ip)-1); /* If the dcc_client_ip is not provided use the * sender_host_address or 127.0.0.1 if it is NULL */ DEBUG(D_acl) debug_printf("my_ip_option = %s - client_ip = %s - sender_host_address = %s\n", dcc_ip_option, client_ip, sender_host_address); if(!(Ustrcmp(client_ip, ""))){ /* Do we have a sender_host_address or is it NULL? */ if(sender_host_address){ Ustrncpy(client_ip, sender_host_address, sizeof(client_ip)-1); } else { /* sender_host_address is NULL which means it comes from localhost */ Ustrncpy(client_ip, dcc_default_ip_option, sizeof(client_ip)-1); } } DEBUG(D_acl) debug_printf("Client IP: %s\n", client_ip); Ustrncpy(sockip, dcc_daemon_ip, sizeof(sockip)-1); /* strncat(opts, my_request, strlen(my_request)); */ Ustrcat(opts, "\n"); Ustrncat(opts, client_ip, sizeof(opts)-Ustrlen(opts)-1); Ustrncat(opts, "\nHELO ", sizeof(opts)-Ustrlen(opts)-1); Ustrncat(opts, dcc_helo_option, sizeof(opts)-Ustrlen(opts)-2); Ustrcat(opts, "\n"); /* initialize the other variables */ dcchdr = header_list; /* we set the default return value to DEFER */ retval = DEFER; bzero(sendbuf,sizeof(sendbuf)); bzero(dcc_header_str,sizeof(dcc_header_str)); bzero(rcpt,sizeof(rcpt)); bzero(from,sizeof(from)); /* send a null return path as "<>". */ if (Ustrlen(sender_address) > 0) Ustrncpy(from, sender_address, sizeof(from)); else Ustrncpy(from, "<>", sizeof(from)); Ustrncat(from, "\n", sizeof(from)-Ustrlen(from)-1); /************************************** * Now creating the socket connection * **************************************/ /* If there is a dcc_daemon_ip, we use a tcp socket, otherwise a UNIX socket */ if(Ustrcmp(sockip, "")){ ipaddress = gethostbyname((char *)sockip); bzero((char *) &serv_addr_in, sizeof(serv_addr_in)); serv_addr_in.sin_family = AF_INET; bcopy((char *)ipaddress->h_addr, (char *)&serv_addr_in.sin_addr.s_addr, ipaddress->h_length); serv_addr_in.sin_port = htons(portnr); if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) < 0){ DEBUG(D_acl) debug_printf("Creating socket failed: %s\n", strerror(errno)); log_write(0,LOG_REJECT,"Creating socket failed: %s\n", strerror(errno)); /* if we cannot create the socket, defer the mail */ (void)fclose(data_file); return retval; } /* Now connecting the socket (INET) */ if (connect(sockfd, (struct sockaddr *)&serv_addr_in, sizeof(serv_addr_in)) < 0){ DEBUG(D_acl) debug_printf("Connecting socket failed: %s\n", strerror(errno)); log_write(0,LOG_REJECT,"Connecting socket failed: %s\n", strerror(errno)); /* if we cannot contact the socket, defer the mail */ (void)fclose(data_file); return retval; } } else { /* connecting to the dccifd UNIX socket */ bzero((char *)&serv_addr,sizeof(serv_addr)); serv_addr.sun_family = AF_UNIX; Ustrcpy(serv_addr.sun_path, sockpath); if ((sockfd = socket(AF_UNIX, SOCK_STREAM,0)) < 0){ DEBUG(D_acl) debug_printf("Creating socket failed: %s\n", strerror(errno)); log_write(0,LOG_REJECT,"Creating socket failed: %s\n", strerror(errno)); /* if we cannot create the socket, defer the mail */ (void)fclose(data_file); return retval; } /* Now connecting the socket (UNIX) */ if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){ DEBUG(D_acl) debug_printf("Connecting socket failed: %s\n", strerror(errno)); log_write(0,LOG_REJECT,"Connecting socket failed: %s\n", strerror(errno)); /* if we cannot contact the socket, defer the mail */ (void)fclose(data_file); return retval; } } /* the socket is open, now send the options to dccifd*/ DEBUG(D_acl) debug_printf("\n---------------------------\nSocket opened; now sending input\n-----------------\n"); /* First, fill in the input buffer */ Ustrncpy(sendbuf, opts, sizeof(sendbuf)); Ustrncat(sendbuf, from, sizeof(sendbuf)-Ustrlen(sendbuf)-1); DEBUG(D_acl) { debug_printf("opts = %s\nsender = %s\nrcpt count = %d\n", opts, from, recipients_count); debug_printf("Sending options:\n****************************\n"); } /* let's send each of the recipients to dccifd */ for (i = 0; i < recipients_count; i++){ DEBUG(D_acl) debug_printf("recipient = %s\n",recipients_list[i].address); if(Ustrlen(sendbuf) + Ustrlen(recipients_list[i].address) > sizeof(sendbuf)) { DEBUG(D_acl) debug_printf("Writing buffer: %s\n", sendbuf); flushbuffer(sockfd, sendbuf); bzero(sendbuf, sizeof(sendbuf)); } Ustrncat(sendbuf, recipients_list[i].address, sizeof(sendbuf)-Ustrlen(sendbuf)-1); Ustrncat(sendbuf, "\r\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1); } /* send a blank line between options and message */ Ustrncat(sendbuf, "\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1); /* Now we send the input buffer */ DEBUG(D_acl) debug_printf("%s\n****************************\n", sendbuf); flushbuffer(sockfd, sendbuf); /* now send the message */ /* Clear the input buffer */ bzero(sendbuf, sizeof(sendbuf)); /* First send the headers */ /* Now send the headers */ DEBUG(D_acl) debug_printf("Sending headers:\n****************************\n"); Ustrncpy(sendbuf, dcchdr->text, sizeof(sendbuf)-2); while((dcchdr=dcchdr->next)) { if(dcchdr->slen > sizeof(sendbuf)-2) { /* The size of the header is bigger than the size of * the input buffer, so split it up in smaller parts. */ flushbuffer(sockfd, sendbuf); bzero(sendbuf, sizeof(sendbuf)); j = 0; while(j < dcchdr->slen) { for(i = 0; i < sizeof(sendbuf)-2; i++) { sendbuf[i] = dcchdr->text[j]; j++; } flushbuffer(sockfd, sendbuf); bzero(sendbuf, sizeof(sendbuf)); } } else if(Ustrlen(sendbuf) + dcchdr->slen > sizeof(sendbuf)-2) { flushbuffer(sockfd, sendbuf); bzero(sendbuf, sizeof(sendbuf)); Ustrncpy(sendbuf, dcchdr->text, sizeof(sendbuf)-2); } else { Ustrncat(sendbuf, dcchdr->text, sizeof(sendbuf)-Ustrlen(sendbuf)-2); } } /* a blank line seperates header from body */ Ustrncat(sendbuf, "\n", sizeof(sendbuf)-Ustrlen(sendbuf)-1); flushbuffer(sockfd, sendbuf); DEBUG(D_acl) debug_printf("\n****************************\n%s", sendbuf); /* Clear the input buffer */ bzero(sendbuf, sizeof(sendbuf)); /* now send the body */ DEBUG(D_acl) debug_printf("Writing body:\n****************************\n"); (void)fseek(data_file, SPOOL_DATA_START_OFFSET, SEEK_SET); while((fread(sendbuf, 1, sizeof(sendbuf)-1, data_file)) > 0) { flushbuffer(sockfd, sendbuf); bzero(sendbuf, sizeof(sendbuf)); } DEBUG(D_acl) debug_printf("\n****************************\n"); /* shutdown() the socket */ if(shutdown(sockfd, 1) < 0){ DEBUG(D_acl) debug_printf("Couldn't shutdown socket: %s\n", strerror(errno)); log_write(0,LOG_MAIN,"Couldn't shutdown socket: %s\n", strerror(errno)); /* If there is a problem with the shutdown() * defer the mail. */ (void)fclose(data_file); return retval; } DEBUG(D_acl) debug_printf("\n-------------------------\nInput sent.\n-------------------------\n"); /******************************** * receiving output from dccifd * ********************************/ DEBUG(D_acl) debug_printf("\n-------------------------------------\nNow receiving output from server\n-----------------------------------\n"); /****************************************************************** * We should get 3 lines: * * 1/ First line is overall result: either 'A' for Accept, * * 'R' for Reject, 'S' for accept Some recipients or * * 'T' for a Temporary error. * * 2/ Second line contains the list of Accepted/Rejected * * recipients in the form AARRA (A = accepted, R = rejected). * * 3/ Third line contains the X-DCC header. * ******************************************************************/ line = 1; /* we start at the first line of the output */ j = 0; /* will be used as index for the recipients list */ k = 0; /* initializing the index of the X-DCC header: dcc_header_str[k] */ /* Let's read from the socket until there's nothing left to read */ bzero(recvbuf, sizeof(recvbuf)); while((resp = read(sockfd, recvbuf, sizeof(recvbuf)-1)) > 0) { /* How much did we get from the socket */ c = Ustrlen(recvbuf) + 1; DEBUG(D_acl) debug_printf("Length of the output buffer is: %d\nOutput buffer is:\n------------\n%s\n-----------\n", c, recvbuf); /* Now let's read each character and see what we've got */ for(i = 0; i < c; i++) { /* First check if we reached the end of the line and * then increment the line counter */ if(recvbuf[i] == '\n') { line++; } else { /* The first character of the first line is the * overall response. If there's another character * on that line it is not correct. */ if(line == 1) { if(i == 0) { /* Now get the value and set the * return value accordingly */ if(recvbuf[i] == 'A') { DEBUG(D_acl) debug_printf("Overall result = A\treturning OK\n"); Ustrcpy(dcc_return_text, "Mail accepted by DCC"); dcc_result = US"A"; retval = OK; } else if(recvbuf[i] == 'R') { DEBUG(D_acl) debug_printf("Overall result = R\treturning FAIL\n"); dcc_result = US"R"; retval = FAIL; if(sender_host_name) { log_write(0, LOG_MAIN, "H=%s [%s] F=<%s>: rejected by DCC", sender_host_name, sender_host_address, sender_address); } else { log_write(0, LOG_MAIN, "H=[%s] F=<%s>: rejected by DCC", sender_host_address, sender_address); } Ustrncpy(dcc_return_text, dcc_reject_message, Ustrlen(dcc_reject_message) + 1); } else if(recvbuf[i] == 'S') { DEBUG(D_acl) debug_printf("Overall result = S\treturning OK\n"); Ustrcpy(dcc_return_text, "Not all recipients accepted by DCC"); /* Since we're in an ACL we want a global result * so we accept for all */ dcc_result = US"A"; retval = OK; } else if(recvbuf[i] == 'G') { DEBUG(D_acl) debug_printf("Overall result = G\treturning FAIL\n"); Ustrcpy(dcc_return_text, "Greylisted by DCC"); dcc_result = US"G"; retval = FAIL; } else if(recvbuf[i] == 'T') { DEBUG(D_acl) debug_printf("Overall result = T\treturning DEFER\n"); retval = DEFER; log_write(0,LOG_MAIN,"Temporary error with DCC: %s\n", recvbuf); Ustrcpy(dcc_return_text, "Temporary error with DCC"); dcc_result = US"T"; } else { DEBUG(D_acl) debug_printf("Overall result = something else\treturning DEFER\n"); retval = DEFER; log_write(0,LOG_MAIN,"Unknown DCC response: %s\n", recvbuf); Ustrcpy(dcc_return_text, "Unknown DCC response"); dcc_result = US"T"; } } else { /* We're on the first line but not on the first character, * there must be something wrong. */ DEBUG(D_acl) debug_printf("Line = %d but i = %d != 0 character is %c - This is wrong!\n", line, i, recvbuf[i]); log_write(0,LOG_MAIN,"Wrong header from DCC, output is %s\n", recvbuf); } } else if(line == 2) { /* On the second line we get a list of * answers for each recipient. We don't care about * it because we're in an acl and take the * global result. */ } else if(line > 2) { /* The third and following lines are the X-DCC header, * so we store it in dcc_header_str. */ /* check if we don't get more than we can handle */ if(k < sizeof(dcc_header_str)) { dcc_header_str[k] = recvbuf[i]; k++; } else { DEBUG(D_acl) debug_printf("We got more output than we can store in the X-DCC header. Truncating at 120 characters.\n"); } } else { /* Wrong line number. There must be a problem with the output. */ DEBUG(D_acl) debug_printf("Wrong line number in output. Line number is %d\n", line); } } } /* we reinitialize the output buffer before we read again */ bzero(recvbuf,sizeof(recvbuf)); } /* We have read everything from the socket */ /* We need to terminate the X-DCC header with a '\n' character. This needs to be k-1 * since dcc_header_str[k] contains '\0'. */ dcc_header_str[k-1] = '\n'; /* Now let's sum up what we've got. */ DEBUG(D_acl) debug_printf("\n--------------------------\nOverall result = %d\nX-DCC header: %sReturn message: %s\ndcc_result: %s\n", retval, dcc_header_str, dcc_return_text, dcc_result); /* We only add the X-DCC header if it starts with X-DCC */ if(!(Ustrncmp(dcc_header_str, "X-DCC", 5))){ dcc_header = dcc_header_str; if(dcc_direct_add_header) { header_add(' ' , "%s", dcc_header_str); /* since the MIME ACL already writes the .eml file to disk without DCC Header we've to erase it */ unspool_mbox(); } } else { DEBUG(D_acl) debug_printf("Wrong format of the X-DCC header: %s\n", dcc_header_str); } /* check if we should add additional headers passed in acl_m_dcc_add_header */ if(dcc_direct_add_header) { if (((xtra_hdrs = expand_string(US"$acl_m_dcc_add_header")) != NULL) && (xtra_hdrs[0] != '\0')) { Ustrncpy(dcc_xtra_hdrs, xtra_hdrs, sizeof(dcc_xtra_hdrs) - 2); if (dcc_xtra_hdrs[Ustrlen(dcc_xtra_hdrs)-1] != '\n') Ustrcat(dcc_xtra_hdrs, "\n"); header_add(' ', "%s", dcc_xtra_hdrs); DEBUG(D_acl) debug_printf("adding additional headers in $acl_m_dcc_add_header: %s", dcc_xtra_hdrs); } } dcc_ok = 1; /* Now return to exim main process */ DEBUG(D_acl) debug_printf("Before returning to exim main process:\nreturn_text = %s - retval = %d\ndcc_result = %s\n", dcc_return_text, retval, dcc_result); (void)fclose(data_file); dcc_rc = retval; return dcc_rc; }
/* Counts number of frames. */ int count(int frames, int out) { unsigned int count = 0; int n, pos, offset; int32_t flen = 0; /* * continue is used for each frame * break is used when needing to refill the buffer * I did this mostly for personal amusement. */ pos = 0; offset = 0; while ((n = fillbuffer(offset)) > 0) { n += offset; do { offset = 0; if (flen == 0) { if (n - pos >= 12) { ttyheader(inbuf+pos, &flen); flen += 12; } else { /* ends in middle of flen header*/ offset = n - pos; memmove(inbuf, inbuf+pos, offset); break; } } if (n - pos >= flen) { if (out) memcpy(outbuf+pos, inbuf+pos, flen); pos += flen; flen = 0; count++; if (frames != 0 && count == frames) { lseek(infd, pos - n, SEEK_CUR); goto end; } continue; } else { if (out) memcpy(outbuf+pos, inbuf+pos, n - pos); flen -= (n - pos); pos = n; break; } } while (1); if (out) flushbuffer(pos); pos = 0; } end: if (out) flushbuffer(pos); return count; }
int cgi_main() { #ifdef WIN32 char *cgi_types[3][2]={ { ".php", "PHP.EXE" }, { ".pl", "PERL.EXE" }, { NULL, NULL } }; DWORD exitcode=0; HANDLE hMyProcess=GetCurrentProcess(); PROCESS_INFORMATION pi; STARTUPINFO si; char Command[512]; char Environ[8192]; char Path[255]; #else char *cgi_types[3][2]={ { ".php", "/usr/bin/php" }, { ".pl", "/usr/bin/perl" }, { NULL, NULL } }; int pset1[2]; int pset2[2]; #endif char *args[10]; char *env[50]; char cgifilename[255]; char *extension; char szBuffer[BUFF_SIZE]; pipe_fd local; pipe_fd remote; int sid=getsid(); int nOutRead; int pid; unsigned int i; unsigned int n; memset(args, 0, sizeof(args)); cgi_makeargs(sid, args); memset(env, 0, sizeof(env)); cgi_makeenv(sid, env, args); snprintf(cgifilename, sizeof(cgifilename)-1, "%s", args[0]); for (i=0;i<10;i++) free(args[i]); n=0; if ((extension=strrchr(cgifilename, '.'))!=NULL) { for (i=0;cgi_types[i][0]!=NULL;i++) { if (strcmp(extension, cgi_types[i][0])==0) { args[n]=calloc(255, sizeof(char)); snprintf(args[n], 254, "%s", cgi_types[i][1]); n++; break; } } } args[n]=calloc(255, sizeof(char)); snprintf(args[n], 254, "%s", cgifilename); #ifdef WIN32 memset(Command, 0, sizeof(Command)); memset(Environ, 0, sizeof(Environ)); ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&si, sizeof(si)); snprintf(Path, sizeof(Path)-1, "%s", cgifilename); if ((extension=strrchr(Path, '\\'))!=NULL) *extension='\0'; if (args[1]==NULL) { snprintf(Command, sizeof(Command)-1, "%s", cgifilename); } else { //snprintf(Command, sizeof(Command)-1, "%s\\%s \"%s\"", config.server_cgi_bin_dir, cgi_types[i][1], cgifilename); snprintf(Command, sizeof(Command)-1, "%s\\%s \"%s\" > file.html", config.server_cgi_bin_dir, cgi_types[i][1], cgifilename); } logerror("Process Command: %s", Command); for (i=0, n=0;env[i]!=NULL;i++) { if (n+strlen(env[i])>sizeof(Environ)) break; n+=sprintf(&Environ[n], "%s", env[i]); n++; } if (!CreatePipe((HANDLE)&remote.in, (HANDLE)&local.out, NULL, BUFF_SIZE)) { for (i=0;i<10;i++) free(args[i]); for (i=0;i<50;i++) free(env[i]); printerror(sid, 500, "Internal Server Error", "Unable to create pipe."); return -1; } if (!CreatePipe((HANDLE)&local.in, (HANDLE)&remote.out, NULL, BUFF_SIZE)) { for (i=0;i<10;i++) free(args[i]); for (i=0;i<50;i++) free(env[i]); CloseHandle((HANDLE)remote.in); CloseHandle((HANDLE)local.out); printerror(sid, 500, "Internal Server Error", "Unable to create pipe."); return -1; } si.cb=sizeof(si); si.dwFlags=STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES; si.wShowWindow=SW_HIDE; si.hStdInput=(HANDLE)remote.in; si.hStdOutput=(HANDLE)remote.out; si.hStdError=(HANDLE)remote.out; if (!CreateProcess(NULL, Command, NULL, NULL, TRUE, CREATE_NO_WINDOW, Environ, Path, &si, &pi)) { for (i=0;i<10;i++) free(args[i]); for (i=0;i<50;i++) free(env[i]); CloseHandle((HANDLE)local.in); CloseHandle((HANDLE)local.out); CloseHandle((HANDLE)remote.in); CloseHandle((HANDLE)remote.out); logerror("CGI failed. [%s]", Command); printerror(sid, 500, "Internal Server Error", "There was a problem running the requested CGI."); return -1; } pid=pi.dwProcessId; CloseHandle(si.hStdInput); CloseHandle(si.hStdOutput); #else if ((pipe(pset1)==-1) || (pipe(pset2)==-1)) { for (i=0;i<10;i++) free(args[i]); for (i=0;i<50;i++) free(env[i]); close(pset1[0]); close(pset1[1]); logerror("pipe() error"); printerror(sid, 500, "Internal Server Error", "Unable to create pipe."); return -1; } local.in=pset1[0]; remote.out=pset1[1]; remote.in=pset2[0]; local.out=pset2[1]; logaccess(1, "Executing CGI [%s %s]", args[0], args[1]); pid=fork(); if (pid<0) { logerror("fork() error"); return -1; } else if (pid==0) { close(local.in); close(local.out); dup2(remote.in, fileno(stdin)); dup2(remote.out, fileno(stdout)); // if ((dup2(remote.in, fileno(stdin))!=0)||(dup2(remote.out, fileno(stdout))!=0)) { // logerror("dup2() error"); // exit(0); // } execve(args[0], &args[0], &env[0]); logerror("execve() error [%s][%s]", args[0], args[1]); exit(0); } else { close(remote.in); close(remote.out); } #endif sendfile(sid, "file.html"); if (conn[sid].dat->in_ContentLength>0) { #ifdef WIN32 WriteFile((HANDLE)local.out, conn[sid].PostData, conn[sid].dat->in_ContentLength, &nOutRead, NULL); #else write(local.out, conn[sid].PostData, conn[sid].dat->in_ContentLength); #endif } conn[sid].dat->out_headdone=1; conn[sid].dat->out_status=200; if (strcasestr(conn[sid].dat->in_Protocol, "HTTP/1.1")!=NULL) { snprintf(conn[sid].dat->out_Protocol, sizeof(conn[sid].dat->out_Protocol)-1, "HTTP/1.1"); } else { snprintf(conn[sid].dat->out_Protocol, sizeof(conn[sid].dat->out_Protocol)-1, "HTTP/1.0"); } snprintf(conn[sid].dat->out_Connection, sizeof(conn[sid].dat->out_Connection)-1, "Close"); prints("%s %d OK\r\n", conn[sid].dat->out_Protocol, conn[sid].dat->out_status); prints("Connection: %s\r\n", conn[sid].dat->out_Connection); flushbuffer(sid); do { memset(szBuffer, 0, sizeof(szBuffer)); #ifdef WIN32 ReadFile((HANDLE)local.in, szBuffer, sizeof(szBuffer)-1, &nOutRead, NULL); #else nOutRead=read(local.in, szBuffer, BUFF_SIZE-1); #endif if (nOutRead>0) { if (RunAsCGI) { fwrite(szBuffer, sizeof(char), nOutRead, stdout); } else { fwrite(szBuffer, sizeof(char), nOutRead, stdout); send(conn[sid].socket, szBuffer, nOutRead, 0); } }; } while (nOutRead>0); flushbuffer(sid); /* cleanup */ for (i=0;i<10;i++) free(args[i]); for (i=0;i<50;i++) free(env[i]); #ifdef WIN32 GetExitCodeProcess(pi.hProcess, &exitcode); if (exitcode==STILL_ACTIVE) TerminateProcess(pi.hProcess, 1); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); CloseHandle((HANDLE)local.in); CloseHandle((HANDLE)local.out); #else close(local.in); close(local.out); #endif conn[sid].dat->out_bodydone=1; flushbuffer(sid); closeconnect(sid, 1); return 0; }
int main(int argc, char *argv[]) { char *c; struct encoder_ctx enc_ctx[2]; struct cc_subtitle dec_sub; #ifdef ENABLE_FFMPEG void *ffmpeg_ctx = NULL; #endif struct lib_ccx_ctx *ctx; struct lib_cc_decode *dec_ctx = NULL; init_options (&ccx_options); parse_configuration(&ccx_options); parse_parameters (&ccx_options, argc, argv); // Initialize libraries ctx = init_libraries(&ccx_options); dec_ctx = ctx->dec_ctx; // Prepare write structures init_write(&ctx->wbout1,ccx_options.wbout1.filename); init_write(&ctx->wbout2,ccx_options.wbout2.filename); int show_myth_banner = 0; memset (&cea708services[0],0,CCX_DECODERS_708_MAX_SERVICES*sizeof (int)); // Cannot (yet) be moved because it's needed in parse_parameters. memset (&dec_sub, 0,sizeof(dec_sub)); if (ctx->num_input_files==0 && ccx_options.input_source==CCX_DS_FILE) { usage (); fatal (EXIT_NO_INPUT_FILES, "(This help screen was shown because there were no input files)\n"); } if (ctx->num_input_files>1 && ccx_options.live_stream) { fatal(EXIT_TOO_MANY_INPUT_FILES, "Live stream mode accepts only one input file.\n"); } if (ctx->num_input_files && ccx_options.input_source==CCX_DS_NETWORK) { fatal(EXIT_TOO_MANY_INPUT_FILES, "UDP mode is not compatible with input files.\n"); } if (ccx_options.input_source==CCX_DS_NETWORK || ccx_options.input_source==CCX_DS_TCP) { ccx_options.buffer_input=1; // Mandatory, because each datagram must be read complete. } if (ctx->num_input_files && ccx_options.input_source==CCX_DS_TCP) { fatal(EXIT_TOO_MANY_INPUT_FILES, "TCP mode is not compatible with input files.\n"); } if (ctx->num_input_files > 0) { ctx->wbout1.multiple_files = 1; ctx->wbout1.first_input_file = ctx->inputfile[0]; ctx->wbout2.multiple_files = 1; ctx->wbout2.first_input_file = ctx->inputfile[0]; } // teletext page number out of range if ((tlt_config.page != 0) && ((tlt_config.page < 100) || (tlt_config.page > 899))) { fatal (EXIT_NOT_CLASSIFIED, "Teletext page number could not be lower than 100 or higher than 899\n"); } if (ccx_options.output_filename!=NULL) { // Use the given output file name for the field specified by // the -1, -2 switch. If -12 is used, the filename is used for // field 1. if (ccx_options.extract==2) ctx->wbout2.filename=ccx_options.output_filename; else ctx->wbout1.filename=ccx_options.output_filename; } switch (ccx_options.write_format) { case CCX_OF_RAW: ctx->extension = ".raw"; break; case CCX_OF_SRT: ctx->extension = ".srt"; break; case CCX_OF_SAMI: ctx->extension = ".smi"; break; case CCX_OF_SMPTETT: ctx->extension = ".ttml"; break; case CCX_OF_TRANSCRIPT: ctx->extension = ".txt"; break; case CCX_OF_RCWT: ctx->extension = ".bin"; break; case CCX_OF_SPUPNG: ctx->extension = ".xml"; break; case CCX_OF_NULL: ctx->extension = ""; break; case CCX_OF_DVDRAW: ctx->extension = ".dvdraw"; break; default: fatal (CCX_COMMON_EXIT_BUG_BUG, "write_format doesn't have any legal value, this is a bug.\n"); } params_dump(ctx); // default teletext page if (tlt_config.page > 0) { // dec to BCD, magazine pages numbers are in BCD (ETSI 300 706) tlt_config.page = ((tlt_config.page / 100) << 8) | (((tlt_config.page / 10) % 10) << 4) | (tlt_config.page % 10); } if (ctx->auto_stream==CCX_SM_MCPOODLESRAW && ccx_options.write_format==CCX_OF_RAW) { fatal (EXIT_INCOMPATIBLE_PARAMETERS, "-in=raw can only be used if the output is a subtitle file.\n"); } if (ctx->auto_stream==CCX_SM_RCWT && ccx_options.write_format==CCX_OF_RCWT && ccx_options.output_filename==NULL) { fatal (EXIT_INCOMPATIBLE_PARAMETERS, "CCExtractor's binary format can only be used simultaneously for input and\noutput if the output file name is specified given with -o.\n"); } subline = (unsigned char *) malloc (SUBLINESIZE); switch (ccx_options.input_source) { case CCX_DS_FILE: ctx->basefilename = (char *) malloc (strlen (ctx->inputfile[0])+1); break; case CCX_DS_STDIN: ctx->basefilename = (char *) malloc (strlen (ctx->basefilename_for_stdin)+1); break; case CCX_DS_NETWORK: case CCX_DS_TCP: ctx->basefilename = (char *) malloc (strlen (ctx->basefilename_for_network)+1); break; } if (ctx->basefilename == NULL) fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n"); switch (ccx_options.input_source) { case CCX_DS_FILE: strcpy (ctx->basefilename, ctx->inputfile[0]); break; case CCX_DS_STDIN: strcpy (ctx->basefilename, ctx->basefilename_for_stdin); break; case CCX_DS_NETWORK: case CCX_DS_TCP: strcpy (ctx->basefilename, ctx->basefilename_for_network); break; } for (c=ctx->basefilename+strlen (ctx->basefilename)-1; ctx->basefilename && *c!='.'; c--) {;} // Get last . if (*c=='.') *c=0; if (ctx->wbout1.filename==NULL) { ctx->wbout1.filename = (char *) malloc (strlen (ctx->basefilename)+3+strlen (ctx->extension)); ctx->wbout1.filename[0]=0; } if (ctx->wbout2.filename==NULL) { ctx->wbout2.filename = (char *) malloc (strlen (ctx->basefilename)+3+strlen (ctx->extension)); ctx->wbout2.filename[0]=0; } if (ctx->buffer == NULL || ctx->pesheaderbuf==NULL || ctx->wbout1.filename == NULL || ctx->wbout2.filename == NULL || subline==NULL || init_file_buffer() ) { fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n"); } if (ccx_options.send_to_srv) { connect_to_srv(ccx_options.srv_addr, ccx_options.srv_port, ccx_options.tcp_desc); } if (ccx_options.write_format!=CCX_OF_NULL) { /* # DVD format uses one raw file for both fields, while Broadcast requires 2 */ if (ccx_options.write_format==CCX_OF_DVDRAW) { if (ctx->wbout1.filename[0]==0) { strcpy (ctx->wbout1.filename,ctx->basefilename); strcat (ctx->wbout1.filename,".raw"); } if (ctx->cc_to_stdout) { ctx->wbout1.fh=STDOUT_FILENO; mprint ("Sending captions to stdout.\n"); } else { mprint ("Creating %s\n", ctx->wbout1.filename); ctx->wbout1.fh=open (ctx->wbout1.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE); if (ctx->wbout1.fh==-1) { fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed\n"); } } } else { if (ctx->cc_to_stdout && ccx_options.extract==12) fatal (EXIT_INCOMPATIBLE_PARAMETERS, "You can't extract both fields to stdout at the same time in broadcast mode."); if (ccx_options.write_format == CCX_OF_SPUPNG && ctx->cc_to_stdout) fatal (EXIT_INCOMPATIBLE_PARAMETERS, "You cannot use -out=spupng with -stdout."); if (ccx_options.extract!=2) { if (ctx->cc_to_stdout) { ctx->wbout1.fh=STDOUT_FILENO; mprint ("Sending captions to stdout.\n"); } else if (!ccx_options.send_to_srv) { if (ctx->wbout1.filename[0]==0) { strcpy (ctx->wbout1.filename,ctx->basefilename); if (ccx_options.extract==12) // _1 only added if there's two files strcat (ctx->wbout1.filename,"_1"); strcat (ctx->wbout1.filename,(const char *) ctx->extension); } mprint ("Creating %s\n", ctx->wbout1.filename); ctx->wbout1.fh=open (ctx->wbout1.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE); if (ctx->wbout1.fh==-1) { fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed (errno=%d)\n", errno); } } switch (ccx_options.write_format) { case CCX_OF_RAW: writeraw(BROADCAST_HEADER, sizeof(BROADCAST_HEADER), &ctx->wbout1); break; case CCX_OF_DVDRAW: break; case CCX_OF_RCWT: if (init_encoder(enc_ctx, &ctx->wbout1)) fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n"); set_encoder_subs_delay(enc_ctx, ctx->subs_delay); set_encoder_last_displayed_subs_ms(enc_ctx, ctx->last_displayed_subs_ms); set_encoder_startcredits_displayed(enc_ctx, ctx->startcredits_displayed); break; default: if (!ccx_options.no_bom){ if (ccx_options.encoding == CCX_ENC_UTF_8){ // Write BOM writeraw(UTF8_BOM, sizeof(UTF8_BOM), &ctx->wbout1); } if (ccx_options.encoding == CCX_ENC_UNICODE){ // Write BOM writeraw(LITTLE_ENDIAN_BOM, sizeof(LITTLE_ENDIAN_BOM), &ctx->wbout1); } } if (init_encoder(enc_ctx, &ctx->wbout1)){ fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n"); } set_encoder_subs_delay(enc_ctx, ctx->subs_delay); set_encoder_last_displayed_subs_ms(enc_ctx, ctx->last_displayed_subs_ms); set_encoder_startcredits_displayed(enc_ctx, ctx->startcredits_displayed); } } if (ccx_options.extract == 12 && ccx_options.write_format != CCX_OF_RAW) mprint (" and \n"); if (ccx_options.extract!=1) { if (ctx->cc_to_stdout) { ctx->wbout1.fh=STDOUT_FILENO; mprint ("Sending captions to stdout.\n"); } else if(ccx_options.write_format == CCX_OF_RAW && ccx_options.extract == 12) { memcpy(&ctx->wbout2, &ctx->wbout1,sizeof(ctx->wbout1)); } else if (!ccx_options.send_to_srv) { if (ctx->wbout2.filename[0]==0) { strcpy (ctx->wbout2.filename,ctx->basefilename); if (ccx_options.extract==12) // _ only added if there's two files strcat (ctx->wbout2.filename,"_2"); strcat (ctx->wbout2.filename,(const char *) ctx->extension); } mprint ("Creating %s\n", ctx->wbout2.filename); ctx->wbout2.fh=open (ctx->wbout2.filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE); if (ctx->wbout2.fh==-1) { fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Failed\n"); } if(ccx_options.write_format == CCX_OF_RAW) writeraw (BROADCAST_HEADER,sizeof (BROADCAST_HEADER),&ctx->wbout2); } switch (ccx_options.write_format) { case CCX_OF_RAW: case CCX_OF_DVDRAW: break; case CCX_OF_RCWT: if( init_encoder(enc_ctx+1,&ctx->wbout2) ) fatal (EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n"); set_encoder_subs_delay(enc_ctx+1, ctx->subs_delay); set_encoder_last_displayed_subs_ms(enc_ctx+1, ctx->last_displayed_subs_ms); set_encoder_startcredits_displayed(enc_ctx+1, ctx->startcredits_displayed); break; default: if (!ccx_options.no_bom){ if (ccx_options.encoding == CCX_ENC_UTF_8){ // Write BOM writeraw(UTF8_BOM, sizeof(UTF8_BOM), &ctx->wbout2); } if (ccx_options.encoding == CCX_ENC_UNICODE){ // Write BOM writeraw(LITTLE_ENDIAN_BOM, sizeof(LITTLE_ENDIAN_BOM), &ctx->wbout2); } } if (init_encoder(enc_ctx + 1, &ctx->wbout2)){ fatal(EXIT_NOT_ENOUGH_MEMORY, "Not enough memory\n"); } set_encoder_subs_delay(enc_ctx+1, ctx->subs_delay); set_encoder_last_displayed_subs_ms(enc_ctx+1, ctx->last_displayed_subs_ms); set_encoder_startcredits_displayed(enc_ctx+1, ctx->startcredits_displayed); } } } } if (ccx_options.transcript_settings.xds) { if (ccx_options.write_format != CCX_OF_TRANSCRIPT) { ccx_options.transcript_settings.xds = 0; mprint ("Warning: -xds ignored, XDS can only be exported to transcripts at this time.\n"); } } if (ccx_options.teletext_mode == CCX_TXT_IN_USE) // Here, it would mean it was forced by user telxcc_init(ctx); ctx->fh_out_elementarystream = NULL; if (ccx_options.out_elementarystream_filename!=NULL) { if ((ctx->fh_out_elementarystream = fopen (ccx_options.out_elementarystream_filename,"wb"))==NULL) { fatal(CCX_COMMON_EXIT_FILE_CREATION_FAILED, "Unable to open clean file: %s\n", ccx_options.out_elementarystream_filename); } } // Initialize HDTV caption buffer init_hdcc(); if (ccx_options.line_terminator_lf) encoded_crlf_length = encode_line(encoded_crlf, (unsigned char *) "\n"); else encoded_crlf_length = encode_line(encoded_crlf, (unsigned char *) "\r\n"); encoded_br_length = encode_line(encoded_br, (unsigned char *) "<br>"); time_t start, final; time(&start); dec_ctx->processed_enough=0; if (ccx_options.binary_concat) { ctx->total_inputsize=gettotalfilessize(ctx); if (ctx->total_inputsize==-1) fatal (EXIT_UNABLE_TO_DETERMINE_FILE_SIZE, "Failed to determine total file size.\n"); } #ifndef _WIN32 signal_ctx = ctx; m_signal(SIGINT, sigint_handler); #endif while (switch_to_next_file(ctx, 0) && !dec_ctx->processed_enough) { prepare_for_new_file(ctx); #ifdef ENABLE_FFMPEG close_input_file(ctx); ffmpeg_ctx = init_ffmpeg(ctx->inputfile[0]); if(ffmpeg_ctx) { do { int ret = 0; unsigned char *bptr = ctx->buffer; int len = ff_get_ccframe(ffmpeg_ctx, bptr, 1024); int cc_count = 0; if(len == AVERROR(EAGAIN)) { continue; } else if(len == AVERROR_EOF) break; else if(len == 0) continue; else if(len < 0 ) { mprint("Error extracting Frame\n"); break; } else cc_count = len/3; ret = process_cc_data(dec_ctx, bptr, cc_count, &dec_sub); if(ret >= 0 && dec_sub.got_output) { encode_sub(enc_ctx, &dec_sub); dec_sub.got_output = 0; } }while(1); continue; } else { mprint ("\rFailed to initialized ffmpeg falling back to legacy\n"); } #endif if (ctx->auto_stream == CCX_SM_AUTODETECT) { detect_stream_type(ctx); switch (ctx->stream_mode) { case CCX_SM_ELEMENTARY_OR_NOT_FOUND: mprint ("\rFile seems to be an elementary stream, enabling ES mode\n"); break; case CCX_SM_TRANSPORT: mprint ("\rFile seems to be a transport stream, enabling TS mode\n"); break; case CCX_SM_PROGRAM: mprint ("\rFile seems to be a program stream, enabling PS mode\n"); break; case CCX_SM_ASF: mprint ("\rFile seems to be an ASF, enabling DVR-MS mode\n"); break; case CCX_SM_WTV: mprint ("\rFile seems to be a WTV, enabling WTV mode\n"); break; case CCX_SM_MCPOODLESRAW: mprint ("\rFile seems to be McPoodle raw data\n"); break; case CCX_SM_RCWT: mprint ("\rFile seems to be a raw caption with time data\n"); break; case CCX_SM_MP4: mprint ("\rFile seems to be a MP4\n"); break; #ifdef WTV_DEBUG case CCX_SM_HEX_DUMP: mprint ("\rFile seems to be an hexadecimal dump\n"); break; #endif case CCX_SM_MYTH: case CCX_SM_AUTODETECT: fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!"); break; } } else { ctx->stream_mode=ctx->auto_stream; } /* ----------------------------------------------------------------- MAIN LOOP ----------------------------------------------------------------- */ // The myth loop autodetect will only be used with ES or PS streams switch (ccx_options.auto_myth) { case 0: // Use whatever stream mode says break; case 1: // Force stream mode to myth ctx->stream_mode=CCX_SM_MYTH; break; case 2: // autodetect myth files, but only if it does not conflict with // the current stream mode switch (ctx->stream_mode) { case CCX_SM_ELEMENTARY_OR_NOT_FOUND: case CCX_SM_PROGRAM: if ( detect_myth(ctx) ) { ctx->stream_mode=CCX_SM_MYTH; } break; default: // Keep stream_mode break; } break; } // Disable sync check for raw formats - they have the right timeline. // Also true for bin formats, but -nosync might have created a // broken timeline for debug purposes. // Disable too in MP4, specs doesn't say that there can't be a jump switch (ctx->stream_mode) { case CCX_SM_MCPOODLESRAW: case CCX_SM_RCWT: case CCX_SM_MP4: #ifdef WTV_DEBUG case CCX_SM_HEX_DUMP: #endif ccx_common_timing_settings.disable_sync_check = 1; break; default: break; } switch (ctx->stream_mode) { case CCX_SM_ELEMENTARY_OR_NOT_FOUND: if (!ccx_options.use_gop_as_pts) // If !0 then the user selected something ccx_options.use_gop_as_pts = 1; // Force GOP timing for ES ccx_common_timing_settings.is_elementary_stream = 1; case CCX_SM_TRANSPORT: case CCX_SM_PROGRAM: case CCX_SM_ASF: case CCX_SM_WTV: if (!ccx_options.use_gop_as_pts) // If !0 then the user selected something ccx_options.use_gop_as_pts = 0; mprint ("\rAnalyzing data in general mode\n"); general_loop(ctx, &enc_ctx); break; case CCX_SM_MCPOODLESRAW: mprint ("\rAnalyzing data in McPoodle raw mode\n"); raw_loop(ctx, &enc_ctx); break; case CCX_SM_RCWT: mprint ("\rAnalyzing data in CCExtractor's binary format\n"); rcwt_loop(ctx, &enc_ctx); break; case CCX_SM_MYTH: mprint ("\rAnalyzing data in MythTV mode\n"); show_myth_banner = 1; myth_loop(ctx, &enc_ctx); break; case CCX_SM_MP4: mprint ("\rAnalyzing data with GPAC (MP4 library)\n"); close_input_file(ctx); // No need to have it open. GPAC will do it for us processmp4 (ctx, ctx->inputfile[0],&enc_ctx); break; #ifdef WTV_DEBUG case CCX_SM_HEX_DUMP: close_input_file(ctx); // processhex will open it in text mode processhex (ctx, ctx->inputfile[0]); break; #endif case CCX_SM_AUTODETECT: fatal(CCX_COMMON_EXIT_BUG_BUG, "Cannot be reached!"); break; } mprint("\n"); dbg_print(CCX_DMT_DECODER_608, "\nTime stamps after last caption block was written:\n"); dbg_print(CCX_DMT_DECODER_608, "Last time stamps: PTS: %s (%+2dF) ", print_mstime( (LLONG) (sync_pts/(MPEG_CLOCK_FREQ/1000) +frames_since_ref_time*1000.0/current_fps) ), frames_since_ref_time); dbg_print(CCX_DMT_DECODER_608, "GOP: %s \n", print_mstime(gop_time.ms) ); // Blocks since last PTS/GOP time stamp. dbg_print(CCX_DMT_DECODER_608, "Calc. difference: PTS: %s (%+3lldms incl.) ", print_mstime( (LLONG) ((sync_pts-min_pts)/(MPEG_CLOCK_FREQ/1000) + fts_offset + frames_since_ref_time*1000.0/current_fps)), fts_offset + (LLONG) (frames_since_ref_time*1000.0/current_fps) ); dbg_print(CCX_DMT_DECODER_608, "GOP: %s (%+3dms incl.)\n", print_mstime((LLONG)(gop_time.ms -first_gop_time.ms +get_fts_max()-fts_at_gop_start)), (int)(get_fts_max()-fts_at_gop_start)); // When padding is active the CC block time should be within // 1000/29.97 us of the differences. dbg_print(CCX_DMT_DECODER_608, "Max. FTS: %s (without caption blocks since then)\n", print_mstime(get_fts_max())); if (ctx->stat_hdtv) { mprint ("\rCC type 0: %d (%s)\n", dec_ctx->cc_stats[0], cc_types[0]); mprint ("CC type 1: %d (%s)\n", dec_ctx->cc_stats[1], cc_types[1]); mprint ("CC type 2: %d (%s)\n", dec_ctx->cc_stats[2], cc_types[2]); mprint ("CC type 3: %d (%s)\n", dec_ctx->cc_stats[3], cc_types[3]); } mprint ("\nTotal frames time: %s (%u frames at %.2ffps)\n", print_mstime( (LLONG)(total_frames_count*1000/current_fps) ), total_frames_count, current_fps); if (ctx->total_pulldownframes) mprint ("incl. pulldown frames: %s (%u frames at %.2ffps)\n", print_mstime( (LLONG)(ctx->total_pulldownframes*1000/current_fps) ), ctx->total_pulldownframes, current_fps); if (pts_set >= 1 && min_pts != 0x01FFFFFFFFLL) { LLONG postsyncms = (LLONG) (ctx->frames_since_last_gop*1000/current_fps); mprint ("\nMin PTS: %s\n", print_mstime( min_pts/(MPEG_CLOCK_FREQ/1000) - fts_offset)); if (pts_big_change) mprint ("(Reference clock was reset at some point, Min PTS is approximated)\n"); mprint ("Max PTS: %s\n", print_mstime( sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms)); mprint ("Length: %s\n", print_mstime( sync_pts/(MPEG_CLOCK_FREQ/1000) + postsyncms - min_pts/(MPEG_CLOCK_FREQ/1000) + fts_offset )); } // dvr-ms files have invalid GOPs if (gop_time.inited && first_gop_time.inited && ctx->stream_mode != CCX_SM_ASF) { mprint ("\nInitial GOP time: %s\n", print_mstime(first_gop_time.ms)); mprint ("Final GOP time: %s%+3dF\n", print_mstime(gop_time.ms), ctx->frames_since_last_gop); mprint ("Diff. GOP length: %s%+3dF", print_mstime(gop_time.ms - first_gop_time.ms), ctx->frames_since_last_gop); mprint (" (%s)\n", print_mstime(gop_time.ms - first_gop_time.ms +(LLONG) ((ctx->frames_since_last_gop)*1000/29.97)) ); } if (ctx->false_pict_header) mprint ("\nNumber of likely false picture headers (discarded): %d\n",ctx->false_pict_header); if (ctx->stat_numuserheaders) mprint("\nTotal user data fields: %d\n", ctx->stat_numuserheaders); if (ctx->stat_dvdccheaders) mprint("DVD-type user data fields: %d\n", ctx->stat_dvdccheaders); if (ctx->stat_scte20ccheaders) mprint("SCTE-20 type user data fields: %d\n", ctx->stat_scte20ccheaders); if (ctx->stat_replay4000headers) mprint("ReplayTV 4000 user data fields: %d\n", ctx->stat_replay4000headers); if (ctx->stat_replay5000headers) mprint("ReplayTV 5000 user data fields: %d\n", ctx->stat_replay5000headers); if (ctx->stat_hdtv) mprint("HDTV type user data fields: %d\n", ctx->stat_hdtv); if (ctx->stat_dishheaders) mprint("Dish Network user data fields: %d\n", ctx->stat_dishheaders); if (ctx->stat_divicom) { mprint("CEA608/Divicom user data fields: %d\n", ctx->stat_divicom); mprint("\n\nNOTE! The CEA 608 / Divicom standard encoding for closed\n"); mprint("caption is not well understood!\n\n"); mprint("Please submit samples to the developers.\n\n\n"); } // Add one frame as fts_max marks the beginning of the last frame, // but we need the end. fts_global += fts_max + (LLONG) (1000.0/current_fps); // CFS: At least in Hauppage mode, cb_field can be responsible for ALL the // timing (cb_fields having a huge number and fts_now and fts_global being 0 all // the time), so we need to take that into account in fts_global before resetting // counters. if (cb_field1!=0) fts_global += cb_field1*1001/3; else fts_global += cb_field2*1001/3; // Reset counters - This is needed if some captions are still buffered // and need to be written after the last file is processed. cb_field1 = 0; cb_field2 = 0; cb_708 = 0; fts_now = 0; fts_max = 0; } // file loop close_input_file(ctx); if (ctx->fh_out_elementarystream!=NULL) fclose (ctx->fh_out_elementarystream); flushbuffer (ctx, &ctx->wbout1, false); flushbuffer (ctx, &ctx->wbout2, false); prepare_for_new_file (ctx); // To reset counters used by handle_end_of_data() telxcc_close(ctx); if (ctx->wbout1.fh!=-1) { if (ccx_options.write_format==CCX_OF_SMPTETT || ccx_options.write_format==CCX_OF_SAMI || ccx_options.write_format==CCX_OF_SRT || ccx_options.write_format==CCX_OF_TRANSCRIPT || ccx_options.write_format==CCX_OF_SPUPNG ) { handle_end_of_data(dec_ctx->context_cc608_field_1, &dec_sub); if (dec_sub.got_output) { encode_sub(enc_ctx,&dec_sub); dec_sub.got_output = 0; } } else if(ccx_options.write_format==CCX_OF_RCWT) { // Write last header and data writercwtdata (dec_ctx, NULL); } dinit_encoder(enc_ctx); } if (ctx->wbout2.fh!=-1) { if (ccx_options.write_format==CCX_OF_SMPTETT || ccx_options.write_format==CCX_OF_SAMI || ccx_options.write_format==CCX_OF_SRT || ccx_options.write_format==CCX_OF_TRANSCRIPT || ccx_options.write_format==CCX_OF_SPUPNG ) { handle_end_of_data(dec_ctx->context_cc608_field_2, &dec_sub); if (dec_sub.got_output) { encode_sub(enc_ctx,&dec_sub); dec_sub.got_output = 0; } } dinit_encoder(enc_ctx+1); } flushbuffer (ctx, &ctx->wbout1,true); flushbuffer (ctx, &ctx->wbout2,true); time (&final); long proc_time=(long) (final-start); mprint ("\rDone, processing time = %ld seconds\n", proc_time); if (proc_time>0) { LLONG ratio=(get_fts_max()/10)/proc_time; unsigned s1=(unsigned) (ratio/100); unsigned s2=(unsigned) (ratio%100); mprint ("Performance (real length/process time) = %u.%02u\n", s1, s2); } dbg_print(CCX_DMT_708, "The 708 decoder was reset [%d] times.\n",resets_708); if (ccx_options.teletext_mode == CCX_TXT_IN_USE) mprint ( "Teletext decoder: %"PRIu32" packets processed, %"PRIu32" SRT frames written.\n", tlt_packet_counter, tlt_frames_produced); if (dec_ctx->processed_enough) { mprint ("\rNote: Processing was cancelled before all data was processed because\n"); mprint ("\rone or more user-defined limits were reached.\n"); } if (ccblocks_in_avc_lost>0) { mprint ("Total caption blocks received: %d\n", ccblocks_in_avc_total); mprint ("Total caption blocks lost: %d\n", ccblocks_in_avc_lost); } mprint ("This is beta software. Report issues to carlos at ccextractor org...\n"); if (show_myth_banner) { mprint ("NOTICE: Due to the major rework in 0.49, we needed to change part of the timing\n"); mprint ("code in the MythTV's branch. Please report results to the address above. If\n"); mprint ("something is broken it will be fixed. Thanks\n"); } dinit_libraries(&ctx); return EXIT_OK; }
void plD_eop_ntk(PLStream *pls) { flushbuffer(pls); tk_cmd("update"); }
void plD_eop_xfig(PLStream *pls) { if (!firstline) flushbuffer(pls); }