Logo Search packages:      
Sourcecode: ncpfs version File versions  Download package

nwpjmv.c

/*
    nwjpmv.c
    Copyright (C) 2003 by Bruno Browning
  
    This program 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 2 of the License, or
    (at your option) any later version.

    This program 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 this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


    Revision history:

      0.00  1996              Volker Lendecke
            Initial revision (as pserver.c)
               2003         Bruno Browning
               nwpjmv.c
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <syslog.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <signal.h>
#include <string.h>
#include <ncp/ncplib.h>

#include "private/libintl.h"
#define _(X) gettext(X)

struct nw_queue
{
      struct ncp_conn *conn;

      char queue_name[NCP_BINDERY_NAME_LEN];
      u_int32_t queue_id;
      u_int16_t job_type;

      char *command;
};

static volatile int term_request;
static char *progname;

static void
usage(void)
{
      fprintf(stderr, _("usage: %s [options] file\n"), progname);
}

static void
help(void)
{
      printf(_("\n"
             "usage: %s [options]\n"), progname);
      printf(_("\n"
             "-S server      Server name to be used\n"
             "-U username    Print Server name sent to server\n"
             "-P password    Use this password\n"
             "-n             Do not use any password\n"
             "-C             Don't convert password to uppercase\n"
             "-q queue name  Name of the printing queue to use\n"
             "-c command     Name of print command, default: 'lpr'\n"
             "-j job number  ID number of job to service\n"
             "-d             Debug"
             "\n"));
}

#ifndef NCP_BINDERY_PSERVER
#define NCP_BINDERY_PSERVER (0x0007)
#endif

static void
terminate_handler(int dummy __attribute__((unused)))
{
      signal(SIGTERM, terminate_handler);
      signal(SIGINT, terminate_handler);
      term_request = 1;
}


static int
init_queue(struct ncp_conn *conn, char *queue_name, char *command,
         struct nw_queue *q)
{
      struct ncp_bindery_object obj;
      long err;

      str_upper(queue_name);

      q->conn = conn;
      q->command = command;

      err = ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE, 
                              queue_name, &obj);
      if (err) {
            fprintf(stderr, _("Queue %s not found: %s\n"), 
                  queue_name, strnwerror(err));
            return -1;
      }
      q->queue_id = obj.object_id;
      memcpy(q->queue_name, obj.object_name, sizeof(q->queue_name));

      err = ncp_attach_to_queue(conn, q->queue_id);
      if (err) {
            fprintf(stderr, _("Could not attach to queue %s: %s\n"),
                  queue_name, strnwerror(err));
            return -1;
      }
      return 0;
}


static void
build_command(struct nw_queue *q, struct queue_job *j,
            char *target, int target_size, char *user)
{
      char *s = q->command;
      char *target_end = target + target_size;

      static void add_string(const char *str)
      {
            int len = strlen(str);
            if (target + len + 1 > target_end)
            {
                  len = target_end - target - 1;
            }
            strncpy(target, str, len);
            target += len;
      }

      memset(target, 0, target_size);

      while ((*s != 0) && (target < target_end))
      {
            if (*s != '%')
            {
                  *target = *s;
                  target += 1;
                  s += 1;
                  continue;
            }
            switch (*(s + 1))
            {
            case '%':
                  *target = '%';
                  target += 1;
                  break;
            case 'u':
                    add_string(user);
                  break;
                case 'd':
                        if (j->j.JobTextDescription[0])
                                add_string(j->j.JobTextDescription);
                        else
                                add_string(_("No Description"));
                        break;
            default:
                  *target = '%';
                  *(target + 1) = *(s + 1);
                  target += 2;
            }
            s += 2;
      }
}




static int
move_job(struct nw_queue *q, u_int32_t jobID)
{
      struct queue_job job;
      int fd[2];
      int pid;
      int retcode;
      struct ncp_bindery_object u;
      char user[50];
      
      retcode = ncp_change_job_position(q->conn, q->queue_id, jobID, 1);
      if (retcode != 0) {
         syslog(LOG_ERR, _("Failed to change job position: %s\n"), strnwerror(retcode));
         return -1;
         }

      retcode = ncp_service_queue_job(q->conn, q->queue_id, q->job_type, &job);
      if (retcode != 0) {
            if (retcode == NWE_Q_NO_JOB || retcode == NWE_SERVER_FAILURE) {
                  /* No job for us */
                  return 0;
            }
            syslog(LOG_ERR, _("Cannot service print job: %s\n"), strnwerror(retcode));
            return 2;
      }

        if (ncp_get_queue_job_info(q->conn, q->queue_id, job.j.JobNumber, &job.j) != 0)
        {
                job.j.JobTextDescription[0]=0;
        }
        
        if (job.j.JobNumber != jobID) {
            syslog(LOG_ERR, _("wrong job queued: expected %08X, got %08X\n"), jobID, job.j.JobNumber);
            goto fail;
        }

      if ((retcode=ncp_get_bindery_object_name
           (q->conn, htonl(job.j.ClientObjectID), &u))
          == 0)
        {
          memcpy(user,u.object_name,48);
            user[48]=0;
        } 
      else
        {
          sprintf(user,_("<Unknown>"));
        }
      
      if (pipe(fd) < 0)
      {
            syslog(LOG_ERR, _("pipe error: %m"));
            goto fail;
      }
      if ((pid = fork()) < 0)
      {
            syslog(LOG_ERR, _("fork error: %m"));
            goto fail;
      }
      if (pid > 0)
      {
            /* parent */
            char buf[1024];
            size_t result;
            off_t offset = 0;

            close(fd[0]);     /* close read end */

            while ((result = ncp_read(q->conn, job.file_handle, offset,
                                sizeof(buf), buf)) > 0)
            {
                  offset += result;
                  if (write(fd[1], buf, result) != (int)result)
                  {
                        goto fail;
                  }
            }

            close(fd[1]);     /* and close write end */

            if (waitpid(pid, NULL, 0) < 0)
            {
                  syslog(LOG_ERR, _("waitpid: %m\n"));
            }
      } else
      {
            /* child */

            char command[2048];

            close(fd[1]);     /* close write end */

            if (fd[0] != STDIN_FILENO)
            {
                  if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
                  {
                        syslog(LOG_ERR, _("dup2 error: %m\n"));
                        close(fd[0]);
                        exit(1);
                  }
                  close(fd[0]);
            }

            build_command(q, &job, command, sizeof(command), user);

            execl("/bin/sh", "sh", "-c", command, NULL);
            syslog(LOG_ERR, _("exec error: %m\n"));
            close(fd[0]);
            exit(1);
      }

      ncp_finish_servicing_job(q->conn, q->queue_id, job.j.JobNumber, 0);
      return 1;

      fail:
      ncp_abort_servicing_job(q->conn, q->queue_id, job.j.JobNumber);
      /* We tell that we did not have a job to avoid overloading
         when something's wrong */
      return 0;
}

static struct nw_queue q;

int
main(int argc, char *argv[])
{
      struct ncp_conn *conn;
      int opt;
      int debug = 0;
      int i;
      long err;

      char *queue_name = NULL;
      char *job_num = NULL;
      char *end;
      
      u_int32_t jobID;

      char default_command[] = "lpr";
      char *command = default_command;

      setlocale(LC_ALL, "");
      bindtextdomain(NCPFS_PACKAGE, LOCALEDIR);
      textdomain(NCPFS_PACKAGE);
      
      progname = argv[0];

      for (i = 1; i < argc; i += 1)
      {
            if ((strcmp(argv[i], "-h") == 0)
                || (strcmp(argv[i], "-?") == 0))
            {
                  help();
                  exit(0);
            }
      }

      for (i = 1; i < argc; i += 1)
      {
            if (strcmp(argv[i], "-d") == 0)
            {
                  debug = 1;
                  break;
            }
      }

      if (debug == 0)
      {
            openlog("nwpjmv", LOG_PID, LOG_LPR);
      }
      if ((conn = ncp_initialize_as(&argc, argv, 1,
                              NCP_BINDERY_PSERVER, &err)) == NULL)
      {
            com_err(argv[0], err, _("when initializing"));
            return 1;
      }
      while ((opt = getopt(argc, argv, "q:c:j:dh")) != EOF)
      {
            switch (opt)
            {
            case 'q':
                  queue_name = optarg;
                  break;
            case 'c':
                  command = optarg;
                  break;
            case 'j':
                  job_num = optarg;
                  break;
            case 'd':
                  debug = 1;
                  break;
            case 'h':
                  break;
            default:
                  usage();
                  return -1;
            }
      }

      if (argc != optind)
      {
            usage();
            return -1;
      }
      memset(&q, 0, sizeof(q));

      if (queue_name == NULL)
      {
            fprintf(stderr, _("You must specify a queue\n"));
            return 1;
      }
      if (init_queue(conn, queue_name, command, &q) != 0)
      {
            ncp_close(conn);
            return 1;
      }

      term_request = 0;
      signal(SIGTERM, terminate_handler);
      signal(SIGINT, terminate_handler);
      
      jobID =  strtoul(job_num, &end, 16);
      if (*end) {
        fprintf(stderr, _("Cannot parse \"%s\" - jobID must be hexadecimal number\n"), argv[i]);
                } else {
                        int err2;

                        err2 = move_job(&q, jobID);
                        if (err2 != 1) {
                        fprintf(stderr, _("Could not move job %08X\n"), jobID);
                        } 
                        }
                         
      ncp_detach_from_queue(conn, q.queue_id);

      ncp_close(conn);
      return 0;
}


Generated by  Doxygen 1.6.0   Back to index