From 9bc646c7b7aa2229464efa05b6f7148a285d0c50 Mon Sep 17 00:00:00 2001 From: nidhijainpnp <12njain06@gmail.com> Date: Thu, 6 Aug 2020 00:45:55 +0530 Subject: [PATCH] modify driverless to list ipp and ipps printers --- utils/driverless.1 | 4 +- utils/driverless.c | 906 +++++++++++++++++++++++---------------------- 2 files changed, 457 insertions(+), 453 deletions(-) diff --git a/utils/driverless.1 b/utils/driverless.1 index ea92c7924..18c5b4f24 100644 --- a/utils/driverless.1 +++ b/utils/driverless.1 @@ -53,11 +53,11 @@ for driverless PPD file generation (to be used by CUPS). .TP .B \fB_ipps._tcp\fP -List the Printer URIs for all available IPPS printers supporting driverless printing. +Check for only IPPS printers supporting driverless printing (to be used by CUPS). .TP .B \fB_ipp._tcp\fP -List the Printer URIs for all available IPP printers supporting driverless printing. +Check for only IPP printers supporting driverless printing (to be used by CUPS). .TP .B \fBcat\fP \fIdriver URI\fP diff --git a/utils/driverless.c b/utils/driverless.c index c4bcc644a..8a23d2f18 100644 --- a/utils/driverless.c +++ b/utils/driverless.c @@ -43,43 +43,365 @@ static int debug = 0; static int job_canceled = 0; static void cancel_job(int sig); +static int +compare_service_uri(char *a, char *b) +{ + size_t size = sizeof(a); + return (memcmp(a,b, size)); +} +void +listPrintersInArray(int post_proc_pipe[], cups_array_t *service_uri_list_ipps, int reg_type_no, int mode){ + int driverless_support = 0, /*process id for ippfind */ + bytes; /* Bytes copied */ + + char buffer[8192], /* Copy buffer */ + *bufferOutput, /* service_uri along with metadata */ + * copy_bufferOutput_ipps; /* ipps scheme version of service_uri along with metadata */ + cups_file_t *fp; /* Post-processing input file */ + char *ptr; /* Pointer into string */ + char *scheme = NULL, + *copy_scheme_ipps = NULL, /* ipps scheme version for ipp printers */ + *service_name = NULL, + *domain = NULL, + *reg_type = NULL, + *copy_reg_type_ipps = NULL, /* ipps reg_type version for ipp printers */ + *txt_usb_mfg = NULL, + *txt_usb_mdl = NULL, + *txt_product = NULL, + *txt_ty = NULL, + *txt_pdl = NULL, + value[256], /* Value string */ + *service_uri,/* URI to list for this service */ + *copy_service_uri_ipps, /* ipps service_uri version for ipp printers */ + service_host_name[1024],/* "Host name" for assembling URI */ + copy_service_host_name_ipps[1024], /* ipps service_host_name version for ipp printers */ + make_and_model[1024], /* Manufacturer and model */ + make[512], /* Manufacturer */ + model[256], /* Model */ + pdl[256], /* PDL */ + driverless_info[256], /* Driverless info string */ + device_id[2048]; /* 1284 device ID */ + + + dup2(post_proc_pipe[0], 0); + close(post_proc_pipe[0]); + close(post_proc_pipe[1]); + + + fp = cupsFileStdin(); + + while ((bytes = cupsFileGetLine(fp, buffer, sizeof(buffer))) > 0){ + /* Mark all the fields of the output of ippfind */ + service_uri = (char *)malloc(2048*(sizeof(char))); + copy_service_uri_ipps = (char *)malloc(2048*(sizeof(char))); + bufferOutput = (char *)malloc(8192*(sizeof(char))); + copy_bufferOutput_ipps = (char *)malloc(8192*(sizeof(char))); + + ptr = buffer; + /* First, build the DNS-SD-service-name-based URI ... */ + while (ptr && !isalnum(*ptr & 255)) ptr ++; + + if ( ( !strncasecmp(ptr, "ipp", 3) && ptr[3] == '\t')) { + scheme = ptr; + + copy_scheme_ipps = "ipps\0"; + ptr += 3; + *ptr = '\0'; + + ptr ++; + reg_type = "_ipp._tcp"; + + copy_reg_type_ipps = "_ipps._tcp"; + + }else if ( (!strncasecmp(ptr, "ipps", 4) && ptr[4] == '\t')) { + scheme = ptr; + ptr += 4; + *ptr = '\0'; + ptr ++; + reg_type = "_ipps._tcp"; + }else + goto read_error; + + service_name = ptr; + + ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); + if (!ptr) goto read_error; + *ptr = '\0'; + ptr ++; + domain = ptr; + ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); + if (!ptr) goto read_error; + *ptr = '\0'; + ptr ++; + snprintf(service_host_name, sizeof(service_host_name) - 1, "%s.%s.%s", + service_name, reg_type, domain); + + if(reg_type_no < 1 ){ + snprintf(copy_service_host_name_ipps, sizeof(copy_service_host_name_ipps) - 1, "%s.%s.%s", + service_name, copy_reg_type_ipps, domain); + } + httpAssembleURIf(HTTP_URI_CODING_ALL, service_uri, + 2047, + scheme, NULL, + service_host_name, 0, "/"); + + if( reg_type_no < 1 ){ + httpAssembleURIf(HTTP_URI_CODING_ALL, copy_service_uri_ipps, + 2047, + copy_scheme_ipps, NULL, + copy_service_host_name_ipps, 0, "/"); + } + + /* ... second, complete the output line, either URI-only or with + extra info for CUPS */ + if (mode == 0){ + /* Manual call on the command line */ + if(reg_type_no < 1){ + if(cupsArrayFind(service_uri_list_ipps,copy_service_uri_ipps) == NULL){ + /* IPPS version of IPP printer is not present */ + printf("%s\n",service_uri); + } + } + else{ + cupsArrayAdd(service_uri_list_ipps , service_uri); + printf("%s\n",service_uri); + } + + } + else { + /* Call by CUPS, either as PPD generator + (/usr/lib/cups/driver/, with "list" command line argument) + or as backend in discovery mode (/usr/lib/cups/backend/, + env variable "SOFTWARE" starts with "CUPS") */ + txt_usb_mfg = ptr; + ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); + if (!ptr) goto read_error; + *ptr = '\0'; + ptr ++; + txt_usb_mdl = ptr; + ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); + if (!ptr) goto read_error; + *ptr = '\0'; + ptr ++; + txt_product = ptr; + ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); + if (!ptr) goto read_error; + *ptr = '\0'; + ptr ++; + txt_ty = ptr; + ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); + if (!ptr) goto read_error; + *ptr = '\0'; + ptr ++; + txt_pdl = ptr; + ptr = memchr(ptr, '\n', sizeof(buffer) - (ptr - buffer)); + if (!ptr) goto read_error; + *ptr = '\0'; + + make_and_model[0] = '\0'; + make[0] = '\0'; + pdl[0] = '\0'; + device_id[0] = '\0'; + strncpy(model, "Unknown", sizeof(model) - 1); + + if (txt_usb_mfg[0] != '\0') { + strncpy(make, txt_usb_mfg, sizeof(make) - 1); + if (strlen(txt_usb_mfg) > 511) + make[511] = '\0'; + ptr = device_id + strlen(device_id); + snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), + "MFG:%s;", txt_usb_mfg); + } + if (txt_usb_mdl[0] != '\0') { + strncpy(model, txt_usb_mdl, sizeof(model) - 1); + if (strlen(txt_usb_mdl) > 255) + model[255] = '\0'; + ptr = device_id + strlen(device_id); + snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), + "MDL:%s;", txt_usb_mdl); + }else if (txt_product[0] != '\0') { + if (txt_product[0] == '(') { + /* Strip parenthesis... */ + if ((ptr = txt_product + strlen(txt_product) - 1) > txt_product && + *ptr == ')') + *ptr = '\0'; + strncpy(model, txt_product + 1, sizeof(model) - 1); + if ((strlen(txt_product) + 1) > 255) + model[255] = '\0'; + } else + strncpy(model, txt_product, sizeof(model) - 1); + }else if (txt_ty[0] != '\0') { + strncpy(model, txt_ty, sizeof(model) - 1); + if (strlen(txt_ty) > 255) + model[255] = '\0'; + if ((ptr = strchr(model, ',')) != NULL) + *ptr = '\0'; + } + if (txt_pdl[0] != '\0') { + strncpy(pdl, txt_pdl, sizeof(pdl) - 1); + if (strlen(txt_pdl) > 255) + pdl[255] = '\0'; + } + + if (!device_id[0] && strcasecmp(model, "Unknown")) { + if (make[0]) + snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", + make, model); + else if (!strncasecmp(model, "designjet ", 10)) + snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;", + model + 10); + else if (!strncasecmp(model, "stylus ", 7)) + snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;", + model + 7); + else if ((ptr = strchr(model, ' ')) != NULL) { + /* Assume the first word is the make...*/ + memcpy(make, model, (size_t)(ptr - model)); + make[ptr - model] = '\0'; + snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", + make, ptr + 1); + } + } + + if (device_id[0] && + !strcasestr(device_id, "CMD:") && + !strcasestr(device_id, "COMMAND SET:") && + (strcasestr(pdl, "application/pdf") || + strcasestr(pdl, "application/postscript") || + strcasestr(pdl, "application/vnd.hp-PCL") || + strcasestr(pdl, "application/PCLm") || + strcasestr(pdl, "image/"))) { + value[0] = '\0'; + if (strcasestr(pdl, "application/pdf")) + strncat(value, ",PDF", sizeof(value)); + if (strcasestr(pdl, "application/PCLm")) + strncat(value, ",PCLM", sizeof(value)); + if (strcasestr(pdl, "application/postscript")) + strncat(value, ",PS", sizeof(value)); + if (strcasestr(pdl, "application/vnd.hp-PCL")) + strncat(value, ",PCL", sizeof(value)); + if (strcasestr(pdl, "image/pwg-raster")) + strncat(value, ",PWGRaster", sizeof(value)); + if (strcasestr(pdl, "image/urf")) + strncat(value, ",AppleRaster", sizeof(value)); + for (ptr = strcasestr(pdl, "image/"); ptr; + ptr = strcasestr(ptr, "image/")) { + char *valptr = value + strlen(value); + if (valptr < (value + sizeof(value) - 1)) + *valptr++ = ','; + ptr += 6; + while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.') { + if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1)) + *valptr++ = (char)toupper(*ptr++ & 255); + else + break; + } + *valptr = '\0'; + } + ptr = device_id + strlen(device_id); + snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), + "CMD:%s;", value + 1); + } + + if (make[0] && + (strncasecmp(model, make, strlen(make)) || + !isspace(model[strlen(make)]))) + snprintf(make_and_model, sizeof(make_and_model), "%s %s", + make, model); + else + strncpy(make_and_model, model, sizeof(make_and_model) - 1); + + /* Check which driverless support is available for the found device: + * 0) DRVLESS_CHECKERR - the device failed to respond + * to any get-printer-attributes request versions available. + * 1) FULL_DRVLESS - the device responded correctly to IPP 2.0 get-printer-attributes request. + * The device is compatible with CUPS 'everywhere' model. + * 2) DRVLESS_IPP11 - the device responded correctly to IPP 1.1 get-printer-attributes request. + * 3) DRVLESS_INCOMPLETEIPP - the device responded correctly to IPP get-printer-attributes request + * without media-col-database attribute + * + * If we know which driverless support is available, we can divide which devices can be supported + * by CUPS temporary queues and which devices need cups-browsed to run. + */ + driverless_support = check_driverless_support(service_uri); + + if (driverless_support == DRVLESS_CHECKERR) + fprintf(stderr, "Failed to get info about driverless support."); + + snprintf(driverless_info, 255, "%s", driverless_support_strs[driverless_support]); + driverless_info[255] = '\0'; + + if (mode == 1){ + /* Call with "list" argument (PPD generator in list mode) */ + snprintf(bufferOutput,8190,"\"driverless:%s\" en \"%s\" \"%s, %s, cups-filters " VERSION + "\" \"%s\"\n", service_uri, make, make_and_model, driverless_info, device_id); + bufferOutput[8191] = '\0'; + if(reg_type_no < 1){ + snprintf(copy_bufferOutput_ipps,8190,"\"driverless:%s\" en \"%s\" \"%s, %s, cups-filters " VERSION + "\" \"%s\"\n", copy_service_uri_ipps, make, make_and_model, driverless_info, device_id); + copy_bufferOutput_ipps[8191] = '\0'; + if(cupsArrayFind(service_uri_list_ipps,copy_bufferOutput_ipps) == NULL){ + /* IPPS version of IPP printer is not present */ + printf("%s",bufferOutput); + } + } + else{ + + cupsArrayAdd(service_uri_list_ipps , bufferOutput); + printf("%s",bufferOutput); + } + } + else{ + /* Call without arguments and env variable "SOFTWARE" starting + with "CUPS" (Backend in discovery mode) */ + snprintf(bufferOutput,8190,"network %s \"%s\" \"%s (%s)\" \"%s\" \"\"\n", service_uri, make_and_model, make_and_model, driverless_info, device_id); + bufferOutput[8191] = '\0'; + if(reg_type_no < 1){ + snprintf(bufferOutput,8190,"network %s \"%s\" \"%s (%s)\" \"%s\" \"\"\n", copy_service_uri_ipps, make_and_model, make_and_model, driverless_info, device_id); + copy_bufferOutput_ipps[8191] = '\0'; + if(cupsArrayFind(service_uri_list_ipps,copy_bufferOutput_ipps) == NULL){ + /* IPPS version of IPP printer is not present */ + printf("%s",bufferOutput); + } + } + else{ + cupsArrayAdd(service_uri_list_ipps , bufferOutput); + printf("%s",bufferOutput); + } + + } + + read_error: + continue; + } + } + + /* + * Copy the rest of the file + */ + + while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) + fwrite(buffer, 1, bytes, stdout); + + return ; + +} int list_printers (int mode ,int reg_type_no) { - int driverless_support = 0, /* Process ID for ippfind */ - ippfind_pid, /* Process ID of ippfind */ - post_proc_pid = 0, /* Process ID of post-processing */ - post_proc_pipe[2], /* Pipe to post-processing */ + int + ippfind_ipp_pid = 0, /* Process ID of ippfind for IPP */ + ippfind_ipps_pid = 0, /* Process ID of ippfind for IPPS */ + post_proc_pipe_ipps[2], /* Pipe to post-processing for IPPS */ + post_proc_pipe_ipp[2], /* Pipe to post-processing for IPP */ wait_children, /* Number of child processes left */ wait_pid, /* Process ID from wait() */ wait_status, /* Status from child */ - exit_status = 0, /* Exit status */ - bytes, /* Bytes copied */ - i; - char *ippfind_argv[100], /* Arguments for ippfind */ - buffer[8192]; /* Copy buffer */ - cups_file_t *fp; /* Post-processing input file */ - char *ptr; /* Pointer into string */ - char *scheme = NULL, - *service_name = NULL, - *domain = NULL, - *reg_type = NULL, - *txt_usb_mfg = NULL, - *txt_usb_mdl = NULL, - *txt_product = NULL, - *txt_ty = NULL, - *txt_pdl = NULL, - value[256], /* Value string */ - service_uri[2048], /* URI to list for this service */ - service_host_name[1024],/* "Host name" for assembling URI */ - make_and_model[1024], /* Manufacturer and model */ - make[512], /* Manufacturer */ - model[256], /* Model */ - pdl[256], /* PDL */ - driverless_info[256], /* Driverless info string */ - device_id[2048]; /* 1284 device ID */ - FILE *fptr1, /*service_name_file */ - *fptr2; /* service_uri_file */ + exit_status = 0, /* Exit status */ + i; + char *ippfind_argv[100]; /* Arguments for ippfind */ + + cups_array_t *service_uri_list_ipps ; /* Array to store ippfind output */ + service_uri_list_ipps = cupsArrayNew((cups_array_func_t)compare_service_uri,NULL); /* * Use CUPS' ippfind utility to discover all printers designed for @@ -92,10 +414,7 @@ list_printers (int mode ,int reg_type_no) i = 0; ippfind_argv[i++] = "ippfind"; - if(reg_type_no == 1) - ippfind_argv[i++] = "_ipps._tcp"; /* list IPPS entries */ - else - ippfind_argv[i++] = "_ipp._tcp"; /* list IPP entries */ + ippfind_argv[i++] = "_ipps._tcp"; /* list IPPS entries */ ippfind_argv[i++] = "-T"; /* Bonjour poll timeout */ ippfind_argv[i++] = "3"; /* 3 seconds */ ippfind_argv[i++] = "!"; /* ! --txt printer-type */ @@ -132,320 +451,106 @@ list_printers (int mode ,int reg_type_no) /* - * Create a pipe for passing the ippfind output to post-processing + * Create a pipe for passing the ippfind output to post-processing for IPPS */ - if (pipe(post_proc_pipe)) + if (pipe(post_proc_pipe_ipps)) { perror("ERROR: Unable to create pipe to post-processing"); exit_status = 1; goto error; } + if(reg_type_no >=1 ){ + + if ((ippfind_ipps_pid = fork()) == 0) + { + /* + * Child comes here... + */ + + dup2(post_proc_pipe_ipps[1], 1); + close(post_proc_pipe_ipps[0]); + close(post_proc_pipe_ipps[1]); - if ((ippfind_pid = fork()) == 0) - { - /* - * Child comes here... - */ + execvp(CUPS_IPPFIND, ippfind_argv); + perror("ERROR: Unable to execute ippfind utility"); - dup2(post_proc_pipe[1], 1); - close(post_proc_pipe[0]); - close(post_proc_pipe[1]); + exit(1); + } + else if (ippfind_ipps_pid < 0) + { + /* + * Unable to fork! + */ - execvp(CUPS_IPPFIND, ippfind_argv); - perror("ERROR: Unable to execute ippfind utility"); + perror("ERROR: Unable to execute ippfind utility"); - exit(1); + exit_status = 1; + goto error; + } + if (debug) + fprintf(stderr, "DEBUG: Started %s (PID %d)\n", ippfind_argv[0], + ippfind_ipps_pid); + + listPrintersInArray(post_proc_pipe_ipps, service_uri_list_ipps, 2, mode); + } - else if (ippfind_pid < 0) - { - /* - * Unable to fork! - */ + close(post_proc_pipe_ipps[0]); + close(post_proc_pipe_ipps[1]); + + /* + * Create a pipe for passing the ippfind output to post-processing for IPP + */ - perror("ERROR: Unable to execute ippfind utility"); + if (pipe(post_proc_pipe_ipp)) + { + perror("ERROR: Unable to create pipe to post-processing"); exit_status = 1; goto error; } - - if (debug) - fprintf(stderr, "DEBUG: Started %s (PID %d)\n", ippfind_argv[0], - ippfind_pid); - - if ((post_proc_pid = fork()) == 0) - { - /* - * Child comes here... - */ - - dup2(post_proc_pipe[0], 0); - close(post_proc_pipe[0]); - close(post_proc_pipe[1]); - - fp = cupsFileStdin(); - - if(reg_type_no == 1){ - if((fptr1 = fopen("service_name_file_ipps","w"))==NULL) - fprintf(stderr,"Unable to write to service_name_file_ipps"); - if((fptr2 = fopen("service_uri_file_ipps","w"))==NULL) - fprintf(stderr,"Unable to write to service_name_file_ipps"); - } - else{ - if((fptr1 = fopen("service_name_file_ipp","w"))==NULL) - fprintf(stderr,"Unable to write to service_name_file_ipp"); - if((fptr2 = fopen("service_uri_file_ipp","w"))==NULL) - fprintf(stderr,"Unable to write to service_name_file_ipp"); - } - while ((bytes = cupsFileGetLine(fp, buffer, sizeof(buffer))) > 0) + if(reg_type_no <= 1){ + if ((ippfind_ipp_pid = fork()) == 0) { - /* Mark all the fields of the output of ippfind */ - ptr = buffer; - /* First, build the DNS-SD-service-name-based URI ... */ - while (ptr && !isalnum(*ptr & 255)) ptr ++; - if (!strncasecmp(ptr, "ipp", 3) && ptr[3] == '\t') { - scheme = ptr; - ptr += 3; - *ptr = '\0'; - ptr ++; - reg_type = "_ipp._tcp"; - } else if (!strncasecmp(ptr, "ipps", 4) && ptr[4] == '\t') { - scheme = ptr; - ptr += 4; - *ptr = '\0'; - ptr ++; - reg_type = "_ipps._tcp"; - } else - goto read_error; - service_name = ptr; - fprintf(fptr1 ,"%s\n",service_name); - ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); - if (!ptr) goto read_error; - *ptr = '\0'; - ptr ++; - domain = ptr; - ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); - if (!ptr) goto read_error; - *ptr = '\0'; - ptr ++; - snprintf(service_host_name, sizeof(service_host_name) - 1, "%s.%s.%s", - service_name, reg_type, domain); - httpAssembleURIf(HTTP_URI_CODING_ALL, service_uri, - sizeof(service_uri) - 1, - scheme, NULL, - service_host_name, 0, "/"); - /* ... second, complete the output line, either URI-only or with - extra info for CUPS */ - if (mode == 0) - /* Manual call on the command line */ - fprintf(fptr2,"%s\n",service_uri); - else { - /* Call by CUPS, either as PPD generator - (/usr/lib/cups/driver/, with "list" command line argument) - or as backend in discovery mode (/usr/lib/cups/backend/, - env variable "SOFTWARE" starts with "CUPS") */ - txt_usb_mfg = ptr; - ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); - if (!ptr) goto read_error; - *ptr = '\0'; - ptr ++; - txt_usb_mdl = ptr; - ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); - if (!ptr) goto read_error; - *ptr = '\0'; - ptr ++; - txt_product = ptr; - ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); - if (!ptr) goto read_error; - *ptr = '\0'; - ptr ++; - txt_ty = ptr; - ptr = memchr(ptr, '\t', sizeof(buffer) - (ptr - buffer)); - if (!ptr) goto read_error; - *ptr = '\0'; - ptr ++; - txt_pdl = ptr; - ptr = memchr(ptr, '\n', sizeof(buffer) - (ptr - buffer)); - if (!ptr) goto read_error; - *ptr = '\0'; - - make_and_model[0] = '\0'; - make[0] = '\0'; - pdl[0] = '\0'; - device_id[0] = '\0'; - strncpy(model, "Unknown", sizeof(model) - 1); - - if (txt_usb_mfg[0] != '\0') { - strncpy(make, txt_usb_mfg, sizeof(make) - 1); - if (strlen(txt_usb_mfg) > 511) - make[511] = '\0'; - ptr = device_id + strlen(device_id); - snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), - "MFG:%s;", txt_usb_mfg); - } - if (txt_usb_mdl[0] != '\0') { - strncpy(model, txt_usb_mdl, sizeof(model) - 1); - if (strlen(txt_usb_mdl) > 255) - model[255] = '\0'; - ptr = device_id + strlen(device_id); - snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), - "MDL:%s;", txt_usb_mdl); - } else if (txt_product[0] != '\0') { - if (txt_product[0] == '(') { - /* Strip parenthesis... */ - if ((ptr = txt_product + strlen(txt_product) - 1) > txt_product && - *ptr == ')') - *ptr = '\0'; - strncpy(model, txt_product + 1, sizeof(model) - 1); - if ((strlen(txt_product) + 1) > 255) - model[255] = '\0'; - } else - strncpy(model, txt_product, sizeof(model) - 1); - } else if (txt_ty[0] != '\0') { - strncpy(model, txt_ty, sizeof(model) - 1); - if (strlen(txt_ty) > 255) - model[255] = '\0'; - if ((ptr = strchr(model, ',')) != NULL) - *ptr = '\0'; - } - if (txt_pdl[0] != '\0') { - strncpy(pdl, txt_pdl, sizeof(pdl) - 1); - if (strlen(txt_pdl) > 255) - pdl[255] = '\0'; - } - - if (!device_id[0] && strcasecmp(model, "Unknown")) { - if (make[0]) - snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", - make, model); - else if (!strncasecmp(model, "designjet ", 10)) - snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;", - model + 10); - else if (!strncasecmp(model, "stylus ", 7)) - snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;", - model + 7); - else if ((ptr = strchr(model, ' ')) != NULL) { - /* Assume the first word is the make...*/ - memcpy(make, model, (size_t)(ptr - model)); - make[ptr - model] = '\0'; - snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", - make, ptr + 1); - } - } - - if (device_id[0] && - !strcasestr(device_id, "CMD:") && - !strcasestr(device_id, "COMMAND SET:") && - (strcasestr(pdl, "application/pdf") || - strcasestr(pdl, "application/postscript") || - strcasestr(pdl, "application/vnd.hp-PCL") || - strcasestr(pdl, "application/PCLm") || - strcasestr(pdl, "image/"))) { - value[0] = '\0'; - if (strcasestr(pdl, "application/pdf")) - strncat(value, ",PDF", sizeof(value)); - if (strcasestr(pdl, "application/PCLm")) - strncat(value, ",PCLM", sizeof(value)); - if (strcasestr(pdl, "application/postscript")) - strncat(value, ",PS", sizeof(value)); - if (strcasestr(pdl, "application/vnd.hp-PCL")) - strncat(value, ",PCL", sizeof(value)); - if (strcasestr(pdl, "image/pwg-raster")) - strncat(value, ",PWGRaster", sizeof(value)); - if (strcasestr(pdl, "image/urf")) - strncat(value, ",AppleRaster", sizeof(value)); - for (ptr = strcasestr(pdl, "image/"); ptr; - ptr = strcasestr(ptr, "image/")) { - char *valptr = value + strlen(value); - if (valptr < (value + sizeof(value) - 1)) - *valptr++ = ','; - ptr += 6; - while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.') { - if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1)) - *valptr++ = (char)toupper(*ptr++ & 255); - else - break; - } - *valptr = '\0'; - } - ptr = device_id + strlen(device_id); - snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), - "CMD:%s;", value + 1); - } - - if (make[0] && - (strncasecmp(model, make, strlen(make)) || - !isspace(model[strlen(make)]))) - snprintf(make_and_model, sizeof(make_and_model), "%s %s", - make, model); - else - strncpy(make_and_model, model, sizeof(make_and_model) - 1); - - /* Check which driverless support is available for the found device: - * 0) DRVLESS_CHECKERR - the device failed to respond - * to any get-printer-attributes request versions available. - * 1) FULL_DRVLESS - the device responded correctly to IPP 2.0 get-printer-attributes request. - * The device is compatible with CUPS 'everywhere' model. - * 2) DRVLESS_IPP11 - the device responded correctly to IPP 1.1 get-printer-attributes request. - * 3) DRVLESS_INCOMPLETEIPP - the device responded correctly to IPP get-printer-attributes request - * without media-col-database attribute - * - * If we know which driverless support is available, we can divide which devices can be supported - * by CUPS temporary queues and which devices need cups-browsed to run. - */ - driverless_support = check_driverless_support(service_uri); - if (driverless_support == DRVLESS_CHECKERR) - fprintf(stderr, "Failed to get info about driverless support."); + /* + * Child comes here... + */ + + ippfind_argv[1] = "_ipp._tcp"; - snprintf(driverless_info, 255, "%s", driverless_support_strs[driverless_support]); - driverless_info[255] = '\0'; + dup2(post_proc_pipe_ipp[1], 1); + close(post_proc_pipe_ipp[0]); + close(post_proc_pipe_ipp[1]); - if (mode == 1) - /* Call with "list" argument (PPD generator in list mode) */ - fprintf(fptr2,"\"driverless:%s\" en \"%s\" \"%s, %s, cups-filters " VERSION - "\" \"%s\"\n", service_uri, make, make_and_model, driverless_info, device_id); - else - /* Call without arguments and env variable "SOFTWARE" starting - with "CUPS" (Backend in discovery mode) */ - fprintf(fptr2,"network %s \"%s\" \"%s (%s)\" \"%s\" \"\"\n", service_uri, make_and_model, make_and_model, driverless_info, device_id); + execvp(CUPS_IPPFIND, ippfind_argv); + perror("ERROR: Unable to execute ippfind utility"); - read_error: - continue; - } + exit(1); } - - /* - * Copy the rest of the file - */ - - while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0) - fwrite(buffer, 1, bytes, stdout); - - fclose(fptr1); - fclose(fptr2); - - exit(0); - } - else if (post_proc_pid < 0) - { + else if (ippfind_ipp_pid < 0) + { /* - * Unable to fork! - */ + * Unable to fork! + */ - perror("ERROR: Unable to execute post-processing process"); + perror("ERROR: Unable to execute ippfind utility"); - exit_status = 1; - goto error; + exit_status = 1; + goto error; + } + if (debug) + fprintf(stderr, "DEBUG: Started %s (PID %d)\n", ippfind_argv[0], + ippfind_ipp_pid); + listPrintersInArray(post_proc_pipe_ipp, service_uri_list_ipps, 0, mode); } - if (debug) - fprintf(stderr, "DEBUG: Started post-processing (PID %d)\n", post_proc_pid); - - close(post_proc_pipe[0]); - close(post_proc_pipe[1]); + + close(post_proc_pipe_ipp[0]); + close(post_proc_pipe_ipp[1]); + /* * Wait for the child processes to exit... */ @@ -462,8 +567,8 @@ list_printers (int mode ,int reg_type_no) { if (job_canceled) { - kill(ippfind_pid, SIGTERM); - kill(post_proc_pid, SIGTERM); + kill(ippfind_ipps_pid, SIGTERM); + kill(ippfind_ipp_pid, SIGTERM); job_canceled = 0; } @@ -487,13 +592,13 @@ list_printers (int mode ,int reg_type_no) if (debug) fprintf(stderr, "DEBUG: PID %d (%s) stopped with status %d!\n", wait_pid, - wait_pid == ippfind_pid ? "ippfind" : - (wait_pid == post_proc_pid ? "Post-processing" : + wait_pid == ippfind_ipps_pid ? "ippfind _ipps._tcp" : + (wait_pid == ippfind_ipp_pid ? "ippfind _ipp._tcp" : "Unknown process"), exit_status); /* When run by CUPS do not exit with an error status if there is simply no driverless printer available or no Avahi present */ - if (mode != 0 && wait_pid == ippfind_pid && exit_status <= 2) + if (mode != 0 && wait_pid == ippfind_ipps_pid && exit_status <= 2) exit_status = 0; } else if (WTERMSIG(wait_status) == SIGTERM) @@ -502,8 +607,8 @@ list_printers (int mode ,int reg_type_no) fprintf(stderr, "DEBUG: PID %d (%s) was terminated normally with signal %d!\n", wait_pid, - wait_pid == ippfind_pid ? "ippfind" : - (wait_pid == post_proc_pid ? "Post-processing" : + wait_pid == ippfind_ipps_pid ? "ippfind _ipps._tcp" : + (wait_pid == ippfind_ipp_pid ? "ippfind _ipp._tcp" : "Unknown process"), exit_status); } @@ -514,8 +619,8 @@ list_printers (int mode ,int reg_type_no) if (debug) fprintf(stderr, "DEBUG: PID %d (%s) crashed on signal %d!\n", wait_pid, - wait_pid == ippfind_pid ? "ippfind" : - (wait_pid == post_proc_pid ? "Post-processing" : + wait_pid == ippfind_ipps_pid ? "ippfind _ipps._tcp" : + (wait_pid == ippfind_ipp_pid ? "ippfind _ipp._tcp" : "Unknown process"), exit_status); } @@ -525,12 +630,13 @@ list_printers (int mode ,int reg_type_no) if (debug) fprintf(stderr, "DEBUG: PID %d (%s) exited with no errors.\n", wait_pid, - wait_pid == ippfind_pid ? "ippfind" : - (wait_pid == post_proc_pid ? "Post-processing" : + wait_pid == ippfind_ipps_pid ? "ippfind _ipps._tcp" : + (wait_pid == ippfind_ipp_pid ? "ippfind _ipp._tcp" : "Unknown process")); } } + cupsArrayDelete(service_uri_list_ipps); /* * Exit... */ @@ -540,113 +646,7 @@ list_printers (int mode ,int reg_type_no) return (exit_status); } -void -copyFromFile(FILE **fptr,int *len_array,char *array[101]){ - int i=0; - while(!feof(*fptr)){ - array[i]= (char *)malloc(1024*sizeof(char)); - fscanf(*fptr,"%[^\n]\n",array[i]); - i++; - } - *len_array = i ; - return; - -} -int -print_list_printers(int mode,int type){ - - char *service_name_list_ipp[101], - *service_name_list_ipps[101]; - int len_service_name_list_ipp = 0, - len_service_name_list_ipps = 0, - reg_type_no = 1 ; /* reg_type = 1 for IPPS and 0 for IPP */ - int exit_status1 = 0, - exit_status2 = 0; - FILE *fptr1; - - exit_status1 = list_printers(mode, reg_type_no); - fprintf(stderr," DEBUG: Exit status for IPPS entries: %d\n",exit_status1); - - reg_type_no = 0; - - exit_status2 = list_printers(mode, reg_type_no); - fprintf(stderr," DEBUG: Exit status for IPP entries: %d\n",exit_status2); - - - - if ((fptr1 = fopen("service_name_file_ipps", "r")) != NULL){ - copyFromFile(&fptr1,&len_service_name_list_ipps,service_name_list_ipps); - fclose(fptr1); - } - else - fprintf(stderr,"Error: Unable to open service_name_file_ipps"); - - if ((fptr1 = fopen("service_name_file_ipp", "r")) != NULL){ - copyFromFile(&fptr1,&len_service_name_list_ipp,service_name_list_ipp); - fclose(fptr1); - } - else - fprintf(stderr,"Error: Unable to open service_name_file_ipp"); - - - if(type == 0 || type == 1){ - /* type 0 for both IPPS and IPP - 1 for IPPS only - 2 for IPP only*/ - if ((fptr1 = fopen("service_uri_file_ipps", "r")) != NULL){ - while(!feof(fptr1)){ - char read[10240]; - fscanf(fptr1,"%[^\n]\n",read); - printf("%s\n",read); - } - fclose(fptr1); - } - else - fprintf(stderr,"Error: Unable to open service_uri_file_ipps"); - } - if(type == 2){ - if ((fptr1 = fopen("service_uri_file_ipp", "r")) != NULL){ - while(!feof(fptr1)){ - char read[10240]; - fscanf(fptr1,"%[^\n]\n",read); - printf("%s\n",read); - } - fclose(fptr1); - } - else - fprintf(stderr,"Error: Unable to open service_uri_file_ipp"); - } -if(type == 0 ){ - int i=0; - int j = 0; /* counter variable to iterate over service_uri_list_ipps array */ - - if ((fptr1 = fopen("service_uri_file_ipp", "r")) == NULL) - fprintf(stderr,"Error: Unable to open service_uri_file_ipp"); - else{ - while(i < len_service_name_list_ipp){ - j = 0; - int isPresent = 0; //not present in service_name_list_ipps array - while(j < len_service_name_list_ipps){ - if(!strcasecmp(service_name_list_ipp[i], service_name_list_ipps[j])){ - isPresent = 1; //present in service_name_list_ipps array - break; - } - j++; - } - char read[10240]; - fscanf(fptr1,"%[^\n]\n",read); - - if(!isPresent) - printf("%s\n",read); - - i++; - - } - } -} - return (exit_status1 || exit_status2); -} int generate_ppd (const char *uri) @@ -711,7 +711,11 @@ generate_ppd (const char *uri) int main(int argc, char*argv[]) { - int i; + int i, + reg_type_no = 1; /* reg_type 0 for only IPP + 1 for both IPPS/IPP + 2 for only IPPS Default is 1*/ + char *val; #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ @@ -757,15 +761,15 @@ int main(int argc, char*argv[]) { /* List a driver URI and metadata for each printer suitable for driverless printing */ debug = 1; - exit(print_list_printers(1,0)); + exit(list_printers(1,reg_type_no)); } else if (!strcasecmp(argv[i], "_ipps._tcp")) { - /* list IPPS printer URIs for all IPPS suitable printers */ + /* reg_type_no = 2 for IPPS entries only*/ debug = 1; - exit(print_list_printers(0,1)); + reg_type_no = 2; }else if (!strcasecmp(argv[i], "_ipp._tcp")) { - /* list IPPS printer URIs for all IPPS suitable printers */ + /* reg_type_no = 0 for IPP entries only*/ debug = 1; - exit(print_list_printers(0,2)); + reg_type_no = 0; }else if (!strncasecmp(argv[i], "cat", 3)) { /* Generate the PPD file for the given driver URI */ debug = 1; @@ -804,10 +808,12 @@ int main(int argc, char*argv[]) { strncasecmp(val, "CUPS", 4) == 0) { /* CUPS backend in discovery mode */ debug = 1; - exit(print_list_printers(2,0)); - } else + exit(list_printers(2,reg_type_no)); + } else{ /* Manual call */ - exit(print_list_printers(0,0)); + debug = 1; + exit(list_printers(0,reg_type_no)); + } help: @@ -824,12 +830,10 @@ int main(int argc, char*argv[]) { " list List the driver URIs and metadata for all available\n" " IPP/IPPS printers supporting driverless printing (to be\n" " used by CUPS).\n" - " _ipps._tcp List the Printer URIs for all available\n" - " IPPS printers supporting driverless printing (to be\n" - " used by CUPS).\n" - " _ipp._tcp List the Printer URIs for all available\n" - " IPP printers supporting driverless printing (to be\n" - " used by CUPS).\n" + " _ipps._tcp Check for only IPPS printers\n" + " supporting driverless printing (to be used by CUPS).\n" + " _ipp._tcp Check for only IPP printers\n" + " supporting driverless printing (to be used by CUPS).\n" " cat Generate the PPD file for the driver URI\n" " (to be used by CUPS).\n" " Generate the PPD file for the IPP/IPPS printer URI\n" -- 2.47.3