示例#1
0
bool AmiraConverter::CanRead(const std::string& fn,
                             const std::vector<int8_t>& start) const
{
  if(!AbstrConverter::CanRead(fn, start)) {
    MESSAGE("Base class says we can't read it...");
    return false;
  }

  // the file should start with:
  // # AmiraMesh ASCII 1.0
  // if it doesn't we probably don't know how to read it.
  std::vector<int8_t>::const_iterator nl =
    std::find(start.begin(), start.end(), '\n');
  if(nl == start.end()) {
    // no newline found.  This isn't one of our files.
    MESSAGE("No newline near the beginning of the file; not mine.");
    return false;
  }
  std::string firstline(
    static_cast<const signed char*>(&start[0]),
    static_cast<const signed char*>(&*nl)
  );
  if(firstline.find("AmiraMesh") == std::string::npos) {
    MESSAGE("No 'AmiraMesh'... not mine.");
    return false;
  }
  if(firstline.find("ASCII") == std::string::npos) {
    MESSAGE("Not in ASCII format... this might be mine, but I can't read it.");
    return false;
  }

  return true;
}
示例#2
0
bool VTKConverter::CanRead(const std::string& fn,
                           const std::vector<int8_t>& start) const {
  if(!AbstrConverter::CanRead(fn, start)) {
    MESSAGE("Base class reports we can't read it, bailing.");
    return false;
  }

  // the file should start with:
  //   # vtk DataFile Version 3.0
  // if it doesn't than we probably can't read it.
  auto nl = std::find(start.begin(), start.end(), '\n');
  if(nl == start.end()) {
    const char* comment = "# vtk DataFile Version 3.0";
    MESSAGE("missing '%s' at beginning of the file; I probably can't read "
            "this.  Bailing out...", comment);
    return false;
  }
  std::string firstline(
    static_cast<const signed char*>(&start[0]),
    static_cast<const signed char*>(&*nl)
  );
  if(firstline.find("vtk") == std::string::npos) {
    MESSAGE("No 'vtk' in first line; this is not mine.");
    return false;
  }
  if(firstline.find("DataFile") == std::string::npos) {
    MESSAGE("No 'DataFile' in first line; this is not mine.");
    return false;
  }
  return true;
}
// ---------------------------------------------------------------------------
// CSdpCodecParseUtil::ParseMediaLevelL
// ---------------------------------------------------------------------------
//
RPointerArray<CSdpMediaField>*
CSdpCodecParseUtil::ParseMediaLevelL()
{
    RStringF headername = iPool.StringF( SdpCodecStringConstants::EMedia,
                                         SdpCodecStringConstants::Table );
    TInt linestartPosition = 0;
    TInt lineEndPosition = 0;
    CSdpMediaField* mediafield = NULL;
    TBool endloop = EFalse;
    while(iData.Length() > 0 && !endloop)
    {
        linestartPosition = iData.FindF(headername.DesC());
        if(linestartPosition != KErrNotFound)
        {
            TPtrC8 firstline(iData.Mid(linestartPosition));
            TPtrC8 templine(iData.Mid(linestartPosition + 1));
            HBufC8* searchString =
                HBufC8::NewLC(KCRLFStr().Length() +
                              headername.DesC().Length());
            TPtr8 strPtr(searchString->Des());
            strPtr.Append(KCRLFStr);
            strPtr.Append(headername.DesC());
            lineEndPosition = templine.FindF(strPtr);
            CleanupStack::PopAndDestroy(searchString);
            if(lineEndPosition == KErrNotFound)
            {
                mediafield =
                    CSdpMediaField::DecodeLC(iData.Mid(linestartPosition));
                User::LeaveIfError(iMediaFields->Append(mediafield));
                CleanupStack::Pop();//mediafield
                mediafield = 0;
                iElementArray.Reset();
                iLineArray.Reset();
                endloop = ETrue;
            }
            else
            {
                mediafield =
                    CSdpMediaField::DecodeLC(firstline.Left(
                                                 lineEndPosition+1+KCRLFStr().Length()));
                User::LeaveIfError(iMediaFields->Append(mediafield));
                CleanupStack::Pop();//mediafield
                mediafield = 0;
                iData.Set(firstline.Mid(lineEndPosition+1));
            }
        }
        else
        {
            endloop = ETrue;
        }
    }
    RPointerArray<CSdpMediaField>* array = iMediaFields;
    iMediaFields = 0;
    return array;
}
示例#4
0
文件: llex.c 项目: calandoa/zite
void luaX_setinput (LexState *LS, ZIO *z)
{
  LS->current = '\n';
  LS->linenumber = 0;
  LS->iflevel = 0;
  LS->ifstate[0].skip = 0;
  LS->ifstate[0].elsepart = 1;  /* to avoid a free $else */
  LS->lex_z = z;
  LS->fs = NULL;
  firstline(LS);
  luaL_resetbuffer();
}
示例#5
0
void luaX_setinput(ZIO *z) {
	LexState *LS = lua_state->lexstate;
	LS->current = '\n';
	LS->linelasttoken = 0;
	LS->linenumber = 0;
	LS->iflevel = 0;
	LS->ifstate[0].skip = 0;
	LS->ifstate[0].elsepart = 1;  // to avoid a free $else
	LS->lex_z = z;
	firstline(LS);
	luaL_resetbuffer();
}
示例#6
0
bool KatePrinter::print (KateDocument *doc)
{
  QPrinter printer;
  readSettings(printer);

  // docname is now always there, including the right Untitled name
  printer.setDocName(doc->documentName());

  KatePrintTextSettings *kpts = new KatePrintTextSettings;
  KatePrintHeaderFooter *kphf = new KatePrintHeaderFooter;
  KatePrintLayout *kpl = new KatePrintLayout;

  QList<QWidget*> tabs;
  tabs << kpts;
  tabs << kphf;
  tabs << kpl;

  QWidget *parentWidget=doc->widget();

  if ( !parentWidget )
    parentWidget=QApplication::activeWindow();

  QScopedPointer<QPrintDialog> printDialog(KdePrint::createPrintDialog(&printer, KdePrint::SystemSelectsPages, tabs, parentWidget));

  if ( doc->activeView()->selection() ) {
    printer.setPrintRange(QPrinter::Selection);
    printDialog->setOption(QAbstractPrintDialog::PrintSelection, true);
  }

  if ( printDialog->exec() )
  {
    writeSettings(printer);

    KateRenderer renderer(doc, doc->activeKateView());
    renderer.config()->setSchema (kpl->colorScheme());
    renderer.setPrinterFriendly(true);

    QPainter paint( &printer );
    /*
     *        We work in tree cycles:
     *        1) initialize variables and retrieve print settings
     *        2) prepare data according to those settings
     *        3) draw to the printer
     */
    uint pdmWidth = printer.width();
    uint pdmHeight = printer.height();
    int y = 0;
    uint xstart = 0; // beginning point for painting lines
    uint lineCount = 0;
    uint maxWidth = pdmWidth;
    int headerWidth = pdmWidth;
    int startCol = 0;
    int endCol = 0;
    bool pageStarted = true;
    int remainder = 0; // remaining sublines from a wrapped line (for the top of a new page)

    // Text Settings Page
    bool selectionOnly = (printDialog->printRange() == QAbstractPrintDialog::Selection);
    bool useGuide = kpts->printGuide();

    bool printLineNumbers = kpts->printLineNumbers();
    uint lineNumberWidth( 0 );

    // Header/Footer Page
    QFont headerFont(kphf->font()); // used for header/footer

    bool useHeader = kphf->useHeader();
    QColor headerBgColor(kphf->headerBackground());
    QColor headerFgColor(kphf->headerForeground());
    uint headerHeight( 0 ); // further init only if needed
    QStringList headerTagList; // do
    bool headerDrawBg = false; // do

    bool useFooter = kphf->useFooter();
    QColor footerBgColor(kphf->footerBackground());
    QColor footerFgColor(kphf->footerForeground());
    uint footerHeight( 0 ); // further init only if needed
    QStringList footerTagList; // do
    bool footerDrawBg = false; // do

    // Layout Page
    renderer.config()->setSchema( kpl->colorScheme() );
    bool useBackground = kpl->useBackground();
    bool useBox = kpl->useBox();
    int boxWidth(kpl->boxWidth());
    QColor boxColor(kpl->boxColor());
    int innerMargin = useBox ? kpl->boxMargin() : 6;

    // Post initialization
    int maxHeight = (useBox ? pdmHeight-innerMargin : pdmHeight);
    uint currentPage( 1 );
    uint lastline = doc->lastLine(); // necessary to print selection only
    uint firstline( 0 );
    const int fontHeight = renderer.fontHeight();
    KTextEditor::Range selectionRange;

    /*
    *        Now on for preparations...
    *        during preparations, variable names starting with a "_" means
    *        those variables are local to the enclosing block.
    */
    {
      if ( selectionOnly )
      {
        // set a line range from the first selected line to the last
        selectionRange = doc->activeView()->selectionRange();
        firstline = selectionRange.start().line();
        lastline = selectionRange.end().line();
        lineCount = firstline;
      }

      if ( printLineNumbers )
      {
        // figure out the horiizontal space required
        QString s( QString("%1 ").arg( doc->lines() ) );
        s.fill('5', -1); // some non-fixed fonts haven't equally wide numbers
        // FIXME calculate which is actually the widest...
        lineNumberWidth = renderer.currentFontMetrics().width( s );
        // a small space between the line numbers and the text
        int _adj = renderer.currentFontMetrics().width( "5" );
        // adjust available width and set horizontal start point for data
        maxWidth -= (lineNumberWidth + _adj);
        xstart += lineNumberWidth + _adj;
      }

      if ( useHeader || useFooter )
      {
        // Set up a tag map
        // This retrieves all tags, ued or not, but
        // none of theese operations should be expensive,
        // and searcing each tag in the format strings is avoided.
        QDateTime dt = QDateTime::currentDateTime();
        QMap<QString,QString> tags;

        KUser u (KUser::UseRealUserID);
        tags["u"] = u.loginName();

        tags["d"] = KGlobal::locale()->formatDateTime(dt, KLocale::ShortDate);
        tags["D"] =  KGlobal::locale()->formatDateTime(dt, KLocale::LongDate);
        tags["h"] =  KGlobal::locale()->formatTime(dt.time(), false);
        tags["y"] =  KGlobal::locale()->formatDate(dt.date(), KLocale::ShortDate);
        tags["Y"] =  KGlobal::locale()->formatDate(dt.date(), KLocale::LongDate);
        tags["f"] =  doc->url().fileName();
        tags["U"] =  doc->url().prettyUrl();
        if ( selectionOnly )
        {
          QString s( i18n("(Selection of) ") );
          tags["f"].prepend( s );
          tags["U"].prepend( s );
        }

        QRegExp reTags( "%([dDfUhuyY])" ); // TODO tjeck for "%%<TAG>"

        if (useHeader)
        {
          headerDrawBg = kphf->useHeaderBackground();
          headerHeight = QFontMetrics( headerFont ).height();
          if ( useBox || headerDrawBg )
            headerHeight += innerMargin * 2;
          else
            headerHeight += 1 + QFontMetrics( headerFont ).leading();

          headerTagList = kphf->headerFormat();
          QMutableStringListIterator it(headerTagList);
          while ( it.hasNext() ) {
            QString tag = it.next();
            int pos = reTags.indexIn( tag );
            QString rep;
            while ( pos > -1 )
            {
              rep = tags[reTags.cap( 1 )];
              tag.replace( (uint)pos, 2, rep );
              pos += rep.length();
              pos = reTags.indexIn( tag, pos );
            }
            it.setValue( tag );
          }

          if (!headerBgColor.isValid())
            headerBgColor = Qt::lightGray;
          if (!headerFgColor.isValid())
            headerFgColor = Qt::black;
        }

        if (useFooter)
        {
          footerDrawBg = kphf->useFooterBackground();
          footerHeight = QFontMetrics( headerFont ).height();
          if ( useBox || footerDrawBg )
            footerHeight += 2*innerMargin;
          else
            footerHeight += 1; // line only

          footerTagList = kphf->footerFormat();
          QMutableStringListIterator it(footerTagList);
          while ( it.hasNext() ) {
            QString tag = it.next();
            int pos = reTags.indexIn( tag );
            QString rep;
            while ( pos > -1 )
            {
              rep = tags[reTags.cap( 1 )];
              tag.replace( (uint)pos, 2, rep );
              pos += rep.length();
              pos = reTags.indexIn( tag, pos );
            }
            it.setValue( tag );
          }

          if (!footerBgColor.isValid())
            footerBgColor = Qt::lightGray;
          if (!footerFgColor.isValid())
            footerFgColor = Qt::black;
          // adjust maxheight, so we can know when/where to print footer
          maxHeight -= footerHeight;
        }
      } // if ( useHeader || useFooter )

      if ( useBackground )
      {
        if ( ! useBox )
        {
          xstart += innerMargin;
          maxWidth -= innerMargin * 2;
        }
      }

      if ( useBox )
      {
        if (!boxColor.isValid())
          boxColor = Qt::black;
        if (boxWidth < 1) // shouldn't be pssible no more!
          boxWidth = 1;
        // set maxwidth to something sensible
        maxWidth -= ( ( boxWidth + innerMargin )  * 2 );
        xstart += boxWidth + innerMargin;
        // maxheight too..
        maxHeight -= boxWidth;
      }
      else
        boxWidth = 0;

      // now that we know the vertical amount of space needed,
      // it is possible to calculate the total number of pages
      // if needed, that is if any header/footer tag contains "%P".
      if ( !headerTagList.filter("%P").isEmpty() || !footerTagList.filter("%P").isEmpty() )
      {
        kDebug(13020)<<"'%P' found! calculating number of pages...";
        int pageHeight = maxHeight;
        if ( useHeader )
          pageHeight -= ( headerHeight + innerMargin );
        if ( useFooter )
          pageHeight -= innerMargin;
        const int linesPerPage = pageHeight / fontHeight;
//         kDebug() << "Lines per page:" << linesPerPage;
        
        // calculate total layouted lines in the document
        int totalLines = 0;
        // TODO: right now ignores selection printing
        for (int i = firstline; i <= lastline; ++i) {
          KateLineLayoutPtr rangeptr(new KateLineLayout(doc));
          rangeptr->setLine(i);
          renderer.layoutLine(rangeptr, (int)maxWidth, false);
          totalLines += rangeptr->viewLineCount();
        }
        int totalPages = (totalLines / linesPerPage)
                      + ((totalLines % linesPerPage) > 0 ? 1 : 0);
//         kDebug() << "_______ pages:" << (totalLines / linesPerPage);
//         kDebug() << "________ rest:" << (totalLines % linesPerPage);

        // TODO: add space for guide if required
//         if ( useGuide )
//           _lt += (guideHeight + (fontHeight /2)) / fontHeight;

        // substitute both tag lists
        QString re("%P");
        QStringList::Iterator it;
        for ( it=headerTagList.begin(); it!=headerTagList.end(); ++it )
          (*it).replace( re, QString( "%1" ).arg( totalPages ) );
        for ( it=footerTagList.begin(); it!=footerTagList.end(); ++it )
          (*it).replace( re, QString( "%1" ).arg( totalPages ) );
      }
    } // end prepare block

     /*
        On to draw something :-)
     */
    while (  lineCount <= lastline  )
    {
      startCol = 0;
      endCol = 0;

      if ( y + fontHeight > maxHeight )
      {
        kDebug(13020)<<"Starting new page,"<<lineCount<<"lines up to now.";
        printer.newPage();
        paint.resetTransform();
        currentPage++;
        pageStarted = true;
        y=0;
      }

      if ( pageStarted )
      {
        if ( useHeader )
        {
          paint.setPen(headerFgColor);
          paint.setFont(headerFont);
          if ( headerDrawBg )
            paint.fillRect(0, 0, headerWidth, headerHeight, headerBgColor);
          if (headerTagList.count() == 3)
          {
            int valign = ( (useBox||headerDrawBg||useBackground) ?
            Qt::AlignVCenter : Qt::AlignTop );
            int align = valign|Qt::AlignLeft;
            int marg = ( useBox || headerDrawBg ) ? innerMargin : 0;
            if ( useBox ) marg += boxWidth;
            QString s;
            for (int i=0; i<3; i++)
            {
              s = headerTagList[i];
              if (s.indexOf("%p") != -1) s.replace("%p", QString::number(currentPage));
              paint.drawText(marg, 0, headerWidth-(marg*2), headerHeight, align, s);
              align = valign|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight);
            }
          }
          if ( ! ( headerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate header from contents
          {
            paint.drawLine( 0, headerHeight-1, headerWidth, headerHeight-1 );
            //y += 1; now included in headerHeight
          }
          y += headerHeight + innerMargin;
        }

        if ( useFooter )
        {
          paint.setPen(footerFgColor);
          if ( ! ( footerDrawBg || useBox || useBackground ) ) // draw a 1 px (!?) line to separate footer from contents
            paint.drawLine( 0, maxHeight + innerMargin - 1, headerWidth, maxHeight + innerMargin - 1 );
          if ( footerDrawBg )
            paint.fillRect(0, maxHeight+innerMargin+boxWidth, headerWidth, footerHeight, footerBgColor);
          if (footerTagList.count() == 3)
          {
            int align = Qt::AlignVCenter|Qt::AlignLeft;
            int marg = ( useBox || footerDrawBg ) ? innerMargin : 0;
            if ( useBox ) marg += boxWidth;
            QString s;
            for (int i=0; i<3; i++)
            {
              s = footerTagList[i];
              if (s.indexOf("%p") != -1) s.replace("%p", QString::number(currentPage));
              paint.drawText(marg, maxHeight+innerMargin, headerWidth-(marg*2), footerHeight, align, s);
              align = Qt::AlignVCenter|(i == 0 ? Qt::AlignHCenter : Qt::AlignRight);
            }
          }
        } // done footer

        if ( useBackground )
        {
          // If we have a box, or the header/footer has backgrounds, we want to paint
          // to the border of those. Otherwise just the contents area.
          int _y = y, _h = maxHeight - y;
          if ( useBox )
          {
            _y -= innerMargin;
            _h += 2 * innerMargin;
          }
          else
          {
            if ( headerDrawBg )
            {
              _y -= innerMargin;
              _h += innerMargin;
            }
            if ( footerDrawBg )
            {
              _h += innerMargin;
            }
          }
          paint.fillRect( 0, _y, pdmWidth, _h, renderer.config()->backgroundColor());
        }

        if ( useBox )
        {
          paint.setPen(QPen(boxColor, boxWidth));
          paint.drawRect(0, 0, pdmWidth, pdmHeight);
          if (useHeader)
            paint.drawLine(0, headerHeight, headerWidth, headerHeight);
          else
            y += innerMargin;

          if ( useFooter ) // drawline is not trustable, grr.
            paint.fillRect( 0, maxHeight+innerMargin, headerWidth, boxWidth, boxColor );
        }

        if ( useGuide && currentPage == 1 )
        {  // FIXME - this may span more pages...
          // draw a box unless we have boxes, in which case we end with a box line
          int _ystart = y;
          QString _hlName = doc->highlight()->name();

          QList<KateExtendedAttribute::Ptr> _attributes; // list of highlight attributes for the legend
          doc->highlight()->getKateExtendedAttributeList(kpl->colorScheme(), _attributes);

          KateAttributeList _defaultAttributes;
          KateHlManager::self()->getDefaults ( renderer.config()->schema(), _defaultAttributes );

          QColor _defaultPen = _defaultAttributes.at(0)->foreground().color();
          paint.setPen(_defaultPen);

          int _marg = 0;
          if ( useBox )
            _marg += (2*boxWidth) + (2*innerMargin);
          else
          {
            if ( useBackground )
              _marg += 2*innerMargin;
            _marg += 1;
            y += 1 + innerMargin;
          }

          // draw a title string
          QFont _titleFont = renderer.config()->font();
          _titleFont.setBold(true);
          paint.setFont( _titleFont );
          QRect _r;
          paint.drawText( QRect(_marg, y, pdmWidth-(2*_marg), maxHeight - y),
            Qt::AlignTop|Qt::AlignHCenter,
            i18n("Typographical Conventions for %1", _hlName ), &_r );
          int _w = pdmWidth - (_marg*2) - (innerMargin*2);
          int _x = _marg + innerMargin;
          y += _r.height() + innerMargin;
          paint.drawLine( _x, y, _x + _w, y );
          y += 1 + innerMargin;

          int _widest( 0 );
          foreach (const KateExtendedAttribute::Ptr &attribute, _attributes)
            _widest = qMax(QFontMetrics(attribute->font()).width(attribute->name().section(':',1,1)), _widest);

          int _guideCols = _w/( _widest + innerMargin );

          // draw attrib names using their styles
          int _cw = _w/_guideCols;
          int _i(0);

          _titleFont.setUnderline(true);
          QString _currentHlName;
          foreach (const KateExtendedAttribute::Ptr &attribute, _attributes)
          {
            QString _hl = attribute->name().section(':',0,0);
            QString _name = attribute->name().section(':',1,1);
            if ( _hl != _hlName && _hl != _currentHlName ) {
              _currentHlName = _hl;
              if ( _i%_guideCols )
                y += fontHeight;
              y += innerMargin;
              paint.setFont(_titleFont);
              paint.setPen(_defaultPen);
              paint.drawText( _x, y, _w, fontHeight, Qt::AlignTop, _hl + ' ' + i18n("text") );
              y += fontHeight;
              _i = 0;
            }

            KTextEditor::Attribute _attr =  *_defaultAttributes[attribute->defaultStyleIndex()];
            _attr += *attribute;
            paint.setPen( _attr.foreground().color() );
            paint.setFont( _attr.font() );

            if (_attr.hasProperty(QTextFormat::BackgroundBrush) ) {
              QRect _rect = QFontMetrics(_attr.font()).boundingRect(_name);
              _rect.moveTo(_x + ((_i%_guideCols)*_cw), y);
               paint.fillRect(_rect, _attr.background() );
            }

            paint.drawText(( _x + ((_i%_guideCols)*_cw)), y, _cw, fontHeight, Qt::AlignTop, _name );

            _i++;
            if ( _i && ! ( _i%_guideCols ) )
              y += fontHeight;
          }

          if ( _i%_guideCols )
            y += fontHeight;// last row not full

          // draw a box around the legend
          paint.setPen ( _defaultPen );
          if ( useBox )
            paint.fillRect( 0, y+innerMargin, headerWidth, boxWidth, boxColor );
          else
          {
            _marg -=1;
            paint.drawRect( _marg, _ystart, pdmWidth-(2*_marg), y-_ystart+innerMargin );
          }

          y += ( useBox ? boxWidth : 1 ) + (innerMargin*2);
        } // useGuide

        paint.translate(xstart,y);
        pageStarted = false;
      } // pageStarted; move on to contents:)
示例#7
0
文件: smtpd.c 项目: 99years/plan9
void
data(void)
{
	int status, nbytes;
	char *cp, *ep;
	char errx[ERRMAX];
	Link *l;
	String *cmd, *err;

	if(rejectcheck())
		return;
	if(senders.last == 0){
		reply("503 2.5.2 Data without MAIL FROM:\r\n");
		rejectcount++;
		return;
	}
	if(rcvers.last == 0){
		reply("503 2.5.2 Data without RCPT TO:\r\n");
		rejectcount++;
		return;
	}
	if(!trusted && sendermxcheck()){
		rerrstr(errx, sizeof errx);
		if(strncmp(errx, "rejected:", 9) == 0)
			reply("554 5.7.1 %s\r\n", errx);
		else
			reply("450 4.7.0 %s\r\n", errx);
		for(l=rcvers.first; l; l=l->next)
			syslog(0, "smtpd", "[%s/%s] %s -> %s sendercheck: %s",
				him, nci->rsys, s_to_c(senders.first->p),
				s_to_c(l->p), errx);
		rejectcount++;
		return;
	}

	cmd = startcmd();
	if(cmd == 0)
		return;

	reply("354 Input message; end with <CRLF>.<CRLF>\r\n");
	if(debug){
		seek(2, 0, 2);
		stamp();
		fprint(2, "# sent 354; accepting DATA %s\n", thedate());
	}


	/*
	 *  allow 145 more minutes to move the data
	 */
	alarm(145*60*1000);

	status = pipemsg(&nbytes);

	/*
	 *  read any error messages
	 */
	err = s_new();
	if (debug) {
		stamp();
		fprint(2, "waiting for upas/send to close stderr\n");
	}
	while(s_read_line(pp->std[2]->fp, err))
		;

	alarm(0);
	atnotify(catchalarm, 0);

	if (debug) {
		stamp();
		fprint(2, "waiting for upas/send to exit\n");
	}
	status |= proc_wait(pp);
	if(debug){
		seek(2, 0, 2);
		stamp();
		fprint(2, "# %d upas/send status %#ux at %s\n",
			getpid(), status, thedate());
		if(*s_to_c(err))
			fprint(2, "# %d error %s\n", getpid(), s_to_c(err));
	}

	/*
	 *  if process terminated abnormally, send back error message
	 */
	if(status){
		int code;
		char *ecode;

		if(strstr(s_to_c(err), "mail refused")){
			syslog(0, "smtpd", "++[%s/%s] %s %s refused: %s",
				him, nci->rsys, s_to_c(senders.first->p),
				s_to_c(cmd), firstline(s_to_c(err)));
			code = 554;
			ecode = "5.0.0";
		} else {
			syslog(0, "smtpd", "++[%s/%s] %s %s %s%s%sreturned %#q %s",
				him, nci->rsys,
				s_to_c(senders.first->p), s_to_c(cmd),
				piperror? "error during pipemsg: ": "",
				piperror? piperror: "",
				piperror? "; ": "",
				pp->waitmsg->msg, firstline(s_to_c(err)));
			code = 450;
			ecode = "4.0.0";
		}
		for(cp = s_to_c(err); ep = strchr(cp, '\n'); cp = ep){
			*ep++ = 0;
			reply("%d-%s %s\r\n", code, ecode, cp);
		}
		reply("%d %s mail process terminated abnormally\r\n",
			code, ecode);
	} else {
		/*
		 * if a message appeared on stderr, despite good status,
		 * log it.  this can happen if rewrite.in contains a bad
		 * r.e., for example.
		 */
		if(*s_to_c(err))
			syslog(0, "smtpd",
				"%s returned good status, but said: %s",
				s_to_c(mailer), s_to_c(err));

		if(filterstate == BLOCKED)
			reply("554 5.7.1 we believe this is spam.  "
				"we don't accept it.\r\n");
		else if(filterstate == DELAY)
			reply("450 4.3.0 There will be a delay in delivery "
				"of this message.\r\n");
		else {
			reply("250 2.5.0 sent\r\n");
			logcall(nbytes);
			if(debug){
				seek(2, 0, 2);
				stamp();
				fprint(2, "# %d sent 250 reply %s\n",
					getpid(), thedate());
			}
		}
	}
	proc_free(pp);
	pp = 0;
	s_free(cmd);
	s_free(err);

	listfree(&senders);
	listfree(&rcvers);
}