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

printerconf.c

#include <errno.h>       
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <glib.h>
#include <config.h>
#include <assert.h>

#include "parport.h"
#include "snmpinter.h"
#include "printerconf.h"

/*----------------------------------------------------------------
  libprinterconf - a function library for detecting and setting up
  printers in linux.

  03/08/2000
----------------------------------------------------------------*/

#define PCONF_MAX_XREF_STRLEN 1024
#define PCONF_XREF_FILE "/extra/projects/printing/libprinterconf/printerconf.xref"

#define IOCNR_GET_DEVICE_ID   1
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)     /* get device_id string */

#define SPOOLDIR_KEY L"sd"
#define ACCOUNTING_FILE_KEY L"af"
#define INPUT_FILTER_KEY L"if"
#define MAXFILE_KEY L"mx"
#define DEVICE_KEY L"lp"
#define SUPP_HEADER_KEY L"sh"
#define REMOTE_MACHINE_KEY L"rm"
#define REMOTE_PORT_KEY L"rp"
#define PPDFILE_KEY L"ppdfile"
#define LOCKFILE_KEY L"lo"
#define STATFILE_KEY L"st"
#define DIR_IP_KEY L"printer_ip"
#define DIR_PORT_KEY L"port"
#define SMB_HOST_KEY L"smb_host"
#define SMB_SHARE_KEY L"smb_share"
#define USER_KEY L"user"
#define PW_KEY L"password"
#define SMB_HOSTIP_KEY L"smb_hostip"
#define SMB_WORKGROUP_KEY L"smb_workgroup"
#define NCP_SERVER_KEY L"ncp_server"
#define NCP_PRINTER_KEY L"ncp_printer"


#define VALBUFSIZE 1024
#define DEFSD L"/var/spool/lpd/"
#define DEFAF L"acct"
#define DEFLO L"lock"
#define DEFST L"status"
#define TRUESTR L"true"
#define FALSESTR L"false"

#warning "fixme: libexecdir needs to defined at config time"
/* couldn't figure out how to make it get defined at configure time */
#define LIBEXECDIR L"/usr/local/libexec"

/*----------------------------------------------------------------
  Autodetect printer on a parallel port using IEEE1284 protocol.

  Attempt parallel port autodetection (IEEE1284). Return a
  string containing a unique printer ID
----------------------------------------------------------------*/
static char *pconf_autodetect_pport(long int port);

pconf_detmethod_t pconf_methods[4] = {
  {PCONF_DETECT_PPORT, "Parallel Port"},
  {PCONF_DETECT_NETWORK, "Network"},
  {PCONF_DETECT_USB,"USB"},
  // {PCONF_DETECT_IRDA,"irda"},
  // {PCONF_DETECT_HPMULTI, "HP Multicast"}, 
  {0, ""}
};

static pconf_xref_t *pconf_xref_top = NULL;

/*==============================================================*/
/*----------------------------------------------------------------
  Return a list (array) of the possible printer detection
  methods.

  Note: need to do better than this; what if we can't 
  (for example) parport probe? Do we want to even present an
  option if we can't do it?
----------------------------------------------------------------*/
pconf_detmethod_t *pconf_get_detection_methods(int *count){
  *count = 2;
  return &(pconf_methods[0]);
}

/*==============================================================*/
static char *pconf_autodetect_pport(long int port)
{
/*----------------------------------------------------------------
  Note: Are we going to use parport for this? Does parport
  put the printer information into /proc/parport/0/devices,
  etc.?
----------------------------------------------------------------*/
  char *printer_name = NULL;

  /* These 2 calls use Red Hat printer-config parport.c calls. */
  probe_parport(port);
  printer_name = (char *)parport_probe_model(port);

  return printer_name;
}

static char **pconf_autodetect_usb(const char *devstr){
  char **dev_strings=g_strsplit(devstr,",",0);
  char **cur;
  char **retval;
  char **curret;
  for(cur=dev_strings;*cur!=NULL;cur++);
  curret=retval=malloc(sizeof(char*)*(cur-dev_strings+1));
  memset(retval,0,sizeof(char*)*(cur-dev_strings+1));

  for(cur=dev_strings;*cur!=NULL;cur++){
     char buf[8192];
     int fd;
     int val;
     char *vendor;
     char *model;
     char *c2;
     GString *str=g_string_new("/dev/usb/lp");
     g_string_sprintfa(str,"%s",*cur);
     fd=open(str->str,O_RDONLY);
     memset(buf,0,8192);
     g_string_assign(str,"");
     if(fd==-1 || (val=ioctl(fd,LPIOC_GET_DEVICE_ID(8192),buf))==-1){
       g_string_free(str,TRUE);
       continue;
     }
     if((vendor=strstr(buf+2,"MFG:"))==0){
       g_string_free(str,TRUE);
       continue;
     }
     vendor+=4;
     if((model=strstr(buf+2,"MDL:"))==0){
       g_string_free(str,TRUE);
       continue;
     }
     model+=4;
     if((c2=strchr(vendor,';'))==0){
       g_string_free(str,TRUE);
       continue;
     }
     *c2=0;
     if((c2=strchr(model,';'))==0){
       g_string_free(str,TRUE);
       continue;
     }
     *c2=0;
     g_string_sprintf(str,"device=%s;vendor=%s;model=%s",str->str,vendor,
                   model);
     *curret=str->str;
     curret++;
     g_string_free(str,FALSE);
   }
  g_strfreev(dev_strings);
  return retval;
}

/*==============================================================*/
char **pconf_detect_printer(pconf_detect_t dettype,const char *detinfo,
                      int *retval)
{
/*----------------------------------------------------------------
  Attempt to detect a printer of a specific type (attached to
  parallel port, networked, etc.). Return a list of unique 
  printer IDs that can be used to setup the detected printers.
----------------------------------------------------------------*/
  char *temp = NULL;
  char *portstr = NULL;
  char **top = NULL;
  char *endptr = NULL;
  char *p = NULL;
  char *info = NULL;
  char *sep = ",";
  long int port = -1;
  int count = 0;
  char *aline = NULL;

  *retval = 0;

  switch (dettype) {
  case PCONF_DETECT_PPORT:
    /* Parse the detinfo (a comma separated set of numbers. */
    temp = (char *)strdup(detinfo);

    portstr = (char *)strtok(temp, sep);
    /* Process a single port string. */
    while (portstr) {
      /* Convert to number */
      port = strtol(portstr, &endptr, 10);
      if (endptr != portstr) {
      /* Expand the list of char*'s as we go. */
      top = realloc(top, (++count) * sizeof(char *));

      /* Get the printer ID for this port */
      p = (char *)pconf_autodetect_pport(port);
      if (!p)
        p = (char *)strdup("Port not configured");

      info = malloc(strlen(portstr) + strlen(p) + 25);
      sprintf(info, "port=%ld;model=%s", port, p);
      if (p)
        free(p);

      top[count - 1] = info;
      }
      portstr = (char *)strtok(NULL, sep);
    }
    top = realloc(top, (++count) * sizeof(char *));
    top[count - 1] = NULL;


    free(temp);
    break;
  case PCONF_DETECT_NETWORK:
    p = (char *) get_snmp_printers (detinfo, retval);

    /* An error occurred. */
    if (*retval != 0)
      return NULL;

    /* Split p up at newlines and make array of string pointers.*/
    if (p != NULL) {
      temp = (char *)strdup(p);
      aline = (char *)strtok(temp, "\n");

      while (aline) {
      /* Expand the list of char*'s as we go. */
      top = realloc(top, (++count) * sizeof(char *));

      info = strdup(aline);
      top[count - 1] = info;

      aline = (char *)strtok(NULL, "\n");
      }
      /* Null terminate the list of strings (char pointers). */
      top = realloc(top, (++count) * sizeof(char *));
      top[count - 1] = NULL;

      free(temp);
    }
    break;
  case PCONF_DETECT_USB:
    return pconf_autodetect_usb(detinfo);
    break;
  default:
    break;
  }

  return (char **)top;
}

/*==============================================================*/
pconf_xref_t *pconf_read_xref_file(char *filename)
{
/*----------------------------------------------------------------
  Read a printer cross-reference file, which has the format:

  # comment
  printer-id\tppd-file-name

----------------------------------------------------------------*/

  FILE *fp;
  char *buf = NULL;
  char *id = NULL;
  char *ppd = NULL;
  char *shortdesc = NULL;
  char *longdesc = NULL;

  pconf_xref_t *top = NULL;
  pconf_xref_t *current = NULL;
  pconf_xref_t *new = NULL;

  /* Sanity checks */

  if (filename == NULL)
    return NULL;

  fp = fopen(filename, "r");  /* ITS4: ignore */
  if (!fp)
    return NULL;

  /* Read file into array */

  buf = (char *)malloc(PCONF_MAX_XREF_STRLEN);
  while (fgets(buf, PCONF_MAX_XREF_STRLEN, fp)) {

    /* Get rid of any trailing newline. */
    if (buf[strlen(buf) - 1] == '\n')
      buf[strlen(buf) - 1] = 0;

    /* Get rid of initial white space. */
    while ((buf[0] != 0) && ((buf[0] == ' ') || (buf[0] == '\t')))
      buf++;

    /* Continue parsing any non-null lines. */
    if ((buf[0] != 0) && (buf[0] != '#')) {

      /* Break on tab */
      id = (char *)strtok(buf, "\t");
      ppd = (char *)strtok(NULL, "\t");
      shortdesc = (char *)strtok(NULL, "\t");
      longdesc = (char *)strtok(NULL, "\t");

      printf("ID: %s FILE: %s\n", id, ppd);     /* ITS4: ignore */

      /* Add this data to xref list. */

      new = (pconf_xref_t *) malloc(sizeof(pconf_xref_t));
      new->id = id ? (char *)strdup(id) : NULL;
      new->ppd = ppd ? (char *)strdup(ppd) : NULL;
      new->shortdesc = shortdesc ? (char *)strdup(shortdesc) : NULL;
      new->longdesc = longdesc ? (char *)strdup(longdesc) : NULL;

      /* list maintenance */
      if (new->id && new->ppd) {
      new->next = NULL;
      if (!top)
        top = new;
      else
        current->next = new;

      current = new;
      } else
      free(new);

    }
  }


  fclose(fp);

  /* Sort array by printer-id */

  return top;
}

/*==============================================================*/
pconf_xref_t *pconf_find_xref_by_id(char *target_id)
{
/*----------------------------------------------------------------
  Given a printer id, return the matching xref struct, or NULL
  if not found.
----------------------------------------------------------------*/
  pconf_xref_t *curr;

  if (pconf_xref_top == NULL)
    pconf_xref_top = (pconf_xref_t *) pconf_read_xref_file(PCONF_XREF_FILE);

  for (curr = pconf_xref_top; curr; curr = curr->next)
    if (!strcmp(curr->id, target_id))
      return curr;

  return NULL;
}

wchar_t *pconf_unique_prname(const char *ns){
  LPS_System_t *sys=lps_init(NULL);
  wchar_t *retval;
  assert(sys);
  retval=pconf_s_unique_prname(sys,ns);
  lps_end(sys);
  return retval;
}

wchar_t *pconf_s_unique_prname(LPS_System_t *sys,const char *ns){
  GString *buf=g_string_new("lp");
  int len;
  wchar_t *name=lps_promote(buf->str);
  assert(name);
  if(lps_get_printer(sys,name,ns)==NULL){
    unsigned int i=0;
    do{
      free(name);
      g_string_sprintf(buf,"lp%ud",i);
      name=lps_promote(buf->str);
      i++;
    }while(lps_get_printer(sys,name,ns)==NULL);
  }
  g_string_free(buf,TRUE);
  lps_end(sys);
  return name;
}

LPS_Printer_t *pconf_create_printer(wchar_t **names,pconf_prn_t type,
                            char *spooldir,pconf_err_t *err, ...){
  LPS_System_t *sys=lps_init(NULL);
  LPS_Printer_t *prn;
  va_list args;

  assert(sys);

  va_start(args,err);
  prn=pconf_v_create_printer(sys,names,type,spooldir,err,args);
  va_end(args);
  assert(prn);
  lps_end(sys);
  return prn;
}

LPS_Printer_t *pconf_s_create_printer(LPS_System_t *sys,wchar_t **names,
                              pconf_prn_t type,char *spooldir,
                              pconf_err_t *err, ...){
  va_list args;
  LPS_Printer_t *retval;

  va_start(args,err);
  retval=pconf_v_create_printer(sys,names,type,spooldir,err,args);
  va_end(args);
  return retval;
}

char *_pconf_mkdir_p(const char *path, mode_t mask)
{
  char *dname = NULL;
  char *loop_ret = NULL;
  
  if ((mkdir(path, mask) == -1) && (errno != ENOENT))
    return (g_strdup(path));

  dname = g_dirname(path);
  loop_ret = _pconf_mkdir_p(dname, mask);
  g_free(dname);
  if (loop_ret)
    return (loop_ret);

  if (mkdir(path, mask) == -1)
    return (g_strdup(path));

  return (NULL);
}

LPS_Printer_t *pconf_v_create_printer(LPS_System_t *sys,wchar_t **names,
                              pconf_prn_t type,char *spooldir,
                              pconf_err_t *err,va_list args){
  LPS_Printer_t *retval=NULL;
  LPS_Pair_t *fields=NULL;
  wchar_t buf[VALBUFSIZE];
  int len;
  struct stat_buf *stbuf;
  char *str;
  

  wcscpy(buf,DEFSD);
  len=wcslen(buf);
  if(spooldir!=NULL){
    wchar_t *wtmp=lps_promote(spooldir);
    assert(wtmp);
    fields=lps_pair_update(fields,SPOOLDIR_KEY,wtmp);    
    free(wtmp);
  }else{
    wcscat(buf,names[0]);
    fields=lps_pair_update(fields,SPOOLDIR_KEY,buf);
  }
  if(fields==NULL) goto no_mem;
  wcscpy(buf+len,DEFAF);
  fields=lps_pair_update(fields,ACCOUNTING_FILE_KEY,buf);
  if(fields==NULL) goto no_mem;
  wcscpy(buf+len,DEFLO);
  fields=lps_pair_update(fields,LOCKFILE_KEY,buf);
  if(fields==NULL) goto no_mem;
  wcscpy(buf+len,DEFST);
  fields=lps_pair_update(fields,STATFILE_KEY,buf);
  if(fields==NULL) goto no_mem;

  fields=lps_pair_update(fields,MAXFILE_KEY,L"0");
  if(fields==NULL) goto no_mem;
  fields=lps_pair_update(fields,SUPP_HEADER_KEY,TRUESTR);
  if(fields==NULL) goto no_mem;
  
  switch(type){
  case PCONF_PRN_LOCAL:
    fields=lps_pair_update(fields,DEVICE_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    break;
  case PCONF_PRN_REMOTELPR:
    fields=lps_pair_update(fields,REMOTE_MACHINE_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,REMOTE_PORT_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    break;
  case PCONF_PRN_DIRECTTCP:
    fields=lps_pair_update(fields,DIR_IP_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,DIR_PORT_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    wcscpy(buf,LIBEXECDIR);
    wcscat(buf,L"/directprint");
    fields=lps_pair_update(fields,INPUT_FILTER_KEY,buf);
    if(fields==NULL) goto no_mem;
    break;
  case PCONF_PRN_SAMBA:
    fields=lps_pair_update(fields,SMB_HOST_KEY ,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,SMB_SHARE_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,USER_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,PW_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,SMB_HOSTIP_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,SMB_WORKGROUP_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    wcscpy(buf,LIBEXECDIR);
    wcscat(buf,L"/smbprint");
    fields=lps_pair_update(fields,INPUT_FILTER_KEY,buf);
    if(fields==NULL) goto no_mem;
    break;
  case PCONF_PRN_NCP:
    fields=lps_pair_update(fields,NCP_SERVER_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,NCP_PRINTER_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,USER_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    fields=lps_pair_update(fields,PW_KEY,va_arg(args,wchar_t *));
    if(fields==NULL) goto no_mem;
    wcscpy(buf,LIBEXECDIR);
    wcscat(buf,L"/ncpprint");
    fields=lps_pair_update(fields,INPUT_FILTER_KEY,buf);
    if(fields==NULL) goto no_mem;
    break;
  };

  retval=lps_create_printer(sys,names,fields,NULL);
  if(retval==NULL){
    switch(sys->lps_errno){
    case LPS_BADNAME:
      *err=PCONF_BADNAME_ERR;
      return NULL;
    case LPS_NOMEM:
      goto no_mem;
    default:
      *err=PCONF_BADSYS_ERR;
      return NULL;
    }
  }

  //create spooldir
  str=lps_demote(lps_pair_lookup(fields,SPOOLDIR_KEY));
  if((str=_pconf_mkdir_p(str,0755))!=NULL){
    *err=PCONF_MKSD_ERR;
    free(str);
    return NULL;
  }
  free(str);

  *err=PCONF_OK_ERR;
  return retval;

 no_mem:
  *err=PCONF_NOMEM_ERR;
  return NULL;
}

Generated by  Doxygen 1.6.0   Back to index