view octave-bug.cc.in @ 10843:229675bb7647 ss-3-3-52

version is now 3.3.52
author John W. Eaton <jwe@octave.org>
date Sun, 01 Aug 2010 11:49:45 -0400
parents d36f8c473dff
children
line wrap: on
line source

/*

Copyright (C) 2008, 2009 Michael Goffioul

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>

#include <windows.h>
#include <mapi.h>
#include <unistd.h>

using namespace std;

static map<string,string> vars;

static void
usage (void)
{
  cerr << "usage: octave-bug [-s subject]" << endl;
  exit (-1);
}

static void
error (const string& msg)
{
  cerr << "error: " << msg << endl;
  exit (-1);
}

static void
warning (const string& msg)
{
  cerr << "warning: " << msg << endl;
}

static string
get_env_variable (const char *name)
{
  char *value = ::getenv (name);
  if (value)
    return string (value);
  else
    return string ("");
}

inline bool
starts_with (const string& s, const string& prefix)
{
  return (s.length () >= prefix.length () && s.find (prefix) == 0);
}

int
main (int argc, char **argv)
{
  int arg_idx = 1;

  vars["config_optvars"] = %OCTAVE_CONF_config_opts%;
  vars["VERSION"] = %OCTAVE_CONF_VERSION%;
  vars["SED"] = %OCTAVE_CONF_SED%;
  vars["MACHINE"] = %OCTAVE_CONF_CANONICAL_HOST_TYPE%;
  vars["F77"] = %OCTAVE_CONF_F77%;
  vars["FFLAGS"] = %OCTAVE_CONF_FFLAGS%;
  vars["FPICFLAG"] = %OCTAVE_CONF_FPICFLAG%;
  vars["FLIBS"] = %OCTAVE_CONF_FLIBS%;
  vars["CPPFLAGS"] = %OCTAVE_CONF_CPPFLAGS%;
  vars["INCFLAGS"] = %OCTAVE_CONF_INCFLAGS%;
  vars["CC"] = %OCTAVE_CONF_CC%;
  vars["CC_VERSION"] = %OCTAVE_CONF_CC_VERSION%;
  vars["CFLAGS"] = %OCTAVE_CONF_CFLAGS%;
  vars["CPICFLAG"] = %OCTAVE_CONF_CPICFLAG%;
  vars["CXX"] = %OCTAVE_CONF_CXX%;
  vars["CXX_VERSION"] = %OCTAVE_CONF_CXX_VERSION%;
  vars["CXXFLAGS"] = %OCTAVE_CONF_CXXFLAGS%;
  vars["CXXPICFLAG"] = %OCTAVE_CONF_CXXPICFLAG%;
  vars["LD_CXX"] = %OCTAVE_CONF_LD_CXX%;
  vars["LDFLAGS"] = %OCTAVE_CONF_LDFLAGS%;
  vars["LIBFLAGS"] = %OCTAVE_CONF_LIBFLAGS%;
  vars["RLD_FLAG"] = %OCTAVE_CONF_RLD_FLAG%;
  vars["LIBS"] = %OCTAVE_CONF_LIBS%;
  vars["LEXLIB"] = %OCTAVE_CONF_LEXLIB%;

  vars["AMD_CPPFLAGS"] = %OCTAVE_CONF_AMD_CPPFLAGS%;
  vars["AMD_LDFLAGS"] = %OCTAVE_CONF_AMD_LDFLAGS%;
  vars["AMD_LIBS"] = %OCTAVE_CONF_AMD_LIBS%;
  vars["ARPACK_CPPFLAGS"] = %OCTAVE_CONF_ARPACK_CPPFLAGS%;
  vars["ARPACK_LDFLAGS"] = %OCTAVE_CONF_ARPACK_LDFLAGS%;
  vars["ARPACK_LIBS"] = %OCTAVE_CONF_ARPACK_LIBS%;
  vars["BLAS_LIBS"] = %OCTAVE_CONF_BLAS_LIBS%;
  vars["CAMD_CPPFLAGS"] = %OCTAVE_CONF_CAMD_CPPFLAGS%;
  vars["CAMD_LDFLAGS"] = %OCTAVE_CONF_CAMD_LDFLAGS%;
  vars["CAMD_LIBS"] = %OCTAVE_CONF_CAMD_LIBS%;
  vars["CARBON_LIBS"] = %OCTAVE_CONF_CARBON_LIBS%;
  vars["CCOLAMD_CPPFLAGS"] = %OCTAVE_CONF_CCOLAMD_CPPFLAGS%;
  vars["CCOLAMD_LDFLAGS"] = %OCTAVE_CONF_CCOLAMD_LDFLAGS%;
  vars["CCOLAMD_LIBS"] = %OCTAVE_CONF_CCOLAMD_LIBS%;
  vars["CHOLMOD_CPPFLAGS"] = %OCTAVE_CONF_CHOLMOD_CPPFLAGS%;
  vars["CHOLMOD_LDFLAGS"] = %OCTAVE_CONF_CHOLMOD_LDFLAGS%;
  vars["CHOLMOD_LIBS"] = %OCTAVE_CONF_CHOLMOD_LIBS%;
  vars["COLAMD_CPPFLAGS"] = %OCTAVE_CONF_COLAMD_CPPFLAGS%;
  vars["COLAMD_LDFLAGS"] = %OCTAVE_CONF_COLAMD_LDFLAGS%;
  vars["COLAMD_LIBS"] = %OCTAVE_CONF_COLAMD_LIBS%;
  vars["CURL_CPPFLAGS"] = %OCTAVE_CONF_CURL_CPPFLAGS%;
  vars["CURL_LDFLAGS"] = %OCTAVE_CONF_CURL_LDFLAGS%;
  vars["CURL_LIBS"] = %OCTAVE_CONF_CURL_LIBS%;
  vars["CXSPARSE_CPPFLAGS"] = %OCTAVE_CONF_CXSPARSE_CPPFLAGS%;
  vars["CXSPARSE_LDFLAGS"] = %OCTAVE_CONF_CXSPARSE_LDFLAGS%;
  vars["CXSPARSE_LIBS"] = %OCTAVE_CONF_CXSPARSE_LIBS%;
  vars["DL_LIBS"] = %OCTAVE_CONF_DL_LIBS%;
  vars["FFTW3_CPPFLAGS"] = %OCTAVE_CONF_FFTW3_CPPFLAGS%;
  vars["FFTW3_LDFLAGS"] = %OCTAVE_CONF_FFTW3_LDFLAGS%;
  vars["FFTW3_LIBS"] = %OCTAVE_CONF_FFTW3_LIBS%;
  vars["FFTW3F_CPPFLAGS"] = %OCTAVE_CONF_FFTW3F_CPPFLAGS%;
  vars["FFTW3F_LDFLAGS"] = %OCTAVE_CONF_FFTW3F_LDFLAGS%;
  vars["FFTW3F_LIBS"] = %OCTAVE_CONF_FFTW3F_LIBS%;
  vars["GRAPHICS_LIBS"] = %OCTAVE_CONF_GRAPHICS_LIBS%;
  vars["GLPK_CPPFLAGS"] = %OCTAVE_CONF_GLPK_CPPFLAGS%;
  vars["GLPK_LDFLAGS"] = %OCTAVE_CONF_GLPK_LDFLAGS%;
  vars["GLPK_LIBS"] = %OCTAVE_CONF_GLPK_LIBS%;
  vars["HDF5_CPPFLAGS"] = %OCTAVE_CONF_HDF5_CPPFLAGS%;
  vars["HDF5_LDFLAGS"] = %OCTAVE_CONF_HDF5_LDFLAGS%;
  vars["HDF5_LIBS"] = %OCTAVE_CONF_HDF5_LIBS%;
  vars["OPENGL_LIBS"] = %OCTAVE_CONF_OPENGL_LIBS%;
  vars["PTHREAD_CFLAGS"] = %OCTAVE_CONF_PTHREAD_CFLAGS%;
  vars["PTHREAD_LIBS"] = %OCTAVE_CONF_PTHREAD_LIBS%;
  vars["QHULL_CPPFLAGS"] = %OCTAVE_CONF_QHULL_CPPFLAGS%;
  vars["QHULL_LDFLAGS"] = %OCTAVE_CONF_QHULL_LDFLAGS%;
  vars["QHULL_LIBS"] = %OCTAVE_CONF_QHULL_LIBS%;
  vars["QRUPDATE_CPPFLAGS"] = %OCTAVE_CONF_QRUPDATE_CPPFLAGS%;
  vars["QRUPDATE_LDFLAGS"] = %OCTAVE_CONF_QRUPDATE_LDFLAGS%;
  vars["QRUPDATE_LIBS"] = %OCTAVE_CONF_QRUPDATE_LIBS%;
  vars["READLINE_LIBS"] = %OCTAVE_CONF_READLINE_LIBS%;
  vars["REGEX_LIBS"] = %OCTAVE_CONF_REGEX_LIBS%;
  vars["TERM_LIBS"] = %OCTAVE_CONF_TERM_LIBS%;
  vars["UMFPACK_CPPFLAGS"] = %OCTAVE_CONF_UMFPACK_CPPFLAGS%;
  vars["UMFPACK_LDFLAGS"] = %OCTAVE_CONF_UMFPACK_LDFLAGS%;
  vars["UMFPACK_LIBS"] = %OCTAVE_CONF_UMFPACK_LIBS%;
  vars["X11_INCFLAGS"] = %OCTAVE_CONF_X11_INCFLAGS%;
  vars["X11_LIBS"] = %OCTAVE_CONF_X11_LIBS%;
  vars["Z_CPPFLAGS"] = %OCTAVE_CONF_Z_CPPFLAGS%;
  vars["Z_LDFLAGS"] = %OCTAVE_CONF_Z_LDFLAGS%;
  vars["Z_LIBS"] = %OCTAVE_CONF_Z_LIBS%;

  vars["DEFS"] = %OCTAVE_CONF_DEFS%;

  vars["USER"] = get_env_variable ("LOGNAME");
  if (vars["USER"].empty ())
    vars["USER"] = get_env_variable ("USERNAME");

  vars["CC_AND_VERSION"] = (vars["CC"] + ", version" + vars["CC_VERSION"]);
  
  vars["CXX_AND_VERSION"] = (vars["CXX"] + ", version" + vars["CXX_VERSION"]);

  // FIXME -- could be obtained from OS.
  vars["UN"] = "Windows";

  // FIXME -- the shell script also checks the minor version number,
  // and if it is greater than or equal to 90, it is assumed that this
  // version of Octave is a test release and bugs should go to the
  // maintainers@octave.org list instead of bugs.
  if (starts_with (vars["VERSION"], "ss"))
    vars["BUGADDR"] = "maintainers@octave.org";
  else
    vars["BUGADDR"] = "bug@octave.org";

  vars["SUBJECT"] = "[50 character or so descriptive subject here (for reference)]";
  if (arg_idx < argc && strcmp (argv[arg_idx], "-s") == 0)
    {
      arg_idx++;
      if (arg_idx < argc)
	vars["SUBJECT"] = argv[arg_idx++];
      else
	usage ();
    }

  ostringstream os;

  os << "Bug report for Octave " << vars["VERSION"] << " configured for " << vars["MACHINE"] << endl;
  os << endl;
  os << "Description:" << endl;
  os << "-----------" << endl;
  os << endl;
  os << "  * Please replace this item with a detailed description of the" << endl;
  os << "    problem.  Suggestions or general comments are also welcome." << endl;
  os << endl;
  os << "Repeat-By:" << endl;
  os << "---------" << endl;
  os << endl;
  os << "  * Please replace this item with a description of the sequence of" << endl;
  os << "    events that causes the problem to occur. " << endl;
  os << endl;
  os << "Fix:" << endl;
  os << "---" << endl;
  os << endl;
  os << "  * If possible, replace this item with a description of how to" << endl;
  os << "    fix the problem (if you don't have a fix for the problem, don't" << endl;
  os << "    include this section, but please do submit your report anyway)." << endl;
  os << endl;
  os << endl;
  os << endl;
  os << "Configuration (please do not edit this section):" << endl;
  os << "-----------------------------------------------" << endl;
  os << endl;
  os << "uname output:      " << vars["UN"] << endl;
  os << "SED:               " << vars["SED"] << endl;
  os << "configure opts:    " << vars["config_opts"] << endl;
  os << "Fortran compiler:  " << vars["F77"] << endl;
  os << "FFLAGS:            " << vars["FFLAGS"] << endl;
  os << "FLIBS:             " << vars["FLIBS"] << endl;
  os << "CPPFLAGS:          " << vars["CPPFLAGS"] << endl;
  os << "INCFLAGS:          " << vars["INCFLAGS"] << endl;
  os << "C compiler:        " << vars["CC_AND_VERSION"] << endl;
  os << "CFLAGS:            " << vars["CFLAGS"] << endl;
  os << "CPICFLAG:          " << vars["CPICFLAG"] << endl;
  os << "C++ compiler:      " << vars["CXX_AND_VERSION"] << endl;
  os << "CXXFLAGS:          " << vars["CXXFLAGS"] << endl;
  os << "CXXPICFLAG:        " << vars["CXXPICFLAG"] << endl;
  os << "LD_CXX:            " << vars["LD_CXX"] << endl;
  os << "LDFLAGS:           " << vars["LDFLAGS"] << endl;
  os << "LIBFLAGS:          " << vars["LIBFLAGS"] << endl;
  os << "RLD_FLAG:          " << vars["RLD_FLAG"] << endl;
  os << "BLAS_LIBS:         " << vars["BLAS_LIBS"] << endl;
  os << "FFTW_LIBS:         " << vars["FFTW_LIBS"] << endl;
  os << "LEXLIB:            " << vars["LEXLIB"] << endl;
  os << "LIBS:              " << vars["LIBS"] << endl;
  os << "AMD_CPPFLAGS:      " << vars["AMD_CPPFLAGS"] << endl;
  os << "AMD_LDFLAGS:       " << vars["AMD_LDFLAGS"] << endl;
  os << "AMD_LIBS:          " << vars["AMD_LIBS"] << endl;
  os << "ARPACK_LIBS:       " << vars["ARPACK_LIBS"] << endl;
  os << "BLAS_LIBS:         " << vars["BLAS_LIBS"] << endl;
  os << "CAMD_CPPFLAGS:     " << vars["CAMD_CPPFLAGS"] << endl;
  os << "CAMD_LDFLAGS:      " << vars["CAMD_LDFLAGS"] << endl;
  os << "CAMD_LIBS:         " << vars["CAMD_LIBS"] << endl;
  os << "CARBON_LIBS:       " << vars["CARBON_LIBS"] << endl;
  os << "CCOLAMD_CPPFLAGS:  " << vars["CCOLAMD_CPPFLAGS"] << endl;
  os << "CCOLAMD_LDFLAGS:   " << vars["CCOLAMD_LDFLAGS"] << endl;
  os << "CCOLAMD_LIBS:      " << vars["CCOLAMD_LIBS"] << endl;
  os << "CHOLMOD_CPPFLAGS:  " << vars["CHOLMOD_CPPFLAGS"] << endl;
  os << "CHOLMOD_LDFLAGS:   " << vars["CHOLMOD_LDFLAGS"] << endl;
  os << "CHOLMOD_LIBS:      " << vars["CHOLMOD_LIBS"] << endl;
  os << "COLAMD_CPPFLAGS:   " << vars["COLAMD_CPPFLAGS"] << endl;
  os << "COLAMD_LDFLAGS:    " << vars["COLAMD_LDFLAGS"] << endl;
  os << "COLAMD_LIBS:       " << vars["COLAMD_LIBS"] << endl;
  os << "CURL_CPPFLAGS:     " << vars["CURL_CPPFLAGS"] << endl;
  os << "CURL_LDFLAGS:      " << vars["CURL_LDFLAGS"] << endl;
  os << "CURL_LIBS:         " << vars["CURL_LIBS"] << endl;
  os << "CXSPARSE_CPPFLAGS: " << vars["CXSPARSE_CPPFLAGS"] << endl;
  os << "CXSPARSE_LDFLAGS:  " << vars["CXSPARSE_LDFLAGS"] << endl;
  os << "CXSPARSE_LIBS:     " << vars["CXSPARSE_LIBS"] << endl;
  os << "DL_LIBS:           " << vars["DL_LIBS"] << endl;
  os << "FFTW3_CPPFLAGS:    " << vars["FFTW3_CPPFLAGS"] << endl;
  os << "FFTW3_LDFLAGS:     " << vars["FFTW3_LDFLAGS"] << endl;
  os << "FFTW3_LIBS:        " << vars["FFTW3_LIBS"] << endl;
  os << "FFTW3F_CPPFLAGS:   " << vars["FFTW3F_CPPFLAGS"] << endl;
  os << "FFTW3F_LDFLAGS:    " << vars["FFTW3F_LDFLAGS"] << endl;
  os << "FFTW3F_LIBS:       " << vars["FFTW3F_LIBS"] << endl;
  os << "GRAPHICS_LIBS:     " << vars["GRAPHICS_LIBS"] << endl;
  os << "GLPK_CPPFLAGS:     " << vars["GLPK_CPPFLAGS"] << endl;
  os << "GLPK_LDFLAGS:      " << vars["GLPK_LDFLAGS"] << endl;
  os << "GLPK_LIBS:         " << vars["GLPK_LIBS"] << endl;
  os << "HDF5_CPPFLAGS:     " << vars["HDF5_CPPFLAGS"] << endl;
  os << "HDF5_LDFLAGS:      " << vars["HDF5_LDFLAGS"] << endl;
  os << "HDF5_LIBS:         " << vars["HDF5_LIBS"] << endl;
  os << "OPENGL_LIBS:       " << vars["OPENGL_LIBS"] << endl;
  os << "PTHREAD_CFLAGS:    " << vars["PTHREAD_CFLAGS"] << endl;
  os << "PTHREAD_LIBS:      " << vars["PTHREAD_LIBS"] << endl;
  os << "QHULL_CPPFLAGS:    " << vars["QHULL_CPPFLAGS"] << endl;
  os << "QHULL_LDFLAGS:     " << vars["QHULL_LDFLAGS"] << endl;
  os << "QHULL_LIBS:        " << vars["QHULL_LIBS"] << endl;
  os << "QRUPDATE_LIBS:     " << vars["QRUPDATE_LIBS"] << endl;
  os << "READLINE_LIBS:     " << vars["READLINE_LIBS"] << endl;
  os << "REGEX_LIBS:        " << vars["REGEX_LIBS"] << endl;
  os << "TERM_LIBS:         " << vars["TERM_LIBS"] << endl;
  os << "UMFPACK_LIBS:      " << vars["UMFPACK_LIBS"] << endl;
  os << "X11_INCFLAGS:      " << vars["X11_INCFLAGS"] << endl;
  os << "X11_LIBS:          " << vars["X11_LIBS"] << endl;
  os << "Z_CPPFLAGS:        " << vars["Z_CPPFLAGS"] << endl;
  os << "Z_LDFLAGS:         " << vars["Z_LDFLAGS"] << endl;
  os << "Z_LIBS:            " << vars["Z_LIBS"] << endl;
  os << "DEFS:" << endl << vars["DEFS"] << endl;
  os << endl;

  if (arg_idx < argc)
    {
      os << endl;
      os << "User-preferences (please do not edit this section):" << endl;
      os << endl;

      ifstream is (argv[arg_idx++]);

      if (! is.fail ())
	{
	  string line;

	  while (! is.eof ())
	    {
	      getline (is, line);
	      os << line << endl;
	    }
	}
      else
	{
	  string msg ("unable to open file for reading: ");

	  msg += argv[arg_idx-1];
	  warning (msg);
	}
    }

  string content = os.str (), msg;

  // Now go for MAPI stuff.

  HMODULE hMapi;
  LHANDLE session;
  LPMAPILOGON mapiLogon;
  LPMAPILOGOFF mapiLogoff;
  LPMAPISENDMAIL mapiSendMail;

  hMapi = LoadLibrary ("mapi32.dll");
  if (hMapi != NULL)
    {
      mapiLogon = (LPMAPILOGON) GetProcAddress (hMapi, "MAPILogon");
      mapiLogoff = (LPMAPILOGOFF) GetProcAddress (hMapi, "MAPILogoff");
      mapiSendMail = (LPMAPISENDMAIL) GetProcAddress (hMapi, "MAPISendMail");

      if (mapiLogon != NULL && mapiLogoff != NULL
	  && mapiSendMail != NULL)
	{
	  ULONG result = 0;

	  if ((result = mapiLogon (0, "", "", MAPI_LOGON_UI, 0, &session)) == SUCCESS_SUCCESS)
	    {
	      MapiMessage mmsg;
	      MapiRecipDesc mrecip[2];

	      ZeroMemory (&mmsg, sizeof (mmsg));
	      ZeroMemory (&mrecip, sizeof (mrecip));

	      mmsg.lpszSubject = strdup (vars["SUBJECT"].c_str ());
	      mmsg.lpszNoteText = strdup (content.c_str ());
	      mmsg.nRecipCount = 1;
	      mmsg.lpRecips = mrecip;

	      mrecip[0].ulRecipClass = MAPI_TO;
	      mrecip[0].lpszName = "Octave";
	      mrecip[0].lpszAddress = strdup (vars["BUGADDR"].c_str ());

	      if (! vars["USER"].empty ())
		{
		  mmsg.nRecipCount = 2;
		  mrecip[1].ulRecipClass = MAPI_CC;
		  mrecip[1].lpszName = strdup (vars["USER"].c_str ());
		}

	      if ((result = mapiSendMail (session, 0, &mmsg, MAPI_DIALOG, 0)) != SUCCESS_SUCCESS
		  && result != MAPI_USER_ABORT)
		msg = "mail not sent";

	      free (mmsg.lpszSubject);
	      free (mmsg.lpszNoteText);
	      free (mrecip[0].lpszAddress);
	      if (mmsg.nRecipCount > 1)
		free (mrecip[1].lpszName);

	      mapiLogoff (session, 0, 0, 0);
	    }
	  else
	    msg = "cannot logon to MAPI service";

	  if (! msg.empty ())
	    {
	      char buf[64];
	      _snprintf (buf, 63, "%08x", result);
	      msg += (" (result: " + string (buf) + ")");
	    }
	}
      else
	msg = "cannot find entry points in MAPI library";

      FreeLibrary (hMapi);
    }
  else
    msg = "unable to find MAPI service";

  if (! msg.empty ())
    {
      warning (msg);

      string tmpfile = _tempnam (NULL, "octave-");
      ofstream ofs (tmpfile.c_str ());

      if (! ofs.fail ())
	{
	  ofs << content;
	  ofs.close ();
      
	  warning ("");
	  warning ("the mail could not be sent to octave; a text editor should appear");
	  warning ("with the content of the bug report; please copy it and paste it");
	  warning ("manually into your mail client and send it to the following");
	  warning ("address: " + vars["BUGADDR"]);

	  string cmd ("notepad ");

	  cmd += tmpfile;
	  ::system (cmd.c_str ());
	  ::unlink (tmpfile.c_str ());
	}
      else
	error ("unable to open file for writing: " + tmpfile);
    }

  return 0;
}