Example #1
0
void eqnsys<nr_type_t>::solve_gauss (void) {
  nr_double_t MaxPivot;
  nr_type_t f;
  int i, c, r, pivot;

  // triangulate the matrix
  for (i = 0; i < N; i++) {
    // find maximum column value for pivoting
    for (MaxPivot = 0, pivot = r = i; r < N; r++) {
      if (abs (A_(r, i)) > MaxPivot) {
	MaxPivot = abs (A_(r, i));
	pivot = r;
      }
    }
    // exchange rows if necessary
    assert (MaxPivot != 0);
    if (i != pivot) {
      A->exchangeRows (i, pivot);
      B->exchangeRows (i, pivot);
    }
    // compute new rows and columns
    for (r = i + 1; r < N; r++) {
      f = A_(r, i) / A_(i, i);
      for (c = i + 1; c < N; c++) A_(r, c) -= f * A_(i, c);
      B_(r) -= f * B_(i);
    }
  }

  // backward substitution
  for (i = N - 1; i >= 0; i--) {
    f = B_(i);
    for (c = i + 1; c < N; c++) f -= A_(i, c) * X_(c);
    X_(i) = f / A_(i, i);
  }
}
Example #2
0
void eqnsys<nr_type_t>::substitute_qr_householder_ls (void) {
  int c, r;
  nr_type_t f;

  // forward substitution in order to solve R'X = B
  for (r = 0; r < N; r++) {
    for (f = B_(r), c = 0; c < r; c++) f -= A_(c, r) * B_(c);
    if (abs (A_(r, r)) > std::numeric_limits<nr_double_t>::epsilon())
      B_(r) = f / A_(r, r);
    else
      B_(r) = 0;
  }

  // compute the least square solution QX
  for (c = N - 1; c >= 0; c--) {
    if (T_(c) != 0) {
      // scalar product u' * B
      for (f = B_(c), r = c + 1; r < N; r++) f += cond_conj (A_(r, c)) * B_(r);
      // z - T * f * u_k
      f *= T_(c); B_(c) -= f;
      for (r = c + 1; r < N; r++) B_(r) -= f * A_(r, c);
    }
  }

  // permute solution vector
  for (r = 0; r < N; r++) X_(cMap[r]) = B_(r);
}
Example #3
0
void eqnsys<nr_type_t>::substitute_lu_doolittle (void) {
  nr_type_t f;
  int i, c;

  // forward substitution in order to solve LY = B
  for (i = 0; i < N; i++) {
    f = B_(rMap[i]);
    for (c = 0; c < i; c++) f -= A_(i, c) * X_(c);
    // remember that the Lii diagonal are ones only in Doolittle's definition
    X_(i) = f;
  }

  // backward substitution in order to solve UX = Y
  for (i = N - 1; i >= 0; i--) {
    f = X_(i);
    for (c = i + 1; c < N; c++) f -= A_(i, c) * X_(c);
    X_(i) = f / A_(i, i);
  }
}
Example #4
0
  void DATA::load(std::string fn)
  {
    std::ifstream infile(fn.c_str());
    std::vector<std::string > vec;
    std::string line;
    std::vector<std::vector<std::string>> matrows;
    if(infile.is_open())
      {
        while(getline(infile,line))
          {
            Tokenizer tok(line);
            vec.assign(tok.begin(),tok.end());
            matrows.push_back(vec);
          }
        infile.close();


        int Nrows = matrows.size();
        int Ncols = matrows[0].size();
        int Ngoodrows = 0;
        for(int i = 0; i < Nrows; ++i)
          {
            if(matrows[i].size() == Ncols)
              {
                Ngoodrows++;
              }
          }
        int rc = 0;
        //printinfo("INPUT MATRIX: " + std::to_string(Nrows) +"x" +std::to_string(Ncols));
        X_ = MatrixRMXd(Ngoodrows, Ncols);
        X_.setZero();
        d_ = Ncols;
        n_ = Nrows;
        for(int i = 0; i < Nrows; ++i)
          {
            int rowsize = matrows[i].size();
            if(rowsize != Ncols)
              {
                std::cout << "Row " << i << " has bad column count" << std::endl;
                continue;
              }
            for(int j = 0; j < Ncols; ++j)
              {

                X_(rc,j) = double(round(strtod(matrows[i][j].c_str(), NULL)));
              }
            rc++;
          }
      }
    else
      {
        printerror("Can not open file!");
        EXIT_FAILURE;
      }
  }
Example #5
0
	void X_(Loop)() {
		for(;;) {
			// switch(mode) {
				X_(real1616_Loop)();
			// }
			// when this returns, evaluate what's going on, and
			// here's where switch to protected set happens and "continue;"

			// lastly,
			if(TowerWantsQuit)
				break;
		}
	}
Example #6
0
void eqnsys<nr_type_t>::substitute_qrh (void) {
  int c, r;
  nr_type_t f;

  // form the new right hand side Q'B
  for (c = 0; c < N - 1; c++) {
    // scalar product u_k^T * B
    for (f = 0, r = c; r < N; r++) f += cond_conj (A_(r, c)) * B_(r);
    // z - 2 * f * u_k
    for (r = c; r < N; r++) B_(r) -= 2.0 * f * A_(r, c);
  }

  // backward substitution in order to solve RX = Q'B
  for (r = N - 1; r >= 0; r--) {
    f = B_(r);
    for (c = r + 1; c < N; c++) f -= A_(r, c) * X_(cMap[c]);
    if (abs (R_(r)) > std::numeric_limits<nr_double_t>::epsilon())
      X_(cMap[r]) = f / R_(r);
    else
      X_(cMap[r]) = 0;
  }
}
Example #7
0
void eqnsys<nr_type_t>::substitute_qr_householder (void) {
  int c, r;
  nr_type_t f;

  // form the new right hand side Q'B
  for (c = 0; c < N; c++) {
    if (T_(c) != 0) {
      // scalar product u' * B
      for (f = B_(c), r = c + 1; r < N; r++) f += cond_conj (A_(r, c)) * B_(r);
      // z - T * f * u
      f *= cond_conj (T_(c)); B_(c) -= f;
      for (r = c + 1; r < N; r++) B_(r) -= f * A_(r, c);
    }
  }

  // backward substitution in order to solve RX = Q'B
  for (r = N - 1; r >= 0; r--) {
    for (f = B_(r), c = r + 1; c < N; c++) f -= A_(r, c) * X_(cMap[c]);
    if (abs (A_(r, r)) > std::numeric_limits<nr_double_t>::epsilon())
      X_(cMap[r]) = f / A_(r, r);
    else
      X_(cMap[r]) = 0;
  }
}
Example #8
0
void eqnsys<nr_type_t>::substitute_svd (void) {
  int c, r;
  nr_type_t f;
  // calculate U'B
  for (c = 0; c < N; c++) {
    f = 0.0;
    // non-zero result only if S is non-zero
    if (S_(c) != 0.0) {
      for (r = 0; r < N; r++) f += cond_conj (U_(r, c)) * B_(r);
      // this is the divide by S
      f /= S_(c);
    }
    R_(c) = f;
  }
  // matrix multiply by V to get the final solution
  for (r = 0; r < N; r++) {
    for (f = 0.0, c = 0; c < N; c++) f += cond_conj (V_(c, r)) * R_(c);
    X_(r) = f;
  }
}
const Scalar TrajectoryWalkgen<Scalar>::getJerk() const
{
  return X_(0);
}
bool TrajectoryWalkgen<Scalar>::solve(Scalar feedBackPeriod)
{
  int N = noDynModel_.getNbSamples();
  int M = config_.withMotionConstraints? motionConstraint_.getNbConstraints() : 0;

  assert(velTrackingObj_.getGradient(X_).size() == N);
  assert(posTrackingObj_.getGradient(X_).size() == N);
  assert(jerkMinObj_.getGradient(X_).size() == N);

  if (config_.withMotionConstraints)
  {
    assert(motionConstraint_.getFunctionInf(X_).size() == M);
    assert(motionConstraint_.getFunctionSup(X_).size() == M);
  }

  assert(feedBackPeriod>0);

  qpMatrix_.p.fill(Scalar(0.0));
  qpMatrix_.bu.fill(Scalar(10e10));
  qpMatrix_.bl.fill(Scalar(-10e10));
  qpMatrix_.xu.fill(Scalar(10e10));
  qpMatrix_.xl.fill(Scalar(-10e10));

  if (weighting_.velocityTracking>0.0)
  {
    qpMatrix_.p +=
       weighting_.velocityTracking*velTrackingObj_.getGradient(X_);
  }
  if (weighting_.positionTracking>0.0)
  {
    qpMatrix_.p +=
        weighting_.positionTracking*posTrackingObj_.getGradient(X_);
  }
  if (weighting_.jerkMinimization>0.0)
  {
    qpMatrix_.p += weighting_.jerkMinimization*jerkMinObj_.getGradient(X_);
  }

  if (config_.withMotionConstraints)
  {
    qpMatrix_.bl.segment(0, M) = motionConstraint_.getFunctionInf(X_);
    qpMatrix_.bu.segment(0, M) = motionConstraint_.getFunctionSup(X_);

    qpMatrix_.xu.fill(noDynModel_.getJerkLimit());
    qpMatrix_.xu -= X_;

    qpMatrix_.xl.fill(-noDynModel_.getJerkLimit());
    qpMatrix_.xl-= X_;

  }

  //The number of iterations can be high in the init phase (approximatively equals to the
  //number of constraints, aka 250).
  const int maxNbIterations = 10000;
  bool solutionFound = qpoasesSolver_->solve(qpMatrix_, maxNbIterations, dX_, true);

  if (!solutionFound)
  {
    std::cerr << "Q : " << std::endl << qpMatrix_.Q << std::endl;
    std::cerr << "p : " << qpMatrix_.p.transpose() << std::endl;
    std::cerr << "A : " << std::endl << qpMatrix_.A << std::endl;
    std::cerr << "bl: " << qpMatrix_.bl.transpose() << std::endl;
    std::cerr << "bu: " << qpMatrix_.bu.transpose() << std::endl;
    std::cerr << "X : " << X_.transpose() << std::endl;
    std::cerr << "dX: " << dX_.transpose() << std::endl;
    std::cerr << "c : " << noDynModel_.getState() << std::endl;
  }

  X_ += dX_;


  noDynModel_.updateState(X_(0), feedBackPeriod);

  return solutionFound;
}
geometry_msgs::Twist generate_smooth_trajectory(geometry_msgs::Twist p_ini, geometry_msgs::Twist p_fin, ros::Publisher pub_pos, double tiempo, bool respecto_robot, geometry_msgs::Twist vel_ant){
//Encontrar las posiciones de la trayectoria con ayuda de un polinomio de quinto orden
    double p_ini_x_;
    double p_ini_y_;
    double a_ini_z_;
    double p_fin_x_;
    double p_fin_y_;
    double a_fin_z_;
    double r_time_;

    p_ini_x_ = p_ini.linear.x;//10;
    p_ini_y_ = p_ini.linear.y;//10;
    a_ini_z_ = p_ini.angular.z;//10;

    p_fin_x_ = p_fin.linear.x;///10;
    p_fin_y_ = p_fin.linear.y;//10;
    a_fin_z_ = p_fin.angular.z;//10;
    r_time_ = p_fin.angular.x;

    Eigen::MatrixXf Mat(6,6);
    Mat <<0,0,0,0,0,1,
         pow(r_time_,5),pow(r_time_,4),pow(r_time_,3),pow(r_time_,2),r_time_,1,
          0,0,0,0,1,0,
          5*pow(r_time_,4),4*pow(r_time_,3),3*pow(r_time_,2),2*r_time_,1,0,
          0,0,0,2,0,0,
          20*pow(r_time_,3),12*pow(r_time_,2),6*r_time_,2,0,0;
    //if (!respecto_robot)
    //    std::cout << "Matriz de polinomio quinto orden" <<Mat << std::endl<< r_time_<<std::endl<<tiempo<<std::endl;
   
    Eigen::MatrixXf X_(6,1);
    X_ <<p_ini_x_,p_fin_x_,vel_ant.linear.x,0,0,0;

    Eigen::MatrixXf Y_(6,1);
    Y_ <<p_ini_y_,p_fin_y_,vel_ant.linear.y,0,0,0;

    Eigen::MatrixXf Z_(6,1);
    Z_ <<a_ini_z_,a_fin_z_,vel_ant.angular.z,0,0,0;

    //std::cout << "Vector X" <<X_ << std::endl;

    Eigen::MatrixXf coeff_X(6,1);
    coeff_X = Mat.colPivHouseholderQr().solve(X_);

    //std::cout << "Vector X" <<coeff_X << std::endl;

    Eigen::MatrixXf coeff_Y(6,1);
    coeff_Y = Mat.colPivHouseholderQr().solve(Y_);
    Eigen::MatrixXf coeff_Z(6,1);
    coeff_Z = Mat.colPivHouseholderQr().solve(Z_);
    double i =.02;// 1/rate_hz;
    geometry_msgs::Twist pos_aux,vel_aux;
    //pos_aux.linear.x =coeff_X(0,0)*pow(i,5)+coeff_X(1,0)*pow(i,4)+coeff_X(2,0)*pow(i,3)+coeff_X(3,0)*pow(i,2)+coeff_X(4,0)*i+coeff_X(5,0);
    pos_aux.linear.x =coeff_X(0,0)*pow(i,5)+
            coeff_X(1,0)*pow(i,4)+
            coeff_X(2,0)*pow(i,3)+
            coeff_X(3,0)*pow(i,2)+       
            coeff_X(4,0)*i+
            coeff_X(5,0);
    pos_aux.linear.y =coeff_Y(0,0)*pow(i,5)+coeff_Y(1,0)*pow(i,4)+coeff_Y(2,0)*pow(i,3)+coeff_Y(3,0)*pow(i,2)+coeff_Y(4,0)*i+coeff_Y(5,0);
    pos_aux.angular.z=coeff_Z(0,0)*pow(i,5)+coeff_Z(1,0)*pow(i,4)+coeff_Z(2,0)*pow(i,3)+coeff_Z(3,0)*pow(i,2)+coeff_Z(4,0)*i+coeff_Z(5,0);


    /*vel_aux.linear.x = 5*coeff_X(0,0)*pow(i,4)
                   +4*coeff_X(1,0)*pow(i,3)
              +3*coeff_X(2,0)*pow(i,2)
              +2*coeff_X(3,0)*i
              +coeff_X(4,0);
    vel_aux.linear.y = 5*coeff_Y(0,0)*pow(i,4)
                  +4*coeff_Y(1,0)*pow(i,3)
              +3*coeff_Y(2,0)*pow(i,2)
              +2*coeff_Y(3,0)*i
              +coeff_Y(4,0);
    vel_aux.angular.z =5*coeff_Z(0,0)*pow(i,4)
                  +4*coeff_Z(1,0)*pow(i,3)
              +3*coeff_Z(2,0)*pow(i,2)
              +2*coeff_Z(3,0)*i
              +coeff_Z(4,0);*/
    //vel_aux.angular.z = 0;
    // Opcion 1
    vel_aux.linear.x = (p_fin_x_-p_ini_x_)/(r_time_-tiempo);
    vel_aux.linear.y = (p_fin_y_-p_ini_y_)/(r_time_-tiempo);
    
    //vel_aux.angular.z = (a_fin_z_-a_ini_z_)/(r_time_-tiempo)*10;
    //vel_aux.linear.x = (p_fin_x_-p_ini_x_)/(r_time_);
    //vel_aux.linear.y = (p_fin_y_-p_ini_y_)/(r_time_);
    vel_aux.angular.z = 0;
   
    //Opcion 2
    /*vel_aux.linear.x = abs(pos_aux.linear.x-p_fin_x_)/(1/(rate_hz));
    vel_aux.linear.y = abs(pos_aux.linear.y-p_fin_y_)/(1/(rate_hz));
    vel_aux.angular.z = 0;*/

    if (respecto_robot){//Publicar la posicion respecto al mundo para tener una idea con el
         pos_aux =  destransformacion_homogenea(pos_aux, goalie_position.angular.z, goalie_position);
        pub_pos.publish(pos_aux);
    }
    /*    ROS_INFO_STREAM("pos esperada sin transf:"
            <<" linear X ="<<pos_aux.linear.x
            <<" linear Y ="<<pos_aux.linear.y
            <<" angular ="<<pos_aux.angular.z);*/
    /*}
    else
    {    Esto es respecto al mundo, no sirve mas que para saber que si se esta haciendo bien la transformacion lineal
        pos_aux =  destransformacion_homogenea(pos_aux, goalie_position.angular.z, goalie_position);
        pub_pos.publish(pos_aux);
        ROS_INFO_STREAM("pos final esp:"
            <<" linear X ="<<p_fin_x_
            <<" linear Y ="<<p_fin_y_
            <<" angular ="<<a_fin_z_);
        ROS_INFO_STREAM("pos inicial esp:"
            <<" linear X ="<<p_ini_x_
            <<" linear Y ="<<p_ini_y_
            <<" angular ="<<a_ini_z_);
   
   
    }*/
    return vel_aux;
}
Example #12
0
void eqnsys<nr_type_t>::solve_sor (void) {
  nr_type_t f;
  int error, conv, i, c, r;
  int MaxIter = N; // -> less than N^3 operations
  nr_double_t reltol = 1e-4;
  nr_double_t abstol = NR_TINY;
  nr_double_t diff, crit, l = 1, d, s;

  // ensure that all diagonal values are non-zero
  ensure_diagonal ();

  // try to raise diagonal dominance
  preconditioner ();

  // decide here about possible convergence
  if ((crit = convergence_criteria ()) >= 1) {
#if DEBUG && 0
    logprint (LOG_STATUS, "NOTIFY: convergence criteria: %g >= 1 (%dx%d)\n",
	      crit, N, N);
#endif
    //solve_lu ();
    //return;
  }

  // normalize the equation system to have ones on its diagonal
  for (r = 0; r < N; r++) {
    f = A_(r, r);
    assert (f != 0); // singular matrix
    for (c = 0; c < N; c++) A_(r, c) /= f;
    B_(r) /= f;
  }

  // the current X vector is a good initial guess for the iteration
  tvector<nr_type_t> * Xprev = new tvector<nr_type_t> (*X);

  // start iterating here
  i = 0; error = 0;
  do {
    // compute new solution vector
    for (r = 0; r < N; r++) {
      for (f = 0, c = 0; c < N; c++) {
	if (c < r)      f += A_(r, c) * X_(c);
	else if (c > r) f += A_(r, c) * Xprev->get (c);
      }
      X_(r) = (1 - l) * Xprev->get (r) + l * (B_(r) - f);
    }
    // check for convergence
    for (s = 0, d = 0, conv = 1, r = 0; r < N; r++) {
      diff = abs (X_(r) - Xprev->get (r));
      if (diff >= abstol + reltol * abs (X_(r))) {
	conv = 0;
	break;
      }
      d += diff; s += abs (X_(r));
      if (!std::isfinite (diff)) { error++; break; }
    }
    if (!error) {
      // adjust relaxation based on average errors
      if ((s == 0 && d == 0) || d >= abstol * N + reltol * s) {
	// values <= 1 -> non-convergence to convergence
	if (l >= 0.6) l -= 0.1;
	if (l >= 1.0) l = 1.0;
      }
      else {
	// values >= 1 -> faster convergence
	if (l < 1.5) l += 0.01;
	if (l < 1.0) l = 1.0;
      }
    }
    // save last values
    *Xprev = *X;
  }
  while (++i < MaxIter && !conv);

  delete Xprev;

  if (!conv || error) {
    logprint (LOG_ERROR,
	      "WARNING: no convergence after %d sor iterations (l = %g)\n",
	      i, l);
    solve_lu_crout ();
  }
#if DEBUG && 0
  else {
    logprint (LOG_STATUS,
	      "NOTIFY: sor convergence after %d iterations\n", i);
  }
#endif
}
Example #13
0
void eqnsys<nr_type_t>::solve_iterative (void) {
  nr_type_t f;
  int error, conv, i, c, r;
  int MaxIter = N; // -> less than N^3 operations
  nr_double_t reltol = 1e-4;
  nr_double_t abstol = NR_TINY;
  nr_double_t diff, crit;

  // ensure that all diagonal values are non-zero
  ensure_diagonal ();

  // try to raise diagonal dominance
  preconditioner ();

  // decide here about possible convergence
  if ((crit = convergence_criteria ()) >= 1) {
#if DEBUG && 0
    logprint (LOG_STATUS, "NOTIFY: convergence criteria: %g >= 1 (%dx%d)\n",
	      crit, N, N);
#endif
    //solve_lu ();
    //return;
  }

  // normalize the equation system to have ones on its diagonal
  for (r = 0; r < N; r++) {
    f = A_(r, r);
    assert (f != 0); // singular matrix
    for (c = 0; c < N; c++) A_(r, c) /= f;
    B_(r) /= f;
  }

  // the current X vector is a good initial guess for the iteration
  tvector<nr_type_t> * Xprev = new tvector<nr_type_t> (*X);

  // start iterating here
  i = 0; error = 0;
  do {
    // compute new solution vector
    for (r = 0; r < N; r++) {
      for (f = 0, c = 0; c < N; c++) {
	if (algo == ALGO_GAUSS_SEIDEL) {
	  // Gauss-Seidel
	  if (c < r)      f += A_(r, c) * X_(c);
	  else if (c > r) f += A_(r, c) * Xprev->get (c);
	}
	else {
	  // Jacobi
	  if (c != r) f += A_(r, c) * Xprev->get (c);
	}
      }
      X_(r) = B_(r) - f;
    }
    // check for convergence
    for (conv = 1, r = 0; r < N; r++) {
      diff = abs (X_(r) - Xprev->get (r));
      if (diff >= abstol + reltol * abs (X_(r))) {
	conv = 0;
	break;
      }
      if (!std::isfinite (diff)) { error++; break; }
    }
    // save last values
    *Xprev = *X;
  }
  while (++i < MaxIter && !conv);

  delete Xprev;

  if (!conv || error) {
    logprint (LOG_ERROR,
	      "WARNING: no convergence after %d %s iterations\n",
	      i, algo == ALGO_JACOBI ? "jacobi" : "gauss-seidel");
    solve_lu_crout ();
  }
#if DEBUG && 0
  else {
    logprint (LOG_STATUS,
	      "NOTIFY: %s convergence after %d iterations\n",
	      algo == ALGO_JACOBI ? "jacobi" : "gauss-seidel", i);
  }
#endif
}
Example #14
0
/*
** This routine is called whenever a pprdrv process exits.
**
** Notice that this routine makes a lot of calls to printer_new_status() which
** attempt to set the printer's status to PRNSTATUS_IDLE without regard to
** whether that is the correct new state.  This is ok since printer_new_status()
** sets the printer to the stopt state if an attempt is made to move it from
** stopping or halting to idle.
*/
static void pprdrv_exited(int prnid, int wstat)
	{
	const char function[] = "pprdrv_exited";
	int estat;							/* for pprdrv exit status */
	int job_status = STATUS_WAITING;	/* job status will be set to this (as modified) */
	int prn_status = PRNSTATUS_IDLE;	/* printer status will be set to this (as modified) */

	DODEBUG_PRNSTOP(("%s(prnid=%d, wstat=0x%04x)", function, prnid, wstat));

	printers[prnid].pid = 0;			/* prevent future false match */
	active_printers--;					/* a printer is no longer active */

	/*
	** This is good.
	*/
	if(WIFEXITED(wstat))
		{
		estat = WEXITSTATUS(wstat);
		}

	/*
	** If it caught a signal and core dumped, that is a major error.  If it
	** caught a signal and didn't core dump it may be that we sent it that
	** signal to cancel a job that was already printing or to halt a printer.
	** We will handle the latter case below.
	*/
	else if(WIFSIGNALED(wstat))
		{
		if(WCOREDUMP(wstat))
			{
			alert(printers[prnid].name, FALSE, _("Internal error, pprdrv core dumped after receiving signal %d (%s)."),
				WSTOPSIG(wstat), gu_strsignal(WSTOPSIG(wstat)));
			estat = EXIT_PRNERR_NORETRY;
			}
		else
			{
			estat = EXIT_SIGNAL;
			}
		}

	/*
	** Stopped by signal!  Someone is playing games!
	*/
	else if(WIFSTOPPED(wstat))
		{
		alert(printers[prnid].name, TRUE, _("Mischief afoot, pprdrv stopt by signal %d (%s)."), WSTOPSIG(wstat), gu_strsignal(WSTOPSIG(wstat)));
		estat = EXIT_PRNERR_NORETRY;
		}

	/*
	** Deep mystery!
	*/
	else
		{
		alert(printers[prnid].name, TRUE, X_("Bizaar pprdrv malfunction, exit status not understood."));
		estat = EXIT_PRNERR_NORETRY;
		}

	#ifdef DEBUG_PRNSTOP
	alert(printers[prnid].name, FALSE, "debug: pprdrv exited with code %d", estat);
	#endif

	/*
	** Act on pprdrv exit code.  Note that we wait until the next switch to
	** handle EXIT_PRNERR and EXIT_PRNERR_NORETRY.  Also note that in this
	** switch we replace certain more specific exit codes with those codes.
	*/
	switch(estat)
		{
		case EXIT_PRINTED:				/* no error */
			DODEBUG_PRNSTOP(("(printed normally)"));

			/* If we were trying to cancel the job, it is too late now. */
			printers[prnid].cancel_job = FALSE;

			/* Tell the user that the job has been printed. */
			respond(nodeid_local(), printers[prnid].jobdestid, printers[prnid].id, printers[prnid].subid, printers[prnid].homenode_id, prnid, RESP_FINISHED);

			/* If the operator was informed that the printer was in a fault state, this call
			   will inform the operator that it has recovered. */
			alert_printer_working(printers[prnid].name,
					printers[prnid].alert_interval,
					printers[prnid].alert_method,
					printers[prnid].alert_address,
					printers[prnid].next_error_retry);

			/* Since the printer suceeded, reset the error retry and
			   engaged retry counts. */
			printers[prnid].next_error_retry = 0;
			printers[prnid].next_engaged_retry = 0;

			break;

		case EXIT_JOBERR:				/* PostScript error in job */
			DODEBUG_PRNSTOP(("(job error)"));

			/* Place the job in the special held state called "arrested". */
			job_status = STATUS_ARRESTED;

			/* Tell the user that his job has been arrested. */
			respond(nodeid_local(), printers[prnid].jobdestid, printers[prnid].id, printers[prnid].subid, printers[prnid].homenode_id, prnid, RESP_ARRESTED);

			/* If the printer was in a fault state, this function will inform the
			   operator that it has recovered. */
			alert_printer_working(printers[prnid].name,
					printers[prnid].alert_interval,
					printers[prnid].alert_method,
					printers[prnid].alert_address,
					printers[prnid].next_error_retry);

			/* Reset error counters. */
			printers[prnid].next_error_retry = 0;
			printers[prnid].next_engaged_retry = 0;

			break;

		case EXIT_INCAPABLE:			/* capabilities exceeded */
			DODEBUG_PRNSTOP(("(printer is incapable)"));
			{
			int y;
			int id,subid;

			id = printers[prnid].id;		/* x is the printer id */
			subid = printers[prnid].subid;

			lock();

			for(y=0; ; y++)				/* find the queue entry */
				{
				if(y == queue_entries)
					fatal(0, "%s(): job missing from array", function);
				if(queue[y].id == id && queue[y].subid == subid)
					break;
				}

			/*
			** If a single printer, set the never mask to 1,
			** arrest the job, and say the printer is incapable.
			*/
			if( ! destid_local_is_group(printers[prnid].jobdestid) )
				{
				queue[y].never |= 1;
				job_status = STATUS_STRANDED;
				respond(nodeid_local(), printers[prnid].jobdestid,
						printers[prnid].id, printers[prnid].subid,
						printers[prnid].homenode_id,
						prnid, RESP_STRANDED_PRINTER_INCAPABLE);
				}

			/*
			** If a group of printers, set the appropriate
			** bit in the never mask.  If the bit has been
			** set for every printer in the group, arrest
			** the job and inform the user.
			*/
			else
				{
				/*
				** Get a number with the bit corresponding to this
				** printer's possition in this destination group
				** and add that bit to the bits set in the never
				** mask.  If the printer has been removed from
				** the group since the job was started, then
				** media_prn_bitmask() will return 0 which will
				** be ok.
				*/
				queue[y].never |= destid_printer_bit(printers[prnid].jobdestid, prnid);

				/*
				** If every never bit has been set, then arrest the job and
				** inform the user.  But, if that was the 1st pass, we give
				** the job a second chance.
				*/
				if(queue[y].never == ((1 << groups[destid_local_to_gindex(printers[prnid].jobdestid)].members) - 1))
					{
					if( ++(queue[y].pass) > 2 ) /* if beyond the second pass */
						{
						job_status = STATUS_STRANDED;
						respond(nodeid_local(), printers[prnid].jobdestid,
								printers[prnid].id,printers[prnid].subid,
								printers[prnid].homenode_id,
								prnid, RESP_STRANDED_GROUP_INCAPABLE);
						}
					else
						{
						queue[y].never = 0;
						}
					}
				} /* end of else (group of printers) */

			unlock();

			}
			break;

		case EXIT_ENGAGED:
			DODEBUG_PRNSTOP(("(otherwise engaged or off-line)"));
			printers[prnid].next_engaged_retry++;				/* increment retry count */
			printers[prnid].countdown = ENGAGED_RETRY;			/* and set time for retry */
			prn_status = PRNSTATUS_ENGAGED;
			break;

		case EXIT_STARVED:
			DODEBUG_PRNSTOP(("(starved for system resources)"));
			starving_printers++;
			prn_status = PRNSTATUS_STARVED;
			break;

		case EXIT_SIGNAL:			/* clean shutdown after receiving a signal */
			DODEBUG_PRNSTOP(("(aborted due to signal)"));

			if(printers[prnid].status == PRNSTATUS_HALTING)
				break;

			if(printers[prnid].status == PRNSTATUS_SEIZING)
				break;

			if(printers[prnid].status == PRNSTATUS_CANCELING)
				break;

			if(WIFSIGNALED(wstat))		/* if it was a real signal, */
				{						/* (Note: we know that there was no core dump) */
				if(WSTOPSIG(wstat) == 0)
					{
					alert(printers[prnid].name, TRUE,
						_("Printing aborted because pprdrv died.  The stated reason for its death (killed\n"
						  "by signal 0) is nonsense but may indicate that dynamic linking failed due to a\n"
						  "problem with the shared library search path.")
						  );
					}
				else
					{
					alert(printers[prnid].name, TRUE,
						_("Printing aborted because pprdrv was killed by signal %d (%s).\n"
						"This was not expected and the cause is unknown."), WSTOPSIG(wstat), gu_strsignal(WSTOPSIG(wstat)));
					}
				}
			else						/* Otherwise, pprdrv caught the signal and exited gracefully, */
				{
				alert(printers[prnid].name, TRUE, _("Unexpected pprdrv shutdown.  It claims to have received a signal to terminate."));
				}
			estat = EXIT_PRNERR;
			break;

		case EXIT_PRNERR:
		case EXIT_PRNERR_NOT_RESPONDING:
		case EXIT_PRNERR_NO_SUCH_ADDRESS:
			estat = EXIT_PRNERR;
			break;

		case EXIT_PRNERR_NORETRY:
		case EXIT_PRNERR_NORETRY_ACCESS_DENIED:
		case EXIT_PRNERR_NORETRY_BAD_SETTINGS:
		case EXIT_PRNERR_NORETRY_NO_SUCH_ADDRESS:
			estat = EXIT_PRNERR_NORETRY;
			break;

		default:
			DODEBUG_PRNSTOP(("(unknown exit code)"));
			alert(printers[prnid].name, FALSE, _("Unrecognized exit code %d returned by pprdrv."), estat);
			estat = EXIT_PRNERR;
			break;
		}

	/*
	** Here we go again.  This time we only pay attention to two generic
	** error codes.  More specific error codes have been converted by
	** now.
	*/
	switch(estat)
		{
		case EXIT_PRNERR_NORETRY:
			DODEBUG_PRNSTOP(("(fault, no retry)"));
			alert(printers[prnid].name, FALSE, _("Printer placed in fault mode, no auto-retry."));
			printers[prnid].next_error_retry = 0;
			printers[prnid].countdown = 0;
			prn_status = PRNSTATUS_FAULT;
			break;

		case EXIT_PRNERR:
			DODEBUG_PRNSTOP(("(fault)"));
			alert(printers[prnid].name, FALSE, _("Printer placed in auto-retry mode."));
			printers[prnid].next_error_retry++;
			printers[prnid].countdown = printers[prnid].next_error_retry * RETRY_MULTIPLIER;
			if(printers[prnid].countdown > MIN_RETRY)
				printers[prnid].countdown = MIN_RETRY;
			prn_status = PRNSTATUS_FAULT;
			break;
		}

	/* If the printer is in fault mode (either with or without retries,
	   give the alert system a chance to inform the operator if it
	   wants to. */
	if(prn_status == PRNSTATUS_FAULT)
		{
		alert_printer_failed(printers[prnid].name,
				printers[prnid].alert_interval, printers[prnid].alert_method, printers[prnid].alert_address,
				printers[prnid].next_error_retry);
		}

	/* If there is an outstanding hold request, prepare to set job
	   state to "held". */
	if(printers[prnid].hold_job)
		{
		job_status = STATUS_HELD;
		printers[prnid].hold_job = FALSE;
		}

	/* If there is an outstanding cancel request, inform the user.
	   But we leave the flag set because the next if() tests it. */
	if(printers[prnid].cancel_job)
		{
		respond(nodeid_local(), printers[prnid].jobdestid,
						printers[prnid].id, printers[prnid].subid,
						printers[prnid].homenode_id,
						prnid, RESP_CANCELED_PRINTING);
		}

	/* If we should remove the job because it was printed or canceled, do it now. */
	if(estat == EXIT_PRINTED || printers[prnid].cancel_job)
		{
		queue_dequeue_job(nodeid_local(), printers[prnid].jobdestid, printers[prnid].id, printers[prnid].subid, printers[prnid].homenode_id);
		printers[prnid].cancel_job = FALSE;
		}

	/* If we will not remove the job, set it to its new state. */
	else
		{
		struct QEntry *p = queue_job_new_status(printers[prnid].id, printers[prnid].subid, printers[prnid].homenode_id, job_status);
		if(job_status == STATUS_WAITING)
			printer_try_start_suitable_4_this_job(p);
		}

	/* Stopping printers can only become stopt. */
	if(printers[prnid].status == PRNSTATUS_STOPPING || printers[prnid].status == PRNSTATUS_HALTING)
		prn_status = PRNSTATUS_STOPT;

	/* Actualy set the printer to its new state. */
	printer_new_status(&printers[prnid], prn_status);

	/* If the printer is now idle, look for something for it to do. */
	if(printers[prnid].status == PRNSTATUS_IDLE)
		printer_look_for_work(prnid);

	} /* end of pprdrv_exited() */
Example #15
0
/** check if a given user is listed in a given ACL
*/
gu_boolean user_acl_allows(const char user[], const char acl[])
	{
	/* Look in one of the internal lists.  These lists are compiled in
	   because the system will cease to function correctly if these usernames
	   are removed. */
	{
	int i;
	for(i = 0; internal_list[i]; i++)
		{
		if(strcmp(user, internal_list[i]) == 0)
			return TRUE;
		}
	}

	/* Look for a line with the user name in the .allow
	   file for the ACL list. */
	{
	FILE *f;
	char fname[MAX_PPR_PATH];
	char line[256];
	ppr_fnamef(fname, "%s/%s.allow", ACLDIR, acl);
	if((f = fopen(fname, "r")))
		{
		while(fgets(line, sizeof(line), f))
			{
			/* Skip comments. */
			if(line[0] == '#' || line[0] == ';')
				continue;

			/* Trim trailing whitespace. */
			line[strcspn(line, " \t\r\n")] = '\0';

			/* Does it match? */
			if(strcmp(line, user) == 0)
				{
				fclose(f);
				return TRUE;
				}
			}
		fclose(f);
		}
	}

	/* For compability with versions of PPR before 1.32,
	   see if the user is a member of a group named
	   for the ACL. */
	{
	struct group *gr;
	int x;
	char *ptr;

	if((gr = getgrnam(acl)) != (struct group *)NULL)
		{
		x = 0;
		while((ptr = gr->gr_mem[x++]) != (char*)NULL)
			{
			if(strcmp(ptr, user) == 0)
				{
				fputs(X_("Warning: your privledges are granted by membership in a Unix\n"
						"group, which is deprecated.  Please use the new ACLs.\n"), stderr);
				return TRUE;
				}
			}
		}
	}

	return FALSE;
	} /* end of user_acl_allows() */