pax_global_header00006660000000000000000000000064136226167740014530gustar00rootroot0000000000000052 comment=523d7413f9a9eabb11c332b2477ef482d4ecd5ca lprint-1.0/000077500000000000000000000000001362261677400127005ustar00rootroot00000000000000lprint-1.0/CHANGES.md000066400000000000000000000032531362261677400142750ustar00rootroot00000000000000LPrint Change History ===================== v1.0 - February 17, 2020 ------------------------ - First production release. v1.0rc1 - February 10, 2020 --------------------------- - Updated media documentation (Issue #13) - The `lprint options` command now reports both English and metric dimensions for all supported sizes (Issue #14) - Now support setting the default media source, top offset, tracking, and type values. - Now save and load next job-id value for each printer, along with the printer-config-change-[date-]time and printer-impressions-completed values. - Fixed some small memory leaks. v1.0b2 - January 26, 2020 ------------------------- - Added support for authentication of remote administrative requests (Issue #1) - Added support for managing printers via web browser (Issue #1) - The `add`, `default`, `delete`, and `modify` sub-commands now support the "-u" option (Issue #1) - Fixed an ASLR issue with some Linux compilers (Issue #5) - Added code to detach the Linux usblp kernel driver since apparently there are still Linux distributions shipping the old (and broken) usblp kernel driver (Issue #7) - Device errors are now logged to stderr (for `lprint devices`) or the server log (for `lprint server`) so that it is possible to see permission and other access errors (Issue #8) - Job attributes are now validated properly against the driver attributes (Issue #9) - Fixed an issue in server mode - a failed IPv6 listener would prevent the server from starting (Issue #12) - Added a "spool-directory" option for the `server` sub-command. - Added a spec file for building RPMs. v1.0b1 - January 15, 2020 ------------------------- - First public release. lprint-1.0/CONTRIBUTING.md000066400000000000000000000010041362261677400151240ustar00rootroot00000000000000Contributing to LPrint ====================== I'm happy to accept changes into LPrint. For new drivers, I ask that contributors provide me with a printer and supplies that would allow me to debug any issues *and/or* commit to providing assistance on any issues that are reported on Github. Contributions should be submitted as pull requests on the [LPrint Github project](https://github.com/michaelrsweet/lprint). New code MUST be supplied under the existing LPrint license (Apache 2.0 with the GPL2 exception). lprint-1.0/DESIGN.md000066400000000000000000000165201362261677400141770ustar00rootroot00000000000000Design Notes for LPrint ======================= LPrint is packaged as a single executable with sub-commands, similar to how Git and other tools are provided. The sub-commands are: - "add" to add printers - "cancel" to cancel one or more jobs - "delete" to delete printers - "jobs" to list pending jobs and their status - "modify" to modify printers - "printers" to list printers - "server" to run a server in the background - "shutdown" to stop a running server - "status" to show server or printer status - "submit" to submit file(s) for printing (this is the default subcommand) Architecture ------------ LPrint has a front-end that handles all of the client-side functions, and automatically runs itself in the background to handle background spooling and communication with the printers. Each printer conforms to the IPP Everywhere specification and supports Apple Raster, PWG Raster, and the printer's native format (CPCL, Dymo, EPL, FGL, PCL, ZPL, etc.), and if libpng is available the PNG file format, with color and grayscale image data being dithered (clustered dot) or thresholded to bi-level suitable for thermal label printers. JPEG is explicitly not supported since it is not suitable for bi-level (barcodes, etc.) imagery. Up to four (4) ready media sizes are reported (whatever is loaded in the printer) and can be updated manually via the `lprint modify` command. The background server listens on a per-user UNIX domain socket. If run explicitly, it will also listen for network connections and advertise its printers via DNS-SD. The server supports a small subset of the IPP System Service operations and attributes - basically just the Create-Printer, Delete- Printer, Get-Printers, Get-System-Attributes, Set-System-Attributes, and Shutdown-All-Printers operations and their corresponding attributes. For security, all System operations except for Get-Printers can only be sent locally over the domain socket. If the server crashes or is killed, any pending jobs are lost. Only printers are persisted (by default in the ~/.lprint.conf file) and their corresponding configuration settings. Attributes ---------- The following operation attributes are supported: - "document-format (mimeMediaType)": The format of the document being printed, including 'application/octet-stream' for auto-typed content. - "document-name (name(MAX))": The document title/name/filename. - "ipp-attribute-fidelity (boolean)": Force Job Template values. - "job-name (name(MAX))": The job title. - "requesting-user-name (name(MAX))": The job owner. This attribute is overridden by authenticated user name, if present. The following Job Template attributes are supported: - "copies (integer(1:MAX))": The number of copies of each label. - "media (type2 keyword | name(MAX))": The media size. - "media-col (collection)": The (detailed) media margins, size, source, tracking, and type. - "media-col.media-source (type2 keyword | name(MAX))": 'main-roll', 'alternate-roll'. - "media-col.media-top-offset (integer)": The offset from the top of the label to start printing in hundredths of millimeters. - "media-col.media-tracking (type2 keyword)": The media tracking mode - 'continuous', 'mark', and 'web'. - "media-col.media-type (type2 keyword | name(MAX))": 'continuous' and 'labels'. - "multiple-document-handling (type2 keyword)": 'separate-documents-collated- copies' and 'separate-documents-uncollated-copies' to control collated copies. - "orientation-requested (type2 enum)": 'portrait' (3), 'landscape' (4), 'reverse-landscape' (5), and 'reverse-portrait' (6). - "print-color-mode (type2 keyword)": 'monochrome' and 'bi-level' to provide dithered or threshold B&W output. - "print-content-optimize (type2 keyword)": 'auto', 'graphic', 'photo', 'text', and 'text-and-graphic'. Basically 'auto' will choose a default "print-color-mode" value of 'monochrome' for grayscale input and 'bi-level' otherwise, 'photo' will choose a default "print-color-mode" value of 'monochrome', and all other values will choose a default "print-color-mode" value of 'bi-level'. - "print-darkness (integer(-100:100))": The relative darkness value for thermal markers - values less than 0 are lighter, greater than 0 are darker. - "print-quality (type2 enum)": 'draft' (3), 'normal' (4), and 'high' (5). Chooses default "print-speed" and "printer-resolution" values accordingly. - "print-speed (integer(1:MAX))": Print speed in hundredths of millimeters per second (2540 = 1 inch/sec). - "printer-resolution (resolution)": Printer resolution in dots-per-inch - most printers only support a single resolution. The following Printer Description attributes are supported: - "copies-default (integer(1:MAX))" and "copies-supported (rangeOfInteger(1:MAX))" - "document-format-default (mimeMediaType)" and "document-format-supported (1setOf mimeMediaType)" - "label-mode-configured (type2 keyword)" and "label-mode-supported (1setOf type2 keyword)": The label printing mode - 'applicator', 'cutter', 'cutter-delayed', 'kiosk', 'peel-off', 'peel-off-prepeel', 'rewind', 'rfid', 'tear-off' - "label-tear-offset-configured (integer)" and "label-tear-offset-supported (rangeOfInteger)": Offset in hundredths of millimeters to allow labels/receipts to be torn off safely. Positive values extend the media roll while negative values retract the media roll. - "media-default (type2 keyword | name(MAX))", "media-ready (1setOf (type2 keyword | name(MAX)))", and "media-supported (1setOf (type2 keyword | name(MAX)))" - "media-bottom-margin-supported (1setOf integer(0:MAX))", "media-col-database (1setOf collection)", "media-col-default (collection)", "media-col-ready (1setOf collection)", "media-col-supported (1setOf keyword)", "media-left-margin-supported (1setOf integer(0:MAX))", "media-right-margin-supported (1setOf integer(0:MAX))", "media-size-supported (1setOf collection)", "media-source-supported (1setOf (type2 keyword | name(MAX)))", "media-top-margin-supported (1setOf integer(0:MAX))", "media-top-offset-supported (rangeOfInteger)", "media-tracking-supported (1setOf type2 keyword)", and "media-type-supported (1setOf (type2 keyword | name(MAX)))" - "multiple-document-handling-default (type2 keyword)" and "multiple-document-handling-supported (1setOf type2 keyword)" - "orientation-requested-default (type2 enum)" and "orientation-requested-supported (1setOf type2 enum)" - "pdl-override-supported (type2 keyword)" with a value of 'attempted'. - "print-color-mode-default (type2 keyword)" and "print-color-mode-supported (1setOf type2 keyword" - "print-content-optimize-default (type2 keyword)" and "print-content-optimize-supported (1setOf type2 keyword)" - "print-darkness-default (integer(-100:100))" and "print-darkness-supported (integer(1:100))": The -supported value specifies the number of discrete darkness values that are actually supported. - "print-quality-default (type2 enum)" and "print-quality-supported (1setOf type2 enum)" - "print-speed-default (integer(1:MAX))" and "print-speed-supported (1setOf (integer(1:MAX) | rangeOfInteger(1:MAX)))" - "printer-darkness-configured (integer(0:100))": The base darkness from 0 (lightest) to 100 (darkest) for thermal markers. - "printer-darkness-supported (integer(1:100))": The number of discrete darkness values that are actually supported. - "printer-resolution-default (resolution)" and "printer-resolution-supported (1setOf resolution)" lprint-1.0/DOCUMENTATION.md000066400000000000000000000263051362261677400152410ustar00rootroot00000000000000LPrint Documentation ==================== LPrint v1.0 - February 17, 2020 Copyright 2019-2020 by Michael R Sweet LPrint is licensed under the Apache License Version 2.0 with an exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS). See the files "LICENSE" and "NOTICE" for more information. Table of Contents ----------------- - [Overview](#overview) - [Installation](#installation) - [Basic Usage](#basic-usage) - [Adding Printers](#adding-printers) - [Printing Options](#printing-options) - [Setting Default Options](#setting-default-options) - [Running a Server](#running-a-server) - [Server Web Interface](#server-web-interface) - [Resources](#resources) Overview -------- LPrint is a label printer application for macOS® and Linux®. I wrote it in response to criticism that coming changes in CUPS will leave users of label printers in the cold - see CUPS Github issue #5271. Basically, LPrint is a print spooler optimized for label printing. It accepts "raw" print data as well as PNG images (like those used for shipping labels by most shippers' current web APIs) and has built-in "drivers" to send the print data to USB and network-connected label printers. The spooler also tries to keep the labels moving by merging jobs over a single connection to the printer rather than starting and stopping like CUPS does to support a wider variety of printers. LPrint supports the full range of options and features supported by the embedded drivers - currently all Dymo and Zebra ZPL label printers. Whenever possible, LPrint will auto-detect the make and model of your printer and its installed capabilities. And you can configure the default values of all options as well as manually configure the media that is loaded in each printer. LPrint also offers a simple network server mode that makes any label printers appear as IPP Everywhere™/AirPrint™ printers on your network. Thus, any macOS, iOS®, or Linux client can use any label printer supported by LPrint. And you can, of course, send jobs from LPrint to an LPrint server on the network. Finally, LPrint offers command-line and web-based monitoring of printer and job status. Installation ------------ LPrint is published as a snap for Linux. Run the following command to install it: sudo snap install lprint A disk image is included with all source releases on Github for use on macOS 10.14 and higher. If you need to install LPrint from source, you'll need a "make" program, a C99 compiler (Clang and GCC work), the CUPS developer files, the PNG library and headers, and the LIBUSB library and headers. Once the prerequisites are installed on your system, use the following commands to install LPrint to "/usr/local/bin": ./configure make sudo make install The "configure" script supports the usual autoconf options - run: ./configure --help to get a list of configuration options. Basic Usage ----------- LPrint uses a single executable to perform all functions. The normal syntax is: lprint SUB-COMMAND [OPTIONS] [FILES] where "SUB-COMMAND" is one of the following: - "add": Add a printer - "cancel": Cancel one or more jobs - "default": Get or set the default printer - "delete": Delete a printer - "devices": List available printers - "drivers": List available drivers - "jobs": List queued jobs - "modify": Modify a printer - "options": Lists the supported options and values - "printers": List added printer queues - "server": Run in server mode - "shutdown": Shutdown a running server - "status": Show server or printer status - "submit": Submit one or more files for printing You can omit the sub-command if you just want to print something, for example: lprint labels.zpl The options vary based on the sub-command, but most commands support "-d" to specify a printer and "-o" to specify a named option with a value, for example: - `lprint -d myprinter labels.zpl`: Print a file to the printer named "myprinter". - `lprint -o media=oe_xl-shipping-label_4x6in label.png`: Print a shipping label image to a 4x6 label. - `lprint default -d myprinter`: Set "myprinter" as the default printer. You can find our more about each sub-command by reading its included man page, for example the following command will explain all of the supported options for the "submit" sub-command: man lprint-submit Adding Printers --------------- The "add" sub-command adds a new printer: lprint add -d PRINTER -v DEVICE-URI -m DRIVER-NAME "PRINTER" is the name you want to give the print queue. Printer names can contain spaces and special characters, but if you do any printing from scripts you probably want to limit yourself to ASCII letters, numbers, and punctuation. "DEVICE-URI" is a "usb:" or "socket:" URI for the printer. For USB-connected label printers, use the "devices" sub-command to discover the URI to use: lprint devices For network-connected printers, print the configuration summary on your label printer to discover its IP address. The device URI will then be "socket://" followed by the IP address. For example, a printer at address 192.168.0.42 will use the device URI "socket://192.168.0.42". Finally, the "DRIVER-NAME" is the name of the internal LPrint driver for the printer. Use the "drivers" sub-command to list the available drivers: lprint drivers For example, the common 4-inch Zebra printer uses the "zpl_4inch-203dpi-dt" driver: lprint add -d myprinter -v socket://192.168.0.42 -m zpl_4inch-203dpi-dt Printing Options ---------------- The following options are supported by the "submit" sub-command: - "-n NNN": Specifies the number of copies to produce. - "-o media=SIZE-NAME": Specifies the media size name using the PWG media size self-describing name (see below). - "-o media-source=ROLL-NAME": Specifies the roll to use such as 'main-roll' or 'alternate-roll'. - "-o media-top-offset=NNNin" or "-o media-top-offset=NNNmm": Specifies a printing offset from the top of the label. - "-o media-type=TYPE-NAME": Specifies a media type name such as 'labels', 'labels-continuous', or 'continuous'. - "-o orientation-requested=none": Prints in portrait or landscape orientation automatically. - "-o orientation-requested=portrait": Prints in portrait orientation. - "-o orientation-requested=landscape": Prints in landscape (90 degrees counter- clockwise) orientation. - "-o orientation-requested=reverse-portrait": Prints in reverse portrait (upside down) orientation. - "-o orientation-requested=reverse-landscape": Prints in reverse landscape (90 degrees clockwise) orientation. - "-o print-color-mode=bi-level": Prints black-and-white output with no shading. - "-o print-color-mode=monochrome": Prints grayscale output with shading as needed. - "-o print-content-optimize=auto": Automatically optimize printing based on content. - "-o print-content-optimize=graphic": Automatically optimize printing for graphics like lines and barcodes. - "-o print-content-optimize=photo": Automatically optimize printing for photos or other shaded images. - "-o print-content-optimize=text": Automatically optimize printing for text. - "-o print-content-optimize=text-and-graphic": Automatically optimize printing for text and graphics. - "-o print-darkness=NNN": Specifies a relative darkness from -100 (lightest) to 100 (darkest). - "-o print-quality=draft": Print using the lowest quality and fastest speed. - "-o print-quality=normal": Print using good quality and speed. - "-o print-quality=high": Print using the best quality and slowest speed. - "-o print-speed=NNNin" or "-o print-speed=NNNmm": Specifies the print speed in inches or millimeters per second. - "-o printer-resolution=NNNdpi": Specifies the print resolution in dots per inch. - "-t TITLE": Specifies the title of the job that appears in the list produced by the "jobs" sub-command. Media sizes use the PWG self-describing name format which looks like this: CLASS_NAME_WIDTHxLENGTHin CLASS_NAME_WIDTHxLENGTHmm "CLASS" is "na" for North American media sizes, "oe" for other cut label sizes in inches, "om" for other cut label sizes in millimeters, or "roll" for continuous roll sizes in inches or millimeters. "NAME" is a string of letters, numbers, dots ("."), and dashes ("-") describing the size. "WIDTH" and "LENGTH" are the width and length of the label or receipt you want to print. The trailing "in" or "mm" specifies the units in inches or millimeters, respectively. For example, a 4x6" shipping label uses the size name `na_4x6-index_4x6in` while a 1.25x3.5" address label uses `oe_address-label_1.25x3.5in` and a 50x200mm receipt uses `roll_receipt_50x200mm`. 2-up labels (where two labels are placed side-by-side) use the combined sizes of both labels. For example, a 2-up 0.5x1" multipurpose label uses the size name `oe_square-multipurpose-label_1x1in`. You can get a list of supported values for these options using the "options" sub-command: lprint options lprint options -d PRINTER Setting Default Options ----------------------- You can set the default values for each option with the "add" or "modify" sub-commands: lprint add -d PRINTER -v DEVICE-URI -m DRIVER-NAME -o OPTION=VALUE ... lprint modify -D PRINTER -o OPTION=VALUE ... In addition, you can configure the installed media and other printer settings using other "-o" options. For example, the following command configures the labels that are installed in a Dymo LabelWriter 450 Twin Turbo printer: lprint modify -d Dymo450TT \ -o media-ready=oe_address-label_1.25x3.5in,oe_shipping-label_2.125x4in Use the "options" sub-command to see which settings are supported for a particular printer. Running a Server ---------------- The "server" sub-command runs a standalone spooler. The following options control the server operation: - "-o server-name=HOSTNAME": Sets the network hostname to advertise. - "-o server-port=NNN": Sets the network port number; the default is randomly assigned. - "-o auth-service=SERVICE": Specifies a PAM service for remote authentication. - "-o admin-group=GROUP": Specifies a group to use for remote authentication. - "-o spool-directory=DIRECTORY": Specifies the directory to store print files. - "-o log-file=FILENAME": Specifies a log file. - "-o log-file=-": Specifies that log entries are written to the standard error. - "-o log-file=syslog": Specifies that log entries are sent to the system log. - "-o log-level=LEVEL": Specifies the log level - "debug", "info", "warn", "error", or "fatal". Server Web Interface -------------------- When you run a standalone spooler on a network hostname, a web interface can be enabled that allows you to add, modify, and delete printers, as well as setting the default printer. Because all web interface operations require authentication, you need to set the PAM authentication service with the `-o auth-service=SERVICE` option. For example, to use the "cups" PAM service with LPrint, run: lprint -o server-name=HOSTNAME -o server-port=NNN -o auth-service=cups By default, any user can authenticate web interface operations. To restrict access to a particular UNIX group, use the `-o admin-group=GROUP` option as well. Resources --------- The following additional resources are available: - LPrint home page: - LPrint Github project: lprint-1.0/LICENSE000066400000000000000000000261351362261677400137140ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. lprint-1.0/Makefile.in000066400000000000000000000115161362261677400147510ustar00rootroot00000000000000# # Makefile for LPrint, a Label Printer Application # # Copyright © 2019-2020 by Michael R Sweet # # Licensed under Apache License v2.0. See the file "LICENSE" for more # information. # # Be silent... .SILENT: # Version number... LPRINT_VERSION = @LPRINT_VERSION@ # Languages we have localized messages for... LANGUAGES = de en es fr it # Programs and options... AR = @AR@ ARFLAGS = @ARFLAGS@ ASAN_OPTIONS = leak_check_at_exit=false CC = @CC@ CFLAGS = -I.. @CFLAGS@ $(OPTIM) CODESIGN_IDENTITY = Developer ID INSTALL = @INSTALL@ LDFLAGS = @LDFLAGS@ $(OPTIM) LIBS = @LIBS@ MKDIR = @MKDIR@ -p OPTIM = @OPTIM@ RANLIB = @RANLIB@ RM = @RM@ -f RMDIR = @RMDIR@ SHELL = /bin/sh # Directories... bindir = @bindir@ datadir = @datadir@ datarootdir = @datarootdir@ exec_prefix = @exec_prefix@ includedir = @includedir@ infodir = @infodir@ libdir = @libdir@ libexecdir = @libexecdir@ localstatedir = @localstatedir@ mandir = @mandir@ oldincludedir = @oldincludedir@ prefix = @prefix@ privateinclude = @privateinclude@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ top_srcdir = @top_srcdir@ BUILDROOT = $(DSTROOT)$(RPM_BUILD_ROOT)$(DESTDIR) # Build commands... .c.o: echo Compiling $<... $(CC) $(CFLAGS) -c -o $@ $< # Targets... MAN1 = \ man/lprint-add.1 \ man/lprint-cancel.1 \ man/lprint-default.1 \ man/lprint-delete.1 \ man/lprint-devices.1 \ man/lprint-drivers.1 \ man/lprint-jobs.1 \ man/lprint-modify.1 \ man/lprint-printers.1 \ man/lprint-server.1 \ man/lprint-shutdown.1 \ man/lprint-status.1 \ man/lprint-submit.1 \ man/lprint.1 MAN5 = \ man/lprint.conf.5 OBJS = \ device.o \ driver-common.o \ driver-dymo.o \ driver-pwg.o \ driver-zpl.o \ lprint.o \ lprint-add.o \ lprint-cancel.o \ lprint-default.o \ lprint-delete.o \ lprint-devices.o \ lprint-drivers.o \ lprint-jobs.o \ lprint-modify.o \ lprint-options.o \ lprint-printers.o \ lprint-server.o \ lprint-shutdown.o \ lprint-status.o \ lprint-submit.o \ server-auth.o \ server-client.o \ server-dnssd.o \ server-ipp.o \ server-job.o \ server-log.o \ server-print.o \ server-printer.o \ server-system.o TARGETS = \ lprint # Make everything... all: $(TARGETS) # Clean everything... clean: $(RM) $(TARGETS) $(OBJS) # Clean everything and generated files distclean: clean $(RM) -r autom4te.cache $(RM) config.h config.log config.status $(RM) Makefile # Install everything... install: all $(INSTALL) -d -m 755 $(BUILDROOT)$(bindir) $(INSTALL) -c -m 755 lprint $(BUILDROOT)$(bindir) $(INSTALL) -d -m 755 $(BUILDROOT)$(mandir)/man1 for file in $(MAN1); do \ $(INSTALL) -c -m 644 $$file $(BUILDROOT)$(mandir)/man1; \ done $(INSTALL) -d -m 755 $(BUILDROOT)$(mandir)/man5 for file in $(MAN5); do \ $(INSTALL) -c -m 644 $$file $(BUILDROOT)$(mandir)/man5; \ done # Test everything... test: $(TARGETS) # LPrint program... lprint: $(OBJS) echo Linking $@... $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) if test `uname` = Darwin; then \ echo Code-signing $@...; \ codesign -s "$(CODESIGN_IDENTITY)" $@; \ fi # Generate resource headers from the corresponding files in the resource # directory... resheaders: echo "Generating lprint-png.h from lprint.png..." echo "static const unsigned char lprint_png[] =" >static-resources/lprint-png.h echo "{" >>static-resources/lprint-png.h od -t x1 -A n -v static-resources/lprint.png | awk '{printf(" "); for (i = 1; i <= NF; i ++) printf("0x%s,", $$i); print "";}' >>static-resources/lprint-png.h echo "};" >>static-resources/lprint-png.h echo "Generating lprint-large-png.h from lprint-large.png..." echo "static const unsigned char lprint_large_png[] =" >static-resources/lprint-large-png.h echo "{" >>static-resources/lprint-large-png.h od -t x1 -A n -v static-resources/lprint-large.png | awk '{printf(" "); for (i = 1; i <= NF; i ++) printf("0x%s,", $$i); print "";}' >>static-resources/lprint-large-png.h echo "};" >>static-resources/lprint-large-png.h for lang in $(LANGUAGES); do \ echo "Generating lprint-$$lang-strings.h from lprint-$$lang.strings..."; \ echo "static const char *lprint_$${lang}_strings =" >static-resources/lprint-$$lang-strings.h; \ sed -e '1,$$s/"/\\"/g' static-resources/lprint-$$lang.strings | awk '{print "\"" $$0 "\\n\""}' >>static-resources/lprint-$$lang-strings.h; \ echo ";" >>static-resources/lprint-$$lang-strings.h; \ done # Dependencies... $(OBJS): common.h config.h device.h driver.h lprint.h Makefile server-client.o: \ static-resources/lprint-png.h \ static-resources/lprint-large-png.h \ static-resources/lprint-de-strings.h \ static-resources/lprint-en-strings.h \ static-resources/lprint-es-strings.h \ static-resources/lprint-fr-strings.h \ static-resources/lprint-it-strings.h server-print.o: dither.h lprint-1.0/NOTICE000066400000000000000000000012531362261677400136050ustar00rootroot00000000000000LPrint Copyright © 2019-2020 by Michael R Sweet Exceptions to the Apache 2.0 License: ===================================== In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 or LGPLv2 (“Combined Software”) and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2 or LGPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. lprint-1.0/README.md000066400000000000000000000052021362261677400141560ustar00rootroot00000000000000LPrint - A Label Printer Application ==================================== LPrint implements printing for a variety of common label and receipt printers connected via network or USB. Features include: - A single executable handles spooling, status, and server functionality. - Multiple printer support. - Each printer implements an IPP Everywhere™ print service and is compatible with the driverless printing support in iOS, macOS, and Linux clients. - Each printer can support options such as label modes, tear-off offsets, media tracking, media top offset, print darkness, resolution, roll selection, and speed. - Each printer can print "raw", Apple/PWG Raster, and/or PNG files. - Each printer automatically recovers from out-of-media, power loss, and disconnected/bad cable issues. For more information, see the file "DOCUMENTATION.md", the man pages in the "man" directory, and/or the LPrint project page at . > Note: Please use the Github issue tracker to report issues or request > features/improvements in LPrint: > > Requirements ------------ LPrint depends on: - A "make" program (both GNU and BSD make are known to work), - A C99 compiler (both Clang and GCC are known to work), - [Avahi](https://www.avahi.org) 0.7 or later or mDNSResponder to provide DNS-SD support, - [CUPS](https://www.cups.org) 2.2.0 or later to provide HTTP, IPP, and Apple/PWG Raster support, - [libpng](https://www.libpng.org) 1.6.0 or later to provide PNG printing support, and - [libusb](https://libusb.info) 1.0 or later to provide USB printing support. Supported Printers ------------------ The following printers are currently supported: - Dymo LabelWriter printers - Zebra ZPL printers Others will be added as time and access to printers permits. Standards --------- LPrint implements PWG 5100.14-2013: IPP Everywhere™ for each printer, and has a partial implementation of PWG 5100.22-2019: IPP System Service v1.0 for managing the print queues and default printer. IPP extensions for label printers have been proposed in the Printer Working Group in the IPP Label Printing Extensions v1.0 document; LPrint will be updated to conform to the final names and values that are approved by the IPP workgroup. Legal Stuff ----------- LPrint is Copyright © 2019-2020 by Michael R Sweet. LPrint is licensed under the Apache License Version 2.0 with an exception to allow linking against GPL2/LGPL2 software (like older versions of CUPS). See the files "LICENSE" and "NOTICE" for more information. LPrint is based loosely on the "ippeveprinter.c" and "rastertolabel.c" code from CUPS. lprint-1.0/common.h000066400000000000000000000035651362261677400143520ustar00rootroot00000000000000// // Common definitions file for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _COMMON_H_ # define _COMMON_H_ // // Include necessary headers... // # include "config.h" # include # include # include # include # include # include // // Debug macro... // # ifdef DEBUG # define LPRINT_DEBUG(...) fprintf(stderr, __VA_ARGS__) # else # define LPRINT_DEBUG(...) # endif // DEBUG // // Function annotations... // # if defined(__GNUC__) || defined(__has_extension) # define LPRINT_FORMAT(a,b) __attribute__ ((__format__(__printf__, a,b))) # define LPRINT_NONNULL(...) __attribute__ ((nonnull(__VA_ARGS__))) # define LPRINT_NORETURN __attribute__ ((noreturn)) # else # define LPRINT_FORMAT(a,b) # define LPRINT_NONNULL(...) # define LPRINT_NORETURN # endif // __GNUC__ || __has_extension // // Emulate safe string functions as needed... // # ifndef __APPLE__ # define strlcat(dst,src,dstsize) lprint_strlcat(dst,src,dstsize) static inline size_t lprint_strlcat(char *dst, const char *src, size_t dstsize) { size_t dstlen, srclen; dstlen = strlen(dst); if (dstsize < (dstlen + 1)) return (dstlen); dstsize -= dstlen + 1; if ((srclen = strlen(src)) > dstsize) srclen = dstsize; memmove(dst + dstlen, src, srclen); dst[dstlen + srclen] = '\0'; return (dstlen = srclen); } # define strlcpy(dst,src,dstsize) lprint_strlcpy(dst,src,dstsize) static inline size_t lprint_strlcpy(char *dst, const char *src, size_t dstsize) { size_t srclen = strlen(src); dstsize --; if (srclen > dstsize) srclen = dstsize; memmove(dst, src, srclen); dst[srclen] = '\0'; return (srclen); } # endif // !__APPLE__ #endif // !_COMMON_H_ lprint-1.0/config.guess000077500000000000000000001313551362261677400152300ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-11-29' # This file 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. # # 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: lprint-1.0/config.h.in000066400000000000000000000011321362261677400147200ustar00rootroot00000000000000// // Configuration header file for LPrint, a Label Printer Utility // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // Version number #define LPRINT_VERSION "" // DNS-SD (mDNSResponder or Avahi) #undef HAVE_DNSSD #undef HAVE_AVAHI // libpng #undef HAVE_LIBPNG // libusb #undef HAVE_LIBUSB // libpam #undef HAVE_LIBPAM #undef HAVE_SECURITY_PAM_APPL_H #undef HAVE_PAM_PAM_APPL_H // Random number support #undef HAVE_SYS_RANDOM_H #undef HAVE_ARC4RANDOM #undef HAVE_GETRANDOM #undef HAVE_GNUTLS_RND lprint-1.0/config.sub000077500000000000000000001054121362261677400146660ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-10-01' # This file 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. # # 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, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: lprint-1.0/configure000077500000000000000000004637131362261677400146250ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for lprint 1.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: https://github.com/michaelrsweet/lprint/issues about $0: your system, including any error possibly output before $0: this message. Then install a modern shell, or manually $0: run the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='lprint' PACKAGE_TARNAME='lprint' PACKAGE_VERSION='1.0' PACKAGE_STRING='lprint 1.0' PACKAGE_BUGREPORT='https://github.com/michaelrsweet/lprint/issues' PACKAGE_URL='https://michaelrsweet.github.io/lprint' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS OPTIM EGREP GREP CPP PKGCONFIG CUPSCONFIG INSTALL ARFLAGS RM MKDIR AR RANLIB OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LPRINT_VERSION target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_static_cups with_dnssd enable_libpng enable_libusb enable_pam enable_debug enable_sanitizer with_ldflags ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures lprint 1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/lprint] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of lprint 1.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-static-cups use static CUPS libraries, default=no --enable-libpng use libpng for PNG printing --enable-libusb use libusb for USB printing --disable-pam disable PAM support --enable-debug turn on debugging, default=no --enable-sanitizer build with AddressSanitizer, default=no Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-dnssd=LIBRARY set DNS-SD library (auto, avahi, mdnsresponder) --with-ldflags=... Specify additional LDFLAGS Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . lprint home page: . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF lprint configure 1.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------------------------------------- ## ## Report this to https://github.com/michaelrsweet/lprint/issues ## ## ------------------------------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by lprint $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" LPRINT_VERSION="1.0" cat >>confdefs.h <<_ACEOF #define LPRINT_VERSION "$LPRINT_VERSION" _ACEOF ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac host_os_name=`echo $host_os | sed -e '1,$s/[0-9.]*$//g'` host_os_version=`echo $host_os | sed -e '1,$s/^[^0-9.]*//g' | awk -F. '{print $1 $2}'` # Linux often does not yield an OS version we can use... if test "x$host_os_version" = x; then host_os_version="0" fi CFLAGS="${CFLAGS:=}" CXXFLAGS="${CXXFLAGS:=}" LDFLAGS="${LDFLAGS:=}" LIBS="${LIBS:=}" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in clang cc gcc do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in clang cc gcc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_AR+:} false; then : $as_echo_n "(cached) " >&6 else case $AR in [\\/]* | ?:[\\/]*) ac_cv_path_AR="$AR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_AR="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi AR=$ac_cv_path_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "mkdir", so it can be a program name with args. set dummy mkdir; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MKDIR+:} false; then : $as_echo_n "(cached) " >&6 else case $MKDIR in [\\/]* | ?:[\\/]*) ac_cv_path_MKDIR="$MKDIR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_MKDIR="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi MKDIR=$ac_cv_path_MKDIR if test -n "$MKDIR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5 $as_echo "$MKDIR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "rm", so it can be a program name with args. set dummy rm; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_RM+:} false; then : $as_echo_n "(cached) " >&6 else case $RM in [\\/]* | ?:[\\/]*) ac_cv_path_RM="$RM" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_RM="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi RM=$ac_cv_path_RM if test -n "$RM"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5 $as_echo "$RM" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$ac_cv_prog_ranlib" = ":"; then ARFLAGS="crs" else ARFLAGS="cr" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for install-sh script" >&5 $as_echo_n "checking for install-sh script... " >&6; } INSTALL="`pwd`/install-sh" { $as_echo "$as_me:${as_lineno-$LINENO}: result: using $INSTALL" >&5 $as_echo "using $INSTALL" >&6; } if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cups-config", so it can be a program name with args. set dummy ${ac_tool_prefix}cups-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_CUPSCONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $CUPSCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_CUPSCONFIG="$CUPSCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_CUPSCONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi CUPSCONFIG=$ac_cv_path_CUPSCONFIG if test -n "$CUPSCONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CUPSCONFIG" >&5 $as_echo "$CUPSCONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_CUPSCONFIG"; then ac_pt_CUPSCONFIG=$CUPSCONFIG # Extract the first word of "cups-config", so it can be a program name with args. set dummy cups-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_CUPSCONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_CUPSCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_CUPSCONFIG="$ac_pt_CUPSCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_CUPSCONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_CUPSCONFIG=$ac_cv_path_ac_pt_CUPSCONFIG if test -n "$ac_pt_CUPSCONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_CUPSCONFIG" >&5 $as_echo "$ac_pt_CUPSCONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_CUPSCONFIG" = x; then CUPSCONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CUPSCONFIG=$ac_pt_CUPSCONFIG fi else CUPSCONFIG="$ac_cv_path_CUPSCONFIG" fi if test "x$CUPSCONFIG" = x; then as_fn_error $? "Sorry, this software requires libcups-dev." "$LINENO" 5 fi case "`$CUPSCONFIG --api-version`" in 1.* | 2.0 | 2.1) as_fn_error $? "Sorry, you need CUPS 2.2.0 or higher." "$LINENO" 5 ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKGCONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKGCONFIG=$ac_cv_path_PKGCONFIG if test -n "$PKGCONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 $as_echo "$PKGCONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKGCONFIG"; then ac_pt_PKGCONFIG=$PKGCONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKGCONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKGCONFIG="$ac_pt_PKGCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKGCONFIG=$ac_cv_path_ac_pt_PKGCONFIG if test -n "$ac_pt_PKGCONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKGCONFIG" >&5 $as_echo "$ac_pt_PKGCONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKGCONFIG" = x; then PKGCONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKGCONFIG=$ac_pt_PKGCONFIG fi else PKGCONFIG="$ac_cv_path_PKGCONFIG" fi # Check whether --enable-static_cups was given. if test "${enable_static_cups+set}" = set; then : enableval=$enable_static_cups; fi if test x$enable_static_cups = xyes; then CFLAGS="$CFLAGS `cups-config --static --cflags`" LDFLAGS="$LDFLAGS `cups-config --static --ldflags`" LIBS="$LIBS `cups-config --image --static --libs`" else CFLAGS="$CFLAGS `cups-config --cflags`" LDFLAGS="$LDFLAGS `cups-config --ldflags`" LIBS="$LIBS `cups-config --image --libs`" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "sys/random.h" "ac_cv_header_sys_random_h" "$ac_includes_default" if test "x$ac_cv_header_sys_random_h" = xyes; then : $as_echo "#define HAVE_SYS_RANDOM_H 1" >>confdefs.h fi for ac_func in arc4random getrandom gnutls_rnd do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : fi if test x$ac_cv_header_pthread_h != xyes; then as_fn_error $? "Sorry, this software requires POSIX threading support." "$LINENO" 5 fi for flag in -lpthreads -lpthread -pthread; do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create using $flag" >&5 $as_echo_n "checking for pthread_create using $flag... " >&6; } SAVELIBS="$LIBS" LIBS="$flag $LIBS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { pthread_create(0, 0, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : have_pthread=yes else LIBS="$SAVELIBS" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x$have_pthread = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$CFLAGS -D_THREAD_SAFE -D_REENTRANT" break else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi done # Check whether --with-dnssd was given. if test "${with_dnssd+set}" = set; then : withval=$with_dnssd; fi if test "x$with_dnssd" != xmdnsresponder -a "x$with_dnssd" != xno -a "x$PKGCONFIG" != x -a x$host_os_name != xdarwin; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Avahi" >&5 $as_echo_n "checking for Avahi... " >&6; } if $PKGCONFIG --exists avahi-client; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$CFLAGS `$PKGCONFIG --cflags avahi-client`" LIBS="$LIBS `$PKGCONFIG --libs avahi-client`" $as_echo "#define HAVE_AVAHI 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test x$with_dnssd = xavahi; then as_fn_error $? "libavahi-client-dev needed for --with-dnssd=avahi." "$LINENO" 5 fi fi elif test x$with_dnssd = xavahi; then as_fn_error $? "pkgconfig and libavahi-client-dev needed for --with-dnssd=avahi." "$LINENO" 5 elif test x$with_dnssd != xavahi -a "x$with_dnssd" != xno; then ac_fn_c_check_header_mongrel "$LINENO" "dns_sd.h" "ac_cv_header_dns_sd_h" "$ac_includes_default" if test "x$ac_cv_header_dns_sd_h" = xyes; then : case "$host_os_name" in darwin*) # Darwin and macOS... $as_echo "#define HAVE_DNSSD 1" >>confdefs.h LIBS="$LIBS -framework CoreFoundation -framework SystemConfiguration" ;; *) # All others... { $as_echo "$as_me:${as_lineno-$LINENO}: checking for current version of dns_sd library" >&5 $as_echo_n "checking for current version of dns_sd library... " >&6; } SAVELIBS="$LIBS" LIBS="$LIBS -ldns_sd" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int constant = kDNSServiceFlagsShareConnection; unsigned char txtRecord[100]; uint8_t valueLen; TXTRecordGetValuePtr(sizeof(txtRecord), txtRecord, "value", &valueLen); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_DNSSD 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } LIBS="$SAVELIBS" if test x$with_dnssd = xmdnsresponder; then as_fn_error $? "mDNSResponder required for --with-dnssd=mdnsresponder." "$LINENO" 5 fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; esac fi fi # Check whether --enable-libpng was given. if test "${enable_libpng+set}" = set; then : enableval=$enable_libpng; fi if test "x$PKGCONFIG" != x -a x$enable_libpng != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libpng-1.6.x" >&5 $as_echo_n "checking for libpng-1.6.x... " >&6; } if $PKGCONFIG --exists libpng16; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; }; $as_echo "#define HAVE_LIBPNG 1" >>confdefs.h CFLAGS="$CFLAGS `$PKGCONFIG --cflags libpng16`" LIBS="$LIBS `$PKGCONFIG --libs libpng16`" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; }; if test x$enable_libpng = xyes; then as_fn_error $? "libpng-dev 1.6 or later required for --enable-libpng." "$LINENO" 5 fi fi elif test x$enable_libpng = xyes; then as_fn_error $? "libpng-dev 1.6 or later required for --enable-libpng." "$LINENO" 5 fi # Check whether --enable-libusb was given. if test "${enable_libusb+set}" = set; then : enableval=$enable_libusb; fi if test "x$PKGCONFIG" != x -a x$enable_libusb != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libusb-1.0" >&5 $as_echo_n "checking for libusb-1.0... " >&6; } if $PKGCONFIG --exists libusb-1.0; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBUSB 1" >>confdefs.h CFLAGS="$CFLAGS `$PKGCONFIG --cflags libusb-1.0`" LIBS="$LIBS `$PKGCONFIG --libs libusb-1.0`" if test "x$host_os_name" = xdarwin; then LIBS="$LIBS -framework IOKit" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test x$enable_libusb = xyes; then as_fn_error $? "libusb-1.0-0-dev required for --enable-libusb." "$LINENO" 5 fi fi elif test x$enable_libusb = xyes; then as_fn_error $? "pkgconfig and libusb-1.0-0-dev required for --enable-libusb." "$LINENO" 5 fi # Check whether --enable-pam was given. if test "${enable_pam+set}" = set; then : enableval=$enable_pam; fi if test x$enable_pam != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBS="-ldl $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_start in -lpam" >&5 $as_echo_n "checking for pam_start in -lpam... " >&6; } if ${ac_cv_lib_pam_pam_start+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpam $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pam_start (); int main () { return pam_start (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pam_pam_start=yes else ac_cv_lib_pam_pam_start=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pam_pam_start" >&5 $as_echo "$ac_cv_lib_pam_pam_start" >&6; } if test "x$ac_cv_lib_pam_pam_start" = xyes; then : $as_echo "#define HAVE_LIBPAM 1" >>confdefs.h LIBS="$LIBS -lpam" fi ac_fn_c_check_header_mongrel "$LINENO" "security/pam_appl.h" "ac_cv_header_security_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_security_pam_appl_h" = xyes; then : $as_echo "#define HAVE_SECURITY_PAM_APPL_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "pam/pam_appl.h" "ac_cv_header_pam_pam_appl_h" "$ac_includes_default" if test "x$ac_cv_header_pam_pam_appl_h" = xyes; then : $as_echo "#define HAVE_PAM_PAM_APPL_H 1" >>confdefs.h fi if test x$ac_pam_start = xno -a x$enable_pam = xyes; then as_fn_error $? "libpam-dev required for --enable-pam." "$LINENO" 5 fi fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; fi # Check whether --enable-sanitizer was given. if test "${enable_sanitizer+set}" = set; then : enableval=$enable_sanitizer; fi if test x$enable_debug = xyes; then OPTIM="-g" else OPTIM="-g -Os" fi if test -n "$GCC"; then if test x$enable_sanitizer = xyes; then # Use -fsanitize=address with debugging... OPTIM="-g -fsanitize=address" else # Otherwise use the Fortify enhancements to catch any unbounded # string operations... CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2" CXXFLAGS="$CXXFLAGS -D_FORTIFY_SOURCE=2" fi CFLAGS="-Wall -Wunused -Wno-unknown-warning-option -Wno-unused-result -Wno-char-subscripts -Wno-format-y2k -Wno-maybe-uninitialized -Wno-switch $CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fPIE" >&5 $as_echo_n "checking whether compiler supports -fPIE... " >&6; } OLDCFLAGS="$CFLAGS" case "$host_os_name" in darwin*) CFLAGS="$CFLAGS -fPIC -fPIE -Wl,-pie" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -Wl,-pie $LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; *) CFLAGS="$CFLAGS -fPIC -fPIE -pie" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -pie $LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; esac CFLAGS="$OLDCFLAGS" fi # Check whether --with-ldflags was given. if test "${with_ldflags+set}" = set; then : withval=$with_ldflags; LDFLAGS="$withval $LDFLAGS" fi ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by lprint $as_me 1.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to . lprint home page: ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ lprint config.status 1.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi lprint-1.0/configure.ac000066400000000000000000000206231362261677400151710ustar00rootroot00000000000000dnl dnl Configuration script for LPrint, a Label Printer Application dnl dnl Copyright © 2019-2020 by Michael R Sweet dnl dnl Licensed under Apache License v2.0. See the file "LICENSE" for more dnl information. dnl dnl We need at least autoconf 2.60... AC_PREREQ(2.60) dnl Package name and version... AC_INIT([lprint], [1.0], [https://github.com/michaelrsweet/lprint/issues], [lprint], [https://michaelrsweet.github.io/lprint]) AC_CONFIG_HEADERS([config.h]) LPRINT_VERSION="AC_PACKAGE_VERSION" AC_SUBST([LPRINT_VERSION]) AC_DEFINE_UNQUOTED([LPRINT_VERSION], "$LPRINT_VERSION", [Version number]) dnl Get the build and host platforms and split the host_os value AC_CANONICAL_BUILD AC_CANONICAL_HOST [host_os_name=`echo $host_os | sed -e '1,$s/[0-9.]*$//g'`] [host_os_version=`echo $host_os | sed -e '1,$s/^[^0-9.]*//g' | awk -F. '{print $1 $2}'`] # Linux often does not yield an OS version we can use... if test "x$host_os_version" = x; then host_os_version="0" fi dnl Compiler options... CFLAGS="${CFLAGS:=}" CXXFLAGS="${CXXFLAGS:=}" LDFLAGS="${LDFLAGS:=}" LIBS="${LIBS:=}" dnl Standard programs... AC_PROG_CC(clang cc gcc) AC_PROG_RANLIB AC_PATH_PROG(AR,ar) AC_PATH_PROG(MKDIR,mkdir) AC_PATH_PROG(RM,rm) dnl Figure out the correct "ar" command flags... if test "$ac_cv_prog_ranlib" = ":"; then ARFLAGS="crs" else ARFLAGS="cr" fi AC_SUBST(ARFLAGS) dnl install-sh AC_MSG_CHECKING([for install-sh script]) INSTALL="`pwd`/install-sh" AC_SUBST(INSTALL) AC_MSG_RESULT([using $INSTALL]) dnl CUPS AC_PATH_TOOL(CUPSCONFIG, cups-config) if test "x$CUPSCONFIG" = x; then AC_MSG_ERROR([Sorry, this software requires libcups-dev.]) fi case "`$CUPSCONFIG --api-version`" in 1.* | 2.0 | 2.1) AC_MSG_ERROR([Sorry, you need CUPS 2.2.0 or higher.]) ;; esac dnl Check for pkg-config, which is used for some other tests later on... AC_PATH_TOOL(PKGCONFIG, pkg-config) dnl CUPS library... AC_ARG_ENABLE(static_cups, [ --enable-static-cups use static CUPS libraries, default=no]) if test x$enable_static_cups = xyes; then CFLAGS="$CFLAGS `cups-config --static --cflags`" LDFLAGS="$LDFLAGS `cups-config --static --ldflags`" LIBS="$LIBS `cups-config --image --static --libs`" else CFLAGS="$CFLAGS `cups-config --cflags`" LDFLAGS="$LDFLAGS `cups-config --ldflags`" LIBS="$LIBS `cups-config --image --libs`" fi dnl Random number support... AC_CHECK_HEADER(sys/random.h, AC_DEFINE([HAVE_SYS_RANDOM_H], 1, [Have header?])) AC_CHECK_FUNCS(arc4random getrandom gnutls_rnd) dnl POSIX threads... AC_CHECK_HEADER(pthread.h) if test x$ac_cv_header_pthread_h != xyes; then AC_MSG_ERROR([Sorry, this software requires POSIX threading support.]) fi for flag in -lpthreads -lpthread -pthread; do AC_MSG_CHECKING([for pthread_create using $flag]) SAVELIBS="$LIBS" LIBS="$flag $LIBS" AC_LANG([C]) AC_LINK_IFELSE([ AC_LANG_PROGRAM([#include ],[pthread_create(0, 0, 0, 0);])], [have_pthread=yes], [LIBS="$SAVELIBS"]) if test x$have_pthread = xyes; then AC_MSG_RESULT([yes]) CFLAGS="$CFLAGS -D_THREAD_SAFE -D_REENTRANT" break else AC_MSG_RESULT([no]) fi done dnl DNS-SD support... AC_ARG_WITH(dnssd, [ --with-dnssd=LIBRARY set DNS-SD library (auto, avahi, mdnsresponder)]) if test "x$with_dnssd" != xmdnsresponder -a "x$with_dnssd" != xno -a "x$PKGCONFIG" != x -a x$host_os_name != xdarwin; then AC_MSG_CHECKING(for Avahi) if $PKGCONFIG --exists avahi-client; then AC_MSG_RESULT([yes]) CFLAGS="$CFLAGS `$PKGCONFIG --cflags avahi-client`" LIBS="$LIBS `$PKGCONFIG --libs avahi-client`" AC_DEFINE([HAVE_AVAHI], 1, [DNS-SD (mDNSResponder or Avahi)]) else AC_MSG_RESULT([no]) if test x$with_dnssd = xavahi; then AC_MSG_ERROR([libavahi-client-dev needed for --with-dnssd=avahi.]) fi fi elif test x$with_dnssd = xavahi; then AC_MSG_ERROR([pkgconfig and libavahi-client-dev needed for --with-dnssd=avahi.]) elif test x$with_dnssd != xavahi -a "x$with_dnssd" != xno; then AC_CHECK_HEADER(dns_sd.h, [ case "$host_os_name" in darwin*) # Darwin and macOS... AC_DEFINE([HAVE_DNSSD], 1, [DNS-SD (mDNSResponder or Avahi)]) LIBS="$LIBS -framework CoreFoundation -framework SystemConfiguration" ;; *) # All others... AC_MSG_CHECKING(for current version of dns_sd library) SAVELIBS="$LIBS" LIBS="$LIBS -ldns_sd" AC_TRY_COMPILE([#include ],[ int constant = kDNSServiceFlagsShareConnection; unsigned char txtRecord[100]; uint8_t valueLen; TXTRecordGetValuePtr(sizeof(txtRecord), txtRecord, "value", &valueLen);],[ AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_DNSSD], 1, [DNS-SD (mDNSResponder or Avahi)])],[ AC_MSG_RESULT([no]) LIBS="$SAVELIBS" if test x$with_dnssd = xmdnsresponder; then AC_MSG_ERROR([mDNSResponder required for --with-dnssd=mdnsresponder.]) fi]) ;; esac ]) fi dnl libpng... AC_ARG_ENABLE(libpng, [ --enable-libpng use libpng for PNG printing]) if test "x$PKGCONFIG" != x -a x$enable_libpng != xno; then AC_MSG_CHECKING([for libpng-1.6.x]) if $PKGCONFIG --exists libpng16; then AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_LIBPNG], 1, [libpng]) CFLAGS="$CFLAGS `$PKGCONFIG --cflags libpng16`" LIBS="$LIBS `$PKGCONFIG --libs libpng16`" else AC_MSG_RESULT([no]); if test x$enable_libpng = xyes; then AC_MSG_ERROR([libpng-dev 1.6 or later required for --enable-libpng.]) fi fi elif test x$enable_libpng = xyes; then AC_MSG_ERROR([libpng-dev 1.6 or later required for --enable-libpng.]) fi dnl libusb... AC_ARG_ENABLE(libusb, [ --enable-libusb use libusb for USB printing]) if test "x$PKGCONFIG" != x -a x$enable_libusb != xno; then AC_MSG_CHECKING([for libusb-1.0]) if $PKGCONFIG --exists libusb-1.0; then AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_LIBUSB], 1, [libusb]) CFLAGS="$CFLAGS `$PKGCONFIG --cflags libusb-1.0`" LIBS="$LIBS `$PKGCONFIG --libs libusb-1.0`" if test "x$host_os_name" = xdarwin; then LIBS="$LIBS -framework IOKit" fi else AC_MSG_RESULT([no]) if test x$enable_libusb = xyes; then AC_MSG_ERROR([libusb-1.0-0-dev required for --enable-libusb.]) fi fi elif test x$enable_libusb = xyes; then AC_MSG_ERROR([pkgconfig and libusb-1.0-0-dev required for --enable-libusb.]) fi dnl PAM support... AC_ARG_ENABLE(pam, [ --disable-pam disable PAM support]) if test x$enable_pam != xno; then dnl PAM needs dlopen... AC_CHECK_LIB([dl], [dlopen]) AC_CHECK_LIB([pam], [pam_start], [ AC_DEFINE([HAVE_LIBPAM], 1, [libpam]) LIBS="$LIBS -lpam"]) dnl PAM has two "standard" locations for its header... AC_CHECK_HEADER(security/pam_appl.h, AC_DEFINE([HAVE_SECURITY_PAM_APPL_H], 1, [Have header?])) AC_CHECK_HEADER(pam/pam_appl.h, AC_DEFINE([HAVE_PAM_PAM_APPL_H], 1, [Have header?])) if test x$ac_pam_start = xno -a x$enable_pam = xyes; then AC_MSG_ERROR([libpam-dev required for --enable-pam.]) fi fi dnl Extra compiler options... AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging, default=no]) AC_ARG_ENABLE(sanitizer, [ --enable-sanitizer build with AddressSanitizer, default=no]) if test x$enable_debug = xyes; then OPTIM="-g" else OPTIM="-g -Os" fi AC_SUBST(OPTIM) if test -n "$GCC"; then if test x$enable_sanitizer = xyes; then # Use -fsanitize=address with debugging... OPTIM="-g -fsanitize=address" else # Otherwise use the Fortify enhancements to catch any unbounded # string operations... CFLAGS="$CFLAGS -D_FORTIFY_SOURCE=2" CXXFLAGS="$CXXFLAGS -D_FORTIFY_SOURCE=2" fi dnl Show all standard warnings + unused variables when compiling... CFLAGS="-Wall -Wunused -Wno-unknown-warning-option -Wno-unused-result -Wno-char-subscripts -Wno-format-y2k -Wno-maybe-uninitialized -Wno-switch $CFLAGS" dnl See if PIE options are supported... AC_MSG_CHECKING(whether compiler supports -fPIE) OLDCFLAGS="$CFLAGS" case "$host_os_name" in darwin*) CFLAGS="$CFLAGS -fPIC -fPIE -Wl,-pie" AC_TRY_COMPILE(,,[ OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -Wl,-pie $LDFLAGS" AC_MSG_RESULT(yes)], AC_MSG_RESULT(no)) ;; *) CFLAGS="$CFLAGS -fPIC -fPIE -pie" AC_TRY_COMPILE(,,[ OLDCFLAGS="-fPIC $OLDCFLAGS" LDFLAGS="-fPIE -pie $LDFLAGS" AC_MSG_RESULT(yes)], AC_MSG_RESULT(no)) ;; esac CFLAGS="$OLDCFLAGS" fi dnl Extra linker options... AC_ARG_WITH(ldflags, [ --with-ldflags=... Specify additional LDFLAGS ], LDFLAGS="$withval $LDFLAGS") dnl Generate the Makefile... AC_OUTPUT(Makefile) lprint-1.0/device.c000066400000000000000000000531541362261677400143130ustar00rootroot00000000000000// // Common device support code for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2007-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include // // Local functions... // static void lprint_error(lprint_deverr_cb_t err_cb, void *err_data, const char *message, ...); #ifdef HAVE_LIBUSB static int lprint_find_usb(lprint_device_cb_t cb, const void *user_data, lprint_device_t *device, lprint_deverr_cb_t err_cb, void *err_data); static int lprint_open_cb(const char *device_uri, const void *user_data); #endif // HAVE_LIBUSB // // 'lprintCloseDevice()' - Close a device connection. // void lprintCloseDevice( lprint_device_t *device) // I - Device to close { if (device) { if (device->debug_fd >= 0) close(device->debug_fd); if (device->fd >= 0) close(device->fd); #ifdef HAVE_LIBUSB else if (device->handle) { libusb_close(device->handle); libusb_unref_device(device->device); } #endif /* HAVE_LIBUSB */ free(device); } } // // 'lprintListDevices()' - List available devices. // void lprintListDevices( lprint_device_cb_t cb, // I - Callback function const void *user_data, // I - User data for callback lprint_deverr_cb_t err_cb, // I - Error callback void *err_data) // I - Data for error callback { #ifdef HAVE_LIBUSB lprint_device_t junk; // Dummy device data lprint_find_usb(cb, user_data, &junk, err_cb, err_data); #endif /* HAVE_LIBUSB */ } // // 'lprintOpenDevice()' - Open a connection to a device. // // Currently only "file:///dev/filename", "socket://address:port", and // "usb://make/model?serial=value" URIs are supported. // lprint_device_t * // O - Device connection or `NULL` lprintOpenDevice( const char *device_uri, // I - Device URI lprint_deverr_cb_t err_cb, // I - Error callback void *err_data) // I - Data for error callback { lprint_device_t *device; // Device structure char scheme[32], // URI scheme userpass[32], // Username/password (not used) host[256], // Host name or make resource[256], // Resource path, if any *options; // Pointer to options, if any int port; // Port number http_uri_status_t status; // URI status if (!device_uri) return (NULL); if ((status = httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource))) < HTTP_URI_STATUS_OK) { lprint_error(err_cb, err_data, "Bad device URI '%s': %s", device_uri, httpURIStatusString(status)); return (NULL); } if ((options = strchr(resource, '?')) != NULL) *options++ = '\0'; if ((device = calloc(1, sizeof(lprint_device_t))) != NULL) { const char *lprint_device_debug = getenv("LPRINT_DEVICE_DEBUG"); if (!strcmp(scheme, "file")) { // Character device file... if ((device->fd = open(resource, O_RDWR | O_EXCL)) < 0) { lprint_error(err_cb, err_data, "Unable to open '%s': %s", resource, strerror(errno)); goto error; } } else if (!strcmp(scheme, "socket")) { // Raw socket (JetDirect or similar) char port_str[32]; // String for port number http_addrlist_t *list; // Address list snprintf(port_str, sizeof(port_str), "%d", port); if ((list = httpAddrGetList(host, AF_UNSPEC, port_str)) == NULL) { lprint_error(err_cb, err_data, "Unable to lookup '%s:%d': %s", host, port, cupsLastErrorString()); goto error; } httpAddrConnect2(list, &device->fd, 30000, NULL); httpAddrFreeList(list); if (device->fd < 0) { lprint_error(err_cb, err_data, "Unable to connect to '%s:%d': %s", host, port, cupsLastErrorString()); goto error; } } #ifdef HAVE_LIBUSB else if (!strcmp(scheme, "usb")) { // USB printer class device device->fd = -1; if (!lprint_find_usb(lprint_open_cb, device_uri, device, err_cb, err_data)) goto error; } #endif // HAVE_LIBUSB else { lprint_error(err_cb, err_data, "Unsupported device URI scheme '%s'.", scheme); goto error; } if (lprint_device_debug) device->debug_fd = open(lprint_device_debug, O_WRONLY | O_CREAT | O_TRUNC, 0666); else device->debug_fd = -1; } return (device); error: free(device); return (NULL); } // // 'lprintPrintfDevice()' - Write a formatted string. // ssize_t // O - Number of characters or -1 on error lprintPrintfDevice( lprint_device_t *device, // I - Device const char *format, // I - Printf-style format string ...) // I - Additional args as needed { va_list ap; // Pointer to additional args char buffer[8192]; // Output buffer va_start(ap, format); vsnprintf(buffer, sizeof(buffer), format, ap); va_end(ap); return (lprintWriteDevice(device, buffer, strlen(buffer))); } // // 'lprintPutsDevice()' - Write a literal string. // ssize_t // O - Number of characters or -1 on error lprintPutsDevice( lprint_device_t *device, // I - Device const char *s) // I - Literal string { return (lprintWriteDevice(device, s, strlen(s))); } // // 'lprintReadDevice()' - Read from a device. // ssize_t // O - Number of bytes read or -1 on error lprintReadDevice( lprint_device_t *device, // I - Device void *buffer, // I - Read buffer size_t bytes) // I - Max bytes to read { if (!device) return (-1); else if (device->fd >= 0) { ssize_t count; // Bytes read this time while ((count = read(device->fd, buffer, bytes)) < 0) if (errno != EINTR && errno != EAGAIN) break; return (count); } #ifdef HAVE_LIBUSB else if (device->handle) { int count; // Bytes that were read if (libusb_bulk_transfer(device->handle, device->read_endp, buffer, (int)bytes, &count, 0) < 0) return (-1); else return (count); } #endif // HAVE_LIBUSB return (-1); } // // 'lprintWriteDevice()' - Write to a device. // ssize_t // O - Number of bytes written or -1 on error lprintWriteDevice( lprint_device_t *device, // I - Device const void *buffer, // I - Write buffer size_t bytes) // I - Number of bytes to write { if (!device) return (-1); if (device->debug_fd >= 0) write(device->debug_fd, buffer, bytes); if (device->fd >= 0) { const char *ptr = (const char *)buffer; // Pointer into buffer ssize_t total = 0, // Total bytes written count; // Bytes written this time while (total < bytes) { if ((count = write(device->fd, ptr, bytes - total)) < 0) { if (errno == EINTR || errno == EAGAIN) continue; return (-1); } total += (size_t)count; ptr += count; } return ((ssize_t)total); } #ifdef HAVE_LIBUSB else if (device->handle) { int count; // Bytes that were written if (libusb_bulk_transfer(device->handle, device->write_endp, (unsigned char *)buffer, (int)bytes, &count, 0) < 0) return (-1); else return (count); } #endif // HAVE_LIBUSB return (-1); } // // 'lprint_error()' - Report an error. // static void lprint_error( lprint_deverr_cb_t err_cb, // I - Error callback void *err_data, // I - Error callback data const char *message, // I - Printf-style message ...) // I - Additional args as needed { va_list ap; // Pointer to additional args char buffer[8192]; // Formatted message if (!err_cb) return; va_start(ap, message); vsnprintf(buffer, sizeof(buffer), message, ap); va_end(ap); (*err_cb)(buffer, err_data); } #ifdef HAVE_LIBUSB // // 'lprint_find_usb()' - Find a USB printer. // static int // O - 1 if found, 0 if not lprint_find_usb( lprint_device_cb_t cb, // I - Callback function const void *user_data, // I - User data pointer lprint_device_t *device, // O - Device info lprint_deverr_cb_t err_cb, // I - Error callback void *err_data) // I - Error callback data { ssize_t err = 0, // Current error i, // Looping var num_udevs; // Number of USB devices libusb_device **udevs; // USB devices /* * Get the list of connected USB devices... */ device->device = NULL; device->handle = NULL; if ((err = libusb_init(NULL)) != 0) { lprint_error(err_cb, err_data, "Unable to initialize USB access: %s", libusb_strerror((enum libusb_error)err)); return (0); } num_udevs = libusb_get_device_list(NULL, &udevs); LPRINT_DEBUG("lprint_find_usb: num_udevs=%d\n", (int)num_udevs); /* * Find the printers and do the callback until we find a match. */ for (i = 0; i < num_udevs; i ++) { libusb_device *udevice = udevs[i]; // Current device char device_id[1024], // Current device ID device_uri[1024]; // Current device URI struct libusb_device_descriptor devdesc; // Current device descriptor struct libusb_config_descriptor *confptr = NULL; // Pointer to current configuration const struct libusb_interface *ifaceptr = NULL; // Pointer to current interface const struct libusb_interface_descriptor *altptr = NULL; // Pointer to current alternate setting const struct libusb_endpoint_descriptor *endpptr = NULL; // Pointer to current endpoint uint8_t conf, // Current configuration iface, // Current interface altset, // Current alternate setting endp, // Current endpoint read_endp, // Current read endpoint write_endp; // Current write endpoint // Ignore devices with no configuration data and anything that is not // a printer... if (libusb_get_device_descriptor(udevice, &devdesc) < 0) { LPRINT_DEBUG("lprint_find_usb: udev%d - no descriptor.\n", (int)i); continue; } LPRINT_DEBUG("lprint_find_usb: udev%d -\n", (int)i); LPRINT_DEBUG("lprint_find_usb: bLength=%d\n", devdesc.bLength); LPRINT_DEBUG("lprint_find_usb: bDescriptorType=%d\n", devdesc.bDescriptorType); LPRINT_DEBUG("lprint_find_usb: bcdUSB=%04x\n", devdesc.bcdUSB); LPRINT_DEBUG("lprint_find_usb: bDeviceClass=%d\n", devdesc.bDeviceClass); LPRINT_DEBUG("lprint_find_usb: bDeviceSubClass=%d\n", devdesc.bDeviceSubClass); LPRINT_DEBUG("lprint_find_usb: bDeviceProtocol=%d\n", devdesc.bDeviceProtocol); LPRINT_DEBUG("lprint_find_usb: bMaxPacketSize0=%d\n", devdesc.bMaxPacketSize0); LPRINT_DEBUG("lprint_find_usb: idVendor=0x%04x\n", devdesc.idVendor); LPRINT_DEBUG("lprint_find_usb: idProduct=0x%04x\n", devdesc.idProduct); LPRINT_DEBUG("lprint_find_usb: bcdDevice=%04x\n", devdesc.bcdDevice); LPRINT_DEBUG("lprint_find_usb: iManufacturer=%d\n", devdesc.iManufacturer); LPRINT_DEBUG("lprint_find_usb: iProduct=%d\n", devdesc.iProduct); LPRINT_DEBUG("lprint_find_usb: iSerialNumber=%d\n", devdesc.iSerialNumber); LPRINT_DEBUG("lprint_find_usb: bNumConfigurations=%d\n", devdesc.bNumConfigurations); if (!devdesc.bNumConfigurations || !devdesc.idVendor || !devdesc.idProduct) continue; if (devdesc.idVendor == 0x05ac) continue; // Skip Apple devices... device->device = udevice; device->handle = NULL; device->conf = -1; device->origconf = -1; device->iface = -1; device->ifacenum = -1; device->altset = -1; device->write_endp = -1; device->read_endp = -1; device->protocol = 0; for (conf = 0; conf < devdesc.bNumConfigurations; conf ++) { if (libusb_get_config_descriptor(udevice, conf, &confptr) < 0) { LPRINT_DEBUG("lprint_find_usb: conf%d - no descriptor\n", conf); continue; } LPRINT_DEBUG("lprint_find_usb: conf%d -\n", conf); LPRINT_DEBUG("lprint_find_usb: bLength=%d\n", confptr->bLength); LPRINT_DEBUG("lprint_find_usb: bDescriptorType=%d\n", confptr->bDescriptorType); LPRINT_DEBUG("lprint_find_usb: wTotalLength=%d\n", confptr->wTotalLength); LPRINT_DEBUG("lprint_find_usb: bNumInterfaces=%d\n", confptr->bNumInterfaces); LPRINT_DEBUG("lprint_find_usb: bConfigurationValue=%d\n", confptr->bConfigurationValue); LPRINT_DEBUG("lprint_find_usb: iConfiguration=%d\n", confptr->iConfiguration); LPRINT_DEBUG("lprint_find_usb: bmAttributes=%d\n", confptr->bmAttributes); LPRINT_DEBUG("lprint_find_usb: MaxPower=%d\n", confptr->MaxPower); LPRINT_DEBUG("lprint_find_usb: interface=%p\n", confptr->interface); LPRINT_DEBUG("lprint_find_usb: extra=%p\n", confptr->extra); LPRINT_DEBUG("lprint_find_usb: extra_length=%d\n", confptr->extra_length); // Some printers offer multiple interfaces... for (iface = 0, ifaceptr = confptr->interface; iface < confptr->bNumInterfaces; iface ++, ifaceptr ++) { if (!ifaceptr->altsetting) { LPRINT_DEBUG("lprint_find_usb: iface%d - no alternate setting\n", iface); continue; } LPRINT_DEBUG("lprint_find_usb: iface%d -\n", iface); LPRINT_DEBUG("lprint_find_usb: num_altsetting=%d\n", ifaceptr->num_altsetting); LPRINT_DEBUG("lprint_find_usb: altsetting=%p\n", ifaceptr->altsetting); for (altset = 0, altptr = ifaceptr->altsetting; (int)altset < ifaceptr->num_altsetting; altset ++, altptr ++) { LPRINT_DEBUG("lprint_find_usb: altset%d - bInterfaceClass=%d, bInterfaceSubClass=%d, bInterfaceProtocol=%d\n", altset, altptr->bInterfaceClass, altptr->bInterfaceSubClass, altptr->bInterfaceProtocol); if (altptr->bInterfaceClass != LIBUSB_CLASS_PRINTER || altptr->bInterfaceSubClass != 1) continue; if (altptr->bInterfaceProtocol != 1 && altptr->bInterfaceProtocol != 2) continue; if (altptr->bInterfaceProtocol < device->protocol) continue; read_endp = 0xff; write_endp = 0xff; for (endp = 0, endpptr = altptr->endpoint; endp < altptr->bNumEndpoints; endp ++, endpptr ++) { if ((endpptr->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK) { if (endpptr->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) read_endp = endp; else write_endp = endp; } } if (write_endp != 0xff) { // Save the best match so far... device->protocol = altptr->bInterfaceProtocol; device->altset = altptr->bAlternateSetting; device->ifacenum = altptr->bInterfaceNumber; device->write_endp = write_endp; if (device->protocol > 1) device->read_endp = read_endp; } } if (device->protocol > 0) { device->conf = conf; device->iface = iface; if (!libusb_open(udevice, &device->handle)) { uint8_t current; // Current configuration // Opened the device, try to set the configuration... if (libusb_control_transfer(device->handle, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE, 8, /* GET_CONFIGURATION */ 0, 0, (unsigned char *)¤t, 1, 5000) < 0) current = 0; if (confptr->bConfigurationValue != current) { // Select the configuration we want... if (libusb_set_configuration(device->handle, confptr->bConfigurationValue) < 0) { libusb_close(device->handle); device->handle = NULL; } } #ifdef __linux if (device->handle) { // Make sure the old, busted usblp kernel driver is not loaded... if (libusb_kernel_driver_active(device->handle, device->iface) == 1) { if ((err = libusb_detach_kernel_driver(device->handle, device->iface)) < 0) { lprint_error(err_cb, err_data, "Unable to detach usblp kernel driver for USB printer %04x:%04x: %s", devdesc.idVendor, devdesc.idProduct, libusb_strerror((enum libusb_error)err)); libusb_close(device->handle); device->handle = NULL; } } } #endif // __linux if (device->handle) { // Claim the interface... if ((err = libusb_claim_interface(device->handle, device->ifacenum)) < 0) { lprint_error(err_cb, err_data, "Unable to claim USB interface: %s", libusb_strerror((enum libusb_error)err)); libusb_close(device->handle); device->handle = NULL; } } if (device->handle && ifaceptr->num_altsetting > 1) { // Set the alternate setting as needed... if ((err = libusb_set_interface_alt_setting(device->handle, device->ifacenum, device->altset)) < 0) { lprint_error(err_cb, err_data, "Unable to set alternate USB interface: %s", libusb_strerror((enum libusb_error)err)); libusb_close(device->handle); device->handle = NULL; } } if (device->handle) { // Get the 1284 Device ID... if ((err = libusb_control_transfer(device->handle, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_INTERFACE, 0, device->conf, (device->iface << 8) | device->altset, (unsigned char *)device_id, sizeof(device_id), 5000)) < 0) { lprint_error(err_cb, err_data, "Unable to get IEEE-1284 device ID: %s", libusb_strerror((enum libusb_error)err)); device_id[0] = '\0'; libusb_close(device->handle); device->handle = NULL; } else { int length = ((device_id[0] & 255) << 8) | (device_id[1] & 255); if (length < 14 || length > sizeof(device_id)) length = ((device_id[1] & 255) << 8) | (device_id[0] & 255); if (length > sizeof(device_id)) length = sizeof(device_id); length -= 2; memmove(device_id, device_id + 2, (size_t)length); device_id[length] = '\0'; LPRINT_DEBUG("lprint_find_usb: device_id=\"%s\"\n", device_id); } } if (device->handle) { // Build the device URI... char *make, // Pointer to make *model, // Pointer to model *serial = NULL, // Pointer to serial number *ptr, // Pointer into device ID temp[256]; // Temporary string for serial # if ((make = strstr(device_id, "MANUFACTURER:")) != NULL) make += 13; else if ((make = strstr(device_id, "MFG:")) != NULL) make += 4; if ((model = strstr(device_id, "MODEL:")) != NULL) model += 6; else if ((model = strstr(device_id, "MDL:")) != NULL) model += 4; if ((serial = strstr(device_id, "SERIALNUMBER:")) != NULL) serial += 12; else if ((serial = strstr(device_id, "SERN:")) != NULL) serial += 5; else if ((serial = strstr(device_id, "SN:")) != NULL) serial += 3; if (serial) { if ((ptr = strchr(serial, ';')) != NULL) *ptr = '\0'; } else { int length = libusb_get_string_descriptor_ascii(device->handle, devdesc.iSerialNumber, (unsigned char *)temp, sizeof(temp) - 1); if (length > 0) { temp[length] = '\0'; serial = temp; } } if (make) { if ((ptr = strchr(make, ';')) != NULL) *ptr = '\0'; } else make = "Unknown"; if (model) { if ((ptr = strchr(model, ';')) != NULL) *ptr = '\0'; } else model = "Unknown"; if (serial) httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "usb", NULL, make, 0, "/%s?serial=%s", model, serial); else httpAssembleURIf(HTTP_URI_CODING_ALL, device_uri, sizeof(device_uri), "usb", NULL, make, 0, "/%s", model); if ((*cb)(device_uri, user_data)) { LPRINT_DEBUG("lprint_find_usb: Found a match.\n"); libusb_ref_device(device->device); if (device->read_endp != -1) device->read_endp = confptr->interface[device->iface].altsetting[device->altset].endpoint[device->read_endp].bEndpointAddress; if (device->write_endp != -1) device->write_endp = confptr->interface[device->iface].altsetting[device->altset].endpoint[device->write_endp].bEndpointAddress; goto match_found; } libusb_close(device->handle); device->handle = NULL; } } } } // iface loop libusb_free_config_descriptor(confptr); } // conf loop } match_found: LPRINT_DEBUG("lprint_find_usb: device->handle=%p\n", device->handle); // Clean up .... if (num_udevs >= 0) libusb_free_device_list(udevs, 1); return (device->handle != NULL); } // // 'lprint_open_cb()' - Look for a matching device URI. // static int // O - 1 on match, 0 otherwise lprint_open_cb(const char *device_uri, // I - This device's URI const void *user_data) // I - URI we are looking for { int match = !strcmp(device_uri, (const char *)user_data); // Does this match? LPRINT_DEBUG("lprint_open_cb(device_uri=\"%s\", user_data=\"%s\") returning %d.\n", device_uri, (char *)user_data, match); return (match); } #endif // HAVE_LIBUSB lprint-1.0/device.h000066400000000000000000000036651362261677400143220ustar00rootroot00000000000000// // Device communication functions for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _DEVICE_COMMON_H_ # define _DEVICE_COMMON_H_ // // Include necessary headers... // # include "common.h" # ifdef HAVE_LIBUSB # include # endif // HAVE_LIBUSB // // Types... // typedef struct lprint_device_s // Device connection data { int fd; // File descriptor connection to device int debug_fd; // Debugging copy of data sent #ifdef HAVE_LIBUSB struct libusb_device *device; // Device info struct libusb_device_handle *handle; // Open handle to device int conf, // Configuration origconf, // Original configuration iface, // Interface ifacenum, // Interface number altset, // Alternate setting write_endp, // Write endpoint read_endp, // Read endpoint protocol; // Protocol: 1 = Uni-di, 2 = Bi-di. #endif // HAVE_LIBUSB } lprint_device_t; // Device callback - return 1 to stop, 0 to continue typedef int (*lprint_device_cb_t)(const char *device_uri, const void *user_data); // Device error callback typedef void (*lprint_deverr_cb_t)(const char *message, void *err_data); // // Functions... // extern void lprintCloseDevice(lprint_device_t *device); extern void lprintListDevices(lprint_device_cb_t cb, const void *user_data, lprint_deverr_cb_t err_cb, void *err_data); extern lprint_device_t *lprintOpenDevice(const char *device_uri, lprint_deverr_cb_t err_cb, void *err_data); extern ssize_t lprintPrintfDevice(lprint_device_t *device, const char *format, ...) LPRINT_FORMAT(2, 3); extern ssize_t lprintPutsDevice(lprint_device_t *device, const char *s); extern ssize_t lprintReadDevice(lprint_device_t *device, void *buffer, size_t bytes); extern ssize_t lprintWriteDevice(lprint_device_t *device, const void *buffer, size_t bytes); #endif // !_DEVICE_COMMON_H_ lprint-1.0/dither.h000066400000000000000000000063071362261677400143360ustar00rootroot00000000000000// // Dither matrices for LPrint, a Label Printer Application // // Copyright © 2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _DITHER_H_ # define _DITHER_H_ // // Include necessary headers... // # include "driver.h" // // Dither matrices... // static const lprint_dither_t ditherc[16] = { // Clustered-Dot Dither Matrix { 96, 40, 48, 104, 140, 188, 196, 148, 97, 41, 49, 105, 141, 189, 197, 149 }, { 32, 0, 8, 56, 180, 236, 244, 204, 33, 1, 9, 57, 181, 237, 245, 205 }, { 88, 24, 16, 64, 172, 228, 252, 212, 89, 25, 17, 65, 173, 229, 253, 213 }, { 120, 80, 72, 112, 132, 164, 220, 156, 121, 81, 73, 113, 133, 165, 221, 157 }, { 136, 184, 192, 144, 100, 44, 52, 108, 137, 185, 193, 145, 101, 45, 53, 109 }, { 176, 232, 240, 200, 36, 4, 12, 60, 177, 233, 241, 201, 37, 5, 13, 61 }, { 168, 224, 248, 208, 92, 28, 20, 68, 169, 225, 249, 209, 93, 29, 21, 69 }, { 128, 160, 216, 152, 124, 84, 76, 116, 129, 161, 217, 153, 125, 85, 77, 117 }, { 98, 42, 50, 106, 142, 190, 198, 150, 99, 43, 51, 107, 143, 191, 199, 151 }, { 34, 2, 10, 58, 182, 238, 246, 206, 35, 3, 11, 59, 183, 239, 247, 207 }, { 90, 26, 18, 66, 174, 230, 254, 214, 91, 27, 19, 67, 175, 231, 254, 215 }, { 122, 82, 74, 114, 134, 166, 222, 158, 123, 83, 75, 115, 135, 167, 223, 159 }, { 138, 186, 194, 146, 102, 46, 54, 110, 139, 187, 195, 147, 103, 47, 55, 111 }, { 178, 234, 242, 202, 38, 6, 14, 62, 179, 235, 243, 203, 39, 7, 15, 63 }, { 170, 226, 250, 210, 94, 30, 22, 70, 171, 227, 251, 211, 95, 31, 23, 71 }, { 130, 162, 218, 154, 126, 86, 78, 118, 131, 163, 219, 155, 127, 87, 79, 119 } }; static const lprint_dither_t dithert[16] = { // Threshold Dither Matrix { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }, { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 } }; #endif // !_DITHER_H_ lprint-1.0/driver-common.c000066400000000000000000000461351362261677400156360ustar00rootroot00000000000000// // Common driver code for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include // // Local functions... // static void lprint_copy_media(lprint_driver_t *driver); static ipp_t *lprint_create_media_size(const char *size_name); // // Local globals... // // Note: lprint_drivers and lprint_models need to be kept in sync static const char * const lprint_drivers[] = { // Driver keywords "dymo_lm-400", "dymo_lm-450", "dymo_lm-pc", "dymo_lm-pc-ii", "dymo_lm-pnp", "dymo_lp-350", "dymo_lw-300", "dymo_lw-310", "dymo_lw-315", "dymo_lw-320", "dymo_lw-330-turbo", "dymo_lw-330", "dymo_lw-400-turbo", "dymo_lw-400", "dymo_lw-450-duo-label", "dymo_lw-450-duo-tape", "dymo_lw-450-turbo", "dymo_lw-450-twin-turbo", "dymo_lw-450", "dymo_lw-4xl", "dymo_lw-duo-label", "dymo_lw-duo-tape", "dymo_lw-duo-tape-128", "dymo_lw-se450", "dymo_lw-wireless", "pwg_2inch", "pwg_4inch", "zpl_2inch-203dpi-dt", "zpl_2inch-203dpi-tt", "zpl_2inch-300dpi-dt", "zpl_2inch-300dpi-tt", "zpl_4inch-203dpi-dt", "zpl_4inch-203dpi-tt", "zpl_4inch-300dpi-dt", "zpl_4inch-300dpi-tt" }; static const char * const lprint_models[] = { // Make and model strings "Dymo LabelMANAGER 400", "Dymo LabelMANAGER 450", "Dymo LabelMANAGER PC", "Dymo LabelMANAGER PC II", "Dymo LabelMANAGER PNP", "Dymo LabelPOINT 350", "Dymo LabelWriter 300", "Dymo LabelWriter 310", "Dymo LabelWriter 315", "Dymo LabelWriter 320", "Dymo LabelWriter 330 Turbo", "Dymo LabelWriter 330", "Dymo LabelWriter 400 Turbo", "Dymo LabelWriter 400", "Dymo LabelWriter 450 DUO Label", "Dymo LabelWriter 450 DUO Tape", "Dymo LabelWriter 450 Turbo", "Dymo LabelWriter 450 Twin Turbo", "Dymo LabelWriter 450", "Dymo LabelWriter 4XL", "Dymo LabelWriter DUO Label", "Dymo LabelWriter DUO Tape", "Dymo LabelWriter DUO Tape 128", "Dymo LabelWriter SE450", "Dymo LabelWriter Wireless", "PWG Raster 2-inch Test Printer", "PWG Raster 4-inch Test Printer", "Zebra ZPL 2-inch/203dpi/Direct-Thermal", "Zebra ZPL 2-inch/203dpi/Thermal-Transfer", "Zebra ZPL 2-inch/300dpi/Direct-Thermal", "Zebra ZPL 2-inch/300dpi/Thermal-Transfer", "Zebra ZPL 4-inch/203dpi/Direct-Thermal", "Zebra ZPL 4-inch/203dpi/Thermal-Transfer", "Zebra ZPL 4-inch/300dpi/Direct-Thermal", "Zebra ZPL 4-inch/300dpi/Thermal-Transfer" }; // // 'lprintCreateDriver()' - Create a driver for a printer. // lprint_driver_t * // O - New driver structure lprintCreateDriver( const char *driver_name) // I - Driver name { int i; // Looping vars lprint_driver_t *driver = NULL; // New driver for (i = 0; i < (int)(sizeof(lprint_drivers) / sizeof(lprint_drivers[0])); i ++) { if (!strcmp(driver_name, lprint_drivers[i])) { if ((driver = calloc(1, sizeof(lprint_driver_t))) != NULL) { // Initialize the driver structure... driver->name = strdup(driver_name); driver->attrs = ippNew(); driver->format = "application/octet-stream"; if (!strncmp(driver_name, "dymo_", 5)) lprintInitDYMO(driver); else if (!strncmp(driver_name, "pwg_", 4)) lprintInitPWG(driver); else lprintInitZPL(driver); // label-mode-supported if (driver->mode_supported) { lprint_label_mode_t mode; // Current mode int num_values = 0; // Number of values const char *values[20]; // Keyword values for (mode = LPRINT_LABEL_MODE_APPLICATOR; mode <= LPRINT_LABEL_MODE_TEAR_OFF; mode *= 2) { if (driver->mode_supported & mode) values[num_values ++] = lprintLabelModeString(mode); } ippAddStrings(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "label-mode-supported", num_values, NULL, values); } // label-tear-offset-supported if (driver->tear_offset_supported[0] || driver->tear_offset_supported[1]) ippAddRange(driver->attrs, IPP_TAG_PRINTER, "label-tear-offset-supported", driver->tear_offset_supported[0], driver->tear_offset_supported[1]); // media-xxx lprint_copy_media(driver); // print-darkness-supported if (driver->darkness_supported) ippAddInteger(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "print-darkness-supported", 2 * driver->darkness_supported); // print-speed-supported if (driver->speed_supported[1]) ippAddRange(driver->attrs, IPP_TAG_PRINTER, "print-speed-supported", driver->speed_supported[0], driver->speed_supported[1]); // printer-darkness-supported if (driver->darkness_supported) ippAddInteger(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-darkness-supported", driver->darkness_supported); // printer-make-and-model ippAddString(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, lprint_models[i]); // printer-resolution-supported, -default if (driver->num_resolution > 0) ippAddResolutions(driver->attrs, IPP_TAG_PRINTER, "printer-resolution-supported", driver->num_resolution, IPP_RES_PER_INCH, driver->x_resolution, driver->y_resolution); // pwg-raster-document-resolution-supported if (driver->num_resolution > 0) ippAddResolutions(driver->attrs, IPP_TAG_PRINTER, "pwg-raster-document-resolution-supported", driver->num_resolution, IPP_RES_PER_INCH, driver->x_resolution, driver->y_resolution); // urf-supported if (driver->num_resolution > 0) { const char *values[3]; // urf-supported values char rs[32]; // RS value if (driver->num_resolution == 1) snprintf(rs, sizeof(rs), "RS%d", driver->x_resolution[0]); else snprintf(rs, sizeof(rs), "RS%d-%d", driver->x_resolution[driver->num_resolution - 2], driver->x_resolution[driver->num_resolution - 1]); values[0] = "V1.4"; values[1] = "W8"; values[2] = rs; ippAddStrings(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "urf-supported", 3, NULL, values); } break; } } } return (driver); } // // 'lprintCreateMediaCol()' - Create a media-col collection. // ipp_t * // O - Collection value lprintCreateMediaCol( lprint_media_col_t *media, // I - Media values int db) // I - 1 for media-col-database, 0 otherwise { ipp_t *col = ippNew(), // Collection value *size = lprint_create_media_size(media->size_name); // media-size value ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-bottom-margin", media->bottom_margin); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-left-margin", media->left_margin); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-right-margin", media->right_margin); ippAddCollection(col, IPP_TAG_ZERO, "media-size", size); ippDelete(size); ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-size-name", NULL, media->size_name); if (media->source[0]) ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-source", NULL, media->source); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-top-margin", media->top_margin); if (!db) ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-top-offset", media->top_offset); if (media->tracking) ippAddString(col, IPP_TAG_ZERO, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-tracking", NULL, lprintMediaTrackingString(media->tracking)); if (media->type[0]) ippAddString(col, IPP_TAG_ZERO, IPP_TAG_KEYWORD, "media-type", NULL, media->type); return (col); } // // 'lprintDeleteDriver()' - Delete a driver for a printer. // void lprintDeleteDriver( lprint_driver_t *driver) // I - Driver { if (driver) { free(driver->name); ippDelete(driver->attrs); lprintCloseDevice(driver->device); free(driver); } } // // 'lprintGetDrivers()' - Get the list of supported drivers. // const char * const * // O - Driver keywords lprintGetDrivers(int *num_drivers) // O - Number of drivers { assert(sizeof(lprint_drivers) == sizeof(lprint_models)); *num_drivers = (int)(sizeof(lprint_drivers) / sizeof(lprint_drivers[0])); return (lprint_drivers); } // // 'lprintGetMakeAndModel()' - Get the make and model string for a driver. // const char * // O - Make and model string lprintGetMakeAndModel( const char *driver_name) // I - Driver name { int i; // Looping var if (driver_name) { for (i = 0; i < (int)(sizeof(lprint_drivers) / sizeof(lprint_drivers[0])); i ++) { if (!strcmp(lprint_drivers[i], driver_name)) return (lprint_models[i]); } } return (NULL); } // // 'lprintImportMediaCol()' - Import a media-col-xxx value. // void lprintImportMediaCol( ipp_t *col, // I - Collection lprint_media_col_t *media) // O - Media values { ipp_attribute_t *size_name = ippFindAttribute(col, "media-size-name", IPP_TAG_ZERO), *x_dimension = ippFindAttribute(col, "media-size/x-dimension", IPP_TAG_INTEGER), *y_dimension = ippFindAttribute(col, "media-size/y-dimension", IPP_TAG_INTEGER), *bottom_margin = ippFindAttribute(col, "media-bottom-margin", IPP_TAG_INTEGER), *left_margin = ippFindAttribute(col, "media-left-margin", IPP_TAG_INTEGER), *right_margin = ippFindAttribute(col, "media-right-margin", IPP_TAG_INTEGER), *source = ippFindAttribute(col, "media-source", IPP_TAG_ZERO), *top_margin = ippFindAttribute(col, "media-top-margin", IPP_TAG_INTEGER), *top_offset = ippFindAttribute(col, "media-top-offset", IPP_TAG_INTEGER), *tracking = ippFindAttribute(col, "media-tracking", IPP_TAG_ZERO), *type = ippFindAttribute(col, "media-type", IPP_TAG_ZERO); if (size_name) { const char *pwg_name = ippGetString(size_name, 0, NULL); pwg_media_t *pwg_media = pwgMediaForPWG(pwg_name); strlcpy(media->size_name, pwg_name, sizeof(media->size_name)); media->size_width = pwg_media->width; media->size_length = pwg_media->length; } else if (x_dimension && y_dimension) { pwg_media_t *pwg_media = pwgMediaForSize(ippGetInteger(x_dimension, 0), ippGetInteger(y_dimension, 0)); strlcpy(media->size_name, pwg_media->pwg, sizeof(media->size_name)); media->size_width = pwg_media->width; media->size_length = pwg_media->length; } if (bottom_margin) media->bottom_margin = ippGetInteger(top_offset, 0); if (left_margin) media->left_margin = ippGetInteger(top_offset, 0); if (right_margin) media->right_margin = ippGetInteger(top_offset, 0); if (source) strlcpy(media->source, ippGetString(source, 0, NULL), sizeof(media->source)); if (top_margin) media->top_margin = ippGetInteger(top_offset, 0); if (top_offset) media->top_offset = ippGetInteger(top_offset, 0); if (tracking) media->tracking = lprintMediaTrackingValue(ippGetString(tracking, 0, NULL)); if (type) strlcpy(media->type, ippGetString(type, 0, NULL), sizeof(media->type)); } // // 'lprintLabelModeString()' - Return the string associated with a label mode bit value. // const char * // O - String lprintLabelModeString( lprint_label_mode_t v) // I - Bit value { switch (v) { case LPRINT_LABEL_MODE_APPLICATOR : return ("applicator"); case LPRINT_LABEL_MODE_CUTTER : return ("cutter"); case LPRINT_LABEL_MODE_CUTTER_DELAYED : return ("cutter-delayed"); case LPRINT_LABEL_MODE_KIOSK : return ("kiosk"); case LPRINT_LABEL_MODE_PEEL_OFF : return ("peel-off"); case LPRINT_LABEL_MODE_PEEL_OFF_PREPEEL : return ("peel-off-prepeel"); case LPRINT_LABEL_MODE_REWIND : return ("rewind"); case LPRINT_LABEL_MODE_RFID : return ("rfid"); case LPRINT_LABEL_MODE_TEAR_OFF : return ("tear-off"); default : return ("unknown"); } } // // 'lprintLabelModeValue()' - Return the bit value associated with a string. // lprint_label_mode_t // O - Bit value lprintLabelModeValue(const char *s) // I - String { if (!strcmp(s, "applicator")) return (LPRINT_LABEL_MODE_APPLICATOR); else if (!strcmp(s, "cutter")) return (LPRINT_LABEL_MODE_CUTTER); else if (!strcmp(s, "cutter-delayed")) return (LPRINT_LABEL_MODE_CUTTER_DELAYED); else if (!strcmp(s, "kiosk")) return (LPRINT_LABEL_MODE_KIOSK); else if (!strcmp(s, "peel-off")) return (LPRINT_LABEL_MODE_PEEL_OFF); else if (!strcmp(s, "peel-off-prepeel")) return (LPRINT_LABEL_MODE_PEEL_OFF_PREPEEL); else if (!strcmp(s, "rewind")) return (LPRINT_LABEL_MODE_REWIND); else if (!strcmp(s, "rfid")) return (LPRINT_LABEL_MODE_RFID); else if (!strcmp(s, "tear-off")) return (LPRINT_LABEL_MODE_TEAR_OFF); else return (0); } // // 'lprintMediaTrackingString()' - Return the string associated with a bit value. // const char * // O - String lprintMediaTrackingString( lprint_media_tracking_t v) // I - Bit value { if (v == LPRINT_MEDIA_TRACKING_CONTINUOUS) return ("continuous"); else if (v == LPRINT_MEDIA_TRACKING_MARK) return ("mark"); else if (v == LPRINT_MEDIA_TRACKING_WEB) return ("web"); else return ("unknown"); } // // 'lprintMediaTrackingValue()' - Return the bit value associated with a string. // lprint_media_tracking_t // O - Bit value lprintMediaTrackingValue(const char *s) // I - String { if (!strcmp(s, "continuous")) return (LPRINT_MEDIA_TRACKING_CONTINUOUS); else if (!strcmp(s, "mark")) return (LPRINT_MEDIA_TRACKING_MARK); else if (!strcmp(s, "web")) return (LPRINT_MEDIA_TRACKING_WEB); else return (0); } // // 'lprint_copy_media()' - Copy media capability attributes. // static void lprint_copy_media( lprint_driver_t *driver) // I - Driver { int i, // Looping var count; // Number of values ipp_attribute_t *attr; // Current attribute ipp_t *col; // Media collection value lprint_media_col_t media; // Media values const char *max_name = NULL,// Maximum size *min_name = NULL;// Minimum size // media-bottom-margin-supported ippAddInteger(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin-supported", driver->bottom_top); // media-col-database for (i = 0, count = 0; i < driver->num_media; i ++) { if (!strncmp(driver->media[i], "roll_max_", 9)) max_name = driver->media[i]; else if (!strncmp(driver->media[i], "roll_min_", 9)) min_name = driver->media[i]; else count ++; } if (max_name && min_name) count ++; attr = ippAddCollections(driver->attrs, IPP_TAG_PRINTER, "media-col-database", count, NULL); memset(&media, 0, sizeof(media)); media.bottom_margin = driver->bottom_top; media.left_margin = driver->left_right; media.right_margin = driver->left_right; media.top_margin = driver->bottom_top; for (i = 0, count = 0; i < driver->num_media; i ++) { // Skip custom size ranges... if (driver->media[i] == max_name || driver->media[i] == min_name) continue; // Add the fixed size... strlcpy(media.size_name, driver->media[i], sizeof(media.size_name)); col = lprintCreateMediaCol(&media, 1); ippSetCollection(driver->attrs, &attr, count, col); ippDelete(col); count ++; } if (max_name && min_name) { ipp_t *size = ippNew(); pwg_media_t *max_pwg = pwgMediaForPWG(max_name), // Maximum size *min_pwg = pwgMediaForPWG(min_name); // Minimum size ippAddRange(size, IPP_TAG_ZERO, "x-dimension", min_pwg->width, max_pwg->width); ippAddRange(size, IPP_TAG_ZERO, "y-dimension", min_pwg->length, max_pwg->length); col = ippNew(); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-bottom-margin", media.bottom_margin); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-left-margin", media.left_margin); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-right-margin", media.right_margin); ippAddCollection(col, IPP_TAG_ZERO, "media-size", size); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "media-top-margin", media.top_margin); ippDelete(size); ippSetCollection(driver->attrs, &attr, count, col); ippDelete(col); } // media-left-margin-supported ippAddInteger(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin-supported", driver->left_right); // media-right-margin-supported ippAddInteger(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin-supported", driver->left_right); // media-size-supported for (i = 0, count = 0; i < driver->num_media; i ++) { if (driver->media[i] != max_name && driver->media[i] != min_name) count ++; } if (max_name && min_name) count ++; attr = ippAddCollections(driver->attrs, IPP_TAG_PRINTER, "media-size-supported", count, NULL); for (i = 0, count = 0; i < driver->num_media; i ++) { if (driver->media[i] == max_name || driver->media[i] == min_name) continue; // Add the fixed size... col = lprint_create_media_size(driver->media[i]); ippSetCollection(driver->attrs, &attr, count, col); ippDelete(col); count ++; } if (max_name && min_name) { ipp_t *size = ippNew(); pwg_media_t *max_pwg = pwgMediaForPWG(max_name), // Maximum size *min_pwg = pwgMediaForPWG(min_name); // Minimum size ippAddRange(size, IPP_TAG_ZERO, "x-dimension", min_pwg->width, max_pwg->width); ippAddRange(size, IPP_TAG_ZERO, "y-dimension", min_pwg->length, max_pwg->length); ippSetCollection(driver->attrs, &attr, count, size); ippDelete(size); } // media-source-supported if (driver->num_source) ippAddStrings(driver->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-source-supported", driver->num_source, NULL, driver->source); // media-supported ippAddStrings(driver->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-supported", driver->num_media, NULL, driver->media); // media-top-margin-supported ippAddInteger(driver->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-top-margin-supported", driver->bottom_top); // media-top-offset-supported if (driver->top_offset_supported[0] || driver->top_offset_supported[1]) ippAddRange(driver->attrs, IPP_TAG_PRINTER, "media-top-offset-supported", driver->top_offset_supported[0], driver->top_offset_supported[1]); // media-tracking-supported if (driver->tracking_supported) { const char *values[3]; // media-tracking values for (count = 0, i = LPRINT_MEDIA_TRACKING_CONTINUOUS; i <= LPRINT_MEDIA_TRACKING_WEB; i *= 2) { if (driver->tracking_supported & i) values[count++] = lprintMediaTrackingString(i); } ippAddStrings(driver->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-tracking-supported", count, NULL, values); } // media-type-supported if (driver->num_type) ippAddStrings(driver->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-type-supported", driver->num_type, NULL, driver->type); } // // 'lprint_create_media_size()' - Create a media-size collection. // static ipp_t * // O - Collection value lprint_create_media_size( const char *size_name) // I - Media size name { ipp_t *col = ippNew(); // Collection value pwg_media_t *pwg = pwgMediaForPWG(size_name); // Size information ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", pwg->width); ippAddInteger(col, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", pwg->length); return (col); } lprint-1.0/driver-cpcl.c000066400000000000000000000066031362261677400152630ustar00rootroot00000000000000// // UNIMPLEMENTED CPCL driver for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local globals... // static const char * const lprint_cpcl_media[] = { // Supported media sizes "oe_1.25x0.25-label_1.25x0.25in", "oe_1.25x2.25-label_1.25x2.25in", "oe_1.5x0.25-label_1.5x0.25in", "oe_1.5x0.5-label_1.5x0.5in", "oe_1.5x1-label_1.5x1in", "oe_1.5x2-label_1.5x2in", "oe_2x0.37-label_2x0.37in", "oe_2x0.5-label_2x0.5in", "oe_2x1-label_2x1in", "oe_2x1.25-label_2x1.25in", "oe_2x2-label_2x2in", "oe_2x3-label_2x3in", "oe_2x4-label_2x4in", "oe_2x5.5-label_2x5.5in", "oe_2.25x0.5-label_2.25xin", "oe_2.25x1.25-label_2.25xin", "oe_30859-paint-can-label_2.25x3.125in", "oe_2.25x4-label_2.25x4in", "oe_2.25x5.5-label_2.25x5.5in", "oe_2.38x5.5-label_2.38x5.5in", "oe_2.5x1-label_2.5x1in", "oe_2.5x2-label_2.5x2in", "oe_2.75x1.25-label_2.75x1.25in", "oe_2.9x1-label_2.9x1in", "oe_3x1-label_3x1in", "oe_3x1.25-label_3x1.25in", "oe_3x2-label_3x2in", "oe_3x3-label_3x3in", "oe_3x5-label_3x5in", "oe_3.25x2-label_3.25x2in", "oe_3.25x5-label_3.25x5in", "oe_3.25x5.5-label_3.25x5.5in", "oe_3.25x5.83-label_3.25x5.83in", "oe_3.25x7.83-label_3.25x7.83in", "oe_3.5x1-label_3.5x1in", "oe_4x1-label_4x1in", "oe_4x2-label_4x2in", "oe_4x3-label_4x3in", "oe_4x4-label_4x4in", "oe_4x5-label_4x5in", "oe_4x6-label_4x6in", "oe_4x6.5-label_4x6.5in", "oe_4x13-label_4x13in", "oe_6x1-label_6x1in", "oe_6x2-label_6x2in", "oe_6x3-label_6x3in", "oe_6x4-label_6x4in", "oe_6x5-label_6x5in", "oe_6x6-label_6x6in", "oe_6x6.5-label_6x6.5in", "oe_6x13-label_6x13in", "oe_8x1-label_8x1in", "oe_8x2-label_8x2in", "oe_8x3-label_8x3in", "oe_8x4-label_8x4in", "oe_8x5-label_8x5in", "oe_8x6-label_8x6in", "oe_8x6.5-label_8x6.5in", "oe_8x13-label_8x13in", "roll_max_8x100in", "roll_min_1.25x0.25in" }; // // Local functions... // static int lprint_cpcl_print(lprint_printer_t *printer, lprint_job_t *job); static int lprint_cpcl_status(lprint_printer_t *printer); // // 'lprintInit()' - Initialize the driver. // void lprintInitCPCL( lprint_driver_t *driver) // I - Driver { pthread_rwlock_wrlock(&driver->rwlock); driver->printfunc = lprint_cpcl_print; driver->statusfunc = lprint_cpcl_status; driver->format = "application/vnd.-"; driver->num_resolution = 1; driver->x_resolution[0] = 203; driver->y_resolution[0] = 203; driver->num_media = (int)(sizeof(lprint_cpcl_media) / sizeof(lprint_cpcl_media[0])); memcpy(driver->media, lprint_cpcl_media, sizeof(lprint_cpcl_media)); driver->num_source = 1; driver->source[0] = "main-roll"; driver->num_type = 1; driver->type[0] = "labels"; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } // // 'lprint_cpcl_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_cpcl_print( lprint_printer_t *printer, // I - Printer lprint_job_t *job) // I - Job { (void)printer; (void)job; return (1); } // // 'lprint_cpcl_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_cpcl_status( lprint_printer_t *printer) // I - Printer { (void)printer; return (1); } lprint-1.0/driver-dymo.c000066400000000000000000000272711362261677400153160ustar00rootroot00000000000000// // Dymo driver for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2007-2019 by Apple Inc. // Copyright © 2001-2007 by Easy Software Products. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local types... // typedef struct lprint_dymo_s // DYMO driver data { unsigned ystart, // First line yend; // Last line int feed; // Accumulated feed } lprint_dymo_t; // // Local globals... // static const char * const lprint_dymo_media[] = { // Supported media sizes "oe_thin-multipurpose-label_0.375x2.8125in", "oe_library-barcode-label_0.5x1.875in", "oe_hanging-file-tab-insert_0.5625x2in", "oe_file-folder-label_0.5625x3.4375in", "oe_return-address-label_0.75x2in", "oe_barcode-label_0.75x2.5in", "oe_video-spine-label_0.75x5.875in", "oe_price-tag-label_0.9375x0.875in", "oe_square-multipurpose-label_1x1in", "oe_book-spine-label_1x1.5in", "oe_sm-multipurpose-label_1x2.125in", "oe_2-up-file-folder-label_1.125x3.4375in", "oe_internet-postage-label_1.25x1.625in", "oe_address-label_1.25x3.5in", "oe_lg-address-label_1.4x3.5in", "oe_video-top-label_1.8x3.1in", "oe_multipurpose-label_2x2.3125in", "oe_md-appointment-card_2x3.5in", "oe_lg-multipurpose-label_2.125x.75in", "oe_shipping-label_2.125x4in", "oe_continuous-label_2.125x3600in", "oe_md-multipurpose-label_2.25x1.25in", "oe_media-label_2.25x2.25in", "oe_2-up-address-label_2.25x3.5in", "oe_name-badge-label_2.25x4in", "oe_3-part-postage-label_2.25x7in", "oe_2-part-internet-postage-label_2.25x7.5in", "oe_shipping-label_2.3125x4in", "oe_internet-postage-label_2.3125x7in", "oe_internet-postage-confirmation-label_2.3125x10.5in", "roll_max_2.3125x3600in", "roll_min_0.25x0.25in" }; // // Local functions... // static int lprint_dymo_print(lprint_job_t *job, lprint_options_t *options); static int lprint_dymo_rendjob(lprint_job_t *job, lprint_options_t *options); static int lprint_dymo_rendpage(lprint_job_t *job, lprint_options_t *options, unsigned page); static int lprint_dymo_rstartjob(lprint_job_t *job, lprint_options_t *options); static int lprint_dymo_rstartpage(lprint_job_t *job, lprint_options_t *options, unsigned page); static int lprint_dymo_rwrite(lprint_job_t *job, lprint_options_t *options, unsigned y, const unsigned char *line); static int lprint_dymo_status(lprint_printer_t *printer); // // 'lprintInitDymo()' - Initialize the driver. // void lprintInitDYMO( lprint_driver_t *driver) // I - Driver { int i; // Looping var pthread_rwlock_wrlock(&driver->rwlock); driver->print = lprint_dymo_print; driver->rendjob = lprint_dymo_rendjob; driver->rendpage = lprint_dymo_rendpage; driver->rstartjob = lprint_dymo_rstartjob; driver->rstartpage = lprint_dymo_rstartpage; driver->rwrite = lprint_dymo_rwrite; driver->status = lprint_dymo_status; driver->format = "application/vnd.dymo-lw"; driver->num_resolution = 1; driver->x_resolution[0] = 300; driver->y_resolution[0] = 300; driver->left_right = 100; driver->bottom_top = 525; driver->num_media = (int)(sizeof(lprint_dymo_media) / sizeof(lprint_dymo_media[0])); memcpy(driver->media, lprint_dymo_media, sizeof(lprint_dymo_media)); if (strstr(driver->name, "-duo") || strstr(driver->name, "-twin")) { driver->num_source = 2; driver->source[0] = "main-roll"; driver->source[1] = "alternate-roll"; strlcpy(driver->media_ready[0].size_name, "oe_multipurpose-label_2x2.3125in", sizeof(driver->media_ready[0].size_name)); strlcpy(driver->media_ready[1].size_name, "oe_address-label_1.25x3.5in", sizeof(driver->media_ready[1].size_name)); } else { driver->num_source = 1; driver->source[0] = "main-roll"; strlcpy(driver->media_ready[0].size_name, "oe_address-label_1.25x3.5in", sizeof(driver->media_ready[0].size_name)); } driver->tracking_supported = LPRINT_MEDIA_TRACKING_WEB; driver->num_type = 1; driver->type[0] = "labels"; driver->media_default.bottom_margin = driver->bottom_top; driver->media_default.left_margin = driver->left_right; driver->media_default.right_margin = driver->left_right; driver->media_default.size_width = 3175; driver->media_default.size_length = 8890; driver->media_default.top_margin = driver->bottom_top; driver->media_default.tracking = LPRINT_MEDIA_TRACKING_WEB; strlcpy(driver->media_default.size_name, "oe_address-label_1.25x3.5in", sizeof(driver->media_default.size_name)); strlcpy(driver->media_default.source, driver->source[0], sizeof(driver->media_default.source)); strlcpy(driver->media_default.type, driver->type[0], sizeof(driver->media_default.type)); for (i = 0; i < driver->num_source; i ++) { pwg_media_t *pwg = pwgMediaForPWG(driver->media_ready[i].size_name); driver->media_ready[i].bottom_margin = driver->bottom_top; driver->media_ready[i].left_margin = driver->left_right; driver->media_ready[i].right_margin = driver->left_right; driver->media_ready[i].size_width = pwg->width; driver->media_ready[i].size_length = pwg->length; driver->media_ready[i].top_margin = driver->bottom_top; driver->media_ready[i].tracking = LPRINT_MEDIA_TRACKING_WEB; strlcpy(driver->media_ready[i].source, driver->source[i], sizeof(driver->media_ready[i].source)); strlcpy(driver->media_ready[i].type, driver->type[0], sizeof(driver->media_ready[i].type)); } driver->darkness_configured = 50; driver->darkness_supported = 4; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } // // 'lprint_dymo_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_dymo_print( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_device_t *device = job->printer->driver->device; // Output device int infd; // Input file ssize_t bytes; // Bytes read/written char buffer[65536]; // Read/write buffer // Reset the printer... lprintPutsDevice(device, "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033@"); // Copy the raw file... job->impressions = 1; infd = open(job->filename, O_RDONLY); while ((bytes = read(infd, buffer, sizeof(buffer))) > 0) { if (lprintWriteDevice(device, buffer, (size_t)bytes) < 0) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to send %d bytes to printer.", (int)bytes); close(infd); return (0); } } close(infd); job->impcompleted = 1; return (1); } // // 'lprint_dymo_rend()' - End a job. // static int // O - 1 on success, 0 on failure lprint_dymo_rendjob( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_driver_t *driver = job->printer->driver; // Driver data (void)options; free(driver->job_data); driver->job_data = NULL; return (1); } // // 'lprint_dymo_rendpage()' - End a page. // static int // O - 1 on success, 0 on failure lprint_dymo_rendpage( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned page) // I - Page number { lprint_device_t *device = job->printer->driver->device; // Output device (void)options; (void)page; lprintPutsDevice(device, "\033E"); return (1); } // // 'lprint_dymo_rstartjob()' - Start a job. // static int // O - 1 on success, 0 on failure lprint_dymo_rstartjob( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_device_t *device = job->printer->driver->device; // Output device lprint_dymo_t *dymo = (lprint_dymo_t *)calloc(1, sizeof(lprint_dymo_t)); // DYMO driver data (void)options; job->printer->driver->job_data = dymo; lprintPutsDevice(device, "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033\033\033\033\033\033\033\033\033\033" "\033@"); return (1); } // // 'lprint_dymo_rstartpage()' - Start a page. // static int // O - 1 on success, 0 on failure lprint_dymo_rstartpage( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned page) // I - Page number { lprint_driver_t *driver = job->printer->driver; // Driver lprint_device_t *device = job->printer->driver->device; // Output device lprint_dymo_t *dymo = (lprint_dymo_t *)job->printer->driver->job_data; // DYMO driver data int darkness = job->printer->driver->darkness_configured + options->print_darkness; const char *density = "cdeg"; // Density codes (void)page; if (options->header.cupsBytesPerLine > 256) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Raster data too large for printer."); return (0); } lprintPrintfDevice(device, "\033Q%c%c", 0, 0); lprintPrintfDevice(device, "\033B%c", 0); lprintPrintfDevice(device, "\033L%c%c", options->header.cupsHeight >> 8, options->header.cupsHeight); lprintPrintfDevice(device, "\033D%c", options->header.cupsBytesPerLine - 1); lprintPrintfDevice(device, "\033q%d", !strcmp(options->media.source, "alternate-roll") ? 2 : 1); if (darkness < 0) darkness = 0; else if (darkness > 100) darkness = 100; lprintPrintfDevice(device, "\033%c", density[3 * darkness / 100]); dymo->feed = 0; dymo->ystart = driver->bottom_top * options->printer_resolution[1] / 2540; dymo->yend = options->header.cupsHeight - dymo->ystart; return (1); } // // 'lprint_dymo_rwrite()' - Write a raster line. // static int // O - 1 on success, 0 on failure lprint_dymo_rwrite( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned y, // I - Line number const unsigned char *line) // I - Line { lprint_device_t *device = job->printer->driver->device; // Output device lprint_dymo_t *dymo = (lprint_dymo_t *)job->printer->driver->job_data; // DYMO driver data unsigned char buffer[256]; // Write buffer if (y < dymo->ystart || y >= dymo->yend) return (1); if (line[0] || memcmp(line, line + 1, options->header.cupsBytesPerLine - 1)) { // Not a blank line, feed for any prior blank lines... if (dymo->feed) { while (dymo->feed > 255) { lprintPrintfDevice(device, "\033f\001%c", 255); dymo->feed -= 255; } lprintPrintfDevice(device, "\033f\001%c", dymo->feed); dymo->feed = 0; } // Then write the non-blank line... buffer[0] = 0x16; memcpy(buffer + 1, line + 1, options->header.cupsBytesPerLine - 1); lprintWriteDevice(device, buffer, options->header.cupsBytesPerLine); } else { // Blank line, accumulate the feed... dymo->feed ++; } return (1); } // // 'lprint_dymo_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_dymo_status( lprint_printer_t *printer) // I - Printer { (void)printer; return (1); } lprint-1.0/driver-epl1.c000066400000000000000000000066071362261677400152070ustar00rootroot00000000000000// // UNIMPLEMENTED EPL1 driver for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local globals... // static const char * const lprint_epl1_media[] = { // Supported media sizes "oe_1.25x0.25-label_1.25x0.25in", "oe_1.25x2.25-label_1.25x2.25in", "oe_1.5x0.25-label_1.5x0.25in", "oe_1.5x0.5-label_1.5x0.5in", "oe_1.5x1-label_1.5x1in", "oe_1.5x2-label_1.5x2in", "oe_2x0.37-label_2x0.37in", "oe_2x0.5-label_2x0.5in", "oe_2x1-label_2x1in", "oe_2x1.25-label_2x1.25in", "oe_2x2-label_2x2in", "oe_2x3-label_2x3in", "oe_2x4-label_2x4in", "oe_2x5.5-label_2x5.5in", "oe_2.25x0.5-label_2.25xin", "oe_2.25x1.25-label_2.25xin", "oe_30859-paint-can-label_2.25x3.125in", "oe_2.25x4-label_2.25x4in", "oe_2.25x5.5-label_2.25x5.5in", "oe_2.38x5.5-label_2.38x5.5in", "oe_2.5x1-label_2.5x1in", "oe_2.5x2-label_2.5x2in", "oe_2.75x1.25-label_2.75x1.25in", "oe_2.9x1-label_2.9x1in", "oe_3x1-label_3x1in", "oe_3x1.25-label_3x1.25in", "oe_3x2-label_3x2in", "oe_3x3-label_3x3in", "oe_3x5-label_3x5in", "oe_3.25x2-label_3.25x2in", "oe_3.25x5-label_3.25x5in", "oe_3.25x5.5-label_3.25x5.5in", "oe_3.25x5.83-label_3.25x5.83in", "oe_3.25x7.83-label_3.25x7.83in", "oe_3.5x1-label_3.5x1in", "oe_4x1-label_4x1in", "oe_4x2-label_4x2in", "oe_4x3-label_4x3in", "oe_4x4-label_4x4in", "oe_4x5-label_4x5in", "oe_4x6-label_4x6in", "oe_4x6.5-label_4x6.5in", "oe_4x13-label_4x13in", "oe_6x1-label_6x1in", "oe_6x2-label_6x2in", "oe_6x3-label_6x3in", "oe_6x4-label_6x4in", "oe_6x5-label_6x5in", "oe_6x6-label_6x6in", "oe_6x6.5-label_6x6.5in", "oe_6x13-label_6x13in", "oe_8x1-label_8x1in", "oe_8x2-label_8x2in", "oe_8x3-label_8x3in", "oe_8x4-label_8x4in", "oe_8x5-label_8x5in", "oe_8x6-label_8x6in", "oe_8x6.5-label_8x6.5in", "oe_8x13-label_8x13in", "roll_max_8x100in", "roll_min_1.25x0.25in" }; // // Local functions... // static int lprint_epl1_print(lprint_printer_t *printer, lprint_job_t *job); static int lprint_epl1_status(lprint_printer_t *printer); // // 'lprintInitEPL1()' - Initialize the driver. // void lprintInitEPL1( lprint_driver_t *driver) // I - Driver { pthread_rwlock_wrlock(&driver->rwlock); driver->printfunc = lprint_epl1_print; driver->statusfunc = lprint_epl1_status; driver->format = "application/vnd.-"; driver->num_resolution = 1; driver->x_resolution[0] = 203; driver->y_resolution[0] = 203; driver->num_media = (int)(sizeof(lprint_epl1_media) / sizeof(lprint_epl1_media[0])); memcpy(driver->media, lprint_epl1_media, sizeof(lprint_epl1_media)); driver->num_source = 1; driver->source[0] = "main-roll"; driver->num_type = 1; driver->type[0] = "labels"; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } // // 'lprint_epl1_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_epl1_print( lprint_printer_t *printer, // I - Printer lprint_job_t *job) // I - Job { (void)printer; (void)job; return (1); } // // 'lprint_epl1_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_epl1_status( lprint_printer_t *printer) // I - Printer { (void)printer; return (1); } lprint-1.0/driver-epl2.c000066400000000000000000000066071362261677400152100ustar00rootroot00000000000000// // UNIMPLEMENTED EPL2 driver for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local globals... // static const char * const lprint_epl2_media[] = { // Supported media sizes "oe_1.25x0.25-label_1.25x0.25in", "oe_1.25x2.25-label_1.25x2.25in", "oe_1.5x0.25-label_1.5x0.25in", "oe_1.5x0.5-label_1.5x0.5in", "oe_1.5x1-label_1.5x1in", "oe_1.5x2-label_1.5x2in", "oe_2x0.37-label_2x0.37in", "oe_2x0.5-label_2x0.5in", "oe_2x1-label_2x1in", "oe_2x1.25-label_2x1.25in", "oe_2x2-label_2x2in", "oe_2x3-label_2x3in", "oe_2x4-label_2x4in", "oe_2x5.5-label_2x5.5in", "oe_2.25x0.5-label_2.25xin", "oe_2.25x1.25-label_2.25xin", "oe_30859-paint-can-label_2.25x3.125in", "oe_2.25x4-label_2.25x4in", "oe_2.25x5.5-label_2.25x5.5in", "oe_2.38x5.5-label_2.38x5.5in", "oe_2.5x1-label_2.5x1in", "oe_2.5x2-label_2.5x2in", "oe_2.75x1.25-label_2.75x1.25in", "oe_2.9x1-label_2.9x1in", "oe_3x1-label_3x1in", "oe_3x1.25-label_3x1.25in", "oe_3x2-label_3x2in", "oe_3x3-label_3x3in", "oe_3x5-label_3x5in", "oe_3.25x2-label_3.25x2in", "oe_3.25x5-label_3.25x5in", "oe_3.25x5.5-label_3.25x5.5in", "oe_3.25x5.83-label_3.25x5.83in", "oe_3.25x7.83-label_3.25x7.83in", "oe_3.5x1-label_3.5x1in", "oe_4x1-label_4x1in", "oe_4x2-label_4x2in", "oe_4x3-label_4x3in", "oe_4x4-label_4x4in", "oe_4x5-label_4x5in", "oe_4x6-label_4x6in", "oe_4x6.5-label_4x6.5in", "oe_4x13-label_4x13in", "oe_6x1-label_6x1in", "oe_6x2-label_6x2in", "oe_6x3-label_6x3in", "oe_6x4-label_6x4in", "oe_6x5-label_6x5in", "oe_6x6-label_6x6in", "oe_6x6.5-label_6x6.5in", "oe_6x13-label_6x13in", "oe_8x1-label_8x1in", "oe_8x2-label_8x2in", "oe_8x3-label_8x3in", "oe_8x4-label_8x4in", "oe_8x5-label_8x5in", "oe_8x6-label_8x6in", "oe_8x6.5-label_8x6.5in", "oe_8x13-label_8x13in", "roll_max_8x100in", "roll_min_1.25x0.25in" }; // // Local functions... // static int lprint_epl2_print(lprint_printer_t *printer, lprint_job_t *job); static int lprint_epl2_status(lprint_printer_t *printer); // // 'lprintInitEPL2()' - Initialize the driver. // void lprintInitEPL2( lprint_driver_t *driver) // I - Driver { pthread_rwlock_wrlock(&driver->rwlock); driver->printfunc = lprint_epl2_print; driver->statusfunc = lprint_epl2_status; driver->format = "application/vnd.-"; driver->num_resolution = 1; driver->x_resolution[0] = 203; driver->y_resolution[0] = 203; driver->num_media = (int)(sizeof(lprint_epl2_media) / sizeof(lprint_epl2_media[0])); memcpy(driver->media, lprint_epl2_media, sizeof(lprint_epl2_media)); driver->num_source = 1; driver->source[0] = "main-roll"; driver->num_type = 1; driver->type[0] = "labels"; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } // // 'lprint_epl2_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_epl2_print( lprint_printer_t *printer, // I - Printer lprint_job_t *job) // I - Job { (void)printer; (void)job; return (1); } // // 'lprint_epl2_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_epl2_status( lprint_printer_t *printer) // I - Printer { (void)printer; return (1); } lprint-1.0/driver-fgl.c000066400000000000000000000065671362261677400151230ustar00rootroot00000000000000// // UNIMPLEMENTED FGL driver for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local globals... // static const char * const lprint_fgl_media[] = { // Supported media sizes "oe_1.25x0.25-label_1.25x0.25in", "oe_1.25x2.25-label_1.25x2.25in", "oe_1.5x0.25-label_1.5x0.25in", "oe_1.5x0.5-label_1.5x0.5in", "oe_1.5x1-label_1.5x1in", "oe_1.5x2-label_1.5x2in", "oe_2x0.37-label_2x0.37in", "oe_2x0.5-label_2x0.5in", "oe_2x1-label_2x1in", "oe_2x1.25-label_2x1.25in", "oe_2x2-label_2x2in", "oe_2x3-label_2x3in", "oe_2x4-label_2x4in", "oe_2x5.5-label_2x5.5in", "oe_2.25x0.5-label_2.25xin", "oe_2.25x1.25-label_2.25xin", "oe_30859-paint-can-label_2.25x3.125in", "oe_2.25x4-label_2.25x4in", "oe_2.25x5.5-label_2.25x5.5in", "oe_2.38x5.5-label_2.38x5.5in", "oe_2.5x1-label_2.5x1in", "oe_2.5x2-label_2.5x2in", "oe_2.75x1.25-label_2.75x1.25in", "oe_2.9x1-label_2.9x1in", "oe_3x1-label_3x1in", "oe_3x1.25-label_3x1.25in", "oe_3x2-label_3x2in", "oe_3x3-label_3x3in", "oe_3x5-label_3x5in", "oe_3.25x2-label_3.25x2in", "oe_3.25x5-label_3.25x5in", "oe_3.25x5.5-label_3.25x5.5in", "oe_3.25x5.83-label_3.25x5.83in", "oe_3.25x7.83-label_3.25x7.83in", "oe_3.5x1-label_3.5x1in", "oe_4x1-label_4x1in", "oe_4x2-label_4x2in", "oe_4x3-label_4x3in", "oe_4x4-label_4x4in", "oe_4x5-label_4x5in", "oe_4x6-label_4x6in", "oe_4x6.5-label_4x6.5in", "oe_4x13-label_4x13in", "oe_6x1-label_6x1in", "oe_6x2-label_6x2in", "oe_6x3-label_6x3in", "oe_6x4-label_6x4in", "oe_6x5-label_6x5in", "oe_6x6-label_6x6in", "oe_6x6.5-label_6x6.5in", "oe_6x13-label_6x13in", "oe_8x1-label_8x1in", "oe_8x2-label_8x2in", "oe_8x3-label_8x3in", "oe_8x4-label_8x4in", "oe_8x5-label_8x5in", "oe_8x6-label_8x6in", "oe_8x6.5-label_8x6.5in", "oe_8x13-label_8x13in", "roll_max_8x100in", "roll_min_1.25x0.25in" }; // // Local functions... // static int lprint_fgl_print(lprint_printer_t *printer, lprint_job_t *job); static int lprint_fgl_status(lprint_printer_t *printer); // // 'lprintInitFGL()' - Initialize the driver. // void lprintInitFGL( lprint_driver_t *driver) // I - Driver { pthread_rwlock_wrlock(&driver->rwlock); driver->printfunc = lprint_fgl_print; driver->statusfunc = lprint_fgl_status; driver->format = "application/vnd.-"; driver->num_resolution = 1; driver->x_resolution[0] = 203; driver->y_resolution[0] = 203; driver->num_media = (int)(sizeof(lprint_fgl_media) / sizeof(lprint_fgl_media[0])); memcpy(driver->media, lprint_fgl_media, sizeof(lprint_fgl_media)); driver->num_source = 1; driver->source[0] = "main-roll"; driver->num_type = 1; driver->type[0] = "labels"; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } // // 'lprint_fgl_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_fgl_print( lprint_printer_t *printer, // I - Printer lprint_job_t *job) // I - Job { (void)printer; (void)job; return (1); } // // 'lprint_fgl_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_fgl_status( lprint_printer_t *printer) // I - Printer { (void)printer; return (1); } lprint-1.0/driver-pcl.c000066400000000000000000000065671362261677400151310ustar00rootroot00000000000000// // UNIMPLEMENTED PCL driver for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local globals... // static const char * const lprint_pcl_media[] = { // Supported media sizes "oe_1.25x0.25-label_1.25x0.25in", "oe_1.25x2.25-label_1.25x2.25in", "oe_1.5x0.25-label_1.5x0.25in", "oe_1.5x0.5-label_1.5x0.5in", "oe_1.5x1-label_1.5x1in", "oe_1.5x2-label_1.5x2in", "oe_2x0.37-label_2x0.37in", "oe_2x0.5-label_2x0.5in", "oe_2x1-label_2x1in", "oe_2x1.25-label_2x1.25in", "oe_2x2-label_2x2in", "oe_2x3-label_2x3in", "oe_2x4-label_2x4in", "oe_2x5.5-label_2x5.5in", "oe_2.25x0.5-label_2.25xin", "oe_2.25x1.25-label_2.25xin", "oe_30859-paint-can-label_2.25x3.125in", "oe_2.25x4-label_2.25x4in", "oe_2.25x5.5-label_2.25x5.5in", "oe_2.38x5.5-label_2.38x5.5in", "oe_2.5x1-label_2.5x1in", "oe_2.5x2-label_2.5x2in", "oe_2.75x1.25-label_2.75x1.25in", "oe_2.9x1-label_2.9x1in", "oe_3x1-label_3x1in", "oe_3x1.25-label_3x1.25in", "oe_3x2-label_3x2in", "oe_3x3-label_3x3in", "oe_3x5-label_3x5in", "oe_3.25x2-label_3.25x2in", "oe_3.25x5-label_3.25x5in", "oe_3.25x5.5-label_3.25x5.5in", "oe_3.25x5.83-label_3.25x5.83in", "oe_3.25x7.83-label_3.25x7.83in", "oe_3.5x1-label_3.5x1in", "oe_4x1-label_4x1in", "oe_4x2-label_4x2in", "oe_4x3-label_4x3in", "oe_4x4-label_4x4in", "oe_4x5-label_4x5in", "oe_4x6-label_4x6in", "oe_4x6.5-label_4x6.5in", "oe_4x13-label_4x13in", "oe_6x1-label_6x1in", "oe_6x2-label_6x2in", "oe_6x3-label_6x3in", "oe_6x4-label_6x4in", "oe_6x5-label_6x5in", "oe_6x6-label_6x6in", "oe_6x6.5-label_6x6.5in", "oe_6x13-label_6x13in", "oe_8x1-label_8x1in", "oe_8x2-label_8x2in", "oe_8x3-label_8x3in", "oe_8x4-label_8x4in", "oe_8x5-label_8x5in", "oe_8x6-label_8x6in", "oe_8x6.5-label_8x6.5in", "oe_8x13-label_8x13in", "roll_max_8x100in", "roll_min_1.25x0.25in" }; // // Local functions... // static int lprint_pcl_print(lprint_printer_t *printer, lprint_job_t *job); static int lprint_pcl_status(lprint_printer_t *printer); // // 'lprintInitPCL()' - Initialize the driver. // void lprintInitPCL( lprint_driver_t *driver) // I - Driver { pthread_rwlock_wrlock(&driver->rwlock); driver->printfunc = lprint_pcl_print; driver->statusfunc = lprint_pcl_status; driver->format = "application/vnd.-"; driver->num_resolution = 1; driver->x_resolution[0] = 203; driver->y_resolution[0] = 203; driver->num_media = (int)(sizeof(lprint_pcl_media) / sizeof(lprint_pcl_media[0])); memcpy(driver->media, lprint_pcl_media, sizeof(lprint_pcl_media)); driver->num_source = 1; driver->source[0] = "main-roll"; driver->num_type = 1; driver->type[0] = "labels"; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } // // 'lprint_pcl_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_pcl_print( lprint_printer_t *printer, // I - Printer lprint_job_t *job) // I - Job { (void)printer; (void)job; return (1); } // // 'lprint_pcl_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_pcl_status( lprint_printer_t *printer) // I - Printer { (void)printer; return (1); } lprint-1.0/driver-pwg.c000066400000000000000000000203741362261677400151400ustar00rootroot00000000000000// // PWG Raster test driver for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // local typs... // typedef struct lprint_pwg_s { int fd; // Output file descriptor cups_raster_t *ras; // PWG raster file } lprint_pwg_t; // // Local globals... // static const char * const lprint_pwg_2inch_media[] = { // Supported media sizes "oe_address-label_1.25x3.5in", "oe_lg-address-label_1.4x3.5in", "oe_multipurpose-label_2x2.3125in", "roll_max_2x3600in", "roll_min_0.25x0.25in" }; static const char * const lprint_pwg_4inch_media[] = { // Supported media sizes "oe_address-label_1.25x3.5in", "oe_lg-address-label_1.4x3.5in", "oe_multipurpose-label_2x2.3125in", "na_index-3x5_3x5in", "na_index-4x6_4x6in", "roll_max_4x3600in", "roll_min_0.25x0.25in" }; // // Local functions... // static int lprint_pwg_print(lprint_job_t *job, lprint_options_t *options); static int lprint_pwg_rendjob(lprint_job_t *job, lprint_options_t *options); static int lprint_pwg_rendpage(lprint_job_t *job, lprint_options_t *options, unsigned page); static int lprint_pwg_rstartjob(lprint_job_t *job, lprint_options_t *options); static int lprint_pwg_rstartpage(lprint_job_t *job, lprint_options_t *options, unsigned page); static int lprint_pwg_rwrite(lprint_job_t *job, lprint_options_t *options, unsigned y, const unsigned char *line); static int lprint_pwg_status(lprint_printer_t *printer); // // 'lprintInitPWG()' - Initialize the driver. // void lprintInitPWG( lprint_driver_t *driver) // I - Driver { int i; // Looping var pthread_rwlock_wrlock(&driver->rwlock); driver->print = lprint_pwg_print; driver->rendjob = lprint_pwg_rendjob; driver->rendpage = lprint_pwg_rendpage; driver->rstartjob = lprint_pwg_rstartjob; driver->rstartpage = lprint_pwg_rstartpage; driver->rwrite = lprint_pwg_rwrite; driver->status = lprint_pwg_status; driver->format = "image/pwg-raster"; driver->num_resolution = 2; driver->x_resolution[0] = 203; driver->y_resolution[0] = 203; driver->x_resolution[1] = 300; driver->y_resolution[1] = 300; driver->left_right = 312; // 1/16" left and right driver->bottom_top = 625; // 1/8" top and bottom if (!strcmp(driver->name, "pwg_2inch")) { driver->num_media = (int)(sizeof(lprint_pwg_2inch_media) / sizeof(lprint_pwg_2inch_media[0])); memcpy(driver->media, lprint_pwg_2inch_media, sizeof(lprint_pwg_2inch_media)); driver->num_source = 1; driver->source[0] = "main-roll"; strlcpy(driver->media_ready[0].size_name, "oe_address-label_1.25x3.5in", sizeof(driver->media_ready[0].size_name)); } else { driver->num_media = (int)(sizeof(lprint_pwg_4inch_media) / sizeof(lprint_pwg_4inch_media[0])); memcpy(driver->media, lprint_pwg_4inch_media, sizeof(lprint_pwg_4inch_media)); driver->num_source = 2; driver->source[0] = "main-roll"; driver->source[1] = "alternate-roll"; strlcpy(driver->media_ready[0].size_name, "oe_address-label_1.25x3.5in", sizeof(driver->media_ready[0].size_name)); strlcpy(driver->media_ready[1].size_name, "na_index-4x6_4x6in", sizeof(driver->media_ready[1].size_name)); } driver->media_default.bottom_margin = driver->bottom_top; driver->media_default.left_margin = driver->left_right; driver->media_default.right_margin = driver->left_right; driver->media_default.size_width = 3175; driver->media_default.size_length = 8890; driver->media_default.top_margin = driver->bottom_top; driver->media_default.tracking = LPRINT_MEDIA_TRACKING_MARK; strlcpy(driver->media_default.size_name, "oe_address-label_1.25x3.5in", sizeof(driver->media_default.size_name)); strlcpy(driver->media_default.source, "main-roll", sizeof(driver->media_default.source)); strlcpy(driver->media_default.type, "labels", sizeof(driver->media_default.type)); for (i = 0; i < driver->num_source; i ++) { pwg_media_t *pwg = pwgMediaForPWG(driver->media_ready[i].size_name); driver->media_ready[i].bottom_margin = driver->bottom_top; driver->media_ready[i].left_margin = driver->left_right; driver->media_ready[i].right_margin = driver->left_right; driver->media_ready[i].size_width = pwg->width; driver->media_ready[i].size_length = pwg->length; driver->media_ready[i].top_margin = driver->bottom_top; driver->media_ready[i].tracking = LPRINT_MEDIA_TRACKING_MARK; strlcpy(driver->media_ready[i].source, driver->source[i], sizeof(driver->media_ready[i].source)); strlcpy(driver->media_ready[i].type, "labels", sizeof(driver->media_ready[i].type)); } driver->tracking_supported = LPRINT_MEDIA_TRACKING_MARK | LPRINT_MEDIA_TRACKING_CONTINUOUS; driver->num_type = 3; driver->type[0] = "continuous"; driver->type[1] = "labels"; driver->type[2] = "labels-continuous"; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } // // 'lprint_pwg_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_pwg_print( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { int infd, // Input file outfd; // Output file char outname[1024]; // Output filename ssize_t bytes; // Bytes read/written char buffer[65536]; // Read/write buffer job->impressions = 1; infd = open(job->filename, O_RDONLY); outfd = lprintCreateJobFile(job, outname, sizeof(outname), job->system->directory, "out.pwg"); while ((bytes = read(infd, buffer, sizeof(buffer))) > 0) write(outfd, buffer, (size_t)bytes); close(infd); close(outfd); job->impcompleted = 1; return (1); } // // 'lprint_pwg_rendjob()' - End a job. // static int // O - 1 on success, 0 on failure lprint_pwg_rendjob( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_pwg_t *pwg = (lprint_pwg_t *)job->printer->driver->job_data; (void)options; cupsRasterClose(pwg->ras); close(pwg->fd); free(pwg); job->printer->driver->job_data = NULL; return (1); } // // 'lprint_pwg_rendpage()' - End a page. // static int // O - 1 on success, 0 on failure lprint_pwg_rendpage( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned page) // I - Page number { (void)job; (void)options; (void)page; return (1); } // // 'lprint_pwg_rstartjob()' - Start a job. // static int // O - 1 on success, 0 on failure lprint_pwg_rstartjob( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_pwg_t *pwg = (lprint_pwg_t *)calloc(1, sizeof(lprint_pwg_t)); // PWG driver data char outname[1024]; // Output filename (void)options; job->printer->driver->job_data = pwg; pwg->fd = lprintCreateJobFile(job, outname, sizeof(outname), job->system->directory, "out.pwg"); pwg->ras = cupsRasterOpen(pwg->fd, CUPS_RASTER_WRITE_PWG); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "Writing PWG output to '%s'.", outname); return (1); } // // 'lprint_pwg_rstartpage()' - Start a page. // static int // O - 1 on success, 0 on failure lprint_pwg_rstartpage( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned page) // I - Page number { lprint_pwg_t *pwg = (lprint_pwg_t *)job->printer->driver->job_data; // PWG driver data (void)page; return (cupsRasterWriteHeader2(pwg->ras, &options->header)); } // // 'lprint_pwg_rwrite()' - Write a raster line. // static int // O - 1 on success, 0 on failure lprint_pwg_rwrite( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned y, // I - Line number const unsigned char *line) // I - Line { lprint_pwg_t *pwg = (lprint_pwg_t *)job->printer->driver->job_data; // PWG driver data (void)y; return (cupsRasterWritePixels(pwg->ras, (unsigned char *)line, options->header.cupsBytesPerLine)); } // // 'lprint_pwg_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_pwg_status( lprint_printer_t *printer) // I - Printer { (void)printer; return (1); } lprint-1.0/driver-zpl.c000066400000000000000000000412101362261677400151400ustar00rootroot00000000000000// // ZPL driver for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2007-2019 by Apple Inc. // Copyright © 2001-2007 by Easy Software Products. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #define ZPL_COMPRESSION 1 // // Local types... // typedef struct lprint_zpl_s // ZPL driver data { unsigned char *comp_buffer; // Compression buffer unsigned char *last_buffer; // Last line int last_buffer_set; // Is the last line set? } lprint_zpl_t; // // Local globals... // static const char * const lprint_zpl_2inch_media[] = { // Supported 2 inch media sizes "oe_1.25x0.25-label_1.25x0.25in", "oe_1.25x2.25-label_1.25x2.25in", "oe_1.5x0.25-label_1.5x0.25in", "oe_1.5x0.5-label_1.5x0.5in", "oe_1.5x1-label_1.5x1in", "oe_1.5x2-label_1.5x2in", "oe_2x0.37-label_2x0.37in", "oe_2x0.5-label_2x0.5in", "oe_2x1-label_2x1in", "oe_2x1.25-label_2x1.25in", "oe_2x2-label_2x2in", "oe_2x3-label_2x3in", "oe_2x4-label_2x4in", "oe_2x5.5-label_2x5.5in", "roll_max_2x39.6in", "roll_min_0.75x0.25in" }; static const char * const lprint_zpl_4inch_media[] = { // Supported 4 inch media sizes "oe_1.25x0.25-label_1.25x0.25in", "oe_1.25x2.25-label_1.25x2.25in", "oe_1.5x0.25-label_1.5x0.25in", "oe_1.5x0.5-label_1.5x0.5in", "oe_1.5x1-label_1.5x1in", "oe_1.5x2-label_1.5x2in", "oe_2x0.37-label_2x0.37in", "oe_2x0.5-label_2x0.5in", "oe_2x1-label_2x1in", "oe_2x1.25-label_2x1.25in", "oe_2x2-label_2x2in", "oe_2x3-label_2x3in", "oe_2x4-label_2x4in", "oe_2x5.5-label_2x5.5in", "oe_2.25x0.5-label_2.25xin", "oe_2.25x1.25-label_2.25xin", "oe_30859-paint-can-label_2.25x3.125in", "oe_2.25x4-label_2.25x4in", "oe_2.25x5.5-label_2.25x5.5in", "oe_2.38x5.5-label_2.38x5.5in", "oe_2.5x1-label_2.5x1in", "oe_2.5x2-label_2.5x2in", "oe_2.75x1.25-label_2.75x1.25in", "oe_2.9x1-label_2.9x1in", "oe_3x1-label_3x1in", "oe_3x1.25-label_3x1.25in", "oe_3x2-label_3x2in", "oe_3x3-label_3x3in", "na_index-3x5_3x5in", "oe_3.25x2-label_3.25x2in", "oe_3.25x5-label_3.25x5in", "oe_3.25x5.5-label_3.25x5.5in", "oe_3.25x5.83-label_3.25x5.83in", "oe_3.25x7.83-label_3.25x7.83in", "oe_3.5x1-label_3.5x1in", "oe_4x1-label_4x1in", "oe_4x2-label_4x2in", "oe_4x3-label_4x3in", "oe_4x4-label_4x4in", "oe_4x5-label_4x5in", "na_index-4x6_4x6in", "oe_4x6.5-label_4x6.5in", "oe_4x13-label_4x13in", "roll_max_4x39.6in", "roll_min_0.75x0.25in" /* "oe_6x1-label_6x1in", "oe_6x2-label_6x2in", "oe_6x3-label_6x3in", "oe_6x4-label_6x4in", "oe_6x5-label_6x5in", "oe_6x6-label_6x6in", "oe_6x6.5-label_6x6.5in", "oe_6x13-label_6x13in", "oe_8x1-label_8x1in", "oe_8x2-label_8x2in", "oe_8x3-label_8x3in", "oe_8x4-label_8x4in", "oe_8x5-label_8x5in", "oe_8x6-label_8x6in", "oe_8x6.5-label_8x6.5in", "oe_8x13-label_8x13in", "roll_max_8x39.6in", "roll_min_1.25x0.25in" */ }; // // Local functions... // #if ZPL_COMPRESSION static int lprint_zpl_compress(lprint_device_t *device, unsigned char ch, unsigned count); #endif // ZPL_COMPRESSION static int lprint_zpl_print(lprint_job_t *job, lprint_options_t *options); static int lprint_zpl_rendjob(lprint_job_t *job, lprint_options_t *options); static int lprint_zpl_rendpage(lprint_job_t *job, lprint_options_t *options, unsigned page); static int lprint_zpl_rstartjob(lprint_job_t *job, lprint_options_t *options); static int lprint_zpl_rstartpage(lprint_job_t *job, lprint_options_t *options, unsigned page); static int lprint_zpl_rwrite(lprint_job_t *job, lprint_options_t *options, unsigned y, const unsigned char *line); static int lprint_zpl_status(lprint_printer_t *printer); // // 'lprintInitZPL()' - Initialize the driver. // void lprintInitZPL( lprint_driver_t *driver) // I - Driver { pthread_rwlock_wrlock(&driver->rwlock); driver->print = lprint_zpl_print; driver->rendjob = lprint_zpl_rendjob; driver->rendpage = lprint_zpl_rendpage; driver->rstartjob = lprint_zpl_rstartjob; driver->rstartpage = lprint_zpl_rstartpage; driver->rwrite = lprint_zpl_rwrite; driver->status = lprint_zpl_status; driver->format = "application/vnd.zebra-zpl"; driver->num_resolution = 1; if (strstr(driver->name, "-203dpi")) { driver->x_resolution[0] = 203; driver->y_resolution[0] = 203; } else { driver->x_resolution[0] = 300; driver->y_resolution[0] = 300; } if (!strncmp(driver->name, "zpl_2inch-", 16)) { // 2 inch printer... driver->num_media = (int)(sizeof(lprint_zpl_2inch_media) / sizeof(lprint_zpl_2inch_media[0])); memcpy(driver->media, lprint_zpl_2inch_media, sizeof(lprint_zpl_2inch_media)); strlcpy(driver->media_default.size_name, "oe_2x3-label_2x3in", sizeof(driver->media_default.size_name)); } else { // 4 inch printer... driver->num_media = (int)(sizeof(lprint_zpl_4inch_media) / sizeof(lprint_zpl_4inch_media[0])); memcpy(driver->media, lprint_zpl_4inch_media, sizeof(lprint_zpl_4inch_media)); strlcpy(driver->media_default.size_name, "oe_4x6-label_4x6in", sizeof(driver->media_default.size_name)); } driver->num_source = 1; driver->source[0] = "main-roll"; driver->top_offset_supported[0] = -1500; driver->top_offset_supported[1] = 1500; driver->tracking_supported = LPRINT_MEDIA_TRACKING_MARK | LPRINT_MEDIA_TRACKING_WEB | LPRINT_MEDIA_TRACKING_CONTINUOUS; driver->num_type = 3; driver->type[0] = "continuous"; driver->type[1] = "labels"; driver->type[2] = "labels-continuous"; driver->media_default.bottom_margin = driver->bottom_top; driver->media_default.left_margin = driver->left_right; driver->media_default.right_margin = driver->left_right; strlcpy(driver->media_default.source, "main-roll", sizeof(driver->media_default.source)); driver->media_default.top_margin = driver->bottom_top; driver->media_default.top_offset = 0; driver->media_default.tracking = LPRINT_MEDIA_TRACKING_MARK; strlcpy(driver->media_default.type, "labels", sizeof(driver->media_default.type)); driver->media_ready[0] = driver->media_default; driver->mode_configured = LPRINT_LABEL_MODE_TEAR_OFF; driver->mode_configured = LPRINT_LABEL_MODE_APPLICATOR | LPRINT_LABEL_MODE_CUTTER | LPRINT_LABEL_MODE_CUTTER_DELAYED | LPRINT_LABEL_MODE_KIOSK | LPRINT_LABEL_MODE_PEEL_OFF | LPRINT_LABEL_MODE_PEEL_OFF_PREPEEL | LPRINT_LABEL_MODE_REWIND | LPRINT_LABEL_MODE_RFID | LPRINT_LABEL_MODE_TEAR_OFF; driver->tear_offset_configured = 0; driver->tear_offset_supported[0] = -1500; driver->tear_offset_supported[1] = 1500; driver->speed_default = 0; driver->speed_supported[0] = 2540; driver->speed_supported[1] = 12 * 2540; driver->darkness_configured = 50; driver->darkness_supported = 30; driver->num_supply = 0; pthread_rwlock_unlock(&driver->rwlock); } #if ZPL_COMPRESSION // // 'lprint_zpl_compress()' - Output a RLE run... // static int // O - 1 on success, 0 on failure lprint_zpl_compress( lprint_device_t *device, // I - Output device unsigned char ch, // I - Repeat character unsigned count) // I - Repeat count { unsigned char buffer[8192], // Output buffer *bufptr = buffer; // Pointer into buffer if (count > 1) { // Print as many z's as possible - they are the largest denomination // representing 400 characters (zC stands for 400 adjacent C's) while (count >= 400) { count -= 400; *bufptr++ = 'z'; if (bufptr >= (buffer + sizeof(buffer))) { if (lprintWriteDevice(device, buffer, sizeof(buffer)) < 0) return (0); bufptr = buffer; } } // Then print 'g' through 'y' as multiples of 20 characters... if (count >= 20) { *bufptr++ = 'f' + count / 20; count %= 20; } // Finally, print 'G' through 'Y' as 1 through 19 characters... if (count > 0) *bufptr++ = 'F' + count; } // Then the character to be repeated... *bufptr++ = ch; return (lprintWriteDevice(device, buffer, bufptr - buffer) > 0); } #endif // ZPL_COMPRESSION // // 'lprint_zpl_print()' - Print a file. // static int // O - 1 on success, 0 on failure lprint_zpl_print( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_device_t *device = job->printer->driver->device; // Output device int infd; // Input file ssize_t bytes; // Bytes read/written char buffer[65536]; // Read/write buffer // Copy the raw file... job->impressions = 1; infd = open(job->filename, O_RDONLY); while ((bytes = read(infd, buffer, sizeof(buffer))) > 0) { if (lprintWriteDevice(device, buffer, (size_t)bytes) < 0) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to send %d bytes to printer.", (int)bytes); close(infd); return (0); } } close(infd); job->impcompleted = 1; return (1); } // // 'lprint_zpl_rendjob()' - End a job. // static int // O - 1 on success, 0 on failure lprint_zpl_rendjob( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_zpl_t *zpl = job->printer->driver->job_data; // ZPL driver data (void)options; free(zpl); job->printer->driver->job_data = NULL; return (1); } // // 'lprint_zpl_rendpage()' - End a page. // static int // O - 1 on success, 0 on failure lprint_zpl_rendpage( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned page) // I - Page number { lprint_driver_t *driver = job->printer->driver; // Driver lprint_device_t *device = job->printer->driver->device; // Output device lprint_zpl_t *zpl = job->printer->driver->job_data; // ZPL driver data (void)page; lprintPrintfDevice(device, "^XA\n^POI\n^PW%u\n^LH0,0\n^LT%d\n", options->header.cupsWidth, options->media.top_offset * options->printer_resolution[1] / 2540); if (options->media.type[0] && strcmp(options->media.type, "labels")) { // Continuous media, so always set tracking to continuous... options->media.tracking = LPRINT_MEDIA_TRACKING_CONTINUOUS; } if (options->media.tracking) { if (options->media.tracking == LPRINT_MEDIA_TRACKING_CONTINUOUS) lprintPrintfDevice(device, "^LL%d\n^MNN\n", options->header.cupsHeight); else if (options->media.tracking == LPRINT_MEDIA_TRACKING_WEB) lprintPutsDevice(device, "^MNY\n"); else lprintPutsDevice(device, "^MNM\n"); } if (strstr(driver->name, "-tt")) lprintPutsDevice(device, "^MTT\n"); // Thermal transfer else lprintPutsDevice(device, "^MTD\n"); // Direct thermal lprintPrintfDevice(device, "^PQ%d, 0, 0, N\n", options->copies); lprintPutsDevice(device, "^FO0,0^XGR:LPRINT.GRF,1,1^FS\n^XZ\n"); lprintPutsDevice(device, "^XA\n^IDR:LPRINT.GRF^FS\n^XZ\n"); free(zpl->comp_buffer); free(zpl->last_buffer); return (1); } // // 'lprint_zpl_rstartjob()' - Start a job. // static int // O - 1 on success, 0 on failure lprint_zpl_rstartjob( lprint_job_t *job, // I - Job lprint_options_t *options) // I - Job options { lprint_driver_t *driver = job->printer->driver; // Driver lprint_device_t *device = driver->device; // Output device lprint_zpl_t *zpl = (lprint_zpl_t *)calloc(1, sizeof(lprint_zpl_t)); // ZPL driver data driver->job_data = zpl; // label-mode-configured switch (driver->mode_configured) { case LPRINT_LABEL_MODE_APPLICATOR : lprintPutsDevice(device, "^MMA,Y\n"); break; case LPRINT_LABEL_MODE_CUTTER : lprintPutsDevice(device, "^MMC,Y\n"); break; case LPRINT_LABEL_MODE_CUTTER_DELAYED : lprintPutsDevice(device, "^MMD,Y\n"); break; case LPRINT_LABEL_MODE_KIOSK : lprintPutsDevice(device, "^MMK,Y\n"); break; case LPRINT_LABEL_MODE_PEEL_OFF : lprintPutsDevice(device, "^MMP,N\n"); break; case LPRINT_LABEL_MODE_PEEL_OFF_PREPEEL : lprintPutsDevice(device, "^MMP,Y\n"); break; case LPRINT_LABEL_MODE_REWIND : lprintPutsDevice(device, "^MMR,Y\n"); break; case LPRINT_LABEL_MODE_RFID : lprintPutsDevice(device, "^MMF,Y\n"); break; case LPRINT_LABEL_MODE_TEAR_OFF : default : lprintPutsDevice(device, "^MMT,Y\n"); break; } // label-tear-offset-configured if (driver->tear_offset_configured < 0) lprintPrintfDevice(device, "~TA%04d\n", driver->tear_offset_configured); else if (driver->tear_offset_configured > 0) lprintPrintfDevice(device, "~TA%03d\n", driver->tear_offset_configured); // printer-darkness lprintPrintfDevice(device, "~SD%02u\n", 30 * driver->darkness_configured / 100); return (1); } // // 'lprint_zpl_rstartpage()' - Start a page. // static int // O - 1 on success, 0 on failure lprint_zpl_rstartpage( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned page) // I - Page number { lprint_device_t *device = job->printer->driver->device; // Output device lprint_zpl_t *zpl = job->printer->driver->job_data; // ZPL driver data int ips; // Inches per second (void)page; // print-darkness lprintPrintfDevice(device, "~MD%d\n", 30 * options->print_darkness / 100); // print-speed if ((ips = options->print_speed / 2540) > 0) lprintPrintfDevice(device, "^PR%d,%d,%d\n", ips, ips, ips); // Download bitmap... lprintPrintfDevice(device, "~DGR:LPRINT.GRF,%u,%u,\n", options->header.cupsHeight * options->header.cupsBytesPerLine, options->header.cupsBytesPerLine); // Allocate memory for writing the bitmap... zpl->comp_buffer = malloc(2 * options->header.cupsBytesPerLine + 1); zpl->last_buffer = malloc(options->header.cupsBytesPerLine); zpl->last_buffer_set = 0; return (1); } // // 'lprint_zpl_rwrite()' - Write a raster line. // static int // O - 1 on success, 0 on failure lprint_zpl_rwrite( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options unsigned y, // I - Line number const unsigned char *line) // I - Line { lprint_device_t *device = job->printer->driver->device; // Output device lprint_zpl_t *zpl = job->printer->driver->job_data; // ZPL driver data unsigned i; // Looping var const unsigned char *ptr; // Pointer into buffer unsigned char *compptr; // Pointer into compression buffer #if ZPL_COMPRESSION unsigned char repeat_char; // Repeated character unsigned repeat_count; // Number of repeated characters #endif // ZPL_COMPRESSION static const unsigned char *hex = (const unsigned char *)"0123456789ABCDEF"; // Hex digits (void)y; // Determine whether this row is the same as the previous line. // If so, output a ':' and return... if (zpl->last_buffer_set && !memcmp(line, zpl->last_buffer, options->header.cupsBytesPerLine)) { lprintWriteDevice(device, ":", 1); return (1); } // Convert the line to hex digits... for (ptr = line, compptr = zpl->comp_buffer, i = options->header.cupsBytesPerLine; i > 0; i --, ptr ++) { *compptr++ = hex[*ptr >> 4]; *compptr++ = hex[*ptr & 15]; } #if ZPL_COMPRESSION // Send run-length compressed HEX data... *compptr = '\0'; // Run-length compress the graphics... for (compptr = zpl->comp_buffer + 1, repeat_char = zpl->comp_buffer[0], repeat_count = 1; *compptr; compptr ++) { if (*compptr == repeat_char) { repeat_count ++; } else { lprint_zpl_compress(device, repeat_char, repeat_count); repeat_char = *compptr; repeat_count = 1; } } if (repeat_char == '0') { // Handle 0's on the end of the line... if (repeat_count & 1) { repeat_count --; lprintPutsDevice(device, "0"); } if (repeat_count > 0) lprintPutsDevice(device, ","); } else lprint_zpl_compress(device, repeat_char, repeat_count); #else // Send uncompressed HEX data... lprintWriteDevice(device, zpl->comp_buffer, compptr - zpl->comp_buffer); #endif // ZPL_COMPRESSION // Save this line for the next round... memcpy(zpl->last_buffer, line, options->header.cupsBytesPerLine); zpl->last_buffer_set = 1; return (1); } // // 'lprint_zpl_status()' - Get current printer status. // static int // O - 1 on success, 0 on failure lprint_zpl_status( lprint_printer_t *printer) // I - Printer { (void)printer; // ZPL commands: // // print-darkness: Map 0 to 100 to ^MD command with values from -30 to 30; // print-darkness-supported=61, -default=50 // // ZPL Auto-configuration: // // ~HI returns model, firmware version, and dots-per-millimeter // ~HQES returns status information // ~HS returns other status and mode information return (1); } lprint-1.0/driver.h000066400000000000000000000166661362261677400143630ustar00rootroot00000000000000// // Driver header file for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _DRIVER_COMMON_H_ # define _DRIVER_COMMON_H_ // // Include necessary headers... // # include "common.h" # include // // Limits... // # define LPRINT_MAX_MEDIA 100 // Maximum number of media sizes # define LPRINT_MAX_RESOLUTION 4 // Maximum number of printer resolutions # define LPRINT_MAX_SOURCE 4 // Maximum number of sources/rolls # define LPRINT_MAX_SUPPLY 4 // Maximum number of supplies # define LPRINT_MAX_TYPE 4 // Maximum number of media types // // Types... // typedef struct lprint_printer_s lprint_printer_t; // Forward defined printer typedef struct lprint_job_s lprint_job_t; // Forward defined job typedef unsigned char lprint_dither_t[16]; // Dither array enum lprint_label_mode_e // Label printing modes { LPRINT_LABEL_MODE_APPLICATOR = 0x0001, LPRINT_LABEL_MODE_CUTTER = 0x0002, LPRINT_LABEL_MODE_CUTTER_DELAYED = 0x0004, LPRINT_LABEL_MODE_KIOSK = 0x0008, LPRINT_LABEL_MODE_PEEL_OFF = 0x0010, LPRINT_LABEL_MODE_PEEL_OFF_PREPEEL = 0x0020, LPRINT_LABEL_MODE_REWIND = 0x0040, LPRINT_LABEL_MODE_RFID = 0x0080, LPRINT_LABEL_MODE_TEAR_OFF = 0x0100 }; typedef unsigned short lprint_label_mode_t; enum lprint_media_tracking_e // Media tracking modes { LPRINT_MEDIA_TRACKING_CONTINUOUS = 0x0001, LPRINT_MEDIA_TRACKING_MARK = 0x0002, LPRINT_MEDIA_TRACKING_WEB = 0x0004 }; typedef unsigned short lprint_media_tracking_t; typedef struct lprint_media_col_s // Media details { int bottom_margin, // Bottom margin in hundredths of millimeters left_margin, // Left margin in hundredths of millimeters right_margin, // Right margin in hundredths of millimeters size_width, // Width in hundredths of millimeters size_length; // Height in hundredths of millimeters char size_name[64], // PWG media size name source[64]; // PWG media source name int top_margin, // Top margin in hundredths of millimeters top_offset; // Top offset in hundredths of millimeters lprint_media_tracking_t tracking; // Media tracking char type[64]; // PWG media type name } lprint_media_col_t; typedef struct lprint_options_s // Computed job options { cups_page_header2_t header; // Raster header unsigned num_pages; // Number of pages in job const lprint_dither_t *dither; // Dither array int copies; // copies lprint_media_col_t media; // media/media-col ipp_orient_t orientation_requested; // orientation-requested const char *print_color_mode, // print-color-mode *print_content_optimize; // print-content-optimize int print_darkness; // print-darkness ipp_quality_t print_quality; // print-quality int print_speed; // print-speed int printer_resolution[2]; // printer-resolution } lprint_options_t; typedef int (*lprint_printfunc_t)(lprint_job_t *job, lprint_options_t *options); // Print a job typedef int (*lprint_rendjobfunc_t)(lprint_job_t *job, lprint_options_t *options); // End a raster job typedef int (*lprint_rendpagefunc_t)(lprint_job_t *job, lprint_options_t *options, unsigned page); // End a raster job typedef int (*lprint_rstartjobfunc_t)(lprint_job_t *job, lprint_options_t *options); // Start a raster job typedef int (*lprint_rstartpagefunc_t)(lprint_job_t *job, lprint_options_t *options, unsigned page); // Start a raster page typedef int (*lprint_rwritefunc_t)(lprint_job_t *job, lprint_options_t *options, unsigned y, const unsigned char *line); // Write a line of raster graphics typedef int (*lprint_statusfunc_t)(lprint_printer_t *printer); // Update printer status typedef struct lprint_supply_s // Supply data { const char *color; // Colorant, if any const char *description; // Description int is_consumed; // Is this a supply that is consumed? int level; // Level (0-100, -1 = unknown) const char *type; // Type } lprint_supply_t; typedef struct lprint_driver_s // Driver data { pthread_rwlock_t rwlock; // Reader/writer lock char *name; // Name of driver ipp_t *attrs; // Capability attributes lprint_device_t *device; // Connection to device void *job_data; // Driver job data lprint_printfunc_t print; // Print (file) function lprint_rendjobfunc_t rendjob; // End raster job function lprint_rendpagefunc_t rendpage; // End raster page function lprint_rstartjobfunc_t rstartjob; // Start raster job function lprint_rstartpagefunc_t rstartpage; // Start raster page function lprint_rwritefunc_t rwrite; // Write raster line function lprint_statusfunc_t status; // Status function const char *format; // Printer-specific format int num_resolution, // Number of printer resolutions x_resolution[LPRINT_MAX_RESOLUTION], y_resolution[LPRINT_MAX_RESOLUTION]; // Printer resolutions int left_right, // Left and right margins in hundredths of millimeters bottom_top; // Bottom and top margins in hundredths of millimeters int num_media; // Number of supported media const char *media[LPRINT_MAX_MEDIA]; // Supported media lprint_media_col_t media_default, // Default media media_ready[LPRINT_MAX_SOURCE]; // Ready media int num_source; // Number of media sources (rolls) const char *source[LPRINT_MAX_SOURCE]; // Media sources int top_offset_supported[2]; // media-top-offset-supported (0,0 for none) lprint_media_tracking_t tracking_supported; // media-tracking-supported int num_type; // Number of media types const char *type[LPRINT_MAX_TYPE]; // Media types lprint_label_mode_t mode_configured,// label-mode-configured mode_supported; // label-mode-supported int tear_offset_configured, // label-tear-offset-configured tear_offset_supported[2]; // label-tear-offset-supported (0,0 for none) int speed_supported[2],// print-speed-supported (0,0 for none) speed_default; // print-speed-default int darkness_configured, // printer-darkness-configured darkness_supported; // printer-darkness-supported (0 for none) int num_supply; // Number of printer-supply lprint_supply_t supply[LPRINT_MAX_SUPPLY]; // printer-supply } lprint_driver_t; // // Functions... // extern lprint_driver_t *lprintCreateDriver(const char *driver_name); extern ipp_t *lprintCreateMediaCol(lprint_media_col_t *media, int db); extern void lprintDeleteDriver(lprint_driver_t *driver); extern const char * const *lprintGetDrivers(int *num_drivers); extern const char *lprintGetMakeAndModel(const char *driver_name); extern void lprintImportMediaCol(ipp_t *col, lprint_media_col_t *media); extern void lprintInitDYMO(lprint_driver_t *driver); extern void lprintInitPWG(lprint_driver_t *driver); extern void lprintInitZPL(lprint_driver_t *driver); extern const char *lprintLabelModeString(lprint_label_mode_t v); extern lprint_label_mode_t lprintLabelModeValue(const char *s); extern const char *lprintMediaTrackingString(lprint_media_tracking_t v); extern lprint_media_tracking_t lprintMediaTrackingValue(const char *s); // Future planned drivers that are not yet implemented //extern void lprintInitCPCL(lprint_driver_t *driver); //extern void lprintInitEPL1(lprint_driver_t *driver); //extern void lprintInitEPL2(lprint_driver_t *driver); //extern void lprintInitFGL(lprint_driver_t *driver); //extern void lprintInitPCL(lprint_driver_t *driver); #endif // !_DRIVER_COMMON_H_ lprint-1.0/install-sh000077500000000000000000000127041362261677400147100ustar00rootroot00000000000000#!/bin/sh # # Install a program, script, or datafile. # # Copyright 2008-2012 by Apple Inc. # # This script is not compatible with BSD (or any other) install program, as it # allows owner and group changes to fail with a warning and makes sure that the # destination directory permissions are as specified - BSD install and the # original X11 install script did not change permissions of existing # directories. It also does not support the transform options since CUPS does # not use them... # # Original script from X11R5 (mit/util/scripts/install.sh) # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # Force umask to 022... umask 022 # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" gzipprog="${GZIPPROG-gzip}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" gzipcp() { # gzipcp from to $gzipprog -9 <"$1" >"$2" } while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue ;; -d) dir_arg=true shift continue ;; -m) chmodcmd="$chmodprog $2" shift shift continue ;; -o) chowncmd="$chownprog $2" shift shift continue ;; -g) chgrpcmd="$chgrpprog $2" shift shift continue ;; -s) stripcmd="$stripprog" shift continue ;; -z) instcmd="gzipcp" shift continue ;; *) if [ x"$src" = x ]; then src="$1" else dst="$1" fi shift continue ;; esac done if [ x"$src" = x ]; then echo "install-sh: No input file specified" exit 1 fi if [ x"$dir_arg" != x ]; then dst="$src" src="" if [ -d "$dst" ]; then instcmd=: else instcmd=$mkdirprog fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ ! -f "$src" -a ! -d "$src" ]; then echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ]; then echo "install: No destination specified" exit 1 fi # If destination is a directory, append the input filename. if [ -d "$dst" ]; then dst="$dst/`basename $src`" fi fi ## this sed command emulates the dirname command dstdir="`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`" # Make sure that the destination directory exists. # This part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ]; then $doit $mkdirprog "${pathcomp}"; fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ]; then # Make a directory... $doit $instcmd $dst || exit 1 # Allow chown/chgrp to fail, but log a warning if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst || echo "warning: Unable to change owner of $dst!"; fi if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst || echo "warning: Unable to change group of $dst!"; fi if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst || exit 1; fi else # Install a file... dstfile="`basename $dst`" # Check the destination file - for libraries just use the "-x" option # to strip... case "$dstfile" in *.a | *.dylib | *.sl | *.sl.* | *.so | *.so.*) stripopt="-x" ;; *) stripopt="" ;; esac # Make a temp file name in the proper directory. dsttmp="$dstdir/#inst.$$#" # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp || exit 1 # Update permissions and strip as needed, then move to the final name. # If the chmod, strip, rm, or mv commands fail, remove the installed # file... if [ x"$stripcmd" != x ]; then $doit $stripcmd $stripopt "$dsttmp" || echo "warning: Unable to strip $dst!"; fi if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp" || echo "warning: Unable to change owner of $dst!"; fi if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp" || echo "warning: Unable to change group of $dst!"; fi trap "rm -f ${dsttmp}" 0 && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; fi && $doit $rmcmd -f "$dstdir/$dstfile" && $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" fi exit 0 lprint-1.0/lprint-add.c000066400000000000000000000251451362261677400151110ustar00rootroot00000000000000// // Add printer sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local functions... // static int get_length(const char *value); // // 'lprintAddOptions()' - Add default/Job Template attributes from options. // void lprintAddOptions( ipp_t *request, // I - IPP request int num_options, // I - Number of options cups_option_t *options) // I - Options { int is_default; // Adding xxx-default attributes? ipp_tag_t group_tag; // Group to add to const char *value; // String value int intvalue; // Integer value const char *media_source = cupsGetOption("media-source", num_options, options), *media_top_offset = cupsGetOption("media-top-offset", num_options, options), *media_tracking = cupsGetOption("media-tracking", num_options, options), *media_type = cupsGetOption("media-type", num_options, options); // media-xxx member values group_tag = ippGetOperation(request) == IPP_PRINT_JOB ? IPP_TAG_JOB : IPP_TAG_PRINTER; is_default = group_tag == IPP_TAG_PRINTER; LPRINT_DEBUG("group_tag=%s, is_default=%d\n", ippTagString(group_tag), is_default); if (is_default) { // Add Printer Description attributes... if ((value = cupsGetOption("label-mode-configured", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "label-model-configured", NULL, value); if ((value = cupsGetOption("label-tear-offset-configured", num_options, options)) != NULL) ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "label-tear-offset-configured", get_length(value)); if ((value = cupsGetOption("media-ready", num_options, options)) != NULL) { int num_values; // Number of values char *values[4], // Pointers to size strings sizes[4][256]; // Size strings if ((num_values = sscanf(value, "%255s,%255s,%255s,%255s", sizes[0], sizes[1], sizes[2], sizes[3])) > 0) { values[0] = sizes[0]; values[1] = sizes[1]; values[2] = sizes[2]; values[3] = sizes[3]; ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-ready", num_values, NULL, (const char * const *)values); } } if ((value = cupsGetOption("printer-darkness-configured", num_options, options)) != NULL) ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-darkness-configured", atoi(value)); if ((value = cupsGetOption("printer-geo-location", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-geo-location", NULL, value); if ((value = cupsGetOption("printer-location", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL, value); if ((value = cupsGetOption("printer-organization", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organization", NULL, value); if ((value = cupsGetOption("printer-organizational-unit", num_options, options)) != NULL) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organizational-unit", NULL, value); } if ((value = cupsGetOption("copies", num_options, options)) == NULL) value = cupsGetOption("copies-default", num_options, options); if (value) ippAddInteger(request, group_tag, IPP_TAG_INTEGER, is_default ? "copies-default" : "copies", atoi(value)); value = cupsGetOption("media", num_options, options); if (media_source || media_top_offset || media_tracking || media_type) { // Add media-col ipp_t *media_col = ippNew(); // media-col value pwg_media_t *pwg = pwgMediaForPWG(value); // Size if (pwg) { ipp_t *media_size = ippNew(); // media-size value ippAddInteger(media_size, IPP_TAG_JOB, IPP_TAG_INTEGER, "x-dimension", pwg->width); ippAddInteger(media_size, IPP_TAG_JOB, IPP_TAG_INTEGER, "y-dimension", pwg->length); ippAddCollection(media_col, IPP_TAG_JOB, "media-size", media_size); ippDelete(media_size); } if (media_source) ippAddString(media_col, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-source", NULL, media_source); if (media_top_offset) ippAddInteger(media_col, IPP_TAG_JOB, IPP_TAG_INTEGER, "media-top-offset", get_length(media_top_offset)); if (media_tracking) ippAddString(media_col, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-tracking", NULL, media_tracking); if (media_type) ippAddString(media_col, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, media_type); ippAddCollection(request, IPP_TAG_JOB, is_default ? "media-col-default" : "media-col", media_col); ippDelete(media_col); } else if (value) { // Add media ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, is_default ? "media-default" : "media", NULL, value); } if ((value = cupsGetOption("orientation-requested", num_options, options)) == NULL) value = cupsGetOption("orientation-requested-default", num_options, options); if (value) { if ((intvalue = ippEnumValue("orientation-requested", value)) != 0) ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "orientation-requested-default" : "orientation-requested", intvalue); else ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "orientation-requested-default" : "orientation-requested", atoi(value)); } if ((value = cupsGetOption("print-color-mode", num_options, options)) == NULL) value = cupsGetOption("print-color-mode-default", num_options, options); if (value) ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? "print-color-mode-default" : "print-color-mode", NULL, value); if ((value = cupsGetOption("print-content-optimize", num_options, options)) == NULL) value = cupsGetOption("print-content-optimize-default", num_options, options); if (value) ippAddString(request, group_tag, IPP_TAG_KEYWORD, is_default ? "print-content-optimize-mode-default" : "print-content-optimize", NULL, value); if ((value = cupsGetOption("print-darkness", num_options, options)) == NULL) value = cupsGetOption("print-darkness-default", num_options, options); if (value) ippAddInteger(request, group_tag, IPP_TAG_INTEGER, is_default ? "print-darkness-default" : "print-darkness", atoi(value)); if ((value = cupsGetOption("print-quality", num_options, options)) == NULL) value = cupsGetOption("print-quality-default", num_options, options); if (value) { if ((intvalue = ippEnumValue("print-quality", value)) != 0) ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "print-quality-default" : "print-quality", intvalue); else ippAddInteger(request, group_tag, IPP_TAG_ENUM, is_default ? "print-quality-default" : "print-quality", atoi(value)); } if ((value = cupsGetOption("print-speed", num_options, options)) == NULL) value = cupsGetOption("print-speed-default", num_options, options); if (value) ippAddInteger(request, group_tag, IPP_TAG_INTEGER, is_default ? "print-speed-default" : "print-speed", get_length(value)); if ((value = cupsGetOption("printer-resolution", num_options, options)) == NULL) value = cupsGetOption("printer-resolution-default", num_options, options); LPRINT_DEBUG("printer-resolution=%s\n", value); if (value) { int xres, yres; // Resolution values char units[32]; // Resolution units if (sscanf(value, "%dx%d%31s", &xres, &yres, units) != 3) { if (sscanf(value, "%d%31s", &xres, units) != 2) { xres = 300; strlcpy(units, "dpi", sizeof(units)); } yres = xres; } ippAddResolution(request, group_tag, is_default ? "printer-resolution-default" : "printer-resolution", !strcmp(units, "dpi") ? IPP_RES_PER_INCH : IPP_RES_PER_CM, xres, yres); } } // // 'lprintDoAdd()' - Do the add printer sub-command. // int // O - Exit status lprintDoAdd(int num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Connection to server ipp_t *request; // Create-Printer request const char *printer_uri, // Printer URI *device_uri, // Device URI *lprint_driver, // Name of driver *printer_name; // Name of printer // Get required values... device_uri = cupsGetOption("device-uri", num_options, options); lprint_driver = cupsGetOption("lprint-driver", num_options, options); printer_name = cupsGetOption("printer-name", num_options, options); if (!device_uri || !lprint_driver || !printer_name) { if (!device_uri) fputs("lprint: Missing '-v DEVICE-URI' option.\n", stderr); if (!lprint_driver) fputs("lprint: Missing '-m DRIVER' option.\n", stderr); if (!printer_name) fputs("lprint: Missing '-d PRINTER' option.\n", stderr); return (1); } // Open a connection to the server... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote server... char resource[1024]; // Resource path if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else if ((http = lprintConnect(1)) == NULL) return (1); // Send a Create-Printer request to the server... request = ippNewRequest(IPP_OP_CREATE_PRINTER); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "printer-service-type", NULL, "print"); ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL, printer_name); ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "lprint-driver", NULL, lprint_driver); ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL, device_uri); lprintAddOptions(request, num_options, options); ippDelete(cupsDoRequest(http, request, "/ipp/system")); httpClose(http); if (cupsLastError() != IPP_STATUS_OK) { fprintf(stderr, "lprint: Unable to add printer - %s\n", cupsLastErrorString()); return (1); } return (0); } // // 'get_length()' - Get a length in hundredths of millimeters. // static int // O - Length value get_length(const char *value) // I - Length string { double n; // Number char *units; // Pointer to units n = strtod(value, &units); if (units && !strcmp(units, "cm")) return ((int)(n * 1000.0)); if (units && !strcmp(units, "in")) return ((int)(n * 2540.0)); else if (units && !strcmp(units, "mm")) return ((int)(n * 100.0)); else if (units && !strcmp(units, "m")) return ((int)(n * 100000.0)); else return ((int)n); } lprint-1.0/lprint-cancel.c000066400000000000000000000046241362261677400156050ustar00rootroot00000000000000// // Cancel sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoCancel()' - Do the cancel sub-command. // int // O - Exit status lprintDoCancel( int num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name char default_printer[256], // Default printer resource[1024]; // Resource path http_t *http; // Server connection ipp_t *request; // IPP request const char *value; // Option value int job_id = 0; // job-id if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else { // Connect to/start up the server and get the destination printer... http = lprintConnect(1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = lprintGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { fputs("lprint: No default printer available.\n", stderr); httpClose(http); return (1); } } } // Figure out which job(s) to cancel... if (cupsGetOption("cancel-all", num_options, options)) { request = ippNewRequest(IPP_OP_CANCEL_MY_JOBS); } else if ((value = cupsGetOption("job-id", num_options, options)) != NULL) { request = ippNewRequest(IPP_OP_CANCEL_JOB); job_id = atoi(value); } else request = ippNewRequest(IPP_OP_CANCEL_CURRENT_JOB); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); if (job_id) ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippDelete(cupsDoRequest(http, request, resource)); httpClose(http); if (cupsLastError() != IPP_STATUS_OK) { fprintf(stderr, "lprint: Unable to cancel - %s\n", cupsLastErrorString()); return (1); } return (0); } lprint-1.0/lprint-default.c000066400000000000000000000102461362261677400160010ustar00rootroot00000000000000// // Set default printer sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoDefault()' - Do the default printer sub-command. // int // O - Exit status lprintDoDefault( int num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response char resource[1024]; // Resource path int printer_id; // printer-id value // Connect to/start up the server and get the destination printer... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote server... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else if ((http = lprintConnect(1)) == NULL) return (1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { char default_printer[256]; // Default printer if (lprintGetDefaultPrinter(http, default_printer, sizeof(default_printer))) puts(default_printer); httpClose(http); return (0); } // OK, setting the default printer so get the printer-id for it... request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); if (printer_uri) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "printer-id"); response = cupsDoRequest(http, request, resource); printer_id = ippGetInteger(ippFindAttribute(response, "printer-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (printer_id == 0) { fprintf(stderr, "lprint: Unable to get information for '%s' - %s\n", printer_name, cupsLastErrorString()); httpClose(http); return (1); } // Now that we have the printer-id, set the system-default-printer-id // attribute for the system service... request = ippNewRequest(IPP_OP_SET_SYSTEM_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddInteger(request, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-default-printer-id", printer_id); ippDelete(cupsDoRequest(http, request, "/ipp/system")); httpClose(http); if (cupsLastError() != IPP_STATUS_OK) { fprintf(stderr, "lprint: Unable to set default printer - %s\n", cupsLastErrorString()); return (1); } return (0); } // // 'lprintGetDefaultPrinter()' - Get the default printer. // // Note: We can't use cupsGetDefault2() because it uses the defaults set via // CUPS environment variables and the lpoptions command, too. // char * // O - Default printer or `NULL` for none lprintGetDefaultPrinter( http_t *http, // I - HTTP connection char *buffer, // I - Buffer for printer name size_t bufsize) // I - Size of buffer { ipp_t *request, // IPP request *response; // IPP response const char *printer_name; // Printer name // Ask the server for its default printer; can't use cupsGetDefault2 // because it will return a default printer for CUPS... request = ippNewRequest(IPP_OP_CUPS_GET_DEFAULT); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "printer-name"); response = cupsDoRequest(http, request, "/ipp/system"); if ((printer_name = ippGetString(ippFindAttribute(response, "printer-name", IPP_TAG_NAME), 0, NULL)) != NULL) strlcpy(buffer, printer_name, bufsize); else *buffer = '\0'; ippDelete(response); return (*buffer ? buffer : NULL); } lprint-1.0/lprint-delete.c000066400000000000000000000054331362261677400156210ustar00rootroot00000000000000// // Delete printer sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoDelete()' - Do the delete printer sub-command. // int // O - Exit status lprintDoDelete( int num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response char resource[1024]; // Resource path int printer_id; // printer-id value // Connect to/start up the server and get the destination printer... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote server... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else if ((http = lprintConnect(1)) == NULL) return (1); else if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { fputs("lprint: No printer specified.\n", stderr); httpClose(http); return (1); } // Get the printer-id for the printer we are deleting... request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); if (printer_uri) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", NULL, "printer-id"); response = cupsDoRequest(http, request, resource); printer_id = ippGetInteger(ippFindAttribute(response, "printer-id", IPP_TAG_INTEGER), 0); ippDelete(response); if (printer_id == 0) { fprintf(stderr, "lprint: Unable to get information for '%s' - %s\n", printer_name, cupsLastErrorString()); httpClose(http); return (1); } // Now that we have the printer-id, delete it from the system service... request = ippNewRequest(IPP_OP_DELETE_PRINTER); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "printer-id", printer_id); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippDelete(cupsDoRequest(http, request, "/ipp/system")); httpClose(http); if (cupsLastError() != IPP_STATUS_OK) { fprintf(stderr, "lprint: Unable to delete printer - %s\n", cupsLastErrorString()); return (1); } return (0); } lprint-1.0/lprint-devices.c000066400000000000000000000025051362261677400157760ustar00rootroot00000000000000// // Devices sub-command for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local functions... // static void lprint_error_device(const char *message, void *err_data); static int lprint_print_device(const char *device_uri, const void *user_data); // // 'lprintDoDevices()' - Do the devices sub-command. // int // O - Exit status lprintDoDevices( int num_options, // I - Number of options cups_option_t *options) // I - Options { (void)num_options; (void)options; lprintListDevices(lprint_print_device, NULL, lprint_error_device, NULL); return (0); } // // 'lprint_error_device()' - Display an error message to the standard error. // static void lprint_error_device( const char *message, // I - Message void *err_data) // I - Callback data (not used) { (void)err_data; fprintf(stderr, "lprint: %s\n", message); } // // 'lprint_print_device()' - Print a device URI. // static int // O - 0 to keep going lprint_print_device( const char *device_uri, // I - Device URI const void *user_data) // I - User data (not used) { (void)user_data; puts(device_uri); return (0); } lprint-1.0/lprint-drivers.c000066400000000000000000000014451362261677400160340ustar00rootroot00000000000000// // Driver list sub-command for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoDrivers()' - Do the drivers sub-command. // int // O - Exit status lprintDoDrivers( int num_options, // I - Number of options cups_option_t *options) // I - Options { (void)num_options; (void)options; int i, // Looping var num_drivers; // Number of drivers const char * const *drivers; // Array of drivers drivers = lprintGetDrivers(&num_drivers); for (i = 0; i < num_drivers; i ++) printf("%-32s%s\n", drivers[i], lprintGetMakeAndModel(drivers[i])); return (0); } lprint-1.0/lprint-jobs.c000066400000000000000000000060461362261677400153150ustar00rootroot00000000000000// // Jobs sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoJobs()' - Do the jobs sub-command. // int // O - Exit status lprintDoJobs(int num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name char default_printer[256], // Default printer resource[1024]; // Resource path http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response ipp_attribute_t *attr; // Current attribute const char *attrname; // Attribute name int job_id, // Current job-id job_state; // Current job-state const char *job_name, // Current job-name *job_user; // Current job-originating-user-name if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else { // Connect to/start up the server and get the destination printer... http = lprintConnect(1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = lprintGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { fputs("lprint: No default printer available.\n", stderr); httpClose(http); return (1); } } } // Send a Get-Jobs request... request = ippNewRequest(IPP_OP_GET_JOBS); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-joba", NULL, "all"); response = cupsDoRequest(http, request, resource); for (attr = ippFirstAttribute(response); attr; attr = ippNextAttribute(response)) { if (ippGetGroupTag(attr) == IPP_TAG_OPERATION) continue; job_id = 0; job_state = IPP_JSTATE_PENDING; job_name = "(none)"; job_user = "(unknown)"; while (ippGetGroupTag(attr) == IPP_TAG_JOB) { attrname = ippGetName(attr); if (!strcmp(attrname, "job-id")) job_id = ippGetInteger(attr, 0); else if (!strcmp(attrname, "job-name")) job_name = ippGetString(attr, 0, NULL); else if (!strcmp(attrname, "job-originating-user-name")) job_user = ippGetString(attr, 0, NULL); else if (!strcmp(attrname, "job-state")) job_state = ippGetInteger(attr, 0); attr = ippNextAttribute(response); } printf("%d %-12s %-16s %s\n", job_id, ippEnumString("job-state", job_state), job_user, job_name); } ippDelete(response); httpClose(http); return (0); } lprint-1.0/lprint-modify.c000066400000000000000000000034421362261677400156440ustar00rootroot00000000000000// // Modify printer sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoModify()' - Do the modify printer sub-command. // int // O - Exit status lprintDoModify( int num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Connection to server ipp_t *request; // Create-Printer request const char *printer_uri, // Printer URI *printer_name; // Name of printer char resource[1024]; // Resource path // Open a connection to the server... if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote server... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else if ((http = lprintConnect(1)) == NULL) { return (1); } else if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { fputs("lprint: Missing '-d PRINTER' option.\n", stderr); return (1); } // Send a Set-Printer-Attributes request to the server... request = ippNewRequest(IPP_OP_SET_PRINTER_ATTRIBUTES); if (printer_uri) ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); lprintAddOptions(request, num_options, options); ippDelete(cupsDoRequest(http, request, resource)); httpClose(http); if (cupsLastError() != IPP_STATUS_OK) { fprintf(stderr, "lprint: Unable to modify printer - %s\n", cupsLastErrorString()); return (1); } return (0); } lprint-1.0/lprint-options.c000066400000000000000000000173271362261677400160570ustar00rootroot00000000000000// // Options sub-command for LPrint, a Label Printer Application // // Copyright © 2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local functions... // static char *get_value(ipp_attribute_t *attr, const char *name, int element, char *buffer, size_t bufsize); static void print_option(ipp_t *response, const char *name); // // 'lprintDoOptions()' - Do the options sub-command. // int // O - Exit status lprintDoOptions( int num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name; // Printer name char default_printer[256]; // Default printer name http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response char resource[1024]; // Resource path if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else { // Connect to/start up the server and get the destination printer... http = lprintConnect(1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = lprintGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { fputs("lprint: No default printer available.\n", stderr); httpClose(http); return (1); } } } // Get the xxx-supported and xxx-default attributes request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); response = cupsDoRequest(http, request, resource); if (cupsLastError() != IPP_STATUS_OK) { fprintf(stderr, "lprint: Unable to get printer options - %s\n", cupsLastErrorString()); ippDelete(response); httpClose(http); return (1); } puts("Print job options:"); puts(" -n COPIES"); print_option(response, "media"); print_option(response, "media-source"); print_option(response, "media-top-offset"); print_option(response, "media-tracking"); print_option(response, "media-type"); print_option(response, "orientation-requested"); print_option(response, "print-color-mode"); print_option(response, "print-content-optimize"); if (ippFindAttribute(response, "print-darkness-supported", IPP_TAG_ZERO)) puts(" -o print-darkness=-100 to 100"); print_option(response, "print-quality"); print_option(response, "print-speed"); print_option(response, "printer-resolution"); puts(" -t 'TITLE'"); puts("\nPrinter options:"); print_option(response, "label-mode"); print_option(response, "label-tear-offset"); if (ippFindAttribute(response, "printer-darkness-supported", IPP_TAG_ZERO)) puts(" -o printer-darkness=0 to 100"); puts(" -o printer-geo-location='geo:LATITUDE,LONGITUDE'"); puts(" -o printer-location='LOCATION'"); puts(" -o printer-organization='ORGANIZATION'"); puts(" -o printer-organizational-unit='UNIT/SECTION'"); ippDelete(response); httpClose(http); return (0); } // // 'get_value() ' - Get the string representation of an attribute value. // static char * // O - String value get_value(ipp_attribute_t *attr, // I - Attribute const char *name, // I - Base name of attribute int element, // I - Value index char *buffer, // I - String buffer size_t bufsize) // I - Size of string buffer { const char *value; // String value int intvalue; // Integer value int lower, // Lower range value upper; // Upper range value int xres, // X resolution yres; // Y resolution ipp_res_t units; // Resolution units *buffer = '\0'; switch (ippGetValueTag(attr)) { default : case IPP_TAG_KEYWORD : if ((value = ippGetString(attr, element, NULL)) != NULL) { if (!strcmp(name, "media")) { pwg_media_t *pwg = pwgMediaForPWG(value); // Media size if ((pwg->width % 100) == 0) snprintf(buffer, bufsize, "%s (%dx%dmm or %.2gx%.2gin)", value, pwg->width / 100, pwg->length / 100, pwg->width / 2540.0, pwg->length / 2540.0); else snprintf(buffer, bufsize, "%s (%.2gx%.2gin or %dx%dmm)", value, pwg->width / 2540.0, pwg->length / 2540.0, pwg->width / 100, pwg->length / 100); } else { strlcpy(buffer, value, bufsize); } } break; case IPP_TAG_ENUM : strlcpy(buffer, ippEnumString(name, ippGetInteger(attr, element)), bufsize); break; case IPP_TAG_INTEGER : intvalue = ippGetInteger(attr, element); if (!strcmp(name, "label-tear-offset") || !strcmp(name, "media-top-offset") || !strcmp(name, "print-speed")) { if ((intvalue % 635) == 0) snprintf(buffer, bufsize, "%.2gin", intvalue / 2540.0); else snprintf(buffer, bufsize, "%.2gmm", intvalue * 0.01); } else snprintf(buffer, bufsize, "%d", intvalue); break; case IPP_TAG_RANGE : lower = ippGetRange(attr, element, &upper); if (!strcmp(name, "label-tear-offset") || !strcmp(name, "media-top-offset") || !strcmp(name, "print-speed")) { if ((upper % 635) == 0) snprintf(buffer, bufsize, "%.2gin to %.2gin", lower / 2540.0, upper / 2540.0); else snprintf(buffer, bufsize, "%.2gmm to %.2gmm", lower * 0.01, upper * 0.01); } else snprintf(buffer, bufsize, "%d to %d", lower, upper); break; case IPP_TAG_RESOLUTION : xres = ippGetResolution(attr, element, &yres, &units); if (xres == yres) snprintf(buffer, bufsize, "%d%s", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); else snprintf(buffer, bufsize, "%dx%d%s", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm"); break; } return (buffer); } // // 'print_option()' - Print the supported and default value for an option. // static void print_option(ipp_t *response, // I - Get-Printer-Attributes response const char *name) // I - Attribute name { char defname[256], // xxx-default/xxx-configured name supname[256]; // xxx-supported name ipp_attribute_t *defattr, // xxx-default/xxx-configured attribute *supattr; // xxx-supported attribute int i, // Looping var count; // Number of values char defvalue[256], // xxx-default/xxx-configured value supvalue[256]; // xxx-supported value // Get the default and supported attributes... snprintf(supname, sizeof(supname), "%s-supported", name); if ((supattr = ippFindAttribute(response, supname, IPP_TAG_ZERO)) == NULL) return; if (!strncmp(name, "media-", 6)) snprintf(defname, sizeof(defname), "media-col-default/%s", name); else snprintf(defname, sizeof(defname), "%s-default", name); if ((defattr = ippFindAttribute(response, defname, IPP_TAG_ZERO)) == NULL) { snprintf(defname, sizeof(defname), "%s-configured", name); defattr = ippFindAttribute(response, defname, IPP_TAG_ZERO); } get_value(defattr, name, 0, defvalue, sizeof(defvalue)); // Show the option with its values... if (defvalue[0]) printf(" -o %s=%s (default)\n", name, defvalue); for (i = 0, count = ippGetCount(supattr); i < count; i ++) { if (strcmp(defvalue, get_value(supattr, name, i, supvalue, sizeof(supvalue)))) printf(" -o %s=%s\n", name, supvalue); } } lprint-1.0/lprint-printers.c000066400000000000000000000024101362261677400162150ustar00rootroot00000000000000// // Printers sub-command for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoPrinters()' - Do the printers sub-command. // int // O - Exit status lprintDoPrinters( int num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response ipp_attribute_t *attr; // Current attribute // Connect to/start up the server and get the list of printers... http = lprintConnect(1); request = ippNewRequest(IPP_OP_GET_PRINTERS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); response = cupsDoRequest(http, request, "/ipp/system"); for (attr = ippFindAttribute(response, "printer-name", IPP_TAG_NAME); attr; attr = ippFindNextAttribute(response, "printer-name", IPP_TAG_NAME)) puts(ippGetString(attr, 0, NULL)); ippDelete(response); httpClose(http); return (0); } lprint-1.0/lprint-server.c000066400000000000000000000041751362261677400156670ustar00rootroot00000000000000// // Server sub-command for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include // // 'lprintDoServer()' - Do the server sub-command. // int // O - Exit status lprintDoServer( int num_options, // I - Number of options cups_option_t *options) // I - Options { lprint_system_t *system; // System object const char *val; // Option value lprint_loglevel_t loglevel; // Log level const char *logfile, // Log file, if any *hostname; // Hostname, if any int port; // Port number, if any // Get config options... if ((val = cupsGetOption("log-level", num_options, options)) != NULL) { if (!strcmp(val, "fatal")) loglevel = LPRINT_LOGLEVEL_FATAL; else if (!strcmp(val, "error")) loglevel = LPRINT_LOGLEVEL_ERROR; else if (!strcmp(val, "warn")) loglevel = LPRINT_LOGLEVEL_WARN; else if (!strcmp(val, "info")) loglevel = LPRINT_LOGLEVEL_INFO; else if (!strcmp(val, "debug")) loglevel = LPRINT_LOGLEVEL_DEBUG; else { fprintf(stderr, "lprint: Bad log-level value '%s'.\n", val); return (1); } } else loglevel = LPRINT_LOGLEVEL_UNSPEC; logfile = cupsGetOption("log-file", num_options, options); hostname = cupsGetOption("server-name", num_options, options); if ((val = cupsGetOption("server-port", num_options, options)) != NULL) { if (!isdigit(*val & 255)) { fprintf(stderr, "lprint: Bad server-port value '%s'.\n", val); return (1); } else port = atoi(val); } else port = 0; // Create the system object and run it... if ((system = lprintCreateSystem(hostname, port, hostname ? "_print,_universal" : NULL, cupsGetOption("spool-directory", num_options, options), logfile, loglevel, cupsGetOption("auth-service", num_options, options), cupsGetOption("admin-group", num_options, options))) == NULL) return (1); lprintRunSystem(system); lprintDeleteSystem(system); return (0); } lprint-1.0/lprint-shutdown.c000066400000000000000000000022701362261677400162260ustar00rootroot00000000000000// // Shutdown sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoShutdown()' - Do the shutdown sub-command. // int // O - Exit status lprintDoShutdown( int num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // HTTP connection ipp_t *request; // IPP request // Try connecting to the server... if ((http = lprintConnect(0)) == NULL) { fputs("lprint: Server is not running.\n", stderr); return (1); } request = ippNewRequest(IPP_OP_SHUTDOWN_ALL_PRINTERS); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippDelete(cupsDoRequest(http, request, "/ipp/system")); if (cupsLastError() != IPP_STATUS_OK) { fprintf(stderr, "lprint: Unable to shutdown server - %s\n", cupsLastErrorString()); return (1); } return (0); } lprint-1.0/lprint-status.c000066400000000000000000000100261362261677400156740ustar00rootroot00000000000000// // Status sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // 'lprintDoStatus()' - Do the status sub-command. // int // O - Exit status lprintDoStatus( int num_options, // I - Number of options cups_option_t *options) // I - Options { http_t *http; // HTTP connection const char *printer_uri, // Printer URI *printer_name; // Printer name char resource[1024]; // Resource path ipp_t *request, // IPP request *response; // IPP response int i, // Looping var count, // Number of reasons state; // *-state value ipp_attribute_t *state_reasons; // *-state-reasons attribute time_t state_time; // *-state-change-time value const char *reason; // *-state-reasons value static const char * const states[] = // *-state strings { "idle", "processing jobs", "stopped" }; static const char * const pattrs[] = { // Requested printer attributes "printer-state", "printer-state-change-date-time", "printer-state-reasons" }; static const char * const sysattrs[] = { // Requested system attributes "system-state", "system-state-change-date-time", "system-state-reasons" }; if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else { // Try connecting to the server... if ((http = lprintConnect(0)) == NULL) { puts("Not running."); return (0); } } if (printer_uri || (printer_name = cupsGetOption("printer-name", num_options, options)) != NULL) { // Get the printer status request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs); response = cupsDoRequest(http, request, resource); state = ippGetInteger(ippFindAttribute(response, "printer-state", IPP_TAG_ENUM), 0); state_time = ippDateToTime(ippGetDate(ippFindAttribute(response, "printer-state-change-date-time", IPP_TAG_DATE), 0)); state_reasons = ippFindAttribute(response, "printer-state-reasons", IPP_TAG_KEYWORD); } else { request = ippNewRequest(IPP_OP_GET_SYSTEM_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "system-uri", NULL, "ipp://localhost/ipp/system"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(sysattrs) / sizeof(sysattrs[0])), NULL, sysattrs); response = cupsDoRequest(http, request, "/ipp/system"); state = ippGetInteger(ippFindAttribute(response, "system-state", IPP_TAG_ENUM), 0); state_time = ippDateToTime(ippGetDate(ippFindAttribute(response, "system-state-change-date-time", IPP_TAG_DATE), 0)); state_reasons = ippFindAttribute(response, "system-state-reasons", IPP_TAG_KEYWORD); } if (state < IPP_PSTATE_IDLE) state = IPP_PSTATE_IDLE; else if (state > IPP_PSTATE_STOPPED) state = IPP_PSTATE_STOPPED; printf("Running, %s since %s\n", states[state - IPP_PSTATE_IDLE], httpGetDateString(state_time)); if (state_reasons) { for (i = 0, count = ippGetCount(state_reasons); i < count; i ++) { reason = ippGetString(state_reasons, i, NULL); if (strcmp(reason, "none")) puts(reason); } } ippDelete(response); return (0); } lprint-1.0/lprint-submit.c000066400000000000000000000122561362261677400156630ustar00rootroot00000000000000// // Submit sub-command for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local functions... // static char *copy_stdin(char *name, size_t namesize); // // 'lprintDoSubmit()' - Do the submit sub-command. // int // O - Exit status lprintDoSubmit( int num_files, // I - Number of files char **files, // I - Files int num_options, // I - Number of options cups_option_t *options) // I - Options { const char *printer_uri, // Printer URI *printer_name, // Printer name *filename, // Current print filename *document_format, // Document format *document_name, // Document name *job_name; // Job name http_t *http; // Server connection ipp_t *request, // IPP request *response; // IPP response char default_printer[256], // Default printer name resource[1024], // Resource path tempfile[1024]; // Temporary file int i; // Looping var char *stdin_file; // Dummy filename for passive stdin jobs ipp_attribute_t *job_id; // job-id for created job // If there are no input files and stdin is not a TTY, treat that as an // implicit request to print from stdin... if (num_files == 0 && !isatty(0)) { stdin_file = (char *)"-"; files = &stdin_file; num_files = 1; } if (num_files == 0) { fputs("lprint: No files to print.\n", stderr); return (1); } if ((printer_uri = cupsGetOption("printer-uri", num_options, options)) != NULL) { // Connect to the remote printer... if ((http = lprintConnectURI(printer_uri, resource, sizeof(resource))) == NULL) return (1); } else { // Connect to/start up the server and get the destination printer... http = lprintConnect(1); if ((printer_name = cupsGetOption("printer-name", num_options, options)) == NULL) { if ((printer_name = lprintGetDefaultPrinter(http, default_printer, sizeof(default_printer))) == NULL) { fputs("lprint: No default printer available.\n", stderr); httpClose(http); return (1); } } } // Loop through the print files job_name = cupsGetOption("job-name", num_options, options); document_format = cupsGetOption("document-format", num_options, options); for (i = 0; i < num_files; i ++) { // Get the current print file... if (!strcmp(files[i], "-")) { if (!copy_stdin(tempfile, sizeof(tempfile))) break; filename = tempfile; document_name = "(stdin)"; } else { filename = files[i]; if ((document_name = strrchr(filename, '/')) != NULL) document_name ++; else document_name = filename; } // Send a Print-Job request... request = ippNewRequest(IPP_OP_PRINT_JOB); if (printer_uri) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); else lprintAddPrinterURI(request, printer_name, resource, sizeof(resource)); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser()); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, job_name ? job_name : document_name); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name", NULL, document_name); if (document_format) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, document_format); lprintAddOptions(request, num_options, options); response = cupsDoFileRequest(http, request, resource, filename); if ((job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL) { fprintf(stderr, "lprint: Unable to print '%s' - %s\n", filename, cupsLastErrorString()); ippDelete(response); break; } if (printer_uri) printf("%d\n", ippGetInteger(job_id, 0)); else printf("%s-%d\n", printer_name, ippGetInteger(job_id, 0)); ippDelete(response); if (filename == tempfile) unlink(tempfile); } httpClose(http); return (i < num_files); } // // 'copy_stdin()' - Copy print data from the standard input... // static char * // O - Temporary filename or `NULL` on error copy_stdin(char *name, // I - Filename buffer size_t namesize) // I - Size of filename buffer { int tempfd; // Temporary file descriptor size_t total = 0; // Total bytes read/written ssize_t bytes; // Number of bytes read/written char buffer[65536]; // Copy buffer if ((tempfd = cupsTempFd(name, (int)namesize)) < 0) { perror("lprint: Unable to create temporary file"); return (NULL); } while ((bytes = read(0, buffer, sizeof(buffer))) > 0) { if (write(tempfd, buffer, (size_t)bytes) < 0) { perror("lprint: Unable to write to temporary file"); close(tempfd); unlink(name); *name = '\0'; return (NULL); } total += (size_t)bytes; } close(tempfd); if (total == 0) { fputs("lprint: No print data received on the standard input.\n", stderr); unlink(name); *name = '\0'; return (NULL); } return (name); } lprint-1.0/lprint.c000066400000000000000000000315361362261677400143640ustar00rootroot00000000000000// // Main entry for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #define _LPRINT_C_ #include "lprint.h" #include // // Local globals... // static char *lprint_path = NULL; // Path to self // // Local functions... // static void usage(int status) LPRINT_NORETURN; // // 'main()' - Main entry for LPrint. // int // O - Exit status main(int argc, // I - Number of command-line arguments char *argv[]) // I - Command-line arguments { int i, j; // Looping vars const char *opt, // Current option character *subcommand = NULL; // Sub-command name int num_files = 0; // Number of files char *files[1000]; // Files int num_options = 0; // Number of options cups_option_t *options = NULL; // Options static const char * const subcommands[] = { // List of sub-commands "add", "cancel", "default", "delete", "devices", "drivers", "jobs", "modify", "options", "printers", "server", "shutdown", "status", "submit" }; lprint_path = argv[0]; for (i = 1; i < argc; i ++) { if (!strcmp(argv[i], "--help")) { usage(0); } else if (!strcmp(argv[i], "--version")) { puts(LPRINT_VERSION); return (0); } else if (!strcmp(argv[i], "--")) { // Filename follows i ++; if (i >= argc) { fputs("lprint: Missing filename after '--'.\n", stderr); usage(1); } else if (num_files >= (int)(sizeof(files) / sizeof(files[0]))) { fputs("lprint: Too many files.\n", stderr); return (1); } files[num_files ++] = argv[i]; } else if (!strncmp(argv[i], "--", 2)) { fprintf(stderr, "lprint: Unknown option '%s'.\n", argv[i]); usage(1); } else if (!strcmp(argv[i], "-") || argv[i][0] != '-') { for (j = 0; j < (int)(sizeof(subcommands) / sizeof(subcommands[0])); j ++) { if (!strcmp(argv[i], subcommands[j])) { subcommand = argv[i]; break; } } if (j >= (int)(sizeof(subcommands) / sizeof(subcommands[0]))) { if (num_files >= (int)(sizeof(files) / sizeof(files[0]))) { fputs("lprint: Too many files.\n", stderr); return (1); } files[num_files ++] = argv[i]; } } else { for (opt = argv[i] + 1; *opt; opt ++) { switch (*opt) { case 'a' : // All num_options = cupsAddOption("cancel-all", "true", num_options, &options); break; case 'd' : // printer name i ++; if (i >= argc) { fputs("lprint: Missing printer name.\n", stderr); usage(1); } num_options = cupsAddOption("printer-name", argv[i], num_options, &options); break; case 'j' : // job ID i ++; if (i >= argc) { fputs("lprint: Missing job ID.\n", stderr); usage(1); } num_options = cupsAddOption("job-id", argv[i], num_options, &options); break; case 'm' : // driver name i ++; if (i >= argc) { fputs("lprint: Missing driver name.\n", stderr); usage(1); } num_options = cupsAddOption("lprint-driver", argv[i], num_options, &options); break; case 'n' : // copies i ++; if (i >= argc) { fputs("lprint: Missing copy count.\n", stderr); usage(1); } num_options = cupsAddOption("copies", argv[i], num_options, &options); break; case 'o' : // name=value i ++; if (i >= argc) { fputs("lprint: Missing option.\n", stderr); usage(1); } num_options = cupsParseOptions(argv[i], num_options, &options); break; case 't' : // title i ++; if (i >= argc) { fputs("lprint: Missing title.\n", stderr); usage(1); } num_options = cupsAddOption("job-name", argv[i], num_options, &options); break; case 'u' : // printer-uri i ++; if (i >= argc) { fputs("lprint: Missing printer URI.\n", stderr); usage(1); } num_options = cupsAddOption("printer-uri", argv[i], num_options, &options); break; case 'v' : // device-uri i ++; if (i >= argc) { fputs("lprint: Missing device URI.\n", stderr); usage(1); } num_options = cupsAddOption("device-uri", argv[i], num_options, &options); break; default : fprintf(stderr, "lprint: Unknown option '-%c'.\n", *opt); usage(1); } } } } #ifdef DEBUG LPRINT_DEBUG("subcommand='%s'\n", subcommand); LPRINT_DEBUG("num_options=%d\n", num_options); for (i = 0; i < num_options; i ++) LPRINT_DEBUG("options[%d].name='%s', value='%s'\n", i, options[i].name, options[i].value); LPRINT_DEBUG("num_files=%d\n", num_files); for (i = 0; i < num_files; i ++) LPRINT_DEBUG("files[%d]='%s'\n", i, files[i]); #endif // DEBUG if (!subcommand || !strcmp(subcommand, "submit")) { return (lprintDoSubmit(num_files, files, num_options, options)); } else if (num_files > 0) { fprintf(stderr, "lprint: Sub-command '%s' does not accept files.\n", subcommand); usage(1); } else if (!strcmp(subcommand, "add")) return (lprintDoAdd(num_options, options)); else if (!strcmp(subcommand, "cancel")) return (lprintDoCancel(num_options, options)); else if (!strcmp(subcommand, "default")) return (lprintDoDefault(num_options, options)); else if (!strcmp(subcommand, "delete")) return (lprintDoDelete(num_options, options)); else if (!strcmp(subcommand, "devices")) return (lprintDoDevices(num_options, options)); else if (!strcmp(subcommand, "drivers")) return (lprintDoDrivers(num_options, options)); else if (!strcmp(subcommand, "jobs")) return (lprintDoJobs(num_options, options)); else if (!strcmp(subcommand, "modify")) return (lprintDoModify(num_options, options)); else if (!strcmp(subcommand, "options")) return (lprintDoOptions(num_options, options)); else if (!strcmp(subcommand, "printers")) return (lprintDoPrinters(num_options, options)); else if (!strcmp(subcommand, "server")) return (lprintDoServer(num_options, options)); else if (!strcmp(subcommand, "shutdown")) return (lprintDoShutdown(num_options, options)); else if (!strcmp(subcommand, "status")) return (lprintDoStatus(num_options, options)); else { fprintf(stderr, "lprint: Unhandled sub-command '%s'.\n", subcommand); usage(1); } } // // 'lprintAddPrinterURI()' - Add the printer-uri attribute and return a resource path. // void lprintAddPrinterURI( ipp_t *request, // I - IPP request const char *printer_name, // I - Printer name char *resource, // I - Resource path buffer size_t rsize) // I - Size of buffer { char uri[1024]; // printer-uri value snprintf(resource, rsize, "/ipp/print/%s", printer_name); httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, "localhost", 0, resource); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); } // // 'lprintConnect()' - Connect to the local server. // http_t * // O - HTTP connection lprintConnect(int auto_start) // I - 1 to start server if not running { http_t *http; // HTTP connection char sockname[1024]; // Socket filename // See if the server is running... http = httpConnect2(lprintGetServerPath(sockname, sizeof(sockname)), 0, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); if (!http && auto_start) { // Nope, start it now... pid_t server_pid; // Server process ID posix_spawnattr_t server_attrs; // Server process attributes char * const server_argv[] = // Server command-line { lprint_path, "server", NULL }; posix_spawnattr_init(&server_attrs); posix_spawnattr_setpgroup(&server_attrs, 0); if (posix_spawn(&server_pid, lprint_path, NULL, &server_attrs, server_argv, environ)) { perror("Unable to start lprint server"); posix_spawnattr_destroy(&server_attrs); return (NULL); } posix_spawnattr_destroy(&server_attrs); // Wait for it to start... while (access(lprintGetServerPath(sockname, sizeof(sockname)), 0)) usleep(250000); http = httpConnect2(sockname, 0, NULL, AF_UNSPEC, HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL); if (!http) fprintf(stderr, "lprint: Unable to connect to server - %s\n", cupsLastErrorString()); } return (http); } // // 'lprintConnectURI()' - Connect to an IPP printer directly. // http_t * // O - HTTP connection or `NULL` on error lprintConnectURI( const char *printer_uri, // I - Printer URI char *resource, // I - Resource path buffer size_t rsize) // I - Size of buffer { char scheme[32], // Scheme (ipp or ipps) userpass[256], // Username/password (unused) hostname[256]; // Hostname int port; // Port number http_encryption_t encryption; // Type of encryption to use http_t *http; // HTTP connection // First extract the components of the URI... if (httpSeparateURI(HTTP_URI_CODING_ALL, printer_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, resource, (int)rsize) < HTTP_URI_STATUS_OK) { fprintf(stderr, "lprint: Bad printer URI '%s'.\n", printer_uri); return (NULL); } if (strcmp(scheme, "ipp") && strcmp(scheme, "ipps")) { fprintf(stderr, "lprint: Unsupported URI scheme '%s'.\n", scheme); return (NULL); } if (userpass[0]) fputs("lprint: User credentials are not supported in URIs.\n", stderr); if (!strcmp(scheme, "ipps") || port == 443) encryption = HTTP_ENCRYPTION_ALWAYS; else encryption = HTTP_ENCRYPTION_IF_REQUESTED; if ((http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, 1, 30000, NULL)) == NULL) fprintf(stderr, "lprint: Unable to connect to printer at '%s' - %s\n", printer_uri, cupsLastErrorString()); return (http); } // // 'lprintGetServerPath()' - Get the UNIX domain socket for the server. // char * // O - Socket filename lprintGetServerPath(char *buffer, // I - Buffer for filenaem size_t bufsize) // I - Size of buffer { const char *tmpdir = getenv("TMPDIR"); // Temporary directory #ifdef __APPLE__ if (!tmpdir) tmpdir = "/private/tmp"; #else if (!tmpdir) tmpdir = "/tmp"; #endif // __APPLE__ snprintf(buffer, bufsize, "%s/lprint%d.sock", tmpdir, (int)getuid()); return (buffer); } // // 'usage()' - Show program usage. // static void usage(int status) // O - Exit status { FILE *fp = status ? stderr : stdout; // Where to send message fputs("Usage: lprint SUB-COMMAND [OPTIONS] [FILENAME]\n", fp); fputs(" lprint [OPTIONS] [FILENAME]\n", fp); fputs(" lprint [OPTIONS] -\n", fp); fputs("\n", fp); fputs("Sub-commands:\n", fp); fputs(" add PRINTER Add a printer.\n", fp); fputs(" cancel Cancel one or more jobs.\n", fp); fputs(" default Set the default printer.\n", fp); fputs(" delete Delete a printer.\n", fp); fputs(" devices List devices.\n", fp); fputs(" drivers List drivers.\n", fp); fputs(" jobs List jobs.\n", fp); fputs(" modify Modify a printer.\n", fp); fputs(" options List printer options.\n", fp); fputs(" printers List printers.\n", fp); fputs(" server Run a server.\n", fp); fputs(" shutdown Shutdown a running server.\n", fp); fputs(" status Show server/printer/job status.\n", fp); fputs(" submit Submit a file for printing.\n", fp); fputs("\n", fp); fputs("Options:\n", fp); fputs(" -a Cancel all jobs (cancel).\n", fp); fputs(" -d PRINTER Specify printer.\n", fp); fputs(" -j JOB-ID Specify job ID (cancel).\n", fp); fputs(" -m DRIVER-NAME Specify driver (add/modify).\n", fp); fputs(" -n COPIES Specify number of copies (submit).\n", fp); fputs(" -o NAME=VALUE Specify option (add,modify,server,submit).\n", fp); fputs(" -u URI Specify ipp: or ipps: printer/server.\n", fp); fputs(" -v DEVICE-URI Specify socket: or usb: device (add/modify).\n", fp); exit(status); } lprint-1.0/lprint.h000066400000000000000000000272501362261677400143670ustar00rootroot00000000000000// // Header file for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // #ifndef _LPRINT_H_ # define _LPRINT_H_ // // Include necessary headers... // # include "device.h" # include "driver.h" # include # include # include # include # include extern char **environ; # ifdef HAVE_DNSSD # include # elif defined(HAVE_AVAHI) # include # include # include # include # endif // HAVE_DNSSD // // New operations/tags defined in CUPS 2.3 and later... // # if CUPS_VERSION_MAJOR == 2 && CUPS_VERSION_MINOR < 3 # define IPP_OP_CREATE_PRINTER (ipp_op_t)0x004C # define IPP_OP_DELETE_PRINTER (ipp_op_t)0x004E # define IPP_OP_GET_PRINTERS (ipp_op_t)0x004F # define IPP_OP_GET_SYSTEM_ATTRIBUTES (ipp_op_t)0x005B # define IPP_OP_SET_SYSTEM_ATTRIBUTES (ipp_op_t)0x0062 # define IPP_OP_SHUTDOWN_ALL_PRINTERS (ipp_op_t)0x0063 # define IPP_TAG_SYSTEM (ipp_tag_t)0x000A # endif // CUPS_VERSION_MAJOR == 2 && CUPS_VERSION_MINOR < 3 // // Wrappers for global constants... // # ifdef _LPRINT_C_ # define VAR # define VALUE(...) = __VA_ARGS__ # else # define VAR extern # define VALUE(...) # endif // _LPRINT_C_ // // Constants... // typedef enum lprint_loglevel_e // Log levels { LPRINT_LOGLEVEL_UNSPEC = -1, // Not specified LPRINT_LOGLEVEL_DEBUG, // Debug message LPRINT_LOGLEVEL_INFO, // Informational message LPRINT_LOGLEVEL_WARN, // Warning message LPRINT_LOGLEVEL_ERROR, // Error message LPRINT_LOGLEVEL_FATAL // Fatal message } lprint_loglevel_t; enum lprint_preason_e // printer-state-reasons bit values { LPRINT_PREASON_NONE = 0x0000, // none LPRINT_PREASON_OTHER = 0x0001, // other LPRINT_PREASON_COVER_OPEN = 0x0002, // cover-open LPRINT_PREASON_MEDIA_EMPTY = 0x0004, // media-empty LPRINT_PREASON_MEDIA_JAM = 0x0008, // media-jam LPRINT_PREASON_MEDIA_LOW = 0x0010, // media-low LPRINT_PREASON_MEDIA_NEEDED = 0x0020 // media-needed }; typedef unsigned int lprint_preason_t; // Bitfield for printer-state-reasons VAR const char * const lprint_preason_strings[6] VALUE({ // Strings for each bit // "none" is implied for no bits set "other", "cover-open", "media-empty", "media-jam", "media-low", "media-needed" }); // // Types and structures... // # ifdef HAVE_DNSSD typedef DNSServiceRef lprint_srv_t; // Service reference typedef TXTRecordRef lprint_txt_t; // TXT record #elif defined(HAVE_AVAHI) typedef AvahiEntryGroup *lprint_srv_t; // Service reference typedef AvahiStringList *lprint_txt_t; // TXT record #else typedef void *lprint_srv_t; // Service reference typedef void *lprint_txt_t; // TXT record #endif // HAVE_DNSSD typedef struct lprint_filter_s // Attribute filter { cups_array_t *ra; // Requested attributes ipp_tag_t group_tag; // Group to copy } lprint_filter_t; typedef struct lprint_system_s // System data { pthread_rwlock_t rwlock; // Reader/writer lock time_t start_time, // Startup time clean_time, // Next clean time save_time, // Do we need to save the config? shutdown_time; // Shutdown requested? char *hostname; // Hostname int port; // Port number, if any char *directory; // Spool directory char *logfile; // Log filename, if any int logfd; // Log file descriptor, if any lprint_loglevel_t loglevel; // Log level char *subtypes; // DNS-SD sub-types, if any char *auth_service; // PAM authorization service, if any char *admin_group; // PAM administrative group, if any gid_t admin_gid; // PAM administrative group ID char *session_key; // Session key int num_listeners; // Number of listener sockets struct pollfd listeners[3]; // Listener sockets int next_client; // Next client number cups_array_t *printers; // Array of printers int default_printer,// Default printer-id next_printer_id;// Next printer-id } lprint_system_t; struct lprint_printer_s // Printer data { pthread_rwlock_t rwlock; // Reader/writer lock lprint_system_t *system; // Containing system # ifdef HAVE_DNSSD lprint_srv_t ipp_ref, // DNS-SD IPP service ipps_ref, // DNS-SD IPPS service http_ref, // DNS-SD HTTP service printer_ref; // DNS-SD LPD service # elif defined(HAVE_AVAHI) lprint_srv_t dnssd_ref; // DNS-SD services # endif // HAVE_DNSSD int printer_id; // printer-id char *printer_name, // printer-name *dns_sd_name, // printer-dns-sd-name *location, // Human-readable location *geo_location, // Geographic location (geo: URI) *organization, // Organization *org_unit, // Organizational unit *resource; // Resource path of printer size_t resourcelen; // Length of resource path char *device_uri, // Device URI *driver_name; // Driver name lprint_driver_t *driver; // Driver ipp_t *attrs; // Static attributes ipp_attribute_t *xri_supported; // printer-xri-supported attribute time_t start_time; // Startup time time_t config_time; // printer-config-change-time ipp_pstate_t state; // printer-state value lprint_preason_t state_reasons; // printer-state-reasons values time_t state_time; // printer-state-change-time time_t status_time; // Last time status was updated lprint_job_t *processing_job;// Currently printing job, if any cups_array_t *active_jobs, // Array of active jobs *completed_jobs,// Array of completed jobs *jobs; // Array of all jobs int next_job_id, // Next job-id is_deleted, // Non-zero if deleted impcompleted; // printer-impressions-completed }; struct lprint_job_s // Job data { pthread_rwlock_t rwlock; // Reader/writer lock lprint_system_t *system; // Containing system lprint_printer_t *printer; // Printer int id; // Job ID const char *name, // job-name *username, // job-originating-user-name *format; // document-format ipp_jstate_t state; // job-state value char *message; // job-state-message value int msglevel; // job-state-message log level (0=error, 1=info) time_t created, // [date-]time-at-creation value processing, // [date-]time-at-processing value completed; // [date-]time-at-completed value int impressions, // job-impressions value impcompleted; // job-impressions-completed value ipp_t *attrs; // Static attributes int cancel; // Non-zero when job canceled char *filename; // Print file name int fd; // Print file descriptor }; typedef struct lprint_client_s // Client data { lprint_system_t *system; // Containing system int number; // Connection number pthread_t thread_id; // Thread ID http_t *http; // HTTP connection ipp_t *request, // IPP request *response; // IPP response time_t start; // Request start time http_state_t operation; // Request operation ipp_op_t operation_id; // IPP operation-id char uri[1024], // Request URI *options; // URI options http_addr_t addr; // Client address char hostname[256]; // Client hostname char username[256]; // Authenticated username, if any lprint_printer_t *printer; // Printer, if any lprint_job_t *job; // Job, if any } lprint_client_t; // // Functions... // extern void lprintAddOptions(ipp_t *request, int num_options, cups_option_t *options); extern void lprintAddPrinterURI(ipp_t *request, const char *printer_name, char *resource, size_t rsize); extern void lprintCheckJobs(lprint_printer_t *printer); extern void lprintCleanJobs(lprint_system_t *system); extern http_t *lprintConnect(int auto_start); extern http_t *lprintConnectURI(const char *printer_uri, char *resource, size_t rsize); extern void lprintCopyAttributes(ipp_t *to, ipp_t *from, cups_array_t *ra, ipp_tag_t group_tag, int quickcopy); extern lprint_client_t *lprintCreateClient(lprint_system_t *system, int sock); extern lprint_job_t *lprintCreateJob(lprint_client_t *client); extern int lprintCreateJobFile(lprint_job_t *job, char *fname, size_t fnamesize, const char *dir, const char *ext); extern lprint_printer_t *lprintCreatePrinter(lprint_system_t *system, int printer_id, const char *printer_name, const char *driver_name, const char *device_uri, const char *location, const char *geo_location, const char *organization, const char *org_unit); extern lprint_system_t *lprintCreateSystem(const char *hostname, int port, const char *subtypes, const char *spooldir, const char *logfile, lprint_loglevel_t loglevel, const char *auth_service, const char *admin_group); extern void lprintDeleteClient(lprint_client_t *client); extern void lprintDeleteJob(lprint_job_t *job); extern void lprintDeletePrinter(lprint_printer_t *printer); extern void lprintDeleteSystem(lprint_system_t *system); extern int lprintDoAdd(int num_options, cups_option_t *options); extern int lprintDoCancel(int num_options, cups_option_t *options); extern int lprintDoDefault(int num_options, cups_option_t *options); extern int lprintDoDelete(int num_options, cups_option_t *options); extern int lprintDoDevices(int num_options, cups_option_t *options); extern int lprintDoDrivers(int num_options, cups_option_t *options); extern int lprintDoJobs(int num_options, cups_option_t *options); extern int lprintDoModify(int num_options, cups_option_t *options); extern int lprintDoOptions(int num_options, cups_option_t *options); extern int lprintDoPrinters(int num_options, cups_option_t *options); extern int lprintDoServer(int num_options, cups_option_t *options); extern int lprintDoShutdown(int num_options, cups_option_t *options); extern int lprintDoStatus(int num_options, cups_option_t *options); extern int lprintDoSubmit(int num_files, char **files, int num_options, cups_option_t *options); extern lprint_job_t *lprintFindJob(lprint_printer_t *printer, int job_id); extern lprint_printer_t *lprintFindPrinter(lprint_system_t *system, const char *resource, int printer_id); extern char *lprintGetDefaultPrinter(http_t *http, char *buffer, size_t bufsize); extern char *lprintGetServerPath(char *buffer, size_t bufsize); extern void lprintInitDNSSD(lprint_system_t *system); extern http_status_t lprintIsAuthorized(lprint_client_t *client); // Note: Log functions currently only support %d, %p, %s, %u, and %x! extern void lprintLog(lprint_system_t *system, lprint_loglevel_t level, const char *message, ...); extern void lprintLogAttributes(lprint_client_t *client, const char *title, ipp_t *ipp, int is_response); extern void lprintLogClient(lprint_client_t *client, lprint_loglevel_t level, const char *message, ...) LPRINT_FORMAT(3, 4); extern void lprintLogJob(lprint_job_t *job, lprint_loglevel_t level, const char *message, ...) LPRINT_FORMAT(3, 4); extern void lprintLogPrinter(lprint_printer_t *printer, lprint_loglevel_t level, const char *message, ...) LPRINT_FORMAT(3, 4); extern char *lprintMakeUUID(lprint_system_t *system, const char *printer_name, int job_id, char *buffer, size_t bufsize); extern void *lprintProcessClient(lprint_client_t *client); extern int lprintProcessHTTP(lprint_client_t *client); extern int lprintProcessIPP(lprint_client_t *client); extern void *lprintProcessJob(lprint_job_t *job); extern unsigned lprintRand(void); extern int lprintRegisterDNSSD(lprint_printer_t *printer); extern int lprintRespondHTTP(lprint_client_t *client, http_status_t code, const char *content_coding, const char *type, size_t length); extern void lprintRespondIPP(lprint_client_t *client, ipp_status_t status, const char *message, ...) LPRINT_FORMAT(3, 4); extern void lprintRunSystem(lprint_system_t *system); extern void lprintUnregisterDNSSD(lprint_printer_t *printer); #endif // !_LPRINT_H_ lprint-1.0/lprint.spec000066400000000000000000000032601362261677400150650ustar00rootroot00000000000000# # RPM "spec" file for LPrint. # Name: lprint Version: 1.0 Release: 0 Summary: LPrint, A Label Printer Application License: ASL 2.0 Source0: https://github.com/michaelrsweet/lprint/releases/download/v%{version}/lprint-%{version}.tar.gz URL: https://www.msweet.org/lprint Packager: Anonymous Vendor: Example Corp # Note: Package names are as defined for Red Hat (and clone) distributions BuildRequires: avahi-devel, cups-devel >= 2.2, gnutls-devel, libpng-devel >= 1.6, libusb-devel >= 1.0, pam-devel #BuildRoot: /tmp/%{name}-root %description LPrint implements printing for a variety of common label and receipt printers connected via network or USB. Features include: - A single executable handles spooling, status, and server functionality. - Multiple printer support. - Each printer implements an IPP Everywhere™ print service and is compatible with the driverless printing support in iOS, macOS, and Linux clients. - Each printer can support options such as label modes, tear-off offsets, media tracking, media top offset, print darkness, resolution, roll selection, and speed. - Each printer can print "raw", Apple/PWG Raster, and/or PNG files. For more information, see the file "DOCUMENTATION.md", the man pages in the "man" directory, and/or the LPrint project page at "https://www.msweet.org/lprint". %prep %setup %build CFLAGS="$RPM_OPT_FLAGS" CXXFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_OPT_FLAGS" ./configure --enable-libpng --enable-libusb --enable-pam --with-dnssd=avahi --prefix=/usr make %install make install %clean rm -rf $RPM_BUILD_ROOT %files /usr/bin/lprint %dir /usr/share/man/man1 /usr/share/man/man1/* %dir /usr/share/man/man5 /usr/share/man/man5/* lprint-1.0/man/000077500000000000000000000000001362261677400134535ustar00rootroot00000000000000lprint-1.0/man/lprint-add.1000066400000000000000000000050601362261677400155740ustar00rootroot00000000000000.\" .\" lprint-add man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-add 1 "LPrint" "January 24, 2020" "Michael R Sweet" .SH NAME lprint-add \- add a printer queue. .SH SYNOPSIS .B lprint .B add [ .B \-u .I SYSTEM-URI ] .B \-d .I PRINTER .B \-m .I DRIVER-NAME .B \-v .I DEVICE-URI [ .B \-o .I OPTION=VALUE ] .SH DESCRIPTION This command creates a label printer queue using the specified name, driver, and driver. .SH OPTIONS The following options are recognized by .B lprint add: .TP 5 \fB\-d \fIPRINTER\fR Specifies the name of the printer queue. .TP 5 \fB\-m \fIDRIVER-NAME\fR Specifies the name of the printer driver. See .BR lprint-drivers (1) for the command to list the available printer drivers. .TP 5 \fB\-o \fIOPTION=VALUE\fR Specifies the default value for the given option name. See .BR lprint-submit (1) for a list of supported options. .TP 5 \fB\-o label-mode-configured\fI=VALUE\fR Specifies the label printing mode: "applicator", "cutter", "cutter-delayed", "kiosk", "peel-off", "peel-off-prepeel", "rewind", "rfid", or "tear-off". .TP 5 \fB\-o label-tear-offset-configured\fI=NNNin\fR .TP 5 \fB\-o label-tear-offset-configured\fI=NNNmm\fR Specifies the label tear-off offset in inches ("NNNin") or millimeters ("NNNmm"). .TP 5 \fB\-o printer-darkness\fI=NNN\fR Specifies the base darkness setting for all print jobs as a percentage. 0 represents the lightest printing while 100 represents the darkest printing. .TP 5 \fB\-o printer-geo-location=geo:\fI=LATLON\fR Specifies the geographic location of the printer as a "geo:" URI. .TP 5 \fB\-o printer-location\fI=LOCATION\fR Specifies the human-readable location, for example "Rack 42". .TP 5 \fB\-o printer-organization\fI=ORGANIZATION\fR Specifies the organization name, for example "Acme, Inc.". .TP 5 \fB\-o printer-organizational-unit\fI=UNIT\fR Specifies the organizational unit, for example "Shipping Department". .TP 5 \fB\-u \fISYSTEM-URI\fR Specifies a remote LPrint server to use. The "SYSTEM-URI" is of the form "ipps://HOSTNAME:PORT/ipp/system". .TP 5 \fB\-v \fIDEVICE-URI\fR Specifies the device for the printer queue. The value can be a socket: URI such as "socket://11.22.33.44" or a usb: URI as listed by the .BR lprint-devices (1) command. .SH SEE ALSO .BR lprint (1), .BR lprint-delete (1), .BR lprint-devices (1), .BR lprint-drivers (1), .BR lprint-modify (1), .BR lprint-options (1), .BR lprint-submit (1) .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-cancel.1000066400000000000000000000023021362261677400162650ustar00rootroot00000000000000.\" .\" lprint-cancel man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-cancel 1 "LPrint" "January 4, 2020" "Michael R Sweet" .SH NAME lprint-cancel \- cancel one or more print jobs. .SH SYNOPSIS .B lprint .B cancel [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] [ .B \-j .I JOB-ID ] .br .B lprint .B cancel [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] .B \-a .SH DESCRIPTION This command cancels one or more print jobs. In the first form, the currently printing job or the specified job is canceled. In the second form, all print jobs are canceled. .SH OPTIONS The following options are recognized by .B lprint cancel: .TP 5 .B \-a Cancel all print jobs. .TP 5 \fB\-d \fIPRINTER\fR Specifies the name of the printer queue. If not specified, the default printer is used. .TP 5 \fB\-j \fIJOB-ID\fR Specifies the print job number. .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .SH SEE ALSO .BR lprint-default (1), .BR lprint-jobs (1), .BR lprint-submit (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-default.1000066400000000000000000000017711362261677400164750ustar00rootroot00000000000000.\" .\" lprint-default man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-default 1 "LPrint" "January 24, 2020" "Michael R Sweet" .SH NAME lprint-default \- set or get the default printer queue. .SH SYNOPSIS .B lprint .B default [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] .SH DESCRIPTION This command gets or sets the default printer queue. When run without options, the current default printer is written to the standard output. Otherwise, the default printer is changed. .SH OPTIONS The following options are recognized by .B lprint default: .TP 5 \fB\-d \fIPRINTER\fR Specifies the new default printer queue. .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1), .BR lprint-modify (1), .BR lprint-printers (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-delete.1000066400000000000000000000015401362261677400163050ustar00rootroot00000000000000.\" .\" lprint-delete man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-delete 1 "LPrint" "January 24, 2020" "Michael R Sweet" .SH NAME lprint-delete \- delete a label printer queue. .SH SYNOPSIS .B lprint .B delete .B \-d .I PRINTER .br .B lprint .B delete .B \-u .I PRINTER-URI .SH DESCRIPTION This command deletes the specified label printer queue. .SH OPTIONS The following options are recognized by .B lprint delete: .TP 5 \fB\-d \fIPRINTER\fR Specifies the printer queue to delete. .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1), .BR lprint-modify (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-devices.1000066400000000000000000000011371362261677400164670ustar00rootroot00000000000000.\" .\" lprint-devices man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-devices 1 "LPrint" "January 4, 2020" "Michael R Sweet" .SH NAME lprint-devices \- list connected label printer devices. .SH SYNOPSIS .B lprint .B devices .SH DESCRIPTION This command lists connected label printer devices. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1), .BR lprint-drivers (1), .BR lprint-modify (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-drivers.1000066400000000000000000000011431362261677400165200ustar00rootroot00000000000000.\" .\" lprint-drivers man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-drivers 1 "LPrint" "January 4, 2020" "Michael R Sweet" .SH NAME lprint-drivers \- list drivers supported by the print server. .SH SYNOPSIS .B lprint .B drivers .SH DESCRIPTION This command lists the supported printer drivers. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1), .BR lprint-devices (1), .BR lprint-modify (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-jobs.1000066400000000000000000000015731362261677400160060ustar00rootroot00000000000000.\" .\" lprint-jobs man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-jobs 1 "LPrint" "January 4, 2020" "Michael R Sweet" .SH NAME lprint-jobs \- list pending print jobs. .SH SYNOPSIS .B lprint .B jobs [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] .SH DESCRIPTION This command lists pending print jobs. If not specified, print jobs submitted to the default printer are listed. .SH OPTIONS The following options are recognized by .B lprint jobs: .TP 5 \fB\-d \fIPRINTER\fR Specifies the printer queue to list. .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .SH SEE ALSO .BR lprint (1), .BR lprint-cancel (1), .BR lprint-default (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-modify.1000066400000000000000000000051231362261677400163330ustar00rootroot00000000000000.\" .\" lprint-modify man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-modify 1 "LPrint" "January 24, 2020" "Michael R Sweet" .SH NAME lprint-modify \- modify a printer queue. .SH SYNOPSIS .B lprint .B modify .B \-d .I PRINTER [ .B \-m .I DRIVER-NAME ] [ .B \-v .I DEVICE-URI ] [ .B \-o .I OPTION=VALUE ] .br .B lprint .B modify .B \-u .I PRINTER-URI [ .B \-m .I DRIVER-NAME ] [ .B \-v .I DEVICE-URI ] [ .B \-o .I OPTION=VALUE ] .SH DESCRIPTION This command modifies an existing label printer queue. .SH OPTIONS The following options are recognized by .B lprint modify: .TP 5 \fB\-d \fIPRINTER-NAME\fR Specifies the name of the print queue. .TP 5 \fB\-m \fIDRIVER-NAME\fR Specifies the name of the print driver. See .BR lprint-drivers (1) for the command to list the available print drivers. .TP 5 \fB\-o \fIOPTION=VALUE\fR Specifies the default value for the given option name. See .BR lprint-submit (1) for a list of supported options. .TP 5 \fB\-o label-mode-configured\fI=VALUE\fR Specifies the label printing mode: "applicator", "cutter", "cutter-delayed", "kiosk", "peel-off", "peel-off-prepeel", "rewind", "rfid", or "tear-off". .TP 5 \fB\-o label-tear-offset-configured\fI=NNNin\fR .TP 5 \fB\-o label-tear-offset-configured\fI=NNNmm\fR Specifies the label tear-off offset in inches ("NNNin") or millimeters ("NNNmm"). .TP 5 \fB\-o printer-darkness\fI=NNN\fR Specifies the base darkness setting for all print jobs as a percentage. 0 represents the lightest printing while 100 represents the darkest printing. .TP 5 \fB\-o printer-geo-location=geo:\fI=LATLON\fR Specifies the geographic location of the printer as a "geo:" URI. .TP 5 \fB\-o printer-location\fI=LOCATION\fR Specifies the human-readable location, for example "Rack 42". .TP 5 \fB\-o printer-organization\fI=ORGANIZATION\fR Specifies the organization name, for example "Acme, Inc.". .TP 5 \fB\-o printer-organizational-unit\fI=UNIT\fR Specifies the organizational unit, for example "Shipping Department". .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .TP 5 \fB\-v \fIDEVICE-URI\fR Specifies the device for the print queue. The value can be a socket: URI such as "socket://11.22.33.44" or a usb: URI as listed by the .BR lprint-devices (1) command. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1), .BR lprint-delete (1), .BR lprint-devices (1), .BR lprint-drivers (1), .BR lprint-options (1), .BR lprint-submit (1) .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-options.1000066400000000000000000000016271362261677400165440ustar00rootroot00000000000000.\" .\" lprint-options man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-default 1 "LPrint" "January 5, 2020" "Michael R Sweet" .SH NAME lprint-options \- get the supported options for a printer queue. .SH SYNOPSIS .B lprint .B options [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] .SH DESCRIPTION This command gets the supported options for a printer queue. .SH OPTIONS The following options are recognized by .B lprint default: .TP 5 \fB\-d \fIPRINTER\fR Specifies the new default printer queue. .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1), .BR lprint-modify (1), .BR lprint-printers (1), .BR lprint-submit (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-printers.1000066400000000000000000000010661362261677400167140ustar00rootroot00000000000000.\" .\" lprint-printers man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-printers 1 "LPrint" "January 4, 2020" "Michael R Sweet" .SH NAME lprint-printers \- list the configured printer queues. .SH SYNOPSIS .B lprint .B printers .SH DESCRIPTION This command lists the configured label printer queues. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-server.1000066400000000000000000000046241362261677400163570ustar00rootroot00000000000000.\" .\" lprint-server man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-server 1 "LPrint" "January 23, 2020" "Michael R Sweet" .SH NAME lprint-server \- start a label print server. .SH SYNOPSIS .B lprint .B server [ .B \-o .I OPTION=VALUE ] .SH DESCRIPTION This command starts a label print server. Normally a server is started automatically as needed, however you can run the server manually to listen on a public network address and/or enable different logging options. .SH OPTIONS The following options are recognized by .B lprint server: .TP 5 \fB\-o admin\-group=\fIGROUP\fR Specifies that remote configuration is authenticated against the named group. If not specified or the value "none" is given then any authenticated user may remotely configure lprint. .TP 5 \fB\-o auth\-service=\fISERVICE\fR Specifies the PAM service to use to authenticate for remote configuration requests. If not specified or the value "none" is given then printers can only be added, modified, or deleted locally. .TP 5 .B \-o log-file=\- Specifies that all messages are written to the standard error. .TP 5 .B \-o log-file=syslog Specifies that all messages are sent to the syslog service. .TP 5 \fB\-o log-file=\fRFILENAME\fR Specifies that all messages are written to the named file. If the file already exists, messages are appended to it. The default log file is "$TMPDIR/lprintUID.log". .TP 5 .B \-o log-level=error Specifies that only error messages should be logged. This is the default. .TP 5 .B \-o log-level=info Specifies that error and informational messages should be logged. .TP 5 .B \-o log-level=debug Specifies that all messages should be logged. .TP 5 \fB\-o server-hostname=\fIHOSTNAME\fR Listens for IPP connections on the specified hostname/address(es). If not specified, the server only listens for connections on a per-user (local) domain socket. .TP 5 \fB\-o server-port=\fIPORT\fR Listens for IPP connections on the specified port. If not specified, a random port between 9000 and 9999 is chosen. .TP 5 \fB\-o spool\-directory=\fIDIRECTORY\fR Specifies a directory that holds pending print files. If not specified, a subdirectory in the system temporary directory is used. .SH SEE ALSO .BR lprint (1), .BR lprint-shutdown (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-shutdown.1000066400000000000000000000010611362261677400167140ustar00rootroot00000000000000.\" .\" lprint-shutdown man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-shutdown 1 "LPrint" "January 4, 2020" "Michael R Sweet" .SH NAME lprint-shutdown \- stop a running label print server. .SH SYNOPSIS .B lprint .B shutdown .SH DESCRIPTION This command stops a running label print server. .SH SEE ALSO .BR lprint (1), .BR lprint-server (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-status.1000066400000000000000000000015711362261677400163720ustar00rootroot00000000000000.\" .\" lprint-status man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-status 1 "LPrint" "January 4, 2020" "Michael R Sweet" .SH NAME lprint-status \- show the current status of a printer .SH SYNOPSIS .B lprint .B status [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] .SH DESCRIPTION This command shows the current status of a printer. If no printer is specified, the combined server state is shown. .SH OPTIONS The following options are recognized by .B lprint status: .TP 5 \fB\-d \fIPRINTER\fR Specifies the name of a printer. .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .SH SEE ALSO .BR lprint (1), .BR lprint-default (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint-submit.1000066400000000000000000000075771362261677400163660ustar00rootroot00000000000000.\" .\" lprint-submit man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint-submit 1 "LPrint" "January 11, 2020" "Michael R Sweet" .SH NAME lprint-submit \- submit a file for printing. .SH SYNOPSIS .B lprint [ .B submit ] [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] [ .B \-n .I COPIES ] [ .B \-o .I OPTION=VALUE ] [ .B \-t .I TITLE ] [ .I FILE [ ... FILE ] ] .br .B lprint [ .B submit ] [ .B \-d .I PRINTER ] [ .B \-u .I PRINTER-URI ] [ .B \-n .I COPIES ] [ .B \-o .I OPTION=VALUE ] [ .B \-t .I TITLE ] \- .SH DESCRIPTION This command submits one or more files for printing. The first form prints the named files. The second form copies the print file from the standard input. .SH OPTIONS The following options are recognized by .B lprint submit: .TP 5 \fB\-d \fIPRINTER\fR Specifies the name of the printer queue. If not specified, the default printer is used. .TP 5 \fB\-n \fICOPIES\fR Specifies the number of copies. .TP 5 \fB\-o media=\fISIZE-NAME\fR Specifies the label size. .TP 5 \fB\-o media-source=\fIROLL-NAME\fR Specifies the label roll. .TP 5 \fB\-o media-top-offset=\fINNN\fBin\fR .TP 5 \fB\-o media-top-offset=\fINNN\fBmm\fR Specifies the distance to offset printing from the top of the label in inches ("NNNin") or millimeters ("NNNmm"). .TP 5 \fB\-o media-tracking=continuous\fR .TP 5 \fB\-o media-tracking=mark\fR .TP 5 \fB\-o media-tracking=web\fR Specifies how labels are tracked on the carrier backing - "continuous" for a continuous label or receipt paper, "mark" for labels that are separated with a visible mark on the carrier backing, or "web" for labels that are separated with a hole in the carrier backing. .TP 5 \fB\-o media-type=continuous\fR .TP 5 \fB\-o media-type=labels\fR Specifies the type of roll media being used - "continuous" for continuous labels or receipt paper, or "labels" for cut labels on a carrier backing. .TP 5 .B \-o orientation-requested=portrait Print images in portrait orientation. .TP 5 .B \-o orientation-requested=landscape Print images in landscape (90 degrees counter-clockwise) orientation. .TP 5 .B \-o orientation-requested=reverse-portrait Print images in reverse-portrait (upside down) orientation. .TP 5 .B \-o orientation-requested=reverse-landscape Print images in reverse-landscape (90 degrees clockwise) orientation. .TP 5 .B \-o orientation-requested=none Print images in automatic (portrait or landscape) orientation. .TP 5 .B \-o print-color-mode=bi-level Only print black or white when printing images. .TP 5 .B \-o print-color-mode=monochrome Halftone shades of gray when printing images. .B \-o print-content-optimize=auto Optimize printing automatically based on the type and content of the file. .B \-o print-content-optimize=graphic Optimize printing for graphics only. .B \-o print-content-optimize=photo Optimize printing for photos. .B \-o print-content-optimize=text Optimize printing for text only. .B \-o print-content-optimize=text-and-graphic Optimize printing for text and graphics. .TP 5 \fB\-o print-darkness=\fINNN\fR Specifies the print darkness from -100 (lightest) to 100 (darkest). .TP 5 \fB\-o print-quality=draft\fR Print using draft quality. .TP 5 \fB\-o print-quality=normal\fR Print using normal quality. .TP 5 \fB\-o print-quality=high\fR Print using high/best quality. .TP 5 \fB\-o print-speed=\fINNNin\fR .TP 5 \fB\-o print-speed=\fINNNmm\fR Specifies the print speed in inches ("NNNin") or millimeters ("NNNmm") per second. .TP 5 \fB\-o printer-resolution=\fINNN\fBdpi\fR Specifies the print resolution in dots per inch. .TP 5 \fB\-t \fITITLE\fR Specifies the print job name. .TP 5 \fB\-u \fIPRINTER-URI\fR Specifies an "ipp:" or "ipps:" URI for a remote printer. .SH SEE ALSO .BR lprint-cancel (1), .BR lprint-default (1), .BR lprint-options (1). .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint.1000066400000000000000000000033231362261677400150460ustar00rootroot00000000000000.\" .\" Main man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019-2020 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint 1 "LPrint" "January 5, 2020" "Michael R Sweet" .SH NAME lprint \- a label printer application .SH SYNOPSIS .B lprint [ .I SUB-COMMAND ] [ OPTIONS ] [ FILES ] .SH DESCRIPTION .B lprint is a label printer application that can be run standalone or as a dedicated IPP Everywhere network service. .B lprint supports printing PNG images, Apple/PWG raster files, and printer-specific label files to USB and network label printers. If no sub-command is specified, "submit" is assumed. .SH SUB-COMMANDS The following sub-commands are recognized by .B lprint: .TP 5 add Add a printer queue. .TP 5 cancel Cancel one or more print jobs. .TP 5 default Set the default printer queue. .TP 5 delete Delete a printer queue. .TP 5 devices List connected printers. .TP 5 drivers List the supported drivers. .TP 5 jobs List pending print jobs. .TP 5 modify Modify a printer queue. .TP 5 options List supported options. .TP 5 printers List the printer queues. .TP 5 server Start a server. .TP 5 shutdown Shutdown a running server. .TP 5 status Show the status of a printer or all printers. .TP 5 submit Submit a file for printing. .SH SEE ALSO .BR lprint-add (1), .BR lprint-cancel (1), .BR lprint-default (1), .BR lprint-delete (1), .BR lprint-devices (1), .BR lprint-drivers (1), .BR lprint-jobs (1), .BR lprint-modify (1), .BR lprint-options (1), .BR lprint-printers (1), .BR lprint-server (1), .BR lprint-shutdown (1), .BR lprint-status (1), .BR lprint-submit (1), .BR lprint.conf (5) .SH COPYRIGHT Copyright \[co] 2019-2020 by Michael R Sweet. lprint-1.0/man/lprint.conf.5000066400000000000000000000013331362261677400157750ustar00rootroot00000000000000.\" .\" lprint.conf man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint.conf 5 "LPrint" "December 13, 2019" "Michael R Sweet" .SH NAME ~/lprint.conf \- printer configuration file. .SH DESCRIPTION The .B ~/.lprint.conf file contains a list of the printer queues configured using the .BR lprint-add (1), .BR lprint-default (1), .BR lprint-delete (1), and .BR lprint-modify (1) commands. .SH SEE ALSO .BR lprint (1), .BR lprint-add (1), .BR lprint-default (1), .BR lprint-delete (1), .BR lprint-modify (1), .BR lprint-server (1). .SH COPYRIGHT Copyright \[co] 2019 by Michael R Sweet. lprint-1.0/man/template.1000066400000000000000000000012751362261677400153550ustar00rootroot00000000000000.\" .\" ??? man page for LPrint, a Label Printer Utility .\" .\" Copyright © 2019 by Michael R Sweet. .\" .\" Licensed under Apache License v2.0. See the file "LICENSE" for more .\" information. .\" .TH lprint 1 "LPrint" "November 21, 2019" "Michael R Sweet" .SH NAME lprint \- description .SH SYNOPSIS .B lprint .B foo [ .B \-\-option .I value ] .SH DESCRIPTION .B lprint description of what this does. .SH OPTIONS The following options are recognized by .B lprint: .TP 5 \fB\-\-option \fIvalue\fR Description of option. .SH EXIT STATUS The .B lprint program returns 1 if it is unable to ... .SH ENVIRONMENT .SH EXAMPLES .SH SEE ALSO .SH COPYRIGHT Copyright \[co] 2019 by Michael R Sweet. lprint-1.0/server-auth.c000066400000000000000000000205411362261677400153130ustar00rootroot00000000000000// // Authentication support for LPrint, a Label Printer Application // // Copyright © 2017-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include #include #include #ifdef HAVE_LIBPAM # ifdef HAVE_PAM_PAM_APPL_H # include # else # include # endif // HAVE_PAM_PAM_APPL_H #endif // HAVE_LIBPAM // // Types... // typedef struct lprint_authdata_s // PAM authentication data { const char *username, // Username string *password; // Password string } lprint_authdata_t; // // Local functions... // static int lprint_authenticate_user(lprint_client_t *client, const char *username, const char *password); #ifdef HAVE_LIBPAM static int lprint_pam_func(int num_msg, const struct pam_message **msg, struct pam_response **resp, lprint_authdata_t *data); #endif // HAVE_LIBPAM // // 'lprintIsAuthorized()' - Determine whether a client is authorized for // administrative requests. // http_status_t // O - HTTP status lprintIsAuthorized( lprint_client_t *client) // I - Client { const char *authorization; // Authorization: header value // Local access is always allowed... if (httpAddrFamily(httpGetAddress(client->http)) == AF_LOCAL) return (HTTP_STATUS_CONTINUE); // Remote access is only allowed if a PAM authentication service is configured... if (!client->system->auth_service) return (HTTP_STATUS_FORBIDDEN); // Remote admin access requires encryption... if (!httpIsEncrypted(client->http) && !httpAddrLocalhost(httpGetAddress(client->http))) return (HTTP_STATUS_UPGRADE_REQUIRED); // Get the authorization header... if ((authorization = httpGetField(client->http, HTTP_FIELD_AUTHORIZATION)) != NULL && *authorization) { if (!strncmp(authorization, "Basic ", 6)) { // Basic authentication... char username[512], // Username value *password; // Password value int userlen = sizeof(username); // Length of username:password struct passwd *user; // User information int num_groups; // Number of autbenticated groups, if any # ifdef __APPLE__ int groups[32]; // Authenticated groups, if any # else gid_t groups[32]; // Authenticated groups, if any # endif // __APPLE__ for (authorization += 6; *authorization && isspace(*authorization & 255); authorization ++); httpDecode64_2(username, &userlen, authorization); if ((password = strchr(username, ':')) != NULL) { *password++ = '\0'; // Authenticate the username and password... if (lprint_authenticate_user(client, username, password)) { // Get the user information (groups, etc.) if ((user = getpwnam(username)) != NULL) { lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Authenticated as \"%s\" using Basic.", username); strlcpy(client->username, username, sizeof(client->username)); num_groups = (int)(sizeof(groups) / sizeof(groups[0])); #ifdef __APPLE__ if (getgrouplist(username, (int)user->pw_gid, groups, &num_groups)) #else if (getgrouplist(username, user->pw_gid, groups, &num_groups)) #endif // __APPLE__ { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Unable to lookup groups for user '%s': %s", username, strerror(errno)); num_groups = 0; } // Check group membership... if (client->system->admin_gid != -1) { if (user->pw_gid != client->system->admin_gid) { int i; // Looping var for (i = 0; i < num_groups; i ++) { if (groups[i] == client->system->admin_gid) break; } if (i >= num_groups) { // Not in the admin group, access is forbidden... return (HTTP_STATUS_FORBIDDEN); } } } // If we get this far, authentication and authorization are good... return (HTTP_STATUS_CONTINUE); } else { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Unable to lookup user '%s'.", username); return (HTTP_STATUS_SERVER_ERROR); } } else { lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Basic authentication of '%s' failed.", username); } } else { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Bad Basic Authorization header value seen."); return (HTTP_STATUS_BAD_REQUEST); } } else { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Unsupported Authorization header value seen."); return (HTTP_STATUS_BAD_REQUEST); } } // If we get there then we don't have any authorization value we can use... return (HTTP_STATUS_UNAUTHORIZED); } // // 'lprint_authenticate_user()' - Validate a username + password combination. // static int // O - 1 if correct, 0 otherwise lprint_authenticate_user( lprint_client_t *client, // I - Client const char *username, // I - Username string const char *password) // I - Password string { int status = 0; // Return status #ifdef HAVE_LIBPAM lprint_authdata_t data; // Authorization data pam_handle_t *pamh; // PAM authentication handle int pamerr; // PAM error code struct pam_conv pamdata; // PAM conversation data data.username = username; data.password = password; pamdata.conv = (int (*)(int, const struct pam_message **, struct pam_response **, void *))lprint_pam_func; pamdata.appdata_ptr = &data; pamh = NULL; if ((pamerr = pam_start(client->system->auth_service, data.username, &pamdata, &pamh)) != PAM_SUCCESS) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "pam_start() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } # ifdef PAM_RHOST else if ((pamerr = pam_set_item(pamh, PAM_RHOST, client->hostname)) != PAM_SUCCESS) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "pam_set_item(PAM_RHOST) returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } # endif // PAM_RHOST # ifdef PAM_TTY else if ((pamerr = pam_set_item(pamh, PAM_TTY, "lprint")) != PAM_SUCCESS) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "pam_set_item(PAM_TTY) returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } # endif // PAM_TTY else if ((pamerr = pam_authenticate(pamh, PAM_SILENT)) != PAM_SUCCESS) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "pam_authenticate() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } else if ((pamerr = pam_setcred(pamh, PAM_ESTABLISH_CRED | PAM_SILENT)) != PAM_SUCCESS) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "pam_setcred() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } else if ((pamerr = pam_acct_mgmt(pamh, PAM_SILENT)) != PAM_SUCCESS) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "pam_acct_mgmt() returned %d (%s)", pamerr, pam_strerror(pamh, pamerr)); } if (pamh) pam_end(pamh, PAM_SUCCESS); if (pamerr == PAM_SUCCESS) { lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "PAM authentication of '%s' succeeded.", username); status = 1; } #endif // HAVE_LIBPAM return (status); } #ifdef HAVE_LIBPAM // // 'lprint_pam_func()' - PAM conversation function. // static int // O - Success or failure lprint_pam_func( int num_msg, // I - Number of messages const struct pam_message **msg, // I - Messages struct pam_response **resp, // O - Responses lprint_authdata_t *data) // I - Authentication data { int i; // Looping var struct pam_response *replies; // Replies // Allocate memory for the responses... if ((replies = calloc((size_t)num_msg, sizeof(struct pam_response))) == NULL) return (PAM_CONV_ERR); // Answer all of the messages... for (i = 0; i < num_msg; i ++) { switch (msg[i]->msg_style) { case PAM_PROMPT_ECHO_ON : replies[i].resp_retcode = PAM_SUCCESS; replies[i].resp = strdup(data->username); break; case PAM_PROMPT_ECHO_OFF : replies[i].resp_retcode = PAM_SUCCESS; replies[i].resp = strdup(data->password); break; default : replies[i].resp_retcode = PAM_SUCCESS; replies[i].resp = NULL; break; } } // Return the responses back to PAM... *resp = replies; return (PAM_SUCCESS); } #endif // HAVE_LIBPAM lprint-1.0/server-client.c000066400000000000000000001514701362261677400156360ustar00rootroot00000000000000// // Client processing code for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include "static-resources/lprint-png.h" #include "static-resources/lprint-large-png.h" #include "static-resources/lprint-de-strings.h" #include "static-resources/lprint-en-strings.h" #include "static-resources/lprint-es-strings.h" #include "static-resources/lprint-fr-strings.h" #include "static-resources/lprint-it-strings.h" #include // // Local types... // typedef struct lprint_resource_s // Resource data { const char *path, // Resource path *content_type; // Content-Type value const void *data; // Pointer to resource data size_t length; // Size of resource } lprint_resource_t; // // Local functions... // static int device_cb(const char *device_uri, lprint_client_t *client); static int get_form_data(lprint_client_t *client, cups_option_t **form); static void html_escape(lprint_client_t *client, const char *s, size_t slen); static void html_footer(lprint_client_t *client); static void html_header(lprint_client_t *client, const char *title, int refresh); static void html_printf(lprint_client_t *client, const char *format, ...) LPRINT_FORMAT(2, 3); static void media_chooser(lprint_client_t *client, lprint_printer_t *printer, const char *title, const char *name, lprint_media_col_t *media); static void media_parse(const char *name, lprint_media_col_t *media, int num_form, cups_option_t *form); static int show_add(lprint_client_t *client); static int show_default(lprint_client_t *client, int printer_id); static int show_delete(lprint_client_t *client, int printer_id); static int show_modify(lprint_client_t *client, int printer_id); static int show_status(lprint_client_t *client); static char *time_string(time_t tv, char *buffer, size_t bufsize); // // 'lprintCreateClient()' - Accept a new network connection and create a client object. // lprint_client_t * // O - Client lprintCreateClient( lprint_system_t *system, // I - Printer int sock) // I - Listen socket { lprint_client_t *client; // Client if ((client = calloc(1, sizeof(lprint_client_t))) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to allocate memory for client connection: %s", strerror(errno)); return (NULL); } client->system = system; pthread_rwlock_wrlock(&system->rwlock); client->number = system->next_client ++; pthread_rwlock_unlock(&system->rwlock); // Accept the client and get the remote address... if ((client->http = httpAcceptConnection(sock, 1)) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to accept client connection: %s", strerror(errno)); free(client); return (NULL); } httpGetHostname(client->http, client->hostname, sizeof(client->hostname)); lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Accepted connection from '%s'.", client->hostname); return (client); } // // 'lprintDeleteClient()' - Close the socket and free all memory used by a client object. // void lprintDeleteClient( lprint_client_t *client) // I - Client { lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Closing connection from '%s'.", client->hostname); // Flush pending writes before closing... httpFlushWrite(client->http); // Free memory... httpClose(client->http); ippDelete(client->request); ippDelete(client->response); free(client); } // // 'lprintProcessClient()' - Process client requests on a thread. // void * // O - Exit status lprintProcessClient( lprint_client_t *client) // I - Client { int first_time = 1; // First time request? // Loop until we are out of requests or timeout (30 seconds)... while (httpWait(client->http, 30000)) { if (first_time) { // See if we need to negotiate a TLS connection... char buf[1]; // First byte from client if (recv(httpGetFd(client->http), buf, 1, MSG_PEEK) == 1 && (!buf[0] || !strchr("DGHOPT", buf[0]))) { lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Starting HTTPS session."); if (httpEncryption(client->http, HTTP_ENCRYPTION_ALWAYS)) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Unable to encrypt connection: %s", cupsLastErrorString()); break; } lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Connection now encrypted."); } first_time = 0; } if (!lprintProcessHTTP(client)) break; } // Close the conection to the client and return... lprintDeleteClient(client); return (NULL); } // // 'lprintProcessHTTP()' - Process a HTTP request. // int // O - 1 on success, 0 on failure lprintProcessHTTP( lprint_client_t *client) // I - Client connection { char uri[1024]; // URI http_state_t http_state; // HTTP state http_status_t http_status; // HTTP status ipp_state_t ipp_state; // State of IPP transfer char scheme[32], // Method/scheme userpass[128], // Username:password hostname[HTTP_MAX_HOST]; // Hostname int port; // Port number int i; // Looping var const lprint_resource_t *resource; // Current resource static const char * const http_states[] = { // Strings for logging HTTP method "WAITING", "OPTIONS", "GET", "GET_SEND", "HEAD", "POST", "POST_RECV", "POST_SEND", "PUT", "PUT_RECV", "DELETE", "TRACE", "CONNECT", "STATUS", "UNKNOWN_METHOD", "UNKNOWN_VERSION" }; const lprint_resource_t resources[] = { { "/lprint-de.strings", "text/strings", lprint_de_strings, 0 }, { "/lprint-en.strings", "text/strings", lprint_en_strings, 0 }, { "/lprint-es.strings", "text/strings", lprint_es_strings, 0 }, { "/lprint-fr.strings", "text/strings", lprint_fr_strings, 0 }, { "/lprint-it.strings", "text/strings", lprint_it_strings, 0 }, { "/lprint.png", "image/png", lprint_png, sizeof(lprint_png) }, { "/lprint-large.png", "image/png", lprint_large_png, sizeof(lprint_large_png) } }; // Clear state variables... ippDelete(client->request); ippDelete(client->response); client->request = NULL; client->response = NULL; client->operation = HTTP_STATE_WAITING; // Read a request from the connection... while ((http_state = httpReadRequest(client->http, uri, sizeof(uri))) == HTTP_STATE_WAITING) usleep(1); // Parse the request line... if (http_state == HTTP_STATE_ERROR) { if (httpError(client->http) == EPIPE) lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Client closed connection."); else lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "Bad request line (%s).", strerror(httpError(client->http))); return (0); } else if (http_state == HTTP_STATE_UNKNOWN_METHOD) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Bad/unknown operation."); lprintRespondHTTP(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } else if (http_state == HTTP_STATE_UNKNOWN_VERSION) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Bad HTTP version."); lprintRespondHTTP(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "%s %s", http_states[http_state], uri); // Separate the URI into its components... if (httpSeparateURI(HTTP_URI_CODING_MOST, uri, scheme, sizeof(scheme), userpass, sizeof(userpass), hostname, sizeof(hostname), &port, client->uri, sizeof(client->uri)) < HTTP_URI_STATUS_OK && (http_state != HTTP_STATE_OPTIONS || strcmp(uri, "*"))) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Bad URI '%s'.", uri); lprintRespondHTTP(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } if ((client->options = strchr(client->uri, '?')) != NULL) *(client->options)++ = '\0'; // Process the request... client->start = time(NULL); client->operation = httpGetState(client->http); // Parse incoming parameters until the status changes... while ((http_status = httpUpdate(client->http)) == HTTP_STATUS_CONTINUE); if (http_status != HTTP_STATUS_OK) { lprintRespondHTTP(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } if (!httpGetField(client->http, HTTP_FIELD_HOST)[0] && httpGetVersion(client->http) >= HTTP_VERSION_1_1) { // HTTP/1.1 and higher require the "Host:" field... lprintRespondHTTP(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } // Handle HTTP Upgrade... if (!strcasecmp(httpGetField(client->http, HTTP_FIELD_CONNECTION), "Upgrade")) { if (strstr(httpGetField(client->http, HTTP_FIELD_UPGRADE), "TLS/") != NULL && !httpIsEncrypted(client->http)) { if (!lprintRespondHTTP(client, HTTP_STATUS_SWITCHING_PROTOCOLS, NULL, NULL, 0)) return (0); lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Upgrading to encrypted connection."); if (httpEncryption(client->http, HTTP_ENCRYPTION_REQUIRED)) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "Unable to encrypt connection: %s", cupsLastErrorString()); return (0); } lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Connection now encrypted."); } else if (!lprintRespondHTTP(client, HTTP_STATUS_NOT_IMPLEMENTED, NULL, NULL, 0)) return (0); } // Handle HTTP Expect... if (httpGetExpect(client->http) && (client->operation == HTTP_STATE_POST || client->operation == HTTP_STATE_PUT)) { if (httpGetExpect(client->http) == HTTP_STATUS_CONTINUE) { // Send 100-continue header... if (!lprintRespondHTTP(client, HTTP_STATUS_CONTINUE, NULL, NULL, 0)) return (0); } else { // Send 417-expectation-failed header... if (!lprintRespondHTTP(client, HTTP_STATUS_EXPECTATION_FAILED, NULL, NULL, 0)) return (0); } } // Handle new transfers... switch (client->operation) { case HTTP_STATE_OPTIONS : // Do OPTIONS command... return (lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, NULL, 0)); case HTTP_STATE_HEAD : if (!strcmp(client->uri, "/")) return (lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0)); else if (client->system->auth_service && (!strcmp(client->uri, "/add") || !strncmp(client->uri, "/default/", 9) || !strncmp(client->uri, "/delete/", 8) || !strncmp(client->uri, "/modify/", 8))) return (lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0)); for (i = (int)(sizeof(resources) / sizeof(resources[0])), resource = resources; i > 0; i --, resource ++) { if (!strcmp(resource->path, client->uri)) { return (lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, resource->content_type, 0)); } } return (lprintRespondHTTP(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); case HTTP_STATE_GET : if (!strcmp(client->uri, "/")) { // Show web status page... return (show_status(client)); } else if (client->system->auth_service) { // Show management pages? if (!strcmp(client->uri, "/add")) return (show_add(client)); else if (!strncmp(client->uri, "/default/", 9)) return (show_default(client, atoi(client->uri + 9))); else if (!strncmp(client->uri, "/delete/", 8)) return (show_delete(client, atoi(client->uri + 8))); else if (!strncmp(client->uri, "/modify/", 8)) return (show_modify(client, atoi(client->uri + 8))); } for (i = (int)(sizeof(resources) / sizeof(resources[0])), resource = resources; i > 0; i --, resource ++) { if (!strcmp(resource->path, client->uri)) { // Send resource file... size_t length; // Length if ((length = resource->length) == 0) length = strlen((char *)resource->data); if (!lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, resource->content_type, length)) return (0); httpWrite2(client->http, (const char *)resource->data, length); httpFlushWrite(client->http); return (1); } } return (lprintRespondHTTP(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); case HTTP_STATE_POST : if (client->system->auth_service) { // Process management pages? if (!strcmp(client->uri, "/add")) return (show_add(client)); else if (!strncmp(client->uri, "/default/", 9)) return (show_default(client, atoi(client->uri + 9))); else if (!strncmp(client->uri, "/delete/", 8)) return (show_delete(client, atoi(client->uri + 8))); else if (!strncmp(client->uri, "/modify/", 8)) return (show_modify(client, atoi(client->uri + 8))); } if (strcmp(httpGetField(client->http, HTTP_FIELD_CONTENT_TYPE), "application/ipp")) { // Not an IPP request... return (lprintRespondHTTP(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0)); } // Read the IPP request... client->request = ippNew(); while ((ipp_state = ippRead(client->http, client->request)) != IPP_STATE_DATA) { if (ipp_state == IPP_STATE_ERROR) { lprintLogClient(client, LPRINT_LOGLEVEL_ERROR, "IPP read error (%s).", cupsLastErrorString()); lprintRespondHTTP(client, HTTP_STATUS_BAD_REQUEST, NULL, NULL, 0); return (0); } } // Now that we have the IPP request, process the request... return (lprintProcessIPP(client)); default : break; // Anti-compiler-warning-code } return (1); } // // 'lprintRespondHTTP()' - Send a HTTP response. // int // O - 1 on success, 0 on failure lprintRespondHTTP( lprint_client_t *client, // I - Client http_status_t code, // I - HTTP status of response const char *content_encoding, // I - Content-Encoding of response const char *type, // I - MIME media type of response size_t length) // I - Length of response { char message[1024]; // Text message lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "%s %s %d", httpStatus(code), type, (int)length); if (code == HTTP_STATUS_CONTINUE) { // 100-continue doesn't send any headers... return (httpWriteResponse(client->http, HTTP_STATUS_CONTINUE) == 0); } // Format an error message... if (!type && !length && code != HTTP_STATUS_OK && code != HTTP_STATUS_SWITCHING_PROTOCOLS) { snprintf(message, sizeof(message), "%d - %s\n", code, httpStatus(code)); type = "text/plain"; length = strlen(message); } else message[0] = '\0'; // Send the HTTP response header... httpClearFields(client->http); if (code == HTTP_STATUS_METHOD_NOT_ALLOWED || client->operation == HTTP_STATE_OPTIONS) httpSetField(client->http, HTTP_FIELD_ALLOW, "GET, HEAD, OPTIONS, POST"); if (code == HTTP_STATUS_UNAUTHORIZED) httpSetField(client->http, HTTP_FIELD_WWW_AUTHENTICATE, "Basic realm=\"LPrint\""); if (type) { if (!strcmp(type, "text/html")) httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, "text/html; charset=utf-8"); else httpSetField(client->http, HTTP_FIELD_CONTENT_TYPE, type); if (content_encoding) httpSetField(client->http, HTTP_FIELD_CONTENT_ENCODING, content_encoding); } httpSetLength(client->http, length); if (code == HTTP_STATUS_UPGRADE_REQUIRED && client->operation == HTTP_STATE_GET) { char redirect[1024]; // Redirect URI code = HTTP_STATUS_MOVED_PERMANENTLY; httpAssembleURI(HTTP_URI_CODING_ALL, redirect, sizeof(redirect), "https", NULL, client->system->hostname, client->system->port, client->uri); httpSetField(client->http, HTTP_FIELD_LOCATION, redirect); } if (httpWriteResponse(client->http, code) < 0) return (0); // Send the response data... if (message[0]) { // Send a plain text message. if (httpPrintf(client->http, "%s", message) < 0) return (0); if (httpWrite2(client->http, "", 0) < 0) return (0); } else if (client->response) { // Send an IPP response... lprintLogAttributes(client, "Response", client->response, 2); ippSetState(client->response, IPP_STATE_IDLE); if (ippWrite(client->http, client->response) != IPP_STATE_DATA) return (0); } return (1); } // // 'device_cb()' - Device callback. // static int // O - 1 to continue device_cb(const char *device_uri, // I - Device URI lprint_client_t *client) // I - Client { char scheme[32], // URI scheme userpass[32], // Username/password (unused) make[64], // Make from URI model[256], // Model from URI *serial; // Pointer to serial number int port; // Port number (unused) if (httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), userpass, sizeof(userpass), make, sizeof(make), &port, model, sizeof(model)) >= HTTP_URI_STATUS_OK) { if ((serial = strstr(model, "?serial=")) != NULL) { *serial = '\0'; serial += 8; } if (serial) html_printf(client, "", device_uri, make, model + 1, serial); else html_printf(client, "", device_uri, make, model + 1); } return (1); } // // 'get_form_data()' - Get POST form data from the web client. // static int // O - Number of form variables read get_form_data(lprint_client_t *client, // I - Client cups_option_t **form) // O - Form variables { int num_form = 0; // Number of form variables char body[8192], // Message body data string *ptr, // Pointer into string name[64], // Variable name *nameptr, // Pointer into name value[1024], // Variable value *valptr; // Pointer into value ssize_t bytes; // Bytes read http_state_t initial_state; // Initial HTTP state // Read form data... initial_state = httpGetState(client->http); for (ptr = body; ptr < (body + sizeof(body) - 1); ptr += bytes) { if ((bytes = httpRead2(client->http, ptr, sizeof(body) - (size_t)(ptr - body + 1))) <= 0) break; } *ptr = '\0'; if (httpGetState(client->http) == initial_state) httpFlush(client->http); // Flush remainder... // Parse the form data... *form = NULL; for (ptr = body; *ptr;) { // Get the name... nameptr = name; while (*ptr && *ptr != '=') { int ch = *ptr++; // Name character if (ch == '%' && isxdigit(ptr[0] & 255) && isxdigit(ptr[1] & 255)) { // Hex-encoded character if (isdigit(*ptr)) ch = (*ptr++ - '0') << 4; else ch = (tolower(*ptr++) - 'a' + 10) << 4; if (isdigit(*ptr)) ch |= *ptr++ - '0'; else ch |= tolower(*ptr++) - 'a' + 10; } else if (ch == '+') ch = ' '; if (nameptr < (name + sizeof(name) - 1)) *nameptr++ = ch; } *nameptr = '\0'; if (!*ptr) break; // Get the value... ptr ++; valptr = value; while (*ptr && *ptr != '&') { int ch = *ptr++; // Name character if (ch == '%' && isxdigit(ptr[0] & 255) && isxdigit(ptr[1] & 255)) { // Hex-encoded character if (isdigit(*ptr)) ch = (*ptr++ - '0') << 4; else ch = (tolower(*ptr++) - 'a' + 10) << 4; if (isdigit(*ptr)) ch |= *ptr++ - '0'; else ch |= tolower(*ptr++) - 'a' + 10; } else if (ch == '+') ch = ' '; if (valptr < (value + sizeof(value) - 1)) *valptr++ = ch; } *valptr = '\0'; if (*ptr) ptr ++; // Add the name + value to the option array... num_form = cupsAddOption(name, value, num_form, form); } return (num_form); } // // 'html_escape()' - Write a HTML-safe string. // static void html_escape(lprint_client_t *client, // I - Client const char *s, // I - String to write size_t slen) // I - Number of characters to write { const char *start, // Start of segment *end; // End of string start = s; end = s + (slen > 0 ? slen : strlen(s)); while (*s && s < end) { if (*s == '&' || *s == '<') { if (s > start) httpWrite2(client->http, start, (size_t)(s - start)); if (*s == '&') httpWrite2(client->http, "&", 5); else httpWrite2(client->http, "<", 4); start = s + 1; } s ++; } if (s > start) httpWrite2(client->http, start, (size_t)(s - start)); } // // 'html_footer()' - Show the web interface footer. // // This function also writes the trailing 0-length chunk. // static void html_footer(lprint_client_t *client) // I - Client { html_printf(client, "\n" "
Copyright 2019-2020 by Michael R Sweet. LPrint v" LPRINT_VERSION " is provided under the terms of the Apache License, Version 2.0.
\n" "\n" "\n"); httpWrite2(client->http, "", 0); } // // 'html_header()' - Show the web interface header and title. // static void html_header(lprint_client_t *client, // I - Client const char *title, // I - Title int refresh) // I - Refresh timer, if any { html_printf(client, "\n" "\n" "\n" "%s%sLPrint v" LPRINT_VERSION "\n" "\n" "\n" "\n", title, title ? " - " : ""); if (refresh > 0) html_printf(client, "\n", refresh); html_printf(client, "\n" "\n" "\n" "\n" "
\n" "

%s

\n", title); } // // 'html_printf()' - Send formatted text to the client, quoting as needed. // static void html_printf(lprint_client_t *client, // I - Client const char *format, // I - Printf-style format string ...) // I - Additional arguments as needed { va_list ap; // Pointer to arguments const char *start; // Start of string char size, // Size character (h, l, L) type; // Format type character int width, // Width of field prec; // Number of characters of precision char tformat[100], // Temporary format string for sprintf() *tptr, // Pointer into temporary format temp[1024]; // Buffer for formatted numbers char *s; // Pointer to string // Loop through the format string, formatting as needed... va_start(ap, format); start = format; while (*format) { if (*format == '%') { if (format > start) httpWrite2(client->http, start, (size_t)(format - start)); tptr = tformat; *tptr++ = *format++; if (*format == '%') { httpWrite2(client->http, "%", 1); format ++; start = format; continue; } else if (strchr(" -+#\'", *format)) *tptr++ = *format++; if (*format == '*') { // Get width from argument... format ++; width = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", width); tptr += strlen(tptr); } else { width = 0; while (isdigit(*format & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; width = width * 10 + *format++ - '0'; } } if (*format == '.') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; format ++; if (*format == '*') { // Get precision from argument... format ++; prec = va_arg(ap, int); snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", prec); tptr += strlen(tptr); } else { prec = 0; while (isdigit(*format & 255)) { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; prec = prec * 10 + *format++ - '0'; } } } if (*format == 'l' && format[1] == 'l') { size = 'L'; if (tptr < (tformat + sizeof(tformat) - 2)) { *tptr++ = 'l'; *tptr++ = 'l'; } format += 2; } else if (*format == 'h' || *format == 'l' || *format == 'L') { if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; size = *format++; } else size = 0; if (!*format) { start = format; break; } if (tptr < (tformat + sizeof(tformat) - 1)) *tptr++ = *format; type = *format++; *tptr = '\0'; start = format; switch (type) { case 'E' : // Floating point formats case 'G' : case 'e' : case 'f' : case 'g' : if ((size_t)(width + 2) > sizeof(temp)) break; sprintf(temp, tformat, va_arg(ap, double)); httpWrite2(client->http, temp, strlen(temp)); break; case 'B' : // Integer formats case 'X' : case 'b' : case 'd' : case 'i' : case 'o' : case 'u' : case 'x' : if ((size_t)(width + 2) > sizeof(temp)) break; # ifdef HAVE_LONG_LONG if (size == 'L') sprintf(temp, tformat, va_arg(ap, long long)); else # endif // HAVE_LONG_LONG if (size == 'l') sprintf(temp, tformat, va_arg(ap, long)); else sprintf(temp, tformat, va_arg(ap, int)); httpWrite2(client->http, temp, strlen(temp)); break; case 'p' : // Pointer value if ((size_t)(width + 2) > sizeof(temp)) break; sprintf(temp, tformat, va_arg(ap, void *)); httpWrite2(client->http, temp, strlen(temp)); break; case 'c' : // Character or character array if (width <= 1) { temp[0] = (char)va_arg(ap, int); temp[1] = '\0'; html_escape(client, temp, 1); } else html_escape(client, va_arg(ap, char *), (size_t)width); break; case 's' : // String if ((s = va_arg(ap, char *)) == NULL) s = "(null)"; html_escape(client, s, strlen(s)); break; } } else format ++; } if (format > start) httpWrite2(client->http, start, (size_t)(format - start)); va_end(ap); } // // 'media_chooser()' - Show the media chooser. static void media_chooser( lprint_client_t *client, // I - Client lprint_printer_t *printer, // I - Printer const char *title, // I - Label/title const char *name, // I - Base name lprint_media_col_t *media) // I - Current media values { int i; // Looping var pwg_media_t *pwg; // PWG media size info char text[256]; // Human-readable value/text lprint_driver_t *driver = printer->driver; // Driver info html_printf(client, "%s"); } // // 'media_parse()' - Parse media values. // static void media_parse( const char *name, // I - Base name lprint_media_col_t *media, // I - Media values int num_form, // I - Number of form values cups_option_t *form) // I - Form values { char varname[64]; // Variable name const char *value; // Variable value snprintf(varname, sizeof(varname), "%s-size", name); if ((value = cupsGetOption(varname, num_form, form)) != NULL) { pwg_media_t *pwg; // PWG media size strlcpy(media->size_name, value, sizeof(media->size_name)); if ((pwg = pwgMediaForPWG(value)) != NULL) { media->size_width = pwg->width; media->size_length = pwg->length; } else { media->size_width = 0; media->size_length = 0; } } snprintf(varname, sizeof(varname), "%s-tracking", name); if ((value = cupsGetOption(varname, num_form, form)) != NULL) media->tracking = lprintMediaTrackingValue(value); snprintf(varname, sizeof(varname), "%s-type", name); if ((value = cupsGetOption(varname, num_form, form)) != NULL) strlcpy(media->type, value, sizeof(media->type)); } // // 'show_add()' - Show the add printer page. // static int // O - 1 on success, 0 on failure show_add(lprint_client_t *client) // I - Client connection { http_status_t status; // Authorization status int num_form = 0; // Number of form variables cups_option_t *form = NULL; // Form variables const char *session = NULL, // Session key *printer_name = NULL, // Printer name *lprint_driver = NULL, // Driver name *device_uri = NULL, // Device URI *socket_address = NULL, // Socket device address *ptr, // Pointer into value *error = NULL; // Error message, if any int i, // Looping var num_drivers; // Number of drivers in list const char * const *drivers; // Driver list if ((status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { // Need authentication... return (lprintRespondHTTP(client, status, NULL, NULL, 0)); } if (client->operation == HTTP_STATE_POST) { // Get form data... int valid = 1; num_form = get_form_data(client, &form); session = cupsGetOption("session-key", num_form, form); printer_name = cupsGetOption("printer-name", num_form, form); lprint_driver = cupsGetOption("lprint-driver", num_form, form); device_uri = cupsGetOption("device-uri", num_form, form); socket_address = cupsGetOption("socket-address", num_form, form); if (!session || strcmp(session, client->system->session_key)) { valid = 0; error = "Bad or missing session key."; } if (valid && printer_name) { if (!*printer_name) { valid = 0; error = "Empty printer name."; } else if (strlen(printer_name) > 127) { valid = 0; error = "Printer name too long."; } for (ptr = printer_name; valid && *ptr; ptr ++) { if (!isalnum(*ptr & 255) && *ptr != '.' && *ptr != '-') { valid = 0; error = "Bad printer name - use only letters, numbers, '.', and '-'."; break; } } if (valid) { char resource[1024]; // Resource path for printer snprintf(resource, sizeof(resource), "/ipp/print/%s", printer_name); if (lprintFindPrinter(client->system, resource, 0)) { valid = 0; error = "A printer with that name already exists."; } } } if (valid && lprint_driver && !lprintGetMakeAndModel(lprint_driver)) { valid = 0; error = "Bad driver."; } if (device_uri && strncmp(device_uri, "usb://", 6)) { if (strcmp(device_uri, "socket")) { valid = 0; error = "Bad device."; } else if (!socket_address || !*socket_address) { valid = 0; error = "Bad network address."; } } if (valid) { // Add the printer... lprint_printer_t *printer; // Printer char uri[1024]; // Socket URI if (!strcmp(device_uri, "socket")) { httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "socket", NULL, socket_address, 9100, "/"); device_uri = uri; } printer = lprintCreatePrinter(client->system, 0, printer_name, lprint_driver, device_uri, NULL, NULL, NULL, NULL); if (printer) { if (!client->system->save_time) client->system->save_time = time(NULL) + 1; lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); html_header(client, "Printer Added", 0); html_printf(client, "

\n", printer->printer_id); html_footer(client); return (1); } else error = "Printer creation failed."; } } lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); html_header(client, "Add Printer", 0); html_printf(client, "

\n"); if (error) html_printf(client, "
Error: %s
\n", error); html_printf(client, "
" "" "\n" "\n" "\n", socket_address ? socket_address : ""); html_printf(client, "\n"); html_printf(client, "\n" "
Name:
Device:
\n" "
Driver:
\n"); html_footer(client); cupsFreeOptions(num_form, form); return (1); } // // 'show_default()' - Show the set default printer page. // static int // O - 1 on success, 0 on failure show_default(lprint_client_t *client, // I - Client connection int printer_id)// I - Printer ID { lprint_printer_t *printer; // Printer http_status_t status; // Authorization status int num_form = 0; // Number of form variables cups_option_t *form = NULL; // Form variables const char *session = NULL, // Session key *error = NULL; // Error message, if any char title[1024]; // Title for page if ((printer = lprintFindPrinter(client->system, NULL, printer_id)) == NULL) { // Printer not found... return (lprintRespondHTTP(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); } if ((status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { // Need authentication... return (lprintRespondHTTP(client, status, NULL, NULL, 0)); } if (client->operation == HTTP_STATE_POST) { // Get form data... int valid = 1; num_form = get_form_data(client, &form); session = cupsGetOption("session-key", num_form, form); if (!session || strcmp(session, client->system->session_key)) { valid = 0; error = "Bad or missing session key."; } if (valid) { // Set as default... client->system->default_printer = printer_id; if (!client->system->save_time) client->system->save_time = time(NULL) + 1; lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); snprintf(title, sizeof(title), "Default Printer Set to '%s'", printer->printer_name); html_header(client, title, 0); html_printf(client, "

\n"); html_footer(client); return (1); } } lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); snprintf(title, sizeof(title), "Set '%s' As Default Printer", printer->printer_name); html_header(client, title, 0); html_printf(client, "

\n"); if (error) html_printf(client, "
Error: %s
\n", error); html_printf(client, "
" "" "\n" "\n" "
Confirm:
\n", printer_id, client->system->session_key, printer->printer_name); html_footer(client); cupsFreeOptions(num_form, form); return (1); } // // 'show_delete()' - Show the delete printer page. // static int // O - 1 on success, 0 on failure show_delete(lprint_client_t *client, // I - Client connection int printer_id) // I - Printer ID { lprint_printer_t *printer; // Printer http_status_t status; // Authorization status int num_form = 0; // Number of form variables cups_option_t *form = NULL; // Form variables const char *session = NULL, // Session key *error = NULL; // Error message, if any char title[1024]; // Title for page if ((printer = lprintFindPrinter(client->system, NULL, printer_id)) == NULL) { // Printer not found... return (lprintRespondHTTP(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); } if ((status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { // Need authentication... return (lprintRespondHTTP(client, status, NULL, NULL, 0)); } if (client->operation == HTTP_STATE_POST) { // Get form data... int valid = 1; num_form = get_form_data(client, &form); session = cupsGetOption("session-key", num_form, form); if (!session || strcmp(session, client->system->session_key)) { valid = 0; error = "Bad or missing session key."; } if (valid) { // Delete printer... if (!printer->processing_job) { lprintDeletePrinter(printer); printer = NULL; } else printer->is_deleted = 1; if (!client->system->save_time) client->system->save_time = time(NULL) + 1; lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); html_header(client, printer ? "Deleting Printer" : "Printer Deleted", 0); html_printf(client, "

\n"); html_footer(client); return (1); } } lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); snprintf(title, sizeof(title), "Delete Printer '%s'", printer->printer_name); html_header(client, title, 0); html_printf(client, "

\n"); if (error) html_printf(client, "
Error: %s
\n", error); html_printf(client, "
" "" "\n" "\n" "
Confirm:
\n", printer_id, client->system->session_key, printer->printer_name); html_footer(client); cupsFreeOptions(num_form, form); return (1); } // // 'show_modify()' - Show the modify printer page. // static int // O - 1 on success, 0 on failure show_modify(lprint_client_t *client, // I - Client connection int printer_id) // I - Printer ID { lprint_printer_t *printer; // Printer http_status_t status; // Authorization status int num_form = 0; // Number of form variables cups_option_t *form = NULL; // Form variables const char *session = NULL, // Session key *location = NULL, // Human-readable location *latitude = NULL, // Latitude *longitude = NULL, // Longitude *organization = NULL, // Organization *org_unit = NULL, // Organizational unit *error = NULL; // Error message, if any char title[1024]; // Title for page float latval = 0.0f, // Latitude in degrees lonval = 0.0f; // Longitude in degrees if ((printer = lprintFindPrinter(client->system, NULL, printer_id)) == NULL) { // Printer not found... return (lprintRespondHTTP(client, HTTP_STATUS_NOT_FOUND, NULL, NULL, 0)); } if ((status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { // Need authentication... return (lprintRespondHTTP(client, status, NULL, NULL, 0)); } if (client->operation == HTTP_STATE_POST) { // Get form data... int valid = 1; // Is form data valid? num_form = get_form_data(client, &form); session = cupsGetOption("session-key", num_form, form); location = cupsGetOption("printer-location", num_form, form); latitude = cupsGetOption("latitude", num_form, form); longitude = cupsGetOption("longitude", num_form, form); organization = cupsGetOption("printer-organization", num_form, form); org_unit = cupsGetOption("printer-organizational-unit", num_form, form); if (!session || strcmp(session, client->system->session_key)) { valid = 0; error = "Bad or missing session key."; } if (valid && latitude) { latval = atof(latitude); if (*latitude && (!strchr("0123456789.-+", *latitude) || latval < -90.0f || latval > 90.0f)) { valid = 0; error = "Bad latitude value."; } } if (valid && longitude) { lonval = atof(longitude); if (*longitude && (!strchr("0123456789.-+", *longitude) || lonval < -180.0f || lonval > 180.0f)) { valid = 0; error = "Bad longitude value."; } } if (valid && latitude && longitude && !*latitude != !*longitude) { valid = 0; error = "Both latitude and longitude must be specified."; } if (valid) { pthread_rwlock_wrlock(&printer->rwlock); if (location) { free(printer->location); printer->location = strdup(location); } if (latitude && *latitude && longitude && *longitude) { char geo[1024]; // geo: URI snprintf(geo, sizeof(geo), "geo:%g,%g", atof(latitude), atof(longitude)); free(printer->geo_location); printer->geo_location = strdup(geo); } else if (latitude && longitude) { free(printer->geo_location); printer->geo_location = NULL; } if (organization) { free(printer->organization); printer->organization = strdup(organization); } if (org_unit) { free(printer->org_unit); printer->org_unit = strdup(org_unit); } media_parse("media-ready0", printer->driver->media_ready + 0, num_form, form); if (printer->driver->num_source > 1) media_parse("media-ready1", printer->driver->media_ready + 1, num_form, form); printer->config_time = time(NULL); pthread_rwlock_unlock(&printer->rwlock); if (!client->system->save_time) client->system->save_time = time(NULL) + 1; lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); html_header(client, "Printer Modified", 0); html_printf(client, "

\n"); html_footer(client); return (1); } } if (!location) location = printer->location; if (latitude && longitude) { latval = atof(latitude); lonval = atof(longitude); } else if (printer->geo_location) sscanf(printer->geo_location, "geo:%f,%f", &latval, &lonval); if (!organization) organization = printer->organization; if (!org_unit) org_unit = printer->org_unit; lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0); snprintf(title, sizeof(title), "Modify Printer '%s'", printer->printer_name); html_header(client, title, 0); html_printf(client, "

\n"); if (error) html_printf(client, "
Error: %s
\n", error); html_printf(client, "
" "" "\n", printer_id, client->system->session_key); html_printf(client, "\n", location ? location : ""); html_printf(client, "\n", latval); html_printf(client, "\n", lonval); html_printf(client, "\n", organization ? organization : ""); html_printf(client, "\n", org_unit ? org_unit : ""); media_chooser(client, printer, "Main Roll:", "media-ready0", printer->driver->media_ready + 0); if (printer->driver->num_source > 1) media_chooser(client, printer, "Second Roll:", "media-ready1", printer->driver->media_ready + 1); html_printf(client, "\n" "
Location:
Latitude:
Longitude:
Organization:
Organizational Unit:
\n"); html_footer(client); cupsFreeOptions(num_form, form); return (1); } // // 'show_status()' - Show printer/system state. // static int // O - 1 on success, 0 on failure show_status(lprint_client_t *client) // I - Client connection { lprint_system_t *system = client->system; // System lprint_printer_t *printer; // Printer lprint_job_t *job; // Current job int i; // Looping var lprint_preason_t reason; // Current reason static const char * const reasons[] = // Reason strings { "Other", "Cover Open", "Media Empty", "Media Jam", "Media Low", "Media Needed" }; static const char * const state_colors[] = { // State colors "rgba(0,192,0,0.5)", // Idle "rgba(224,224,0,0.5)", // Processing "rgba(192,0,0,0.5)" // Stopped }; if (!lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "text/html", 0)) return (0); pthread_rwlock_rdlock(&system->rwlock); for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { if (printer->state == IPP_PSTATE_PROCESSING) break; } html_header(client, "Printers", printer ? 5 : 15); if (client->system->auth_service) html_printf(client, "

\n"); for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { html_printf(client, "

%s%s

\n" "

%s", printer->printer_name, printer->printer_id == client->system->default_printer ? " (Default)" : "", state_colors[printer->state - IPP_PSTATE_IDLE], lprintGetMakeAndModel(printer->driver_name)); if (printer->location) html_printf(client, ", %s", printer->location); if (printer->organization) html_printf(client, "
\n%s%s%s", printer->organization, printer->org_unit ? ", " : "", printer->org_unit ? printer->org_unit : ""); html_printf(client, "
\n" "%s, %d job(s)", printer->state == IPP_PSTATE_IDLE ? "Idle" : printer->state == IPP_PSTATE_PROCESSING ? "Printing" : "Stopped", cupsArrayCount(printer->jobs)); for (i = 0, reason = 1; i < (int)(sizeof(reasons) / sizeof(reasons[0])); i ++, reason <<= 1) { if (printer->state_reasons & reason) html_printf(client, ",%s", reasons[i]); } html_printf(client, ".

\n"); if (client->system->auth_service) { html_printf(client, "

", printer->printer_id, printer->printer_id); if (printer->printer_id != client->system->default_printer) html_printf(client, " ", printer->printer_id); html_printf(client, "

\n"); } if (cupsArrayCount(printer->jobs) > 0) { pthread_rwlock_rdlock(&printer->rwlock); html_printf(client, "\n"); for (job = (lprint_job_t *)cupsArrayFirst(printer->jobs); job; job = (lprint_job_t *)cupsArrayNext(printer->jobs)) { char when[256], // When job queued/started/finished hhmmss[64]; // Time HH:MM:SS switch (job->state) { case IPP_JSTATE_PENDING : case IPP_JSTATE_HELD : snprintf(when, sizeof(when), "Queued at %s", time_string(job->created, hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_PROCESSING : case IPP_JSTATE_STOPPED : snprintf(when, sizeof(when), "Started at %s", time_string(job->processing, hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_ABORTED : snprintf(when, sizeof(when), "Aborted at %s", time_string(job->completed, hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_CANCELED : snprintf(when, sizeof(when), "Canceled at %s", time_string(job->completed, hhmmss, sizeof(hhmmss))); break; case IPP_JSTATE_COMPLETED : snprintf(when, sizeof(when), "Completed at %s", time_string(job->completed, hhmmss, sizeof(hhmmss))); break; } html_printf(client, "\n", job->id, job->name, job->username, when); } html_printf(client, "
Job #NameOwnerStatus
%d%s%s%s
\n"); pthread_rwlock_unlock(&printer->rwlock); } } html_footer(client); pthread_rwlock_unlock(&system->rwlock); return (1); } // // 'time_string()' - Return the local time in hours, minutes, and seconds. // static char * time_string(time_t tv, // I - Time value char *buffer, // I - Buffer size_t bufsize) // I - Size of buffer { struct tm date; // Local time and date localtime_r(&tv, &date); strftime(buffer, bufsize, "%X", &date); return (buffer); } lprint-1.0/server-dnssd.c000066400000000000000000000400671362261677400154720ustar00rootroot00000000000000// // DNS-SD support for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local globals... // #ifdef HAVE_DNSSD static DNSServiceRef dnssd_master = NULL; #elif defined(HAVE_AVAHI) static AvahiThreadedPoll *dnssd_master = NULL; static AvahiClient *dnssd_client = NULL; #endif // HAVE_DNSSD // // Local functions... // #ifdef HAVE_DNSSD static void DNSSD_API dnssd_callback(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, lprint_printer_t *printer); static void *dnssd_run(void *data); #elif defined(HAVE_AVAHI) static void dnssd_callback(AvahiEntryGroup *p, AvahiEntryGroupState state, void *context); static void dnssd_client_cb(AvahiClient *c, AvahiClientState state, void *userdata); #endif // HAVE_DNSSD // // 'lprintInitDNSSD()' - Initialize DNS-SD registration threads... // void lprintInitDNSSD(lprint_system_t *system)// I - System { #ifdef HAVE_DNSSD int err; // Status pthread_t tid; // Thread ID if ((err = DNSServiceCreateConnection(&dnssd_master)) != kDNSServiceErr_NoError) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to initialize DNS-SD (%d).", err); return; } if (pthread_create(&tid, NULL, dnssd_run, system)) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to create DNS-SD thread - %s", strerror(errno)); return; } pthread_detach(tid); #elif defined(HAVE_AVAHI) int error; // Error code, if any if ((dnssd_master = avahi_threaded_poll_new()) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to initialize DNS-SD."); return; } if ((dnssd_client = avahi_client_new(avahi_threaded_poll_get(dnssd_master), AVAHI_CLIENT_NO_FAIL, dnssd_client_cb, NULL, &error)) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to initialize DNS-SD (%d).", error); return; } avahi_threaded_poll_start(dnssd_master); #endif // HAVE_DNSSD } // // 'lprintRegisterDNSSD()' - Register a printer's DNS-SD service. // int // O - 1 on success, 0 on failure lprintRegisterDNSSD( lprint_printer_t *printer) // I - Printer { #if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) lprint_system_t *system = printer->system; // System lprint_txt_t ipp_txt; // Bonjour IPP TXT record int i, // Looping var count; // Number of values ipp_attribute_t *document_format_supported, *printer_kind, *printer_location, *printer_make_and_model, *printer_more_info, *printer_uuid, *urf_supported; // Printer attributes const char *value; // Value string char formats[252], // List of supported formats kind[251], // List of printer-kind values urf[252], // List of supported URF values *ptr; // Pointer into string char regtype[256]; // DNS-SD service type # ifdef HAVE_DNSSD DNSServiceErrorType error; // Error from mDNSResponder # endif // HAVE_DNSSD // Get attributes and values for the TXT record... document_format_supported = ippFindAttribute(printer->attrs, "document-format-supported", IPP_TAG_MIMETYPE); printer_kind = ippFindAttribute(printer->attrs, "printer-kind", IPP_TAG_KEYWORD); printer_location = ippFindAttribute(printer->attrs, "printer-location", IPP_TAG_TEXT); printer_make_and_model = ippFindAttribute(printer->attrs, "printer-make-and-model", IPP_TAG_TEXT); printer_more_info = ippFindAttribute(printer->attrs, "printer-more-info", IPP_TAG_URI); printer_uuid = ippFindAttribute(printer->attrs, "printer-uuid", IPP_TAG_URI); urf_supported = ippFindAttribute(printer->driver->attrs, "urf-supported", IPP_TAG_KEYWORD); for (i = 0, count = ippGetCount(document_format_supported), ptr = formats; i < count; i ++) { value = ippGetString(document_format_supported, i, NULL); if (!strcasecmp(value, "application/octet-stream")) continue; if (ptr > formats && ptr < (formats + sizeof(formats) - 1)) *ptr++ = ','; strlcpy(ptr, value, sizeof(formats) - (size_t)(ptr - formats)); ptr += strlen(ptr); if (ptr >= (formats + sizeof(formats) - 1)) break; } kind[0] = '\0'; for (i = 0, count = ippGetCount(printer_kind), ptr = kind; i < count; i ++) { value = ippGetString(printer_kind, i, NULL); if (ptr > kind && ptr < (kind + sizeof(kind) - 1)) *ptr++ = ','; strlcpy(ptr, value, sizeof(kind) - (size_t)(ptr - kind)); ptr += strlen(ptr); if (ptr >= (kind + sizeof(kind) - 1)) break; } urf[0] = '\0'; for (i = 0, count = ippGetCount(urf_supported), ptr = urf; i < count; i ++) { value = ippGetString(urf_supported, i, NULL); if (ptr > urf && ptr < (urf + sizeof(urf) - 1)) *ptr++ = ','; strlcpy(ptr, value, sizeof(urf) - (size_t)(ptr - urf)); ptr += strlen(ptr); if (ptr >= (urf + sizeof(urf) - 1)) break; } #endif // HAVE_DNSSD || HAVE_AVAHI #ifdef HAVE_DNSSD // Build the TXT record for IPP... TXTRecordCreate(&ipp_txt, 1024, NULL); TXTRecordSetValue(&ipp_txt, "rp", (uint8_t)strlen(printer->resource) - 1, printer->resource + 1); if ((value = ippGetString(printer_make_and_model, 0, NULL)) != NULL) TXTRecordSetValue(&ipp_txt, "ty", (uint8_t)strlen(value), value); if ((value = ippGetString(printer_more_info, 0, NULL)) != NULL) TXTRecordSetValue(&ipp_txt, "adminurl", (uint8_t)strlen(value), value); if ((value = ippGetString(printer_location, 0, NULL)) != NULL) TXTRecordSetValue(&ipp_txt, "note", (uint8_t)strlen(value), value); TXTRecordSetValue(&ipp_txt, "pdl", (uint8_t)strlen(formats), formats); if (kind[0]) TXTRecordSetValue(&ipp_txt, "kind", (uint8_t)strlen(kind), kind); if ((value = ippGetString(printer_uuid, 0, NULL)) != NULL) TXTRecordSetValue(&ipp_txt, "UUID", (uint8_t)strlen(value) - 9, value + 9); if (urf[0]) TXTRecordSetValue(&ipp_txt, "URF", (uint8_t)strlen(urf), urf); TXTRecordSetValue(&ipp_txt, "TLS", 3, "1.2"); TXTRecordSetValue(&ipp_txt, "txtvers", 1, "1"); TXTRecordSetValue(&ipp_txt, "qtotal", 1, "1"); // Register the _printer._tcp (LPD) service type with a port number of 0 to // defend our service name but not actually support LPD... printer->printer_ref = dnssd_master; if ((error = DNSServiceRegister(&(printer->printer_ref), kDNSServiceFlagsShareConnection, 0 /* interfaceIndex */, printer->dns_sd_name, "_printer._tcp", NULL /* domain */, NULL /* host */, 0 /* port */, 0 /* txtLen */, NULL /* txtRecord */, (DNSServiceRegisterReply)dnssd_callback, printer)) != kDNSServiceErr_NoError) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_ERROR, "Unable to register '%s._printer._tcp': %d", printer->dns_sd_name, error); return (0); } // Then register the corresponding IPP service types with the real port // number to advertise our printer... printer->ipp_ref = dnssd_master; if (system->subtypes && *system->subtypes) snprintf(regtype, sizeof(regtype), "_ipp._tcp,%s", system->subtypes); else strlcpy(regtype, "_ipp._tcp", sizeof(regtype)); if ((error = DNSServiceRegister(&(printer->ipp_ref), kDNSServiceFlagsShareConnection, 0 /* interfaceIndex */, printer->dns_sd_name, regtype, NULL /* domain */, system->hostname, htons(system->port), TXTRecordGetLength(&ipp_txt), TXTRecordGetBytesPtr(&ipp_txt), (DNSServiceRegisterReply)dnssd_callback, printer)) != kDNSServiceErr_NoError) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_ERROR, "Unable to register \"%s.%s\": %d", printer->dns_sd_name, regtype, error); return (0); } printer->ipps_ref = dnssd_master; if (system->subtypes && *system->subtypes) snprintf(regtype, sizeof(regtype), "_ipps._tcp,%s", system->subtypes); else strlcpy(regtype, "_ipps._tcp", sizeof(regtype)); if ((error = DNSServiceRegister(&(printer->ipps_ref), kDNSServiceFlagsShareConnection, 0 /* interfaceIndex */, printer->dns_sd_name, regtype, NULL /* domain */, system->hostname, htons(system->port), TXTRecordGetLength(&ipp_txt), TXTRecordGetBytesPtr(&ipp_txt), (DNSServiceRegisterReply)dnssd_callback, printer)) != kDNSServiceErr_NoError) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_ERROR, "Unable to register \"%s.%s\": %d", printer->dns_sd_name, regtype, error); return (0); } // Register the geolocation of the service... // TODO: Add GEOLOCATION // register_geo(printer); // Similarly, register the _http._tcp,_printer (HTTP) service type with the // real port number to advertise our IPP printer... printer->http_ref = dnssd_master; if ((error = DNSServiceRegister(&(printer->http_ref), kDNSServiceFlagsShareConnection, 0 /* interfaceIndex */, printer->dns_sd_name, "_http._tcp,_printer", NULL /* domain */, system->hostname, htons(system->port), 0 /* txtLen */, NULL /* txtRecord */, (DNSServiceRegisterReply)dnssd_callback, printer)) != kDNSServiceErr_NoError) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_ERROR, "Unable to register \"%s.%s\": %d", printer->dns_sd_name, "_http._tcp,_printer", error); return (0); } TXTRecordDeallocate(&ipp_txt); #elif defined(HAVE_AVAHI) // Create the TXT record... ipp_txt = NULL; ipp_txt = avahi_string_list_add_printf(ipp_txt, "rp=%s", printer->resource + 1); if ((value = ippGetString(printer_make_and_model, 0, NULL)) != NULL) ipp_txt = avahi_string_list_add_printf(ipp_txt, "ty=%s", value); if ((value = ippGetString(printer_more_info, 0, NULL)) != NULL) ipp_txt = avahi_string_list_add_printf(ipp_txt, "adminurl=%s", value); if ((value = ippGetString(printer_location, 0, NULL)) != NULL) ipp_txt = avahi_string_list_add_printf(ipp_txt, "note=%s", value); ipp_txt = avahi_string_list_add_printf(ipp_txt, "pdl=%s", formats); if ((value = ippGetString(printer_uuid, 0, NULL)) != NULL) ipp_txt = avahi_string_list_add_printf(ipp_txt, "UUID=%s", value + 9); if (urf[0]) ipp_txt = avahi_string_list_add_printf(ipp_txt, "URF=%s", urf); ipp_txt = avahi_string_list_add_printf(ipp_txt, "TLS=1.2"); ipp_txt = avahi_string_list_add_printf(ipp_txt, "txtvers=1"); ipp_txt = avahi_string_list_add_printf(ipp_txt, "qtotal=1"); // Register _printer._tcp (LPD) with port 0 to reserve the service name... avahi_threaded_poll_lock(dnssd_master); printer->dnssd_ref = avahi_entry_group_new(dnssd_client, dnssd_callback, NULL); avahi_entry_group_add_service_strlst(printer->dnssd_ref, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_printer._tcp", NULL, NULL, 0, NULL); // Then register the IPP/IPPS services... avahi_entry_group_add_service_strlst(printer->dnssd_ref, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipp._tcp", NULL, system->hostname, system->port, ipp_txt); if (system->subtypes && *system->subtypes) { char *temptypes = strdup(system->subtypes), *start, *end; for (start = temptypes; *start; start = end) { if ((end = strchr(start, ',')) != NULL) *end++ = '\0'; else end = start + strlen(start); snprintf(regtype, sizeof(regtype), "%s._sub._ipp._tcp", start); avahi_entry_group_add_service_subtype(printer->dnssd_ref, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipp._tcp", NULL, regtype); } free(temptypes); } avahi_entry_group_add_service_strlst(printer->dnssd_ref, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipps._tcp", NULL, system->hostname, system->port, ipp_txt); if (system->subtypes && *system->subtypes) { char *temptypes = strdup(system->subtypes), *start, *end; for (start = temptypes; *start; start = end) { if ((end = strchr(start, ',')) != NULL) *end++ = '\0'; else end = start + strlen(start); snprintf(regtype, sizeof(regtype), "%s._sub._ipps._tcp", start); avahi_entry_group_add_service_subtype(printer->dnssd_ref, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_ipps._tcp", NULL, regtype); } free(temptypes); } // Register the geolocation of the service... // TODO: Add GEOLOCATION // register_geo(printer); // Finally _http.tcp (HTTP) for the web interface... avahi_entry_group_add_service_strlst(printer->dnssd_ref, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_http._tcp", NULL, system->hostname, system->port, NULL); avahi_entry_group_add_service_subtype(printer->dnssd_ref, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, printer->dns_sd_name, "_http._tcp", NULL, "_printer._sub._http._tcp"); // Commit it... avahi_entry_group_commit(printer->dnssd_ref); avahi_threaded_poll_unlock(dnssd_master); avahi_string_list_free(ipp_txt); #endif // HAVE_DNSSD return (1); } // // 'lprintUnregisterDNSSD()' - Unregister a printer's DNS-SD service. // void lprintUnregisterDNSSD( lprint_printer_t *printer) // I - Printer { #if HAVE_DNSSD // TODO: Add GEOLOCATION support // if (printer->geo_ref) // { // DNSServiceRemoveRecord(printer->printer_ref, printer->geo_ref, 0); // printer->geo_ref = NULL; // } if (printer->printer_ref) { DNSServiceRefDeallocate(printer->printer_ref); printer->printer_ref = NULL; } if (printer->ipp_ref) { DNSServiceRefDeallocate(printer->ipp_ref); printer->ipp_ref = NULL; } if (printer->ipps_ref) { DNSServiceRefDeallocate(printer->ipps_ref); printer->ipps_ref = NULL; } if (printer->http_ref) { DNSServiceRefDeallocate(printer->http_ref); printer->http_ref = NULL; } #elif defined(HAVE_AVAHI) avahi_threaded_poll_lock(dnssd_master); if (printer->dnssd_ref) { avahi_entry_group_free(printer->dnssd_ref); printer->dnssd_ref = NULL; } avahi_threaded_poll_unlock(dnssd_master); #else (void)printer; #endif /* HAVE_DNSSD */ } #ifdef HAVE_DNSSD // // 'dnssd_callback()' - Handle Bonjour registration events. // static void DNSSD_API dnssd_callback( DNSServiceRef sdRef, // I - Service reference DNSServiceFlags flags, // I - Status flags DNSServiceErrorType errorCode, // I - Error, if any const char *name, // I - Service name const char *regtype, // I - Service type const char *domain, // I - Domain for service lprint_printer_t *printer) // I - Printer { (void)sdRef; (void)flags; (void)domain; if (errorCode) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_ERROR, "DNSServiceRegister for '%s' failed with error %d.", regtype, (int)errorCode); return; } else if (strcasecmp(name, printer->dns_sd_name)) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_INFO, "Now using DNS-SD service name '%s'.\n", name); pthread_rwlock_wrlock(&printer->rwlock); free(printer->dns_sd_name); printer->dns_sd_name = strdup(name); pthread_rwlock_unlock(&printer->rwlock); } } // // 'dnssd_run()' - Handle DNS-SD traffic. // static void * // O - Exit status dnssd_run(void *data) // I - System object { int err; // Status lprint_system_t *system = (lprint_system_t *)data; // System object for (;;) { if ((err = DNSServiceProcessResult(dnssd_master)) != kDNSServiceErr_NoError) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "DNSServiceProcessResult returned %d.", err); break; } } return (NULL); } #elif defined(HAVE_AVAHI) // // 'dnssd_callback()' - Handle Bonjour registration events. // static void dnssd_callback( AvahiEntryGroup *srv, // I - Service AvahiEntryGroupState state, // I - Registration state void *context) // I - Printer { (void)srv; (void)state; (void)context; } // //'dnssd_client_cb()' - Client callback for Avahi. // // Called whenever the client or server state changes... // static void dnssd_client_cb( AvahiClient *c, // I - Client AvahiClientState state, // I - Current state void *userdata) // I - User data (unused) { (void)userdata; if (!c) return; switch (state) { default : fprintf(stderr, "Ignored Avahi state %d.\n", state); break; case AVAHI_CLIENT_FAILURE: if (avahi_client_errno(c) == AVAHI_ERR_DISCONNECTED) { fputs("Avahi server crashed, exiting.\n", stderr); exit(1); } break; } } #endif // HAVE_DNSSD lprint-1.0/server-ipp.c000066400000000000000000002312741362261677400151510ustar00rootroot00000000000000// // IPP processing for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" // // Local type... // typedef struct lprint_attr_s // Input attribute structure { const char *name; // Attribute name ipp_tag_t value_tag; // Value tag int max_count; // Max number of values } lprint_attr_t; // // Local functions... // static void copy_job_attributes(lprint_client_t *client, lprint_job_t *job, cups_array_t *ra); static void copy_printer_attributes(lprint_client_t *client, lprint_printer_t *printer, cups_array_t *ra); static void copy_printer_state(ipp_t *ipp, lprint_printer_t *printer, cups_array_t *ra); static int filter_cb(lprint_filter_t *filter, ipp_t *dst, ipp_attribute_t *attr); static void finish_document_data(lprint_client_t *client, lprint_job_t *job); static void ipp_cancel_job(lprint_client_t *client); static void ipp_cancel_jobs(lprint_client_t *client); static void ipp_close_job(lprint_client_t *client); static void ipp_create_job(lprint_client_t *client); static void ipp_create_printer(lprint_client_t *client); static void ipp_delete_printer(lprint_client_t *client); static void ipp_get_job_attributes(lprint_client_t *client); static void ipp_get_jobs(lprint_client_t *client); static void ipp_get_printer_attributes(lprint_client_t *client); static void ipp_get_printers(lprint_client_t *client); static void ipp_get_system_attributes(lprint_client_t *client); static void ipp_identify_printer(lprint_client_t *client); static void ipp_print_job(lprint_client_t *client); static void ipp_send_document(lprint_client_t *client); static void ipp_set_printer_attributes(lprint_client_t *client); static void ipp_set_system_attributes(lprint_client_t *client); static void ipp_shutdown_all_printers(lprint_client_t *client); static void ipp_validate_job(lprint_client_t *client); static void respond_unsupported(lprint_client_t *client, ipp_attribute_t *attr); static int set_printer_attributes(lprint_client_t *client, lprint_printer_t *printer); static int valid_doc_attributes(lprint_client_t *client); static int valid_job_attributes(lprint_client_t *client); // // 'lprintCopyAttributes()' - Copy attributes from one message to another. // void lprintCopyAttributes( ipp_t *to, // I - Destination request ipp_t *from, // I - Source request cups_array_t *ra, // I - Requested attributes ipp_tag_t group_tag, // I - Group to copy int quickcopy) // I - Do a quick copy? { lprint_filter_t filter; // Filter data filter.ra = ra; filter.group_tag = group_tag; ippCopyAttributes(to, from, quickcopy, (ipp_copycb_t)filter_cb, &filter); } // // 'lprintProcessIPP()' - Process an IPP request. // int // O - 1 on success, 0 on error lprintProcessIPP( lprint_client_t *client) // I - Client { ipp_tag_t group; // Current group tag ipp_attribute_t *attr; // Current attribute ipp_attribute_t *charset; // Character set attribute ipp_attribute_t *language; // Language attribute ipp_attribute_t *uri; // Printer URI attribute int major, minor; // Version number ipp_op_t op; // Operation code const char *name; // Name of attribute lprintLogAttributes(client, "Request", client->request, 1); // First build an empty response message for this request... client->operation_id = ippGetOperation(client->request); client->response = ippNewResponse(client->request); // Then validate the request header and required attributes... major = ippGetVersion(client->request, &minor); op = ippGetOperation(client->request); if (major < 1 || major > 2) { // Return an error, since we only support IPP 1.x and 2.x. lprintRespondIPP(client, IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED, "Bad request version number %d.%d.", major, minor); } else if (ippGetRequestId(client->request) <= 0) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Bad request-id %d.", ippGetRequestId(client->request)); } else if (!ippFirstAttribute(client->request)) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "No attributes in request."); } else { // Make sure that the attributes are provided in the correct order and // don't repeat groups... for (attr = ippFirstAttribute(client->request), group = ippGetGroupTag(attr); attr; attr = ippNextAttribute(client->request)) { if (ippGetGroupTag(attr) < group && ippGetGroupTag(attr) != IPP_TAG_ZERO) { // Out of order; return an error... lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Attribute groups are out of order (%x < %x).", ippGetGroupTag(attr), group); break; } else group = ippGetGroupTag(attr); } if (!attr) { // Then make sure that the first three attributes are: // // attributes-charset // attributes-natural-language // system-uri/printer-uri/job-uri attr = ippFirstAttribute(client->request); name = ippGetName(attr); if (attr && name && !strcmp(name, "attributes-charset") && ippGetValueTag(attr) == IPP_TAG_CHARSET) charset = attr; else charset = NULL; attr = ippNextAttribute(client->request); name = ippGetName(attr); if (attr && name && !strcmp(name, "attributes-natural-language") && ippGetValueTag(attr) == IPP_TAG_LANGUAGE) language = attr; else language = NULL; if ((attr = ippFindAttribute(client->request, "system-uri", IPP_TAG_URI)) != NULL) uri = attr; else if ((attr = ippFindAttribute(client->request, "printer-uri", IPP_TAG_URI)) != NULL) uri = attr; else if ((attr = ippFindAttribute(client->request, "job-uri", IPP_TAG_URI)) != NULL) uri = attr; else uri = NULL; client->printer = NULL; client->job = NULL; if (charset && strcasecmp(ippGetString(charset, 0, NULL), "us-ascii") && strcasecmp(ippGetString(charset, 0, NULL), "utf-8")) { // Bad character set... lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Unsupported character set \"%s\".", ippGetString(charset, 0, NULL)); } else if (!charset || !language || (!uri && op != IPP_OP_CUPS_GET_DEFAULT && op != IPP_OP_CUPS_GET_PRINTERS)) { // Return an error, since attributes-charset, // attributes-natural-language, and system/printer/job-uri are required // for all operations. lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing required attributes."); } else { if (uri) { char scheme[32], // URI scheme userpass[32], // Username/password in URI host[256], // Host name in URI resource[256], // Resource path in URI *resptr; // Pointer into resource int port, // Port number in URI job_id; // Job ID name = ippGetName(uri); if (httpSeparateURI(HTTP_URI_CODING_ALL, ippGetString(uri, 0, NULL), scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) { lprintRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Bad %s value '%s'.", name, ippGetString(uri, 0, NULL)); } else if (!strcmp(name, "system-uri")) { if (strcmp(resource, "/ipp/system")) { lprintRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Bad %s value '%s'.", name, ippGetString(uri, 0, NULL)); } else client->printer = lprintFindPrinter(client->system, NULL, ippGetInteger(ippFindAttribute(client->request, "printer-id", IPP_TAG_INTEGER), 0)); } else if ((client->printer = lprintFindPrinter(client->system, resource, 0)) != NULL) { if (!strcmp(name, "job-uri") && (resptr = strrchr(resource, '/')) != NULL) job_id = atoi(resptr + 1); else job_id = ippGetInteger(ippFindAttribute(client->request, "job-id", IPP_TAG_INTEGER), 0); if (job_id) client->job = lprintFindJob(client->printer, job_id); } else { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "%s %s not found.", name, ippGetString(uri, 0, NULL)); } } if (ippGetStatusCode(client->response) == IPP_STATUS_OK) { if (client->printer) { // Try processing the printer operation... switch (ippGetOperation(client->request)) { case IPP_OP_PRINT_JOB : ipp_print_job(client); break; case IPP_OP_VALIDATE_JOB : ipp_validate_job(client); break; case IPP_OP_CREATE_JOB : ipp_create_job(client); break; case IPP_OP_SEND_DOCUMENT : ipp_send_document(client); break; case IPP_OP_CANCEL_JOB : case IPP_OP_CANCEL_CURRENT_JOB : ipp_cancel_job(client); break; case IPP_OP_CANCEL_JOBS : case IPP_OP_CANCEL_MY_JOBS : ipp_cancel_jobs(client); break; case IPP_OP_GET_JOB_ATTRIBUTES : ipp_get_job_attributes(client); break; case IPP_OP_GET_JOBS : ipp_get_jobs(client); break; case IPP_OP_GET_PRINTER_ATTRIBUTES : ipp_get_printer_attributes(client); break; case IPP_OP_SET_PRINTER_ATTRIBUTES : ipp_set_printer_attributes(client); break; case IPP_OP_CLOSE_JOB : ipp_close_job(client); break; case IPP_OP_IDENTIFY_PRINTER : ipp_identify_printer(client); break; default : lprintRespondIPP(client, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, "Operation not supported."); break; } } else { // Try processing the system operation... switch (ippGetOperation(client->request)) { case IPP_OP_CREATE_PRINTER : ipp_create_printer(client); break; case IPP_OP_DELETE_PRINTER : ipp_delete_printer(client); break; case IPP_OP_GET_PRINTERS : case IPP_OP_CUPS_GET_PRINTERS : ipp_get_printers(client); break; case IPP_OP_GET_PRINTER_ATTRIBUTES : case IPP_OP_CUPS_GET_DEFAULT : client->printer = lprintFindPrinter(client->system, NULL, client->system->default_printer); ipp_get_printer_attributes(client); break; case IPP_OP_GET_SYSTEM_ATTRIBUTES : ipp_get_system_attributes(client); break; case IPP_OP_SET_SYSTEM_ATTRIBUTES : ipp_set_system_attributes(client); break; case IPP_OP_SHUTDOWN_ALL_PRINTERS : ipp_shutdown_all_printers(client); break; default : lprintRespondIPP(client, IPP_STATUS_ERROR_OPERATION_NOT_SUPPORTED, "Operation not supported."); break; } } } } } } // Send the HTTP header and return... if (httpGetState(client->http) != HTTP_STATE_POST_SEND) httpFlush(client->http); // Flush trailing (junk) data return (lprintRespondHTTP(client, HTTP_STATUS_OK, NULL, "application/ipp", ippLength(client->response))); } // // 'lprintRespondIPP()' - Send an IPP response. // void lprintRespondIPP( lprint_client_t *client, // I - Client ipp_status_t status, // I - status-code const char *message, // I - printf-style status-message ...) // I - Additional args as needed { const char *formatted = NULL; // Formatted message ippSetStatusCode(client->response, status); if (message) { va_list ap; // Pointer to additional args ipp_attribute_t *attr; // New status-message attribute va_start(ap, message); if ((attr = ippFindAttribute(client->response, "status-message", IPP_TAG_TEXT)) != NULL) ippSetStringfv(client->response, &attr, 0, message, ap); else attr = ippAddStringfv(client->response, IPP_TAG_OPERATION, IPP_TAG_TEXT, "status-message", NULL, message, ap); va_end(ap); formatted = ippGetString(attr, 0, NULL); } if (formatted) lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "%s %s (%s)", ippOpString(client->operation_id), ippErrorString(status), formatted); else lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "%s %s", ippOpString(client->operation_id), ippErrorString(status)); } // // 'copy_job_attrs()' - Copy job attributes to the response. // static void copy_job_attributes( lprint_client_t *client, // I - Client lprint_job_t *job, // I - Job cups_array_t *ra) // I - requested-attributes { lprintCopyAttributes(client->response, job->attrs, ra, IPP_TAG_JOB, 0); if (!ra || cupsArrayFind(ra, "date-time-at-completed")) { if (job->completed) ippAddDate(client->response, IPP_TAG_JOB, "date-time-at-completed", ippTimeToDate(job->completed)); else ippAddOutOfBand(client->response, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-completed"); } if (!ra || cupsArrayFind(ra, "date-time-at-processing")) { if (job->processing) ippAddDate(client->response, IPP_TAG_JOB, "date-time-at-processing", ippTimeToDate(job->processing)); else ippAddOutOfBand(client->response, IPP_TAG_JOB, IPP_TAG_NOVALUE, "date-time-at-processing"); } if (!ra || cupsArrayFind(ra, "job-impressions")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions", job->impressions); if (!ra || cupsArrayFind(ra, "job-impressions-completed")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-impressions-completed", job->impcompleted); if (!ra || cupsArrayFind(ra, "job-printer-up-time")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-printer-up-time", (int)(time(NULL) - client->printer->start_time)); if (!ra || cupsArrayFind(ra, "job-state")) ippAddInteger(client->response, IPP_TAG_JOB, IPP_TAG_ENUM, "job-state", (int)job->state); if (!ra || cupsArrayFind(ra, "job-state-message")) { if (job->message) { ippAddString(client->response, IPP_TAG_JOB, IPP_TAG_TEXT, "job-state-message", NULL, job->message); } else { switch (job->state) { case IPP_JSTATE_PENDING : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job pending."); break; case IPP_JSTATE_HELD : if (job->fd >= 0) ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job incoming."); else if (ippFindAttribute(job->attrs, "job-hold-until", IPP_TAG_ZERO)) ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job held."); else ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job created."); break; case IPP_JSTATE_PROCESSING : if (job->cancel) ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job canceling."); else ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job printing."); break; case IPP_JSTATE_STOPPED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job stopped."); break; case IPP_JSTATE_CANCELED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job canceled."); break; case IPP_JSTATE_ABORTED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job aborted."); break; case IPP_JSTATE_COMPLETED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_TEXT), "job-state-message", NULL, "Job completed."); break; } } } if (!ra || cupsArrayFind(ra, "job-state-reasons")) { switch (job->state) { case IPP_JSTATE_PENDING : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "none"); break; case IPP_JSTATE_HELD : if (job->fd >= 0) ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-incoming"); else ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-data-insufficient"); break; case IPP_JSTATE_PROCESSING : if (job->cancel) ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "processing-to-stop-point"); else ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-printing"); break; case IPP_JSTATE_STOPPED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-stopped"); break; case IPP_JSTATE_CANCELED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-canceled-by-user"); break; case IPP_JSTATE_ABORTED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "aborted-by-system"); break; case IPP_JSTATE_COMPLETED : ippAddString(client->response, IPP_TAG_JOB, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-state-reasons", NULL, "job-completed-successfully"); break; } } if (!ra || cupsArrayFind(ra, "time-at-completed")) ippAddInteger(client->response, IPP_TAG_JOB, job->completed ? IPP_TAG_INTEGER : IPP_TAG_NOVALUE, "time-at-completed", (int)(job->completed - client->printer->start_time)); if (!ra || cupsArrayFind(ra, "time-at-processing")) ippAddInteger(client->response, IPP_TAG_JOB, job->processing ? IPP_TAG_INTEGER : IPP_TAG_NOVALUE, "time-at-processing", (int)(job->processing - client->printer->start_time)); } // // 'copy_printer_attributes()' - Copy printer attributes to a response... // static void copy_printer_attributes( lprint_client_t *client, // I - Client lprint_printer_t *printer, // I - Printer cups_array_t *ra) // I - Requested attributes { lprintCopyAttributes(client->response, printer->attrs, ra, IPP_TAG_ZERO, IPP_TAG_CUPS_CONST); lprintCopyAttributes(client->response, printer->driver->attrs, ra, IPP_TAG_ZERO, IPP_TAG_CUPS_CONST); copy_printer_state(client->response, printer, ra); if ((!ra || cupsArrayFind(ra, "media-col-default")) && printer->driver->media_default.size_name[0]) { ipp_t *col = lprintCreateMediaCol(&printer->driver->media_default, 0); // Collection value ippAddCollection(client->response, IPP_TAG_PRINTER, "media-col-default", col); ippDelete(col); } if (!ra || cupsArrayFind(ra, "media-col-ready")) { int i, j, // Looping vars count; // Number of values ipp_t *col; // Collection value ipp_attribute_t *attr; // media-col-ready attribute for (i = 0, count = 0; i < printer->driver->num_source; i ++) { if (printer->driver->media_ready[i].size_name[0]) count ++; } if (count > 0) { attr = ippAddCollections(client->response, IPP_TAG_PRINTER, "media-col-ready", count, NULL); for (i = 0, j = 0; i < printer->driver->num_source && j < count; i ++) { if (printer->driver->media_ready[i].size_name[0]) { col = lprintCreateMediaCol(printer->driver->media_ready + i, 0); ippSetCollection(client->response, &attr, j ++, col); ippDelete(col); } } } } if ((!ra || cupsArrayFind(ra, "media-default")) && printer->driver->media_default.size_name[0]) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-default", NULL, printer->driver->media_default.size_name); if (!ra || cupsArrayFind(ra, "media-ready")) { int i, j, // Looping vars count; // Number of values ipp_attribute_t *attr; // media-col-ready attribute for (i = 0, count = 0; i < printer->driver->num_source; i ++) { if (printer->driver->media_ready[i].size_name[0]) count ++; } if (count > 0) { attr = ippAddStrings(client->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "media-ready", count, NULL, NULL); for (i = 0, j = 0; i < printer->driver->num_source && j < count; i ++) { if (printer->driver->media_ready[i].size_name[0]) ippSetString(client->response, &attr, j ++, printer->driver->media_ready[i].size_name); } } } if (!ra || cupsArrayFind(ra, "printer-config-change-date-time")) ippAddDate(client->response, IPP_TAG_PRINTER, "printer-config-change-date-time", ippTimeToDate(printer->config_time)); if (!ra || cupsArrayFind(ra, "printer-config-change-time")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-config-change-time", (int)(printer->config_time - printer->start_time)); if (!ra || cupsArrayFind(ra, "printer-current-time")) ippAddDate(client->response, IPP_TAG_PRINTER, "printer-current-time", ippTimeToDate(time(NULL))); if (!ra || cupsArrayFind(ra, "printer-geo-location")) { if (printer->geo_location) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-geo-location", NULL, printer->geo_location); else ippAddOutOfBand(client->response, IPP_TAG_PRINTER, IPP_TAG_UNKNOWN, "printer-geo-location"); } if (!ra || cupsArrayFind(ra, "printer-is-accepting-jobs")) ippAddBoolean(client->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", !printer->system->shutdown_time); if (!ra || cupsArrayFind(ra, "printer-location")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location", NULL, printer->location ? printer->location : ""); if (!ra || cupsArrayFind(ra, "printer-organization")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organization", NULL, printer->organization ? printer->organization : ""); if (!ra || cupsArrayFind(ra, "printer-organizational-unit")) ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-organizational-unit", NULL, printer->org_unit ? printer->org_unit : ""); if (!ra || cupsArrayFind(ra, "printer-state-change-date-time")) ippAddDate(client->response, IPP_TAG_PRINTER, "printer-state-change-date-time", ippTimeToDate(printer->state_time)); if (!ra || cupsArrayFind(ra, "printer-state-change-time")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-state-change-time", (int)(printer->state_time - printer->start_time)); if (!ra || cupsArrayFind(ra, "printer-strings-uri")) { const char *lang = ippGetString(ippFindAttribute(client->request, "attributes-natural-language", IPP_TAG_LANGUAGE), 0, NULL); // Language char baselang[3], // Base language uri[1024]; // Strings file URI strlcpy(baselang, lang, sizeof(baselang)); if (!strcmp(baselang, "de") || !strcmp(baselang, "en") || !strcmp(baselang, "es") || !strcmp(baselang, "fr") || !strcmp(baselang, "it")) { httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "https", NULL, client->system->hostname ? client->system->hostname : "localhost", client->system->port, "/lprint-%s.strings", baselang); ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-strings-uri", NULL, uri); } } if (!ra || cupsArrayFind(ra, "printer-up-time")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-up-time", (int)(time(NULL) - printer->start_time)); if (!ra || cupsArrayFind(ra, "queued-job-count")) ippAddInteger(client->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "queued-job-count", cupsArrayCount(printer->active_jobs)); } // // 'copy_printer_state()' - Copy the printer-state-xxx attributes. // static void copy_printer_state( ipp_t *ipp, // I - IPP message lprint_printer_t *printer, // I - Printer cups_array_t *ra) // I - Requested attributes { if (!ra || cupsArrayFind(ra, "printer-state")) ippAddInteger(ipp, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", (int)printer->state); if (!ra || cupsArrayFind(ra, "printer-state-message")) { static const char * const messages[] = { "Idle.", "Printing.", "Stopped." }; ippAddString(ipp, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_TEXT), "printer-state-message", NULL, messages[printer->state - IPP_PSTATE_IDLE]); } if (!ra || cupsArrayFind(ra, "printer-state-reasons")) { if (printer->state_reasons == LPRINT_PREASON_NONE) { ippAddString(ipp, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-state-reasons", NULL, "none"); } else { ipp_attribute_t *attr = NULL; // printer-state-reasons lprint_preason_t bit; // Reason bit int i; // Looping var char reason[32]; // Reason string for (i = 0, bit = 1; i < (int)(sizeof(lprint_preason_strings) / sizeof(lprint_preason_strings[0])); i ++, bit *= 2) { if (printer->state_reasons & bit) { snprintf(reason, sizeof(reason), "%s-%s", lprint_preason_strings[i], printer->state == IPP_PSTATE_IDLE ? "report" : printer->state == IPP_PSTATE_PROCESSING ? "warning" : "error"); if (attr) ippSetString(ipp, &attr, ippGetCount(attr), reason); else attr = ippAddString(ipp, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "printer-state-reasons", NULL, reason); } } } } } // // 'filter_cb()' - Filter printer attributes based on the requested array. // static int // O - 1 to copy, 0 to ignore filter_cb(lprint_filter_t *filter, // I - Filter parameters ipp_t *dst, // I - Destination (unused) ipp_attribute_t *attr) // I - Source attribute { // Filter attributes as needed... #ifndef _WIN32 /* Avoid MS compiler bug */ (void)dst; #endif /* !_WIN32 */ ipp_tag_t group = ippGetGroupTag(attr); const char *name = ippGetName(attr); if ((filter->group_tag != IPP_TAG_ZERO && group != filter->group_tag && group != IPP_TAG_ZERO) || !name || (!strcmp(name, "media-col-database") && !cupsArrayFind(filter->ra, (void *)name))) return (0); return (!filter->ra || cupsArrayFind(filter->ra, (void *)name) != NULL); } // // 'finish_document()' - Finish receiving a document file and start processing. // static void finish_document_data( lprint_client_t *client, // I - Client lprint_job_t *job) // I - Job { char filename[1024], // Filename buffer buffer[4096]; // Copy buffer ssize_t bytes; // Bytes read cups_array_t *ra; // Attributes to send in response // Create a file for the request data... // // TODO: Update code to support piping large raster data to the print command. if ((job->fd = lprintCreateJobFile(job, filename, sizeof(filename), client->system->directory, NULL)) < 0) { lprintRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to create print file: %s", strerror(errno)); goto abort_job; } lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "Created job file \"%s\", format \"%s\".", filename, job->format); while ((bytes = httpRead2(client->http, buffer, sizeof(buffer))) > 0) { if (write(job->fd, buffer, (size_t)bytes) < bytes) { int error = errno; // Write error close(job->fd); job->fd = -1; unlink(filename); lprintRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); goto abort_job; } } if (bytes < 0) { // Got an error while reading the print data, so abort this job. close(job->fd); job->fd = -1; unlink(filename); lprintRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to read print file."); goto abort_job; } if (close(job->fd)) { int error = errno; // Write error job->fd = -1; unlink(filename); lprintRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Unable to write print file: %s", strerror(error)); goto abort_job; } job->fd = -1; job->filename = strdup(filename); job->state = IPP_JSTATE_PENDING; // Process the job... lprintCheckJobs(client->printer); // Return the job info... lprintRespondIPP(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); cupsArrayAdd(ra, "job-state"); cupsArrayAdd(ra, "job-state-message"); cupsArrayAdd(ra, "job-state-reasons"); cupsArrayAdd(ra, "job-uri"); copy_job_attributes(client, job, ra); cupsArrayDelete(ra); return; // If we get here we had to abort the job... abort_job: job->state = IPP_JSTATE_ABORTED; job->completed = time(NULL); pthread_rwlock_wrlock(&client->printer->rwlock); cupsArrayRemove(client->printer->active_jobs, job); cupsArrayAdd(client->printer->completed_jobs, job); if (!client->system->clean_time) client->system->clean_time = time(NULL) + 60; pthread_rwlock_unlock(&client->printer->rwlock); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); cupsArrayAdd(ra, "job-state"); cupsArrayAdd(ra, "job-state-reasons"); cupsArrayAdd(ra, "job-uri"); copy_job_attributes(client, job, ra); cupsArrayDelete(ra); } // // 'ipp_cancel_job()' - Cancel a job. // static void ipp_cancel_job(lprint_client_t *client) // I - Client { lprint_job_t *job; // Job information // Get the job... if (ippGetOperation(client->request) == IPP_OP_CANCEL_CURRENT_JOB) job = client->printer->processing_job; else job = client->job; if (!job) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); return; } // See if the job is already completed, canceled, or aborted; if so, // we can't cancel... switch (job->state) { case IPP_JSTATE_CANCELED : lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already canceled - can\'t cancel.", job->id); break; case IPP_JSTATE_ABORTED : lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already aborted - can\'t cancel.", job->id); break; case IPP_JSTATE_COMPLETED : lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already completed - can\'t cancel.", job->id); break; default : // Cancel the job... pthread_rwlock_wrlock(&client->printer->rwlock); if (job->state == IPP_JSTATE_PROCESSING || (job->state == IPP_JSTATE_HELD && job->fd >= 0)) { job->cancel = 1; } else { job->state = IPP_JSTATE_CANCELED; job->completed = time(NULL); cupsArrayRemove(client->printer->active_jobs, job); cupsArrayAdd(client->printer->completed_jobs, job); } pthread_rwlock_unlock(&client->printer->rwlock); lprintRespondIPP(client, IPP_STATUS_OK, NULL); if (!client->system->clean_time) client->system->clean_time = time(NULL) + 60; break; } } // // 'ipp_cancel_jobs()' - Cancel all jobs. // static void ipp_cancel_jobs(lprint_client_t *client)// I - Client { lprint_job_t *job; // Job information http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { lprintRespondHTTP(client, auth_status, NULL, NULL, 0); return; } // Loop through all jobs and cancel them... pthread_rwlock_wrlock(&client->printer->rwlock); for (job = (lprint_job_t *)cupsArrayFirst(client->printer->jobs); job; job = (lprint_job_t *)cupsArrayNext(client->printer->jobs)) { // Cancel this job... if (job->state == IPP_JSTATE_PROCESSING || (job->state == IPP_JSTATE_HELD && job->fd >= 0)) { job->cancel = 1; } else { job->state = IPP_JSTATE_CANCELED; job->completed = time(NULL); cupsArrayRemove(client->printer->active_jobs, job); cupsArrayAdd(client->printer->completed_jobs, job); } } pthread_rwlock_unlock(&client->printer->rwlock); lprintRespondIPP(client, IPP_STATUS_OK, NULL); if (!client->system->clean_time) client->system->clean_time = time(NULL) + 60; } // // 'ipp_close_job()' - Close an open job. // static void ipp_close_job(lprint_client_t *client) // I - Client { lprint_job_t *job = client->job; // Job information // Get the job... if (!job) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); return; } // See if the job is already completed, canceled, or aborted; if so, // we can't cancel... switch (job->state) { case IPP_JSTATE_CANCELED : lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is canceled - can\'t close.", job->id); break; case IPP_JSTATE_ABORTED : lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is aborted - can\'t close.", job->id); break; case IPP_JSTATE_COMPLETED : lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is completed - can\'t close.", job->id); break; case IPP_JSTATE_PROCESSING : case IPP_JSTATE_STOPPED : lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job #%d is already closed.", job->id); break; default : lprintRespondIPP(client, IPP_STATUS_OK, NULL); break; } } // // 'ipp_create_job()' - Create a job object. // static void ipp_create_job(lprint_client_t *client) // I - Client { lprint_job_t *job; // New job cups_array_t *ra; // Attributes to send in response // Validate print job attributes... if (!valid_job_attributes(client)) { httpFlush(client->http); return; } // Do we have a file to print? if (httpGetState(client->http) == HTTP_STATE_POST_RECV) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Unexpected document data following request."); return; } // Create the job... if ((job = lprintCreateJob(client)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BUSY, "Currently printing another job."); return; } // Return the job info... lprintRespondIPP(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "job-id"); cupsArrayAdd(ra, "job-state"); cupsArrayAdd(ra, "job-state-message"); cupsArrayAdd(ra, "job-state-reasons"); cupsArrayAdd(ra, "job-uri"); copy_job_attributes(client, job, ra); cupsArrayDelete(ra); } // // 'ipp_create_printer()' - Create a printer. // static void ipp_create_printer( lprint_client_t *client) // I - Client { const char *printer_name, // Printer name *device_uri, // Device URI *driver_name, // Name of driver *location, // printer-location *geo_location, // printer-gwo-location *organization, // printer-organization *org_unit; // printer-organizational-unit ipp_attribute_t *attr; // Current attribute char resource[256]; // Resource path lprint_printer_t *printer; // Printer cups_array_t *ra; // Requested attributes http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { lprintRespondHTTP(client, auth_status, NULL, NULL, 0); return; } // Get required attributes... if ((attr = ippFindAttribute(client->request, "printer-service-type", IPP_TAG_ZERO)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'printer-service-type' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION || ippGetValueTag(attr) != IPP_TAG_KEYWORD || ippGetCount(attr) != 1 || strcmp(ippGetString(attr, 0, NULL), "print")) { respond_unsupported(client, attr); return; } if ((attr = ippFindAttribute(client->request, "printer-name", IPP_TAG_ZERO)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'printer-name' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_PRINTER || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG) || ippGetCount(attr) != 1 || strlen(ippGetString(attr, 0, NULL)) > 127) { respond_unsupported(client, attr); return; } else printer_name = ippGetString(attr, 0, NULL); if ((attr = ippFindAttribute(client->request, "device-uri", IPP_TAG_ZERO)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'device-uri' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_PRINTER || ippGetValueTag(attr) != IPP_TAG_URI || ippGetCount(attr) != 1) { respond_unsupported(client, attr); return; } else { device_uri = ippGetString(attr, 0, NULL); if (strncmp(device_uri, "file:///", 8) && strncmp(device_uri, "socket://", 9) && strncmp(device_uri, "usb://", 6)) { respond_unsupported(client, attr); return; } } if ((attr = ippFindAttribute(client->request, "lprint-driver", IPP_TAG_ZERO)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing 'lprint-driver' attribute in request."); return; } else if (ippGetGroupTag(attr) != IPP_TAG_PRINTER || ippGetValueTag(attr) != IPP_TAG_KEYWORD || ippGetCount(attr) != 1) { respond_unsupported(client, attr); return; } else { driver_name = ippGetString(attr, 0, NULL); if (!lprintGetMakeAndModel(driver_name)) { respond_unsupported(client, attr); return; } } location = ippGetString(ippFindAttribute(client->request, "printer-location", IPP_TAG_TEXT), 0, NULL); geo_location = ippGetString(ippFindAttribute(client->request, "printer-geo-location", IPP_TAG_TEXT), 0, NULL); organization = ippGetString(ippFindAttribute(client->request, "printer-organization", IPP_TAG_TEXT), 0, NULL); org_unit = ippGetString(ippFindAttribute(client->request, "printer-organizational-unit", IPP_TAG_TEXT), 0, NULL); // See if the printer already exists... snprintf(resource, sizeof(resource), "/ipp/print/%s", printer_name); if (lprintFindPrinter(client->system, resource, 0)) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Printer name '%s' already exists.", printer_name); return; } // Create the printer... if ((printer = lprintCreatePrinter(client->system, 0, printer_name, driver_name, device_uri, location, geo_location, organization, org_unit)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_INTERNAL, "Printer name '%s' already exists.", printer_name); return; } if (!set_printer_attributes(client, printer)) return; // Return the printer lprintRespondIPP(client, IPP_STATUS_OK, NULL); ra = cupsArrayNew((cups_array_func_t)strcmp, NULL); cupsArrayAdd(ra, "printer-id"); cupsArrayAdd(ra, "printer-is-accepting-jobs"); cupsArrayAdd(ra, "printer-state"); cupsArrayAdd(ra, "printer-state-reasons"); cupsArrayAdd(ra, "printer-uuid"); cupsArrayAdd(ra, "printer-xri-supported"); copy_printer_attributes(client, printer, ra); cupsArrayDelete(ra); } // // 'ipp_delete_printer()' - Delete a printer. // static void ipp_delete_printer( lprint_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { lprintRespondHTTP(client, auth_status, NULL, NULL, 0); return; } if (!client->printer) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Printer not found."); return; } if (!client->printer->processing_job) lprintDeletePrinter(client->printer); else client->printer->is_deleted = 1; lprintRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_get_job_attributes()' - Get the attributes for a job object. // static void ipp_get_job_attributes( lprint_client_t *client) // I - Client { lprint_job_t *job = client->job; // Job information cups_array_t *ra; // requested-attributes if (!job) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job not found."); return; } lprintRespondIPP(client, IPP_STATUS_OK, NULL); ra = ippCreateRequestedArray(client->request); copy_job_attributes(client, job, ra); cupsArrayDelete(ra); } // // 'ipp_get_jobs()' - Get a list of job objects. // static void ipp_get_jobs(lprint_client_t *client) // I - Client { ipp_attribute_t *attr; // Current attribute const char *which_jobs = NULL; // which-jobs values int job_comparison; // Job comparison ipp_jstate_t job_state; // job-state value int first_job_id, // First job ID limit, // Maximum number of jobs to return count; // Number of jobs that match const char *username; // Username cups_array_t *list; // Jobs list lprint_job_t *job; // Current job pointer cups_array_t *ra; // Requested attributes array // See if the "which-jobs" attribute have been specified... if ((attr = ippFindAttribute(client->request, "which-jobs", IPP_TAG_KEYWORD)) != NULL) { which_jobs = ippGetString(attr, 0, NULL); lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "Get-Jobs \"which-jobs\"='%s'", which_jobs); } if (!which_jobs || !strcmp(which_jobs, "not-completed")) { job_comparison = -1; job_state = IPP_JSTATE_STOPPED; list = client->printer->active_jobs; } else if (!strcmp(which_jobs, "completed")) { job_comparison = 1; job_state = IPP_JSTATE_CANCELED; list = client->printer->completed_jobs; } else if (!strcmp(which_jobs, "all")) { job_comparison = 1; job_state = IPP_JSTATE_PENDING; list = client->printer->jobs; } else { lprintRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "The \"which-jobs\" value '%s' is not supported.", which_jobs); ippAddString(client->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD, "which-jobs", NULL, which_jobs); return; } // See if they want to limit the number of jobs reported... if ((attr = ippFindAttribute(client->request, "limit", IPP_TAG_INTEGER)) != NULL) { limit = ippGetInteger(attr, 0); lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "Get-Jobs \"limit\"='%d'", limit); } else limit = 0; if ((attr = ippFindAttribute(client->request, "first-job-id", IPP_TAG_INTEGER)) != NULL) { first_job_id = ippGetInteger(attr, 0); lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "Get-Jobs \"first-job-id\"='%d'", first_job_id); } else first_job_id = 1; // See if we only want to see jobs for a specific user... username = NULL; if ((attr = ippFindAttribute(client->request, "my-jobs", IPP_TAG_BOOLEAN)) != NULL) { int my_jobs = ippGetBoolean(attr, 0); lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "Get-Jobs \"my-jobs\"='%s'", my_jobs ? "true" : "false"); if (my_jobs) { if ((attr = ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Need \"requesting-user-name\" with \"my-jobs\"."); return; } username = ippGetString(attr, 0, NULL); lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "Get-Jobs \"requesting-user-name\"='%s'", username); } } // OK, build a list of jobs for this printer... ra = ippCreateRequestedArray(client->request); lprintRespondIPP(client, IPP_STATUS_OK, NULL); pthread_rwlock_rdlock(&(client->printer->rwlock)); for (count = 0, job = (lprint_job_t *)cupsArrayFirst(list); (limit <= 0 || count < limit) && job; job = (lprint_job_t *)cupsArrayNext(list)) { // Filter out jobs that don't match... if (job->printer != client->printer) continue; if ((job_comparison < 0 && job->state > job_state) || (job_comparison == 0 && job->state != job_state) || (job_comparison > 0 && job->state < job_state) || job->id < first_job_id || (username && job->username && strcasecmp(username, job->username))) continue; if (count > 0) ippAddSeparator(client->response); count ++; copy_job_attributes(client, job, ra); } cupsArrayDelete(ra); pthread_rwlock_unlock(&(client->printer->rwlock)); } // // 'ipp_get_printer_attributes()' - Get the attributes for a printer object. // static void ipp_get_printer_attributes( lprint_client_t *client) // I - Client { cups_array_t *ra; // Requested attributes array lprint_printer_t *printer; // Printer // TODO: Update status attributes as needed (querying printer, etc.) // Send the attributes... ra = ippCreateRequestedArray(client->request); printer = client->printer; lprintRespondIPP(client, IPP_STATUS_OK, NULL); pthread_rwlock_rdlock(&(printer->rwlock)); copy_printer_attributes(client, printer, ra); pthread_rwlock_unlock(&(printer->rwlock)); cupsArrayDelete(ra); } // // 'ipp_get_printers()' - Get printers. // static void ipp_get_printers( lprint_client_t *client) // I - Client { lprint_system_t *system = client->system; // System cups_array_t *ra; // Requested attributes array int i, // Looping var limit; // Maximum number to return lprint_printer_t *printer; // Current printer // Get request attributes... limit = ippGetInteger(ippFindAttribute(client->request, "limit", IPP_TAG_INTEGER), 0); ra = ippCreateRequestedArray(client->request); lprintRespondIPP(client, IPP_STATUS_OK, NULL); pthread_rwlock_rdlock(&system->rwlock); for (i = 0, printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; i ++, printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { if (limit && i >= limit) break; if (i) ippAddSeparator(client->response); pthread_rwlock_rdlock(&printer->rwlock); copy_printer_attributes(client, printer, ra); pthread_rwlock_unlock(&printer->rwlock); } pthread_rwlock_unlock(&system->rwlock); cupsArrayDelete(ra); } // // 'ipp_get_system_attributes()' - Get system attributes. // static void ipp_get_system_attributes( lprint_client_t *client) // I - Client { lprint_system_t *system = client->system; // System cups_array_t *ra; // Requested attributes array int i; // Looping var lprint_printer_t *printer; // Current printer ipp_attribute_t *attr; // Current attribute ipp_t *col; // configured-printers value time_t config_time = 0;// system-config-change-[date-]time value time_t state_time = 0; // system-state-change-[date-]time value http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { lprintRespondHTTP(client, auth_status, NULL, NULL, 0); return; } ra = ippCreateRequestedArray(client->request); lprintRespondIPP(client, IPP_STATUS_OK, NULL); pthread_rwlock_rdlock(&system->rwlock); if (!ra || cupsArrayFind(ra, "system-config-change-date-time") || cupsArrayFind(ra, "system-config-change-time")) { for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { if (config_time < printer->config_time) config_time = printer->config_time; } if (!ra || cupsArrayFind(ra, "system-config-change-date-time")) ippAddDate(client->response, IPP_TAG_SYSTEM, "system-config-change-date-time", ippTimeToDate(config_time)); if (!ra || cupsArrayFind(ra, "system-config-change-time")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-config-change-time", (int)(config_time - system->start_time)); } if (!ra || cupsArrayFind(ra, "system-configured-printers")) { attr = ippAddCollections(client->response, IPP_TAG_SYSTEM, "system-configured-printers", cupsArrayCount(system->printers), NULL); for (i = 0, printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; i ++, printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { col = ippNew(); pthread_rwlock_rdlock(&printer->rwlock); ippAddInteger(col, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "printer-id", printer->printer_id); ippAddString(col, IPP_TAG_SYSTEM, IPP_TAG_TEXT, "printer-info", NULL, printer->printer_name); ippAddBoolean(col, IPP_TAG_SYSTEM, "printer-is-accepting-jobs", 1); ippAddString(col, IPP_TAG_SYSTEM, IPP_TAG_TEXT, "printer-name", NULL, printer->printer_name); ippAddString(col, IPP_TAG_SYSTEM, IPP_TAG_KEYWORD, "printer-service-type", NULL, "print"); copy_printer_state(col, printer, NULL); ippCopyAttribute(col, printer->xri_supported, 0); pthread_rwlock_unlock(&printer->rwlock); ippSetCollection(client->response, &attr, i, col); ippDelete(col); } } if (!ra || cupsArrayFind(ra, "system-current-time")) ippAddDate(client->response, IPP_TAG_SYSTEM, "system-current-time", ippTimeToDate(time(NULL))); if (!ra || cupsArrayFind(ra, "system-default-printer-id")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-default-printer-id", system->default_printer); if (!ra || cupsArrayFind(ra, "system-state")) { int state = IPP_PSTATE_IDLE; // System state for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { if (printer->state == IPP_PSTATE_PROCESSING) { state = IPP_PSTATE_PROCESSING; break; } } ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_ENUM, "system-state", state); } if (!ra || cupsArrayFind(ra, "system-state-change-date-time") || cupsArrayFind(ra, "system-state-change-time")) { for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { if (state_time < printer->state_time) state_time = printer->state_time; } if (!ra || cupsArrayFind(ra, "system-state-change-date-time")) ippAddDate(client->response, IPP_TAG_SYSTEM, "system-state-change-date-time", ippTimeToDate(state_time)); if (!ra || cupsArrayFind(ra, "system-state-change-time")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-state-change-time", (int)(state_time - system->start_time)); } if (!ra || cupsArrayFind(ra, "system-state-reasons")) { lprint_preason_t state_reasons = LPRINT_PREASON_NONE; for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { state_reasons |= printer->state_reasons; } if (state_reasons == LPRINT_PREASON_NONE) { ippAddString(client->response, IPP_TAG_SYSTEM, IPP_CONST_TAG(IPP_TAG_KEYWORD), "system-state-reasons", NULL, "none"); } else { ipp_attribute_t *attr = NULL; // printer-state-reasons lprint_preason_t bit; // Reason bit int i; // Looping var for (i = 0, bit = 1; i < (int)(sizeof(lprint_preason_strings) / sizeof(lprint_preason_strings[0])); i ++, bit *= 2) { if (state_reasons & bit) { if (attr) ippSetString(client->response, &attr, ippGetCount(attr), lprint_preason_strings[i]); else attr = ippAddString(client->response, IPP_TAG_SYSTEM, IPP_TAG_KEYWORD, "system-state-reasons", NULL, lprint_preason_strings[i]); } } } } if (!ra || cupsArrayFind(ra, "system-up-time")) ippAddInteger(client->response, IPP_TAG_SYSTEM, IPP_TAG_INTEGER, "system-up-time", (int)(time(NULL) - system->start_time)); pthread_rwlock_unlock(&system->rwlock); cupsArrayDelete(ra); } // // 'ipp_identify_printer()' - Beep or display a message. // static void ipp_identify_printer( lprint_client_t *client) // I - Client { ipp_attribute_t *actions, // identify-actions *message; // message actions = ippFindAttribute(client->request, "identify-actions", IPP_TAG_KEYWORD); message = ippFindAttribute(client->request, "message", IPP_TAG_TEXT); // TODO: FIX ME if (!actions || ippContainsString(actions, "sound")) { putchar(0x07); fflush(stdout); } if (ippContainsString(actions, "display")) printf("IDENTIFY from %s: %s\n", client->hostname, message ? ippGetString(message, 0, NULL) : "No message supplied"); lprintRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_print_job()' - Create a job object with an attached document. // static void ipp_print_job(lprint_client_t *client) // I - Client { lprint_job_t *job; // New job // Validate print job attributes... if (!valid_job_attributes(client)) { httpFlush(client->http); return; } // Do we have a file to print? if (httpGetState(client->http) == HTTP_STATE_POST_SEND) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "No file in request."); return; } // Create the job... if ((job = lprintCreateJob(client)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BUSY, "Currently printing another job."); return; } // Then finish getting the document data and process things... finish_document_data(client, job); } // // 'ipp_send_document()' - Add an attached document to a job object created with // Create-Job. // static void ipp_send_document( lprint_client_t *client) // I - Client { lprint_job_t *job = client->job; // Job information ipp_attribute_t *attr; // Current attribute // Get the job... if (!job) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_FOUND, "Job does not exist."); httpFlush(client->http); return; } // See if we already have a document for this job or the job has already // in a non-pending state... if (job->state > IPP_JSTATE_HELD) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_POSSIBLE, "Job is not in a pending state."); httpFlush(client->http); return; } else if (job->filename || job->fd >= 0) { lprintRespondIPP(client, IPP_STATUS_ERROR_MULTIPLE_JOBS_NOT_SUPPORTED, "Multiple document jobs are not supported."); httpFlush(client->http); return; } // Make sure we have the "last-document" operation attribute... if ((attr = ippFindAttribute(client->request, "last-document", IPP_TAG_ZERO)) == NULL) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "Missing required \"last-document\" attribute."); httpFlush(client->http); return; } else if (ippGetGroupTag(attr) != IPP_TAG_OPERATION) { lprintRespondIPP(client, IPP_STATUS_ERROR_BAD_REQUEST, "The \"last-document\" attribute is not in the operation group."); httpFlush(client->http); return; } else if (ippGetValueTag(attr) != IPP_TAG_BOOLEAN || ippGetCount(attr) != 1 || !ippGetBoolean(attr, 0)) { respond_unsupported(client, attr); httpFlush(client->http); return; } // Validate document attributes... if (!valid_doc_attributes(client)) { httpFlush(client->http); return; } // Then finish getting the document data and process things... pthread_rwlock_wrlock(&(client->printer->rwlock)); lprintCopyAttributes(job->attrs, client->request, NULL, IPP_TAG_JOB, 0); if ((attr = ippFindAttribute(job->attrs, "document-format-detected", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else if ((attr = ippFindAttribute(job->attrs, "document-format-supplied", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else job->format = client->printer->driver->format; pthread_rwlock_unlock(&(client->printer->rwlock)); finish_document_data(client, job); } // // 'ipp_set_printer_attributes()' - Set printer attributes. // static void ipp_set_printer_attributes( lprint_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { lprintRespondHTTP(client, auth_status, NULL, NULL, 0); return; } if (!set_printer_attributes(client, client->printer)) return; lprintRespondIPP(client, IPP_STATUS_OK, "Printer attributes set."); } // // 'ipp_set_system_attributes()' - Set system attributes. // static void ipp_set_system_attributes( lprint_client_t *client) // I - Client { lprint_system_t *system = client->system; // System ipp_attribute_t *rattr; // Current request attribute ipp_tag_t value_tag; // Value tag int count; // Number of values const char *name; // Attribute name int i; // Looping var http_status_t auth_status; // Authorization status static lprint_attr_t sattrs[] = // Settable system attributes { { "default-printer-id", IPP_TAG_INTEGER, 1 } }; // Verify the connection is authorized... if ((auth_status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { lprintRespondHTTP(client, auth_status, NULL, NULL, 0); return; } // Preflight request attributes... for (rattr = ippFirstAttribute(client->request); rattr; rattr = ippNextAttribute(client->request)) { lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "%s %s %s%s ...", ippTagString(ippGetGroupTag(rattr)), ippGetName(rattr), ippGetCount(rattr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(rattr))); if (ippGetGroupTag(rattr) == IPP_TAG_OPERATION) { continue; } else if (ippGetGroupTag(rattr) != IPP_TAG_SYSTEM) { respond_unsupported(client, rattr); continue; } name = ippGetName(rattr); value_tag = ippGetValueTag(rattr); count = ippGetCount(rattr); for (i = 0; i < (int)(sizeof(sattrs) / sizeof(sattrs[0])); i ++) { if (!strcmp(name, sattrs[i].name) && value_tag == sattrs[i].value_tag && count <= sattrs[i].max_count) break; } if (i >= (int)(sizeof(sattrs) / sizeof(sattrs[0]))) respond_unsupported(client, rattr); if (!strcmp(name, "default-printer-id")) { if (!lprintFindPrinter(system, NULL, ippGetInteger(rattr, 0))) { respond_unsupported(client, rattr); break; } } } if (ippGetStatusCode(client->response) != IPP_STATUS_OK) return; // Now apply changes... pthread_rwlock_wrlock(&system->rwlock); for (rattr = ippFirstAttribute(client->request); rattr; rattr = ippNextAttribute(client->request)) { if (ippGetGroupTag(rattr) == IPP_TAG_OPERATION) continue; name = ippGetName(rattr); if (!strcmp(name, "default-printer-id")) { // Value was checked previously... system->default_printer = ippGetInteger(rattr, 0); } } pthread_rwlock_unlock(&system->rwlock); if (!system->save_time) system->save_time = time(NULL) + 1; lprintRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_shutdown_all_printers()' - Shutdown the system. // static void ipp_shutdown_all_printers( lprint_client_t *client) // I - Client { http_status_t auth_status; // Authorization status // Verify the connection is authorized... if ((auth_status = lprintIsAuthorized(client)) != HTTP_STATUS_CONTINUE) { lprintRespondHTTP(client, auth_status, NULL, NULL, 0); return; } client->system->shutdown_time = time(NULL); lprintRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'ipp_validate_job()' - Validate job creation attributes. // static void ipp_validate_job( lprint_client_t *client) // I - Client { if (valid_job_attributes(client)) lprintRespondIPP(client, IPP_STATUS_OK, NULL); } // // 'respond_unsupported()' - Respond with an unsupported attribute. // static void respond_unsupported( lprint_client_t *client, // I - Client ipp_attribute_t *attr) // I - Atribute { ipp_attribute_t *temp; // Copy of attribute lprintRespondIPP(client, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, "Unsupported %s %s%s value.", ippGetName(attr), ippGetCount(attr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(attr))); temp = ippCopyAttribute(client->response, attr, 0); ippSetGroupTag(client->response, &temp, IPP_TAG_UNSUPPORTED_GROUP); } // // 'set_printer_attributes()' - Set printer attributes. // static int // O - 1 if OK, 0 on failure set_printer_attributes( lprint_client_t *client, // I - Client lprint_printer_t *printer) // I - Printer { int create_printer; // Create-Printer request? ipp_attribute_t *rattr, // Current request attribute *pattr; // Current printer attribute ipp_tag_t value_tag; // Value tag int count; // Number of values const char *name; // Attribute name int i; // Looping var static lprint_attr_t pattrs[] = // Settable printer attributes { { "copies-default", IPP_TAG_INTEGER, 1 }, { "document-format-default", IPP_TAG_MIMETYPE, 1 }, { "label-mode-configured", IPP_TAG_KEYWORD, 1 }, { "label-tear-off-configured", IPP_TAG_INTEGER, 1 }, { "media-col-default", IPP_TAG_BEGIN_COLLECTION, 1 }, { "media-col-ready", IPP_TAG_BEGIN_COLLECTION, LPRINT_MAX_SOURCE }, { "media-default", IPP_TAG_KEYWORD, 1 }, { "media-ready", IPP_TAG_KEYWORD, LPRINT_MAX_SOURCE }, { "multiple-document-handling-default", IPP_TAG_KEYWORD, 1 }, { "orientation-requested-default", IPP_TAG_ENUM, 1 }, { "print-color-mode-default", IPP_TAG_KEYWORD, 1 }, { "print-content-optimize-default", IPP_TAG_KEYWORD, 1 }, { "print-darkness-default", IPP_TAG_INTEGER, 1 }, { "print-quality-default", IPP_TAG_ENUM, 1 }, { "print-speed-default", IPP_TAG_INTEGER, 1 }, { "printer-darkness-configured", IPP_TAG_INTEGER, 1 }, { "printer-geo-location", IPP_TAG_URI, 1 }, { "printer-location", IPP_TAG_TEXT, 1 }, { "printer-organization", IPP_TAG_TEXT, 1 }, { "printer-organizational-unit", IPP_TAG_TEXT, 1 }, { "printer-resolution-default", IPP_TAG_RESOLUTION, 1 } }; // Preflight request attributes... create_printer = ippGetOperation(client->request) == IPP_OP_CREATE_PRINTER; for (rattr = ippFirstAttribute(client->request); rattr; rattr = ippNextAttribute(client->request)) { lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "%s %s %s%s ...", ippTagString(ippGetGroupTag(rattr)), ippGetName(rattr), ippGetCount(rattr) > 1 ? "1setOf " : "", ippTagString(ippGetValueTag(rattr))); if (ippGetGroupTag(rattr) == IPP_TAG_OPERATION) { continue; } else if (ippGetGroupTag(rattr) != IPP_TAG_PRINTER) { respond_unsupported(client, rattr); continue; } name = ippGetName(rattr); if (create_printer && (!strcmp(name, "printer-name") || !strcmp(name, "device-uri") || !strcmp(name, "lprint-driver"))) continue; value_tag = ippGetValueTag(rattr); count = ippGetCount(rattr); for (i = 0; i < (int)(sizeof(pattrs) / sizeof(pattrs[0])); i ++) { if (!strcmp(name, pattrs[i].name) && value_tag == pattrs[i].value_tag && count <= pattrs[i].max_count) break; } if (i >= (int)(sizeof(pattrs) / sizeof(pattrs[0]))) respond_unsupported(client, rattr); } if (ippGetStatusCode(client->response) != IPP_STATUS_OK) return (0); // Now apply changes... pthread_rwlock_wrlock(&printer->rwlock); for (rattr = ippFirstAttribute(client->request); rattr; rattr = ippNextAttribute(client->request)) { if (ippGetGroupTag(rattr) == IPP_TAG_OPERATION) continue; name = ippGetName(rattr); if (!strcmp(name, "media-col-default")) { lprintImportMediaCol(ippGetCollection(rattr, 0), &printer->driver->media_default); } else if (!strcmp(name, "media-col-ready")) { count = ippGetCount(rattr); for (i = 0; i < count; i ++) lprintImportMediaCol(ippGetCollection(rattr, i), printer->driver->media_ready + i); for (; i < LPRINT_MAX_SOURCE; i ++) memset(printer->driver->media_ready + i, 0, sizeof(lprint_media_col_t)); } else if (!strcmp(name, "media-default")) { strlcpy(printer->driver->media_default.size_name, ippGetString(rattr, 0, NULL), sizeof(printer->driver->media_default.size_name)); } else if (!strcmp(name, "media-ready")) { count = ippGetCount(rattr); for (i = 0; i < count; i ++) { const char *media = ippGetString(rattr, i, NULL); // Media value strlcpy(printer->driver->media_ready[i].size_name, media, sizeof(printer->driver->media_ready[i].size_name)); } for (; i < LPRINT_MAX_SOURCE; i ++) printer->driver->media_ready[i].size_name[0] = '\0'; } else if (!strcmp(name, "printer-geo-location")) { free(printer->geo_location); printer->geo_location = strdup(ippGetString(rattr, 0, NULL)); } else if (!strcmp(name, "printer-location")) { free(printer->location); printer->location = strdup(ippGetString(rattr, 0, NULL)); } else if (!strcmp(name, "printer-organization")) { free(printer->organization); printer->organization = strdup(ippGetString(rattr, 0, NULL)); } else if (!strcmp(name, "printer-organization-unit")) { free(printer->org_unit); printer->org_unit = strdup(ippGetString(rattr, 0, NULL)); } else { for (i = 0; i < (int)(sizeof(pattrs) / sizeof(pattrs[0])); i ++) { if (strcmp(name, pattrs[i].name)) continue; if ((pattr = ippFindAttribute(printer->attrs, name, IPP_TAG_ZERO)) != NULL) ippDeleteAttribute(printer->attrs, pattr); ippCopyAttribute(printer->attrs, rattr, 0); } } } printer->config_time = time(NULL); pthread_rwlock_unlock(&printer->rwlock); if (!client->system->save_time) client->system->save_time = time(NULL) + 1; return (1); } // // 'valid_doc_attributes()' - Determine whether the document attributes are // valid. // // When one or more document attributes are invalid, this function adds a // suitable response and attributes to the unsupported group. // static int // O - 1 if valid, 0 if not valid_doc_attributes( lprint_client_t *client) // I - Client { int valid = 1; // Valid attributes? ipp_op_t op = ippGetOperation(client->request); // IPP operation const char *op_name = ippOpString(op); // IPP operation name ipp_attribute_t *attr, // Current attribute *supported; // xxx-supported attribute const char *compression = NULL, // compression value *format = NULL; // document-format value // Check operation attributes... if ((attr = ippFindAttribute(client->request, "compression", IPP_TAG_ZERO)) != NULL) { // If compression is specified, only accept a supported value in a Print-Job // or Send-Document request... compression = ippGetString(attr, 0, NULL); supported = ippFindAttribute(client->printer->attrs, "compression-supported", IPP_TAG_KEYWORD); if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD || ippGetGroupTag(attr) != IPP_TAG_OPERATION || (op != IPP_OP_PRINT_JOB && op != IPP_OP_SEND_DOCUMENT && op != IPP_OP_VALIDATE_JOB) || !ippContainsString(supported, compression)) { respond_unsupported(client, attr); valid = 0; } else { lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "%s \"compression\"='%s'", op_name, compression); ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "compression-supplied", NULL, compression); if (strcmp(compression, "none")) { lprintLogClient(client, LPRINT_LOGLEVEL_INFO, "Receiving job file with '%s' compression.", compression); httpSetField(client->http, HTTP_FIELD_CONTENT_ENCODING, compression); } } } // Is it a format we support? if ((attr = ippFindAttribute(client->request, "document-format", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_MIMETYPE || ippGetGroupTag(attr) != IPP_TAG_OPERATION) { respond_unsupported(client, attr); valid = 0; } else { format = ippGetString(attr, 0, NULL); lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "%s \"document-format\"='%s'", op_name, format); ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-supplied", NULL, format); } } else { format = ippGetString(ippFindAttribute(client->printer->attrs, "document-format-default", IPP_TAG_MIMETYPE), 0, NULL); if (!format) format = "application/octet-stream"; /* Should never happen */ attr = ippAddString(client->request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, format); } if (format && !strcmp(format, "application/octet-stream") && (ippGetOperation(client->request) == IPP_OP_PRINT_JOB || ippGetOperation(client->request) == IPP_OP_SEND_DOCUMENT)) { // Auto-type the file using the first 8 bytes of the file... unsigned char header[8]; // First 8 bytes of file memset(header, 0, sizeof(header)); httpPeek(client->http, (char *)header, sizeof(header)); if (!memcmp(header, "%PDF", 4)) format = "application/pdf"; else if (!memcmp(header, "%!", 2)) format = "application/postscript"; else if (!memcmp(header, "\377\330\377", 3) && header[3] >= 0xe0 && header[3] <= 0xef) format = "image/jpeg"; else if (!memcmp(header, "\211PNG", 4)) format = "image/png"; else if (!memcmp(header, "RAS2", 4)) format = "image/pwg-raster"; else if (!memcmp(header, "UNIRAST", 8)) format = "image/urf"; else format = client->printer->driver->format; if (format) { lprintLogClient(client, LPRINT_LOGLEVEL_DEBUG, "%s Auto-typed \"document-format\"='%s'.", op_name, format); ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format-detected", NULL, format); } } if (op != IPP_OP_CREATE_JOB && (supported = ippFindAttribute(client->printer->attrs, "document-format-supported", IPP_TAG_MIMETYPE)) != NULL && !ippContainsString(supported, format)) { respond_unsupported(client, attr); valid = 0; } return (valid); } // // 'valid_job_attributes()' - Determine whether the job attributes are valid. // // When one or more job attributes are invalid, this function adds a suitable // response and attributes to the unsupported group. // static int // O - 1 if valid, 0 if not valid_job_attributes( lprint_client_t *client) // I - Client { int i, // Looping var count, // Number of values valid = 1; // Valid attributes? ipp_attribute_t *attr, // Current attribute *supported; // xxx-supported attribute // If a shutdown is pending, do not accept more jobs... if (client->system->shutdown_time) { lprintRespondIPP(client, IPP_STATUS_ERROR_NOT_ACCEPTING_JOBS, "Not accepting new jobs."); return (0); } // Check operation attributes... valid = valid_doc_attributes(client); // Check the various job template attributes... if ((attr = ippFindAttribute(client->request, "copies", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetInteger(attr, 0) < 1 || ippGetInteger(attr, 0) > 999) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "ipp-attribute-fidelity", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_BOOLEAN) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-hold-until", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG && ippGetValueTag(attr) != IPP_TAG_KEYWORD) || strcmp(ippGetString(attr, 0, NULL), "no-hold")) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-impressions", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetInteger(attr, 0) < 0) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-name", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG)) { respond_unsupported(client, attr); valid = 0; } ippSetGroupTag(client->request, &attr, IPP_TAG_JOB); } else ippAddString(client->request, IPP_TAG_JOB, IPP_TAG_NAME, "job-name", NULL, "Untitled"); if ((attr = ippFindAttribute(client->request, "job-priority", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_INTEGER || ippGetInteger(attr, 0) < 1 || ippGetInteger(attr, 0) > 100) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "job-sheets", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG && ippGetValueTag(attr) != IPP_TAG_KEYWORD) || strcmp(ippGetString(attr, 0, NULL), "none")) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "media", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || (ippGetValueTag(attr) != IPP_TAG_NAME && ippGetValueTag(attr) != IPP_TAG_NAMELANG && ippGetValueTag(attr) != IPP_TAG_KEYWORD)) { respond_unsupported(client, attr); valid = 0; } else { supported = ippFindAttribute(client->printer->driver->attrs, "media-supported", IPP_TAG_KEYWORD); if (!ippContainsString(supported, ippGetString(attr, 0, NULL))) { respond_unsupported(client, attr); valid = 0; } } } if ((attr = ippFindAttribute(client->request, "media-col", IPP_TAG_ZERO)) != NULL) { ipp_t *col, // media-col collection *size; // media-size collection ipp_attribute_t *member, // Member attribute *x_dim, // x-dimension *y_dim; // y-dimension int x_value, // y-dimension value y_value; // x-dimension value if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_BEGIN_COLLECTION) { respond_unsupported(client, attr); valid = 0; } col = ippGetCollection(attr, 0); if ((member = ippFindAttribute(col, "media-size-name", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(member) != 1 || (ippGetValueTag(member) != IPP_TAG_NAME && ippGetValueTag(member) != IPP_TAG_NAMELANG && ippGetValueTag(member) != IPP_TAG_KEYWORD)) { respond_unsupported(client, attr); valid = 0; } else { supported = ippFindAttribute(client->printer->driver->attrs, "media-supported", IPP_TAG_KEYWORD); if (!ippContainsString(supported, ippGetString(member, 0, NULL))) { respond_unsupported(client, attr); valid = 0; } } } else if ((member = ippFindAttribute(col, "media-size", IPP_TAG_BEGIN_COLLECTION)) != NULL) { if (ippGetCount(member) != 1) { respond_unsupported(client, attr); valid = 0; } else { size = ippGetCollection(member, 0); if ((x_dim = ippFindAttribute(size, "x-dimension", IPP_TAG_INTEGER)) == NULL || ippGetCount(x_dim) != 1 || (y_dim = ippFindAttribute(size, "y-dimension", IPP_TAG_INTEGER)) == NULL || ippGetCount(y_dim) != 1) { respond_unsupported(client, attr); valid = 0; } else { x_value = ippGetInteger(x_dim, 0); y_value = ippGetInteger(y_dim, 0); supported = ippFindAttribute(client->printer->driver->attrs, "media-size-supported", IPP_TAG_BEGIN_COLLECTION); count = ippGetCount(supported); for (i = 0; i < count ; i ++) { size = ippGetCollection(supported, i); x_dim = ippFindAttribute(size, "x-dimension", IPP_TAG_ZERO); y_dim = ippFindAttribute(size, "y-dimension", IPP_TAG_ZERO); if (ippContainsInteger(x_dim, x_value) && ippContainsInteger(y_dim, y_value)) break; } if (i >= count) { respond_unsupported(client, attr); valid = 0; } } } } } if ((attr = ippFindAttribute(client->request, "multiple-document-handling", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_KEYWORD || (strcmp(ippGetString(attr, 0, NULL), "separate-documents-uncollated-copies") && strcmp(ippGetString(attr, 0, NULL), "separate-documents-collated-copies"))) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "orientation-requested", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_ENUM || ippGetInteger(attr, 0) < IPP_ORIENT_PORTRAIT || ippGetInteger(attr, 0) > IPP_ORIENT_NONE) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "page-ranges", IPP_TAG_ZERO)) != NULL) { if (ippGetValueTag(attr) != IPP_TAG_RANGE) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "print-quality", IPP_TAG_ZERO)) != NULL) { if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_ENUM || ippGetInteger(attr, 0) < IPP_QUALITY_DRAFT || ippGetInteger(attr, 0) > IPP_QUALITY_HIGH) { respond_unsupported(client, attr); valid = 0; } } if ((attr = ippFindAttribute(client->request, "printer-resolution", IPP_TAG_ZERO)) != NULL) { supported = ippFindAttribute(client->printer->driver->attrs, "printer-resolution-supported", IPP_TAG_RESOLUTION); if (ippGetCount(attr) != 1 || ippGetValueTag(attr) != IPP_TAG_RESOLUTION || !supported) { respond_unsupported(client, attr); valid = 0; } else { int xdpi, // Horizontal resolution for job template attribute ydpi, // Vertical resolution for job template attribute sydpi; // Vertical resolution for supported value ipp_res_t units, // Units for job template attribute sunits; // Units for supported value xdpi = ippGetResolution(attr, 0, &ydpi, &units); count = ippGetCount(supported); for (i = 0; i < count; i ++) { if (xdpi == ippGetResolution(supported, i, &sydpi, &sunits) && ydpi == sydpi && units == sunits) break; } if (i >= count) { respond_unsupported(client, attr); valid = 0; } } } return (valid); } lprint-1.0/server-job.c000066400000000000000000000221241362261677400151230ustar00rootroot00000000000000// // Job object for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include /* * 'lprintCheckJobs()' - Check for new jobs to process. */ void lprintCheckJobs( lprint_printer_t *printer) // I - Printer { lprint_job_t *job; // Current job lprintLogPrinter(printer, LPRINT_LOGLEVEL_DEBUG, "Checking for new jobs to process."); if (printer->processing_job) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_DEBUG, "Printer is already processing job %d.", printer->processing_job->id); return; } else if (printer->is_deleted) { lprintLogPrinter(printer, LPRINT_LOGLEVEL_DEBUG, "Printer is being deleted."); return; } pthread_rwlock_wrlock(&printer->rwlock); for (job = (lprint_job_t *)cupsArrayFirst(printer->active_jobs); job; job = (lprint_job_t *)cupsArrayNext(printer->active_jobs)) { if (job->state == IPP_JSTATE_PENDING) { pthread_t t; // Thread lprintLogPrinter(printer, LPRINT_LOGLEVEL_DEBUG, "Starting job %d.", job->id); if (pthread_create(&t, NULL, (void *(*)(void *))lprintProcessJob, job)) { job->state = IPP_JSTATE_ABORTED; job->completed = time(NULL); pthread_rwlock_wrlock(&printer->rwlock); cupsArrayRemove(printer->active_jobs, job); cupsArrayAdd(printer->completed_jobs, job); if (!printer->system->clean_time) printer->system->clean_time = time(NULL) + 60; pthread_rwlock_unlock(&printer->rwlock); } else pthread_detach(t); break; } } if (!job) lprintLogPrinter(printer, LPRINT_LOGLEVEL_DEBUG, "No jobs to process at this time."); pthread_rwlock_unlock(&printer->rwlock); } // // 'lprintCleanJobs()' - Clean out old (completed) jobs. // void lprintCleanJobs( lprint_system_t *system) // I - System { lprint_printer_t *printer; // Current printer lprint_job_t *job; // Current job time_t cleantime; // Clean time cleantime = time(NULL) - 60; pthread_rwlock_rdlock(&system->rwlock); for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { if (cupsArrayCount(printer->completed_jobs) == 0) continue; pthread_rwlock_wrlock(&printer->rwlock); for (job = (lprint_job_t *)cupsArrayFirst(printer->completed_jobs); job; job = (lprint_job_t *)cupsArrayNext(printer->completed_jobs)) { if (job->completed && job->completed < cleantime) { cupsArrayRemove(printer->completed_jobs, job); cupsArrayRemove(printer->jobs, job); } else break; } pthread_rwlock_unlock(&printer->rwlock); } pthread_rwlock_unlock(&system->rwlock); } // // 'lprintCreateJob()' - Create a new job object from a Print-Job or Create-Job request. // lprint_job_t * // O - Job lprintCreateJob( lprint_client_t *client) // I - Client { lprint_job_t *job; // Job ipp_attribute_t *attr; // Job attribute char job_printer_uri[1024], // job-printer-uri value job_uri[1024], // job-uri value job_uuid[64]; // job-uuid value // Allocate and initialize the job object... if ((job = calloc(1, sizeof(lprint_job_t))) == NULL) { lprintLog(client->system, LPRINT_LOGLEVEL_ERROR, "Unable to allocate memory for job: %s", strerror(errno)); return (NULL); } job->system = client->system; job->printer = client->printer; job->attrs = ippNew(); job->state = IPP_JSTATE_HELD; job->fd = -1; // Copy all of the job attributes... lprintCopyAttributes(job->attrs, client->request, NULL, IPP_TAG_JOB, 0); // Get the requesting-user-name, document format, and priority... if ((attr = ippFindAttribute(client->request, "requesting-user-name", IPP_TAG_NAME)) != NULL) job->username = ippGetString(attr, 0, NULL); else job->username = "anonymous"; ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_NAME, "job-originating-user-name", NULL, job->username); if (ippGetOperation(client->request) != IPP_OP_CREATE_JOB) { if ((attr = ippFindAttribute(job->attrs, "document-format-detected", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else if ((attr = ippFindAttribute(job->attrs, "document-format-supplied", IPP_TAG_MIMETYPE)) != NULL) job->format = ippGetString(attr, 0, NULL); else job->format = "application/octet-stream"; } if ((attr = ippFindAttribute(client->request, "job-impressions", IPP_TAG_INTEGER)) != NULL) job->impressions = ippGetInteger(attr, 0); if ((attr = ippFindAttribute(client->request, "job-name", IPP_TAG_NAME)) != NULL) job->name = ippGetString(attr, 0, NULL); // Add job description attributes and add to the jobs array... pthread_rwlock_wrlock(&client->printer->rwlock); job->id = client->printer->next_job_id ++; if ((attr = ippFindAttribute(client->request, "printer-uri", IPP_TAG_URI)) != NULL) { strlcpy(job_printer_uri, ippGetString(attr, 0, NULL), sizeof(job_printer_uri)); snprintf(job_uri, sizeof(job_uri), "%s/%d", ippGetString(attr, 0, NULL), job->id); } else { httpAssembleURI(HTTP_URI_CODING_ALL, job_printer_uri, sizeof(job_printer_uri), "ipps", NULL, client->system->hostname, client->system->port, client->printer->resource); httpAssembleURIf(HTTP_URI_CODING_ALL, job_uri, sizeof(job_uri), "ipps", NULL, client->system->hostname, client->system->port, "%s/%d", client->printer->resource, job->id); } lprintMakeUUID(client->system, client->printer->printer_name, job->id, job_uuid, sizeof(job_uuid)); ippAddDate(job->attrs, IPP_TAG_JOB, "date-time-at-creation", ippTimeToDate(time(&job->created))); ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id); ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, job_uri); ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uuid", NULL, job_uuid); ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, job_printer_uri); ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)(job->created - client->printer->start_time)); cupsArrayAdd(client->printer->jobs, job); cupsArrayAdd(client->printer->active_jobs, job); pthread_rwlock_unlock(&client->printer->rwlock); return (job); } // // 'lprintCreateJobFile()' - Create a file for the document in a job. // int // O - File descriptor or -1 on error lprintCreateJobFile( lprint_job_t *job, // I - Job char *fname, // I - Filename buffer size_t fnamesize, // I - Size of filename buffer const char *directory, // I - Directory to store in const char *ext) // I - Extension (`NULL` for default) { char name[256], // "Safe" filename *nameptr; // Pointer into filename const char *job_name; // job-name value // Make a name from the job-name attribute... if ((job_name = ippGetString(ippFindAttribute(job->attrs, "job-name", IPP_TAG_NAME), 0, NULL)) == NULL) job_name = "untitled"; for (nameptr = name; *job_name && nameptr < (name + sizeof(name) - 1); job_name ++) { if (isalnum(*job_name & 255) || *job_name == '-') { *nameptr++ = (char)tolower(*job_name & 255); } else { *nameptr++ = '_'; while (job_name[1] && !isalnum(job_name[1] & 255) && job_name[1] != '-') job_name ++; } } *nameptr = '\0'; // Figure out the extension... if (!ext) { if (!strcasecmp(job->format, "image/jpeg")) ext = "jpg"; else if (!strcasecmp(job->format, "image/png")) ext = "png"; else if (!strcasecmp(job->format, "image/pwg-raster")) ext = "pwg"; else if (!strcasecmp(job->format, "image/urf")) ext = "urf"; else if (!strcasecmp(job->format, "application/pdf")) ext = "pdf"; else if (!strcasecmp(job->format, "application/postscript")) ext = "ps"; else ext = "prn"; } // Create a filename with the job-id, job-name, and document-format (extension)... snprintf(fname, fnamesize, "%s/%s-%d-%s.%s", directory, job->printer->printer_name, job->id, name, ext); return (open(fname, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW | O_CLOEXEC, 0600)); } // // 'lprintDeleteJob()' - Remove a job from the system and free its memory. // void lprintDeleteJob(lprint_job_t *job) // I - Job { lprintLogJob(job, LPRINT_LOGLEVEL_INFO, "Removing job from history."); ippDelete(job->attrs); if (job->message) free(job->message); if (job->filename) { unlink(job->filename); free(job->filename); } free(job); } // // 'lprintFindJob()' - Find a job specified in a request. // lprint_job_t * // O - Job or `NULL` lprintFindJob(lprint_printer_t *printer,// I - Printer int job_id) // I - Job ID { lprint_job_t key, // Job search key *job; // Matching job, if any key.id = job_id; pthread_rwlock_rdlock(&(printer->rwlock)); job = (lprint_job_t *)cupsArrayFind(printer->jobs, &key); pthread_rwlock_unlock(&(printer->rwlock)); return (job); } lprint-1.0/server-log.c000066400000000000000000000164651362261677400151450ustar00rootroot00000000000000// // Logging functions for LPrint, a Label Printer Application // // Note: Log format strings currently only support %d and %s! // // Copyright © 2019-2020 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include #include // // Local functions... // static void write_log(lprint_system_t *system, lprint_loglevel_t level, const char *message, va_list ap); // // Local globals... // static const int syslevels[] = // Mapping of log levels to syslog { LOG_DEBUG | LOG_PID | LOG_LPR, LOG_INFO | LOG_PID | LOG_LPR, LOG_WARNING | LOG_PID | LOG_LPR, LOG_ERR | LOG_PID | LOG_LPR, LOG_CRIT | LOG_PID | LOG_LPR }; // // 'lprintLog()' - Log a message for the system. // void lprintLog(lprint_system_t *system, // I - System lprint_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { va_list ap; // Pointer to arguments if (level < system->loglevel) return; va_start(ap, message); if (system->logfd >= 0) write_log(system, level, message, ap); else vsyslog(syslevels[level], message, ap); va_end(ap); } // // 'lprintLogAttributes()' - Log attributes for a client connection. // void lprintLogAttributes( lprint_client_t *client, // I - Client const char *title, // I - Title for attributes ipp_t *ipp, // I - IPP message int is_response) // I - 1 if a response, 0 if a request { if (client->system->loglevel > LPRINT_LOGLEVEL_DEBUG) return; } // // 'lprintLogClient()' - Log a message for a client. // void lprintLogClient( lprint_client_t *client, // I - Client lprint_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { char cmessage[1024]; // Message with client prefix va_list ap; // Pointer to arguments if (level < client->system->loglevel) return; snprintf(cmessage, sizeof(cmessage), "[Client %d] %s", client->number, message); va_start(ap, message); if (client->system->logfd >= 0) write_log(client->system, level, cmessage, ap); else vsyslog(syslevels[level], cmessage, ap); va_end(ap); } // // 'lprintLogJob()' - Log a message for a job. // void lprintLogJob( lprint_job_t *job, // I - Job lprint_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { char jmessage[1024]; // Message with job prefix va_list ap; // Pointer to arguments if (level < job->system->loglevel) return; snprintf(jmessage, sizeof(jmessage), "[Job %d] %s", job->id, message); va_start(ap, message); if (job->system->logfd >= 0) write_log(job->system, level, jmessage, ap); else vsyslog(syslevels[level], jmessage, ap); va_end(ap); } // // 'lprintLogPrinter()' - Log a message for a printer. // void lprintLogPrinter( lprint_printer_t *printer, // I - Printer lprint_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string ...) // I - Additional arguments as needed { char pmessage[1024]; // Message with printer prefix va_list ap; // Pointer to arguments if (level < printer->system->loglevel) return; snprintf(pmessage, sizeof(pmessage), "[Printer %s] %s", printer->printer_name, message); va_start(ap, message); if (printer->system->logfd >= 0) write_log(printer->system, level, pmessage, ap); else vsyslog(syslevels[level], pmessage, ap); va_end(ap); } // // 'write_log()' - Write a line to the log file... // static void write_log(lprint_system_t *system, // I - System lprint_loglevel_t level, // I - Log level const char *message, // I - Printf-style message string va_list ap) // I - Pointer to additional arguments { char buffer[2048], // Output buffer *bufptr, // Pointer into buffer *bufend; // Pointer to end of buffer time_t curtime; // Current time struct tm curdate; // Current date static const char *prefix = "DIWEF"; // Message prefix const char *sval; // String value // Each log line starts with a standard prefix of log level and date/time... time(&curtime); gmtime_r(&curtime, &curdate); snprintf(buffer, sizeof(buffer), "%c [%04d-%02d-%02dT%02d:%02d:%02dZ] ", prefix[level], curdate.tm_year + 1900, curdate.tm_mon + 1, curdate.tm_mday, curdate.tm_hour, curdate.tm_min, curdate.tm_sec); bufptr = buffer + 25; // Skip level/date/time bufend = buffer + sizeof(buffer) - 1; // Leave room for newline on end // Then format the message line using a subset of printf format sequences... while (*message && bufptr < bufend) { if (*message == '%') { message ++; switch (*message) { case 'd' : // Log an integer snprintf(bufptr, bufptr - bufend + 1, "%d", va_arg(ap, int)); bufptr += strlen(bufptr); break; case 'p' : // Log a pointer snprintf(bufptr, bufptr - bufend + 1, "%p", va_arg(ap, void *)); bufptr += strlen(bufptr); break; case 's' : // Log a string if ((sval = va_arg(ap, char *)) == NULL) sval = "(null)"; while (*sval && bufptr < bufend) { int val = (*sval++) & 255; if (val < ' ' || val == 0x7f || val == '\\' || val == '\'' || val == '\"') { // Escape control and special characters in the string... if (bufptr > (bufend - 4)) break; *bufptr++ = '\\'; if (val == '\\') *bufptr++ = '\\'; else if (val == '\'') *bufptr++ = '\''; else if (val == '\"') *bufptr++ = '\"'; else if (val == '\n') *bufptr++ = 'n'; else if (val == '\r') *bufptr++ = 'r'; else if (val == '\t') *bufptr++ = 't'; else { // Use octal escape for other control characters... *bufptr++ = '0' + (val / 64); *bufptr++ = '0' + ((val / 8) & 7); *bufptr++ = '0' + (val & 7); } } else *bufptr++ = val; } break; case 'u' : // Log an unsigned integer snprintf(bufptr, bufptr - bufend + 1, "%u", va_arg(ap, unsigned)); bufptr += strlen(bufptr); break; case 'x' : // Log an unsigned integer as hex snprintf(bufptr, bufptr - bufend + 1, "%x", va_arg(ap, unsigned)); bufptr += strlen(bufptr); break; default : // Something else we don't support *bufptr++ = '%'; if (bufptr < bufend) *bufptr++ = *message; break; } } else *bufptr++ = *message; message ++; } // Add a newline and write it out... *bufptr++ = '\n'; write(system->logfd, buffer, bufptr - buffer); } lprint-1.0/server-print.c000066400000000000000000000547651362261677400155250ustar00rootroot00000000000000// // Print functions for LPrint, a Label Printer Application // // Copyright © 2019 by Michael R Sweet. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include "dither.h" #ifdef HAVE_LIBPNG # include #endif // HAVE_LIBPNG // // Local functions... // static void device_error(const char *message, void *err_data); static ipp_attribute_t *find_attr(lprint_job_t *job, const char *name, ipp_tag_t value_tag); static void prepare_options(lprint_job_t *job, lprint_options_t *options, unsigned num_pages); #ifdef HAVE_LIBPNG static void process_png(lprint_job_t *job); #endif // HAVE_LIBPNG static void process_raster(lprint_job_t *job); static void process_raw(lprint_job_t *job); // // 'lprintProcessJob()' - Process a print job. // void * // O - Thread exit status lprintProcessJob(lprint_job_t *job) // I - Job { int first_open = 1; // Is this the first time we try to open the device? // Move the job to the processing state... pthread_rwlock_wrlock(&job->rwlock); job->state = IPP_JSTATE_PROCESSING; job->processing = time(NULL); job->printer->processing_job = job; pthread_rwlock_wrlock(&job->rwlock); // Open the output device... pthread_rwlock_wrlock(&job->printer->driver->rwlock); while (!job->printer->driver->device) { job->printer->driver->device = lprintOpenDevice(job->printer->device_uri, device_error, job->system); if (!job->printer->driver->device) { // Log that the printer is unavailable then sleep for 5 seconds to retry. if (first_open) { lprintLogPrinter(job->printer, LPRINT_LOGLEVEL_ERROR, "Unable to open device '%s', pausing queue until printer becomes available.", job->printer->device_uri); first_open = 0; job->printer->state = IPP_PSTATE_STOPPED; job->printer->state_time = time(NULL); } sleep(5); } } pthread_rwlock_unlock(&job->printer->driver->rwlock); // Process the job... job->printer->state = IPP_PSTATE_PROCESSING; job->printer->state_time = time(NULL); if (!strcmp(job->format, "image/pwg-raster") || !strcmp(job->format, "image/urf")) { process_raster(job); } #ifdef HAVE_LIBPNG else if (!strcmp(job->format, "image/png")) { process_png(job); } #endif // HAVE_LIBPNG else if (!strcmp(job->format, job->printer->driver->format)) { process_raw(job); } else { // Abort a job we can't process... lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to process job with format '%s'.", job->format); job->state = IPP_JSTATE_ABORTED; } // Move the job to a completed state... pthread_rwlock_wrlock(&job->rwlock); if (job->cancel) job->state = IPP_JSTATE_CANCELED; else if (job->state == IPP_JSTATE_PROCESSING) job->state = IPP_JSTATE_COMPLETED; job->completed = time(NULL); job->printer->state = IPP_PSTATE_IDLE; job->printer->state_time = time(NULL); job->printer->processing_job = NULL; pthread_rwlock_wrlock(&job->rwlock); pthread_rwlock_wrlock(&job->printer->rwlock); cupsArrayRemove(job->printer->active_jobs, job); cupsArrayAdd(job->printer->completed_jobs, job); if (!job->system->clean_time) job->system->clean_time = time(NULL) + 60; pthread_rwlock_unlock(&job->printer->rwlock); if (job->printer->is_deleted) { lprintDeletePrinter(job->printer); } else if (cupsArrayCount(job->printer->active_jobs) > 0) { lprintCheckJobs(job->printer); } else { pthread_rwlock_wrlock(&job->printer->driver->rwlock); lprintCloseDevice(job->printer->driver->device); job->printer->driver->device = NULL; pthread_rwlock_unlock(&job->printer->driver->rwlock); } return (NULL); } // // 'device_error()' - Log a device error for the system... // static void device_error( const char *message, // I - Message void *err_data) // I - Callback data (system) { lprint_system_t *system = (lprint_system_t *)err_data; // System lprintLog(system, LPRINT_LOGLEVEL_ERROR, "[Device] %s", message); } // // 'find_attr()' - Find a matching attribute for a job. // static ipp_attribute_t * // O - Attribute find_attr(lprint_job_t *job, // I - Job const char *name, // I - Attribute name ipp_tag_t value_tag) // I - Value tag { char defname[256]; // xxx-default attribute ipp_attribute_t *attr; // Attribute if ((attr = ippFindAttribute(job->attrs, name, value_tag)) != NULL) return (attr); snprintf(defname, sizeof(defname), "%s-default", name); if ((attr = ippFindAttribute(job->printer->attrs, defname, value_tag)) != NULL) return (attr); return (ippFindAttribute(job->printer->driver->attrs, defname, value_tag)); } // // 'prepare_options()' - Prepare the job options. // static void prepare_options( lprint_job_t *job, // I - Job lprint_options_t *options, // I - Job options data unsigned num_pages) // I - Number of pages { int i; // Looping var ipp_attribute_t *attr; // Attribute lprint_driver_t *driver = job->printer->driver; // Driver info // Clear all options... memset(options, 0, sizeof(lprint_options_t)); options->num_pages = num_pages; options->media = driver->media_default; pthread_rwlock_rdlock(&job->printer->rwlock); pthread_rwlock_rdlock(&job->printer->driver->rwlock); // copies if ((attr = find_attr(job, "copies", IPP_TAG_INTEGER)) != NULL) options->copies = ippGetInteger(attr, 0); else options->copies = 1; // media-xxx if ((attr = find_attr(job, "media-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) { options->media.source[0] = '\0'; lprintImportMediaCol(ippGetCollection(attr, 0), &options->media); } else if ((attr = find_attr(job, "media", IPP_TAG_ZERO)) != NULL) { const char *pwg_name = ippGetString(attr, 0, NULL); pwg_media_t *pwg_media = pwgMediaForPWG(pwg_name); strlcpy(options->media.size_name, pwg_name, sizeof(options->media.size_name)); options->media.size_width = pwg_media->width; options->media.size_length = pwg_media->length; options->media.source[0] = '\0'; } if (!options->media.source[0]) { for (i = 0; i < driver->num_source; i ++) { if (!strcmp(options->media.size_name, driver->media_ready[i].size_name)) { strlcpy(options->media.source, driver->source[i], sizeof(options->media.source)); break; } } if (!options->media.source[0]) strlcpy(options->media.source, driver->media_default.source, sizeof(options->media.source)); } // orientation-requested if ((attr = find_attr(job, "orientation-requested", IPP_TAG_ENUM)) != NULL) options->orientation_requested = (ipp_orient_t)ippGetInteger(attr, 0); else options->orientation_requested = IPP_ORIENT_NONE; // print-color-mode if ((attr = find_attr(job, "print-color-mode", IPP_TAG_KEYWORD)) != NULL) options->print_color_mode = ippGetString(attr, 0, NULL); else options->print_color_mode = "bi-level"; if (!strcmp(options->print_color_mode, "bi-level")) options->dither = dithert; else options->dither = ditherc; // print-content-optimize if ((attr = find_attr(job, "print-content-optimize", IPP_TAG_KEYWORD)) != NULL) options->print_color_mode = ippGetString(attr, 0, NULL); else options->print_content_optimize = "auto"; // print-darkness if ((attr = find_attr(job, "print-darkness", IPP_TAG_INTEGER)) != NULL) options->print_darkness = ippGetInteger(attr, 0); // print-quality if ((attr = find_attr(job, "print-quality", IPP_TAG_ENUM)) != NULL) options->print_quality = (ipp_quality_t)ippGetInteger(attr, 0); else options->print_quality = IPP_QUALITY_NORMAL; // print-speed if ((attr = find_attr(job, "print-speed", IPP_TAG_INTEGER)) != NULL) options->print_speed = ippGetInteger(attr, 0); else options->print_speed = driver->speed_default; // printer-resolution if ((attr = find_attr(job, "printer-resolution", IPP_TAG_RESOLUTION)) != NULL) { ipp_res_t units; // Resolution units options->printer_resolution[0] = ippGetResolution(attr, 0, options->printer_resolution + 1, &units); } else if (options->print_quality == IPP_QUALITY_DRAFT) { // print-quality=draft options->printer_resolution[0] = driver->x_resolution[0]; options->printer_resolution[1] = driver->y_resolution[0]; } else if (options->print_quality == IPP_QUALITY_NORMAL) { // print-quality=normal i = driver->num_resolution / 2; options->printer_resolution[0] = driver->x_resolution[i]; options->printer_resolution[1] = driver->y_resolution[i]; } else { // print-quality=high i = driver->num_resolution - 1; options->printer_resolution[0] = driver->x_resolution[i]; options->printer_resolution[1] = driver->y_resolution[i]; } // Figure out the PWG raster header... cupsRasterInitPWGHeader(&options->header, pwgMediaForPWG(options->media.size_name), "black_1", options->printer_resolution[0], options->printer_resolution[1], "one-sided", "normal"); // Log options... lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsWidth=%u", options->header.cupsWidth); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsHeight=%u", options->header.cupsHeight); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsBitsPerColor=%u", options->header.cupsBitsPerColor); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsBitsPerPixel=%u", options->header.cupsBitsPerPixel); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsBytesPerLine=%u", options->header.cupsBytesPerLine); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsColorOrder=%u", options->header.cupsColorOrder); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsColorSpace=%u", options->header.cupsColorSpace); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.cupsNumColors=%u", options->header.cupsNumColors); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "header.HWResolution=[%u %u]", options->header.HWResolution[0], options->header.HWResolution[1]); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "num_pages=%u", options->num_pages); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "copies=%d", options->copies); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.bottom_margin=%d", options->media.bottom_margin); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.left_margin=%d", options->media.left_margin); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.right_margin=%d", options->media.right_margin); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.size=%dx%d", options->media.size_width, options->media.size_length); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.size_name='%s'", options->media.size_name); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.source='%s'", options->media.source); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.top_margin=%d", options->media.top_margin); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.top_offset=%d", options->media.top_offset); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.tracking='%s'", lprintMediaTrackingString(options->media.tracking)); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "media.type='%s'", options->media.type); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "orientation_requested=%s", ippEnumString("orientation-requested", (int)options->orientation_requested)); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "print_color_mode='%s'", options->print_color_mode); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "print_content_optimize='%s'", options->print_content_optimize); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "print_darkness=%d", options->print_darkness); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "print_quality=%s", ippEnumString("print-quality", (int)options->print_quality)); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "print_speed=%d", options->print_speed); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "printer_resolution=%dx%ddpi", options->printer_resolution[0], options->printer_resolution[1]); pthread_rwlock_unlock(&job->printer->driver->rwlock); pthread_rwlock_unlock(&job->printer->rwlock); } // // 'process_png()' - Process a PNG image file. // #ifdef HAVE_LIBPNG static void process_png(lprint_job_t *job) // I - Job { int i; // Looping var lprint_driver_t *driver = job->printer->driver; // Driver const unsigned char *dither; // Dither line lprint_options_t options; // Job options png_image png; // PNG image data png_color bg; // Background color unsigned ileft, // Imageable left margin itop, // Imageable top margin iwidth, // Imageable width iheight; // Imageable length/height unsigned char *line = NULL, // Output line *lineptr, // Pointer in line byte, // Byte in line *pixels = NULL, // Pixels in image *pixbase, // Pointer to first pixel *pixptr, // Pointer into image bit; // Current bit unsigned png_width, // Rotated PNG width png_height, // Rotated PNG height x, // X position xsize, // Scaled width xstep, // X step xstart, // X start position xend, // X end position y, // Y position ysize, // Scaled height ystart, // Y start position yend; // Y end position int xdir, xerr, // X error accumulator xmod, // X modulus ydir; // Prepare options... prepare_options(job, &options, 1); options.header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount] = options.copies; job->impressions = options.copies; ileft = options.media.left_margin * options.printer_resolution[0] / 2540; itop = options.media.top_margin * options.printer_resolution[1] / 2540; iwidth = options.header.cupsWidth - (options.media.left_margin + options.media.right_margin) * options.printer_resolution[0] / 2540; iheight = options.header.cupsHeight - (options.media.bottom_margin + options.media.top_margin) * options.printer_resolution[1] / 2540; lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "ileft=%u, itop=%u, iwidth=%u, iheight=%u", ileft, itop, iwidth, iheight); if (iwidth == 0 || iheight == 0) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Invalid media size"); goto abort_job; } // Load the PNG... memset(&png, 0, sizeof(png)); png.version = PNG_IMAGE_VERSION; bg.red = bg.green = bg.blue = 255; png_image_begin_read_from_file(&png, job->filename); if (png.warning_or_error & PNG_IMAGE_ERROR) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to open PNG file '%s' - %s", job->filename, png.message); goto abort_job; } lprintLogJob(job, LPRINT_LOGLEVEL_INFO, "PNG image is %ux%u", png.width, png.height); png.format = PNG_FORMAT_GRAY; pixels = malloc(PNG_IMAGE_SIZE(png)); png_image_finish_read(&png, &bg, pixels, 0, NULL); if (png.warning_or_error & PNG_IMAGE_ERROR) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to open PNG file '%s' - %s", job->filename, png.message); goto abort_job; } // Figure out the scaling and rotation of the image... if (options.orientation_requested == IPP_ORIENT_NONE) { if (png.width > png.height && options.header.cupsWidth < options.header.cupsHeight) { options.orientation_requested = IPP_ORIENT_LANDSCAPE; lprintLogJob(job, LPRINT_LOGLEVEL_INFO, "Auto-orientation: landscape"); } else { options.orientation_requested = IPP_ORIENT_PORTRAIT; lprintLogJob(job, LPRINT_LOGLEVEL_INFO, "Auto-orientation: portrait"); } } switch (options.orientation_requested) { default : case IPP_ORIENT_PORTRAIT : pixbase = pixels; png_width = png.width; png_height = png.height; xdir = 1; ydir = png.width; xsize = iwidth; ysize = xsize * png.height / png.width; if (ysize > iheight) { ysize = iheight; xsize = ysize * png.width / png.height; } break; case IPP_ORIENT_REVERSE_PORTRAIT : pixbase = pixels + png.width * png.height - 1; png_width = png.width; png_height = png.height; xdir = -1; ydir = -png.width; xsize = iwidth; ysize = xsize * png.height / png.width; if (ysize > iheight) { ysize = iheight; xsize = ysize * png.width / png.height; } break; case IPP_ORIENT_LANDSCAPE : // 90 counter-clockwise pixbase = pixels + png.width - 1; png_width = png.height; png_height = png.width; xdir = png.width; ydir = -1; xsize = iwidth; ysize = xsize * png.width / png.height; if (ysize > iheight) { ysize = iheight; xsize = ysize * png.height / png.width; } break; case IPP_ORIENT_REVERSE_LANDSCAPE : // 90 clockwise pixbase = pixels + (png.height - 1) * png.width; png_width = png.height; png_height = png.width; xdir = -png.width; ydir = 1; xsize = iwidth; ysize = xsize * png.width / png.height; if (ysize > iheight) { ysize = iheight; xsize = ysize * png.height / png.width; } break; } xstart = ileft + (iwidth - xsize) / 2; xend = xstart + xsize; ystart = itop + (iheight - ysize) / 2; yend = ystart + ysize; xmod = png_width % xsize; xstep = (png_width / xsize) * xdir; lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "xsize=%u, xstart=%u, xend=%u, xdir=%d, xmod=%d, xstep=%d", xsize, xstart, xend, xdir, xmod, xstep); lprintLogJob(job, LPRINT_LOGLEVEL_DEBUG, "ysize=%u, ystart=%u, yend=%u, ydir=%d", ysize, ystart, yend, ydir); // Start the job... if (!(driver->rstartjob)(job, &options)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to start raster job."); goto abort_job; } line = malloc(options.header.cupsBytesPerLine); // Print every copy... for (i = 0; i < options.copies; i ++) { if (!(driver->rstartpage)(job, &options, 1)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to start raster page."); goto abort_job; } // Leading blank space... memset(line, 0, options.header.cupsBytesPerLine); for (y = 0; y < ystart; y ++) { if (!(driver->rwrite)(job, &options, y, line)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to write raster line %u.", y); goto abort_job; } } // Now dither the image... for (; y < yend; y ++) { pixptr = pixbase + ydir * (int)((y - ystart) * png_height / ysize); dither = options.dither[y & 15]; for (x = xstart, lineptr = line + x / 8, bit = 128 >> (x & 7), byte = 0, xerr = 0; x < xend; x ++) { // Dither the current pixel... if (*pixptr <= dither[x & 15]) byte |= bit; // Advance to the next pixel... pixptr += xstep; xerr += xmod; if (xerr >= xsize) { // Accumulated error has overflowed, advance another pixel... xerr -= xsize; pixptr += xdir; } // and the next bit if (bit == 1) { // Current byte is "full", save it... *lineptr++ = byte; byte = 0; bit = 128; } else bit /= 2; } if (bit < 128) *lineptr = byte; if (!(driver->rwrite)(job, &options, y, line)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to write raster line %u.", y); goto abort_job; } } // Trailing blank space... memset(line, 0, options.header.cupsBytesPerLine); for (; y < options.header.cupsHeight; y ++) { if (!(driver->rwrite)(job, &options, y, line)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to write raster line %u.", y); goto abort_job; } } // End the page... if (!(driver->rendpage)(job, &options, 1)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to end raster page."); goto abort_job; } job->impcompleted ++; } // End the job... if (!(driver->rendjob)(job, &options)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to end raster job."); goto abort_job; } // Free the image data when we're done... png_image_free(&png); free(pixels); free(line); return; // If we get there then something bad happened... abort_job: job->state = IPP_JSTATE_ABORTED; // Free the image data when we're done... png_image_free(&png); free(pixels); free(line); } #endif // HAVE_LIBPNG // // 'process_raster()' - Process an Apple/PWG Raster file. // static void process_raster(lprint_job_t *job) // I - Job { lprint_driver_t *driver = job->printer->driver; // Driver for job lprint_options_t options; // Job options int fd = -1; // Job file cups_raster_t *ras = NULL; // Raster stream cups_page_header2_t header; // Page header unsigned char *line; // Pixel line unsigned page = 0, // Current page y; // Current line // Open the raster stream... if ((fd = open(job->filename, O_RDONLY)) < 0) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to open job file '%s' - %s", job->filename, strerror(errno)); goto abort_job; } if ((ras = cupsRasterOpen(fd, CUPS_RASTER_READ)) == NULL) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to open raster stream for file '%s' - %s", job->filename, cupsLastErrorString()); goto abort_job; } // Prepare options... if (!cupsRasterReadHeader2(ras, &header)) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to read raster stream for file '%s' - %s", job->filename, cupsLastErrorString()); goto abort_job; } job->impressions = (int)header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount]; prepare_options(job, &options, job->impressions); if (!(driver->rstartjob)(job, &options)) goto abort_job; // Print pages... do { page ++; job->impcompleted ++; if (!(driver->rstartpage)(job, &options, page)) goto abort_job; line = malloc(header.cupsBytesPerLine); for (y = 0; y < header.cupsHeight; y ++) { if (cupsRasterReadPixels(ras, line, header.cupsBytesPerLine)) (driver->rwrite)(job, &options, y, line); else break; } free(line); if (!(driver->rendpage)(job, &options, page)) goto abort_job; if (y < header.cupsHeight) { lprintLogJob(job, LPRINT_LOGLEVEL_ERROR, "Unable to read page from raster stream for file '%s' - %s", job->filename, cupsLastErrorString()); (driver->rendjob)(job, &options); goto abort_job; } } while (cupsRasterReadHeader2(ras, &header)); if (!(driver->rendjob)(job, &options)) goto abort_job; cupsRasterClose(ras); close(fd); return; // If we get here something went wrong... abort_job: if (ras) cupsRasterClose(ras); if (fd >= 0) close(fd); job->state = IPP_JSTATE_ABORTED; } // // 'process_raw()' - Process a raw print file. // static void process_raw(lprint_job_t *job) // I - Job { lprint_options_t options; // Job options prepare_options(job, &options, 1); if (!(job->printer->driver->print)(job, &options)) job->state = IPP_JSTATE_ABORTED; } lprint-1.0/server-printer.c000066400000000000000000000631201362261677400160350ustar00rootroot00000000000000// // Printer object for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include #ifdef __APPLE__ # include # include #else # include #endif // __APPLE__ #ifdef HAVE_SYS_RANDOM_H # include #endif // HAVE_SYS_RANDOM_H #ifdef HAVE_GNUTLS_RND # include #endif // HAVE_GNUTLS_RND // // Local functions... // static int compare_active_jobs(lprint_job_t *a, lprint_job_t *b); static int compare_completed_jobs(lprint_job_t *a, lprint_job_t *b); static int compare_jobs(lprint_job_t *a, lprint_job_t *b); static int compare_printers(lprint_printer_t *a, lprint_printer_t *b); static void free_printer(lprint_printer_t *printer); static ipp_t *make_xri(const char *uri, const char *authentication, const char *security); // // 'lprintCreatePrinter()' - Create a new printer. // lprint_printer_t * // O - Printer lprintCreatePrinter( lprint_system_t *system, // I - System int printer_id, // I - printer-id value or 0 for new const char *printer_name, // I - Printer name const char *driver_name, // I - Driver name const char *device_uri, // I - Device URI const char *geo_location, // I - Geographic location or `NULL` const char *location, // I - Human-readable location or `NULL` const char *organization, // I - Organization const char *org_unit) // I - Organizational unit { lprint_printer_t *printer; // Printer char resource[1024], // Resource path ipp_uri[1024], // Printer URI ipps_uri[1024], // Secure printer URI *uris[2], // All URIs icons[2][1024], // printer-icons URIs adminurl[1024], // printer-more-info URI supplyurl[1024],// printer-supply-info-uri URI uuid[128]; // printer-uuid ipp_t *xris[2]; // All XRIs int k_supported; // Maximum file size supported int num_formats; // Number of supported document formats const char *formats[10]; // Supported document formats struct statfs spoolinfo; // FS info for spool directory double spoolsize; // FS size static const char * const ipp_versions[] = { // ipp-versions-supported values "1.1", "2.0" }; static const char * const ipp_features[] = { // ipp-features-supported values "ipp-everywhere" }; static const int operations[] = // operations-supported values { IPP_OP_PRINT_JOB, IPP_OP_VALIDATE_JOB, IPP_OP_CREATE_JOB, IPP_OP_SEND_DOCUMENT, IPP_OP_CANCEL_JOB, IPP_OP_GET_JOB_ATTRIBUTES, IPP_OP_GET_JOBS, IPP_OP_GET_PRINTER_ATTRIBUTES, IPP_OP_SET_PRINTER_ATTRIBUTES, IPP_OP_CANCEL_MY_JOBS, IPP_OP_CLOSE_JOB, IPP_OP_IDENTIFY_PRINTER }; static const char * const charset[] = // charset-supported values { "us-ascii", "utf-8" }; static const char * const compression[] = { // compression-supported values "deflate", "gzip", "none" }; static const char * const identify_actions[] = { // identify-actions-supported values "display", "sound" }; static const char * const job_creation_attributes[] = { // job-creation-attributes-supported values "copies", "document-format", "document-name", "ipp-attribute-fidelity", "job-name", "job-priority", "media", "media-col", "multiple-document-handling", "orientation-requested", "print-color-mode", "print-content-optimize", "print-darkness", "print-quality", "print-speed", "printer-resolution" }; static const char * const media_col[] = { // media-col-supported values "media-bottom-margin", "media-left-margin", "media-right-margin", "media-size", "media-size-name", "media-source", "media-top-margin", "media-top-offset", "media-tracking", "media-type" }; static const char * const multiple_document_handling[] = { // multiple-document-handling-supported values "separate-documents-uncollated-copies", "separate-documents-collated-copies" }; static const int orientation_requested[] = { IPP_ORIENT_PORTRAIT, IPP_ORIENT_LANDSCAPE, IPP_ORIENT_REVERSE_LANDSCAPE, IPP_ORIENT_REVERSE_PORTRAIT, IPP_ORIENT_NONE }; static const char * const print_color_mode[] = { // print-color-mode-supported "bi-level", "monochrome" }; static const char * const print_content_optimize[] = { // print-content-optimize-supported "auto", "graphic", "photo", "text-and-graphic", "text" }; static const int print_quality[] = // print-quality-supported { IPP_QUALITY_DRAFT, IPP_QUALITY_NORMAL, IPP_QUALITY_HIGH }; static const char * const printer_kind[] = { // printer-kind values "labels", "receipt" }; static const char * const printer_settable_attributes[] = { // printer-settable-attributes values "copies-default", "document-format-default", "label-mode-configured", "label-tear-off-configured", "media-col-default", "media-col-ready", "media-default", "media-ready", "multiple-document-handling-default", "orientation-requested-default", "print-color-mode-default", "print-content-optimize-default", "print-darkness-default", "print-quality-default", "print-speed-default", "printer-darkness-configured", "printer-geo-location", "printer-location", "printer-organization", "printer-organizational-unit", "printer-resolution-default" }; static const char * const printer_strings_languages[] = { // printer-strings-languages-supported values "de", "en", "es", "fr", "it" }; static const char * const uri_authentication[] = { // uri-authentication-supported values "none", "none" }; static const char * const uri_security[] = { // uri-security-supported values "none", "tls" }; static const char * const which_jobs[] = { // which-jobs-supported values "completed", "not-completed", "all" }; // Allocate memory for the printer... if ((printer = calloc(1, sizeof(lprint_printer_t))) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to allocate memory for printer: %s", strerror(errno)); return (NULL); } // Prepare URI values for the printer attributes... snprintf(resource, sizeof(resource), "/ipp/print/%s", printer_name); httpAssembleURI(HTTP_URI_CODING_ALL, ipp_uri, sizeof(ipp_uri), "ipp", NULL, system->hostname, system->port, resource); httpAssembleURI(HTTP_URI_CODING_ALL, ipps_uri, sizeof(ipps_uri), "ipps", NULL, system->hostname, system->port, resource); httpAssembleURI(HTTP_URI_CODING_ALL, icons[0], sizeof(icons[0]), "https", NULL, system->hostname, system->port, "/lprint.png"); httpAssembleURI(HTTP_URI_CODING_ALL, icons[1], sizeof(icons[1]), "https", NULL, system->hostname, system->port, "/lprint-large.png"); httpAssembleURI(HTTP_URI_CODING_ALL, adminurl, sizeof(adminurl), "https", NULL, system->hostname, system->port, resource); httpAssembleURIf(HTTP_URI_CODING_ALL, supplyurl, sizeof(supplyurl), "https", NULL, system->hostname, system->port, "%s/supplies", resource); lprintMakeUUID(system, printer_name, 0, uuid, sizeof(uuid)); // Get the maximum spool size based on the size of the filesystem used for // the spool directory. If the host OS doesn't support the statfs call // or the filesystem is larger than 2TiB, always report INT_MAX. if (statfs(system->directory, &spoolinfo)) k_supported = INT_MAX; else if ((spoolsize = (double)spoolinfo.f_bsize * spoolinfo.f_blocks / 1024) > INT_MAX) k_supported = INT_MAX; else k_supported = (int)spoolsize; // Create the driver and assemble the final list of document formats... printer->driver = lprintCreateDriver(driver_name); num_formats = 0; formats[num_formats ++] = "application/octet-stream"; if (printer->driver->format && strcmp(printer->driver->format, "application/octet-stream")) formats[num_formats ++] = printer->driver->format; #ifdef HAVE_LIBPNG formats[num_formats ++] = "image/png"; #endif // HAVE_LIBPNG formats[num_formats ++] = "image/pwg-raster"; formats[num_formats ++] = "image/urf"; // Initialize printer structure and attributes... pthread_rwlock_init(&printer->rwlock, NULL); printer->system = system; printer->printer_name = strdup(printer_name); printer->dns_sd_name = strdup(printer_name); printer->resource = strdup(resource); printer->resourcelen = strlen(resource); printer->device_uri = strdup(device_uri); printer->driver_name = strdup(driver_name); printer->geo_location = geo_location ? strdup(geo_location) : NULL; printer->location = location ? strdup(location) : NULL; printer->organization = organization ? strdup(organization) : NULL; printer->org_unit = org_unit ? strdup(org_unit) : NULL; printer->attrs = ippNew(); printer->start_time = time(NULL); printer->config_time = printer->start_time; printer->state = IPP_PSTATE_IDLE; printer->state_reasons = LPRINT_PREASON_NONE; printer->state_time = printer->start_time; printer->jobs = cupsArrayNew3((cups_array_func_t)compare_jobs, NULL, NULL, 0, NULL, (cups_afree_func_t)lprintDeleteJob); printer->active_jobs = cupsArrayNew((cups_array_func_t)compare_active_jobs, NULL); printer->completed_jobs = cupsArrayNew((cups_array_func_t)compare_completed_jobs, NULL); printer->next_job_id = 1; // charset-configured ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_CHARSET), "charset-configured", NULL, "utf-8"); // charset-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_CHARSET), "charset-supported", sizeof(charset) / sizeof(charset[0]), NULL, charset); // compression-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "compression-supported", (int)(sizeof(compression) / sizeof(compression[0])), NULL, compression); // copies-default ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "copies-default", 1); // copies-supported ippAddRange(printer->attrs, IPP_TAG_PRINTER, "copies-supported", 1, 999); // document-format-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_MIMETYPE), "document-format-default", NULL, "application/octet-stream"); // document-format-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, "document-format-supported", num_formats, NULL, formats); // generated-natural-language-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "generated-natural-language-supported", NULL, "en"); // identify-actions-default ippAddString (printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "identify-actions-default", NULL, "sound"); // identify-actions-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "identify-actions-supported", sizeof(identify_actions) / sizeof(identify_actions[0]), NULL, identify_actions); // ipp-features-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-features-supported", sizeof(ipp_features) / sizeof(ipp_features[0]), NULL, ipp_features); // ipp-versions-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "ipp-versions-supported", (int)(sizeof(ipp_versions) / sizeof(ipp_versions[0])), NULL, ipp_versions); // job-creation-attributes-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "job-creation-attributes-supported", (int)(sizeof(job_creation_attributes) / sizeof(job_creation_attributes[0])), NULL, job_creation_attributes); // job-ids-supported ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "job-ids-supported", 1); // job-k-octets-supported ippAddRange(printer->attrs, IPP_TAG_PRINTER, "job-k-octets-supported", 0, k_supported); // job-priority-default ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-priority-default", 50); // job-priority-supported ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-priority-supported", 1); // job-sheets-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_NAME), "job-sheets-default", NULL, "none"); // job-sheets-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_NAME), "job-sheets-supported", NULL, "none"); // media-col-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "media-col-supported", (int)(sizeof(media_col) / sizeof(media_col[0])), NULL, media_col); // multiple-document-handling-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-document-handling-supported", sizeof(multiple_document_handling) / sizeof(multiple_document_handling[0]), NULL, multiple_document_handling); // multiple-document-jobs-supported ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "multiple-document-jobs-supported", 0); // multiple-operation-time-out ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "multiple-operation-time-out", 60); // multiple-operation-time-out-action ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "multiple-operation-time-out-action", NULL, "abort-job"); // natural-language-configured ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_LANGUAGE), "natural-language-configured", NULL, "en"); // operations-supported ippAddIntegers(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "operations-supported", (int)(sizeof(operations) / sizeof(operations[0])), operations); // orientation-requested-default ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "orientation-requested-default", IPP_ORIENT_NONE); // orientation-requested-supported ippAddIntegers(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "orientation-requested-supported", (int)(sizeof(orientation_requested) / sizeof(orientation_requested[0])), orientation_requested); // pdl-override-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pdl-override-supported", NULL, "attempted"); // print-color-mode-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-default", NULL, "monochrome"); // print-color-mode-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-supported", (int)(sizeof(print_color_mode) / sizeof(print_color_mode[0])), NULL, print_color_mode); // print-content-optimize-default ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-content-optimize-default", NULL, "auto"); // print-content-optimize-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-content-optimize-supported", (int)(sizeof(print_content_optimize) / sizeof(print_content_optimize[0])), NULL, print_content_optimize); // print-quality-default ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-default", IPP_QUALITY_NORMAL); // print-quality-supported ippAddIntegers(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "print-quality-supported", (int)(sizeof(print_quality) / sizeof(print_quality[0])), print_quality); // printer-get-attributes-supported ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-get-attributes-supported", NULL, "document-format"); // printer-icons uris[0] = icons[0]; uris[1] = icons[1]; ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-icons", 2, NULL, (const char * const *)uris); // printer-info ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info", NULL, printer_name); // printer-kind ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "printer-kind", (int)(sizeof(printer_kind) / sizeof(printer_kind[0])), NULL, printer_kind); // printer-more-info ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", NULL, adminurl); // printer-name ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME, "printer-name", NULL, printer_name); // printer-settable-attributes ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "printer-settable-attributes", (int)(sizeof(printer_settable_attributes) / sizeof(printer_settable_attributes[0])), NULL, printer_settable_attributes); // printer-strings-languages-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_LANGUAGE, "printer-strings-languages-supported", (int)(sizeof(printer_strings_languages) / sizeof(printer_strings_languages[0])), NULL, printer_strings_languages); // printer-supply-info-uri ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-supply-info-uri", NULL, supplyurl); // printer-uri-supported uris[0] = ipp_uri; uris[1] = ipps_uri; ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uri-supported", 2, NULL, (const char * const *)uris); // printer-uuid ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-uuid", NULL, uuid); // printer-xri-supported xris[0] = make_xri(ipp_uri, uri_authentication[0], uri_security[0]); xris[1] = make_xri(ipps_uri, uri_authentication[1], uri_security[1]); printer->xri_supported = ippAddCollections(printer->attrs, IPP_TAG_PRINTER, "printer-xri-supported", 2, (const ipp_t **)xris); ippDelete(xris[0]); ippDelete(xris[1]); // uri-authentication-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-authentication-supported", 2, NULL, uri_authentication); // uri-security-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "uri-security-supported", 2, NULL, uri_security); // which-jobs-supported ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "which-jobs-supported", sizeof(which_jobs) / sizeof(which_jobs[0]), NULL, which_jobs); // Add the printer to the system... pthread_rwlock_wrlock(&system->rwlock); if (printer_id) printer->printer_id = printer_id; else printer->printer_id = system->next_printer_id ++; if (!system->printers) system->printers = cupsArrayNew3((cups_array_func_t)compare_printers, NULL, NULL, 0, NULL, (cups_afree_func_t)free_printer); cupsArrayAdd(system->printers, printer); if (!system->default_printer) system->default_printer = printer->printer_id; pthread_rwlock_unlock(&system->rwlock); // Register the printer with Bonjour... if (system->subtypes) lprintRegisterDNSSD(printer); // Return it! return (printer); } // // 'lprintDeletePrinter()' - Delete a printer. // void lprintDeletePrinter(lprint_printer_t *printer) /* I - Printer */ { // Remove the printer from the system object... pthread_rwlock_wrlock(&printer->system->rwlock); cupsArrayRemove(printer->system->printers, printer); pthread_rwlock_unlock(&printer->system->rwlock); } // // 'lprintFindPrinter()' - Find a printer by resource... // lprint_printer_t * // O - Printer or `NULL` if none lprintFindPrinter( lprint_system_t *system, // I - System const char *resource, // I - Resource path or `NULL` int printer_id) // I - Printer ID or `0` { lprint_printer_t *printer; // Matching printer lprintLog(system, LPRINT_LOGLEVEL_DEBUG, "lprintFindPrinter(system, resource=\"%s\", printer_id=%d)", resource, printer_id); pthread_rwlock_rdlock(&system->rwlock); if (resource && (!strcmp(resource, "/ipp/print") || (!strncmp(resource, "/ipp/print/", 11) && isdigit(resource[11] & 255)))) { printer_id = system->default_printer; resource = NULL; lprintLog(system, LPRINT_LOGLEVEL_DEBUG, "lprintFindPrinter: Looking for default printer_id=%d", printer_id); } for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { lprintLog(system, LPRINT_LOGLEVEL_DEBUG, "lprintFindPrinter: printer '%s' - resource=\"%s\", printer_id=%d", printer->printer_name, printer->resource, printer->printer_id); if (resource && !strncmp(printer->resource, resource, printer->resourcelen) && (!resource[printer->resourcelen] || resource[printer->resourcelen] == '/')) break; else if (printer->printer_id == printer_id) break; } pthread_rwlock_unlock(&system->rwlock); lprintLog(system, LPRINT_LOGLEVEL_DEBUG, "lprintFindPrinter: Returning %p(%s)", printer, printer ? printer->printer_name : "none"); return (printer); } // // 'lprintMakeUUID()' - Make a UUID for a system, printer, or job. // // Unlike httpAssembleUUID, this function does not introduce random data for // printers and systems so the UUIDs are stable. // char * // I - UUID string lprintMakeUUID( lprint_system_t *system, // I - System const char *printer_name, // I - Printer name or `NULL` for none int job_id, // I - Job ID or `0` for none char *buffer, // I - String buffer size_t bufsize) // I - Size of buffer { char data[1024]; // Source string for MD5 unsigned char sha256[32]; // SHA-256 digest/sum // Build a version 3 UUID conforming to RFC 4122. // // Start with the SHA-256 sum of the hostname, port, object name and // number, and some random data on the end for jobs (to avoid duplicates). if (printer_name && job_id) snprintf(data, sizeof(data), "_LPRINT_JOB_:%s:%d:%s:%d:%08x", system->hostname, system->port, printer_name, job_id, lprintRand()); else if (printer_name) snprintf(data, sizeof(data), "_LPRINT_PRINTER_:%s:%d:%s", system->hostname, system->port, printer_name); else snprintf(data, sizeof(data), "_LPRINT_SYSTEM_:%s:%d", system->hostname, system->port); cupsHashData("sha-256", (unsigned char *)data, strlen(data), sha256, sizeof(sha256)); // Generate the UUID from the SHA-256... snprintf(buffer, bufsize, "urn:uuid:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", sha256[0], sha256[1], sha256[3], sha256[4], sha256[5], sha256[6], (sha256[10] & 15) | 0x30, sha256[11], (sha256[15] & 0x3f) | 0x40, sha256[16], sha256[20], sha256[21], sha256[25], sha256[26], sha256[30], sha256[31]); return (buffer); } // // 'lprintRand()' - Return the best 32-bit random number we can. // unsigned // O - Random number lprintRand(void) { #ifdef HAVE_ARC4RANDOM // arc4random uses real entropy automatically... return (arc4random()); #else # ifdef HAVE_GETRANDOM // Linux has the getrandom function to get real entropy, but can fail... unsigned buffer; // Random number buffer if (getrandom(&buffer, sizeof(buffer), 0) == sizeof(buffer)) return (buffer); # elif defined(HAVE_GNUTLS_RND) // GNU TLS has the gnutls_rnd function we can use as well, but can fail... unsigned buffer; // Random number buffer if (!gnutls_rnd(GNUTLS_RND_NONCE, &buffer, sizeof(buffer))) return (buffer); # endif // HAVE_GETRANDOM // Fall back to random() seeded with the current time - not ideal, but for // our non-cryptographic purposes this is OK... static int first_time = 1; // First time we ran? if (first_time) { srandom(time(NULL)); first_time = 0; } return ((unsigned)random()); #endif // __APPLE__ } // // 'compare_active_jobs()' - Compare two active jobs. // static int // O - Result of comparison compare_active_jobs(lprint_job_t *a, // I - First job lprint_job_t *b) // I - Second job { return (b->id - a->id); } // // 'compare_completed_jobs()' - Compare two completed jobs. // static int // O - Result of comparison compare_completed_jobs(lprint_job_t *a, // I - First job lprint_job_t *b) // I - Second job { return (b->id - a->id); } // // 'compare_jobs()' - Compare two jobs. // static int // O - Result of comparison compare_jobs(lprint_job_t *a, // I - First job lprint_job_t *b) // I - Second job { return (b->id - a->id); } // // 'compare_printers()' - Compare two printers. // static int // O - Result of comparison compare_printers(lprint_printer_t *a, // I - First printer lprint_printer_t *b) // I - Second printer { return (strcmp(a->printer_name, b->printer_name)); } // // 'free_printer()' - Free the memory used by a printer. // static void free_printer(lprint_printer_t *printer) // I - Printer { // Remove DNS-SD registrations... lprintUnregisterDNSSD(printer); // Free memory... free(printer->printer_name); free(printer->dns_sd_name); free(printer->location); free(printer->geo_location); free(printer->organization); free(printer->org_unit); free(printer->resource); free(printer->device_uri); free(printer->driver_name); lprintDeleteDriver(printer->driver); ippDelete(printer->attrs); cupsArrayDelete(printer->active_jobs); cupsArrayDelete(printer->completed_jobs); cupsArrayDelete(printer->jobs); free(printer); } // // 'make_xri()' - Make a printer-xri collection value. // static ipp_t * // O - Collection value make_xri(const char *uri, // I - xri-uri const char *authentication, // I - xri-authentication const char *security) // I - xri-security { ipp_t *col = ippNew(); // Collection value ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "xri-authentication", NULL, authentication); ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "xri-security", NULL, security); ippAddString(col, IPP_TAG_PRINTER, IPP_TAG_URI, "xri-uri", NULL, uri); return (col); } lprint-1.0/server-system.c000066400000000000000000000574661362261677400157160ustar00rootroot00000000000000// // System object for LPrint, a Label Printer Application // // Copyright © 2019-2020 by Michael R Sweet. // Copyright © 2010-2019 by Apple Inc. // // Licensed under Apache License v2.0. See the file "LICENSE" for more // information. // // // Include necessary headers... // #include "lprint.h" #include #include // // Local globals... // static int shutdown_system = 0; // // Local functions... // static int create_listener(const char *name, int port, int family); static char *get_config_file(char *buffer, size_t bufsize); static void get_media_col(const char *value, lprint_media_col_t *media); static int load_config(lprint_system_t *system); static void put_media_col(cups_file_t *fp, const char *name, lprint_media_col_t *media); static int save_config(lprint_system_t *system); static void sigterm_handler(int sig); // // 'lprintCreateSystem()' - Create a system object. // lprint_system_t * // O - System object lprintCreateSystem( const char *hostname, // I - Hostname or `NULL` for none int port, // I - Port number or `0` for auto const char *subtypes, // I - DNS-SD sub-types or `NULL` for none const char *spooldir, // I - Spool directory or `NULL` for default const char *logfile, // I - Log file or `NULL` for default lprint_loglevel_t loglevel, // I - Log level const char *auth_service, // I - PAM authentication service or `NULL` for none const char *admin_group) // I - Administrative group or `NULL` for none { lprint_system_t *system; // System object char sockname[256], // Domain socket key[65]; // Session key const char *tmpdir; // Temporary directory // Allocate memory... if ((system = (lprint_system_t *)calloc(1, sizeof(lprint_system_t))) == NULL) return (NULL); // Initialize values... pthread_rwlock_init(&system->rwlock, NULL); if (hostname) { system->hostname = strdup(hostname); system->port = port ? port : 8000 + (getuid() % 1000); } system->start_time = time(NULL); system->directory = spooldir ? strdup(spooldir) : NULL; system->logfd = 2; system->logfile = logfile ? strdup(logfile) : NULL; system->loglevel = loglevel; system->next_client = 1; system->next_printer_id = 1; system->admin_gid = (gid_t)-1; if (subtypes) system->subtypes = strdup(subtypes); if (auth_service) system->auth_service = strdup(auth_service); if (admin_group) system->admin_group = strdup(admin_group); // Setup listeners... if ((system->listeners[0].fd = create_listener(lprintGetServerPath(sockname, sizeof(sockname)), 0, AF_LOCAL)) < 0) { lprintLog(system, LPRINT_LOGLEVEL_FATAL, "Unable to create domain socket listener for %s: %s", sockname, strerror(errno)); goto fatal; } else system->listeners[0].events = POLLIN; system->num_listeners = 1; if (system->hostname) { // Create listener sockets... const char *lishost; // Listen hostname if (strcmp(system->hostname, "localhost")) lishost = NULL; else lishost = "localhost"; if (system->port == 0) system->port = 9000 + (getuid() % 1000); if ((system->listeners[system->num_listeners].fd = create_listener(lishost, system->port, AF_INET)) < 0) lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to create IPv4 listener for %s:%d: %s", lishost ? lishost : "*", system->port, strerror(errno)); else system->listeners[system->num_listeners ++].events = POLLIN; if ((system->listeners[system->num_listeners].fd = create_listener(lishost, system->port, AF_INET6)) < 0) lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to create IPv6 listener for %s:%d: %s", lishost ? lishost : "*", system->port, strerror(errno)); else system->listeners[system->num_listeners ++].events = POLLIN; // Error out if we cannot listen to IPv4 or IPv6 addresses... if (system->num_listeners == 1) goto fatal; // Set the server credentials... cupsSetServerCredentials(NULL, system->hostname, 1); } // Initialize random data for a session key... snprintf(key, sizeof(key), "%08x%08x%08x%08x%08x%08x%08x%08x", lprintRand(), lprintRand(), lprintRand(), lprintRand(), lprintRand(), lprintRand(), lprintRand(), lprintRand()); system->session_key = strdup(key); // Initialize DNS-SD as needed... if (system->subtypes) lprintInitDNSSD(system); // Load printers... if (!load_config(system)) goto fatal; // See if the spool directory can be created... if ((tmpdir = getenv("TMPDIR")) == NULL) #ifdef __APPLE__ tmpdir = "/private/tmp"; #else tmpdir = "/tmp"; #endif // __APPLE__ if (!system->directory) { char newspooldir[256]; // Spool directory snprintf(newspooldir, sizeof(newspooldir), "%s/lprint%d.d", tmpdir, (int)getuid()); system->directory = strdup(newspooldir); } if (mkdir(system->directory, 0700) && errno != EEXIST) { perror(system->directory); goto fatal; } // Initialize logging... if (system->loglevel == LPRINT_LOGLEVEL_UNSPEC) system->loglevel = LPRINT_LOGLEVEL_ERROR; if (!system->logfile) { // Default log file is $TMPDIR/lprintUID.log... char newlogfile[256]; // Log filename snprintf(newlogfile, sizeof(newlogfile), "%s/lprint%d.log", tmpdir, (int)getuid()); system->logfile = strdup(newlogfile); } if (!strcmp(system->logfile, "syslog")) { // Log to syslog... system->logfd = -1; } else if (!strcmp(system->logfile, "-")) { // Log to stderr... system->logfd = 2; } else if ((system->logfd = open(system->logfile, O_CREAT | O_WRONLY | O_APPEND | O_NOFOLLOW | O_CLOEXEC, 0600)) < 0) { // Fallback to stderr if we can't open the log file... perror(system->logfile); system->logfd = 2; } lprintLog(system, LPRINT_LOGLEVEL_INFO, "System configuration loaded, %d printers.", cupsArrayCount(system->printers)); lprintLog(system, LPRINT_LOGLEVEL_INFO, "Listening for local connections at '%s'.", sockname); if (system->hostname) lprintLog(system, LPRINT_LOGLEVEL_INFO, "Listening for TCP connections at '%s' on port %d.", system->hostname, system->port); // Initialize authentication... if (system->auth_service && !strcmp(system->auth_service, "none")) { free(system->auth_service); system->auth_service = NULL; } if (system->admin_group && strcmp(system->admin_group, "none")) { char buffer[8192]; // Buffer for strings struct group grpbuf, // Group buffer *grp = NULL; // Admin group if (getgrnam_r(system->admin_group, &grpbuf, buffer, sizeof(buffer), &grp) || !grp) lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to find admin-group '%s'.", system->admin_group); else system->admin_gid = grp->gr_gid; } return (system); // If we get here, something went wrong... fatal: lprintDeleteSystem(system); return (NULL); } // // 'lprintDeleteSystem()' - Delete a system object. // void lprintDeleteSystem( lprint_system_t *system) // I - System object { int i; // Looping var char sockname[256]; // Domain socket filename if (!system) return; free(system->hostname); free(system->directory); free(system->logfile); free(system->subtypes); free(system->auth_service); free(system->admin_group); free(system->session_key); if (system->logfd >= 0 && system->logfd != 2) close(system->logfd); for (i = 0; i < system->num_listeners; i ++) close(system->listeners[i].fd); cupsArrayDelete(system->printers); pthread_rwlock_destroy(&system->rwlock); free(system); unlink(lprintGetServerPath(sockname, sizeof(sockname))); } // // 'lprintRunSystem()' - Run the printer service. // void lprintRunSystem(lprint_system_t *system)// I - System { int i, // Looping var count, // Number of listeners that fired timeout; // Timeout for poll() lprint_client_t *client; // New client // Catch important signals... lprintLog(system, LPRINT_LOGLEVEL_INFO, "Starting main loop."); signal(SIGTERM, sigterm_handler); signal(SIGINT, sigterm_handler); // Loop until we are shutdown or have a hard error... while (!shutdown_system) { if (system->save_time || system->shutdown_time) timeout = 5; else timeout = 10; if (system->clean_time && (i = (int)(time(NULL) - system->clean_time)) < timeout) timeout = i; if ((count = poll(system->listeners, (nfds_t)system->num_listeners, timeout * 1000)) < 0 && errno != EINTR && errno != EAGAIN) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to accept new connections: %s", strerror(errno)); break; } if (count > 0) { // Accept client connections as needed... for (i = 0; i < system->num_listeners; i ++) { if (system->listeners[i].revents & POLLIN) { if ((client = lprintCreateClient(system, system->listeners[i].fd)) != NULL) { if (pthread_create(&client->thread_id, NULL, (void *(*)(void *))lprintProcessClient, client)) { // Unable to create client thread... lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to create client thread: %s", strerror(errno)); lprintDeleteClient(client); } else { // Detach the main thread from the client thread to prevent hangs... pthread_detach(client->thread_id); } } } } } if (system->save_time) { // Save the configuration... pthread_rwlock_rdlock(&system->rwlock); save_config(system); pthread_rwlock_unlock(&system->rwlock); system->save_time = 0; } if (system->shutdown_time) { // Shutdown requested, see if we can do so safely... int count = 0; // Number of active jobs lprint_printer_t *printer; // Current printer // Force shutdown after 60 seconds if ((time(NULL) - system->shutdown_time) > 60) break; // Otherwise shutdown immediately if there are no more active jobs... pthread_rwlock_rdlock(&system->rwlock); for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { pthread_rwlock_rdlock(&printer->rwlock); count += cupsArrayCount(printer->active_jobs); pthread_rwlock_unlock(&printer->rwlock); } pthread_rwlock_unlock(&system->rwlock); if (count == 0) break; } // Clean out old jobs... if (system->clean_time && time(NULL) >= system->clean_time) lprintCleanJobs(system); } lprintLog(system, LPRINT_LOGLEVEL_INFO, "Shutting down main loop."); if (system->save_time) { // Save the configuration... pthread_rwlock_rdlock(&system->rwlock); save_config(system); pthread_rwlock_unlock(&system->rwlock); } } // // 'create_listener()' - Create a listener socket. // static int // O - Listener socket or -1 on error create_listener(const char *name, // I - Host name or `NULL` for any address int port, // I - Port number int family) // I - Address family { int sock; // Listener socket http_addrlist_t *addrlist; // Listen address char service[255]; // Service port snprintf(service, sizeof(service), "%d", port); if ((addrlist = httpAddrGetList(name, family, service)) == NULL) return (-1); sock = httpAddrListen(&(addrlist->addr), port); httpAddrFreeList(addrlist); return (sock); } // // 'get_config_file()' - Get the configuration filename. // // The configuration filename is, by convention, "~/.lprintrc". // static char * // O - Filename get_config_file(char *buffer, // I - Filename buffer size_t bufsize) // I - Size of buffer { const char *home = getenv("HOME"); // HOME environment variable if (home) snprintf(buffer, bufsize, "%s/.lprintrc", home); else #ifdef __APPLE__ snprintf(buffer, bufsize, "/private/tmp/lprintrc.%d", getuid()); #else snprintf(buffer, bufsize, "/tmp/lprintrc.%d", getuid()); #endif // __APPLE__ return (buffer); } // // 'get_media_col()' - Get a media col value. // static void get_media_col( const char *value, // I - Value string lprint_media_col_t *media) // I - Media collection { unsigned tracking = 0; // Tracking value sscanf(value, "%d,%d,%d,%d,%d,%63[^,],%63[^,],%d,%d,%u,%63s\n", &media->bottom_margin, &media->left_margin, &media->right_margin, &media->size_width, &media->size_length, media->size_name, media->source, &media->top_margin, &media->top_offset, &tracking, media->type); media->tracking = tracking; } // // 'load_config()' - Load the configuration file. // static int // O - 1 on success, 0 on failure load_config(lprint_system_t *system) // I - System { char configfile[256]; // Configuration filename cups_file_t *fp; // File pointer char line[1024], // Line from file *value; // Value from line int linenum = 0; // Line number in file // Try opening the config file... if ((fp = cupsFileOpen(get_config_file(configfile, sizeof(configfile)), "r")) == NULL) return (1); while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { if (!value) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Missing value for '%s' on line %d of '%s'.", line, linenum, configfile); } else if (!strcmp(line, "DefaultPrinterId")) { system->default_printer = atoi(value); } else if (!strcmp(line, "NextPrinterId")) { system->next_printer_id = atoi(value); } else if (!strcmp(line, "AdminGroup")) { if (!system->admin_group) system->admin_group = strdup(value); } else if (!strcmp(line, "AuthService")) { if (!system->auth_service) system->auth_service = strdup(value); } else if (!strcmp(line, "LogFile")) { if (!system->logfile) system->logfile = strdup(value); } else if (!strcmp(line, "LogLevel")) { if (system->loglevel != LPRINT_LOGLEVEL_UNSPEC) continue; if (!strcmp(value, "debug")) system->loglevel = LPRINT_LOGLEVEL_DEBUG; else if (!strcmp(value, "info")) system->loglevel = LPRINT_LOGLEVEL_INFO; else if (!strcmp(value, "warn")) system->loglevel = LPRINT_LOGLEVEL_WARN; else if (!strcmp(value, "error")) system->loglevel = LPRINT_LOGLEVEL_ERROR; else if (!strcmp(value, "fatal")) system->loglevel = LPRINT_LOGLEVEL_FATAL; else lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Bad LogLevel value '%s' on line %d of '%s'.", value, linenum, configfile); } else if (!strcmp(line, "Printer")) { lprint_printer_t *printer; // Printer char *printer_name, // Printer name *printer_id, // Printer ID number *device_uri, // Device URI *lprint_driver; // Driver name ipp_attribute_t *attr; // IPP attribute printer_name = value; if ((printer_id = strchr(printer_name, ' ')) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Bad Printer value '%s' on line %d of '%s'.", value, linenum, configfile); break; } if ((device_uri = strchr(printer_id + 1, ' ')) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Bad Printer value '%s' on line %d of '%s'.", value, linenum, configfile); break; } if ((lprint_driver = strchr(device_uri + 1, ' ')) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Bad Printer value '%s' on line %d of '%s'.", value, linenum, configfile); break; } *printer_id++ = '\0'; *device_uri++ = '\0'; *lprint_driver++ = '\0'; printer = lprintCreatePrinter(system, atoi(printer_id), printer_name, lprint_driver, device_uri, NULL, NULL, NULL, NULL); if (printer->printer_id >= system->next_printer_id) system->next_printer_id = printer->printer_id + 1; while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) { if (!strcmp(line, "EndPrinter")) { break; } else if (!value) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Missing value for '%s' on line %d of '%s'.", line, linenum, configfile); } else if (!strcmp(line, "ConfigTime")) { printer->config_time = (time_t)strtol(value, NULL, 10); } else if (!strcmp(line, "ImpCompleted")) { printer->impcompleted = atoi(value); } else if (!strcmp(line, "NextJobId")) { printer->next_job_id = atoi(value); } else { // Delete any existing attribute... if ((attr = ippFindAttribute(printer->attrs, line, IPP_TAG_ZERO)) != NULL) ippDeleteAttribute(printer->attrs, attr); if (!strcmp(line, "copies-default") || !strcmp(line, "print-darkness-default") || !strcmp(line, "print-speed-default")) { ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, line, atoi(value)); } else if (!strcmp(line, "document-format-default")) { ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_MIMETYPE, line, NULL, value); } else if (!strcmp(line, "print-quality-default") || !strcmp(line, "orientation-requested-default")) { ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, line, ippEnumValue(line, value)); } else if (!strcmp(line, "label-mode-configured")) { printer->driver->mode_configured = lprintLabelModeValue(value); } else if (!strcmp(line, "label-tear-offset-configured")) { printer->driver->tear_offset_configured = atoi(value); } else if (!strcmp(line, "media-col-default")) { get_media_col(value, &printer->driver->media_default); } else if (!strncmp(line, "media-col-ready-", 16)) { int src = atoi(line + 16); // Source index if (src >= 0 && src < printer->driver->num_source) get_media_col(value, printer->driver->media_ready + src); } else if (!strcmp(line, "print-color-mode-default") || !strcmp(line, "print-content-optimize-default")) { ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, line, NULL, value); } else if (!strcmp(line, "printer-darkness-configured")) { printer->driver->darkness_configured = atoi(value); } else if (!strcmp(line, "printer-geo-location")) { printer->geo_location = strdup(value); } else if (!strcmp(line, "printer-location")) { printer->location = strdup(value); } else if (!strcmp(line, "printer-organization")) { printer->organization = strdup(value); } else if (!strcmp(line, "printer-organizational-unit")) { printer->org_unit = strdup(value); } else if (!strcmp(line, "printer-resolution-default")) { int xres, yres; // Resolution values char units[32]; // Resolution units if (sscanf(value, "%dx%d%31s", &xres, &yres, units) != 3) { if (sscanf(value, "%d%31s", &xres, units) != 2) { xres = 300; strlcpy(units, "dpi", sizeof(units)); } yres = xres; } ippAddResolution(printer->attrs, IPP_TAG_PRINTER, "printer-resolution-default", !strcmp(units, "dpi") ? IPP_RES_PER_INCH : IPP_RES_PER_CM, xres, yres); } else { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unsupported attribute '%s' with value '%s' on line %d of '%s'.", line, value, linenum, configfile); } } } } else if (!strcmp(line, "SpoolDir")) { if (!system->directory) system->directory = strdup(value); } else { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unknown '%s %s' on line %d of '%s'.", line, value, linenum, configfile); } } cupsFileClose(fp); return (1); } // // 'put_media_col()' - Put a media col value. // static void put_media_col( cups_file_t *fp, // I - File to write to const char *name, // I - Name of attribute lprint_media_col_t *media) // I - Media collection { cupsFilePrintf(fp, "%s %d,%d,%d,%d,%d,%s,%s,%d,%d,%u,%s\n", name, media->bottom_margin, media->left_margin, media->right_margin, media->size_width, media->size_length, media->size_name, media->source, media->top_margin, media->top_offset, media->tracking, media->type); } // // 'save_config()' - Save the configuration file. // static int // O - 1 on success, 0 on failure save_config(lprint_system_t *system) // I - System { char configfile[256];// Configuration filename cups_file_t *fp; // File pointer lprint_printer_t *printer; // Current printer int i; // Looping var ipp_attribute_t *attr; // Printer attribute char value[1024]; // Attribute value static const char * const llevels[] = // Log level strings { "debug", "info", "warn", "error", "fatal" }; static const char * const pattrs[] = // List of printer attributes to save { "copies-default", "document-format-default-default", "orientation-requested-default", "print-color-mode-default", "print-content-optimize-default", "print-darkness-default", "print-quality-default", "print-speed-default", "printer-resolution-default" }; if ((fp = cupsFileOpen(get_config_file(configfile, sizeof(configfile)), "w")) == NULL) { lprintLog(system, LPRINT_LOGLEVEL_ERROR, "Unable to save configuration to '%s': %s", configfile, strerror(errno)); return (0); } lprintLog(system, LPRINT_LOGLEVEL_INFO, "Saving system configuration to '%s'.", configfile); cupsFilePrintf(fp, "DefaultPrinterId %d\n", system->default_printer); cupsFilePrintf(fp, "NextPrinterId %d\n", system->next_printer_id); if (system->admin_group) cupsFilePutConf(fp, "AdminGroup", system->admin_group); if (system->auth_service) cupsFilePutConf(fp, "AuthService", system->auth_service); if (system->logfile) cupsFilePutConf(fp, "LogFile", system->logfile); cupsFilePutConf(fp, "LogLevel", llevels[system->loglevel]); if (system->directory) cupsFilePutConf(fp, "SpoolDir", system->directory); for (printer = (lprint_printer_t *)cupsArrayFirst(system->printers); printer; printer = (lprint_printer_t *)cupsArrayNext(system->printers)) { cupsFilePrintf(fp, "Printer %s %d %s %s\n", printer->printer_name, printer->printer_id, printer->device_uri, printer->driver_name); cupsFilePrintf(fp, "ConfigTime %ld\n", (long)printer->config_time); cupsFilePrintf(fp, "ImpCompleted %d\n", printer->impcompleted); cupsFilePrintf(fp, "NextJobId %d\n", printer->next_job_id); if (printer->driver->mode_supported) cupsFilePutConf(fp, "label-mode-configured", lprintLabelModeString(printer->driver->mode_configured)); if (printer->driver->tear_offset_supported[0] != printer->driver->tear_offset_supported[1]) cupsFilePrintf(fp, "label-tear-offset-configured %d\n", printer->driver->tear_offset_configured); put_media_col(fp, "media-col-default", &printer->driver->media_default); for (i = 0; i < printer->driver->num_source; i ++) { if (printer->driver->media_ready[i].size_name[0]) { snprintf(value, sizeof(value), "media-col-ready-%d", i); put_media_col(fp, value, printer->driver->media_ready + i); } } if (printer->driver->darkness_supported) cupsFilePrintf(fp, "printer-darkness-configured %d\n", printer->driver->darkness_configured); if (printer->geo_location) cupsFilePutConf(fp, "printer-geo-location", printer->geo_location); if (printer->location) cupsFilePutConf(fp, "printer-location", printer->location); if (printer->organization) cupsFilePutConf(fp, "printer-organization", printer->organization); if (printer->org_unit) cupsFilePutConf(fp, "printer-organizational-unit", printer->org_unit); for (i = 0; i < (int)(sizeof(pattrs) / sizeof(pattrs[0])); i ++) { if ((attr = ippFindAttribute(printer->attrs, pattrs[i], IPP_TAG_ZERO)) != NULL) { ippAttributeString(attr, value, sizeof(value)); cupsFilePutConf(fp, pattrs[i], value); } } cupsFilePuts(fp, "EndPrinter\n"); } cupsFileClose(fp); return (1); } // // 'sigterm_handler()' - SIGTERM handler. // static void sigterm_handler(int sig) // I - Signal (ignored) { shutdown_system = 1; } lprint-1.0/snap/000077500000000000000000000000001362261677400136415ustar00rootroot00000000000000lprint-1.0/snap/snapcraft.yaml000066400000000000000000000026671362261677400165210ustar00rootroot00000000000000name: lprint base: core18 version: 1.0 summary: A Label Printer Application description: | LPrint implements printing for a variety of common label and receipt printers connected via network or USB. Features include: - A single executable handles spooling, status, and server functionality. - Multiple printer support. - Each printer implements an IPP Everywhere™ print service and is compatible with the driverless printing support in iOS, macOS, and Linux clients. - Each printer can support options such as label modes, tear-off offsets, media tracking, media top offset, print darkness, resolution, roll selection, and speed. - Each printer can print "raw", Apple/PWG Raster, and/or PNG files. For more information, see the file "DOCUMENTATION.md", the man pages in the "man" directory, and/or the LPrint project page at "https://www.msweet.org/lprint". grade: stable confinement: strict icon: static-resources/lprint.png apps: lprint: command: bin/lprint plugs: [avahi-observe, home, network, network-bind, raw-usb] parts: main: plugin: autotools configflags: [--enable-libpng,--enable-libusb,--with-dnssd=avahi] source: . build-packages: [libavahi-client-dev, libcups2-dev, libcupsimage2-dev, libgnutls28-dev, libpng-dev, libusb-1.0-0-dev, zlib1g-dev] stage-packages: [libavahi-client3, libcups2, libcupsimage2, libpng16-16, libusb-1.0-0] lprint-1.0/static-resources/000077500000000000000000000000001362261677400161775ustar00rootroot00000000000000lprint-1.0/static-resources/lprint-de-strings.h000066400000000000000000000070331362261677400217400ustar00rootroot00000000000000static const char *lprint_de_strings = "\"copies\" = \"Number of Copies\";\n" "\"job-state\" = \"Auftragsstatus\";\n" "\"job-state.3\" = \"Anstehend\";\n" "\"job-state.4\" = \"Gehalten\";\n" "\"job-state.5\" = \"Verarbeiten\";\n" "\"job-state.6\" = \"Gestoppt\";\n" "\"job-state.7\" = \"Abgebrochen\";\n" "\"job-state.8\" = \"Abgebrochen\";\n" "\"job-state.9\" = \"Abgeschlossen\";\n" "\"job-state-reasons\" = \"Detaillierter Auftragsstatus\";\n" "\"job-state-reasons.aborted-by-system\" = \"Vom System abgebrochen.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Auftrag durch den Benutzer abgebrochen.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Auftrag erfolgreich ausgeführt.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Unzureichende Auftragsdaten.\";\n" "\"job-state-reasons.job-incoming\" = \"Eingehender Auftrag.\";\n" "\"job-state-reasons.job-printing\" = \"Auftrag wird gedruckt.\";\n" "\"job-state-reasons.job-stopped\" = \"Druckauftrag gestoppt.\";\n" "\"job-state-reasons.none\" = \"Ohne.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Verarbeitung zum Stopppunkt.\";\n" "\"media\" = \"Medien\";\n" "\"media-col\" = \"Medien\";\n" "\"media-size\" = \"Medienmaße\";\n" "\"media-size-name\" = \"Medienname\";\n" "\"media-source\" = \"Medienquelle\";\n" "\"media-source.alternate-roll\" = \"Alternative Rolle\";\n" "\"media-source.main-roll\" = \"Hauptrolle\";\n" "\"media-top-offset\" = \"Oberer Versatz\";\n" "\"media-tracking\" = \"Etikettenverfolgung\";\n" "\"media-tracking.continuous\" = \"Kontinuierlich\";\n" "\"media-tracking.mark\" = \"Markierung\";\n" "\"media-tracking.web\" = \"Loch\";\n" "\"media-type\" = \"Medienart\";\n" "\"media-type.continuous\" = \"Kontinuierlich\";\n" "\"media-type.labels\" = \"Etiketten\";\n" "\"media-type.labels-continuous\" = \"Etiketten Kontinuierlich\";\n" "\"orientation-requested\" = \"Ausrichtung\";\n" "\"orientation-requested.3\" = \"Hochformat\";\n" "\"orientation-requested.4\" = \"Querformat\";\n" "\"orientation-requested.5\" = \"Querformat umgedreht\";\n" "\"orientation-requested.6\" = \"Hochformat umgedreht\";\n" "\"orientation-requested.7\" = \"Automatisch\";\n" "\"print-color-mode\" = \"Druck-Farbmodus\";\n" "\"print-color-mode.bi-level\" = \"Text\";\n" "\"print-color-mode.monochrome\" = \"Einfarbig\";\n" "\"print-content-optimize\" = \"Druckoptimierung\";\n" "\"print-content-optimize.auto\" = \"Automatisch\";\n" "\"print-content-optimize.graphic\" = \"Grafiken\";\n" "\"print-content-optimize.photo\" = \"Foto\";\n" "\"print-content-optimize.text\" = \"Text\";\n" "\"print-content-optimize.text-and-graphic\" = \"Text und Grafiken\";\n" "\"print-darkness\" = \"Dunkelheit drucken\";\n" "\"print-quality\" = \"Druckqualität\";\n" "\"print-quality.3\" = \"Entwurf\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Hoch\";\n" "\"print-speed\" = \"Druckgeschwindigkeit\";\n" "\"printer-resolution\" = \"Druckauflösung\";\n" "\"printer-state\" = \"Druckerstatus\";\n" "\"printer-state.3\" = \"Inaktiv\";\n" "\"printer-state.4\" = \"Verarbeiten\";\n" "\"printer-state.5\" = \"Gestoppt\";\n" "\"printer-state-reaosns\" = \"Detaillierter Druckerstatus\";\n" "\"printer-state-reasons.cover-open\" = \"Abdeckung offen.\";\n" "\"printer-state-reasons.media-empty\" = \"Medien leer.\";\n" "\"printer-state-reasons.media-jam\" = \"Medienstau.\";\n" "\"printer-state-reasons.media-low\" = \"Medien niedrig.\";\n" "\"printer-state-reasons.media-needed\" = \"Medien benötigt.\";\n" "\"printer-state-reasons.none\" = \"Ohne.\";\n" "\"printer-state-reasons.other\" = \"Andere.\";\n" ; lprint-1.0/static-resources/lprint-de.strings000066400000000000000000000057121362261677400215150ustar00rootroot00000000000000"copies" = "Number of Copies"; "job-state" = "Auftragsstatus"; "job-state.3" = "Anstehend"; "job-state.4" = "Gehalten"; "job-state.5" = "Verarbeiten"; "job-state.6" = "Gestoppt"; "job-state.7" = "Abgebrochen"; "job-state.8" = "Abgebrochen"; "job-state.9" = "Abgeschlossen"; "job-state-reasons" = "Detaillierter Auftragsstatus"; "job-state-reasons.aborted-by-system" = "Vom System abgebrochen."; "job-state-reasons.job-canceled-by-user" = "Auftrag durch den Benutzer abgebrochen."; "job-state-reasons.job-completed-successfully" = "Auftrag erfolgreich ausgeführt."; "job-state-reasons.job-data-insufficient" = "Unzureichende Auftragsdaten."; "job-state-reasons.job-incoming" = "Eingehender Auftrag."; "job-state-reasons.job-printing" = "Auftrag wird gedruckt."; "job-state-reasons.job-stopped" = "Druckauftrag gestoppt."; "job-state-reasons.none" = "Ohne."; "job-state-reasons.processing-to-stop-point" = "Verarbeitung zum Stopppunkt."; "media" = "Medien"; "media-col" = "Medien"; "media-size" = "Medienmaße"; "media-size-name" = "Medienname"; "media-source" = "Medienquelle"; "media-source.alternate-roll" = "Alternative Rolle"; "media-source.main-roll" = "Hauptrolle"; "media-top-offset" = "Oberer Versatz"; "media-tracking" = "Etikettenverfolgung"; "media-tracking.continuous" = "Kontinuierlich"; "media-tracking.mark" = "Markierung"; "media-tracking.web" = "Loch"; "media-type" = "Medienart"; "media-type.continuous" = "Kontinuierlich"; "media-type.labels" = "Etiketten"; "media-type.labels-continuous" = "Etiketten Kontinuierlich"; "orientation-requested" = "Ausrichtung"; "orientation-requested.3" = "Hochformat"; "orientation-requested.4" = "Querformat"; "orientation-requested.5" = "Querformat umgedreht"; "orientation-requested.6" = "Hochformat umgedreht"; "orientation-requested.7" = "Automatisch"; "print-color-mode" = "Druck-Farbmodus"; "print-color-mode.bi-level" = "Text"; "print-color-mode.monochrome" = "Einfarbig"; "print-content-optimize" = "Druckoptimierung"; "print-content-optimize.auto" = "Automatisch"; "print-content-optimize.graphic" = "Grafiken"; "print-content-optimize.photo" = "Foto"; "print-content-optimize.text" = "Text"; "print-content-optimize.text-and-graphic" = "Text und Grafiken"; "print-darkness" = "Dunkelheit drucken"; "print-quality" = "Druckqualität"; "print-quality.3" = "Entwurf"; "print-quality.4" = "Normal"; "print-quality.5" = "Hoch"; "print-speed" = "Druckgeschwindigkeit"; "printer-resolution" = "Druckauflösung"; "printer-state" = "Druckerstatus"; "printer-state.3" = "Inaktiv"; "printer-state.4" = "Verarbeiten"; "printer-state.5" = "Gestoppt"; "printer-state-reaosns" = "Detaillierter Druckerstatus"; "printer-state-reasons.cover-open" = "Abdeckung offen."; "printer-state-reasons.media-empty" = "Medien leer."; "printer-state-reasons.media-jam" = "Medienstau."; "printer-state-reasons.media-low" = "Medien niedrig."; "printer-state-reasons.media-needed" = "Medien benötigt."; "printer-state-reasons.none" = "Ohne."; "printer-state-reasons.other" = "Andere."; lprint-1.0/static-resources/lprint-en-strings.h000066400000000000000000000065131362261677400217540ustar00rootroot00000000000000static const char *lprint_en_strings = "\"copies\" = \"Number of Copies\";\n" "\"job-state\" = \"Job State\";\n" "\"job-state.3\" = \"Pending\";\n" "\"job-state.4\" = \"Held\";\n" "\"job-state.5\" = \"Processing\";\n" "\"job-state.6\" = \"Stopped\";\n" "\"job-state.7\" = \"Canceled\";\n" "\"job-state.8\" = \"Aborted\";\n" "\"job-state.9\" = \"Completed\";\n" "\"job-state-reasons\" = \"Job Status\";\n" "\"job-state-reasons.aborted-by-system\" = \"Aborted.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Canceled.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Printed.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Waiting for document.\";\n" "\"job-state-reasons.job-incoming\" = \"Receiving document.\";\n" "\"job-state-reasons.job-printing\" = \"Printing.\";\n" "\"job-state-reasons.job-stopped\" = \"Stopped.\";\n" "\"job-state-reasons.none\" = \"Pending.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Stopping.\";\n" "\"media\" = \"Media Size\";\n" "\"media-col\" = \"Media\";\n" "\"media-size\" = \"Media Size\";\n" "\"media-size-name\" = \"Media Size\";\n" "\"media-source\" = \"Roll\";\n" "\"media-source.alternate-roll\" = \"Alternate Roll\";\n" "\"media-source.main-roll\" = \"Main Roll\";\n" "\"media-top-offset\" = \"Top Offset\";\n" "\"media-tracking\" = \"Label Tracking\";\n" "\"media-tracking.continuous\" = \"Continuous\";\n" "\"media-tracking.mark\" = \"Mark\";\n" "\"media-tracking.web\" = \"Web/Hole\";\n" "\"media-type\" = \"Media Type\";\n" "\"media-type.continuous\" = \"Continuous Paper\";\n" "\"media-type.labels\" = \"Cut Labels\";\n" "\"media-type.labels-continuous\" = \"Continuous Labels\";\n" "\"orientation-requested\" = \"Orientation\";\n" "\"orientation-requested.3\" = \"Portrait\";\n" "\"orientation-requested.4\" = \"Landscape\";\n" "\"orientation-requested.5\" = \"Reverse Landscape\";\n" "\"orientation-requested.6\" = \"Reverse Portrait\";\n" "\"orientation-requested.7\" = \"Automatic\";\n" "\"print-color-mode\" = \"Color Mode\";\n" "\"print-color-mode.bi-level\" = \"Black and White\";\n" "\"print-color-mode.monochrome\" = \"Grayscale\";\n" "\"print-content-optimize\" = \"Optimize\";\n" "\"print-content-optimize.auto\" = \"Automatically\";\n" "\"print-content-optimize.graphic\" = \"for Graphics\";\n" "\"print-content-optimize.photo\" = \"for Photographs\";\n" "\"print-content-optimize.text\" = \"for Text Only\";\n" "\"print-content-optimize.text-and-graphic\" = \"for Text and Graphics\";\n" "\"print-darkness\" = \"Print Darkness\";\n" "\"print-quality\" = \"Print Quality\";\n" "\"print-quality.3\" = \"Draft\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Best\";\n" "\"print-speed\" = \"Print Speed\";\n" "\"printer-resolution\" = \"Print Resolution\";\n" "\"printer-state\" = \"Printer State\";\n" "\"printer-state.3\" = \"Idle\";\n" "\"printer-state.4\" = \"Processing\";\n" "\"printer-state.5\" = \"Stopped\";\n" "\"printer-state-reaosns\" = \"Printer Status\";\n" "\"printer-state-reasons.cover-open\" = \"Cover open.\";\n" "\"printer-state-reasons.media-empty\" = \"Out of paper.\";\n" "\"printer-state-reasons.media-jam\" = \"Paper jam.\";\n" "\"printer-state-reasons.media-low\" = \"Replace paper soon.\";\n" "\"printer-state-reasons.media-needed\" = \"Load paper.\";\n" "\"printer-state-reasons.none\" = \"Ready.\";\n" "\"printer-state-reasons.other\" = \"See printer.\";\n" ; lprint-1.0/static-resources/lprint-en.strings000066400000000000000000000053721362261677400215310ustar00rootroot00000000000000"copies" = "Number of Copies"; "job-state" = "Job State"; "job-state.3" = "Pending"; "job-state.4" = "Held"; "job-state.5" = "Processing"; "job-state.6" = "Stopped"; "job-state.7" = "Canceled"; "job-state.8" = "Aborted"; "job-state.9" = "Completed"; "job-state-reasons" = "Job Status"; "job-state-reasons.aborted-by-system" = "Aborted."; "job-state-reasons.job-canceled-by-user" = "Canceled."; "job-state-reasons.job-completed-successfully" = "Printed."; "job-state-reasons.job-data-insufficient" = "Waiting for document."; "job-state-reasons.job-incoming" = "Receiving document."; "job-state-reasons.job-printing" = "Printing."; "job-state-reasons.job-stopped" = "Stopped."; "job-state-reasons.none" = "Pending."; "job-state-reasons.processing-to-stop-point" = "Stopping."; "media" = "Media Size"; "media-col" = "Media"; "media-size" = "Media Size"; "media-size-name" = "Media Size"; "media-source" = "Roll"; "media-source.alternate-roll" = "Alternate Roll"; "media-source.main-roll" = "Main Roll"; "media-top-offset" = "Top Offset"; "media-tracking" = "Label Tracking"; "media-tracking.continuous" = "Continuous"; "media-tracking.mark" = "Mark"; "media-tracking.web" = "Web/Hole"; "media-type" = "Media Type"; "media-type.continuous" = "Continuous Paper"; "media-type.labels" = "Cut Labels"; "media-type.labels-continuous" = "Continuous Labels"; "orientation-requested" = "Orientation"; "orientation-requested.3" = "Portrait"; "orientation-requested.4" = "Landscape"; "orientation-requested.5" = "Reverse Landscape"; "orientation-requested.6" = "Reverse Portrait"; "orientation-requested.7" = "Automatic"; "print-color-mode" = "Color Mode"; "print-color-mode.bi-level" = "Black and White"; "print-color-mode.monochrome" = "Grayscale"; "print-content-optimize" = "Optimize"; "print-content-optimize.auto" = "Automatically"; "print-content-optimize.graphic" = "for Graphics"; "print-content-optimize.photo" = "for Photographs"; "print-content-optimize.text" = "for Text Only"; "print-content-optimize.text-and-graphic" = "for Text and Graphics"; "print-darkness" = "Print Darkness"; "print-quality" = "Print Quality"; "print-quality.3" = "Draft"; "print-quality.4" = "Normal"; "print-quality.5" = "Best"; "print-speed" = "Print Speed"; "printer-resolution" = "Print Resolution"; "printer-state" = "Printer State"; "printer-state.3" = "Idle"; "printer-state.4" = "Processing"; "printer-state.5" = "Stopped"; "printer-state-reaosns" = "Printer Status"; "printer-state-reasons.cover-open" = "Cover open."; "printer-state-reasons.media-empty" = "Out of paper."; "printer-state-reasons.media-jam" = "Paper jam."; "printer-state-reasons.media-low" = "Replace paper soon."; "printer-state-reasons.media-needed" = "Load paper."; "printer-state-reasons.none" = "Ready."; "printer-state-reasons.other" = "See printer."; lprint-1.0/static-resources/lprint-es-strings.h000066400000000000000000000071601362261677400217600ustar00rootroot00000000000000static const char *lprint_es_strings = "\"copies\" = \"Copias\";\n" "\"job-state\" = \"Estado de la impresión\";\n" "\"job-state.3\" = \"Pendiente\";\n" "\"job-state.4\" = \"Retenida\";\n" "\"job-state.5\" = \"Procesando\";\n" "\"job-state.6\" = \"Detenida\";\n" "\"job-state.7\" = \"Cancelado\";\n" "\"job-state.8\" = \"Interrumpido\";\n" "\"job-state.9\" = \"Completada\";\n" "\"job-state-reasons\" = \"Estado de la impresión detallado\";\n" "\"job-state-reasons.aborted-by-system\" = \"Interrumpido por el sistema.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Impresión cancelada por el usuario.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Impresión completada correctamente.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Datos de impresión insuficientes.\";\n" "\"job-state-reasons.job-incoming\" = \"Impresión entrante.\";\n" "\"job-state-reasons.job-printing\" = \"Imprimiendo tarea.\";\n" "\"job-state-reasons.job-stopped\" = \"Detenida.\";\n" "\"job-state-reasons.none\" = \"Ninguna.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Procesando hasta el punto de detención.\";\n" "\"media\" = \"Papel\";\n" "\"media-col\" = \"Papel\";\n" "\"media-size\" = \"Dimensiones del papel\";\n" "\"media-size-name\" = \"Nombre del soporte\";\n" "\"media-source\" = \"Fuente de papel\";\n" "\"media-source.alternate-roll\" = \"Rollo alternativo\";\n" "\"media-source.main-roll\" = \"Rollo principal\";\n" "\"media-top-offset\" = \"Desplazamiento superior\";\n" "\"media-tracking\" = \"Seguimiento de etiquetas\";\n" "\"media-tracking.continuous\" = \"Continuo\";\n" "\"media-tracking.mark\" = \"Mancha\";\n" "\"media-tracking.web\" = \"Agujero\";\n" "\"media-type\" = \"Tipo de papel\";\n" "\"media-type.continuous\" = \"Continuo\";\n" "\"media-type.labels\" = \"Etiquetas\";\n" "\"media-type.labels-continuous\" = \"Etiquetas continuas\";\n" "\"orientation-requested\" = \"Orientación\";\n" "\"orientation-requested.3\" = \"Vertical\";\n" "\"orientation-requested.4\" = \"Horizontal\";\n" "\"orientation-requested.5\" = \"Horizontal inversa\";\n" "\"orientation-requested.6\" = \"Vertical inversa\";\n" "\"orientation-requested.7\" = \"Automática\";\n" "\"print-color-mode\" = \"Modo de color de la impresión\";\n" "\"print-color-mode.bi-level\" = \"Texto\";\n" "\"print-color-mode.monochrome\" = \"Monocromo\";\n" "\"print-content-optimize\" = \"Optimización de la impresión\";\n" "\"print-content-optimize.auto\" = \"Automática\";\n" "\"print-content-optimize.graphic\" = \"Gráficos\";\n" "\"print-content-optimize.photo\" = \"Foto\";\n" "\"print-content-optimize.text\" = \"Texto\";\n" "\"print-content-optimize.text-and-graphic\" = \"Texto y gráficos\";\n" "\"print-darkness\" = \"Imprimir oscuridad\";\n" "\"print-quality\" = \"Calidad de impresión\";\n" "\"print-quality.3\" = \"Borrador\";\n" "\"print-quality.4\" = \"Normal\";\n" "\"print-quality.5\" = \"Alta\";\n" "\"print-speed\" = \"Print Speed\";\n" "\"printer-resolution\" = \"Resolución de la impresión\";\n" "\"printer-state\" = \"Estado de la impresora\";\n" "\"printer-state.3\" = \"Inactiva\";\n" "\"printer-state.4\" = \"Procesando\";\n" "\"printer-state.5\" = \"Detenida\";\n" "\"printer-state-reaosns\" = \"Estado de la impresora detallado\";\n" "\"printer-state-reasons.cover-open\" = \"Tapa abierta.\";\n" "\"printer-state-reasons.media-empty\" = \"Papel vacío.\";\n" "\"printer-state-reasons.media-jam\" = \"Atasco de papel.\";\n" "\"printer-state-reasons.media-low\" = \"Poco papel.\";\n" "\"printer-state-reasons.media-needed\" = \"Se necesita papel.\";\n" "\"printer-state-reasons.none\" = \"Ninguna.\";\n" "\"printer-state-reasons.other\" = \"Otra.\";\n" ; lprint-1.0/static-resources/lprint-es.strings000066400000000000000000000060371362261677400215350ustar00rootroot00000000000000"copies" = "Copias"; "job-state" = "Estado de la impresión"; "job-state.3" = "Pendiente"; "job-state.4" = "Retenida"; "job-state.5" = "Procesando"; "job-state.6" = "Detenida"; "job-state.7" = "Cancelado"; "job-state.8" = "Interrumpido"; "job-state.9" = "Completada"; "job-state-reasons" = "Estado de la impresión detallado"; "job-state-reasons.aborted-by-system" = "Interrumpido por el sistema."; "job-state-reasons.job-canceled-by-user" = "Impresión cancelada por el usuario."; "job-state-reasons.job-completed-successfully" = "Impresión completada correctamente."; "job-state-reasons.job-data-insufficient" = "Datos de impresión insuficientes."; "job-state-reasons.job-incoming" = "Impresión entrante."; "job-state-reasons.job-printing" = "Imprimiendo tarea."; "job-state-reasons.job-stopped" = "Detenida."; "job-state-reasons.none" = "Ninguna."; "job-state-reasons.processing-to-stop-point" = "Procesando hasta el punto de detención."; "media" = "Papel"; "media-col" = "Papel"; "media-size" = "Dimensiones del papel"; "media-size-name" = "Nombre del soporte"; "media-source" = "Fuente de papel"; "media-source.alternate-roll" = "Rollo alternativo"; "media-source.main-roll" = "Rollo principal"; "media-top-offset" = "Desplazamiento superior"; "media-tracking" = "Seguimiento de etiquetas"; "media-tracking.continuous" = "Continuo"; "media-tracking.mark" = "Mancha"; "media-tracking.web" = "Agujero"; "media-type" = "Tipo de papel"; "media-type.continuous" = "Continuo"; "media-type.labels" = "Etiquetas"; "media-type.labels-continuous" = "Etiquetas continuas"; "orientation-requested" = "Orientación"; "orientation-requested.3" = "Vertical"; "orientation-requested.4" = "Horizontal"; "orientation-requested.5" = "Horizontal inversa"; "orientation-requested.6" = "Vertical inversa"; "orientation-requested.7" = "Automática"; "print-color-mode" = "Modo de color de la impresión"; "print-color-mode.bi-level" = "Texto"; "print-color-mode.monochrome" = "Monocromo"; "print-content-optimize" = "Optimización de la impresión"; "print-content-optimize.auto" = "Automática"; "print-content-optimize.graphic" = "Gráficos"; "print-content-optimize.photo" = "Foto"; "print-content-optimize.text" = "Texto"; "print-content-optimize.text-and-graphic" = "Texto y gráficos"; "print-darkness" = "Imprimir oscuridad"; "print-quality" = "Calidad de impresión"; "print-quality.3" = "Borrador"; "print-quality.4" = "Normal"; "print-quality.5" = "Alta"; "print-speed" = "Print Speed"; "printer-resolution" = "Resolución de la impresión"; "printer-state" = "Estado de la impresora"; "printer-state.3" = "Inactiva"; "printer-state.4" = "Procesando"; "printer-state.5" = "Detenida"; "printer-state-reaosns" = "Estado de la impresora detallado"; "printer-state-reasons.cover-open" = "Tapa abierta."; "printer-state-reasons.media-empty" = "Papel vacío."; "printer-state-reasons.media-jam" = "Atasco de papel."; "printer-state-reasons.media-low" = "Poco papel."; "printer-state-reasons.media-needed" = "Se necesita papel."; "printer-state-reasons.none" = "Ninguna."; "printer-state-reasons.other" = "Otra."; lprint-1.0/static-resources/lprint-fr-strings.h000066400000000000000000000072261362261677400217630ustar00rootroot00000000000000static const char *lprint_fr_strings = "\"copies\" = \"Copies\";\n" "\"job-state\" = \"État de la tâche\";\n" "\"job-state.3\" = \"En attente\";\n" "\"job-state.4\" = \"Retenue\";\n" "\"job-state.5\" = \"Traitement en cours\";\n" "\"job-state.6\" = \"Arrêtée\";\n" "\"job-state.7\" = \"Annulée\";\n" "\"job-state.8\" = \"Interrompue\";\n" "\"job-state.9\" = \"Terminée\";\n" "\"job-state-reasons\" = \"État détaillé de la tâche\";\n" "\"job-state-reasons.aborted-by-system\" = \"Interrompue par le système.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Tâche annulée par l’utilisateur.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Tâche terminée.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Données sur la tâche insuffisantes.\";\n" "\"job-state-reasons.job-incoming\" = \"Réception de la tâche.\";\n" "\"job-state-reasons.job-printing\" = \"Impression de la tâche.\";\n" "\"job-state-reasons.job-stopped\" = \"Arrêtée.\";\n" "\"job-state-reasons.none\" = \"Aucun.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Traitement jusqu’au point d’arrêt.\";\n" "\"media\" = \"Support\";\n" "\"media-col\" = \"Support\";\n" "\"media-size\" = \"Dimensions du support\";\n" "\"media-size-name\" = \"Nom du support\";\n" "\"media-source\" = \"Source du papier\";\n" "\"media-source.alternate-roll\" = \"Bobine secondaire\";\n" "\"media-source.main-roll\" = \"Bobine principale\";\n" "\"media-top-offset\" = \"Décalage supérieur\";\n" "\"media-tracking\" = \"Suivi des étiquettes\";\n" "\"media-tracking.continuous\" = \"Continu\";\n" "\"media-tracking.mark\" = \"Tache\";\n" "\"media-tracking.web\" = \"Bouge\";\n" "\"media-type\" = \"Type de papier\";\n" "\"media-type.continuous\" = \"Continu\";\n" "\"media-type.labels\" = \"Étiquettes\";\n" "\"media-type.labels-continuous\" = \"Étiquettes continues\";\n" "\"orientation-requested\" = \"Orientation\";\n" "\"orientation-requested.3\" = \"Portrait\";\n" "\"orientation-requested.4\" = \"Paysage\";\n" "\"orientation-requested.5\" = \"Paysage inversé\";\n" "\"orientation-requested.6\" = \"Portrait inversé\";\n" "\"orientation-requested.7\" = \"Automatique\";\n" "\"print-color-mode\" = \"Mode colorimétrique de l’impression\";\n" "\"print-color-mode.bi-level\" = \"Texte\";\n" "\"print-color-mode.monochrome\" = \"Monochrome\";\n" "\"print-content-optimize\" = \"Optimisation de l’impression\";\n" "\"print-content-optimize.auto\" = \"Automatique\";\n" "\"print-content-optimize.graphic\" = \"Graphismes\";\n" "\"print-content-optimize.photo\" = \"Photo\";\n" "\"print-content-optimize.text\" = \"Texte\";\n" "\"print-content-optimize.text-and-graphic\" = \"Texte et graphismes\";\n" "\"print-darkness\" = \"Imprimer l'obscurité\";\n" "\"print-quality\" = \"Qualité d’impression\";\n" "\"print-quality.3\" = \"Brouillon\";\n" "\"print-quality.4\" = \"Normale\";\n" "\"print-quality.5\" = \"Élevée\";\n" "\"print-speed\" = \"Vitesse d'impression\";\n" "\"printer-resolution\" = \"Résolution de l’impression\";\n" "\"printer-state\" = \"État de l’imprimante\";\n" "\"printer-state.3\" = \"Idle\";\n" "\"printer-state.4\" = \"Processing\";\n" "\"printer-state.5\" = \"Stopped\";\n" "\"printer-state-reaosns\" = \"État détaillé de l’imprimante\";\n" "\"printer-state-reasons.cover-open\" = \"Couverture ouverte.\";\n" "\"printer-state-reasons.media-empty\" = \"Support épuisé.\";\n" "\"printer-state-reasons.media-jam\" = \"Bourrage du support.\";\n" "\"printer-state-reasons.media-low\" = \"Support presque épuisé.\";\n" "\"printer-state-reasons.media-needed\" = \"Support requis.\";\n" "\"printer-state-reasons.none\" = \"Aucun.\";\n" "\"printer-state-reasons.other\" = \"Autre.\";\n" ; lprint-1.0/static-resources/lprint-fr.strings000066400000000000000000000061051362261677400215310ustar00rootroot00000000000000"copies" = "Copies"; "job-state" = "État de la tâche"; "job-state.3" = "En attente"; "job-state.4" = "Retenue"; "job-state.5" = "Traitement en cours"; "job-state.6" = "Arrêtée"; "job-state.7" = "Annulée"; "job-state.8" = "Interrompue"; "job-state.9" = "Terminée"; "job-state-reasons" = "État détaillé de la tâche"; "job-state-reasons.aborted-by-system" = "Interrompue par le système."; "job-state-reasons.job-canceled-by-user" = "Tâche annulée par l’utilisateur."; "job-state-reasons.job-completed-successfully" = "Tâche terminée."; "job-state-reasons.job-data-insufficient" = "Données sur la tâche insuffisantes."; "job-state-reasons.job-incoming" = "Réception de la tâche."; "job-state-reasons.job-printing" = "Impression de la tâche."; "job-state-reasons.job-stopped" = "Arrêtée."; "job-state-reasons.none" = "Aucun."; "job-state-reasons.processing-to-stop-point" = "Traitement jusqu’au point d’arrêt."; "media" = "Support"; "media-col" = "Support"; "media-size" = "Dimensions du support"; "media-size-name" = "Nom du support"; "media-source" = "Source du papier"; "media-source.alternate-roll" = "Bobine secondaire"; "media-source.main-roll" = "Bobine principale"; "media-top-offset" = "Décalage supérieur"; "media-tracking" = "Suivi des étiquettes"; "media-tracking.continuous" = "Continu"; "media-tracking.mark" = "Tache"; "media-tracking.web" = "Bouge"; "media-type" = "Type de papier"; "media-type.continuous" = "Continu"; "media-type.labels" = "Étiquettes"; "media-type.labels-continuous" = "Étiquettes continues"; "orientation-requested" = "Orientation"; "orientation-requested.3" = "Portrait"; "orientation-requested.4" = "Paysage"; "orientation-requested.5" = "Paysage inversé"; "orientation-requested.6" = "Portrait inversé"; "orientation-requested.7" = "Automatique"; "print-color-mode" = "Mode colorimétrique de l’impression"; "print-color-mode.bi-level" = "Texte"; "print-color-mode.monochrome" = "Monochrome"; "print-content-optimize" = "Optimisation de l’impression"; "print-content-optimize.auto" = "Automatique"; "print-content-optimize.graphic" = "Graphismes"; "print-content-optimize.photo" = "Photo"; "print-content-optimize.text" = "Texte"; "print-content-optimize.text-and-graphic" = "Texte et graphismes"; "print-darkness" = "Imprimer l'obscurité"; "print-quality" = "Qualité d’impression"; "print-quality.3" = "Brouillon"; "print-quality.4" = "Normale"; "print-quality.5" = "Élevée"; "print-speed" = "Vitesse d'impression"; "printer-resolution" = "Résolution de l’impression"; "printer-state" = "État de l’imprimante"; "printer-state.3" = "Idle"; "printer-state.4" = "Processing"; "printer-state.5" = "Stopped"; "printer-state-reaosns" = "État détaillé de l’imprimante"; "printer-state-reasons.cover-open" = "Couverture ouverte."; "printer-state-reasons.media-empty" = "Support épuisé."; "printer-state-reasons.media-jam" = "Bourrage du support."; "printer-state-reasons.media-low" = "Support presque épuisé."; "printer-state-reasons.media-needed" = "Support requis."; "printer-state-reasons.none" = "Aucun."; "printer-state-reasons.other" = "Autre."; lprint-1.0/static-resources/lprint-it-strings.h000066400000000000000000000071421362261677400217650ustar00rootroot00000000000000static const char *lprint_it_strings = "\"copies\" = \"Copie\";\n" "\"job-state\" = \"Stato stampa\";\n" "\"job-state.3\" = \"In sospeso\";\n" "\"job-state.4\" = \"Bloccato\";\n" "\"job-state.5\" = \"Elaborazione in corso\";\n" "\"job-state.6\" = \"Interrotta\";\n" "\"job-state.7\" = \"Annullato\";\n" "\"job-state.8\" = \"Interrotto\";\n" "\"job-state.9\" = \"Completato\";\n" "\"job-state-reasons\" = \"Stato dettagliato stampa\";\n" "\"job-state-reasons.aborted-by-system\" = \"Interrotto dal sistema.\";\n" "\"job-state-reasons.job-canceled-by-user\" = \"Stampa annullata da utente.\";\n" "\"job-state-reasons.job-completed-successfully\" = \"Stampa completata.\";\n" "\"job-state-reasons.job-data-insufficient\" = \"Dati stampa insufficienti.\";\n" "\"job-state-reasons.job-incoming\" = \"Stampa in entrata.\";\n" "\"job-state-reasons.job-printing\" = \"Stampa.\";\n" "\"job-state-reasons.job-stopped\" = \"Interrotta.\";\n" "\"job-state-reasons.none\" = \"Nessuno.\";\n" "\"job-state-reasons.processing-to-stop-point\" = \"Punto di interruzione elaborazione.\";\n" "\"media\" = \"File multimediale\";\n" "\"media-col\" = \"File multimediale\";\n" "\"media-size\" = \"Dimensioni file multimediale\";\n" "\"media-size-name\" = \"Nome supporto\";\n" "\"media-source\" = \"Sorgente media\";\n" "\"media-source.alternate-roll\" = \"Secondo rotolo\";\n" "\"media-source.main-roll\" = \"Rotolo principale\";\n" "\"media-top-offset\" = \"Offset superiore\";\n" "\"media-tracking\" = \"Monitoraggio label\";\n" "\"media-tracking.continuous\" = \"Continuo\";\n" "\"media-tracking.mark\" = \"Segno\";\n" "\"media-tracking.web\" = \"Buco\";\n" "\"media-type\" = \"Tipo media\";\n" "\"media-type.continuous\" = \"Continuo\";\n" "\"media-type.labels\" = \"Etichette\";\n" "\"media-type.labels-continuous\" = \"Etichette continuo\";\n" "\"orientation-requested\" = \"Orientamento\";\n" "\"orientation-requested.3\" = \"Verticale\";\n" "\"orientation-requested.4\" = \"Orizzontale\";\n" "\"orientation-requested.5\" = \"Inverti orientamento orizzontale\";\n" "\"orientation-requested.6\" = \"Inverti orientamento verticale\";\n" "\"orientation-requested.7\" = \"Automatico\";\n" "\"print-color-mode\" = \"Modalità colore di stampa\";\n" "\"print-color-mode.bi-level\" = \"Testo\";\n" "\"print-color-mode.monochrome\" = \"Monocromo\";\n" "\"print-content-optimize\" = \"Ottimizzazione stampa\";\n" "\"print-content-optimize.auto\" = \"Automatica\";\n" "\"print-content-optimize.graphic\" = \"Grafici\";\n" "\"print-content-optimize.photo\" = \"Foto\";\n" "\"print-content-optimize.text\" = \"Testo\";\n" "\"print-content-optimize.text-and-graphic\" = \"Testo e grafica\";\n" "\"print-darkness\" = \"Stampa l'oscurità\";\n" "\"print-quality\" = \"Qualità stampa\";\n" "\"print-quality.3\" = \"Bozza\";\n" "\"print-quality.4\" = \"Normale\";\n" "\"print-quality.5\" = \"Alta\";\n" "\"print-speed\" = \"Velocità di stampa\";\n" "\"printer-resolution\" = \"Risoluzione stampa\";\n" "\"printer-state\" = \"Stato stampante\";\n" "\"printer-state.3\" = \"Bozza\";\n" "\"printer-state.4\" = \"Normale\";\n" "\"printer-state.5\" = \"Stopped\";\n" "\"printer-state-reaosns\" = \"Stato dettagliato stampante\";\n" "\"printer-state-reasons.cover-open\" = \"Coperchio aperto.\";\n" "\"printer-state-reasons.media-empty\" = \"File multimediale esaurito.\";\n" "\"printer-state-reasons.media-jam\" = \"Inceppamento file multimediale.\";\n" "\"printer-state-reasons.media-low\" = \"Livello file multimediale basso.\";\n" "\"printer-state-reasons.media-needed\" = \"Necessario file multimediale.\";\n" "\"printer-state-reasons.none\" = \"Nessuna.\";\n" "\"printer-state-reasons.other\" = \"Altro.\";\n" ; lprint-1.0/static-resources/lprint-it.strings000066400000000000000000000060211362261677400215330ustar00rootroot00000000000000"copies" = "Copie"; "job-state" = "Stato stampa"; "job-state.3" = "In sospeso"; "job-state.4" = "Bloccato"; "job-state.5" = "Elaborazione in corso"; "job-state.6" = "Interrotta"; "job-state.7" = "Annullato"; "job-state.8" = "Interrotto"; "job-state.9" = "Completato"; "job-state-reasons" = "Stato dettagliato stampa"; "job-state-reasons.aborted-by-system" = "Interrotto dal sistema."; "job-state-reasons.job-canceled-by-user" = "Stampa annullata da utente."; "job-state-reasons.job-completed-successfully" = "Stampa completata."; "job-state-reasons.job-data-insufficient" = "Dati stampa insufficienti."; "job-state-reasons.job-incoming" = "Stampa in entrata."; "job-state-reasons.job-printing" = "Stampa."; "job-state-reasons.job-stopped" = "Interrotta."; "job-state-reasons.none" = "Nessuno."; "job-state-reasons.processing-to-stop-point" = "Punto di interruzione elaborazione."; "media" = "File multimediale"; "media-col" = "File multimediale"; "media-size" = "Dimensioni file multimediale"; "media-size-name" = "Nome supporto"; "media-source" = "Sorgente media"; "media-source.alternate-roll" = "Secondo rotolo"; "media-source.main-roll" = "Rotolo principale"; "media-top-offset" = "Offset superiore"; "media-tracking" = "Monitoraggio label"; "media-tracking.continuous" = "Continuo"; "media-tracking.mark" = "Segno"; "media-tracking.web" = "Buco"; "media-type" = "Tipo media"; "media-type.continuous" = "Continuo"; "media-type.labels" = "Etichette"; "media-type.labels-continuous" = "Etichette continuo"; "orientation-requested" = "Orientamento"; "orientation-requested.3" = "Verticale"; "orientation-requested.4" = "Orizzontale"; "orientation-requested.5" = "Inverti orientamento orizzontale"; "orientation-requested.6" = "Inverti orientamento verticale"; "orientation-requested.7" = "Automatico"; "print-color-mode" = "Modalità colore di stampa"; "print-color-mode.bi-level" = "Testo"; "print-color-mode.monochrome" = "Monocromo"; "print-content-optimize" = "Ottimizzazione stampa"; "print-content-optimize.auto" = "Automatica"; "print-content-optimize.graphic" = "Grafici"; "print-content-optimize.photo" = "Foto"; "print-content-optimize.text" = "Testo"; "print-content-optimize.text-and-graphic" = "Testo e grafica"; "print-darkness" = "Stampa l'oscurità"; "print-quality" = "Qualità stampa"; "print-quality.3" = "Bozza"; "print-quality.4" = "Normale"; "print-quality.5" = "Alta"; "print-speed" = "Velocità di stampa"; "printer-resolution" = "Risoluzione stampa"; "printer-state" = "Stato stampante"; "printer-state.3" = "Bozza"; "printer-state.4" = "Normale"; "printer-state.5" = "Stopped"; "printer-state-reaosns" = "Stato dettagliato stampante"; "printer-state-reasons.cover-open" = "Coperchio aperto."; "printer-state-reasons.media-empty" = "File multimediale esaurito."; "printer-state-reasons.media-jam" = "Inceppamento file multimediale."; "printer-state-reasons.media-low" = "Livello file multimediale basso."; "printer-state-reasons.media-needed" = "Necessario file multimediale."; "printer-state-reasons.none" = "Nessuna."; "printer-state-reasons.other" = "Altro."; lprint-1.0/static-resources/lprint-large-png.h000066400000000000000000003743631362261677400215520ustar00rootroot00000000000000static const unsigned char lprint_large_png[] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, 0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x08,0x06,0x00,0x00,0x00,0xf4,0x78,0xd4, 0xfa,0x00,0x00,0x04,0x19,0x69,0x43,0x43,0x50,0x6b,0x43,0x47,0x43,0x6f,0x6c,0x6f, 0x72,0x53,0x70,0x61,0x63,0x65,0x47,0x65,0x6e,0x65,0x72,0x69,0x63,0x52,0x47,0x42, 0x00,0x00,0x38,0x8d,0x8d,0x55,0x5d,0x68,0x1c,0x55,0x14,0x3e,0xbb,0x73,0x67,0x23, 0x24,0xce,0x53,0x6c,0x34,0x85,0x74,0xa8,0x3f,0x0d,0x25,0x0d,0x93,0x56,0x34,0xa1, 0xb4,0xba,0x7f,0xdd,0xdd,0x36,0x6e,0x96,0x49,0x36,0xda,0x22,0xe8,0x64,0xf6,0xee, 0xce,0x98,0xc9,0xce,0x38,0x33,0xbb,0xfd,0xa1,0x4f,0x45,0x50,0x7c,0x31,0xea,0x9b, 0x14,0xc4,0xbf,0xb7,0x80,0x20,0x28,0xf5,0x0f,0xdb,0x3e,0xb4,0x2f,0x95,0x0a,0x25, 0xda,0xd4,0x20,0x28,0x3e,0xb4,0xf8,0x83,0x50,0xe8,0x8b,0xa6,0xeb,0x99,0x3b,0x33, 0x99,0x69,0xba,0xb1,0xde,0x65,0xee,0x7c,0xf3,0x9d,0xef,0x9e,0x7b,0xee,0xb9,0x67, 0xef,0x05,0xe8,0xb9,0xaa,0x58,0x96,0x91,0x14,0x01,0x16,0x9a,0xae,0x2d,0x17,0x32, 0xe2,0x73,0x87,0x8f,0x88,0x3d,0x2b,0x90,0x84,0x87,0xa0,0x17,0x06,0xa1,0x57,0x51, 0x1d,0x2b,0x5d,0xa9,0x4c,0x02,0x36,0x4f,0x0b,0x77,0xb5,0x5b,0xdf,0x43,0xc2,0x7b, 0x5f,0xd9,0xd5,0xdd,0xfe,0x9f,0xad,0xb7,0x46,0x1d,0x15,0x20,0x71,0x1f,0x62,0xb3, 0xe6,0xa8,0x0b,0x88,0x8f,0x01,0xf0,0xa7,0x55,0xcb,0x76,0x01,0x7a,0xfa,0x91,0x1f, 0x3f,0xea,0x5a,0x1e,0xf6,0x62,0xe8,0xb7,0x31,0x40,0xc4,0x2f,0x7a,0xb8,0xe1,0x63, 0xd7,0xc3,0x73,0x3e,0x7e,0x8d,0x69,0x66,0xe4,0x2c,0xe2,0xd3,0x88,0x05,0x55,0x53, 0x6a,0x88,0x97,0x10,0x8f,0xcc,0xc5,0xf8,0x46,0x0c,0xfb,0x31,0xb0,0xd6,0x5f,0xa0, 0x4d,0x6a,0xeb,0xaa,0xe8,0xe5,0xa2,0x62,0x9b,0x75,0xdd,0xa0,0xb1,0x70,0xef,0x61, 0xfe,0x9f,0x6d,0xc1,0x68,0x85,0xf3,0x6d,0xc3,0xa7,0xcf,0x99,0x9f,0x3e,0x84,0xef, 0x61,0x5c,0xfb,0x2b,0x35,0x25,0xe7,0xe1,0x51,0xc4,0x4b,0xaa,0x92,0x9f,0x46,0xfc, 0x08,0xe2,0x6b,0x6d,0x7d,0xb6,0x1c,0xe0,0xdb,0x96,0x9b,0x91,0x11,0x3f,0x06,0x90, 0xdc,0xde,0x9a,0xaf,0xa6,0x11,0xef,0x44,0x5c,0xac,0xdb,0x07,0xaa,0xbe,0x9f,0xa4, 0xad,0xb5,0x8a,0x21,0x7e,0xe7,0x84,0x36,0xf3,0x2c,0xe2,0x2d,0x88,0xcf,0x37,0xe7, 0xca,0x53,0xc1,0xd8,0xab,0xaa,0x93,0xc5,0x9c,0xc1,0x76,0xc4,0xb7,0x35,0x5a,0xf2, 0xf2,0x3b,0x04,0xc0,0x89,0xba,0x5b,0x9a,0xf1,0xc7,0x72,0xfb,0x6d,0x53,0x9e,0xf2, 0xe7,0xe5,0xea,0x35,0x9a,0xcb,0x7b,0x79,0x44,0xfc,0xfa,0xbc,0x79,0x48,0xf6,0x7d, 0x72,0x9f,0x39,0xed,0xe9,0x7c,0xe8,0xf3,0x84,0x96,0x2d,0x07,0xfc,0xa5,0x97,0x94, 0x83,0x15,0xc4,0x83,0x88,0x7f,0xa1,0x46,0x41,0xf6,0xe7,0xe2,0xfe,0xb1,0xdc,0x4a, 0x10,0x03,0x19,0x6a,0x1a,0xe5,0x49,0x7f,0x2e,0x92,0xa3,0x0e,0x5b,0x2f,0xe3,0x5d, 0x6d,0xa6,0xe8,0xcf,0x4b,0x0c,0x17,0x37,0xd4,0x1f,0x4b,0x16,0xeb,0xfa,0x81,0x52, 0xa0,0xff,0x44,0xb3,0x8b,0x72,0x80,0xaf,0x59,0x06,0xab,0x51,0x8c,0x8d,0x4f,0xda, 0x2d,0xb9,0xea,0xeb,0xf9,0x51,0xc5,0xce,0x17,0x7c,0x9f,0x7c,0x85,0x36,0xab,0x81, 0x7f,0xbe,0x0d,0xb3,0x09,0x05,0x28,0x98,0x30,0x87,0xbd,0x0a,0x4d,0x58,0x03,0x11, 0x64,0x28,0x40,0x06,0xdf,0x16,0xd8,0x68,0xa9,0x83,0x0e,0x06,0x32,0x14,0xad,0x14, 0x19,0x8a,0x5f,0xa1,0x66,0x17,0x1b,0xe7,0xc0,0x3c,0xf2,0x3a,0xb4,0x99,0xcd,0xc1, 0xbe,0xc2,0x94,0xfe,0xc8,0xc8,0x5f,0x83,0xf9,0xb8,0xce,0xb4,0x2a,0x64,0x87,0x3e, 0x82,0x16,0xb2,0x1a,0xfc,0x8e,0xac,0x16,0xd3,0x65,0xf1,0xab,0x85,0x5c,0x63,0x13, 0x3f,0x7e,0x2c,0x37,0x02,0x3f,0x26,0x19,0x20,0x12,0xd9,0x83,0xcf,0x5e,0x32,0x49, 0xf6,0x91,0x71,0x32,0x01,0x22,0x79,0x8a,0x3c,0x4d,0xf6,0x93,0x1c,0xb2,0x13,0x64, 0xef,0xfa,0xd8,0x4a,0x6c,0x45,0x5e,0x3c,0x37,0xd6,0xfd,0xbc,0x8c,0x33,0x52,0xa6, 0x9b,0x45,0xdd,0x39,0xb4,0xbb,0xa0,0x60,0xff,0x33,0x2a,0x4c,0x5c,0x53,0xd7,0xac, 0x2c,0x0e,0xb6,0x86,0x23,0xcb,0x29,0xfb,0x05,0x5d,0xbd,0xfc,0xc6,0x5f,0xb1,0x5c, 0xe9,0x2c,0x37,0x51,0xb6,0xe2,0x19,0x9d,0xba,0x57,0xce,0xf9,0x5f,0xf9,0xeb,0xfc, 0x32,0xf6,0x2b,0xfc,0x6a,0xa4,0xe0,0x7f,0xe4,0x57,0xf1,0xb7,0x72,0xc7,0x5a,0xcc, 0xbb,0xb2,0x4c,0xc3,0xec,0x6c,0x58,0x73,0x77,0x55,0x1a,0x6d,0x06,0xe3,0x16,0xf0, 0xd1,0x99,0xc5,0x89,0xc5,0x1d,0xf3,0x71,0xf1,0xe4,0x57,0x0f,0x46,0x7e,0x96,0xc9, 0x99,0xe7,0xaf,0xf4,0x5d,0x3c,0x59,0x6f,0x2e,0x0e,0x46,0xac,0x97,0x05,0xfa,0x6a, 0xf9,0x56,0x19,0x4e,0x8d,0x44,0xac,0xf4,0x83,0xf4,0x87,0xb4,0x2c,0xbd,0x27,0x7d, 0x28,0xfd,0xc6,0xbd,0xcd,0x7d,0xca,0x7d,0xcd,0x7d,0xce,0x7d,0xc1,0x5d,0x02,0x91, 0x3b,0xcb,0x9d,0xe3,0xbe,0xe1,0x2e,0x70,0x1f,0x73,0x5f,0xc6,0xf6,0x6a,0xf3,0x1a, 0x5a,0xdf,0x7b,0x16,0x79,0x18,0xb7,0x67,0xe9,0x96,0x6b,0xac,0x4a,0x21,0x23,0x6c, 0x15,0x1e,0x16,0x72,0xc2,0x36,0xe1,0x51,0x61,0x32,0xf2,0x27,0x0c,0x08,0x63,0x42, 0x51,0xd8,0x81,0x96,0xad,0xeb,0xfb,0x16,0x9f,0x2f,0x9e,0x3d,0x1d,0x0e,0x63,0x1f, 0xe6,0xa7,0xfb,0x5c,0xbe,0x2e,0x56,0x01,0x89,0xfb,0xb1,0x02,0xf4,0x4d,0xfe,0x55, 0x55,0x54,0xe9,0x70,0x94,0x29,0x1d,0x56,0x6f,0x4d,0x38,0xbe,0x41,0x13,0x8c,0x24, 0x43,0x64,0x8c,0x94,0x36,0x54,0xf7,0xb8,0x57,0xf3,0xa1,0x22,0x95,0x4f,0xe5,0x52, 0x69,0x10,0x53,0x3b,0x53,0x13,0xa9,0xb1,0xd4,0x41,0x0f,0x87,0xb3,0xa6,0x76,0xa0, 0x6d,0x02,0xfb,0xfc,0x1d,0xd5,0xa9,0x6e,0xb2,0x52,0xea,0xd2,0x63,0xde,0x7d,0x02, 0x59,0xd3,0x3a,0x6e,0xeb,0x0d,0xcd,0x15,0x77,0x4b,0xd2,0x93,0x62,0x1a,0xaf,0x36, 0x2a,0x96,0x9a,0xea,0xe8,0x88,0xa8,0x18,0x86,0xc8,0x4c,0x8e,0x68,0x53,0x87,0xda, 0x6d,0x5a,0x1b,0x05,0xef,0xde,0xf4,0x8f,0xf4,0x9b,0x32,0xbb,0x0f,0x13,0x5b,0x2e, 0x47,0x9c,0xfb,0x0c,0xc0,0xbe,0x3f,0xf1,0xec,0xfb,0x2e,0xe2,0x8e,0xb4,0x00,0x96, 0x1c,0x80,0x81,0xc7,0x23,0x6e,0x18,0xcf,0xca,0x07,0xde,0x05,0x38,0xf3,0x84,0xda, 0xb2,0xdb,0xc1,0x1d,0x91,0x48,0x7c,0x0b,0xe0,0xd4,0xf7,0xec,0xf6,0xbf,0xfa,0x32, 0x78,0x7e,0xfd,0xd4,0xe9,0xdc,0xc4,0x73,0xac,0xe7,0x2d,0x80,0xb5,0x37,0x3b,0x9d, 0xbf,0xdf,0xef,0x74,0xd6,0x3e,0x40,0xff,0xab,0x00,0x67,0x8d,0x7f,0x01,0xa0,0x9f, 0x7c,0x55,0x03,0x5c,0x0b,0xef,0x00,0x00,0x00,0x38,0x65,0x58,0x49,0x66,0x4d,0x4d, 0x00,0x2a,0x00,0x00,0x00,0x08,0x00,0x01,0x87,0x69,0x00,0x04,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x1a,0x00,0x00,0x00,0x00,0x00,0x02,0xa0,0x02,0x00,0x04,0x00,0x00, 0x00,0x01,0x00,0x00,0x02,0x00,0xa0,0x03,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00, 0x02,0x00,0x00,0x00,0x00,0x00,0x28,0x30,0x97,0xbf,0x00,0x00,0x03,0x63,0x69,0x54, 0x58,0x74,0x58,0x4d,0x4c,0x3a,0x63,0x6f,0x6d,0x2e,0x61,0x64,0x6f,0x62,0x65,0x2e, 0x78,0x6d,0x70,0x00,0x00,0x00,0x00,0x00,0x3c,0x78,0x3a,0x78,0x6d,0x70,0x6d,0x65, 0x74,0x61,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3a,0x78,0x3d,0x22,0x61,0x64,0x6f,0x62, 0x65,0x3a,0x6e,0x73,0x3a,0x6d,0x65,0x74,0x61,0x2f,0x22,0x20,0x78,0x3a,0x78,0x6d, 0x70,0x74,0x6b,0x3d,0x22,0x58,0x4d,0x50,0x20,0x43,0x6f,0x72,0x65,0x20,0x35,0x2e, 0x34,0x2e,0x30,0x22,0x3e,0x0a,0x20,0x20,0x20,0x3c,0x72,0x64,0x66,0x3a,0x52,0x44, 0x46,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3a,0x72,0x64,0x66,0x3d,0x22,0x68,0x74,0x74, 0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x77,0x33,0x2e,0x6f,0x72,0x67,0x2f,0x31, 0x39,0x39,0x39,0x2f,0x30,0x32,0x2f,0x32,0x32,0x2d,0x72,0x64,0x66,0x2d,0x73,0x79, 0x6e,0x74,0x61,0x78,0x2d,0x6e,0x73,0x23,0x22,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20, 0x20,0x3c,0x72,0x64,0x66,0x3a,0x44,0x65,0x73,0x63,0x72,0x69,0x70,0x74,0x69,0x6f, 0x6e,0x20,0x72,0x64,0x66,0x3a,0x61,0x62,0x6f,0x75,0x74,0x3d,0x22,0x22,0x0a,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x78,0x6d,0x6c,0x6e,0x73, 0x3a,0x64,0x63,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x70,0x75,0x72,0x6c, 0x2e,0x6f,0x72,0x67,0x2f,0x64,0x63,0x2f,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73, 0x2f,0x31,0x2e,0x31,0x2f,0x22,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x78,0x6d,0x6c,0x6e,0x73,0x3a,0x49,0x70,0x74,0x63,0x34,0x78,0x6d, 0x70,0x45,0x78,0x74,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x69,0x70,0x74, 0x63,0x2e,0x6f,0x72,0x67,0x2f,0x73,0x74,0x64,0x2f,0x49,0x70,0x74,0x63,0x34,0x78, 0x6d,0x70,0x45,0x78,0x74,0x2f,0x32,0x30,0x30,0x38,0x2d,0x30,0x32,0x2d,0x32,0x39, 0x2f,0x22,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x78, 0x6d,0x6c,0x6e,0x73,0x3a,0x70,0x68,0x6f,0x74,0x6f,0x73,0x68,0x6f,0x70,0x3d,0x22, 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6e,0x73,0x2e,0x61,0x64,0x6f,0x62,0x65,0x2e, 0x63,0x6f,0x6d,0x2f,0x70,0x68,0x6f,0x74,0x6f,0x73,0x68,0x6f,0x70,0x2f,0x31,0x2e, 0x30,0x2f,0x22,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x64, 0x63,0x3a,0x63,0x72,0x65,0x61,0x74,0x6f,0x72,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x72,0x64,0x66,0x3a,0x53,0x65,0x71,0x3e, 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x3c,0x72,0x64,0x66,0x3a,0x6c,0x69,0x3e,0x4d,0x69,0x63,0x68,0x61,0x65,0x6c,0x20, 0x53,0x77,0x65,0x65,0x74,0x3c,0x2f,0x72,0x64,0x66,0x3a,0x6c,0x69,0x3e,0x0a,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x72,0x64,0x66, 0x3a,0x53,0x65,0x71,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c, 0x2f,0x64,0x63,0x3a,0x63,0x72,0x65,0x61,0x74,0x6f,0x72,0x3e,0x0a,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x64,0x63,0x3a,0x72,0x69,0x67,0x68,0x74,0x73, 0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x72, 0x64,0x66,0x3a,0x41,0x6c,0x74,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x72,0x64,0x66,0x3a,0x6c,0x69,0x20,0x78, 0x6d,0x6c,0x3a,0x6c,0x61,0x6e,0x67,0x3d,0x22,0x78,0x2d,0x64,0x65,0x66,0x61,0x75, 0x6c,0x74,0x22,0x3e,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x32,0x30, 0x31,0x39,0x20,0x4d,0x69,0x63,0x68,0x61,0x65,0x6c,0x20,0x53,0x77,0x65,0x65,0x74, 0x3c,0x2f,0x72,0x64,0x66,0x3a,0x6c,0x69,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20, 0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x72,0x64,0x66,0x3a,0x41,0x6c,0x74,0x3e, 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x64,0x63,0x3a,0x72, 0x69,0x67,0x68,0x74,0x73,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 0x3c,0x49,0x70,0x74,0x63,0x34,0x78,0x6d,0x70,0x45,0x78,0x74,0x3a,0x48,0x65,0x61, 0x64,0x6c,0x69,0x6e,0x65,0x3e,0x4e,0x65,0x77,0x20,0x49,0x63,0x6f,0x6e,0x3c,0x2f, 0x49,0x70,0x74,0x63,0x34,0x78,0x6d,0x70,0x45,0x78,0x74,0x3a,0x48,0x65,0x61,0x64, 0x6c,0x69,0x6e,0x65,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c, 0x70,0x68,0x6f,0x74,0x6f,0x73,0x68,0x6f,0x70,0x3a,0x48,0x65,0x61,0x64,0x6c,0x69, 0x6e,0x65,0x3e,0x4e,0x65,0x77,0x20,0x49,0x63,0x6f,0x6e,0x3c,0x2f,0x70,0x68,0x6f, 0x74,0x6f,0x73,0x68,0x6f,0x70,0x3a,0x48,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x3e, 0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x72,0x64,0x66,0x3a,0x44,0x65,0x73, 0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x3e,0x0a,0x20,0x20,0x20,0x3c,0x2f,0x72, 0x64,0x66,0x3a,0x52,0x44,0x46,0x3e,0x0a,0x3c,0x2f,0x78,0x3a,0x78,0x6d,0x70,0x6d, 0x65,0x74,0x61,0x3e,0x0a,0xdd,0xf2,0x38,0x1b,0x00,0x00,0x59,0x3b,0x49,0x44,0x41, 0x54,0x78,0xda,0xed,0x9d,0x07,0xd4,0x14,0x45,0xd6,0x86,0x87,0x9c,0x25,0x47,0x45, 0x40,0x51,0x82,0xa8,0x28,0x28,0x62,0x40,0x10,0x03,0x60,0x16,0x54,0x5c,0x77,0x15, 0x71,0x0d,0xbf,0x39,0x8b,0x98,0x11,0x45,0x0c,0x80,0xae,0xa2,0x08,0xab,0x62,0xc0, 0x04,0x2a,0x06,0x44,0x51,0x30,0x07,0x14,0x01,0x49,0x06,0x14,0x73,0xc4,0x1c,0x40, 0x09,0xf5,0xdf,0x3b,0x74,0x2f,0x45,0x3b,0x79,0x7a,0x66,0xba,0x7b,0x9e,0x3a,0xe7, 0x39,0x67,0x5d,0xd2,0xd7,0xdd,0xd5,0xf5,0xbe,0x7d,0xeb,0xde,0x5b,0xb1,0x18,0x83, 0xc1,0x60,0x30,0x18,0x0c,0x06,0x83,0xc1,0x60,0x30,0x18,0x0c,0x06,0x83,0xc1,0x60, 0x30,0x18,0x0c,0x06,0x83,0xc1,0x60,0x30,0x18,0x0c,0x06,0x83,0xc1,0x60,0x30,0x18, 0x0c,0x06,0x83,0xc1,0x60,0x30,0x18,0x0c,0x06,0x83,0xc1,0x60,0x30,0x18,0x0c,0x46, 0xe4,0x46,0x05,0x00,0x00,0x08,0x34,0x0c,0x86,0x6f,0xe2,0x5e,0x31,0x0b,0x2a,0x01, 0x00,0x40,0x41,0xc9,0x66,0x4d,0xc6,0x24,0x30,0xd2,0x8a,0x7d,0x3a,0x21,0xaf,0x9c, 0x82,0x2a,0x00,0x00,0x50,0x12,0x52,0xad,0xcd,0xe9,0x8c,0x03,0xa6,0x00,0xc1,0x4f, 0x28,0xf2,0xf6,0x04,0xab,0x6a,0x51,0x2d,0x0d,0xd5,0x01,0x00,0xa0,0xa0,0xa4,0x5b, 0x87,0xed,0x35,0x3b,0x99,0x59,0x48,0x64,0x0a,0x30,0x04,0x11,0x15,0xfd,0x54,0x82, 0x5f,0x25,0x81,0xc0,0xbb,0x13,0xad,0x86,0x45,0x4d,0x0f,0xb5,0x00,0x00,0x20,0x10, 0x78,0xd7,0x67,0x7b,0xed,0xf6,0x1a,0x07,0xdb,0x1c,0x64,0x6a,0x08,0x18,0x21,0x15, 0xfd,0x74,0x82,0x6f,0x8b,0xbd,0x2d,0xec,0xb5,0x1d,0xea,0x38,0x6c,0x64,0x51,0x37, 0x09,0xf5,0x00,0x00,0xa0,0xa0,0x24,0x5b,0x7f,0xed,0x35,0xda,0x5d,0xb7,0xdd,0x75, 0xdc,0x36,0x0a,0x5e,0x53,0x90,0x89,0x21,0xc0,0x0c,0x44,0x40,0xf4,0xab,0x79,0xc4, 0xbe,0xa6,0x25,0xf6,0x75,0x2c,0x71,0x77,0x27,0x5a,0x7d,0xa1,0x81,0x43,0x43,0x8b, 0x46,0x1e,0x1a,0x03,0x00,0x40,0x51,0xf1,0xae,0xc3,0xf6,0x1a,0xed,0xae,0xdb,0xf5, 0x3d,0xc6,0x61,0x23,0xcb,0x18,0xd4,0xf2,0x44,0x0c,0x6c,0x43,0x80,0x19,0x08,0xa9, 0xf0,0xa7,0x13,0x7d,0x5b,0xf0,0xeb,0x7a,0x84,0xbe,0xa1,0x25,0xe8,0x4d,0x1c,0x9a, 0x0a,0xcd,0x1c,0x9a,0x3b,0xb4,0xb0,0xd8,0x18,0x00,0x00,0x4a,0x82,0xbd,0x16,0xbb, 0xeb,0xb3,0xbb,0x5e,0x37,0xb5,0xd6,0xf1,0xc6,0x96,0x49,0xb0,0x8d,0x41,0xdd,0x04, 0x86,0x20,0x9d,0x19,0xc0,0x08,0x04,0x54,0xf8,0x53,0x89,0xbe,0xfd,0x85,0xef,0x0a, 0xbe,0x2d,0xf6,0x4d,0x2d,0x71,0xd7,0x89,0xb5,0x89,0xd0,0x52,0xd8,0xd4,0xa1,0x95, 0xd0,0xda,0xa1,0x8d,0xc5,0x66,0x00,0x00,0x50,0x12,0xec,0xb5,0xd8,0x5d,0x9f,0x5b, 0x59,0xeb,0x76,0x4b,0x67,0x2d,0xdf,0xd8,0x32,0x09,0x4d,0x3d,0xa6,0xc0,0x35,0x04, 0x76,0x84,0x20,0x9d,0x19,0xc0,0x08,0x04,0x58,0xf8,0xed,0x2f,0xfd,0x8d,0xac,0xaf, 0x7c,0xf7,0x0b,0xbf,0x89,0xf5,0x45,0xef,0x8a,0x7d,0x17,0xe1,0x70,0xe1,0x6c,0x61, 0x8c,0x30,0x45,0x78,0x5e,0x58,0x20,0x7c,0x21,0xfc,0x28,0xfc,0x21,0xac,0x16,0x0c, 0x00,0x00,0x94,0x84,0xd5,0xce,0x5a,0xfc,0xa3,0xb3,0x36,0xeb,0x1a,0xfd,0x82,0xb3, 0x66,0xdf,0x20,0x9c,0x2b,0xfc,0x43,0xd8,0x49,0x68,0x2b,0x6c,0x6e,0x99,0x05,0xd7, 0x1c,0xb8,0xa6,0xc0,0x8d,0x18,0x34,0xb1,0x22,0x04,0x6e,0x74,0x60,0x23,0x4f,0x64, 0x00,0x23,0x10,0x60,0xe1,0x77,0xbf,0xf6,0xed,0xf0,0xbe,0x2b,0xfa,0x8d,0x2d,0xd1, 0x57,0x17,0xd8,0x51,0x38,0x52,0x18,0xed,0x4c,0x9c,0xef,0x79,0xa9,0x00,0x00,0x22, 0x87,0xae,0xed,0x2f,0x3a,0xc6,0x60,0x90,0xf3,0xa1,0xb7,0x85,0x65,0x0a,0x5a,0x5b, 0x86,0xa0,0x85,0x65,0x06,0x1a,0x5b,0x66,0xc0,0xde,0x26,0x70,0xa3,0x02,0x18,0x81, 0x22,0x8a,0x7f,0xa6,0xc2,0xef,0x7e,0xed,0x37,0xf0,0x7c,0xe9,0xeb,0xc3,0xdd,0x57, 0xb8,0x56,0x78,0x5b,0x58,0xcb,0x8b,0x01,0x00,0x50,0x76,0xe8,0xda,0x3f,0x57,0x18, 0x25,0xf4,0x17,0x3a,0x58,0x86,0xc0,0x8d,0x10,0xb4,0xf4,0x98,0x01,0x77,0x9b,0xc0, 0x8e,0x0a,0x64,0x63,0x04,0x18,0x79,0x7e,0xf5,0x67,0x23,0xfc,0x8d,0xad,0xfd,0xfc, 0x7e,0xc2,0xad,0xc2,0x97,0x4c,0x7c,0x00,0x00,0xf0,0xa0,0xda,0x70,0x9b,0x63,0x06, 0xda,0x0b,0x5b,0x5a,0x66,0xc0,0x8d,0x0c,0xb8,0x79,0x03,0x8d,0x73,0x30,0x02,0x44, 0x03,0x7c,0xfc,0xea,0xb7,0xf7,0xf8,0x6d,0xe1,0x77,0xc3,0xfc,0xea,0xd8,0xb6,0x12, 0x2e,0x16,0x3e,0x60,0x72,0x03,0x00,0x40,0x86,0xa8,0x66,0x0c,0x13,0xba,0x3b,0x66, 0xc0,0x8d,0x0c,0xb4,0xf6,0x44,0x05,0xdc,0xed,0x01,0xaf,0x11,0x70,0x73,0x04,0x88, 0x06,0x14,0xe0,0xab,0xdf,0x4e,0xee,0xf3,0x7e,0xf1,0xeb,0x43,0xe9,0x21,0xdc,0x2d, 0xfc,0xc9,0x44,0x06,0x00,0x80,0x1c,0x51,0x0d,0x99,0xe4,0x6c,0x1b,0x6b,0xbe,0x58, 0x3b,0x27,0x99,0xd0,0x8d,0x0a,0x6c,0x6c,0x19,0x01,0x3b,0x22,0x60,0x27,0x0b,0x12, 0x0d,0xf0,0xe1,0xab,0xdf,0x0e,0xf7,0xd7,0xb2,0x92,0xfb,0xec,0x50,0xff,0x5e,0xc2, 0x53,0x4c,0x5a,0x00,0x00,0xf0,0x99,0xa7,0x85,0x43,0x9c,0xc8,0x72,0x7b,0x8f,0x11, 0x68,0xe1,0xd9,0x1a,0x70,0x93,0x05,0x6b,0x79,0xb6,0x05,0x88,0x06,0x64,0x28,0xfe, 0xc9,0xbe,0xfa,0xdd,0x70,0x7f,0x7d,0x27,0x21,0xa3,0xa9,0xf3,0xc5,0xff,0x04,0x13, 0x14,0x00,0x00,0x0a,0xcc,0x34,0x61,0xff,0x04,0x46,0xa0,0xa5,0x65,0x04,0x1a,0x39, 0x1a,0xe5,0xdd,0x16,0x48,0x15,0x0d,0x20,0xe4,0x9f,0x64,0xaf,0xdf,0xfe,0xea,0x77, 0xf7,0xf9,0x9b,0x38,0x59,0x9b,0xe3,0x63,0xd4,0xe3,0x03,0x00,0x40,0x71,0xfb,0x0f, 0xdc,0x29,0xec,0xea,0x18,0x01,0x77,0x6b,0xa0,0xb5,0x95,0x2c,0xd8,0xc4,0xca,0x0f, 0xf0,0x46,0x03,0xd8,0x12,0xc8,0x20,0xe4,0x9f,0xec,0xab,0x5f,0xf7,0x5c,0xce,0x8c, 0xad,0x6b,0xfe,0xc0,0x64,0x04,0x00,0x80,0x52,0xa0,0x1a,0x34,0x54,0xd8,0xd6,0x32, 0x02,0xda,0x53,0xa0,0x95,0x93,0x1f,0x90,0x2e,0x1a,0x50,0xd6,0x5b,0x02,0x99,0x84, 0xfc,0xed,0xbd,0xfe,0x26,0x4e,0x56,0xe6,0x4b,0x4c,0x3c,0x00,0x00,0x08,0x08,0xaf, 0x38,0x89,0x82,0xdb,0xc4,0xd6,0xf7,0x13,0x70,0xb7,0x05,0xdc,0x68,0x80,0x9d,0x1b, 0x50,0xf6,0x5b,0x02,0xd9,0x86,0xfc,0xd5,0x49,0x9d,0x23,0xac,0x60,0xb2,0x01,0x00, 0x40,0xc0,0x50,0x6d,0xba,0x48,0xe8,0x2c,0x74,0x72,0xa2,0x01,0x9b,0x7b,0xa2,0x01, 0xd9,0x6e,0x09,0x94,0xad,0xf8,0xdb,0x21,0xff,0x0e,0x4e,0xe2,0x05,0x93,0x0c,0x00, 0x00,0x82,0x5e,0x2d,0xb0,0xbb,0x27,0x1a,0xe0,0xe6,0x06,0x34,0xf3,0x6c,0x09,0x94, 0x9d,0x09,0x48,0x27,0xfe,0xb5,0x63,0x1b,0x96,0xf7,0xed,0x2d,0x7c,0xc6,0xa4,0x02, 0x00,0x80,0x90,0xf0,0x79,0x6c,0xdd,0x81,0x72,0x9d,0x3d,0xb9,0x01,0xee,0x96,0x80, 0x5d,0x2e,0x58,0xbb,0x5c,0x4c,0x40,0x22,0xf1,0x77,0xeb,0xfb,0x6b,0x7a,0xc4,0x5f, 0xf7,0x4c,0x4e,0x13,0x56,0x32,0x99,0x00,0x00,0x20,0x64,0xa8,0x76,0x0d,0x11,0xb6, 0x17,0xb6,0x8e,0xad,0x2b,0x19,0x74,0xb7,0x04,0x5a,0x78,0xf2,0x02,0xdc,0xe4,0xc0, 0x44,0xfd,0x02,0x22,0x61,0x02,0x32,0x15,0x7f,0x77,0xbf,0x7f,0x34,0x13,0x08,0x00, 0x00,0x42,0xce,0xcd,0x42,0x57,0xa7,0x52,0x40,0xb7,0x04,0xda,0x26,0xc8,0x0b,0x88, 0xb4,0x09,0xc8,0x44,0xfc,0xdd,0x64,0x3f,0xdd,0x27,0x99,0xc2,0xa4,0x01,0x00,0x80, 0x88,0xf0,0xa8,0xb0,0xb3,0xb3,0x25,0xd0,0xd1,0xca,0x0b,0xf0,0x26,0x07,0x46,0xce, 0x04,0xa4,0xda,0xf3,0xf7,0x8a,0xbf,0xba,0xa2,0x67,0x99,0x2c,0x00,0x00,0x10,0x31, 0x66,0xc6,0xd6,0x35,0x0e,0xda,0xce,0xc9,0x0b,0xd0,0xd3,0x06,0xdb,0x38,0x1f,0xbd, 0xc9,0x4c,0x40,0xe8,0x73,0x02,0x32,0x15,0x7f,0x4d,0x90,0xa0,0xbe,0x1f,0x00,0x00, 0xa2,0xdc,0x2f,0x60,0x77,0x27,0x2f,0xa0,0x53,0x1e,0x26,0x20,0x74,0x5f,0xff,0xc9, 0xb2,0xfd,0xdd,0x2f,0x7f,0xc4,0x1f,0x00,0x00,0xca,0xc1,0x04,0xf4,0xb0,0x4c,0x40, 0xbb,0x04,0x26,0x20,0x59,0x75,0x40,0x68,0xa2,0x00,0xde,0xd0,0x7f,0x32,0xf1,0xdf, 0x84,0xb0,0x3f,0x00,0x00,0x94,0x11,0xb3,0x9c,0xed,0x80,0x6c,0x4d,0x40,0x28,0xb6, 0x02,0x12,0x89,0x7f,0xd5,0xd8,0xfa,0x26,0x3f,0x6e,0xa9,0x5f,0x53,0x12,0xfe,0x00, 0x00,0xa0,0x0c,0x99,0x1a,0x5b,0xd7,0xda,0x3e,0xd9,0x76,0x80,0x5b,0x22,0xe8,0x36, 0x0b,0xaa,0x1a,0x16,0x13,0x90,0x28,0xe3,0xbf,0x7a,0x6c,0x7d,0x87,0x3f,0xb7,0xce, 0x9f,0x52,0x3f,0x00,0x00,0x28,0x57,0xc6,0x26,0x30,0x01,0x6e,0x75,0x80,0xdb,0x27, 0xc0,0xed,0x18,0x58,0x3d,0x49,0x65,0x40,0xe0,0xf7,0xfd,0xed,0x83,0x7d,0xb4,0x05, 0xa2,0x76,0x41,0x3a,0x8d,0x87,0x0f,0x00,0x00,0x65,0xce,0x85,0xc2,0x4e,0x8e,0x09, 0xd0,0xea,0x80,0x2d,0x62,0xeb,0x9b,0x05,0x35,0x76,0x34,0xd3,0x3e,0x40,0x28,0xb0, 0xf9,0x00,0xc9,0xf6,0xfd,0x5d,0xf1,0xd7,0xec,0x46,0xed,0x83,0xac,0xed,0x7d,0xe9, 0xf0,0x07,0x00,0x00,0xe5,0x8e,0x6a,0xe1,0xbf,0x84,0x6e,0xb1,0x75,0x25,0x82,0xda, 0x27,0xc0,0x6d,0x16,0xd4,0xdc,0xd1,0xcc,0x7a,0x96,0x09,0x08,0x6c,0x3e,0x40,0xa2, 0xd0,0xbf,0x37,0xe9,0x4f,0x3b,0x21,0xd1,0xdb,0x1f,0x00,0x00,0x60,0x1d,0x7a,0x76, 0x40,0x1f,0xc7,0x04,0x74,0x76,0x74,0x52,0xdb,0x06,0xeb,0xd9,0x01,0xcd,0x12,0x24, 0x05,0x06,0x6e,0x2b,0xc0,0x75,0x21,0xa9,0xf6,0xfd,0x35,0xb1,0x81,0x53,0xfd,0x00, 0x00,0x00,0x36,0xe4,0x19,0xa7,0x32,0x60,0x87,0xd8,0xba,0xb6,0xc1,0x7a,0x76,0xc0, 0x66,0x9e,0xa4,0xc0,0x44,0xf9,0x00,0x25,0x8f,0x02,0xa4,0x0b,0xfd,0xd7,0x77,0x12, 0x1a,0xce,0xe5,0x21,0x03,0x00,0x00,0x24,0xe4,0x72,0x61,0x97,0xd8,0xba,0xb3,0x03, 0xf4,0x00,0xa1,0x76,0x9e,0xa4,0xc0,0xfa,0x41,0xdc,0x0a,0x48,0x15,0xfa,0x77,0xf7, 0xfd,0x35,0xd3,0x71,0x05,0x0f,0x18,0x00,0x00,0x20,0x21,0xaa,0x91,0x87,0x5a,0x95, 0x01,0x76,0x52,0xa0,0x9d,0x0f,0x10,0x98,0xad,0x00,0x6f,0xd6,0xbf,0x37,0xf4,0xdf, 0xd0,0xd9,0xc3,0xa0,0xd3,0x1f,0x00,0x00,0x40,0x6a,0x5e,0x8d,0xad,0x6b,0x17,0x9c, 0x28,0x1f,0xc0,0x6d,0x12,0x64,0x6f,0x05,0x94,0xb4,0x2a,0x20,0x93,0xd0,0xff,0x99, 0x3c,0x54,0x00,0x00,0x80,0x8c,0xb8,0x4c,0xd8,0xcd,0xc9,0x07,0xd8,0x26,0xb6,0xbe, 0x53,0x60,0xa6,0x5b,0x01,0x25,0xfd,0xfa,0x77,0xb3,0xfe,0x1b,0x39,0xee,0xe5,0x47, 0x1e,0x28,0x00,0x00,0x40,0x46,0xa8,0x66,0xee,0x1b,0x5b,0x77,0x84,0x70,0x97,0xd8, 0xba,0x26,0x41,0xde,0xad,0x00,0xb7,0x2a,0xa0,0x64,0x09,0x81,0xc9,0xbe,0xfe,0xed, 0xac,0xff,0xf1,0x3c,0x4c,0x00,0x00,0x80,0xac,0xb8,0xcb,0xd9,0x0a,0xd8,0xc9,0xda, 0x0a,0x48,0x54,0x15,0x50,0x92,0x28,0x40,0xa2,0xaf,0x7f,0x3b,0xf1,0x4f,0x3b,0x18, 0xe9,0x89,0x47,0xab,0x79,0x90,0x00,0x00,0x00,0x59,0xa1,0xda,0x79,0x64,0x6c,0x7d, 0x69,0xa0,0x6e,0x05,0xb8,0xad,0x82,0xdd,0x2e,0x81,0x89,0x12,0x02,0x8b,0x12,0x05, 0xc8,0xe4,0xeb,0xff,0x09,0x1e,0x22,0x40,0x61,0x90,0x15,0xc0,0x0c,0x89,0x55,0x34, 0x2f,0xc4,0x2a,0x9b,0x27,0x85,0xb3,0xe4,0x7f,0x77,0x8e,0x55,0x30,0x15,0xb8,0x37, 0x00,0x51,0x61,0xba,0xd0,0xcb,0x53,0x15,0xd0,0xd6,0x4a,0x08,0x2c,0x49,0x14,0x20, 0x93,0xaf,0xff,0xbd,0x78,0x78,0x00,0x85,0x61,0xb0,0x88,0xfd,0x3c,0x11,0xfd,0xc5, 0xb1,0x2a,0x7f,0xe3,0x25,0xf9,0xff,0x87,0xc5,0x2a,0x99,0x9e,0x62,0x06,0xaa,0x71, 0xaf,0x00,0xc2,0xce,0x31,0x4e,0x34,0x7d,0xc7,0xd8,0xba,0x06,0x41,0x6e,0x42,0x60, 0xc9,0xa2,0x00,0xa9,0xbe,0xfe,0xdd,0xb2,0xbf,0xa7,0x78,0x70,0x00,0xfe,0x73,0xbc, 0x88,0x7f,0x22,0xe1,0x4f,0xc4,0x1c,0x31,0x03,0x37,0x8a,0x19,0x38,0x48,0xcc,0x40, 0x3d,0xee,0x1d,0x40,0x18,0x99,0x21,0xec,0x11,0x5b,0xd7,0x20,0xa8,0x8b,0x15,0x05, 0xd8,0x34,0xb6,0xbe,0x4d,0x70,0x51,0xa3,0x00,0x99,0xec,0xfd,0xf3,0xe0,0x00,0x7c, 0xe6,0x5f,0x59,0x88,0xbf,0x97,0x85,0x62,0x06,0xee,0x12,0x33,0x30,0x48,0xfe,0x8e, 0x56,0xdc,0x4b,0x80,0x30,0xf1,0xcf,0xd8,0xfa,0xde,0x00,0x6e,0x9b,0x60,0xb7,0x2c, 0x30,0x5d,0x14,0xa0,0xa8,0x7b,0xff,0xea,0x48,0xee,0xe6,0x81,0x01,0xf8,0xcb,0x00, 0xf9,0x8a,0xcf,0x55,0xfc,0x13,0xf1,0x98,0x18,0x82,0x33,0xc4,0x0c,0x6c,0x23,0x7f, 0x2f,0xf7,0x17,0x20,0xd0,0x3c,0x28,0xf4,0x4e,0x11,0x05,0x28,0x5a,0x2e,0x80,0x6d, 0x00,0xec,0xba,0x7f,0xf7,0xeb,0x5f,0x7f,0xb0,0x3f,0x79,0x60,0x00,0xfe,0xb1,0x9f, 0x88,0xf4,0xc2,0x24,0x7b,0xfe,0x7e,0xa0,0x89,0x84,0x97,0x4b,0x74,0xa0,0x87,0xfc, 0x3b,0x55,0xb9,0xdf,0x00,0x41,0x43,0x35,0xf5,0xe0,0x24,0x51,0x00,0x6f,0x2e,0x80, 0xdb,0x17,0xa0,0xa0,0x06,0xa0,0x72,0x6c,0xc3,0xae,0x7f,0x6e,0xe6,0xff,0xc5,0x3c, 0x2c,0x00,0xff,0xd8,0x53,0x44,0xf9,0x9d,0x02,0x8a,0xbf,0x97,0xb7,0xe4,0xdf,0xba, 0x41,0xcc,0xc0,0x01,0xf2,0xef,0xd6,0xe5,0xfe,0x03,0x04,0x85,0x6b,0x93,0x44,0x01, 0xec,0x8a,0x00,0xbb,0x3b,0xa0,0xef,0xdb,0x00,0xde,0xf0,0xbf,0xdb,0xf3,0xdf,0xed, 0xfa,0xa7,0x1d,0x8a,0x3e,0xe0,0x41,0x01,0xf8,0xc3,0x6e,0x22,0xc2,0xf3,0x8a,0x28, 0xfe,0x5e,0x16,0xc8,0xbf,0x3d,0x51,0xcc,0xc0,0x51,0xb2,0x55,0xb0,0x09,0xcf,0x03, 0xa0,0x94,0x2c,0x15,0xf6,0xb6,0x2a,0x02,0xdc,0x16,0xc1,0xad,0x63,0x1b,0x76,0x07, 0xb4,0xcf,0x08,0xf0,0x35,0x0a,0x90,0x2c,0xf9,0xcf,0xed,0xf9,0xdf,0x8f,0x87,0x04, 0xe0,0x0f,0xdd,0x44,0xfc,0xe7,0x96,0x50,0xfc,0x13,0x31,0x55,0x7e,0x9e,0xd3,0xc4, 0x0c,0x74,0x22,0x6f,0x00,0xa0,0x14,0x1c,0xef,0x54,0x04,0x68,0x8b,0x60,0xed,0x0b, 0xd0,0x31,0xb6,0xbe,0x3b,0xa0,0x7b,0x46,0x40,0xc1,0x92,0x01,0x2b,0xc4,0xd6,0x1f, 0xf9,0x9b,0xa8,0xf4,0xef,0x56,0x1e,0x10,0x40,0xfe,0x6c,0x27,0x02,0xfb,0x56,0xc0, 0xc4,0xdf,0xcb,0xf3,0xf2,0xf3,0x5d,0x22,0x66,0x60,0x57,0xf9,0x59,0xab,0xf0,0xcc, 0x00,0x8a,0xc1,0x9d,0xb1,0x75,0x3d,0x76,0xdc,0x83,0x82,0xb6,0x8e,0xad,0x3b,0x23, 0x20,0x59,0x49,0xa0,0x7b,0x54,0x70,0x05,0x3f,0xc4,0x3f,0x51,0xf8,0xdf,0x4d,0xfe, 0x53,0x07,0xf2,0x15,0x0f,0x08,0x20,0x3f,0xf4,0xeb,0x7a,0x76,0xc0,0xc5,0xdf,0xcb, 0x9b,0xf2,0xf3,0x8e,0x96,0xad,0x82,0xfd,0xe5,0x67,0xdf,0x88,0x67,0x08,0x50,0x28, 0xbe,0x16,0xfa,0x08,0x3d,0x63,0xeb,0xcf,0x08,0x48,0x94,0x0c,0xe8,0xfb,0x36,0x40, 0xa2,0xf0,0xbf,0x7b,0xe4,0xaf,0x26,0x20,0xec,0xcb,0xc3,0x01,0xc8,0x0f,0xd9,0xd0, 0x33,0xaf,0x85,0x4c,0xfc,0xbd,0x68,0xc2,0xe2,0x1d,0x62,0x06,0xb4,0x67,0x41,0x0b, 0x9e,0x29,0x80,0xdf,0x9c,0x90,0x20,0x19,0x70,0x73,0x2b,0x19,0xd0,0x3d,0x2a,0xd8, 0xd7,0x6d,0x80,0x44,0xd9,0xff,0x76,0xf8,0xff,0x5a,0x1e,0x0c,0x40,0xee,0xc8,0x1b, 0x6c,0x5e,0x0e,0xb9,0xf8,0x27,0xe2,0x11,0xb9,0xa6,0x53,0xc5,0x0c,0x74,0x24,0x6f, 0x00,0xc0,0x0f,0xc6,0x7a,0x92,0x01,0x75,0x1b,0x40,0x0f,0x09,0x6a,0x95,0x62,0x1b, 0xc0,0x17,0x03,0x90,0x2c,0xfb,0x5f,0x43,0x0f,0x6f,0xf3,0x60,0x00,0x72,0x43,0xde, 0xdc,0x78,0x2d,0x7e,0xd4,0xc4,0xdf,0xcb,0x4c,0xb9,0xc6,0x8b,0xc5,0x0c,0xec,0x4c, 0xde,0x00,0x40,0xae,0xcc,0x13,0xfa,0xc6,0xd6,0x1d,0x12,0x94,0x68,0x1b,0x20,0x59, 0x35,0x40,0x85,0x7c,0xbf,0xfe,0x2b,0x25,0xc9,0xfe,0xd7,0x4c,0xc4,0xb5,0x3c,0x18, 0x80,0xec,0x91,0x5e,0x9e,0x71,0x61,0x8c,0xba,0xf8,0x7b,0xd1,0x3c,0x87,0xeb,0x64, 0xab,0xa0,0x9f,0x98,0x81,0x3a,0xcc,0x03,0x80,0x4c,0x51,0xad,0xed,0x9f,0x64,0x1b, 0x20,0x59,0x35,0x40,0x5e,0x79,0x00,0xc9,0xf6,0xff,0xdd,0xd6,0xbf,0x47,0xf2,0x50, 0x00,0xb2,0x47,0x5e,0x1e,0x33,0xa3,0x0c,0xc5,0xdf,0xcb,0x7c,0xb9,0x07,0xff,0x15, 0x33,0x70,0xa4,0x44,0x07,0x9a,0x33,0x2f,0x00,0xd2,0x71,0xb6,0xb3,0x0d,0x90,0xac, 0x1a,0xa0,0x81,0x9f,0x79,0x00,0x89,0xf6,0xff,0xeb,0x3a,0x7b,0x0d,0xda,0x80,0x60, 0x34,0x0f,0x04,0x20,0x3b,0x24,0x4e,0x67,0xa6,0x21,0xfe,0x09,0x99,0x22,0xf7,0xe5, 0x64,0x31,0x03,0x1d,0x98,0x27,0x00,0x89,0x18,0x67,0x55,0x03,0xb8,0xad,0x81,0xed, 0xa6,0x40,0x0d,0x1d,0x8d,0xf6,0x25,0x0f,0xa0,0x42,0x8a,0xf2,0x3f,0x3d,0x8d,0xe8, 0x05,0x1e,0x08,0x40,0xe6,0x88,0x3d,0x37,0x8f,0x23,0xfe,0x19,0xf1,0xac,0xdc,0xa7, 0x0b,0xc5,0x0c,0x74,0x97,0xad,0x82,0xca,0xcc,0x1d,0x00,0xe5,0x65,0xa7,0xf2,0xce, 0x6d,0x0a,0xb4,0x9d,0x20,0x7e,0x39,0xde,0x14,0x68,0xe3,0x14,0xe5,0x80,0x39,0x19, 0x80,0x44,0x87,0xff,0xb8,0xfb,0xff,0xba,0xe7,0xf0,0x3d,0x0f,0x04,0x20,0x33,0xb4, 0xbf,0xfe,0xa3,0x88,0x7f,0x4e,0xbc,0x21,0xf7,0xed,0x5a,0xd9,0x2a,0xe8,0x2b,0x66, 0xa0,0x16,0x73,0x09,0xca,0x17,0xd5,0xdc,0xfd,0x85,0x3d,0x85,0x5d,0xd3,0xe4,0x01, 0x78,0x0f,0x07,0xf2,0x6d,0xff,0xbf,0xa9,0xf3,0x0f,0xf3,0x40,0x00,0x32,0x40,0x9b, 0xe4,0x4c,0x46,0xfc,0x7d,0xcb,0x1b,0x18,0x2f,0x66,0x60,0xa0,0x44,0x07,0x9a,0x32, 0xb7,0xa0,0xfc,0xf8,0x87,0x55,0x0e,0xe8,0xcd,0x03,0x68,0xea,0x57,0x1e,0x40,0xaa, 0xfa,0x7f,0xdd,0x6b,0x38,0x9c,0x07,0x01,0x90,0x1e,0xfd,0x62,0x7d,0x40,0x04,0x0b, 0xf1,0x2e,0x0c,0x6a,0xac,0xfe,0x4f,0xcc,0x40,0x3b,0xe6,0x1a,0x94,0x07,0x67,0x3a, 0x79,0x00,0xbb,0x7b,0xf2,0x00,0x5a,0x59,0x79,0x00,0x79,0xf7,0x03,0xf0,0x1a,0x00, 0x6f,0xfd,0xff,0x39,0x3c,0x08,0x80,0xd4,0xc8,0x1b,0x68,0x26,0x21,0xfe,0x45,0x43, 0x2b,0x2b,0x2e,0x10,0x33,0xa0,0x07,0x2a,0x55,0x62,0xfe,0x41,0x34,0x19,0x1e,0x5b, 0x77,0x00,0x5f,0x26,0xfd,0x00,0xf2,0x32,0x00,0xa9,0x12,0x00,0xc7,0xf0,0x20,0x00, 0x92,0x23,0xf1,0x37,0x73,0x17,0xe2,0x5f,0x32,0xb4,0xb5,0xf2,0x48,0xb9,0xff,0xfb, 0x88,0x19,0xa8,0xc9,0x7c,0x84,0xe8,0x30,0xde,0x49,0x04,0xec,0x1d,0x5b,0x7f,0x3a, 0xa0,0xef,0x89,0x80,0x5e,0x03,0x50,0xdb,0xf9,0x4b,0xdd,0x04,0xc0,0x29,0x3c,0x08, 0x80,0xc4,0x88,0xed,0x8e,0xf7,0xc5,0x47,0x88,0x83,0xc1,0x3c,0x31,0x03,0xe3,0xe4, 0x79,0x1c,0x2e,0xd1,0x81,0xc6,0xcc,0x4f,0x08,0x37,0x8f,0x59,0x89,0x80,0xc9,0x1a, 0x02,0xd5,0xb3,0x12,0x01,0xf3,0x32,0x00,0x89,0x3a,0x00,0xea,0xe1,0x03,0xcf,0xf3, 0x20,0x00,0xfe,0x8e,0xbc,0x30,0x66,0x02,0xe2,0x1f,0x58,0x16,0x89,0x19,0xd0,0x9c, 0x8c,0x13,0xc4,0x0c,0xb4,0x65,0xbe,0x42,0x38,0x4b,0x01,0x0f,0x88,0xad,0x3f,0x1e, 0xb8,0xab,0xd0,0x49,0x68,0xeb,0x68,0x73,0xb2,0x8e,0x80,0x59,0x19,0x00,0x6f,0x0b, 0x60,0xbb,0x02,0x40,0xb3,0x0d,0x17,0xf0,0x20,0x00,0x36,0x44,0xfb,0xdc,0x8f,0x43, 0xfc,0x43,0xc5,0xd3,0x62,0x08,0xce,0x13,0x33,0xd0,0x55,0xb6,0x0a,0x2a,0x32,0x87, 0x21,0xf8,0x2c,0x12,0x0e,0x14,0xf6,0xc9,0xa2,0x12,0x20,0xeb,0x52,0xc0,0x54,0x2d, 0x80,0xf5,0x1f,0xf9,0x82,0x07,0x01,0xb0,0xa1,0xf8,0x8f,0x45,0xfc,0x43,0xcd,0xab, 0x62,0x06,0xae,0x92,0x67,0xd8,0x5b,0xcc,0x40,0x0d,0xe6,0x34,0x04,0x93,0x2f,0x85, 0x83,0xac,0x4a,0x00,0x3d,0x19,0x70,0x9b,0xd8,0xba,0x93,0x01,0xd3,0xb5,0x04,0xce, 0xc9,0x00,0x78,0x8f,0x00,0xd6,0x72,0x83,0x1f,0x79,0x10,0x00,0xeb,0xd0,0x4e,0x75, 0xff,0x41,0xfc,0x23,0xc5,0x5c,0x31,0x03,0x6a,0xe8,0xfa,0x8b,0x19,0x68,0xc8,0x1c, 0x87,0xe0,0xa0,0xda,0x7b,0x70,0x6c,0xc3,0x96,0xc0,0xae,0x01,0x68,0x15,0xfb,0xfb, 0xd1,0xc0,0x59,0x1b,0x80,0x74,0x3d,0x00,0x5a,0x0b,0x7f,0xf0,0x20,0x00,0x62,0xf1, 0x72,0xb3,0x1b,0x10,0xff,0xc8,0xe7,0x0d,0xdc,0x2b,0xcf,0xf8,0x58,0xd9,0x2a,0x68, 0xcd,0x9c,0x87,0xd2,0xa2,0xda,0x7b,0x48,0x6c,0xdd,0xd1,0xc0,0x3d,0x9d,0x52,0xc0, 0x44,0x67,0x02,0xe4,0xdc,0x0b,0x20,0x13,0x03,0xb0,0x9a,0x07,0x01,0xe5,0x8e,0xee, 0x19,0x8f,0x42,0xfc,0xcb,0x0e,0x3d,0xcc,0xe9,0x2c,0x31,0x03,0x9d,0x25,0x3a,0x50, 0x81,0xf7,0x00,0x8a,0xcb,0x6a,0xc7,0x00,0x24,0xea,0x05,0x50,0x30,0x03,0x60,0x37, 0x01,0x6a,0xc3,0x43,0x00,0xc4,0x3f,0x16,0x3f,0xd7,0x1e,0x41,0x2c,0x6f,0x5e,0x12, 0x33,0x70,0x85,0xcc,0x83,0x9e,0x62,0x06,0xaa,0xf1,0x5e,0x40,0x71,0xe8,0xef,0x18, 0x00,0x3d,0x14,0xa8,0x7b,0x8a,0x66,0x40,0xbe,0x18,0x80,0x5a,0x18,0x00,0x80,0xf5, 0xe8,0x57,0xdf,0xc8,0x0c,0xc5,0xff,0xc3,0x6d,0xb6,0x37,0xbf,0x3e,0xfd,0x8c,0x59, 0xb9,0x64,0x89,0xf9,0xee,0xca,0x11,0xe6,0xa3,0x2e,0xdd,0x10,0xce,0x88,0x32,0x47, 0xcc,0xc0,0x8d,0x32,0x2f,0x0e,0x12,0x33,0x50,0x8f,0xf7,0x04,0x0a,0x6b,0x00,0x12, 0x9d,0x0a,0xe8,0x4b,0x37,0x40,0x0c,0x00,0x40,0x0a,0xf1,0x1f,0x91,0x81,0xf8,0xbf, 0xd7,0x6c,0x13,0xf3,0xe3,0xed,0x77,0x98,0xb5,0x6b,0xd6,0x18,0xef,0xf8,0xeb,0x93, 0x4f,0xcc,0xf2,0xd1,0x37,0x98,0x65,0x3d,0x7a,0x99,0xc5,0x15,0xab,0x22,0x9e,0x11, 0x64,0xa1,0x98,0x01,0xed,0x04,0x39,0x48,0xb6,0x0a,0x36,0xe5,0xbd,0x01,0x7f,0x19, 0x10,0xdb,0xb0,0x1b,0xa0,0xef,0x06,0xc0,0xed,0x02,0x68,0x1b,0x00,0xb7,0x0d,0xf0, 0x66,0x3c,0x00,0x28,0x57,0xf1,0xbf,0x2a,0x9d,0xf8,0x57,0xaa,0x66,0xbe,0x3a,0xe5, 0x34,0xb3,0xfa,0xa7,0x9f,0x4c,0x26,0x63,0xd5,0x37,0xdf,0x98,0x1f,0x6e,0x1b,0x6f, 0x3e,0xe9,0xb3,0xaf,0x59,0x5c,0xb5,0x26,0xe2,0x19,0x51,0xa6,0x8a,0x21,0x38,0x5d, 0xcc,0xc0,0xd6,0x12,0x1d,0xe0,0x5d,0x02,0x1f,0x0c,0xc0,0x7e,0x09,0x0c,0x80,0xdd, 0x0e,0xd8,0x36,0x00,0x59,0x75,0x03,0xc4,0x00,0x00,0x24,0x60,0x78,0x1a,0xf1,0xff, 0x70,0xdb,0x2e,0xe6,0x8f,0x39,0x73,0x4c,0xae,0x43,0x4d,0xc3,0x4f,0xf7,0x4e,0x32, 0x9f,0x1d,0x72,0xa8,0x59,0x52,0x73,0x23,0x84,0x33,0xa2,0xbc,0x20,0x66,0xe0,0x52, 0x31,0x03,0x3d,0xc4,0x0c,0x54,0xe1,0xbd,0x82,0xfc,0x0c,0x80,0xb6,0x03,0xd6,0xf3, 0x00,0x3a,0x16,0xc2,0x00,0x54,0xc7,0x00,0x00,0xc4,0xcc,0xb0,0x54,0xe2,0x5f,0xa5, 0x86,0xf9,0xf6,0xd2,0xcb,0xcd,0xda,0xbf,0xfe,0x32,0x7e,0x8d,0x35,0x7f,0xfc,0x61, 0x7e,0x79,0xe4,0x51,0xf3,0xf9,0xbf,0x06,0x99,0x77,0xeb,0x37,0x46,0x38,0x23,0xca, 0x9b,0x62,0x06,0x46,0xcb,0xdc,0xda,0x5f,0xcc,0x40,0x5d,0xde,0x33,0xf0,0xdf,0x00, 0x54,0xf7,0xc3,0x00,0xd4,0xc3,0x00,0x00,0xe2,0xff,0x77,0x96,0xb6,0xdb,0xca,0xac, 0x78,0xfb,0x6d,0x53,0xc8,0xa1,0xc6,0xe2,0xd7,0x67,0x66,0x98,0x2f,0x4f,0x3c,0x29, 0x9e,0x5b,0x80,0x70,0x46,0x93,0x77,0xc4,0x0c,0xe8,0x21,0x52,0xff,0x92,0xe8,0x40, 0x0b,0xde,0x3b,0xc8,0xcf,0x00,0xd4,0xc3,0x00,0x00,0xe4,0xc9,0xe5,0x29,0xc4,0xff, 0x8b,0x63,0xfe,0x6d,0xd6,0xfc,0xf6,0x9b,0x29,0xe6,0xd0,0xa4,0xc2,0xdf,0x5f,0x7e, 0xc5,0x7c,0x7d,0xd6,0x39,0xe6,0x83,0x36,0x5b,0x20,0x9c,0x11,0xe6,0x11,0x31,0x04, 0xa7,0x8a,0x19,0xe8,0xc0,0x7b,0x08,0x1b,0x72,0xa8,0x63,0x00,0xf6,0xc4,0x00,0x00, 0x14,0x08,0xdd,0xa7,0x4d,0xb4,0x30,0x2f,0xa9,0x51,0xc7,0xfc,0x74,0xd7,0xdd,0x26, 0x08,0x63,0xc5,0xdc,0xb9,0xe6,0xdb,0x8b,0x2f,0x35,0x4b,0xb7,0xda,0x16,0xd1,0x8c, 0x30,0x33,0xc5,0x0c,0x5c,0x24,0xf3,0x71,0x67,0xd9,0x2a,0xa8,0xcc,0xbb,0x89,0x01, 0xd8,0xf0,0x48,0x60,0x0c,0x00,0x40,0x31,0xc4,0xff,0x83,0xd6,0x6d,0x0b,0x1e,0xf2, 0xcf,0x75,0xac,0x7c,0xef,0x3d,0xf3,0xdd,0x88,0x91,0xe6,0xa3,0x1d,0x76,0x32,0x8b, 0x2b,0x20,0x9a,0x51,0x65,0xb6,0x98,0x01,0x6d,0x42,0xd5,0x57,0xcc,0x40,0x6d,0xde, 0x55,0x0c,0x00,0x06,0x00,0xc0,0x3f,0x2e,0x49,0x22,0xfe,0x5a,0xb7,0xbf,0x6a,0xf9, 0x72,0x13,0x86,0xf1,0xd7,0x67,0x9f,0x99,0xef,0x6f,0xbc,0xc9,0x7c,0xdc,0xb3,0x77, 0xbc,0x34,0x11,0xe1,0x8c,0x26,0xf3,0xc5,0x0c,0x4c,0x10,0x33,0x70,0x84,0xcc,0xd9, 0x66,0xbc,0xbb,0x18,0x00,0x0c,0x00,0x80,0xff,0xe2,0xaf,0xd9,0xf8,0x6b,0xff,0xfc, 0x33,0x67,0x41,0x1e,0x3a,0x74,0xa8,0xa9,0x5d,0xbb,0xb6,0xe9,0xd5,0xab,0x97,0x19, 0x3b,0x76,0xac,0xf9,0xfa,0xeb,0xaf,0x8b,0x66,0x06,0x56,0x7d,0xf7,0x9d,0xf9,0x71, 0xc2,0x7f,0xcd,0xa7,0xfb,0x1e,0x60,0x96,0x54,0xab,0x85,0x70,0x46,0x98,0xc9,0x62, 0x08,0xfe,0x4f,0xe6,0x70,0x3b,0xde,0x65,0x0c,0x00,0x06,0x00,0x20,0x7f,0xf1,0xff, 0x66,0xe8,0x45,0x79,0x8b,0xb0,0x8a,0xbf,0xfd,0x6f,0x55,0xac,0x58,0xb1,0x24,0x66, 0x60,0xf5,0x2f,0xbf,0x98,0x9f,0xee,0xbb,0xdf,0x7c,0x76,0xe8,0x40,0xb3,0xa4,0x76, 0x3d,0x44,0x33,0xc2,0xcc,0x10,0x33,0x70,0x81,0xcc,0xe9,0x6e,0xb2,0x55,0x50,0x89, 0xf7,0x1b,0x03,0x80,0x01,0x00,0xc8,0x4e,0xfc,0xb5,0x7f,0xbf,0x1f,0x43,0x23,0x00, 0x2a,0xfa,0x89,0xfe,0xed,0x52,0x99,0x81,0x35,0x2b,0x56,0x98,0x5f,0x1e,0x7b,0xdc, 0x7c,0x31,0xe8,0x58,0xf3,0x6e,0x83,0x26,0x88,0x66,0x84,0x79,0x4d,0xcc,0xc0,0xd5, 0xb2,0x55,0xb0,0xb7,0x98,0x81,0x9a,0xbc,0xef,0x18,0x00,0x0c,0x00,0x40,0xea,0x84, 0x3f,0xed,0xd7,0xef,0xe7,0xf8,0xea,0xab,0xaf,0xcc,0x4d,0x37,0xdd,0x64,0x76,0xdf, 0x7d,0xf7,0xb4,0x66,0xe0,0x96,0x5b,0x6e,0x29,0xaa,0x19,0x58,0xbb,0x6a,0x95,0xf9, 0xed,0xd9,0xe7,0xcc,0x57,0x27,0x9d,0x62,0xde,0x6f,0xb1,0x29,0xa2,0x19,0x61,0xe6, 0x89,0x19,0xb8,0x55,0xcc,0xc0,0x61,0x32,0xef,0x1b,0xf3,0xfe,0x63,0x00,0x30,0x00, 0x80,0xf8,0x5b,0x48,0x06,0xfd,0x0f,0xb7,0xde,0x56,0x50,0xc1,0xcd,0xc6,0x0c,0x14, 0x3b,0x32,0xb0,0x76,0xed,0x5a,0xf3,0xfb,0x6b,0xaf,0x9b,0xaf,0xcf,0x3d,0xdf,0x7c, 0xb0,0x79,0x3b,0x44,0x33,0xc2,0x2c,0x12,0x33,0x70,0xbf,0x98,0x81,0xe3,0xe5,0x3d, 0x68,0xcb,0x7a,0x80,0x01,0xc0,0x00,0x40,0xb9,0x70,0x59,0xa2,0x26,0x3f,0x92,0x31, 0xff,0xe3,0xc4,0xbb,0x8a,0x9a,0xb1,0x1f,0x64,0x33,0x10,0xef,0x35,0x30,0x7f,0x7e, 0xbc,0xd5,0xb1,0x1e,0x6d,0x8c,0x68,0x46,0x9b,0xe9,0x62,0x08,0xce,0x13,0x33,0xd0, 0x55,0xb6,0x0a,0x2a,0xb2,0x46,0x60,0x00,0x30,0x00,0x50,0x4e,0x1d,0xfe,0x72,0xfd, 0xf2,0xff,0x44,0x8e,0xf8,0xdd,0x73,0xcf,0x3d,0x4d,0xb5,0x6a,0xd5,0xcc,0xf6,0xdb, 0x6f,0x6f,0x86,0x0f,0x1f,0x6e,0x16,0x2d,0x5a,0x14,0x39,0x33,0xf0,0xe7,0xd2,0xa5, 0x66,0xf9,0x35,0xd7,0x99,0x65,0x3b,0xed,0x42,0xaf,0x81,0x88,0xf3,0x8a,0x98,0x01, 0x3d,0xfd,0xb2,0xb7,0x98,0x81,0xea,0xac,0x19,0x18,0x00,0x0c,0x00,0x44,0x81,0x64, 0xbd,0xfd,0xbf,0xbd,0xe4,0xb2,0x9c,0x85,0xb1,0x77,0xef,0xde,0x09,0xff,0xad,0x2d, 0xb7,0xdc,0xd2,0x0c,0x19,0x32,0xc4,0xbc,0xf1,0xc6,0x1b,0xf1,0xd0,0x7a,0x94,0xcc, 0xc0,0x5f,0x5f,0x7c,0x61,0xbe,0xbf,0xf9,0x16,0xf3,0x71,0xef,0xbd,0xcd,0xe2,0xca, 0xd5,0x11,0xcd,0x08,0x33,0x57,0xcc,0xc0,0xcd,0xf2,0xde,0xf4,0x17,0x33,0xa0,0x79, 0x03,0xf5,0x59,0x47,0x30,0x00,0x00,0x61,0x42,0x26,0xb6,0xb9,0x22,0x89,0xf8,0x7f, 0x79,0xdc,0x89,0x79,0x89,0xa1,0x7e,0xf9,0xa7,0xfb,0xf7,0x37,0xde,0x78,0x63,0x73, 0xea,0xa9,0xa7,0x9a,0xe7,0x9e,0x7b,0xce,0xac,0x5e,0xbd,0x3a,0x52,0x66,0x60,0xf5, 0xf7,0xdf,0x9b,0x1f,0xef,0xb8,0xd3,0x7c,0xba,0xff,0x41,0x66,0x49,0xf5,0xda,0x88, 0x66,0x84,0x79,0x4e,0xcc,0xc0,0x34,0x41,0xdf,0x25,0x4e,0x30,0xc4,0x00,0x00,0x84, 0x42,0xfc,0xaf,0x4c,0x22,0xfe,0x9f,0x1e,0x70,0xb0,0x59,0x9b,0xa5,0x20,0x7b,0x87, 0x86,0xff,0xb3,0xf9,0x79,0x1a,0x36,0x6c,0x68,0x8e,0x39,0xe6,0x18,0xf3,0xd8,0x63, 0x8f,0x99,0x15,0x52,0x8e,0x97,0xcd,0x50,0x71,0x0f,0xb2,0x19,0x58,0xf3,0xeb,0xaf, 0xe6,0xe7,0x07,0x1f,0x32,0x9f,0x0f,0x3c,0xd2,0xbc,0x5b,0xa7,0x3e,0xa2,0x19,0x61, 0xae,0x91,0x77,0x8a,0xf5,0x05,0x03,0x00,0x10,0x68,0xf1,0x1f,0x91,0x44,0xfc,0x97, 0x75,0xdf,0xd5,0xac,0xf9,0xe3,0x8f,0xbc,0x45,0x4f,0x73,0x00,0xf6,0xd8,0x63,0x8f, 0x9c,0x7e,0x3e,0x6d,0x12,0x74,0xe8,0xa1,0x87,0x9a,0xfb,0xee,0xbb,0xcf,0xfc,0xfc, 0xf3,0xcf,0xd1,0x32,0x03,0x2b,0x57,0x9a,0x5f,0x9e,0x78,0xd2,0x7c,0x31,0xf8,0x38, 0xf3,0x5e,0xa3,0x66,0x88,0x66,0x04,0xab,0x08,0x5a,0xb1,0xc6,0x60,0x00,0x00,0x82, 0x2a,0xfe,0x57,0x27,0x11,0xff,0xf7,0x9a,0x6d,0x62,0x56,0x49,0x68,0xdd,0xcf,0xb1, 0x6c,0xd9,0x32,0x73,0xfd,0xf5,0xd7,0x9b,0x5d,0x77,0xdd,0x35,0xa9,0x20,0xa7,0xa2, 0x6a,0xd5,0xaa,0xa6,0x6f,0xdf,0xbe,0x66,0xfc,0xf8,0xf1,0xe6,0x9b,0x6f,0xbe,0x89, 0x94,0x19,0xd0,0x28,0xcb,0x6f,0xb3,0x9e,0x37,0x5f,0x9d,0x7a,0xba,0x79,0x7f,0x93, 0xd6,0x08,0x68,0x44,0xd0,0xd6,0xc3,0xac,0x35,0x18,0x00,0x80,0x40,0xa1,0x65,0x4c, 0xd7,0x24,0x11,0x7f,0x4d,0x5a,0xfb,0xfd,0xc5,0x97,0x0a,0x2a,0x78,0x2a,0xb0,0xe3, 0xc6,0x8d,0x33,0x7d,0xfa,0xf4,0x89,0x0b,0x7b,0xd6,0x3f,0xbf,0x88,0x75,0x8f,0x1e, 0x3d,0xcc,0xe8,0xd1,0xa3,0xcd,0xc7,0x1f,0x7f,0x9c,0xf5,0xbf,0x7d,0xf3,0xcd,0x37, 0x07,0xd7,0x0c,0x48,0x42,0xe4,0x1f,0x6f,0xcc,0x36,0xdf,0x0c,0x19,0x6a,0x96,0x6e, 0xd9,0x11,0x21,0x0d,0x31,0x77,0xb1,0x0d,0x80,0x01,0x00,0x08,0x9a,0xf8,0x5f,0x97, 0x4c,0xfc,0xb5,0xcb,0xdf,0xa8,0x31,0x79,0x95,0xfa,0x75,0xed,0xda,0xd5,0x8c,0x1c, 0x39,0xd2,0x7c,0xf8,0xe1,0x87,0x19,0xfd,0xd9,0x9f,0x7e,0xfa,0xc9,0xdc,0x7b,0xef, 0xbd,0xa6,0x7f,0xff,0xfe,0xa6,0x56,0xad,0x5a,0x39,0x5d,0x53,0xae,0xe5,0x85,0x41, 0x37,0x03,0xf1,0xa3,0x8c,0x17,0x2e,0x34,0xdf,0x0e,0x1b,0x6e,0x3e,0xec,0xdc,0x15, 0x51,0x0d,0x19,0x6f,0xc9,0x36,0x00,0x6b,0x0e,0x06,0x00,0x20,0x10,0xe8,0xc1,0x27, 0xd7,0xa7,0x10,0xff,0xcf,0x0e,0x3b,0xc2,0xd7,0x52,0x3f,0xd7,0x0c,0x2c,0x95,0x1a, 0xf9,0x8c,0x1a,0xeb,0x48,0xd2,0xdf,0xa3,0x8f,0x3e,0x6a,0x8e,0x3e,0xfa,0x68,0xd3, 0xa0,0x41,0x83,0x9c,0xae,0x31,0xd7,0xf2,0xc2,0x30,0x98,0x81,0x3f,0x3f,0xfa,0xc8, 0x2c,0xbf,0x7e,0xb4,0x59,0xb6,0x4b,0x0f,0xb3,0xb8,0x62,0x55,0x44,0x36,0x04,0x34, 0x65,0xdd,0xc1,0x00,0x00,0x04,0x41,0xfc,0xc7,0xa4,0x10,0xff,0xa5,0x1d,0xb6,0x8e, 0x67,0xa9,0x17,0xaa,0xd4,0xaf,0x4b,0x97,0x2e,0xe6,0xea,0xab,0xaf,0xce,0x38,0x32, 0xb0,0x4a,0x7a,0xf0,0x3f,0xfb,0xec,0xb3,0xe6,0xe4,0x93,0x4f,0x8e,0x97,0x09,0xe6, 0x72,0xcd,0x9b,0x6c,0xb2,0x89,0x39,0xe5,0x94,0x53,0xcc,0xcc,0x99,0x33,0xb3,0x2a, 0x2f,0xcc,0xd4,0x0c,0xf4,0xec,0xd9,0xb3,0x64,0x66,0x40,0x73,0x34,0x7e,0xb8,0x65, 0x9c,0xf9,0x64,0xaf,0x3e,0x66,0x71,0x95,0x1a,0x88,0x6d,0x40,0xd9,0x51,0xfa,0x03, 0xb0,0xfe,0x60,0x00,0x00,0x4a,0x46,0x65,0xe1,0xc6,0x14,0xe2,0xaf,0x02,0xb2,0x62, 0xde,0xbc,0xa2,0x95,0xfa,0x65,0x6b,0x06,0xf4,0x4b,0xfe,0xf5,0xd7,0x5f,0x37,0xe7, 0x9d,0x77,0x9e,0xd9,0x62,0x8b,0x2d,0x72,0xba,0x07,0x5a,0x5e,0x38,0x68,0xd0,0xa0, 0xac,0xcb,0x0b,0xc3,0x60,0x06,0x56,0xff,0xf0,0x83,0xf9,0xe9,0xae,0xbb,0xcd,0xa7, 0x07,0xf5,0x37,0x4b,0x6a,0xd4,0x41,0x78,0x03,0xc4,0xfe,0x18,0x00,0x0c,0x00,0x40, 0xa9,0x90,0xc9,0x6a,0xfe,0x93,0x4a,0xfc,0xf5,0x68,0xdf,0xe1,0x57,0xe5,0x5d,0xea, 0xa7,0xa1,0xf1,0x5c,0x7e,0xbe,0x6c,0xcd,0x80,0x8e,0x05,0x0b,0x16,0x98,0x61,0xc3, 0x86,0x99,0xed,0xb6,0xdb,0x2e,0xaf,0xf2,0xc2,0x49,0x93,0x26,0x65,0x55,0x5e,0xe8, 0x9a,0x01,0x15,0xfb,0xa0,0x9a,0x81,0x35,0xbf,0xff,0x6e,0x7e,0x9e,0x3c,0xc5,0x7c, 0x7e,0xe4,0x51,0xe6,0xdd,0xba,0x0d,0x11,0xe1,0x12,0x33,0x88,0x4a,0x00,0x0c,0x00, 0x40,0xa9,0xc4,0x7f,0x6c,0x1a,0xf1,0xff,0x68,0x87,0x9d,0xe2,0x47,0xde,0xfa,0x31, 0x74,0xaf,0xff,0xaa,0xab,0xae,0xca,0x59,0x98,0xd5,0x0c,0x64,0x93,0x40,0xe8,0x96, 0x17,0x8e,0x1a,0x35,0xaa,0xe8,0xe5,0x85,0x61,0x30,0x03,0x6b,0xff,0xfc,0xd3,0xfc, 0xfa,0xd4,0xf4,0x78,0x37,0xc7,0xf7,0x9a,0xb4,0x40,0x90,0x4b,0xc0,0x59,0x18,0x00, 0x0c,0x00,0x40,0x29,0xc4,0xff,0xd6,0x34,0xe2,0xaf,0xad,0x69,0x57,0x2e,0x5e,0x5c, 0x10,0xf1,0x29,0x85,0x19,0x50,0x01,0xcf,0xb7,0xbc,0x70,0xb7,0xdd,0x76,0xcb,0xba, 0xbc,0x30,0x14,0x66,0x60,0xcd,0x1a,0xf3,0xfb,0x0b,0x2f,0x9a,0xaf,0xcf,0x38,0xcb, 0xbc,0xdf,0x6a,0x73,0xc4,0xb9,0x48,0x5c,0x82,0x01,0xc0,0x00,0x00,0x14,0x93,0xaa, 0xc2,0x6d,0x69,0xc4,0x3f,0x5e,0xf2,0x77,0xed,0xf5,0x45,0x11,0x1f,0x3f,0xcc,0x40, 0xb6,0xdb,0x04,0x1a,0xda,0xd7,0xf2,0xc2,0x01,0x03,0x06,0xe4,0x55,0x5e,0x78,0xc5, 0x15,0x57,0x64,0x55,0x5e,0x98,0x8d,0x19,0xd0,0xdf,0x57,0x0a,0x33,0xa0,0xe3,0x8f, 0xb7,0xe6,0x98,0x6f,0x86,0x5e,0x64,0x96,0xb6,0xef,0x84,0x50,0xd3,0x12,0x18,0x03, 0x80,0x01,0x80,0x28,0x50,0x4d,0x98,0x90,0x81,0xf8,0x7f,0xd4,0x6d,0xe7,0xf8,0x57, 0x61,0xb1,0x47,0x29,0xcc,0x80,0x26,0xfd,0x4d,0x9d,0x3a,0x35,0xef,0xf2,0xc2,0xf3, 0xcf,0x3f,0x3f,0xab,0xf2,0xc2,0xa0,0x9b,0x01,0x4d,0xfc,0xfc,0x64,0xef,0xbe,0x08, 0x75,0x01,0xb9,0x19,0x03,0x80,0x01,0x00,0x28,0x06,0x7a,0x36,0xf9,0x1d,0x19,0x88, 0xbf,0xd6,0x90,0xff,0xf1,0xe6,0x5b,0xa6,0xd4,0xa3,0x14,0x66,0xc0,0x8f,0xf2,0x42, 0xfd,0x73,0x5a,0x5e,0xa8,0xa7,0x17,0xae,0xca,0x30,0x7f,0x22,0x53,0x33,0x30,0x74, 0xe8,0xd0,0xc2,0x1f,0x57,0xfc,0xf9,0xe7,0xe6,0x8b,0xa3,0x8e,0xa1,0x97,0x40,0x11, 0x98,0x80,0x01,0xc0,0x00,0x00,0x14,0x9a,0x9a,0xc2,0xc4,0x4c,0xc4,0x5f,0x8f,0xf8, 0xfd,0xf7,0x09,0x39,0x8b,0x87,0x0a,0x94,0x66,0xd1,0x6b,0x59,0xdc,0x98,0x31,0x63, 0xe2,0x15,0x00,0x7e,0x99,0x81,0x11,0x23,0x46,0x14,0xd5,0x0c,0xb8,0xe5,0x85,0xfa, 0x65,0xaf,0x5f,0xf8,0xc5,0x2a,0x2f,0x4c,0x65,0x06,0xf4,0xde,0x16,0x2c,0x0f,0x40, 0xcc,0xca,0xf2,0xeb,0x46,0x99,0x25,0xb5,0xeb,0x21,0xce,0xb4,0x03,0xc6,0x00,0x60, 0x00,0x20,0x2a,0xe2,0x7f,0x77,0x86,0xe2,0xff,0x6e,0xbd,0x46,0x66,0xd5,0xb7,0xdf, 0xe6,0x2c,0x22,0x2a,0x50,0x89,0xc4,0x57,0x5b,0xf1,0x2e,0xf6,0x29,0xa1,0xb0,0x14, 0x66,0x40,0xc7,0x42,0x69,0xbb,0x9b,0x4f,0x79,0xa1,0xe6,0x1a,0x68,0xce,0x41,0x36, 0xe5,0x85,0xb6,0x19,0xd0,0x7b,0x5b,0xa8,0x08,0xc0,0xef,0xaf,0xbe,0x66,0x96,0x6e, 0xb5,0x2d,0xa2,0x5c,0x64,0x1e,0xc0,0x00,0x60,0x00,0x00,0x0a,0x85,0x4c,0x42,0x33, 0x29,0x43,0xf1,0x57,0xbe,0x1f,0x73,0x63,0x5e,0x42,0xa2,0x02,0x95,0xaa,0xdc,0xae, 0x5d,0xbb,0x76,0xe6,0x82,0x0b,0x2e,0x30,0xb3,0x67,0xcf,0x0e,0xb5,0x19,0x70,0xcb, 0x0b,0xb5,0x2a,0x20,0x9f,0xf2,0xc2,0xdb,0x6e,0xbb,0x2d,0xeb,0xd3,0x0b,0x7d,0xed, 0x0b,0x20,0x47,0x3a,0x7f,0x7d,0xd6,0x39,0x84,0xfb,0x4b,0xc4,0xc3,0x9c,0x07,0x80, 0x01,0x00,0x28,0x04,0xb5,0x85,0xfb,0xb2,0x10,0x7f,0xfd,0x02,0xf4,0xa3,0xe6,0x5f, 0x05,0x4d,0x85,0x2d,0x5d,0xb9,0x5d,0xcb,0x96,0x2d,0xcd,0xa9,0xa7,0x9e,0x6a,0x66, 0xcd,0x9a,0x95,0x55,0x2b,0xde,0xa0,0x99,0x81,0x4c,0xaf,0x37,0x5d,0x79,0xa1,0x1a, 0x0a,0x35,0x16,0x45,0xcb,0xf4,0x9f,0xfd,0xa6,0xf9,0x60,0x8b,0x0e,0x08,0x71,0x09, 0x99,0x8a,0x01,0xc0,0x00,0x00,0xf8,0xcd,0x46,0xc2,0x83,0x59,0x88,0xbf,0xf2,0xeb, 0xb4,0xa7,0x7c,0x17,0x19,0x0d,0x75,0x6b,0xc8,0x5b,0x43,0xdf,0x89,0xb6,0x07,0x5c, 0x1a,0x35,0x6a,0x64,0x06,0x0f,0x1e,0x6c,0x1e,0x7f,0xfc,0x71,0xb3,0x72,0xe5,0xca, 0xd0,0x9a,0x01,0x3f,0xca,0x0b,0xf7,0xd8,0x63,0x0f,0xdf,0x72,0x27,0x92,0xe5,0x36, 0x2c,0x1f,0x79,0x2d,0x67,0x04,0x04,0x80,0x27,0x30,0x00,0x18,0x00,0x00,0x3f,0xa9, 0x2b,0x4c,0x96,0x85,0x25,0x9b,0x85,0x68,0xd9,0x4e,0xbb,0x14,0xbe,0xac,0xcc,0x29, 0xb7,0xd3,0xa4,0x38,0x4d,0x8e,0x4b,0xd5,0x8a,0xf7,0xb0,0xc3,0x0e,0x33,0xf7,0xdf, 0x7f,0xbf,0xf9,0xe5,0x97,0x5f,0x7c,0x33,0x03,0x5a,0xb7,0x5f,0x4c,0x33,0x60,0x5f, 0x6f,0xb6,0xe5,0x85,0x7a,0x7e,0x42,0x41,0x0e,0x09,0xfa,0xee,0xbb,0x75,0x07,0x04, 0x21,0xbe,0x81,0xe0,0x29,0x0c,0x00,0x06,0x00,0xc0,0x4f,0xf1,0x9f,0x92,0xa5,0xf8, 0xc7,0xbf,0xfe,0x9f,0x99,0x51,0xdc,0x03,0x6a,0x24,0xe4,0xaf,0x65,0x72,0x5a,0x2e, 0xa7,0xa7,0xf2,0xa5,0xda,0x2b,0xef,0xd7,0xaf,0x9f,0x99,0x30,0x61,0x82,0xf9,0x36, 0x8f,0xe4,0xc4,0x52,0x9b,0x01,0x2d,0x07,0xd4,0xeb,0xcd,0xb4,0xbc,0x50,0x4f,0x50, 0xf4,0x3d,0xe4,0x2f,0xa5,0x9d,0xef,0x6f,0xba,0x19,0xc2,0x1b,0x20,0x9e,0xc6,0x00, 0x60,0x00,0x00,0xfc,0xa0,0xbe,0xf0,0x68,0x0e,0xe2,0xbf,0x6c,0xd7,0xdd,0x73,0x3a, 0xe0,0x47,0xbf,0x52,0x55,0xa8,0xba,0x76,0xed,0x9a,0x75,0x5b,0x5e,0x6f,0x48,0x5a, 0x1b,0xe8,0xa4,0x2b,0xb7,0xd3,0xbd,0x72,0x3f,0xcb,0x0b,0x4b,0x65,0x06,0x32,0x29, 0x2f,0xec,0xdd,0xbb,0xb7,0xaf,0xe2,0xff,0xe3,0xc4,0xbb,0xcc,0x92,0x6a,0xb5,0x10, 0xdd,0x80,0x31,0x03,0x03,0x80,0x01,0x00,0xc8,0x97,0x06,0xc2,0xd4,0x1c,0xc4,0x5f, 0xf9,0x6d,0xe6,0xac,0xac,0x05,0x45,0x05,0x2a,0xd1,0xcf,0xe1,0x9a,0x01,0x15,0xd7, 0x5c,0x87,0x96,0xdb,0x69,0x8b,0xdd,0x74,0xfb,0xf7,0x7e,0x96,0x17,0xe6,0x6b,0x06, 0xf4,0xcf,0xe5,0x62,0x06,0xec,0xeb,0xd5,0xbf,0x43,0x0d,0x95,0x1a,0x2b,0xbf,0x72, 0x00,0xd4,0x6c,0x7c,0x73,0xd1,0x25,0x88,0x2d,0x06,0x00,0x30,0x00,0x10,0x45,0x1a, 0x09,0x8f,0xe7,0x28,0xfe,0x1f,0xf7,0xcc,0xed,0x4b,0x53,0x85,0xaa,0x50,0x5f,0xc8, 0xf6,0xd0,0x43,0x77,0xf4,0xf0,0x9d,0x74,0xe5,0x76,0x76,0x79,0x61,0xa6,0xad,0x78, 0x83,0x68,0x06,0xfc,0x3e,0xed,0xef,0xf3,0x81,0x47,0x22,0xb4,0x01,0xe6,0x39,0x0c, 0x00,0x06,0x00,0x20,0x1f,0xf1,0x7f,0x32,0x47,0xf1,0x8f,0x7f,0xfd,0xcf,0x78,0x36, 0x27,0x71,0xd1,0xaf,0xd4,0x62,0x84,0xcb,0x13,0x95,0xdb,0x69,0xfd,0x7c,0xaa,0x72, 0x3b,0xcd,0x29,0xf0,0xab,0xbc,0x30,0xac,0x66,0x60,0x8d,0x24,0x20,0x7e,0xd2,0x6f, 0x7f,0x44,0x36,0xe0,0xcc,0xc4,0x00,0x60,0x00,0x00,0x72,0x41,0x26,0x96,0x99,0x96, 0x87,0xf8,0x6b,0xdd,0x7f,0xae,0x43,0x43,0xd4,0xbd,0x7a,0xf5,0x2a,0xea,0xde,0x79, 0xa2,0xf2,0xc2,0x43,0x0f,0x3d,0x34,0x65,0x79,0xa1,0x56,0x1b,0x1c,0x73,0xcc,0x31, 0xf1,0xf2,0xc2,0x4c,0x5b,0xf1,0x86,0xdd,0x0c,0xac,0xf9,0xed,0x37,0xf3,0xf1,0x1e, 0x7b,0x21,0xb0,0x18,0x00,0xc0,0x00,0x40,0x14,0x69,0x2a,0x3c,0x95,0x87,0xf8,0x2b, 0x3f,0xdc,0x36,0x3e,0x10,0x07,0xf6,0xe4,0x93,0x40,0xe8,0x96,0xdb,0x69,0xaf,0xfd, 0x4c,0xcb,0x0b,0xef,0xbb,0xef,0xbe,0x8c,0x5b,0xf1,0x16,0xca,0x0c,0x14,0xaa,0xd6, 0x7f,0xb5,0x5c,0xd7,0xb2,0x5d,0x7a,0x20,0xae,0x21,0x61,0x16,0x06,0x00,0x03,0x00, 0x90,0x0d,0xcd,0x84,0xe9,0x79,0x8a,0xff,0x7b,0x0d,0x9b,0xc6,0xdb,0xc0,0x06,0xed, 0xf4,0xbe,0x7c,0xcd,0x40,0xb6,0xe5,0x85,0xe3,0xc7,0x8f,0xcf,0xbb,0xbc,0x30,0x57, 0x33,0xe0,0x77,0xad,0xff,0xea,0xef,0xbf,0x37,0x1f,0x75,0xed,0x86,0xb0,0x62,0x00, 0x00,0x03,0x00,0x51,0xa4,0xb9,0xf0,0x74,0x9e,0xe2,0xaf,0x7c,0x73,0xc1,0x85,0x05, 0x0d,0x43,0x97,0xe2,0x28,0xdf,0x64,0xe5,0x85,0x43,0x86,0x0c,0x49,0x5b,0x5e,0xd8, 0xa3,0x47,0x8f,0x78,0x79,0xa1,0x26,0x1d,0x16,0xcb,0x0c,0xf8,0x59,0xeb,0xaf,0x5f, 0xfe,0x1f,0x76,0xee,0x8a,0xa8,0x86,0x8c,0xe7,0x31,0x00,0x18,0x00,0x80,0x4c,0x68, 0x21,0xcc,0xf0,0x41,0xfc,0x17,0x57,0xae,0x1e,0x3f,0xf3,0xbd,0x58,0x23,0x08,0x66, 0x40,0xc7,0xa2,0x45,0x8b,0xfe,0x57,0x6e,0x57,0x8c,0xf2,0xc2,0x74,0x66,0xc0,0xaf, 0x5a,0x7f,0xcd,0xf6,0x67,0xcf,0x3f,0x9c,0xbc,0x80,0x01,0xc0,0x00,0x00,0x14,0x4d, 0xfc,0x85,0xcf,0xfa,0x1f,0x56,0xb2,0xd2,0xb4,0xa0,0x98,0x01,0xb7,0xbc,0x50,0xbf, 0xfc,0xd3,0x95,0x17,0x6a,0x04,0x21,0xdf,0xf2,0x42,0xbd,0x6e,0xfd,0xb9,0xf5,0xe7, 0xf7,0xb3,0xd6,0x5f,0x7f,0x26,0x4a,0xfd,0x30,0x00,0x80,0x01,0x00,0xc4,0x3f,0x23, 0x7e,0x79,0xfc,0x09,0x13,0x84,0x51,0xaa,0x03,0x7b,0x12,0x95,0x17,0x6a,0x2e,0x40, 0xa6,0xe5,0x85,0x33,0x67,0xce,0xf4,0xe5,0xf4,0x42,0x3f,0x46,0xfc,0x28,0x5f,0x84, 0x14,0x03,0x00,0x18,0x00,0x88,0x1e,0x1b,0xfb,0x2c,0xfe,0xef,0x35,0x69,0xe1,0xcb, 0x91,0xbf,0x51,0x35,0x03,0xd9,0x96,0x17,0x6a,0xf5,0x41,0xbe,0xe5,0x85,0xb9,0x8e, 0xe5,0xd7,0x8f,0x46,0x44,0x31,0x00,0x80,0x01,0x80,0xa8,0x8a,0xff,0xb3,0x3e,0x8a, 0xbf,0xf2,0xf5,0x99,0x67,0xe7,0x24,0x36,0x43,0x87,0x0e,0x8d,0x0b,0xa2,0x9f,0xbd, 0xf8,0x83,0x6e,0x06,0xdc,0xf2,0x42,0x15,0xfa,0x74,0xe5,0x85,0x6a,0x18,0xfc,0x28, 0x2f,0xcc,0x74,0xfc,0xf2,0xc8,0xa3,0x66,0x71,0x05,0x04,0x34,0xec,0xbc,0x88,0x01, 0xc0,0x00,0x00,0x14,0x43,0xfc,0x95,0x15,0x73,0xe7,0xe6,0x24,0x38,0x89,0xbe,0x86, 0xfd,0xec,0xc5,0x1f,0x74,0x33,0xa0,0x21,0x7f,0x0d,0xfd,0x17,0xb3,0xbc,0x30,0xd9, 0xf8,0xf3,0x83,0x0f,0xcc,0xbb,0x75,0x1b,0x22,0xa0,0x11,0xe0,0x25,0x0c,0x00,0x06, 0x00,0xa0,0x18,0xe2,0xff,0xe1,0x36,0xdb,0xe7,0x2c,0x3a,0x1a,0x01,0xc8,0xb4,0x17, 0x7f,0xd4,0xcd,0x80,0x26,0xde,0xe9,0x75,0x6a,0x72,0xa0,0x5e,0x77,0xaa,0xf2,0x42, 0xbd,0x6f,0xbe,0x76,0xf9,0x93,0xde,0x0d,0xfa,0x1c,0x11,0xcf,0x68,0xf0,0x0a,0x06, 0x00,0x03,0x00,0x60,0x27,0xfc,0x15,0x42,0xfc,0x95,0xe5,0xd7,0x5e,0x9f,0x77,0xb2, 0x9c,0xf6,0xe2,0xef,0xd3,0xa7,0x4f,0xca,0x64,0xb9,0x96,0x2d,0x5b,0xfa,0xd6,0x8b, 0xbf,0x50,0x9d,0xf8,0xfc,0x32,0x03,0x6e,0x79,0xa1,0x46,0x42,0x12,0xfd,0x2c,0x1a, 0x39,0xf1,0x73,0x7c,0x71,0xf4,0x60,0x84,0x33,0x42,0xbc,0x8a,0x01,0xc0,0x00,0x00, 0x14,0x22,0xdb,0xdf,0xcb,0x9f,0x79,0x1c,0xd1,0x9b,0x2c,0x59,0x6e,0xc0,0x80,0x01, 0x29,0x93,0xe5,0x1a,0x35,0x6a,0x64,0x06,0x0f,0x1e,0x1c,0xef,0xc5,0xbf,0x72,0xe5, 0xca,0xc8,0x9b,0x01,0xbb,0xbc,0x50,0xef,0x8b,0x9f,0x11,0x00,0x6d,0xdd,0x8c,0x68, 0x62,0x00,0x00,0x03,0x00,0x11,0x6c,0xef,0xfb,0x4c,0x01,0xc5,0xff,0xc3,0x4e,0x9d, 0x0b,0x16,0x9a,0xd7,0x64,0xb9,0xa9,0x53,0xa7,0x66,0xdc,0x8b,0xff,0xfe,0xfb,0xef, 0x37,0xbf,0xfc,0xf2,0x4b,0xe4,0xcd,0x80,0xaf,0xf7,0x58,0x72,0x37,0x96,0x54,0xab, 0x85,0x68,0x46,0x8c,0xd7,0x30,0x00,0x18,0x00,0xe0,0x60,0x9f,0xa7,0x0b,0x28,0xfe, 0xf1,0xd6,0xbf,0x17,0x5e,0x5c,0x14,0xa1,0xca,0xb6,0x17,0xff,0x84,0x09,0x13,0x0a, 0x96,0x2c,0x17,0xd6,0xa3,0x7c,0xff,0x96,0x73,0xf0,0xd7,0x5f,0xec,0xfb,0x47,0x94, 0x37,0x30,0x00,0x18,0x00,0x28,0x5f,0x9a,0xf8,0x70,0xaa,0x5f,0x26,0xfc,0x31,0xfb, 0xcd,0xe2,0x0b,0x97,0xd3,0x8b,0xff,0xfc,0xf3,0xcf,0x4f,0xdb,0x8b,0xbf,0xd0,0xe5, 0x85,0x61,0x36,0x03,0xdf,0x5e,0x7c,0x29,0x62,0x19,0x51,0xde,0xc4,0x00,0x60,0x00, 0xa0,0x3c,0x69,0x24,0x4c,0x2b,0x82,0xf8,0xbf,0xbf,0x71,0xab,0xbc,0xda,0xd8,0xfa, 0x35,0x16,0x2e,0x5c,0x18,0xef,0xc5,0x9f,0x2e,0x8b,0xbf,0xd0,0xe5,0x85,0x61,0x32, 0x03,0x2b,0xde,0x7e,0x3b,0x7e,0x76,0x03,0x62,0x19,0x4d,0xde,0xc6,0x00,0x60,0x00, 0xa0,0xfc,0xa8,0x2f,0x3c,0x56,0x04,0xf1,0x57,0xbe,0xfc,0xbf,0x93,0x03,0xd7,0xf9, 0xcf,0x4d,0x96,0xdb,0x6d,0xb7,0xdd,0x32,0x2e,0x2f,0x2c,0x84,0x89,0x09,0xb2,0x19, 0x20,0xf4,0x1f,0x7d,0xe6,0x61,0x00,0x30,0x00,0x50,0x5e,0xd4,0x15,0x1e,0x29,0x92, 0xf8,0xc7,0x7b,0xff,0x4b,0xd7,0xb8,0x20,0x0f,0xb7,0xbc,0x30,0xd3,0x5e,0xfc,0x85, 0x2a,0x2f,0xcc,0xd7,0x0c,0xec,0xb1,0xc7,0x1e,0xbe,0x6e,0x61,0x7c,0x7b,0xc9,0x65, 0x88,0x64,0xc4,0x79,0x07,0x03,0x80,0x01,0x80,0xf2,0xa1,0xb6,0xf0,0x50,0x11,0xc5, 0x7f,0x71,0xc5,0xaa,0x66,0xf5,0x0f,0x3f,0x98,0xb0,0x8c,0x6c,0x7b,0xf1,0x6b,0x79, 0x61,0x21,0x7a,0xf1,0xe7,0x6a,0x06,0xf4,0x94,0x3f,0x3f,0xc6,0xca,0x25,0x4b,0xcc, 0xe2,0x2a,0x35,0x10,0xc9,0x88,0xb3,0x08,0x03,0x80,0x01,0x80,0xf2,0xa0,0xa6,0x70, 0x5f,0xac,0x52,0x51,0x17,0x98,0x0f,0x3b,0x77,0x35,0x61,0x1d,0x6e,0x2f,0xfe,0x4c, 0xcb,0x0b,0x0b,0xd5,0x8b,0x3f,0x1b,0x33,0xa0,0x47,0xfd,0xfa,0x31,0x3e,0xe9,0xbb, 0x1f,0x02,0x59,0x06,0x9c,0x1d,0xab,0xc8,0xda,0x88,0x01,0x80,0xa8,0x23,0x13,0xc2, 0xdc,0x55,0x64,0xf1,0xcf,0xe7,0xf0,0x9f,0xa0,0x8d,0x6c,0xcb,0x0b,0x0b,0xd5,0x8b, 0x3f,0x9d,0x19,0xe8,0xdd,0xbb,0x77,0xde,0xff,0xc6,0xaf,0xd3,0x9e,0x42,0x1c,0xcb, 0x80,0x11,0xb2,0x1e,0xb0,0x36,0x62,0x00,0x20,0xe2,0xc8,0x84,0x30,0xb7,0x95,0x40, 0xfc,0xe3,0xfb,0xff,0x8f,0x3d,0x6e,0xa2,0x36,0xdc,0xf2,0x42,0xed,0xc5,0x9f,0xae, 0xbc,0x50,0x3b,0xf2,0x69,0x79,0xa1,0x26,0x1d,0x16,0xc2,0x0c,0x68,0x02,0xa0,0x56, 0x2d,0xe8,0x97,0xbf,0x86,0xff,0xf3,0xcd,0x01,0xd0,0xa3,0x9a,0x97,0xb6,0xef,0x84, 0x40,0x46,0x9c,0x5b,0x64,0x3d,0xa8,0xc4,0xda,0x88,0x01,0x80,0x68,0x53,0x51,0xb8, 0xa1,0x44,0xe2,0x1f,0xdf,0xff,0xff,0xf1,0x47,0x13,0xf5,0xa1,0xbd,0xf8,0xb5,0xbc, 0x30,0x5d,0x88,0xbe,0x18,0xa7,0x17,0xe6,0x3b,0xbe,0x1f,0x73,0x23,0x02,0x19,0x71, 0xee,0x95,0xf5,0xa0,0x3a,0x6b,0x23,0x06,0x00,0xa2,0xcf,0x88,0x52,0x89,0x7f,0xc8, 0xf7,0xff,0xfd,0xe8,0xc5,0x9f,0xae,0xbc,0x50,0x23,0x08,0x85,0x2a,0x2f,0xcc,0x65, 0xac,0x5a,0xbe,0xdc,0xbc,0x5b,0xbf,0x31,0x22,0x19,0x61,0xa6,0x4a,0xd2,0xdf,0x46, 0xd6,0x3c,0x3c,0x8a,0x1c,0x00,0x0c,0x00,0x44,0x93,0x8b,0xe5,0xe5,0x2e,0xe5,0x62, 0xf3,0xc5,0xb1,0xc7,0x9b,0x72,0x1e,0x5a,0x5e,0xa8,0xb9,0x00,0x99,0x96,0x17,0xce, 0x9c,0x39,0xb3,0x60,0xa7,0x17,0x66,0x32,0xbe,0x3e,0xf7,0x7c,0x44,0x32,0xc2,0xe8, 0x29,0x9f,0x4d,0xac,0x79,0x77,0x40,0xac,0x02,0xc7,0x01,0x63,0x00,0x20,0x8a,0x9c, 0x51,0x62,0xf1,0x57,0x7e,0x18,0x7b,0xab,0x61,0xe4,0x56,0x5e,0xa8,0xd5,0x07,0x85, 0x28,0x2f,0x4c,0xfa,0xf5,0xff,0xdd,0x77,0x66,0x49,0xad,0xba,0x08,0x65,0x44,0x51, 0xa1,0x6f,0x65,0xcd,0xb3,0xdd,0x44,0xfc,0xb5,0x07,0xc0,0x73,0x18,0x00,0x0c,0x00, 0x44,0x8b,0xa3,0x02,0x20,0xfe,0xf1,0xfe,0xff,0xaf,0xbf,0x81,0xf2,0xa7,0x28,0x2f, 0x54,0xa1,0x4f,0x57,0x5e,0xa8,0x86,0xa1,0x50,0xe5,0x85,0x1b,0x44,0x2b,0x2e,0xb8, 0x10,0xa1,0x8c,0x70,0xbf,0xff,0x4e,0x22,0xf8,0xee,0xbc,0xda,0x46,0xfe,0xf7,0x1c, 0xa7,0x17,0xc8,0x93,0x18,0x00,0x0c,0x00,0x44,0x07,0x0d,0xeb,0x2d,0x2a,0x66,0xa3, 0x9f,0x64,0x48,0xff,0xf8,0x35,0x45,0xfc,0x82,0x0d,0x73,0x79,0xa1,0x86,0xfe,0x4b, 0x59,0x5e,0xb8,0xfa,0xfb,0xef,0xcd,0xbb,0x75,0xea,0x23,0x96,0x11,0x6d,0xf5,0xdb, 0xdd,0x12,0xff,0x36,0xc2,0xab,0xd6,0xfa,0x30,0x19,0x03,0x80,0x01,0x80,0x68,0xd0, 0xc3,0x09,0xeb,0x05,0x61,0xe1,0xf9,0x70,0xeb,0xed,0x50,0xf7,0x1c,0xca,0x0b,0x35, 0x29,0x50,0x93,0x03,0x35,0x49,0x30,0x55,0x79,0xe1,0xd0,0xa1,0x43,0xfd,0x6b,0xf9, 0xcb,0x69,0x7f,0x91,0x64,0xa1,0xac,0x05,0x7d,0x2d,0xf1,0xd7,0xfd,0xff,0x67,0x3d, 0xeb,0xc3,0x3d,0xf4,0x02,0xc0,0x00,0x40,0xf8,0xd9,0x4e,0x5e,0xf4,0xb7,0x03,0x22, 0xfe,0xf1,0x04,0xc0,0x41,0xc7,0xa2,0xe8,0x3e,0x94,0x17,0x6a,0xd9,0x60,0xa2,0xf2, 0x42,0xdd,0x1e,0xf0,0xe5,0xeb,0x5f,0xca,0x34,0xdf,0xad,0xdb,0x10,0xc1,0x8c,0x20, 0x47,0x58,0x19,0xfe,0x9a,0xf9,0x3f,0x35,0xc1,0xfa,0x30,0x1e,0x03,0x80,0x01,0x80, 0x70,0x23,0x0f,0xd6,0xbc,0x16,0x20,0xf1,0x57,0x96,0x5f,0x73,0x1d,0x0a,0x5e,0xa0, 0xf2,0x42,0x15,0x7f,0xbf,0x22,0x00,0xdf,0x5d,0x7d,0x0d,0x62,0x19,0x41,0x4e,0xb2, 0xc4,0xbf,0x9a,0x70,0x4f,0x92,0x72,0xe0,0x1b,0x31,0x00,0x18,0x00,0x08,0x2f,0x8d, 0x84,0x19,0x01,0x13,0xff,0x30,0x9c,0x00,0xc8,0x90,0x2d,0x87,0x35,0x6b,0xcc,0x07, 0xad,0xdb,0x22,0x98,0x11,0xe3,0x12,0x4b,0xfc,0xb5,0x11,0xd8,0xcd,0x29,0x7a,0x81, 0x5c,0x83,0x01,0xc0,0x00,0x40,0x78,0x0f,0xf7,0x99,0x1c,0x40,0xf1,0x57,0x56,0x2e, 0x5c,0x88,0xc2,0x06,0x7c,0x68,0x9b,0x66,0x04,0x33,0x5a,0x8c,0x16,0x41,0xaf,0x60, 0xad,0x11,0x57,0xa4,0x69,0x04,0x36,0x0c,0x03,0x80,0x01,0x80,0xf0,0xa1,0x7d,0xbc, 0xc7,0x95,0xb0,0xcb,0x5f,0x4a,0x2a,0x54,0xa1,0x02,0x20,0x04,0xe3,0x93,0x7d,0xfa, 0x21,0x9a,0x11,0xe2,0x76,0x59,0x0f,0xaa,0x58,0x6b,0xc4,0x39,0x19,0x94,0x03,0x5f, 0x40,0x27,0x40,0x0c,0x00,0x84,0x8f,0x61,0x41,0x15,0x7f,0xe1,0xfd,0x4d,0x37,0x43, 0x5d,0x03,0x3e,0xfe,0x7c,0xff,0xfd,0xb8,0x51,0x43,0x38,0xa3,0xc1,0x83,0xb2,0x1e, 0xd4,0xb4,0xd6,0x87,0x23,0x33,0xec,0x05,0x72,0x06,0x06,0x00,0x03,0x00,0xe1,0x62, 0x70,0x40,0x1a,0xfd,0x24,0xe3,0xe3,0xde,0x7b,0xa3,0xb0,0x01,0x1f,0x7a,0x4c,0x33, 0xc2,0x19,0x0d,0xa6,0xc9,0x36,0x60,0x7d,0x6b,0x7d,0xe8,0x9b,0x45,0x2f,0x90,0x13, 0x31,0x00,0x18,0x00,0x08,0x0f,0x3d,0xe5,0xe5,0x5e,0x18,0xd0,0x7d,0x7f,0x97,0x2f, 0x8f,0xff,0x3f,0x14,0x36,0xc0,0x63,0xcd,0xca,0x95,0x1c,0xfa,0x13,0x11,0x9e,0x97, 0xb5,0xa0,0x85,0xb5,0x3e,0x68,0xd3,0x9f,0x79,0x59,0xac,0x0f,0x47,0x63,0x00,0x30, 0x00,0x10,0x0e,0xb6,0x14,0xde,0x0c,0xb8,0xf8,0x2b,0xdf,0x5e,0x72,0x19,0x2a,0x1b, 0xe0,0xf1,0xf3,0xc3,0x8f,0x20,0x9e,0x11,0xe0,0x75,0x59,0x0b,0xb6,0xb0,0xd6,0x87, 0x8e,0x22,0xfe,0xd9,0xae,0x0f,0x87,0x63,0x00,0x30,0x00,0x10,0x7c,0x1a,0x24,0xe8, 0xe2,0x15,0x54,0x38,0x04,0x28,0xd8,0xe3,0xb3,0x01,0x87,0x23,0xa0,0x21,0x47,0x9b, 0x7e,0x6d,0x6f,0x75,0xf9,0xdb,0x54,0x78,0x29,0x87,0xf5,0xe1,0x00,0xeb,0xef,0x00, 0x0c,0x00,0x04,0x90,0xca,0xc2,0xdd,0x01,0x4e,0xfa,0x53,0xde,0x68,0xd8,0xd4,0x8c, 0x3f,0x7c,0xa0,0x19,0x7e,0xc1,0x05,0x66,0xc9,0x82,0x05,0xa8,0x6c,0x40,0xc7,0xea, 0x5f,0x7e,0x31,0x4b,0xaa,0xd7,0x46,0x44,0x43,0x8c,0xb6,0xfb,0xde,0xdd,0x12,0x6e, 0xed,0x05,0xf2,0x4c,0x8e,0x1f,0x07,0x7b,0x61,0x00,0x30,0x00,0x10,0x6c,0x86,0x06, 0x3c,0xe9,0x4f,0xc5,0xff,0xca,0xf3,0x87,0x98,0xcb,0x2e,0xbb,0x2c,0xce,0xa7,0x9f, 0x7e,0x8a,0xd2,0x06,0x74,0xfc,0x38,0xf1,0x2e,0x44,0x34,0xe4,0x1c,0x64,0x89,0xb6, 0x2c,0xf2,0x66,0x4a,0x1e,0x91,0xc1,0xdd,0x30,0x00,0x18,0x00,0x08,0x2e,0xfb,0xcb, 0x0b,0x1a,0xf4,0x05,0x49,0xbf,0xfc,0x5d,0xf1,0x57,0xbe,0x97,0xd3,0xe5,0x18,0xd4, 0xfe,0x83,0xff,0x0c,0xb6,0xf6,0xec,0xb5,0xe6,0xff,0xce,0x3c,0x23,0x83,0x5d,0x31, 0x00,0x18,0x00,0x08,0x26,0xed,0x84,0xb7,0x43,0xb0,0xef,0x3f,0x7c,0xc8,0x05,0x1b, 0x18,0x80,0x3f,0xff,0xfc,0x13,0xa5,0x0d,0xe0,0x58,0xf5,0xcd,0x37,0x66,0x71,0xa5, 0x6a,0x08,0x69,0x48,0x39,0xcb,0x12,0x7f,0xed,0xf6,0x37,0xc6,0x87,0x6d,0xc1,0x4e, 0x18,0x00,0x0c,0x00,0x04,0x8f,0xda,0xc2,0xd3,0x21,0x49,0xfa,0xd3,0x7d,0x7f,0xdb, 0x00,0xdc,0x7c,0xf3,0xcd,0xe6,0xc5,0x17,0x5f,0x34,0xcb,0x97,0x2f,0x47,0x75,0x83, 0x14,0xfe,0xbf,0xe3,0x4e,0x84,0x34,0xa4,0x5c,0xe9,0x69,0xd9,0x7b,0xb1,0x4f,0xdb, 0x82,0x6d,0x59,0x6b,0x31,0x00,0x10,0x3c,0xae,0x0f,0x78,0xd2,0x5f,0xaa,0x2d,0x00, 0x9b,0x71,0xe3,0xc6,0x99,0x97,0x5f,0x7e,0xd9,0xfc,0x28,0xc7,0xce,0x32,0x4a,0x9c, 0xfd,0x7f,0xe8,0x40,0xc4,0x34,0x84,0x8c,0x95,0xb5,0xa0,0x92,0xb5,0x36,0x9c,0xea, 0x63,0x4e,0xd0,0xc6,0xac,0xb5,0x18,0x00,0x08,0x16,0x03,0x42,0xb0,0xef,0x9f,0x2a, 0x09,0x30,0x19,0xe3,0xc7,0x8f,0x37,0xaf,0xbd,0xf6,0x9a,0xf9,0xf9,0xe7,0x9f,0x51, 0xe3,0x22,0x8f,0xb5,0xab,0x56,0x99,0x77,0xeb,0x36,0x44,0x50,0x43,0x86,0x1e,0xe3, 0x5b,0xcd,0x5a,0x1b,0x0e,0xf3,0x39,0x21,0xb8,0x01,0xeb,0x2d,0x06,0x00,0x82,0x43, 0xdb,0x90,0xec,0xfb,0x27,0x32,0x01,0xb7,0x0d,0x3c,0xc2,0x5c,0x7e,0xc9,0x25,0x69, 0x8d,0x80,0x72,0xfb,0xed,0xb7,0x9b,0xd9,0xb3,0x67,0x9b,0x5f,0x7f,0xfd,0x15,0x75, 0x2e,0xc2,0xf8,0xfd,0x85,0x17,0x11,0xd4,0x90,0x31,0x55,0xd6,0x81,0x3a,0xd6,0xda, 0xb0,0x67,0x01,0xba,0x80,0xd6,0x64,0xcd,0xc5,0x00,0x40,0x30,0xa8,0x2a,0x4c,0x0d, 0xa1,0xf8,0x6f,0xd0,0xa0,0xa4,0x56,0x5d,0xf3,0x68,0xb7,0x9d,0xcd,0x8d,0xc7,0xfe, 0x3b,0x23,0x23,0xa0,0x4c,0x9c,0x38,0xd1,0xbc,0xf5,0xd6,0x5b,0xe6,0xf7,0xdf,0x7f, 0x47,0xa9,0x0b,0x34,0xbe,0x39,0xff,0x02,0x44,0x35,0x44,0xcc,0x90,0x75,0xa0,0xb1, 0xb5,0x36,0x74,0xcd,0xb2,0xc5,0x6f,0xa6,0x54,0x64,0xdd,0xc5,0x00,0x40,0x30,0x38, 0x27,0xe0,0xf5,0xfe,0xd9,0xf2,0x66,0xbd,0x46,0x66,0xf2,0x6e,0x3d,0xcd,0xa8,0x93, 0x4e,0xce,0xc8,0x08,0x5c,0x7e,0xf9,0xe5,0xe6,0xee,0xbb,0xef,0x36,0x73,0xe7,0xce, 0x35,0x2b,0x38,0x4e,0xd8,0xd7,0xf1,0xe1,0xd6,0xdb,0x21,0xac,0x21,0xe1,0x65,0x11, 0xfa,0x56,0x9e,0x16,0xe0,0x6f,0x14,0x40,0xfc,0xd5,0x50,0xb0,0xee,0x62,0x00,0x20, 0x00,0x74,0x0e,0xc1,0x21,0x3f,0xf9,0xf0,0x5a,0x93,0x16,0xe6,0xfe,0x3d,0xf7,0x36, 0xd7,0x9e,0x7e,0x46,0x46,0x66,0x60,0xd8,0xb0,0x61,0xe6,0xde,0x7b,0xef,0x35,0xf3, 0xe7,0xcf,0x37,0x2b,0xe5,0xf0,0x1a,0x46,0x1e,0xe5,0x7f,0x5f,0x7d,0x85,0xb0,0x86, 0xc5,0x34,0xcb,0x1a,0xd0,0xd1,0x2a,0xcd,0xd3,0x83,0x7e,0x5e,0x28,0xd0,0xba,0xf0, 0x1a,0x06,0x00,0x03,0x00,0xa5,0x47,0x93,0x7c,0xa6,0x45,0x58,0xfc,0xbd,0xbc,0xd8, 0xb2,0x8d,0xb9,0xbb,0xdf,0x7e,0x66,0xc4,0x39,0xe7,0x66,0x64,0x06,0xae,0xb8,0xe2, 0x0a,0x73,0xff,0xfd,0xf7,0x9b,0x85,0x0b,0x17,0xd2,0x63,0x20,0x87,0xf1,0xf3,0xe4, 0x29,0x88,0x6b,0x08,0xd0,0x2f,0xf2,0x9d,0x2c,0xf1,0xaf,0x5f,0xe0,0x75,0x61,0x26, 0x06,0x00,0x03,0x00,0xa5,0x67,0x48,0xc4,0x42,0xff,0x99,0xb2,0xb0,0x42,0x55,0xf3, 0x5c,0xdb,0x76,0xe6,0x8e,0x83,0xfb,0xff,0xad,0x99,0x50,0x32,0x86,0x0f,0x1f,0x6e, 0x1e,0x7a,0xe8,0x21,0xb3,0x64,0xc9,0x12,0xb3,0x4a,0x32,0xdb,0x19,0xe9,0xc7,0xd7, 0x67,0x9e,0x8d,0xc0,0x06,0xfd,0x5d,0x10,0x31,0xb6,0xfb,0xf2,0x6b,0x72,0xde,0x83, 0x05,0x2e,0x05,0x9e,0x86,0x01,0xc0,0x00,0x40,0x69,0xd9,0x2a,0xe2,0xa1,0xff,0x4c, 0x59,0x50,0xb9,0xba,0x79,0xba,0xe3,0x36,0xe6,0xb6,0xc3,0x8f,0x30,0xc3,0x2e,0xba, 0x28,0x23,0x33,0x70,0xd5,0x55,0x57,0x99,0x87,0x1f,0x7e,0xd8,0xbc,0xf7,0xde,0x7b, 0x66,0xf5,0xea,0xd5,0x28,0x7d,0x92,0xf1,0xd1,0x8e,0xdd,0x11,0xd9,0x80,0x33,0xd0, 0xea,0xf2,0xa7,0x87,0x7f,0x4d,0x28,0x42,0x1f,0x90,0x29,0x18,0x00,0x0c,0x00,0x94, 0x8e,0x0a,0x45,0x70,0xf9,0xa1,0x0c,0x85,0x56,0xab,0x6d,0x9e,0xd8,0xae,0xab,0x19, 0x7b,0xd4,0xd1,0x19,0x97,0x15,0x8e,0x18,0x31,0xc2,0x3c,0xfa,0xe8,0xa3,0x66,0xe9, 0xd2,0xa5,0x66,0xcd,0x9a,0x35,0xa8,0xbe,0x33,0xd6,0xfc,0xf1,0x87,0x59,0x5c,0xa5, 0x06,0xf3,0x2a,0xc0,0x9c,0x68,0x89,0xbf,0x72,0x6d,0x91,0xd6,0x84,0x7b,0x3d,0xdd, 0x05,0x01,0x03,0x00,0x45,0x64,0x60,0x99,0x86,0xfe,0xb3,0x2b,0x2b,0xac,0xb7,0xae, 0xac,0xf0,0xdf,0xc7,0x65,0x5c,0x56,0x38,0x72,0xe4,0x48,0xf3,0xf8,0xe3,0x8f,0x9b, 0x8f,0x3e,0xfa,0xa8,0xec,0xcd,0xc0,0x6f,0xcf,0xbf,0xc0,0x3c,0x0a,0x30,0x17,0x7b, 0xc4,0xbf,0x98,0xdb,0x81,0x13,0x30,0x00,0x18,0x00,0x28,0x0d,0x0d,0x85,0xd7,0x09, 0xfd,0x67,0xc5,0xec,0xfa,0x8d,0xcd,0x43,0x3d,0x7a,0x65,0x5c,0x56,0xa8,0x5c,0x7b, 0xed,0xb5,0xe6,0xc9,0x27,0x9f,0x34,0x1f,0x7f,0xfc,0xb1,0x59,0xbb,0x76,0x6d,0xd9, 0x19,0x80,0xef,0xae,0x1c,0xc1,0xdc,0x09,0x28,0xda,0xee,0xbb,0x82,0xb5,0x26,0x9c, 0x58,0xe4,0x0f,0x82,0xff,0x60,0x00,0x30,0x00,0x50,0x1a,0x2e,0x23,0xf4,0x9f,0x17, 0xaf,0x34,0xdb,0xc4,0xdc,0xb7,0xd7,0x3e,0xe6,0x9a,0x33,0xce,0xcc,0xd8,0x0c,0x5c, 0x7f,0xfd,0xf5,0x66,0xfa,0xf4,0xe9,0xe6,0xb3,0xcf,0x3e,0x2b,0x9f,0xfe,0xff,0xfd, 0x0f,0x63,0xbe,0x04,0x10,0xfd,0xfa,0xae,0x62,0xad,0x07,0x07,0x95,0xa0,0xfd,0xf7, 0xb5,0x18,0x00,0x0c,0x00,0x14,0x9f,0x36,0xc2,0x02,0xbe,0xfe,0x7d,0x61,0x91,0xf0, 0xc2,0xa6,0x9b,0x99,0xbb,0xf7,0xdd,0xdf,0x8c,0x38,0xf7,0xdc,0x8c,0xcd,0xc0,0xe8, 0xd1,0xa3,0xcd,0x8c,0x19,0x33,0xcc,0x97,0x5f,0x7e,0x19,0x69,0x03,0xb0,0x74,0xcb, 0x8e,0xcc,0x93,0x80,0xa1,0x79,0x3f,0x76,0x0b,0xde,0xdd,0x45,0xfc,0xdf,0x29,0xc1, 0x7a,0x30,0x0c,0x03,0x80,0x01,0x80,0xe2,0xf3,0x1f,0xbe,0xfe,0x0b,0x53,0x4a,0x55, 0x51,0xca,0x0a,0xb7,0x68,0x6f,0x6e,0x3f,0x64,0xc0,0xdf,0x8e,0x28,0x4e,0xc5,0x0d, 0x37,0xdc,0x60,0x9e,0x7b,0xee,0x39,0xf3,0xcd,0x37,0xdf,0x44,0x2f,0x01,0x50,0xee, 0x09,0x73,0x23,0x38,0x68,0xe9,0x5d,0x7d,0x4f,0x03,0xb0,0x52,0x9d,0xfd,0x31,0xd4, 0x93,0x7f,0x00,0x18,0x00,0x28,0x30,0xdb,0x87,0xec,0xa4,0xbf,0xb0,0xf2,0x4e,0xe5, 0x1a,0x66,0xfa,0x56,0x52,0x56,0x38,0xf0,0x1f,0x52,0x56,0x78,0x71,0xc6,0x66,0xe0, 0xa6,0x9b,0x6e,0x32,0xcf,0x3f,0xff,0xbc,0xf9,0xee,0xbb,0xef,0x42,0x6f,0x00,0xfe, 0x78,0x6b,0x0e,0x73,0x21,0x40,0xcc,0x12,0xa1,0x6f,0x61,0xad,0x05,0x9b,0x0b,0xaf, 0x96,0x30,0x12,0x78,0x16,0x06,0x00,0x03,0x00,0xc5,0x65,0x22,0x5f,0xff,0xc5,0x2f, 0x2b,0xac,0x2e,0x65,0x85,0xdb,0xef,0x60,0x6e,0x3e,0x7a,0x90,0xb9,0xec,0xd2,0x4b, 0x33,0x36,0x03,0xb7,0xdc,0x72,0x8b,0x79,0xf1,0xc5,0x17,0xcd,0xf7,0xdf,0x7f,0x1f, 0x4a,0x03,0xf0,0xe3,0x9d,0x13,0x79,0xfe,0x41,0x69,0x85,0x2d,0x42,0xdf,0xd6,0x5a, 0x07,0x9a,0x09,0x33,0x4b,0xbc,0x0d,0xf8,0x7f,0x18,0x00,0x0c,0x00,0x14,0xb7,0xdf, 0x3f,0x8b,0x61,0x69,0x99,0x53,0xbb,0xbe,0x79,0x64,0xa7,0x5d,0xcc,0x0d,0xc7,0x1d, 0x9f,0xb1,0x11,0x50,0xc6,0x8d,0x1b,0x67,0x5e,0x79,0xe5,0x15,0xf3,0xd3,0x4f,0x3f, 0x85,0xa7,0x03,0xe0,0xd9,0xe7,0xf2,0xcc,0x83,0x50,0xca,0x2a,0x42,0xdf,0xd9,0xea, 0xf2,0x57,0x57,0x78,0x3c,0x00,0x39,0x40,0x83,0x30,0x00,0x18,0x00,0x28,0x1e,0xb7, 0xf0,0xf5,0x1f,0x28,0xde,0x68,0xd0,0xc4,0x3c,0xb4,0x7b,0x2f,0x73,0xfd,0xc9,0xa7, 0x64,0x65,0x06,0x26,0x4c,0x98,0x60,0x5e,0x7b,0xed,0x35,0xf3,0xcb,0x2f,0xbf,0x04, 0xda,0x00,0x7c,0xd2,0x67,0x5f,0x9e,0x73,0xa9,0xb7,0xa2,0x44,0xe8,0x7b,0x58,0xe2, 0x2f,0x0b,0xb3,0x99,0x14,0x90,0x75,0x60,0x20,0x06,0x00,0x03,0x00,0xc5,0xa1,0xbd, 0xc0,0x82,0x18,0xe0,0xb2,0xc2,0xe6,0x2d,0xa5,0xac,0xb0,0x8f,0x19,0x79,0xe6,0x59, 0x59,0x99,0x81,0x3b,0xee,0xb8,0xc3,0xcc,0x9e,0x3d,0xdb,0xfc,0xf6,0xdb,0x6f,0xc1, 0xab,0x00,0x68,0xb7,0x15,0xcf,0xb6,0xa4,0x15,0x2a,0x95,0xcd,0x01,0x96,0xf8,0x57, 0x0a,0xd8,0x47,0xc0,0x81,0xd6,0xcf,0x06,0x18,0x00,0x28,0x20,0xd7,0xf0,0xf5,0x1f, 0x9a,0xb2,0xc2,0xe7,0x5b,0x6d,0x6e,0xee,0xda,0xef,0x00,0x73,0xd5,0x79,0xe7,0x65, 0x6c,0x04,0x2e,0xbf,0xfc,0x72,0x33,0x71,0xe2,0x44,0x33,0x67,0xce,0x1c,0xf3,0xfb, 0xef,0xbf,0x07,0xc2,0x00,0x2c,0xa9,0x51,0x87,0x67,0x5a,0x42,0x8e,0xf6,0x7c,0x61, 0x5f,0x15,0xb0,0x35,0x60,0x1f,0x0c,0x00,0x06,0x00,0x0a,0x8f,0x96,0xfd,0xcc,0xa3, 0xee,0x3f,0x84,0x65,0x85,0xd5,0xcc,0xb3,0x5b,0x76,0x88,0x97,0x15,0x5e,0x31,0x74, 0x68,0x56,0x66,0xe0,0x9e,0x7b,0xee,0x31,0x73,0xe7,0xce,0x35,0x2b,0x56,0xac,0x28, 0x89,0xf8,0xaf,0x92,0x92,0x46,0x9e,0x61,0xe9,0x38,0xd3,0x23,0xfe,0x67,0x05,0xb0, 0xed,0x77,0x0f,0x0c,0x00,0x06,0x00,0x0a,0xcf,0xbf,0xe9,0xf9,0x1f,0xfe,0xbd,0x5c, 0x39,0x50,0xe7,0xa9,0x4e,0xdb,0x9a,0x71,0x47,0x1c,0x99,0x55,0x59,0xe1,0xb0,0x61, 0xc3,0xcc,0xa4,0x49,0x93,0xcc,0x3b,0xef,0xbc,0x63,0xfe,0xfc,0xf3,0xcf,0xe2,0x95, 0x00,0xce,0x7e,0x93,0xe7,0x56,0x22,0x86,0x7b,0x1a,0xec,0x0c,0x0e,0xe8,0xfb,0xbf, 0x03,0x06,0x00,0x03,0x00,0x85,0x3f,0xf1,0xef,0x19,0xbe,0xfe,0x23,0x56,0x56,0x58, 0xc7,0x3c,0xde,0x65,0x47,0x73,0xf3,0xa0,0x63,0xb2,0x2a,0x2b,0x1c,0x3e,0x7c,0xb8, 0x79,0xe0,0x81,0x07,0xcc,0xc2,0x85,0x0b,0xcd,0x5f,0x7f,0xfd,0x55,0x50,0x03,0xf0, 0xf3,0x43,0x93,0x79,0x56,0x25,0xe0,0x26,0x11,0xff,0x8a,0xd6,0xfb,0xbf,0xaf,0x88, 0xec,0xa2,0x80,0xbe,0xff,0x5b,0x63,0x00,0x30,0x00,0x50,0x58,0x76,0xa5,0xf4,0x2f, 0xd2,0xbc,0x55,0xa7,0x81,0x79,0xa4,0xfb,0xae,0x66,0xcc,0xf1,0x27,0x64,0x95,0x3c, 0x78,0xe5,0x95,0x57,0x9a,0xc9,0x93,0x27,0x9b,0x25,0x4b,0x96,0x98,0x55,0xab,0x56, 0xf9,0x6e,0x00,0x96,0x5f,0x37,0x8a,0xe7,0x53,0x64,0xee,0x12,0xf1,0xaf,0x6a,0xbd, 0xfb,0x3b,0xcb,0xbb,0x3f,0x3f,0xc0,0xe6,0xbf,0x2d,0xeb,0x33,0x06,0x00,0x0a,0xcb, 0x08,0x92,0xff,0xca,0xa7,0xac,0xb0,0x61,0x53,0xf3,0x60,0xcf,0x3d,0xcc,0x75,0xa7, 0x9c,0x9a,0x95,0x19,0xb8,0xea,0xaa,0xab,0xcc,0xc3,0x0f,0x3f,0x6c,0xde,0x7f,0xff, 0x7d,0xb3,0x7a,0xf5,0x6a,0x7f,0x7a,0x00,0x9c,0x79,0x36,0xcf,0xa4,0x88,0x3c,0x22, 0x42,0x5f,0xc7,0x7a,0xef,0x3b,0x89,0xf8,0xbf,0x15,0xf0,0xc8,0xdf,0x26,0xac,0xcf, 0x18,0x00,0x28,0x1c,0xfa,0x35,0xf0,0x26,0xe1,0xff,0xb2,0xe4,0x65,0x29,0x2b,0x9c, 0xb4,0x77,0x5f,0x33,0xf2,0xac,0xec,0xca,0x0a,0xaf,0xbe,0xfa,0x6a,0x33,0x75,0xea, 0x54,0xb3,0x74,0xe9,0x52,0xb3,0x66,0xcd,0x9a,0x9c,0x0d,0xc0,0x17,0x47,0x0f,0xe6, 0x39,0x14,0x09,0xdd,0xe2,0x6b,0x64,0xbd,0xf7,0xad,0x84,0x57,0x42,0xf0,0xde,0x37, 0x62,0x8d,0xc6,0x00,0x40,0xe1,0xd8,0x8b,0xf0,0x3f,0x65,0x85,0x15,0xa4,0xac,0xb0, 0xb5,0x94,0x15,0xee,0x7f,0xa0,0x94,0x15,0x9e,0x9f,0x95,0x19,0xb8,0xe6,0x9a,0x6b, 0xcc,0xe3,0x8f,0x3f,0x6e,0x96,0x2d,0x5b,0x66,0xd6,0xae,0x5d,0x9b,0x95,0x01,0xf8, 0x74,0xff,0x83,0xb8,0xff,0x45,0xe0,0x25,0x11,0xfa,0x4d,0xad,0x77,0x5e,0x45,0x75, 0x46,0x48,0x4c,0x7f,0x4d,0xd6,0x68,0x0c,0x00,0x14,0x8e,0x31,0x84,0xff,0xc1,0x53, 0x56,0x38,0xa3,0x5d,0x47,0xf3,0xdf,0xfe,0x87,0x4a,0x59,0xe1,0x85,0x59,0x99,0x81, 0xeb,0xae,0xbb,0xce,0x4c,0x9b,0x36,0xcd,0x7c,0xf2,0xc9,0x27,0x19,0x99,0x81,0xf7, 0x7b,0xef,0xcd,0x3d,0x2f,0x30,0xb3,0x45,0xe8,0x3b,0x58,0xef,0x7b,0x6d,0xe1,0x91, 0x10,0x45,0xfc,0x2a,0xb1,0x46,0x63,0x00,0xa0,0x30,0x54,0x21,0xfc,0x0f,0x29,0xcb, 0x0a,0x6b,0x9a,0xa7,0xb6,0xee,0x6c,0xc6,0xfd,0xe3,0x48,0x73,0xf9,0xc5,0x17,0x67, 0x65,0x06,0x46,0x8d,0x1a,0x65,0x9e,0x7e,0xfa,0x69,0xf3,0xf9,0xe7,0x9f,0x27,0x35, 0x00,0x63,0x6f,0xfc,0x8f,0xb9,0xed,0xf0,0x23,0xe2,0x79,0x09,0xdc,0xef,0x02,0x54, 0x82,0xc8,0xbb,0xdd,0xcd,0xca,0xa2,0xaf,0x1a,0xb2,0x83,0xbe,0xf4,0xe7,0x67,0x9d, 0xc6,0x00,0x40,0x81,0xe8,0x46,0xf8,0x1f,0x32,0x64,0x6e,0x8d,0x8d,0xcc,0x63,0x5d, 0xbb,0x99,0x9b,0x06,0x0d,0xce,0xaa,0xac,0x50,0x19,0x33,0x66,0x8c,0x99,0x31,0x63, 0x86,0xf9,0xea,0xab,0xaf,0x36,0x30,0x00,0x1a,0x31,0x88,0x57,0x1b,0x9c,0x3f,0x04, 0x13,0xe0,0x77,0x24,0x47,0xc4,0x73,0x2f,0x4b,0xfc,0xb5,0xec,0xef,0xc6,0x90,0x45, 0xfb,0x5e,0xc7,0x00,0x60,0x00,0xa0,0x70,0x9c,0x4d,0xf3,0x1f,0xc8,0xa5,0xac,0x70, 0xa3,0x06,0xe6,0xe1,0x9d,0x77,0x33,0x63,0x4e,0x38,0x31,0x2b,0x23,0xa0,0xdc,0x78, 0xe3,0x8d,0x66,0xe6,0xcc,0x99,0xe6,0x1b,0xe9,0x02,0x78,0xc5,0x15,0x57,0xfc,0xef, 0xff,0x1f,0x7f,0xf8,0x40,0xee,0xad,0x8f,0x1c,0xe6,0xe9,0xf2,0x77,0x59,0x08,0xb7, 0xfa,0x9e,0xc7,0x00,0x60,0x00,0xa0,0x70,0x4c,0x25,0xfc,0x0f,0xf9,0x7e,0xa5,0x35, 0x6a,0x66,0x1e,0xec,0xd5,0xdb,0x5c,0x77,0xea,0x69,0x59,0x9b,0x81,0x0d,0x1a,0x10, 0x5d,0x70,0x01,0xf7,0xd3,0x27,0x4e,0xf0,0x88,0xff,0xe9,0x21,0x35,0xfa,0x4f,0x61, 0x00,0x30,0x00,0x50,0x18,0x1a,0x71,0xf2,0x1f,0xf8,0x5d,0x56,0xd8,0x62,0x53,0x73, 0xef,0x3e,0x7d,0xcd,0xd5,0x67,0x9f,0x9d,0xbd,0x01,0x18,0x82,0x01,0xf0,0x83,0xa1, 0x1e,0xf1,0x1f,0x18,0xe2,0x28,0xdf,0xc3,0x18,0x00,0x0c,0x00,0x14,0x86,0xde,0xec, 0xff,0x43,0x01,0xcb,0x0a,0x67,0xb5,0x69,0x6b,0x26,0x1e,0x70,0x50,0x7c,0x7f,0x3f, 0x13,0x03,0xc0,0x16,0x40,0xfe,0x5c,0xe7,0xe9,0xef,0xbf,0xb7,0xbc,0xe3,0x0b,0x43, 0x1c,0xe5,0x9b,0xe4,0xb9,0x1e,0xc0,0x00,0x00,0xfb,0xff,0x10,0x22,0x16,0x54,0xd2, 0xb2,0xc2,0xad,0xcc,0x7f,0x07,0x1c,0x66,0xae,0xb8,0x30,0x71,0x59,0x21,0x49,0x80, 0xf9,0x33,0x5e,0xc4,0xb2,0xb2,0xf5,0x7e,0xef,0x28,0xe2,0x1f,0xf6,0xd3,0x3d,0xff, 0x8b,0x01,0xc0,0x00,0x40,0x61,0xb8,0x9b,0xfa,0x7f,0x28,0x32,0xf3,0xab,0xd6,0x34, 0xd3,0xb6,0xd9,0xce,0xdc,0xfa,0x8f,0x7f,0xc6,0x43,0xfe,0xba,0xef,0xaf,0x5f,0xfe, 0x88,0x7f,0x7e,0x3c,0x20,0xef,0x72,0x0d,0xeb,0xdd,0x6e,0x2f,0xcc,0x8e,0x40,0x7e, 0xcf,0xcd,0x18,0x00,0x0c,0x00,0xf8,0x8f,0x7e,0x29,0xcc,0x25,0x01,0x10,0x20,0xf4, 0x3c,0x21,0xef,0x71,0x3d,0xeb,0xdd,0xd6,0xde,0xf9,0x2f,0x46,0xe4,0xdd,0xbe,0x0e, 0x03,0x80,0x01,0x00,0xff,0xd9,0x82,0x04,0x40,0x80,0xd0,0x33,0x53,0x84,0xbe,0xb9, 0xf5,0x5e,0x37,0x10,0xa6,0x47,0xc8,0xd8,0x5f,0x81,0x01,0xc0,0x00,0x80,0xff,0xf4, 0x25,0x01,0x10,0x20,0xd4,0xbc,0x2a,0x42,0xbf,0xb9,0xf5,0x4e,0x6b,0xcf,0xfc,0xc9, 0x11,0x8b,0xea,0x5d,0xe8,0xa9,0x68,0x00,0x0c,0x00,0xf8,0xc0,0xa9,0x24,0x00,0x02, 0x84,0x96,0x39,0x22,0xf4,0xdb,0x5a,0x5d,0xfe,0xb4,0xa5,0xf7,0x7f,0x23,0x98,0xd3, 0x73,0x16,0x06,0x00,0x03,0x00,0xfe,0x73,0x23,0x09,0x80,0x00,0xe1,0x3c,0x9f,0x41, 0xc4,0x7f,0x37,0x4b,0xfc,0x65,0x41,0x35,0xd7,0x47,0xf4,0x7d,0x3e,0x09,0x03,0x80, 0x01,0x00,0xff,0x79,0x92,0x04,0x40,0x80,0xf0,0xf5,0x57,0x90,0xf7,0x76,0x3f,0x4b, 0xfc,0x95,0x0b,0x23,0x1c,0xcd,0x1b,0x8c,0x01,0xc0,0x00,0x80,0xff,0xcc,0xc3,0x00, 0x00,0x84,0x8e,0xa3,0x3c,0x82,0xf8,0x7f,0x11,0xdf,0xca,0x1b,0x88,0x01,0xc0,0x00, 0x80,0xbf,0x34,0xa4,0x02,0x00,0x20,0x74,0x9c,0xee,0x11,0xc3,0xfe,0x65,0x90,0xc8, 0x7b,0x90,0x27,0xda,0x01,0x18,0x00,0xc8,0x93,0x4e,0x54,0x00,0x00,0x84,0x8a,0x61, 0x9e,0x72,0xb8,0x3d,0xe4,0x1d,0x5e,0x50,0x06,0x51,0xbc,0x3e,0x18,0x00,0x0c,0x00, 0xf8,0xcb,0x5e,0x18,0x00,0x80,0xd0,0xf0,0x1f,0x11,0xff,0x8a,0xd6,0xfb,0xbb,0xbd, 0xbc,0xbf,0xe5,0xd2,0xc4,0x6b,0x77,0x0c,0x00,0x06,0x00,0xfc,0xe5,0x28,0x4a,0x00, 0x01,0x42,0xc1,0x44,0x11,0xff,0xaa,0xd6,0xbb,0xdb,0x56,0x78,0xbd,0x8c,0xf2,0x77, 0xba,0x61,0x00,0x30,0x00,0xe0,0x2f,0xa7,0x63,0x00,0x00,0x02,0x8f,0x1e,0x85,0x5b, 0xdb,0x7a,0x6f,0xb5,0xe3,0xdf,0xac,0x32,0x4b,0xde,0xdd,0x16,0x03,0x80,0x01,0x00, 0x7f,0xb9,0x14,0x03,0x00,0x10,0x68,0x9e,0x16,0xa1,0x6f,0x64,0xbd,0xb3,0x75,0xcb, 0xb4,0x74,0x77,0x0b,0xd6,0x6b,0x0c,0x00,0xf8,0xcb,0x68,0x9a,0x00,0x01,0x04,0x16, 0x3d,0xc8,0xa7,0xa5,0xf5,0xbe,0xea,0x29,0x7f,0xf7,0x95,0xe9,0x3b,0xdb,0x92,0xf5, 0x1a,0x03,0x00,0xfe,0x72,0x3b,0x06,0x00,0x20,0x90,0xe8,0x11,0xbe,0x1d,0xac,0x77, 0x55,0x16,0x4a,0x33,0xae,0x8c,0xdf,0xd7,0x46,0xac,0xd7,0x18,0x00,0xf0,0x97,0x87, 0x69,0x02,0x04,0x10,0x38,0x34,0xb3,0x7f,0x07,0xcf,0x9e,0xf7,0xd5,0x65,0x6e,0xd6, 0x6b,0xb3,0x5e,0x63,0x00,0xc0,0x5f,0xa6,0x63,0x00,0x00,0x02,0x85,0xd6,0xf4,0xf7, 0xf6,0x88,0xff,0xb9,0xe4,0xea,0x98,0xca,0xac,0xd7,0x18,0x00,0xf0,0x97,0x59,0x18, 0x00,0x80,0x40,0x31,0xc0,0x23,0xfe,0xc7,0x22,0xfe,0xe6,0x01,0x4f,0xf3,0x23,0xc0, 0x00,0x80,0x0f,0xbc,0x8a,0x01,0x00,0x08,0x0c,0xc7,0x79,0x5a,0xfc,0x1e,0x20,0x66, 0x60,0x11,0xef,0xa8,0x39,0x90,0x12,0x40,0x0c,0x00,0xf8,0xcf,0x1c,0x16,0x17,0x80, 0x40,0x70,0x81,0x47,0xfc,0xf5,0x98,0xdf,0x77,0x78,0x3f,0xe3,0x1f,0x29,0x55,0x59, 0xab,0x31,0x00,0xe0,0x3f,0x0b,0x59,0x60,0x00,0x4a,0xce,0x35,0x9e,0x10,0xf7,0x36, 0x22,0xfe,0x98,0xf3,0x75,0x9c,0xc3,0x29,0x80,0x18,0x00,0xf0,0x9f,0x8a,0x9c,0x04, 0x08,0x50,0x72,0xb4,0xb4,0xcf,0x4e,0x70,0x6b,0xc3,0xd6,0xdc,0xff,0x58,0xe4,0xe9, 0x83,0x00,0x18,0x00,0xf0,0x89,0x0a,0x18,0x00,0x80,0x92,0xa2,0x4d,0x7d,0x6a,0x58, 0xef,0x64,0x13,0xe1,0x59,0xc4,0x7f,0x03,0x73,0xc4,0x5a,0x8d,0x01,0x00,0x0c,0x00, 0x40,0xa4,0x78,0x5c,0x84,0xbe,0xae,0xf5,0x3e,0x6e,0x24,0x4c,0x45,0xfc,0x37,0xa0, 0x27,0xc9,0x7f,0x18,0x00,0x28,0x1c,0x2c,0x32,0x00,0xc5,0xe7,0x39,0x11,0xfa,0x66, 0xd6,0x7b,0x58,0x4d,0xb8,0x87,0xae,0x9c,0x1b,0x30,0x43,0xee,0x51,0x05,0xd6,0x68, 0x0c,0x00,0x60,0x00,0x00,0xa2,0x94,0xd5,0xbe,0x99,0x27,0x17,0xe7,0x26,0xc4,0x3f, 0x6d,0x49,0x24,0x60,0x00,0x00,0x03,0x00,0x10,0x5a,0xde,0x12,0xf1,0xdf,0xc6,0x13, 0xd6,0x1e,0x86,0xf8,0xff,0x8d,0x79,0x72,0x9f,0x1a,0xb0,0x3e,0x63,0x00,0x78,0x00, 0x85,0xa5,0xbd,0x30,0x44,0x9c,0xf6,0x4b,0xec,0x3d,0x02,0x14,0x94,0xf9,0xf2,0x8e, 0xed,0xea,0x11,0xff,0x33,0xe9,0xf2,0x97,0x90,0x91,0x24,0xff,0x61,0x00,0x30,0x00, 0xc5,0x43,0x4f,0x1a,0xeb,0x25,0x8b,0xd3,0x18,0x79,0xf1,0xe6,0x61,0x06,0x00,0x7c, 0x2f,0x67,0xdb,0xd7,0x23,0xfe,0x47,0x22,0xfe,0x49,0xe9,0x4c,0xf2,0x1f,0x06,0x00, 0x03,0x50,0x1a,0x34,0x1b,0x79,0xa0,0x2c,0x4e,0xf7,0x11,0x9a,0x04,0xf0,0x85,0x7f, 0x79,0xf6,0xb3,0xfb,0xd2,0xe2,0x37,0x29,0x7a,0x42,0x29,0xeb,0x30,0x06,0x00,0x03, 0x50,0x24,0xee,0x10,0xa1,0xff,0xa7,0x2c,0x50,0xf5,0x12,0xfc,0x5a,0x2b,0xe1,0x74, 0xf9,0x35,0x6a,0x93,0x01,0x72,0xe3,0x34,0x8f,0xf8,0x77,0x17,0xf1,0x27,0xca,0x96, 0x9c,0x43,0x49,0xfe,0xc3,0x00,0x60,0x00,0x8a,0xc7,0x64,0x67,0x31,0xd2,0x3d,0xca, 0x1b,0xc5,0x0c,0xe8,0x56,0x40,0xa5,0x04,0xbf,0x6f,0x27,0xf9,0xff,0x47,0xc8,0xaf, 0xbf,0xc9,0xe2,0x05,0x90,0x11,0x97,0x7b,0xf6,0xb2,0x3b,0xca,0x3b,0xc4,0xfb,0x93, 0x9c,0xd9,0x72,0x6f,0x6a,0xb0,0x26,0x63,0x00,0x30,0x00,0xc5,0xe3,0x86,0x04,0xa1, 0x7e,0x4d,0x0a,0x3c,0x4f,0x9c,0xf8,0x96,0x09,0x7e,0x7f,0x0d,0xe7,0x94,0xb2,0xdb, 0xe5,0xcf,0x71,0x96,0x00,0x40,0x62,0xd4,0x4c,0x57,0xb4,0xde,0x9b,0x4d,0x05,0x92, 0x6d,0x53,0x33,0x94,0xaf,0x7f,0x0c,0x00,0x06,0xa0,0xb8,0x9c,0x9b,0x26,0x19,0x49, 0x23,0x04,0x9a,0xb0,0x54,0x37,0xc1,0x9f,0x6d,0x2a,0x1c,0x2f,0xbf,0xf6,0x04,0x0b, 0x1b,0xc0,0xff,0xb8,0x53,0xc4,0xbf,0x8a,0xf5,0x9e,0x34,0x12,0x9e,0xe6,0x1d,0x49, 0xcb,0x66,0xac,0xc7,0x18,0x00,0x0c,0x40,0x71,0x39,0x22,0xc3,0x6c,0x64,0xdd,0xb7, 0xd4,0x2a,0x81,0xdd,0x93,0x6c,0x11,0x6c,0x2b,0xff,0xff,0xc5,0xf2,0x77,0x71,0x90, 0x09,0x94,0x33,0x53,0x64,0xfe,0xd7,0xb2,0xde,0x0b,0xfd,0xdf,0x53,0x78,0x27,0xd2, 0x72,0x3b,0xa5,0x7f,0x18,0x00,0x0c,0x40,0xf1,0xe9,0x21,0xc2,0x9d,0xed,0xcb,0xfa, 0xa2,0x2c,0x68,0x1a,0x39,0x68,0x9b,0xe0,0xef,0xd3,0x2f,0x9f,0xbd,0xe4,0xef,0xbc, 0x59,0x5e,0xe8,0xf9,0x2c,0x7c,0x50,0x46,0x4c,0x97,0xf9,0xde,0xd0,0xf3,0x2e,0xdc, 0x41,0x35,0x4d,0x46,0xec,0x45,0xe9,0x1f,0x06,0x00,0x03,0x50,0x7c,0x36,0xcf,0xb3, 0x23,0xe0,0x83,0xb2,0xc0,0x1d,0x91,0x64,0x8b,0xa0,0xbe,0xa0,0x25,0x50,0x93,0x31, 0x02,0x10,0x71,0x5e,0x90,0x39,0xbe,0x89,0xe7,0xb0,0xad,0xd1,0x88,0x7f,0x46,0x3c, 0x2f,0xf7,0xae,0x12,0x6b,0x31,0x06,0x00,0x03,0x50,0x7c,0xaa,0xfb,0xd4,0x12,0x58, 0xb7,0x08,0x74,0xc1,0xeb,0x91,0x64,0x8b,0x40,0xa3,0x05,0xe7,0x88,0x19,0x78,0x1e, 0x33,0x00,0x11,0xe3,0x0d,0x99,0xd3,0xed,0x3c,0xf3,0xfd,0x62,0x1a,0xfd,0x64,0xcc, 0x49,0x24,0xff,0x61,0x00,0x30,0x00,0xa5,0xe3,0x45,0x9f,0x45,0x59,0xbf,0x86,0xce, 0x4e,0xb2,0x45,0xa0,0x99,0xd1,0xda,0x12,0xf5,0x3a,0x31,0x0b,0x6f,0x63,0x06,0x20, 0xe4,0xcc,0x95,0x39,0xdc,0xd5,0x13,0xbe,0x3e,0x19,0xf1,0xcf,0x98,0x77,0xe4,0xfe, 0x35,0x66,0x0d,0xc6,0x00,0x60,0x00,0x4a,0x47,0x21,0xbb,0xfe,0x3d,0x20,0x7f,0xf7, 0xc0,0x24,0x5b,0x04,0x9a,0x20,0xd5,0x5f,0x16,0xcf,0xbb,0xe5,0xf7,0xd0,0x19,0x0d, 0xc2,0xc6,0x02,0x99,0xb3,0xbd,0x3d,0xe2,0x7f,0x18,0xe2,0x9f,0x15,0xa3,0x49,0xfe, 0xc3,0x00,0x60,0x00,0x4a,0xcb,0xb5,0x45,0xd8,0xab,0xd4,0x2d,0x82,0xeb,0xe5,0xdf, 0xd9,0x4d,0x16,0xcc,0x8a,0x09,0x7e,0x86,0x8d,0x9d,0x2f,0x27,0xca,0xa5,0x20,0x2c, 0xf4,0xf7,0x88,0xbf,0x9a,0x01,0x7a,0x63,0x64,0xc7,0x8e,0x24,0xff,0x61,0x00,0x30, 0x00,0xa5,0xe5,0x8c,0x22,0x7f,0xb5,0xe8,0x16,0xc1,0x59,0xf2,0x6f,0x6e,0x9e,0xe4, 0xe7,0xe9,0x22,0x8b,0x82,0x1e,0x93,0xfa,0x06,0x8b,0x29,0x04,0x94,0x7f,0x7b,0xf6, 0xad,0x75,0x1b,0x60,0x2e,0xf3,0x35,0x2b,0x1e,0xa7,0xef,0x3f,0x06,0x00,0x03,0x50, 0x7a,0x06,0xe4,0x50,0x0a,0xe8,0x17,0xba,0xfd,0x70,0xb8,0x2c,0xa6,0x1b,0x25,0xf8, 0xb9,0xaa,0x0a,0xfd,0xe4,0x67,0xbb,0x4d,0x7e,0xcf,0x02,0x16,0x57,0x08,0x08,0x43, 0x3c,0xe2,0xaf,0x1d,0x33,0x31,0xab,0xd9,0xf3,0x0f,0x92,0xff,0x30,0x00,0x18,0x80, 0xd2,0xd3,0xbd,0x84,0x06,0xc0,0xde,0x22,0xd0,0xc4,0xc0,0x5d,0x93,0x6c,0x11,0x68, 0x37,0xb5,0xc1,0xb2,0x60,0x4c,0x65,0xa1,0x85,0x12,0x72,0xb5,0x67,0xcf,0xba,0x85, 0xf0,0x02,0x73,0x32,0x6b,0xde,0xf2,0x34,0x4c,0x02,0x0c,0x00,0x06,0xa0,0x44,0xb4, 0xf4,0xa9,0x14,0xd0,0xcf,0xba,0xe0,0x33,0x45,0xec,0xdb,0x24,0xf9,0x79,0x3b,0x08, 0x17,0xc8,0xaf,0xbf,0xcc,0xc2,0x0b,0x45,0xe4,0x56,0x11,0xff,0xca,0x9e,0x3e,0x17, 0xd3,0x98,0x83,0x39,0x71,0x29,0x5f,0xff,0x18,0x00,0x0c,0x40,0x30,0xd0,0x45,0x2d, 0xa8,0xc9,0x4b,0xba,0x45,0xa0,0x99,0xd5,0x75,0x12,0xfc,0xdc,0xda,0x6f,0x40,0x4f, 0x2f,0xd4,0x03,0x8d,0x38,0x62,0x15,0x0a,0x3d,0x0f,0xab,0x5b,0x73,0xaf,0xa6,0xf0, 0x20,0x8d,0x7e,0x72,0x66,0x4b,0xd6,0x5d,0x0c,0x00,0x06,0x20,0x38,0x3c,0x1b,0x70, 0x01,0xd5,0x04,0x2b,0xad,0x56,0xd8,0x59,0x04,0xbf,0x42,0x82,0x9f,0x5f,0x73,0x08, 0xb4,0xdc,0xf0,0x7e,0x16,0x65,0xf0,0x99,0xc7,0x64,0xee,0xd5,0xf5,0x18,0xe6,0xf1, 0xcc,0xb3,0x9c,0xb9,0x87,0xd2,0x3f,0x0c,0x00,0x06,0x20,0x58,0x4c,0x0c,0xd1,0x82, 0x36,0x4b,0x16,0x64,0xad,0x5c,0x68,0x9d,0xe4,0x5a,0x5a,0x3b,0x95,0x0d,0xcf,0x11, 0x15,0x80,0x3c,0x51,0x63,0xdc,0xd4,0x33,0xbf,0xae,0x41,0xfc,0xf3,0x62,0x5f,0x4a, 0xff,0x30,0x00,0x18,0x80,0x60,0x71,0x55,0x48,0x17,0xb5,0x7b,0xe5,0xe7,0xd6,0x2a, 0x86,0xda,0x49,0xae,0x6b,0x27,0xf9,0xb5,0x11,0xf2,0x7b,0xde,0xc2,0x0c,0x40,0x96, 0xe8,0xc9,0x96,0xde,0x3c,0x94,0x21,0x34,0xfa,0xc9,0x8b,0x97,0xe4,0x9e,0x56,0x61, 0xbd,0xc5,0x00,0x60,0x00,0x82,0xc5,0x49,0x21,0x5f,0xd8,0xb4,0xad,0xb0,0x7e,0x99, 0x75,0x4f,0xb2,0x45,0x50,0x43,0x38,0x50,0x7e,0xed,0x0e,0xba,0x0e,0x42,0x86,0x59, 0xea,0x5b,0x7b,0xbe,0x54,0x8f,0x43,0xfc,0xf3,0xe6,0x0c,0x92,0xff,0x30,0x00,0x18, 0x80,0xe0,0x71,0x40,0x00,0x4a,0x01,0xfd,0x62,0xa6,0x2c,0xde,0xa7,0xc9,0x42,0xd3, 0x2a,0xc9,0xb5,0x36,0x13,0x4e,0x90,0x5f,0x7f,0x12,0x23,0x00,0x09,0xd0,0x63,0xac, 0x77,0xf6,0x88,0xff,0x41,0x11,0x7a,0x3f,0x4a,0x85,0x26,0x1a,0x37,0x67,0xad,0xc5, 0x00,0x60,0x00,0x82,0x47,0x97,0x88,0x2e,0x70,0x9a,0x70,0xa4,0x2d,0x5b,0x93,0xd5, 0x1c,0x6f,0x2b,0xbf,0x76,0x89,0x98,0x81,0xd7,0x30,0x03,0x20,0x68,0x74,0xa8,0xaf, 0x47,0xfc,0x77,0x97,0xff,0x7e,0x87,0xf9,0x91,0x37,0x37,0x91,0xfc,0x87,0x01,0xc0, 0x00,0x04,0x93,0x66,0x01,0xeb,0x05,0x50,0x88,0x2d,0x02,0x6d,0xe2,0xb2,0x53,0x92, 0x2d,0x02,0xdd,0x97,0xdc,0x5b,0x7e,0x6d,0xac,0xfc,0x1e,0x16,0xfb,0xf2,0xe5,0x48, 0x4f,0x88,0x5a,0x0d,0x22,0xa7,0x56,0xfa,0xc3,0x2e,0x24,0xff,0x61,0x00,0x30,0x00, 0xc1,0x44,0x45,0xb1,0x5c,0x6a,0xe9,0x35,0xb3,0xfb,0x54,0x59,0xe8,0x37,0x4d,0x72, 0x2f,0xb4,0xc1,0xcb,0xbf,0xe4,0xd7,0xa7,0xb0,0xf0,0x97,0x15,0xa7,0x7a,0xc4,0x5f, 0xcf,0xaa,0x78,0x95,0x39,0xe0,0x0b,0x4f,0xd1,0xf7,0x1f,0x03,0x80,0x01,0x08,0x36, 0x4f,0x95,0xe1,0x62,0x77,0x97,0x7c,0xf1,0x1f,0x22,0x5f,0x26,0x35,0x93,0xdc,0x93, 0xb6,0xc2,0xb9,0x22,0x0c,0xb4,0x7b,0x2d,0xaf,0xce,0x74,0x1a,0x11,0x9b,0xc9,0x33, 0xf7,0x8d,0x41,0x24,0xff,0x61,0x00,0x30,0x00,0xc1,0x66,0x42,0x19,0xd7,0x37,0xcf, 0x91,0xc5,0x5e,0xcb,0x05,0xbb,0x25,0x09,0x53,0xea,0xf9,0x04,0x7a,0x94,0xb1,0x9e, 0x57,0xc0,0xa9,0x6f,0xd1,0x62,0x8c,0x3c,0x53,0x7b,0x5b,0x48,0x9b,0xfe,0x3c,0xc6, 0x33,0xf6,0x75,0xfb,0xad,0x2e,0xeb,0x2b,0x06,0x00,0x03,0x10,0x6c,0x2e,0xa3,0xc1, 0x49,0x9c,0x19,0xb2,0x60,0x9d,0x22,0x5f,0x2c,0x2d,0x93,0xdc,0xa7,0xda,0xce,0x09, 0x8a,0xf7,0x70,0xbf,0x42,0x8f,0x96,0x85,0xda,0x75,0xe9,0xda,0xee,0x77,0x12,0xcf, 0xd5,0x57,0xae,0x24,0xf9,0x0f,0x03,0x80,0x01,0x08,0x3e,0xd4,0x39,0xff,0x3d,0x23, 0x5c,0x3b,0x24,0x1e,0x9c,0x62,0x8b,0x60,0x13,0x41,0xcd,0xc2,0x33,0x7c,0x31,0x86, 0x8e,0xc9,0xf2,0xcc,0x6a,0x7a,0xce,0x96,0xb8,0x05,0xf1,0xf7,0x9d,0x4e,0x24,0xff, 0x61,0x00,0x30,0x00,0xc1,0xa7,0x2f,0xb5,0xce,0x29,0x1b,0xc3,0x68,0xb7,0xc4,0x1d, 0x52,0x2c,0x66,0x5d,0xe5,0xd7,0xae,0x90,0xdf,0x33,0x1b,0x33,0x10,0x8a,0xa4,0xb4, 0x06,0x9e,0xe7,0x77,0x25,0xe2,0xef,0x3b,0xff,0xc7,0xde,0x3f,0x06,0x00,0x03,0x10, 0x0e,0xb6,0xc1,0x00,0x64,0xbc,0x45,0x70,0xb2,0x2c,0x6c,0x1b,0x27,0xb9,0x8f,0xd5, 0x04,0xed,0x77,0xae,0x07,0xc6,0x2c,0xc0,0x0c,0x04,0x0e,0x4d,0xe8,0xf4,0x3e,0xbb, 0xb3,0x88,0x7e,0xf9,0xce,0x39,0x88,0x3f,0x06,0x00,0x03,0x10,0x1e,0x1a,0x44,0xbc, 0x17,0x40,0x21,0xb6,0x08,0xee,0x14,0x91,0x3f,0x30,0xc5,0x16,0x81,0x4c,0x66,0x73, 0xac,0x2c,0x84,0x53,0x31,0x02,0x81,0xe0,0x75,0x79,0x0e,0xde,0xa3,0x68,0xff,0x85, 0xf8,0xfb,0xce,0x85,0x88,0x3f,0x06,0x00,0x03,0x10,0x3e,0xe6,0x20,0x54,0x39,0xf1, 0xa6,0xdc,0x37,0x0d,0x21,0x77,0x4d,0xb1,0x45,0xd0,0x51,0x7e,0x6d,0xa8,0x2c,0x8c, 0x2f,0x73,0x8f,0x4b,0x76,0xa4,0x74,0x17,0xcf,0xf3,0xd1,0x48,0x0d,0x67,0x43,0xf8, 0xcb,0x30,0x92,0xfe,0x30,0x00,0x18,0x80,0x70,0xc2,0x97,0x6a,0xfe,0x68,0x42,0xa0, 0xee,0x7d,0xb6,0x48,0x72,0x8f,0xf5,0x3c,0xf9,0x3d,0x44,0x78,0x6e,0x94,0x85,0x72, 0x1e,0xf7,0xbb,0x28,0xe8,0x56,0x4c,0x2f,0x8f,0xf8,0x6b,0xbf,0xff,0xf9,0xdc,0x7f, 0x5f,0xb9,0xda,0x53,0x52,0x09,0x18,0x00,0x0c,0x40,0x88,0x20,0x0b,0xda,0xdf,0x2d, 0x02,0x2d,0x33,0xd3,0x83,0x96,0x6a,0x24,0xb9,0xdf,0x5a,0x1f,0x7d,0x84,0x98,0x85, 0x07,0xb8,0xef,0x05,0xe5,0x60,0x8f,0xf8,0x6b,0x66,0xfa,0x9b,0x88,0xbf,0xaf,0x8c, 0x96,0x39,0x5c,0x91,0x35,0x14,0x03,0x80,0x01,0x08,0x2f,0x17,0xb2,0x1f,0x5a,0xb0, 0x2d,0x02,0xad,0x10,0xe8,0x92,0x62,0x8b,0x40,0xcf,0x9e,0x3f,0x53,0xee,0x3f,0x1d, 0xe8,0xfc,0xe5,0x58,0xcf,0x7e,0xb4,0x9e,0x12,0xc9,0x36,0x8c,0xbf,0xdc,0x2c,0x73, 0xbb,0x32,0xeb,0x27,0x06,0x00,0x03,0x10,0x6e,0x8e,0xc6,0x00,0x14,0x9c,0xe9,0x22, 0x3e,0x27,0xa6,0xd8,0x22,0xd0,0x10,0x6a,0x77,0x31,0x0a,0x1a,0x4e,0x7d,0x0b,0xa1, 0xca,0x8b,0xf3,0x3c,0xe2,0xdf,0x48,0x98,0xc1,0x3d,0xf5,0x95,0xf1,0x9e,0x66,0x4a, 0x80,0x01,0xc0,0x00,0x84,0x94,0xde,0x94,0x02,0x16,0x75,0x8b,0xe0,0xbf,0xb2,0x78, 0xee,0x2f,0xf7,0xbc,0x7a,0x92,0xe7,0x51,0xd3,0x39,0x8b,0x5e,0xab,0x0d,0x48,0x56, 0xcb,0x8e,0x11,0x9e,0x64,0x34,0xed,0xe0,0xf8,0x08,0xf7,0xd0,0x57,0x74,0x5e,0x56, 0x63,0xdd,0xc4,0x00,0x60,0x00,0xa2,0x41,0x7b,0x4a,0x01,0x4b,0xb6,0x45,0xa0,0xd9, 0xd3,0xdb,0xa7,0xd8,0x22,0x68,0x2e,0x68,0xe4,0x60,0x1a,0x22,0x96,0x16,0xcd,0x65, 0xa9,0x64,0xdd,0xbb,0xaa,0xc2,0x44,0xf2,0x2c,0x7c,0x45,0x5b,0x26,0xd7,0x64,0xcd, 0xc4,0x00,0x60,0x00,0xa2,0x43,0x1d,0x0c,0x40,0x20,0xba,0xd4,0x9d,0x20,0x42,0xdf, 0x3c,0xc5,0x73,0xd2,0x73,0xea,0xf5,0x04,0xbb,0xd7,0x30,0x03,0x7f,0xe3,0x5e,0x11, 0xa6,0xea,0x9e,0x83,0x9c,0x6e,0x44,0xfc,0x7d,0xe5,0x41,0xb9,0x9f,0xb5,0x59,0x2f, 0x31,0x00,0x18,0x80,0xe8,0xf1,0x3a,0xa2,0x12,0x08,0x16,0xca,0x73,0xd0,0x13,0x1a, 0xf7,0x13,0xb1,0x4f,0x16,0x66,0xd5,0xbd,0xd7,0x7d,0xe4,0xd7,0xf5,0x8b,0xf7,0x1d, 0x9e,0x5b,0xbc,0x8c,0x75,0x23,0x0e,0xb9,0x2a,0x28,0x8f,0x70,0xba,0x1f,0x06,0x00, 0x03,0x10,0x5d,0x26,0x23,0x24,0x81,0x43,0xcf,0x17,0xb8,0x5c,0x84,0xac,0x73,0x8a, 0x2d,0x02,0xed,0xe4,0x78,0x94,0x44,0x05,0xa6,0x94,0xe9,0xf3,0xd3,0xe4,0xbe,0x26, 0x9e,0x7b,0x72,0x2a,0x49,0xad,0xbe,0xf2,0xb8,0xdc,0xe3,0xfa,0xac,0x91,0x18,0x00, 0x0c,0x40,0x74,0xb9,0x81,0x2f,0xa6,0x40,0xa3,0x39,0x00,0xc7,0x8b,0xb0,0x35,0x4d, 0xf1,0x0c,0xb5,0xdd,0xad,0x66,0xc0,0xbf,0x50,0x26,0x66,0xe0,0x15,0xb9,0xce,0xd6, 0x9e,0x7b,0x30,0x10,0xf1,0xf7,0x7d,0x6b,0xaa,0x11,0xeb,0x23,0x06,0x00,0x03,0x10, 0x6d,0xce,0x65,0xe1,0x0c,0xcd,0x16,0x81,0x96,0x60,0xf5,0x4b,0xb1,0x45,0xa0,0xfb, 0xdf,0x3d,0xe4,0xd7,0xaf,0x97,0xdf,0x37,0x37,0xa2,0x66,0x40,0x13,0x28,0xb7,0xf2, 0x44,0x46,0xf6,0x96,0xff,0x5e,0x48,0x24,0xcb,0xd7,0xe8,0x4a,0x73,0xd6,0x46,0x0c, 0x00,0x06,0x20,0xfa,0xfc,0x03,0x03,0x10,0x3a,0xde,0x90,0x05,0x5a,0xf7,0xba,0xb7, 0x4d,0xb1,0x45,0xa0,0x49,0x5b,0x87,0xca,0xb3,0xbd,0x27,0x42,0x11,0x1e,0x6d,0xa5, 0xdc,0xdd,0x73,0xcd,0x3b,0xca,0x7f,0xd3,0x62,0xd9,0x3f,0x66,0xc9,0xbd,0xdc,0x84, 0x75,0x11,0x03,0x80,0x01,0x28,0x0f,0x7a,0xd0,0x0b,0x20,0xd4,0x3c,0x29,0x0b,0xf6, 0xbf,0x45,0xe8,0x9b,0xa4,0x78,0xc6,0x2d,0x9d,0xfd,0xf1,0x30,0x37,0xc5,0xd1,0x2f, 0xfc,0x3e,0x1e,0xf1,0xd7,0x32,0xd6,0xd9,0x88,0xbf,0x6f,0xbc,0x98,0x60,0x6b,0x05, 0x30,0x00,0x18,0x80,0x08,0xb3,0x39,0xa5,0x80,0x91,0xd9,0x22,0xb8,0x4d,0xbe,0xf6, 0xfb,0x8a,0x48,0x56,0x4d,0xf1,0xbc,0xf5,0x04,0xc3,0xe1,0xf2,0xfb,0xc2,0xd6,0x1b, 0xff,0x08,0x4f,0x97,0x3f,0xfd,0x4a,0x7d,0x01,0xf1,0xf7,0x8d,0x57,0xe5,0x5e,0xb6, 0x65,0x3d,0xc4,0x00,0x60,0x00,0xca,0x8b,0xea,0x18,0x80,0xc8,0xa1,0xa5,0x9d,0x97, 0x88,0x60,0x6e,0x93,0x62,0x8b,0x40,0x9f,0xbb,0x96,0x1c,0x6a,0x5e,0x41,0xd0,0xf7, 0xcf,0x4f,0xf6,0x88,0xbf,0x56,0x40,0x3c,0x85,0xf8,0xfb,0x3a,0x5f,0x3a,0xb0,0x16, 0x62,0x00,0x30,0x00,0xe5,0xc9,0x8b,0x2c,0xa6,0x91,0xe5,0x09,0x79,0xb6,0x7a,0x40, 0x4e,0xe3,0x14,0xcf,0x5f,0xb7,0x0f,0xf4,0xf7,0x3c,0x16,0xc0,0x79,0x70,0xb1,0x47, 0xfc,0x6b,0x52,0xba,0xea,0x7b,0x52,0x65,0x2a,0xa3,0x08,0x18,0x00,0x0c,0x40,0xc4, 0xb9,0x8f,0x52,0xc0,0xc8,0xb3,0x40,0x16,0xfa,0x5b,0xe5,0x39,0xeb,0x3e,0x7a,0xaa, 0xc3,0x5c,0x34,0xc3,0x5e,0x4f,0x89,0x7c,0x25,0x00,0x22,0x3b,0xca,0x73,0xde,0xbc, 0xfe,0xdc,0xff,0x65,0xae,0xfa,0xc6,0x1c,0x79,0xc6,0x5d,0x10,0x7f,0xc0,0x00,0x94, 0x37,0xd7,0xb1,0xa8,0x96,0x15,0xda,0x52,0x58,0xbf,0xac,0xb7,0x4e,0xb1,0xf8,0x57, 0x76,0x0e,0x8b,0xd2,0xb6,0xba,0xa5,0xc8,0xb2,0xff,0xaf,0xe7,0xd4,0xb9,0x0a,0xcc, 0x53,0x5f,0x99,0x9b,0xa0,0xa2,0x02,0x30,0x00,0x18,0x80,0x32,0xe4,0x0c,0x4a,0x01, 0xcb,0x16,0x0d,0xfb,0x0f,0x96,0xe7,0x9f,0xaa,0xe9,0x4b,0x5d,0xa7,0x5c,0xf4,0x81, 0x22,0x09,0xf0,0x43,0xf2,0x33,0x79,0x0f,0x9e,0x19,0xca,0x1c,0xf5,0x8d,0xf9,0x72, 0x7f,0x7b,0x20,0xfe,0x80,0x01,0x00,0x65,0x00,0xa5,0x80,0x6c,0x11,0x88,0x28,0xe8, 0x19,0x03,0xfb,0xa4,0xd9,0x22,0x90,0x17,0xd5,0x9c,0x25,0x62,0x3c,0xab,0x40,0x51, 0x81,0x69,0x09,0xda,0xcf,0x9e,0x80,0xf8,0xfb,0x86,0x9e,0x21,0xb1,0x27,0xe2,0x0f, 0x18,0x00,0x70,0xe9,0x8e,0x01,0x00,0x4f,0x49,0xd8,0x45,0x22,0xba,0x5b,0xa5,0x10, 0x8a,0x0a,0xce,0xbc,0xb9,0x5a,0x4c,0xc3,0x1c,0x9f,0xcc,0xc0,0xf3,0xf2,0xf7,0xb4, 0xf0,0xfc,0x3b,0xfd,0x99,0x9b,0xbe,0x96,0x8a,0xf6,0x43,0xfc,0x01,0x03,0x00,0xde, 0x46,0x31,0x2c,0x90,0x90,0xec,0xc4,0xbd,0x63,0xd2,0x6c,0x11,0x68,0xb8,0xfe,0x60, 0x11,0x96,0x3b,0xc5,0x0c,0x2c,0xca,0xd1,0x0c,0x68,0x29,0xda,0x16,0x9e,0xbf,0xb7, 0x97,0xfc,0x9d,0x0b,0xc8,0xf8,0xf7,0x05,0x7d,0x2e,0x07,0x23,0xfe,0x80,0x01,0x80, 0x44,0x09,0x5f,0xf4,0x52,0x87,0x74,0xa1,0xe3,0xb1,0x22,0xf0,0x7b,0xa5,0xd9,0x22, 0xd0,0x2f,0xf8,0x13,0xc5,0x30,0x4c,0xcb,0x62,0x3e,0xbd,0x2d,0xbf,0x77,0x3b,0x8f, 0x38,0x6d,0x2f,0xff,0xfd,0x36,0x73,0xd2,0x37,0x06,0x7a,0xca,0x29,0x01,0x30,0x00, 0xf0,0x3f,0x9e,0x63,0xb1,0x85,0x2c,0xb6,0x08,0xb4,0x54,0xb0,0x63,0x9a,0x2f,0x4a, 0x3d,0xce,0xf8,0x52,0xf9,0x7d,0xaf,0xa7,0x98,0x5b,0x6a,0x2c,0x76,0xf7,0xfc,0x3d, 0xda,0x91,0xee,0x75,0xe6,0xa3,0x6f,0x1c,0x85,0xf8,0x03,0x06,0x00,0x52,0x31,0x91, 0x12,0x2b,0xc8,0x81,0x47,0x45,0xa8,0x8f,0x16,0x81,0x69,0x98,0x62,0x6e,0x69,0xc4, 0x40,0xfb,0x0f,0x68,0x92,0xe1,0x3b,0x96,0xb0,0x6b,0x58,0xfa,0x40,0x8f,0xf8,0xeb, 0x29,0x74,0xb3,0x10,0x7f,0xdf,0x38,0x1e,0xf1,0x07,0x0c,0x00,0xa4,0xe3,0x2a,0x0c, 0x00,0xe4,0xb9,0x45,0x70,0xb3,0xcc,0xa1,0x3d,0xd3,0x6c,0x11,0xa8,0x51,0x50,0xc3, 0xf0,0xb0,0x93,0x5b,0xe0,0x2d,0x37,0x7c,0x02,0xf1,0x2f,0x58,0x0b,0x65,0x00,0x0c, 0x00,0x24,0xe4,0x24,0x4a,0xad,0xc0,0x27,0xb4,0x8b,0xe0,0x05,0x32,0x9f,0xb2,0xe9, 0x2f,0x5f,0x83,0x8e,0x94,0xbe,0x72,0x0e,0xe2,0x0f,0x18,0x00,0xc8,0x94,0x03,0x29, 0xb7,0x82,0x02,0xf0,0x88,0x98,0x01,0xdd,0x83,0x6e,0x90,0x62,0xee,0xc9,0xc2,0x10, 0x6f,0x53,0xcc,0xfd,0xf2,0x87,0x8b,0x10,0x7f,0xc0,0x00,0x40,0x36,0x74,0xc5,0x00, 0x40,0x81,0xbb,0xcf,0xfd,0x47,0x44,0x5e,0xdb,0x0b,0x57,0xf6,0xcc,0xbd,0x11,0x88, 0xbf,0x6f,0x0c,0x93,0x7b,0xc9,0x7a,0x06,0x18,0x00,0xc8,0x8a,0x66,0xf4,0x02,0x80, 0x22,0xf1,0xb2,0x98,0x81,0x21,0xf2,0x95,0xda,0x5e,0xe6,0xdc,0x39,0x6c,0x3d,0xf9, 0xc6,0x48,0xcf,0xe1,0x49,0x00,0x18,0x00,0xc8,0x08,0x5d,0x38,0xe6,0x93,0x80,0x05, 0x10,0x4a,0x46,0x8b,0xf8,0x57,0x64,0x1d,0x03,0x0c,0x00,0xe4,0xca,0x53,0x18,0x00, 0x80,0xd0,0xa1,0xd5,0x17,0x95,0x59,0xbf,0x00,0x03,0x00,0xf9,0x30,0x81,0xbd,0x58, 0x80,0x50,0x31,0xde,0x73,0x6c,0x32,0x00,0x06,0x00,0x72,0xe2,0x72,0x0c,0x00,0x40, 0x68,0xd0,0xe6,0x5d,0xd5,0x58,0xb7,0x00,0x03,0x00,0x7e,0x70,0x1c,0x09,0x59,0x00, 0xa1,0x60,0x92,0x88,0x7f,0x4d,0xd6,0x2c,0xc0,0x00,0x80,0x5f,0xf4,0xa5,0x14,0x10, 0x20,0xf0,0x3c,0x24,0xb9,0x3a,0xb5,0x59,0xaf,0x00,0x03,0x00,0x7e,0xb2,0x0d,0x06, 0x00,0x20,0xf0,0x8d,0x95,0xea,0xb2,0x56,0x01,0x06,0x00,0xfc,0xa6,0x01,0xbd,0x00, 0x00,0x02,0x8b,0x9e,0x93,0xd0,0x80,0x75,0x0a,0x30,0x00,0x50,0x28,0xe6,0x50,0x0a, 0x08,0x10,0x38,0xb4,0x44,0xb7,0x31,0xeb,0x13,0x60,0x00,0xa0,0x90,0x3c,0x86,0x01, 0x00,0x08,0x14,0x33,0xe4,0x9d,0x6c,0xce,0xda,0x04,0x18,0x00,0x28,0x34,0xb7,0x50, 0x0a,0x08,0x10,0x18,0x66,0x89,0xf8,0x6f,0xc2,0xba,0x04,0x18,0x00,0x28,0x06,0x17, 0x52,0x0a,0x08,0x10,0x08,0x5e,0x14,0xf1,0x6f,0xcd,0x9a,0x04,0x18,0x00,0x28,0x16, 0x47,0x63,0x00,0x00,0x4a,0xce,0xab,0x22,0xfe,0x6d,0x59,0x8f,0x00,0x03,0x00,0xc5, 0x64,0x4f,0x4a,0x01,0x01,0x4a,0xca,0xeb,0x22,0xfe,0x1d,0x58,0x8b,0x00,0x03,0x00, 0xc5,0xa6,0x03,0xa5,0x80,0x00,0x25,0xe3,0x4d,0x11,0xff,0x6d,0xc5,0x84,0xb3,0x16, 0x01,0x06,0x00,0x8a,0x4e,0x1d,0x0c,0x00,0x40,0x49,0xd0,0x12,0xdc,0xae,0x88,0x3f, 0x60,0x00,0xa0,0x94,0x74,0x92,0x45,0x68,0x84,0x54,0x03,0xcc,0xa5,0x24,0x10,0xa0, 0x28,0xcc,0x93,0x77,0xad,0x3b,0xe2,0x0f,0x18,0x00,0x08,0x0a,0xda,0x72,0xf4,0x58, 0x49,0x0a,0x9c,0x8e,0x11,0x00,0x28,0x18,0xf3,0xe5,0xfd,0xea,0x81,0xf8,0x03,0x06, 0x00,0x82,0x8a,0x2e,0x50,0xda,0x23,0x60,0x21,0x66,0x00,0xc0,0x37,0xde,0x91,0xf7, 0x69,0x4f,0xc4,0x1f,0x30,0x00,0x3c,0x84,0x30,0xd0,0x42,0x38,0x4b,0xa2,0x02,0x2f, 0x63,0x04,0x00,0xf2,0x42,0xcd,0x74,0x3f,0xc4,0x1f,0x30,0x00,0x18,0x80,0xb0,0x21, 0x0f,0xd2,0x1c,0x20,0x8b,0xd7,0x7d,0x74,0x0e,0x04,0xc8,0x9a,0x45,0x22,0xfe,0x07, 0x23,0xfe,0x80,0x01,0xc0,0x00,0x84,0x9d,0xf6,0xc2,0x30,0x31,0x02,0x1c,0x24,0x04, 0x90,0x19,0x03,0x25,0x8a,0xc6,0xda,0x01,0x18,0x00,0x0c,0x40,0xa4,0x4a,0x08,0x8f, 0x92,0x85,0xed,0x49,0x8c,0x00,0x40,0x52,0x8e,0x46,0xfc,0x01,0x03,0x80,0x01,0x88, 0x32,0x5a,0xd2,0x74,0xa3,0x44,0x05,0x16,0x60,0x06,0x00,0xfe,0xc7,0xf1,0x88,0x3f, 0x60,0x00,0x30,0x00,0xe5,0x42,0x53,0xe1,0x34,0x59,0xf4,0x5e,0xc0,0x08,0x40,0x99, 0x73,0x0a,0xe2,0x0f,0x18,0x00,0x0c,0x40,0x39,0x52,0x59,0xe8,0x2b,0x51,0x81,0xbb, 0x49,0x1a,0x84,0x32,0xe4,0x5c,0xc4,0x1f,0x30,0x00,0x18,0x00,0x88,0xc5,0x4f,0x39, 0xbb,0x44,0x16,0xc4,0x37,0x89,0x0a,0x40,0x19,0x70,0x11,0xe2,0x0f,0x18,0x00,0x0c, 0x00,0x6c,0x48,0x4d,0xe1,0x1f,0xb2,0x38,0x4e,0xc5,0x08,0x40,0x44,0xd1,0xea,0x18, 0xde,0x75,0xc0,0x00,0x60,0x00,0x20,0x05,0x3b,0xc8,0xf6,0xc0,0x28,0x59,0x2c,0xe7, 0x63,0x06,0x20,0x22,0x8c,0x94,0xf9,0x5c,0x81,0x77,0x1b,0x30,0x00,0x18,0x00,0xc8, 0x8c,0x46,0xc2,0x49,0x12,0x15,0x98,0x85,0x11,0x80,0x10,0x33,0x5a,0xc4,0xbf,0x22, 0xef,0x33,0x60,0x00,0x30,0x00,0x90,0x3d,0x32,0x59,0xcc,0x5e,0x12,0x15,0xb8,0x83, 0xa4,0x41,0x08,0x19,0x63,0x65,0xce,0x56,0xe6,0x1d,0x06,0x0c,0x00,0x06,0x00,0xf2, 0xa7,0x8d,0x30,0x54,0xa2,0x02,0x6f,0x10,0x15,0x80,0x80,0x33,0x5e,0xc4,0xbf,0x0a, 0xef,0x2c,0x60,0x00,0x30,0x00,0xe0,0x2f,0x35,0x84,0xc3,0xc4,0x08,0x3c,0x8c,0x11, 0x80,0x00,0x32,0x51,0xc4,0xbf,0x1a,0xef,0x29,0x60,0x00,0x30,0x00,0x50,0x58,0xb6, 0x93,0xed,0x81,0x6b,0x64,0xc1,0x9d,0x87,0x19,0x80,0x00,0x30,0x49,0xe6,0x62,0x4d, 0xde,0x4b,0xc0,0x00,0x60,0x00,0xa0,0x78,0xd4,0x17,0xb4,0xbd,0xea,0x0c,0x8c,0x00, 0x94,0x88,0x87,0x64,0xee,0xd5,0xe6,0x5d,0x04,0x0c,0x00,0x06,0x00,0x4a,0x83,0x96, 0x5b,0xf5,0x92,0xa8,0x80,0xee,0xc1,0x2e,0xc2,0x0c,0x40,0x91,0x78,0x54,0xe6,0x5a, 0x5d,0xde,0x3f,0xc0,0x00,0x60,0x00,0x20,0x18,0xb4,0x14,0xce,0x93,0xa8,0xc0,0xab, 0x18,0x01,0x28,0x20,0x4f,0xc8,0xfc,0x6a,0xc0,0xfb,0x06,0x18,0x00,0x0c,0x00,0x04, 0x0f,0x4d,0xc8,0x3a,0x44,0xa2,0x02,0x0f,0x61,0x04,0xc0,0x67,0xa6,0xcb,0x9c,0x6a, 0xcc,0x3b,0x06,0x18,0x00,0x0c,0x00,0x04,0x9f,0x4e,0x62,0x04,0xae,0x92,0xed,0x81, 0xb9,0x98,0x01,0xc8,0x13,0xcd,0x37,0x69,0xce,0x3b,0x05,0x18,0x00,0x0c,0x00,0x84, 0x0b,0xdd,0xaf,0x1d,0x2c,0xdb,0x03,0xd3,0x31,0x02,0x90,0x03,0xcf,0xcb,0xbc,0x69, 0xc9,0x7b,0x04,0x18,0x00,0x0c,0x00,0x84,0x9b,0xdd,0x24,0x2a,0x70,0x8b,0x44,0x05, 0x16,0x62,0x06,0x20,0x03,0x5e,0x92,0x79,0xd2,0x9a,0xf7,0x06,0x30,0x00,0x18,0x00, 0x88,0x0e,0x2d,0x84,0xb3,0x24,0x2a,0xf0,0x32,0x46,0x00,0x92,0xa0,0x09,0xa5,0x5b, 0xf0,0xae,0x00,0x06,0x00,0x03,0x00,0xd1,0x44,0x5b,0xb8,0x1e,0x20,0x51,0x81,0xfb, 0x38,0x7f,0x00,0x2c,0xb4,0x05,0x75,0x07,0xde,0x0f,0xc0,0x00,0x60,0x00,0xa0,0x3c, 0x68,0x2f,0xe8,0x59,0xee,0x73,0x88,0x0a,0x94,0x35,0x6f,0xca,0xf3,0xdf,0x56,0x4c, 0x21,0xef,0x04,0x60,0x00,0x30,0x00,0x50,0x66,0x68,0x87,0xb7,0x7f,0xc9,0xf6,0xc0, 0x93,0x18,0x81,0xb2,0x43,0xcd,0x5f,0x57,0xc4,0x1f,0x30,0x00,0x18,0x00,0x80,0xee, 0x22,0x06,0x37,0x4a,0x54,0x60,0x01,0x66,0x20,0xf2,0xe8,0x19,0x13,0xdd,0x11,0x7f, 0xc0,0x00,0x60,0x00,0x00,0x6c,0x9a,0x0a,0xa7,0x4a,0x54,0xe0,0x05,0x8c,0x40,0x24, 0x99,0x2f,0xcf,0xb5,0x07,0xe2,0x0f,0x18,0x00,0x0c,0x00,0x40,0x32,0x2a,0x0b,0x7d, 0x45,0x28,0xee,0x22,0x69,0x30,0x32,0xbc,0x23,0xe2,0xbf,0x27,0xe2,0x0f,0x18,0x00, 0x0c,0x00,0x40,0xa6,0xb4,0x15,0x2e,0x96,0xa8,0xc0,0x9b,0x44,0x05,0x42,0x8b,0xf6, 0x83,0xd8,0x17,0xf1,0x07,0x0c,0x00,0x06,0x00,0x20,0x17,0xf4,0x4c,0xf8,0x23,0xc4, 0x08,0x4c,0xc5,0x08,0x84,0x0a,0x3d,0x41,0xf2,0x10,0xc4,0x1f,0x30,0x00,0x18,0x00, 0x00,0x3f,0xd0,0x0c,0xf2,0x51,0xb2,0x3d,0x30,0x1f,0x33,0x10,0x78,0x06,0x8a,0x69, 0x63,0xce,0x02,0x06,0x00,0x03,0x00,0xe0,0x2b,0x8d,0x84,0xff,0x13,0x81,0x99,0x85, 0x11,0x08,0x24,0x47,0x23,0xfe,0x00,0x18,0x00,0x80,0x42,0x22,0x2f,0x80,0xd9,0x4b, 0xa2,0x02,0xb7,0x93,0x34,0x18,0x18,0x4e,0x40,0xfc,0x01,0x30,0x00,0x00,0xc5,0xa4, 0xb5,0x70,0x81,0x88,0xcf,0x1b,0x44,0x05,0x4a,0xc6,0xa9,0x88,0x3f,0x00,0x06,0x00, 0xa0,0x54,0xd4,0x10,0x0e,0x15,0x21,0x9a,0x82,0x11,0x28,0x2a,0xe7,0x22,0xfe,0x00, 0x18,0x00,0x80,0xa0,0xd0,0x59,0xb6,0x07,0xae,0x91,0xed,0x81,0x79,0x98,0x81,0x82, 0x72,0x31,0xe2,0x0f,0x80,0x01,0x00,0x08,0x22,0xf5,0x85,0xe3,0x44,0xa4,0x66,0x60, 0x04,0x7c,0xe7,0x0a,0x31,0x58,0xcc,0x31,0x00,0x0c,0x00,0x40,0xa0,0x91,0x97,0xc6, 0xf4,0x92,0xa8,0xc0,0x6d,0x22,0x5a,0x8b,0x30,0x03,0x79,0x33,0x52,0xee,0x63,0x05, 0xe6,0x15,0x00,0x06,0x00,0x20,0x4c,0xb4,0x14,0x74,0xdf,0xfa,0x55,0x8c,0x40,0x4e, 0x8c,0x11,0xf1,0xaf,0xc8,0x3c,0x02,0xc0,0x00,0x00,0x84,0x95,0xaa,0xc2,0xc1,0x12, 0x15,0x78,0x90,0x52,0xc2,0x8c,0x19,0x2b,0xf7,0xaa,0x32,0x73,0x07,0x00,0x03,0x00, 0x10,0x15,0x3a,0x89,0x11,0xb8,0x4a,0xc4,0x6d,0x2e,0x51,0x81,0xa4,0x4c,0x90,0xfb, 0x53,0x85,0xb9,0x02,0x80,0x01,0x00,0x88,0x22,0x75,0x85,0x63,0x64,0x7b,0x60,0x3a, 0x46,0x60,0x03,0x26,0x8a,0xf8,0x57,0x63,0x7e,0x00,0x60,0x00,0x00,0xca,0x81,0xdd, 0x24,0x2a,0xa0,0x21,0xef,0x85,0x65,0x6e,0x06,0x26,0xc9,0x3d,0xa8,0xc9,0x7c,0x00, 0xc0,0x00,0x00,0x94,0x1b,0x2d,0x84,0x33,0x25,0x2a,0xf0,0x72,0x19,0x1a,0x81,0x87, 0xe4,0x9a,0x6b,0x33,0x07,0x00,0x30,0x00,0x00,0xe5,0x8c,0xee,0x7f,0xef,0x2f,0x51, 0x81,0x49,0x65,0x92,0x34,0xf8,0xa8,0x88,0x7f,0x5d,0x9e,0x3b,0x00,0x06,0x00,0x00, 0xd6,0xd3,0x5e,0x18,0x26,0x46,0x60,0x4e,0x44,0xa3,0x02,0x4f,0xc8,0x75,0x35,0xe0, 0x39,0x03,0x60,0x00,0x00,0x20,0x31,0x1a,0x1e,0xff,0x97,0x6c,0x0f,0x3c,0x19,0x21, 0x23,0xa0,0x09,0x90,0x8d,0x79,0xb6,0x00,0x18,0x00,0x00,0xc8,0x8c,0xee,0xb2,0x3d, 0x70,0xa3,0x44,0x05,0x16,0x84,0xd8,0x0c,0x68,0xcb,0xe4,0xe6,0x3c,0x4b,0x00,0x0c, 0x00,0x00,0x64,0x4f,0x53,0x41,0x8f,0xc7,0x7d,0x21,0x64,0x46,0xe0,0x79,0xf9,0x79, 0x5b,0xf2,0xfc,0x00,0x30,0x00,0x00,0x90,0x1f,0xda,0x31,0xaf,0xaf,0x44,0x05,0x26, 0x86,0x20,0x69,0xf0,0x25,0x11,0xff,0x36,0x3c,0x33,0x00,0x0c,0x00,0x00,0xf8,0x4b, 0x5b,0x41,0x8f,0xce,0x7d,0x33,0x80,0x51,0x01,0x3d,0x13,0x61,0x0b,0x9e,0x11,0x00, 0x06,0x00,0x00,0x0a,0x87,0x36,0xd4,0x19,0x28,0x46,0x60,0x6a,0x40,0x8c,0xc0,0x1b, 0xf2,0x73,0x74,0xe0,0xb9,0x00,0x60,0x00,0x00,0xa0,0x78,0x74,0x95,0xed,0x81,0xeb, 0x65,0x7b,0x60,0x7e,0x89,0xcc,0x80,0x46,0x23,0xb6,0x95,0x9f,0x81,0x67,0x01,0x80, 0x01,0x00,0x80,0x12,0xd0,0x48,0x38,0x51,0xa2,0x02,0x33,0x8b,0x68,0x04,0xb4,0x7f, 0x41,0x57,0xc4,0x1f,0x00,0x03,0x00,0x00,0xa5,0xa7,0xa2,0xb0,0xa7,0x88,0xf2,0x7f, 0x0b,0x9c,0x34,0x38,0x4f,0xc4,0xbf,0x3b,0xe2,0x0f,0x80,0x01,0x00,0x80,0xe0,0xd1, 0x5a,0xb8,0x40,0xa2,0x02,0x6f,0xf8,0x1c,0x15,0xd0,0xed,0x86,0xdd,0x11,0x7f,0x00, 0x0c,0x00,0x00,0x04,0x9b,0x1a,0xc2,0x00,0x11,0xec,0x29,0x3e,0x18,0x01,0x6d,0x50, 0xb4,0x17,0xe2,0x0f,0x80,0x01,0x00,0x80,0x70,0xd1,0x59,0xc4,0x7b,0xa4,0x6c,0x0f, 0xcc,0xcb,0xc1,0x0c,0xe8,0x91,0xc6,0xfb,0x22,0xfe,0x00,0x18,0x00,0x00,0x08,0x2f, 0xf5,0x85,0x7f,0xcb,0xf6,0xc0,0x8c,0x0c,0x8d,0xc0,0x22,0xf9,0x7d,0x87,0x20,0xfe, 0x00,0x18,0x00,0x00,0x88,0x06,0xb2,0x10,0x98,0x9e,0x22,0xec,0xe3,0x24,0x2a,0xb0, 0x28,0x85,0x19,0xd0,0xbe,0x03,0xdc,0x2f,0x00,0x0c,0x00,0x00,0x44,0x10,0xed,0xe1, 0x7f,0xae,0x08,0xfd,0xab,0x1e,0x23,0x70,0x34,0xe2,0x0f,0x80,0x01,0x00,0x80,0xe8, 0x53,0x55,0x38,0x48,0xa2,0x02,0x0f,0x48,0x54,0xe0,0x04,0xc4,0x1f,0x00,0x03,0x00, 0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x06,0x00, 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x0c,0x00, 0x00,0x00,0x00,0x60,0x00,0x00,0x20,0x14,0x54,0xaa,0x54,0xc9,0x54,0xaf,0x5e,0x9d, 0x7b,0x01,0x80,0x01,0x00,0x80,0x72,0x60,0xd0,0xa0,0x41,0x66,0xde,0xbc,0x79,0x66, 0xe5,0xca,0x95,0x66,0xed,0xda,0xb5,0xe6,0xa3,0x8f,0x3e,0x32,0xa3,0x46,0x8d,0x32, 0xb5,0x6b,0xd7,0xe6,0xfe,0x00,0x60,0x00,0x20,0x88,0x34,0x6e,0xdc,0xd8,0xb4,0x69, 0xd3,0x26,0x29,0x75,0xeb,0xd6,0x0d,0xfd,0x35,0x64,0x4a,0xab,0x56,0xad,0x4c,0xa3, 0x46,0x8d,0x4c,0xb5,0x6a,0xd5,0x98,0x1b,0x59,0x70,0xc3,0x0d,0x37,0x98,0x64,0xe3, 0xdd,0x77,0xdf,0x35,0x35,0x6a,0xd4,0xe0,0x3e,0x01,0x60,0x00,0x20,0x68,0x7c,0xf8, 0xe1,0x87,0x26,0xd5,0x98,0x32,0x65,0x4a,0xe8,0xaf,0x21,0x97,0xf1,0xe7,0x9f,0x7f, 0x9a,0xe5,0xcb,0x97,0x9b,0x65,0xcb,0x96,0x99,0xb7,0xdf,0x7e,0xdb,0xdc,0x73,0xcf, 0x3d,0xe6,0xbc,0xf3,0xce,0x33,0x7d,0xfa,0xf4,0x31,0x2d,0x5a,0xb4,0x60,0xee,0x38, 0x74,0xe9,0xd2,0xc5,0xac,0x59,0xb3,0x26,0xe5,0xbd,0xbc,0xfa,0xea,0xab,0xb9,0x57, 0x00,0x18,0x00,0x08,0x1a,0x1f,0x7f,0xfc,0x71,0xca,0xc5,0xfb,0xd1,0x47,0x1f,0x0d, 0xfd,0x35,0x14,0x62,0x7c,0xfb,0xed,0xb7,0x66,0xc2,0x84,0x09,0xa6,0x57,0xaf,0x5e, 0xa6,0x62,0xc5,0xf2,0xed,0x8d,0x3f,0x74,0xe8,0xd0,0xb4,0xf7,0x6a,0xc9,0x92,0x25, 0xbc,0x6b,0x00,0x18,0x00,0xc0,0x00,0x44,0xc3,0x00,0xd8,0xe3,0xf3,0xcf,0x3f,0x37, 0xd7,0x5d,0x77,0x9d,0xd9,0x6c,0xb3,0xcd,0xca,0x6e,0xfe,0xdc,0x7e,0xfb,0xed,0x69, 0xef,0xcf,0x5f,0x7f,0xfd,0x15,0x4f,0x0e,0xe4,0x7d,0x03,0xc0,0x00,0x00,0x06,0x20, 0x52,0x06,0xc0,0x1d,0x2b,0x56,0xac,0x30,0x97,0x5d,0x76,0x59,0x59,0x65,0xc1,0x6b, 0x14,0x24,0x93,0xd1,0xb0,0x61,0x43,0xde,0x37,0x00,0x0c,0x00,0x60,0x00,0xa2,0x69, 0x00,0xdc,0xa1,0x39,0x09,0x7d,0xfb,0xf6,0x2d,0x8b,0xf9,0x73,0xcb,0x2d,0xb7,0xa4, 0xbd,0x1f,0xbf,0xff,0xfe,0xbb,0xa9,0x50,0xa1,0x02,0xef,0x1b,0x00,0x06,0x00,0x30, 0x00,0xd1,0x36,0x00,0x3a,0xb4,0x14,0xee,0xb8,0xe3,0x8e,0x8b,0xfc,0xfc,0x39,0xfb, 0xec,0xb3,0xd3,0xde,0x0b,0x2d,0x0f,0xe4,0x5d,0xcb,0x8d,0xfd,0xf6,0xdb,0xcf,0x7c, 0xf2,0xc9,0x27,0x1b,0x30,0x73,0xe6,0x4c,0xee,0x0d,0x06,0x00,0x03,0x00,0x18,0x80, 0xa0,0x1a,0x00,0xd7,0x04,0x1c,0x7f,0xfc,0xf1,0x91,0x9e,0x3f,0x2d,0x5b,0xb6,0x34, 0xbf,0xfd,0xf6,0x5b,0xca,0xfb,0x70,0xca,0x29,0xa7,0xf0,0xae,0xf9,0x98,0x63,0xa1, 0x39,0x27,0xdc,0x1b,0x0c,0x00,0x06,0x00,0x30,0x00,0x19,0x5c,0x83,0xd6,0xa2,0x1f, 0x79,0xe4,0x91,0x49,0xf9,0xe7,0x3f,0xff,0x69,0x06,0x0f,0x1e,0x6c,0x4e,0x3b,0xed, 0xb4,0x78,0x56,0xfb,0x55,0x57,0x5d,0x15,0x0f,0x6d,0xcf,0x9a,0x35,0x2b,0x9e,0xed, 0x9f,0xaf,0x09,0xd0,0x26,0x39,0x51,0x9e,0x43,0x27,0x9e,0x78,0xa2,0x59,0xbd,0x7a, 0x75,0xc2,0xeb,0x9f,0x3e,0x7d,0x7a,0x59,0x57,0x49,0xe4,0x83,0xde,0xb7,0x6f,0xbe, 0xf9,0x06,0x03,0x00,0x18,0x00,0xc0,0x00,0x94,0xea,0x1a,0xb4,0x39,0x90,0x86,0x62, 0xef,0xbc,0xf3,0x4e,0xf3,0xe3,0x8f,0x3f,0x66,0x6d,0x02,0x7e,0xfd,0xf5,0x57,0xd3, 0xbc,0x79,0xf3,0x48,0xcf,0xa3,0x1d,0x77,0xdc,0xd1,0xdc,0x7f,0xff,0xfd,0x66,0xf1, 0xe2,0xc5,0xf1,0x30,0xb5,0x0a,0xbf,0x46,0x3f,0xd8,0xfb,0xcf,0x9d,0x6e,0xdd,0xba, 0x25,0xad,0x3a,0xe1,0xfe,0x60,0x00,0x30,0x00,0x80,0x01,0x28,0xf2,0x35,0x54,0xa9, 0x52,0xc5,0x1c,0x7e,0xf8,0xe1,0xf1,0x56,0xb7,0xd9,0x8c,0xbb,0xee,0xba,0x8b,0xf9, 0x06,0x59,0x31,0x7c,0xf8,0x70,0x0c,0x00,0x60,0x00,0x00,0x03,0x10,0xb4,0x6b,0xd0, 0x76,0xc1,0xba,0x5d,0xb0,0x6a,0xd5,0xaa,0x8c,0xb7,0x02,0xba,0x77,0xef,0xce,0x9c, 0x83,0x8c,0xd1,0xe4,0x49,0x0c,0x00,0x60,0x00,0x00,0x03,0x10,0xd0,0x6b,0x38,0xe8, 0xa0,0x83,0xe2,0x6d,0x83,0x33,0x19,0x8f,0x3c,0xf2,0x08,0x73,0x0e,0x32,0x62,0xd3, 0x4d,0x37,0x4d,0xd9,0x78,0x8a,0x7b,0x84,0x01,0xc0,0x00,0x00,0x06,0x20,0x00,0xd7, 0xa0,0xf9,0x01,0xfa,0x85,0x9f,0x6e,0x68,0xb6,0x3c,0x07,0x0d,0x41,0x26,0x9c,0x74, 0xd2,0x49,0x18,0x00,0xc0,0x00,0x00,0x06,0x20,0x0c,0xd7,0x90,0x49,0x4b,0x5c,0x1d, 0x7a,0x98,0x10,0xf3,0x0e,0xd2,0x31,0x6d,0xda,0x34,0x0c,0x00,0x60,0x00,0x00,0x03, 0x10,0x86,0x6b,0xd0,0x23,0x89,0x33,0xa9,0x10,0xb8,0xe9,0xa6,0x9b,0x98,0x77,0x90, 0x92,0x5a,0xb5,0x6a,0xc5,0xdb,0x4a,0x63,0x00,0x00,0x03,0x00,0x18,0x80,0x90,0x5c, 0xc3,0xb8,0x71,0xe3,0xd2,0x1a,0x80,0xb7,0xde,0x7a,0x8b,0x79,0x07,0x29,0x39,0xf0, 0xc0,0x03,0xd3,0x1e,0x3e,0xc5,0x7d,0xc2,0x00,0x60,0x00,0x00,0x03,0x10,0xa0,0x6b, 0xd0,0x5c,0x80,0x74,0xe3,0xb3,0xcf,0x3e,0x2b,0xe9,0xbd,0xd2,0xce,0x7d,0x5a,0xc6, 0x78,0xf1,0xc5,0x17,0xc7,0x4b,0x13,0x5f,0x7f,0xfd,0x75,0x33,0x77,0xee,0xdc,0xf8, 0xf9,0x05,0xaf,0xbe,0xfa,0xaa,0x79,0xf8,0xe1,0x87,0xe3,0x4d,0x90,0x2e,0xbd,0xf4, 0xd2,0x78,0x83,0x1f,0xfd,0x1a,0x8d,0xd2,0x7c,0x6f,0xdf,0xbe,0xbd,0x39,0xf9,0xe4, 0x93,0xe3,0xcd,0x9e,0x26,0x4e,0x9c,0x68,0x66,0xcc,0x98,0x11,0xef,0x5d,0xf0,0xf5, 0xd7,0x5f,0xc7,0x4b,0x3b,0xdf,0x7e,0xfb,0x6d,0xf3,0xdc,0x73,0xcf,0x99,0x29,0x53, 0xa6,0x98,0xd1,0xa3,0x47,0xc7,0xef,0x95,0x26,0xe4,0x15,0xe3,0x67,0x6b,0xd0,0xa0, 0x81,0x39,0xff,0xfc,0xf3,0xcd,0x17,0x5f,0x7c,0x81,0x01,0x00,0x0c,0x00,0x60,0x00, 0xc2,0x74,0x0d,0x7a,0x0a,0x60,0xba,0x8a,0x00,0xfd,0xf5,0x6c,0xff,0xde,0x1a,0x35, 0x6a,0x98,0x9f,0x7f,0xfe,0x39,0xfe,0x67,0xbd,0xac,0x5c,0xb9,0x32,0xde,0x9b,0x20, 0xdd,0xdf,0xd1,0xae,0x5d,0xbb,0x78,0x23,0xa3,0x4c,0xcb,0x16,0xdd,0xd1,0xa4,0x49, 0x93,0x9c,0x7f,0x36,0x97,0x7d,0xf6,0xd9,0x27,0xaf,0xfb,0x9a,0xea,0xdf,0xd0,0x6d, 0x97,0x74,0x9d,0x06,0xdb,0xb4,0x69,0x63,0x86,0x0c,0x19,0x92,0xb4,0xac,0x2e,0x93, 0xa1,0xa2,0xac,0x86,0xa0,0x10,0x47,0x3e,0xeb,0xb3,0x19,0x3b,0x76,0x6c,0xfc,0xd0, 0xa4,0x4c,0x47,0xaa,0xfb,0x9d,0x8a,0x67,0x9f,0x7d,0x96,0x75,0x0f,0x03,0x80,0x01, 0x00,0x0c,0x40,0x29,0x7e,0x16,0x1d,0x75,0xeb,0xd6,0xcd,0xea,0xef,0xac,0x5d,0xbb, 0x76,0xca,0xbf,0x6f,0x93,0x4d,0x36,0x49,0xfa,0x67,0x3b,0x76,0xec,0x68,0x1e,0x78, 0xe0,0x01,0xb3,0x66,0xcd,0x9a,0xac,0x45,0xef,0xa7,0x9f,0x7e,0xca,0xfb,0x67,0xd3, 0x31,0x60,0xc0,0x80,0xbc,0xee,0x69,0xba,0x7f,0xa3,0x6d,0xdb,0xb6,0x09,0xff,0x9c, 0x8a,0xf5,0xd3,0x4f,0x3f,0xed,0xeb,0xf9,0x0e,0x7a,0x1f,0xb5,0x9c,0x73,0xeb,0xad, 0xb7,0xce,0x7b,0xae,0xec,0xb5,0xd7,0x5e,0xe6,0xc9,0x27,0x9f,0xcc,0xa8,0x82,0xc4, 0xaf,0xc1,0x16,0x14,0x06,0x00,0x03,0x00,0x18,0x80,0x02,0x31,0x7b,0xf6,0xec,0xb4, 0x8b,0xb0,0x7e,0x91,0xfa,0x29,0x80,0x5d,0xbb,0x76,0x4d,0xf8,0xe7,0xf6,0xdf,0x7f, 0xff,0xac,0xbe,0x2a,0xbd,0x43,0xaf,0x25,0x0c,0x06,0xe0,0x90,0x43,0x0e,0xd9,0xe0, 0xf7,0x6b,0x44,0xe0,0xf4,0xd3,0x4f,0x4f,0x7b,0x48,0x51,0x3e,0x43,0x93,0xf4,0x4e, 0x38,0xe1,0x84,0x9c,0xaf,0xe9,0x99,0x67,0x9e,0x29,0xc9,0x01,0x55,0x18,0x00,0x0c, 0x00,0x06,0x00,0x30,0x00,0x05,0x42,0xf7,0x94,0x53,0x0d,0x3d,0x34,0x27,0xdb,0x73, 0x01,0xd2,0x09,0xa0,0xe6,0x1e,0x78,0xff,0x4c,0xaa,0x03,0x7a,0x32,0x1d,0xf7,0xdc, 0x73,0x4f,0x28,0x0c,0xc0,0x65,0x97,0x5d,0xf6,0xbf,0xdf,0xdb,0xaa,0x55,0x2b,0xf3, 0xca,0x2b,0xaf,0x14,0x4d,0x50,0x27,0x4d,0x9a,0x64,0x2a,0x55,0xaa,0x94,0xf5,0x35, 0xe9,0x01,0x55,0x18,0x00,0xc0,0x00,0x00,0xe2,0x19,0xa1,0x6b,0xd0,0xa4,0xba,0x74, 0x43,0x0f,0x17,0xf2,0x53,0x00,0x8f,0x3d,0xf6,0xd8,0xff,0xfd,0x5e,0x3d,0x7c,0x47, 0x13,0xdc,0xfc,0x18,0x97,0x5c,0x72,0x49,0x28,0x0c,0x80,0x26,0x2e,0xea,0xef,0xab, 0x57,0xaf,0x5e,0x3c,0xa1,0xaf,0xd8,0xe3,0xda,0x6b,0xaf,0xc5,0x00,0x00,0x06,0x00, 0x30,0x00,0xe5,0x7e,0x0d,0xe9,0x0e,0x09,0xd2,0x24,0xbc,0x6c,0x4f,0xc8,0x4b,0x27, 0x80,0x17,0x5e,0x78,0xe1,0xff,0x7e,0xaf,0x8a,0xb6,0x5f,0x63,0xe0,0xc0,0x81,0xa1, 0x30,0x00,0x5a,0xc1,0x50,0xb9,0x72,0xe5,0x78,0x82,0x5b,0xa9,0x46,0x26,0xf7,0x0a, 0x03,0x00,0x18,0x00,0x40,0x3c,0x23,0x7a,0x0d,0x2a,0xec,0xe9,0xf6,0x9d,0x35,0x9b, 0xdc,0x6f,0x01,0xfc,0xcf,0x7f,0xfe,0x13,0xff,0x7d,0x3b,0xed,0xb4,0x53,0x56,0x59, 0xfe,0xba,0x8f,0xad,0xe2,0xb9,0x74,0xe9,0xd2,0x78,0x35,0x81,0x77,0x6c,0xb7,0xdd, 0x76,0xa1,0x30,0x00,0x9a,0x44,0x77,0xdf,0x7d,0xf7,0x65,0x74,0xcd,0x9a,0x13,0xa1, 0xfb,0xef,0xfa,0xd5,0xae,0x95,0x01,0xc7,0x1d,0x77,0x5c,0xbc,0xd4,0x6f,0xd0,0xa0, 0x41,0xe6,0xac,0xb3,0xce,0x8a,0xdf,0x4b,0xad,0x16,0xc8,0x36,0x69,0xf2,0x97,0x5f, 0x7e,0x89,0x47,0x20,0x32,0xbd,0x26,0x8d,0xd2,0x3c,0xf4,0xd0,0x43,0x09,0xc9,0x24, 0x91,0x34,0xd9,0x9f,0x4d,0x47,0x26,0x51,0x1d,0xc0,0x00,0x60,0x00,0x30,0x00,0x18, 0x80,0x2c,0xe9,0xd2,0xa5,0x4b,0xda,0x85,0x5b,0xeb,0xcc,0xfd,0x16,0x40,0x5d,0xd8, 0xeb,0xd4,0xa9,0x13,0x17,0xf2,0x74,0xf9,0x07,0xfa,0x95,0xac,0xa2,0xd7,0xac,0x59, 0xb3,0xbf,0x99,0x17,0xcd,0x4d,0xd0,0x13,0x0b,0x8f,0x38,0xe2,0x08,0x73,0xce,0x39, 0xe7,0x98,0x9a,0x35,0x6b,0x86,0xc2,0x00,0xa4,0x1b,0x7f,0xfd,0xf5,0x97,0xb9,0xf5, 0xd6,0x5b,0xcd,0xae,0xbb,0xee,0x6a,0xaa,0x56,0xad,0x9a,0x71,0x67,0xc7,0xcb,0x2f, 0xbf,0xdc,0xfc,0xf0,0xc3,0x0f,0x19,0xff,0x3b,0x5a,0xc3,0xef,0xc7,0x3c,0xba,0xe8, 0xa2,0x8b,0xe8,0x03,0x00,0x18,0x00,0xc0,0x00,0x84,0xe9,0x1a,0x32,0x09,0xbf,0xab, 0x58,0xfb,0x2d,0x80,0x2f,0xbd,0xf4,0x92,0xb9,0xe3,0x8e,0x3b,0x52,0xfe,0x1e,0x15, 0xfe,0x2d,0xb7,0xdc,0xd2,0xf7,0x6b,0x0e,0xba,0x01,0xd0,0x33,0x1a,0x34,0x31,0x30, 0xd7,0x7f,0xbb,0x61,0xc3,0x86,0xe6,0xf9,0xe7,0x9f,0xcf,0xb8,0x57,0x40,0x26,0x3d, 0x19,0x30,0x00,0x80,0x01,0x00,0xc4,0x33,0x62,0xd7,0x30,0x67,0xce,0x9c,0xb4,0x22, 0x71,0xf4,0xd1,0x47,0x17,0x55,0x00,0x7f,0xfd,0xf5,0x57,0xf3,0xcf,0x7f,0xfe,0xb3, 0x60,0xd7,0x1c,0x54,0x03,0xa0,0xd1,0x0e,0x8d,0x74,0xf8,0x71,0x8d,0x2a,0xea,0xd3, 0xa7,0x4f,0xcf,0xe8,0xdf,0xed,0xdf,0xbf,0x3f,0x06,0x00,0x30,0x00,0x80,0x01,0x28, 0xa7,0x6b,0x38,0xf8,0xe0,0x83,0x33,0x12,0x25,0xfd,0xa2,0x2c,0x96,0x01,0xd0,0x2e, 0x79,0x9a,0x17,0x50,0xc8,0xeb,0x0e,0xa2,0x01,0xd0,0xfb,0x9c,0xa8,0x34,0x32,0x1f, 0xb4,0x85,0x70,0x26,0xf9,0x15,0x37,0xdc,0x70,0x03,0x06,0x00,0x30,0x00,0x80,0x01, 0x28,0x97,0x6b,0xd0,0x56,0xb5,0x99,0x24,0x6e,0x69,0x28,0xb9,0x58,0x5f,0xc0,0xdf, 0x7d,0xf7,0x9d,0xe9,0xdc,0xb9,0x73,0xc1,0xef,0x7d,0x10,0x0d,0xc0,0xd5,0x57,0x5f, 0x5d,0x90,0x6b,0xd5,0x33,0x12,0xfc,0x68,0x9e,0x84,0x01,0x00,0x0c,0x00,0x20,0x9e, 0x11,0xb8,0x06,0x6d,0x02,0x73,0xf7,0xdd,0x77,0x67,0x24,0x4c,0xa7,0x9c,0x72,0x4a, 0x51,0x04,0x50,0xb3,0xe2,0xf3,0xed,0xbf,0x1f,0x56,0x03,0xf0,0xfe,0xfb,0xef,0xc7, 0xcf,0x64,0x28,0xc4,0xb5,0x36,0x6d,0xda,0x34,0x9e,0xed,0x9f,0x2e,0xe1,0x50,0x0d, 0x21,0x06,0x00,0x30,0x00,0x80,0x78,0x46,0xf8,0x1a,0x74,0x6f,0x58,0x93,0xfa,0x32, 0x19,0x1f,0x7c,0xf0,0x81,0xa9,0x56,0xad,0x5a,0x51,0x0c,0xc0,0xa8,0x51,0xa3,0x8a, 0x76,0xef,0x83,0x66,0x00,0x0e,0x3d,0xf4,0xd0,0x82,0x5e,0xaf,0x56,0x13,0xa4,0x1b, 0x5a,0x0d,0x82,0x01,0x00,0x0c,0x00,0x20,0x9e,0x11,0xbd,0x06,0x2d,0x97,0x7b,0xed, 0xb5,0xd7,0x32,0x16,0xa6,0xbe,0x7d,0xfb,0x16,0x45,0x00,0xb5,0x13,0x5e,0xa6,0xa5, 0x6e,0x51,0x33,0x00,0x9a,0xf3,0x90,0xab,0xc9,0xca,0x94,0xb3,0xcf,0x3e,0x3b,0xed, 0xcf,0xa1,0x87,0xfc,0x60,0x00,0x00,0x03,0x00,0x88,0x67,0x84,0xae,0x41,0x6b,0xe5, 0x77,0xdc,0x71,0x47,0x33,0x79,0xf2,0xe4,0xac,0xbe,0xc8,0xf5,0xf4,0xb8,0x62,0x7d, 0x01,0x1f,0x75,0xd4,0x51,0x45,0xbd,0xf7,0x41,0x32,0x00,0xe3,0xc7,0x8f,0x0f,0x44, 0xb2,0x67,0xbe,0x51,0x08,0x0c,0x00,0x60,0x00,0x00,0x03,0x50,0xe2,0x6b,0x50,0xc1, 0x6f,0xd9,0xb2,0x65,0x3c,0xa3,0x5c,0x43,0xbf,0x5a,0xe7,0x9d,0xed,0xf8,0xf4,0xd3, 0x4f,0xe3,0x7f,0x47,0x31,0x04,0x50,0xff,0x2d,0x3f,0xea,0xd0,0xc3,0x6a,0x00,0xf6, 0xde,0x7b,0xef,0x82,0x5f,0xaf,0x26,0x56,0xa6,0x1b,0xc7,0x1f,0x7f,0x3c,0x06,0x00, 0x30,0x00,0x80,0x01,0x08,0xc2,0x35,0xe8,0xfe,0xbb,0xd6,0x84,0x27,0x42,0x4f,0xcd, 0xd3,0xb0,0xae,0x36,0xf1,0x19,0x39,0x72,0xa4,0xb9,0xe9,0xa6,0x9b,0xcc,0xfd,0xf7, 0xdf,0x6f,0xe6,0xce,0x9d,0x9b,0xd7,0x51,0xba,0xae,0x20,0xeb,0x99,0xf4,0xc5,0x10, 0x59,0x1d,0xda,0xda,0xb6,0xd8,0xf7,0x3e,0x48,0x06,0x20,0xdb,0x43,0x96,0x72,0xa1, 0x6e,0xdd,0xba,0x69,0x7f,0x8e,0xf3,0xce,0x3b,0x0f,0x03,0x00,0x18,0x00,0xc0,0x00, 0x04,0xe1,0x1a,0x4a,0x31,0xfc,0x12,0xff,0x6c,0x04,0xb0,0x18,0x65,0x7f,0x41,0x35, 0x00,0x5f,0x7e,0xf9,0x65,0xd1,0xae,0x39,0x5d,0x7b,0x60,0x15,0x70,0x0c,0x00,0x60, 0x00,0x00,0x03,0x50,0x86,0x06,0x40,0x6b,0xc1,0xfd,0x12,0xff,0x4c,0x05,0x50,0x45, 0xa9,0x62,0xc5,0x8a,0x65,0x6b,0x00,0x9e,0x7e,0xfa,0xe9,0xa2,0x5d,0xb3,0x0a,0x30, 0x06,0x00,0x30,0x00,0x80,0x01,0xc0,0x00,0xfc,0x6f,0xfc,0xfc,0xf3,0xcf,0xf1,0x5a, 0x7f,0xbf,0x85,0x38,0x13,0x01,0x2c,0xd5,0x73,0x0a,0x8a,0x01,0xf0,0xa3,0x03,0x1f, 0x06,0x00,0x30,0x00,0x18,0x00,0x0c,0x00,0x06,0x20,0xeb,0xa1,0xfd,0x00,0x5a,0xb4, 0x68,0x51,0x32,0x91,0x2d,0x66,0xed,0x7f,0x10,0x0d,0xc0,0xb0,0x61,0xc3,0x30,0x00, 0x80,0x01,0xc0,0x00,0x00,0x06,0xa0,0x38,0x63,0xd9,0xb2,0x65,0xf1,0x23,0x63,0x37, 0xdf,0x7c,0xf3,0x92,0x8b,0xec,0xd0,0xa1,0x43,0xcb,0xda,0x00,0x9c,0x7b,0xee,0xb9, 0x18,0x00,0x28,0x07,0x03,0xb0,0x1f,0x06,0x00,0x30,0x00,0x25,0x30,0x00,0x7a,0xc8, 0xcc,0x82,0x05,0x0b,0xe2,0xf5,0xe6,0x3d,0x7b,0xf6,0x8c,0x97,0x09,0x06,0x45,0x64, 0x4f,0x38,0xe1,0x84,0xb2,0x36,0x00,0x5a,0xcd,0x81,0x01,0x80,0x88,0x33,0xc0,0x31, 0x00,0xbd,0x8b,0x65,0x00,0xea,0x7a,0x0c,0xc0,0x6a,0x1e,0x02,0x06,0x20,0x8a,0x06, 0x40,0xfb,0xe7,0x6b,0x9f,0x77,0x5d,0x5c,0xb5,0x9b,0x9e,0x76,0xf9,0xd3,0xc4,0x32, 0xad,0xff,0x57,0x71,0xd5,0x06,0x40,0xf9,0xf6,0x78,0x2f,0xa4,0x00,0x1e,0x76,0xd8, 0x61,0x65,0x6d,0x00,0x8e,0x3c,0xf2,0x48,0x0c,0x00,0x44,0x99,0xd5,0x19,0x1a,0x80, 0xba,0x7e,0x18,0x80,0x6a,0x49,0x0c,0xc0,0x1f,0x3c,0x08,0x0c,0x40,0xd8,0xae,0xe1, 0xa9,0xa7,0x9e,0x8a,0x8b,0x48,0x32,0x6a,0xd5,0xaa,0x55,0x92,0x0c,0xfa,0x20,0x89, 0x6c,0xd8,0x0d,0x40,0x31,0xaf,0x1f,0x03,0x00,0x25,0xe0,0x8f,0x2c,0x0d,0x40,0xb5, 0x42,0x18,0x80,0x1f,0x79,0x10,0x18,0x00,0xae,0x01,0x03,0x80,0x01,0xc0,0x00,0x40, 0x51,0xf9,0xd1,0x63,0x00,0x76,0x16,0xb6,0x13,0x3a,0xf8,0x69,0x00,0x2a,0x0a,0x95, 0x3d,0x06,0xa0,0x91,0xd0,0x42,0x68,0x23,0x7c,0xc1,0x83,0xc0,0x00,0x70,0x0d,0x18, 0x00,0x0c,0x00,0x06,0x00,0x8a,0xca,0x97,0x8e,0x01,0xd8,0x37,0x81,0x01,0x68,0xe3, 0x68,0x74,0x23,0x8f,0x01,0xa8,0xec,0x68,0xba,0x6f,0x06,0x60,0x01,0x0f,0x02,0x03, 0xc0,0x35,0x60,0x00,0x30,0x00,0x18,0x00,0x28,0x2a,0x8b,0x84,0xfe,0x8e,0x01,0xd8, 0xa3,0x18,0x06,0xa0,0x66,0x02,0x03,0xf0,0x02,0x0f,0x02,0x03,0xc0,0x35,0x60,0x00, 0x30,0x00,0x18,0x00,0x28,0x2a,0x2f,0x3b,0x06,0xa0,0x9f,0x63,0x00,0xba,0x0b,0x9d, 0x85,0xf6,0x09,0x0c,0x40,0x4d,0xbf,0x0c,0xc0,0x46,0x42,0x43,0xa1,0xb9,0xd0,0x5a, 0x98,0xc2,0x83,0xc0,0x00,0x70,0x0d,0x18,0x00,0x0c,0x00,0x06,0x00,0x8a,0xca,0xe3, 0xc2,0x21,0x8e,0x01,0xe8,0x25,0xec,0x64,0x19,0x80,0xd6,0x8e,0x46,0x37,0x74,0x34, 0xbb,0x60,0x06,0xe0,0x06,0x1e,0x04,0x06,0x80,0x6b,0xc0,0x00,0x60,0x00,0x30,0x00, 0x50,0x54,0x26,0x38,0x06,0xa0,0xaf,0xd0,0xd3,0x31,0x00,0xdb,0x0a,0xed,0xfc,0x32, 0x00,0x31,0xcb,0x00,0x54,0xf5,0x18,0x80,0x66,0x42,0x2b,0xe1,0x3c,0x1e,0x04,0x06, 0x80,0x6b,0xc0,0x00,0x60,0x00,0x30,0x00,0x50,0x54,0x46,0x08,0x07,0x0b,0x7d,0x1c, 0x03,0xd0,0x4d,0xd8,0x46,0xd8,0xd2,0xd1,0xe6,0x66,0x1e,0x03,0x50,0xd5,0x32,0x00, 0xb1,0x5c,0x0c,0x40,0x0d,0xa1,0x8e,0xd0,0xc0,0xf9,0xcb,0x37,0x15,0xfe,0xc1,0x83, 0xc0,0x00,0x70,0x0d,0x18,0x00,0x0c,0x00,0x06,0x00,0x8a,0xca,0x39,0xc2,0x41,0x8e, 0x01,0xd8,0x5d,0xd8,0xd1,0x32,0x00,0x9b,0x3a,0x1a,0xdd,0xc0,0xd1,0xec,0x1a,0xf9, 0x18,0x80,0x4a,0x09,0x0c,0x40,0x53,0xe7,0x1f,0xd9,0x89,0x07,0x81,0x01,0xe0,0x1a, 0x30,0x00,0x18,0x00,0x0c,0x00,0x14,0x95,0x63,0x84,0x03,0x85,0x7d,0x84,0x1e,0xc2, 0x0e,0xc2,0xd6,0xc2,0x16,0x8e,0x36,0x37,0x4d,0x60,0x00,0x2a,0x65,0x6b,0x00,0x2a, 0x78,0x0c,0x40,0x6d,0xa1,0xbe,0xd0,0x44,0x68,0x29,0xb4,0x15,0xbe,0xe7,0x61,0x60, 0x00,0xb8,0x06,0x0c,0x00,0x06,0x00,0x03,0x00,0x45,0x41,0x35,0xf7,0x30,0xe1,0x00, 0x61,0x2f,0x61,0x37,0xa1,0xab,0xd0,0xc9,0xd1,0xe4,0x96,0x8e,0x46,0xd7,0x77,0x34, 0xdb,0x36,0x00,0x15,0x72,0x31,0x00,0xee,0x79,0x00,0xfa,0x97,0xd5,0x73,0xfe,0xf2, 0x4d,0x84,0xcd,0x85,0x17,0x79,0x20,0x18,0x00,0xae,0x01,0x03,0x80,0x01,0x28,0x8d, 0x01,0xf8,0xfe,0xfb,0xef,0x59,0xbb,0xca,0x8b,0x57,0x62,0x7f,0x3f,0x0a,0xb8,0x8b, 0xb0,0x95,0xa3,0xc9,0x9b,0x38,0x1a,0x5d,0xcf,0xd1,0xec,0xac,0xcf,0x01,0x48,0x66, 0x00,0x12,0x9d,0x08,0x48,0x25,0x00,0x06,0x80,0x6b,0xc0,0x00,0x60,0x00,0x0a,0x64, 0x00,0x86,0x0c,0x19,0x92,0xf6,0x7a,0xeb,0xd4,0xa9,0xc3,0xfa,0x55,0x5e,0x15,0x00, 0xde,0x2e,0x80,0x7a,0x0e,0x80,0xb7,0x0d,0x70,0xce,0x27,0x01,0x26,0x2b,0x05,0x4c, 0xd4,0x0d,0x70,0x10,0x0f,0x04,0x03,0xc0,0x35,0x60,0x00,0x30,0x00,0x85,0x31,0x00, 0x7a,0xb4,0x71,0xba,0xd1,0xb9,0x73,0x67,0xd6,0xaf,0xf2,0x61,0x48,0x8a,0x1e,0x00, 0xbe,0x74,0x01,0xcc,0xb4,0x17,0x40,0x2b,0x27,0xf4,0xb0,0x96,0x87,0x82,0x01,0xe0, 0x1a,0x30,0x00,0x18,0x00,0xff,0x0d,0xc0,0xc0,0x81,0x03,0xd3,0x5e,0xef,0x21,0x87, 0x1c,0xc2,0xfa,0x55,0x1e,0xa8,0xd6,0x1e,0xe5,0xa9,0x00,0xe8,0x66,0xf5,0x00,0x68, 0xe5,0x57,0x0f,0x00,0xaf,0x01,0x48,0x56,0x09,0xa0,0x59,0x87,0x73,0x79,0x30,0x18, 0x00,0xae,0x01,0x03,0x80,0x01,0xf0,0xdf,0x00,0xec,0xb3,0xcf,0x3e,0x69,0xaf,0x77, 0xc4,0x88,0x11,0xac,0x5f,0xe5,0xc1,0x7c,0xe1,0x70,0xa7,0x02,0x60,0xef,0x2c,0x2a, 0x00,0x72,0x32,0x00,0xde,0x52,0xc0,0xea,0x9e,0x4a,0x00,0x37,0x11,0x70,0x14,0x0f, 0x06,0x03,0xc0,0x35,0x60,0x00,0x30,0x00,0xfe,0x1b,0x80,0xd6,0xad,0x5b,0xa7,0xbd, 0xde,0x5f,0x7f,0xfd,0xd5,0x34,0x6d,0xda,0x94,0x35,0x2c,0xfa,0x8c,0xf3,0x24,0x00, 0xee,0x9a,0x24,0x01,0xb0,0xbe,0x95,0x00,0x98,0x53,0x09,0x60,0x36,0x89,0x80,0xfd, 0x79,0x30,0x18,0x00,0xae,0x01,0x03,0x80,0x01,0xf0,0xdf,0x00,0x28,0x5f,0x7f,0xfd, 0x75,0xda,0x6b,0x1e,0x3b,0x76,0x2c,0x6b,0x58,0xf4,0x39,0x3d,0x96,0xfc,0x14,0x40, 0x5f,0x13,0x00,0x53,0xe5,0x01,0xd4,0x8d,0x6d,0x78,0x26,0x80,0xfe,0xe3,0x5f,0xf2, 0x70,0x30,0x00,0x5c,0x03,0x06,0x00,0x03,0xe0,0xbf,0x01,0xd0,0x39,0x9b,0x6e,0xac, 0x5a,0xb5,0xca,0xf4,0xeb,0xd7,0x8f,0x75,0x2c,0xba,0x7c,0x25,0x0c,0x8c,0xfd,0xbd, 0x05,0x70,0xa2,0x33,0x00,0x72,0x3e,0x05,0x30,0x9b,0x3c,0x80,0x66,0x56,0x1e,0xc0, 0x6d,0x3c,0xa0,0xe8,0x1b,0x80,0x35,0x6b,0xd6,0x98,0xf9,0xf3,0xe7,0x17,0x9d,0x69, 0xd3,0xa6,0x61,0x00,0x30,0x00,0x65,0x6b,0x00,0x06,0x0f,0x1e,0x6c,0x32,0x1d,0x37, 0xdc,0x70,0x83,0xa9,0x5e,0xbd,0x3a,0xeb,0x59,0xf4,0xb8,0x3b,0xb6,0xbe,0x01,0x90, 0xee,0xff,0xef,0x96,0x60,0xff,0xbf,0x99,0x9f,0xfb,0xff,0xb6,0x01,0x48,0xd6,0x11, 0xd0,0xcd,0x03,0x60,0x1b,0xa0,0x0c,0x0c,0x40,0xa9,0xc6,0xf2,0xe5,0xcb,0x31,0x00, 0x18,0x80,0xb2,0x35,0x00,0x2a,0xe8,0xdf,0x7d,0xf7,0x5d,0xc6,0xef,0xcb,0xbb,0xef, 0xbe,0x6b,0xc6,0x8c,0x19,0x63,0x8e,0x39,0xe6,0x18,0xd3,0xa3,0x47,0x0f,0xb3,0xd5, 0x56,0x5b,0x99,0x5d,0x76,0xd9,0xc5,0x1c,0x78,0xe0,0x81,0xe6,0xf8,0xe3,0x8f,0x37, 0xb7,0xdc,0x72,0x8b,0x79,0xeb,0xad,0xb7,0xcc,0x4f,0x3f,0xfd,0x64,0x36,0xdb,0x6c, 0x33,0xd6,0xbe,0x70,0x70,0x86,0x53,0xff,0xbf,0x9f,0x53,0xff,0xbf,0x4b,0x9a,0xfd, 0x7f,0x6f,0x0b,0xe0,0x9c,0x0c,0x40,0xb2,0x3c,0x00,0x6f,0x3f,0x00,0xad,0x41,0xfc, 0x80,0x87,0x84,0x01,0xc0,0x00,0x60,0x00,0x30,0x00,0xfe,0x1a,0x00,0x65,0xf8,0xf0, 0xe1,0x05,0x79,0xb7,0x3a,0x75,0xea,0xc4,0xda,0x17,0x7c,0x96,0x0a,0x47,0x38,0xe1, 0xff,0xbe,0x19,0xd6,0xff,0xe7,0xbd,0xff,0x9f,0x49,0x3f,0x00,0xf7,0x68,0x60,0x3d, 0x85,0x68,0x18,0x0f,0x0a,0x03,0x80,0x01,0xc0,0x00,0x60,0x00,0xfc,0x37,0x00,0x35, 0x6b,0xd6,0x34,0x8b,0x17,0x2f,0xc6,0x00,0x94,0x27,0x63,0x3c,0xe1,0x7f,0x2d,0xff, 0xdb,0xd1,0x09,0xff,0x27,0x3b,0x02,0x38,0xef,0xfd,0xff,0x74,0x79,0x00,0xf5,0x9d, 0x9a,0xc3,0x96,0x4e,0x08,0xa2,0xbb,0xf0,0x27,0x0f,0x0b,0x03,0x80,0x01,0xc0,0x00, 0x60,0x00,0xfc,0x35,0x00,0x8a,0x8a,0xf5,0x1f,0x7f,0xfc,0x81,0x01,0x28,0x2f,0x54, 0x53,0x8f,0x71,0xb6,0xd9,0x93,0x85,0xff,0x5b,0x3a,0x5a,0x5c,0xdf,0xcf,0xfd,0xff, 0x44,0x79,0x00,0x89,0xca,0x01,0xed,0x6d,0x80,0x49,0x3c,0x30,0x0c,0x00,0x06,0x00, 0x03,0x80,0x01,0xf0,0xdf,0x00,0x28,0xbb,0xef,0xbe,0x7b,0x56,0xf9,0x00,0x18,0x80, 0xd0,0x33,0xd9,0xc9,0xfe,0x3f,0xc8,0xca,0xfe,0x4f,0x14,0xfe,0x4f,0x56,0xfe,0x97, 0xb7,0x01,0xb0,0xf3,0x00,0x92,0x6d,0x03,0xb8,0xd5,0x00,0xfb,0xf2,0xc0,0x30,0x00, 0x18,0x00,0x0c,0x00,0x06,0xa0,0x30,0x06,0x20,0xe6,0x34,0x07,0x7a,0xe3,0x8d,0x37, 0x30,0x00,0xe5,0xc1,0xc9,0x56,0xf3,0x9f,0xbd,0x52,0x64,0xff,0x27,0x0a,0xff,0x57, 0xf2,0x43,0xfc,0x93,0x6d,0x03,0x78,0xab,0x01,0xb4,0x11,0x41,0x47,0xe1,0x69,0x1e, 0x5a,0x38,0x59,0xb4,0x68,0x51,0x20,0x0d,0xc0,0x27,0x9f,0x7c,0xe2,0xdb,0x35,0xdc, 0x7b,0xef,0xbd,0xa1,0x7e,0x46,0x35,0x6a,0xd4,0x30,0x2b,0x56,0xac,0x48,0x79,0x8d, 0x7d,0xfb,0xf6,0x8d,0xec,0xcf,0x16,0xb4,0xeb,0x7f,0xef,0xbd,0xf7,0x52,0xfe,0x2c, 0x67,0x9e,0x79,0x66,0xc1,0xfe,0x6d,0xbd,0xce,0x97,0x5e,0x7a,0x29,0xe7,0xf7,0xea, 0x95,0x57,0x5e,0x31,0xcd,0x9b,0x37,0x67,0xed,0x0b,0x2e,0xcf,0x39,0xc9,0x7f,0xee, 0xe1,0x3f,0x6e,0xf3,0x9f,0xed,0x1d,0xad,0xdd,0x2c,0x45,0xf6,0x7f,0x65,0xbf,0xbe, 0xfe,0x53,0x6d,0x03,0xb8,0xd5,0x00,0x6e,0x53,0xa0,0x76,0xce,0x0f,0xcb,0xc3,0x03, 0x00,0x28,0x02,0x2d,0x5a,0xb4,0x88,0x1f,0x1a,0xa4,0xdd,0x00,0x67,0xcc,0x98,0x61, 0xe6,0xcc,0x99,0x63,0x96,0x2d,0x5b,0x66,0x7e,0xf8,0xe1,0x87,0x78,0x84,0x42,0xff, 0x5b,0x7b,0x69,0xdc,0x71,0xc7,0x1d,0xf1,0x6a,0x82,0x83,0x0f,0x3e,0x38,0xfe,0x67, 0xb8,0x77,0xa1,0xe8,0xfc,0x97,0x28,0xf9,0x6f,0x9b,0xd8,0x86,0xcd,0x7f,0x92,0x65, 0xff,0xfb,0x66,0x00,0x92,0x55,0x03,0xd8,0x87,0x03,0x69,0x22,0x42,0x5b,0x27,0x31, 0x61,0x1a,0x0f,0x0f,0x00,0x00,0x20,0x27,0x9e,0x11,0xfe,0xe1,0x7c,0x50,0xef,0x9b, 0x20,0xf9,0xaf,0xad,0x95,0xfc,0xe7,0x36,0xff,0xf1,0x35,0xfb,0x3f,0x55,0x14,0xc0, 0x3e,0x1c,0x28,0x51,0x32,0xa0,0xee,0x57,0xac,0xe6,0x21,0x02,0x00,0x00,0x64,0x85, 0x6a,0xe7,0x29,0xce,0xd7,0xbf,0x9e,0xfc,0xb7,0x4f,0x6c,0xc3,0xa3,0x7f,0x13,0x25, 0xff,0x25,0x3a,0xfc,0xa7,0x60,0x06,0xa0,0x8a,0x27,0x19,0xd0,0x6e,0x0d,0xec,0x46, 0x01,0xee,0xe4,0x41,0x02,0x00,0x00,0x64,0xc5,0x7d,0x19,0x7c,0xfd,0xdb,0xad,0x7f, 0xed,0xe4,0xbf,0x2a,0x85,0x32,0x00,0xa9,0x92,0x01,0xed,0x13,0x02,0xdd,0x28,0x80, 0x1e,0x55,0xf8,0x23,0x0f,0x13,0x00,0x00,0x20,0x23,0x54,0x33,0x07,0x5b,0x7b,0xff, 0xc9,0xbe,0xfe,0x37,0xf6,0x7c,0xfd,0x17,0x24,0xf9,0x2f,0x9b,0x28,0x40,0xc3,0x04, 0x51,0x80,0xa1,0x3c,0x50,0x00,0x00,0x80,0x8c,0x18,0x99,0x20,0xf3,0x3f,0xd9,0xd7, 0x7f,0xc3,0x62,0x7e,0xfd,0xbb,0x06,0x20,0x5d,0x14,0xc0,0xcd,0x05,0x68,0xe7,0x38, 0x96,0x57,0x78,0xa8,0x00,0x00,0x00,0x29,0x79,0x5d,0xf8,0x67,0x6c,0x7d,0xdd,0xbf, 0x9d,0xf9,0xef,0x1e,0xfb,0x9b,0x68,0xef,0x3f,0xd1,0xd7,0x7f,0x41,0x0c,0x40,0x26, 0xb9,0x00,0xde,0x8a,0x00,0xdd,0xc3,0x58,0xc1,0xc3,0x05,0x00,0x00,0x48,0x88,0x6a, 0xe4,0x49,0xc2,0xe1,0xb1,0x75,0x5d,0xff,0xdc,0x43,0x7f,0xb4,0xc5,0xfe,0xf6,0x49, 0x32,0xff,0x8b,0xfa,0xf5,0x9f,0x6d,0x14,0xa0,0x75,0x6c,0xdd,0x41,0x05,0x5a,0xb3, 0x78,0x11,0x0f,0x18,0x00,0x00,0x20,0x21,0xd7,0x3a,0x89,0x7f,0xfd,0x9d,0x8f,0xe6, 0x3d,0x9d,0x3c,0xba,0x1d,0x1c,0x0d,0xdd,0xd2,0xd1,0xd4,0x92,0x7e,0xfd,0x67,0x13, 0x05,0x70,0xbb,0x03,0x76,0x88,0xad,0xeb,0x5b,0x4c,0x87,0x40,0x00,0x00,0x80,0x0d, 0x79,0xd6,0x0a,0xfd,0xdb,0x89,0x7f,0x6e,0xcf,0xff,0x0e,0xb1,0xf5,0x5d,0xff,0x4a, 0xfa,0xf5,0x9f,0x2a,0x0a,0xe0,0xf6,0x05,0xb0,0xbb,0x03,0xb6,0x8a,0xad,0xeb,0x57, 0xdc,0xc9,0xb9,0xa0,0xcf,0x79,0xd8,0x00,0x00,0x00,0x71,0x54,0x13,0x8f,0xf5,0x84, 0xfe,0xdd,0x96,0xbf,0x5d,0x1c,0xed,0xdc,0xc2,0xd1,0x52,0xbb,0xeb,0x9f,0x5d,0xf7, 0x5f,0xd4,0xaf,0xff,0x74,0x51,0x00,0xf7,0xa8,0xe0,0x26,0x56,0x59,0x60,0x3b,0x27, 0x8c,0xa1,0x17,0xb9,0x92,0x87,0x0e,0x00,0x00,0x65,0x8e,0x6a,0xe1,0x19,0x56,0xd6, 0xbf,0x1b,0xfa,0xdf,0xcd,0x0a,0xfd,0xb7,0xb3,0xca,0xfe,0xdc,0x9e,0xff,0x75,0x4a, 0xf9,0xf5,0x9f,0x2c,0x0a,0x60,0x9f,0x11,0xe0,0x96,0x05,0xba,0x09,0x81,0x9b,0x5b, 0x5b,0x01,0x43,0x78,0xf0,0x00,0x00,0x50,0xe6,0x8c,0x70,0xf6,0xfd,0x07,0x58,0x59, 0xff,0x6e,0xcd,0xbf,0x1b,0xfa,0xdf,0xdc,0x4a,0xfc,0x73,0xcb,0xfe,0xec,0x9e,0xff, 0x25,0xf9,0xfa,0x4f,0x14,0x05,0x48,0x94,0x10,0xe8,0xdd,0x0a,0xd8,0xca,0xc9,0x68, 0xbc,0x99,0x87,0x0f,0x00,0x00,0x65,0xca,0xed,0xc2,0x91,0xd6,0xbe,0x7f,0x1f,0xa1, 0xa7,0x27,0xeb,0xdf,0x1b,0xfa,0x4f,0x94,0xf8,0x57,0x92,0xaf,0xff,0x44,0x51,0x80, 0x74,0x5b,0x01,0xad,0x9d,0x70,0x86,0x9e,0x63,0xdc,0x55,0x78,0x94,0x49,0x00,0x00, 0x00,0x65,0xc6,0x93,0xc2,0xbf,0x62,0xeb,0xba,0xfd,0xd9,0xfb,0xfe,0xbb,0x38,0xda, 0xb8,0x75,0x6c,0xfd,0x69,0x7f,0x99,0x86,0xfe,0x4b,0x62,0x00,0x52,0x25,0x04,0xd6, 0x4a,0x52,0x15,0xa0,0xad,0x0c,0xb7,0x75,0x92,0x1c,0x66,0x32,0x19,0x00,0x00,0xa0, 0x4c,0x78,0x41,0x38,0xda,0xc9,0x87,0x3b,0x38,0xb6,0xae,0xdb,0x9f,0xf6,0xfa,0x77, 0x4b,0xfe,0xdc,0x76,0xbf,0x89,0xb2,0xfe,0x6b,0x95,0x3a,0xf1,0x2f,0x97,0xad,0x80, 0xba,0xb1,0xf5,0x6d,0x82,0xbd,0xf9,0x00,0x7a,0xd1,0x74,0x0a,0x04,0x00,0x80,0xa8, 0xa3,0x9d,0xfe,0x06,0x59,0xe2,0x6f,0x27,0xfd,0x25,0xda,0xf7,0x77,0xdb,0xfd,0xd6, 0x0d,0x5a,0xe8,0x3f,0xdb,0xad,0x00,0x6f,0x3e,0x80,0x76,0x34,0xea,0x28,0x6c,0x17, 0x5b,0xd7,0xea,0x10,0x13,0x00,0x00,0x00,0x51,0x16,0xff,0x63,0x84,0x81,0x56,0xc6, 0xff,0x5e,0x8e,0xfe,0x75,0x73,0xb4,0xb0,0xa3,0xa3,0x8d,0xde,0x7d,0xff,0x40,0x86, 0xfe,0x33,0xad,0x0a,0xb0,0xf3,0x01,0xdc,0x2e,0x81,0xde,0xa4,0x40,0xbd,0x09,0xb3, 0x98,0x24,0x00,0x00,0x10,0xc1,0xb0,0xff,0x20,0x4b,0xfc,0xf7,0x73,0xc4,0xdf,0x6d, 0xf6,0xe3,0x4d,0xfa,0x73,0xbb,0xfd,0xd9,0xfb,0xfe,0x81,0xc8,0xfa,0xcf,0x65,0x2b, 0xc0,0x9b,0x0f,0x60,0x27,0x05,0x6a,0x7b,0xc3,0x4e,0xce,0x0d,0xd0,0xed,0x80,0xa9, 0x4c,0x16,0x00,0x00,0x88,0x50,0xc2,0x9f,0xbb,0xe7,0xef,0x15,0x7f,0x37,0xe3,0xbf, 0x53,0x6c,0x7d,0xab,0x5f,0x37,0xe9,0x2f,0xd9,0xbe,0x7f,0xa0,0x42,0xff,0x99,0x6c, 0x05,0xb8,0xf9,0x00,0xb5,0x9c,0xbd,0x0c,0x3b,0x29,0xb0,0x8d,0xc7,0x04,0xe8,0x0d, 0x19,0xcb,0xa4,0x01,0x00,0x80,0x90,0x73,0xbb,0x93,0xed,0x6f,0xef,0xf9,0x27,0x13, 0xff,0x36,0x9e,0xa4,0xbf,0xba,0x8e,0x66,0xba,0xfb,0xfe,0x81,0x0d,0xfd,0x67,0x9a, 0x0f,0xe0,0x4d,0x0a,0xb4,0x4d,0x40,0x3b,0x8f,0x09,0xb8,0x30,0x46,0xc7,0x40,0x00, 0x00,0x08,0x1f,0xaa,0x5d,0xda,0xe4,0x47,0xeb,0xfc,0x0f,0x4b,0x23,0xfe,0xed,0x3c, 0xe2,0xef,0x4d,0xfa,0xab,0x16,0x26,0xf1,0x4f,0x95,0x0f,0x90,0x8d,0x09,0xd8,0xc9, 0x71,0x4e,0x9c,0x1d,0x00,0x00,0x00,0x61,0x41,0x35,0x4b,0xdb,0xfb,0x6a,0x87,0x3f, 0x6d,0xf2,0xa3,0x75,0xfe,0xfd,0x9c,0x6c,0xff,0x1e,0xd6,0x9e,0x7f,0x36,0xe2,0x5f, 0x39,0x4c,0xe2,0x9f,0x2c,0x1f,0xc0,0xae,0x0c,0x70,0x3b,0x05,0x36,0x4c,0xb1,0x1d, 0xa0,0x37,0x4a,0xbb,0x23,0x3d,0xc3,0xa4,0x02,0x00,0x80,0x80,0xa3,0xa7,0xfa,0xe9, 0xc1,0x3e,0xda,0xdb,0x5f,0xdb,0xfb,0x6a,0x87,0x3f,0x6d,0xf2,0xa3,0x75,0xfe,0xbb, 0x79,0xc4,0x7f,0xcb,0x04,0xe2,0xef,0x76,0xfa,0xab,0xe9,0x11,0xff,0x40,0xef,0xfb, 0x67,0xba,0x15,0x90,0x8d,0x09,0xd8,0xca,0x29,0x8b,0xd8,0xd1,0x49,0x0e,0x1c,0x26, 0xac,0x60,0x82,0x01,0x00,0x40,0xc0,0x50,0x6d,0xba,0x2e,0xb6,0xee,0x48,0x5f,0x37, 0xd9,0x6f,0x7f,0xe7,0x03,0x76,0x0f,0x47,0xc3,0x76,0x74,0x34,0x6d,0xab,0x3c,0xc4, 0x3f,0x54,0x06,0x20,0x99,0x09,0xa8,0x9a,0xc2,0x04,0xb8,0xd5,0x01,0x5a,0x0e,0xa1, 0x35,0x91,0xda,0x18,0x41,0xbb,0x23,0xed,0xe2,0x84,0x53,0x5e,0x65,0xb2,0x01,0x00, 0x40,0x40,0xd0,0xfa,0xfe,0x93,0x3c,0x21,0x7f,0xdd,0xef,0xd7,0x83,0x7d,0x7a,0x3a, 0xda,0xb5,0x83,0xa3,0x65,0x1d,0x1d,0x6d,0x73,0xb3,0xfd,0x93,0x89,0x7f,0xd5,0x28, 0x88,0x7f,0x36,0x26,0xa0,0xae,0xc7,0x04,0xb8,0xcd,0x82,0xb4,0x2b,0x92,0xb6,0x46, 0xec,0xea,0x24,0x4e,0x68,0x02,0xc5,0x65,0xc2,0x8f,0x4c,0x3c,0x00,0x00,0x28,0x11, 0xaa,0x41,0x23,0xad,0xaf,0xfe,0xfe,0x56,0xc8,0x7f,0x4f,0x2b,0xd9,0xaf,0xab,0xa3, 0x61,0x1d,0x62,0xeb,0x9b,0xfc,0x6c,0x9c,0x60,0xcf,0x3f,0x92,0xe2,0x9f,0xad,0x09, 0x70,0xfb,0x04,0xb8,0xcd,0x82,0xb4,0x25,0xa2,0xf6,0x45,0xde,0xda,0xd9,0x3b,0xe9, 0xe6,0xec,0xa5,0xa8,0xc3,0xba,0x4b,0x58,0xcd,0x44,0x04,0x00,0x80,0x22,0xa1,0x9a, 0x73,0x9f,0x30,0xd8,0xd9,0xeb,0x77,0xbf,0xfa,0xb5,0xbe,0x7f,0x1f,0x27,0xe4,0xef, 0xb6,0xf6,0xdd,0xde,0xd1,0xae,0xf6,0x8e,0x96,0xb9,0x4d,0x7e,0xdc,0x3a,0xff,0xb2, 0x10,0xff,0x4c,0x72,0x02,0x6a,0x78,0x4c,0x80,0x76,0x41,0xd2,0x56,0x88,0xda,0x0f, 0x79,0x33,0x27,0x5b,0x72,0x2b,0x6b,0x4b,0x60,0x67,0xc7,0x61,0x69,0x99,0xc5,0x74, 0x26,0x25,0x00,0x00,0x14,0x18,0x4d,0x48,0x3f,0xc5,0x09,0xf7,0x1f,0x66,0xed,0xf5, 0xdb,0x5f,0xfd,0x3b,0x5b,0x21,0xff,0xad,0x1c,0xed,0xda,0xcc,0xd1,0xb2,0xe6,0x8e, 0xb6,0x35,0x48,0x91,0xed,0x1f,0x49,0xf1,0xcf,0xd4,0x04,0xb8,0x1d,0x03,0xb5,0x05, 0xa2,0xf6,0x41,0x6e,0xe6,0x24,0x4a,0xb8,0x79,0x01,0x1a,0x46,0xd9,0x46,0xe8,0xe2, 0x64,0x54,0xaa,0xd3,0xea,0x15,0x5b,0xd7,0x63,0x79,0x06,0x13,0x14,0x00,0x00,0x7c, 0xe6,0x39,0xe1,0x74,0x8f,0xf0,0x6b,0xb8,0xbf,0x9f,0xb3,0xd7,0xdf,0xcb,0xca,0xf2, 0xef,0xe2,0x68,0x54,0x07,0x6b,0xbf,0x7f,0x13,0x47,0xcb,0x1a,0x39,0xda,0xe6,0x76, 0xf8,0x2b,0x2b,0xf1,0xcf,0xc6,0x04,0xd4,0x49,0x90,0x1c,0xe8,0x6e,0x09,0xb8,0xfd, 0x02,0xdc,0x68,0x80,0xee,0xb3,0xf4,0x70,0x42,0x2f,0xba,0x1f,0xf3,0xa0,0xf0,0x27, 0x93,0x16,0x00,0x00,0x72,0x44,0x35,0x64,0xb2,0x70,0xb2,0x13,0xea,0x77,0x85,0xff, 0x40,0x67,0x0b,0xda,0x0d,0xf7,0xf7,0x70,0x34,0xc8,0xfd,0xea,0x77,0xeb,0xfb,0x37, 0x4f,0xb0,0xdf,0xef,0x1e,0xec,0x53,0xb6,0xe2,0x9f,0xce,0x04,0xb8,0x67,0x07,0xb8, 0x07,0x08,0xd9,0x79,0x01,0xee,0x96,0x40,0x1b,0x4f,0x34,0x40,0xf7,0x59,0x76,0x74, 0xb2,0x2d,0x35,0x04,0xa3,0x35,0x97,0xda,0x79,0xe9,0x5a,0x61,0x29,0x13,0x19,0x00, 0x00,0x32,0x44,0x35,0x63,0x4c,0x6c,0xfd,0xc9,0x7d,0x87,0x5a,0x5f,0xfc,0xae,0xf0, 0xf7,0x76,0xb4,0x66,0x17,0x47,0x7b,0xb6,0xf7,0x7c,0xf5,0xb7,0xb1,0x42,0xfe,0xf6, 0x7e,0xbf,0x7d,0xb0,0x4f,0xd5,0x72,0x15,0xff,0x44,0x26,0x20,0xd1,0x01,0x42,0x6e, 0x72,0xa0,0xbd,0x25,0x60,0x47,0x03,0xec,0xdc,0x80,0x6d,0x9d,0xd0,0x4b,0x37,0x8f, 0x11,0xd0,0xf0,0xcc,0xf1,0xc2,0x9d,0xc2,0xd7,0x4c,0x6e,0x00,0x00,0xf0,0xa0,0xda, 0x70,0x77,0x6c,0x5d,0x07,0x3f,0xf7,0x6b,0xbf,0xbf,0x93,0xdc,0xb7,0xbf,0x15,0xea, 0xb7,0x85,0xbf,0x9b,0xa3,0x39,0xdb,0x7a,0xf6,0xfa,0xed,0xaf,0x7e,0x3b,0xe4,0x5f, 0xdb,0x23,0xfe,0xb6,0xf0,0x97,0x9d,0xf8,0x7b,0x4d,0x40,0x36,0x5b,0x02,0x6e,0x34, 0xc0,0xcd,0x0d,0x68,0x9b,0xc2,0x08,0xb8,0x5b,0x03,0xda,0x83,0x59,0x9b,0x32,0x9c, 0x10,0x5b,0x77,0xd8,0xd0,0x3c,0x61,0x2d,0x13,0x1f,0x00,0xa0,0xec,0xd0,0xb5,0x7f, 0xbe,0x30,0xce,0xd9,0xdb,0x1f,0xe8,0x88,0xfe,0x00,0x27,0x7a,0x7c,0x80,0x93,0xd5, 0xdf,0xc7,0xd1,0x0e,0x37,0xd4,0x9f,0x4c,0xf8,0xdb,0x5a,0x7b,0xfd,0xee,0x57,0x7f, 0xb6,0x21,0xff,0xb2,0x13,0xff,0x6c,0xb7,0x04,0x12,0x45,0x03,0x5a,0x58,0xdb,0x02, 0xfa,0x10,0xda,0x7b,0x8c,0xc0,0x8e,0x4e,0x56,0xa6,0x26,0x68,0xf4,0xb4,0xa2,0x02, 0x7d,0x1d,0x87,0x77,0xb6,0x33,0x09,0x5e,0x16,0xbe,0xe7,0xc5,0x00,0x00,0x88,0x1c, 0xba,0xb6,0xbf,0x22,0x4c,0x10,0x86,0x08,0x47,0xc5,0xd6,0xd5,0xee,0x1f,0xea,0xe8, 0x80,0x2d,0xfa,0x7d,0xad,0xaf,0xfd,0x9e,0x8e,0x76,0xec,0xec,0x68,0x89,0x2d,0xfc, 0xed,0x1d,0xcd,0x71,0xc3,0xfd,0x2d,0x32,0xf8,0xea,0x2f,0xeb,0x90,0x7f,0x3e,0x5b, 0x02,0xde,0x68,0x80,0x5d,0x2e,0xe8,0x1a,0x81,0x4d,0x13,0x18,0x01,0x37,0x47,0x60, 0x07,0x27,0x43,0xd3,0x8d,0x0a,0xf4,0xb2,0xcc,0x40,0x1f,0x67,0x6f,0x67,0x7f,0x27, 0xcb,0xf3,0x4c,0xe1,0x4a,0x61,0xbc,0xf0,0x98,0x63,0x0e,0x16,0x09,0x5f,0xc6,0xd6, 0x35,0x7f,0xf8,0x23,0x46,0xff,0x01,0x00,0x80,0x52,0xd7,0xe3,0xff,0xe1,0xac,0xc9, 0x5f,0x3a,0x6b,0xb4,0xae,0xd5,0x8f,0x3b,0x42,0x7f,0xb5,0x70,0x8e,0xb3,0x97,0x7f, 0x98,0x23,0xf6,0x03,0x9c,0xfd,0xfc,0x83,0x9c,0x64,0xbe,0xfd,0x9d,0xb5,0xbf,0x8f, 0x25,0xfa,0xbd,0xac,0xaf,0xfd,0x9d,0x1c,0xed,0x70,0xf7,0xf8,0xbd,0xc2,0xbf,0xa9, 0x25,0xfc,0x8d,0x3d,0x7b,0xfd,0xf6,0x57,0x3f,0x21,0x7f,0x1f,0xb6,0x04,0xec,0x68, 0x80,0x5b,0x2e,0x58,0xcf,0x32,0x02,0xcd,0x9c,0xbd,0x17,0xdb,0x08,0x68,0x78,0x46, 0xdb,0x2f,0x6e,0xed,0x64,0x68,0xba,0x51,0x01,0xdb,0x0c,0xf4,0x74,0x42,0x3c,0x7b, 0x5a,0x86,0xa0,0x9f,0x65,0x0a,0x0e,0x70,0x26,0xcb,0x41,0x8e,0x53,0x3c,0xc4,0xa1, 0xbf,0xc3,0x00,0x0f,0x87,0x02,0x00,0x40,0x41,0xf1,0xae,0xbb,0xee,0x7a,0xec,0xae, 0xcf,0x07,0x5b,0x42,0x7f,0x80,0x25,0xf6,0xfd,0x2c,0xc1,0xdf,0xd3,0x59,0xfb,0x7b, 0x7a,0x44,0xdf,0xfd,0xda,0xef,0xec,0x68,0x47,0x47,0x2b,0xd4,0xef,0x0a,0xff,0xc6, 0x8e,0xe6,0xb8,0xc2,0x5f,0x2f,0xb6,0xbe,0xbc,0x2f,0x93,0xaf,0x7e,0xc4,0x3f,0x87, 0x68,0x80,0x9b,0x1b,0xe0,0xdd,0x16,0x70,0xf3,0x03,0x5c,0x23,0xe0,0x6e,0x0d,0xe8, 0xbe,0xcc,0xe6,0x4e,0x66,0xa6,0x1d,0x15,0x70,0xcd,0xc0,0x0e,0xce,0x9e,0x8e,0x86, 0x78,0x76,0x75,0x26,0xc1,0xee,0x56,0x84,0x60,0x4f,0x67,0x0f,0x68,0x1f,0x67,0xd2, 0xf4,0x71,0x42,0x44,0xfd,0x2c,0x93,0xb0,0xaf,0x13,0x3a,0x4a,0xc6,0xfe,0x00,0x00, 0x90,0x17,0xa9,0xd6,0xd8,0x7d,0x2d,0x71,0xef,0xe7,0xac,0xd1,0xee,0x7a,0xbd,0x8f, 0xb3,0x86,0xef,0x69,0x7d,0xe1,0xef,0xee,0xac,0xf5,0xbb,0x3a,0x6b,0x7f,0x37,0x47, 0x0b,0x5c,0xd1,0xb7,0xbf,0xf6,0xb7,0x70,0x34,0xa4,0xb5,0x15,0xea,0x77,0x85,0xbf, 0xa1,0x25,0xfc,0x76,0xb8,0x3f,0xd1,0x5e,0x3f,0x5f,0xfd,0x3e,0x47,0x03,0xdc,0x6d, 0x01,0xaf,0x11,0xb0,0xb7,0x06,0xdc,0x64,0x41,0x37,0x2a,0xa0,0x0f,0x72,0x4b,0xcb, 0x0c,0x6c,0xed,0xec,0xe9,0x6c,0xe7,0x31,0x04,0xdd,0x9d,0x89,0xb1,0x8b,0xb3,0x07, 0xe4,0x1a,0x83,0x9e,0x0e,0xbd,0x1c,0xe7,0xb8,0x87,0x33,0xa9,0x6c,0xf6,0x04,0x00, 0x80,0x82,0xe2,0x5d,0x77,0xdd,0xf5,0xb8,0x97,0xb5,0x4e,0xbb,0x42,0xbf,0x9b,0xb3, 0x96,0xef,0xec,0xac,0xed,0xb6,0xe0,0x6f,0xe7,0x68,0xc0,0xd6,0x96,0xe8,0x6f,0xe9, 0x68,0x85,0xfb,0xb5,0xef,0x26,0xf7,0x35,0x4d,0xf0,0xc5,0xef,0x0a,0xbf,0x1d,0xee, 0xe7,0xab,0xbf,0x48,0xd1,0x80,0x74,0x46,0xa0,0x91,0x93,0x91,0x69,0x47,0x05,0x5a, 0x59,0x66,0x60,0x0b,0x27,0xb4,0xd3,0xc1,0x32,0x04,0x6e,0x84,0x60,0x7b,0x67,0x82, 0x74,0x75,0x26,0xcb,0x8e,0xce,0xc4,0xd9,0xc9,0xa1,0xbb,0x65,0x14,0x76,0xb6,0x0c, 0x03,0x00,0x00,0x14,0x1e,0x7b,0xed,0x75,0xd7,0x63,0x77,0x7d,0xee,0xe6,0xac,0xd9, 0x3b,0x38,0x6b,0x78,0x17,0x67,0x4d,0x77,0xbf,0xf0,0x5d,0xc1,0xef,0xe0,0x68,0xc0, 0x16,0x96,0xe8,0xb7,0xf2,0x7c,0xed,0x37,0x71,0xb4,0x24,0x5b,0xe1,0xe7,0xab,0xbf, 0x40,0xd1,0x80,0x4c,0x8c,0x80,0x9b,0x2c,0x58,0xdf,0xda,0x1e,0xb0,0xcd,0x80,0x1b, 0x19,0xd0,0xd0,0xce,0x66,0x1e,0x43,0xd0,0xde,0x32,0x05,0x9d,0x2c,0x63,0xb0,0xad, 0x43,0x67,0x87,0xed,0x1c,0xb6,0x07,0x00,0x80,0x92,0xe0,0xae,0xc3,0xee,0xba,0xec, 0xae,0xd3,0xae,0xd0,0x77,0xb2,0xc4,0xbe,0xbd,0x47,0xf0,0x37,0x73,0x34,0xc0,0xfd, 0xd2,0xb7,0x45,0xdf,0x0d,0xf3,0xd7,0xb7,0x92,0xfb,0xb2,0x15,0x7e,0xc4,0xbf,0x04, 0x46,0xc0,0x4e,0x16,0xb4,0xa3,0x02,0xae,0x19,0xb0,0x23,0x03,0xcd,0x9d,0x84,0x0e, 0xd7,0x10,0xb8,0x11,0x02,0xd7,0x14,0xb4,0x75,0x26,0xcb,0x96,0x0e,0xae,0x41,0x70, 0x4d,0x82,0x4d,0x47,0x00,0x00,0x28,0x0a,0xde,0xf5,0xb7,0xbd,0x25,0xf0,0xee,0x7a, 0xbd,0x85,0xb3,0x86,0xbb,0x62,0xef,0x7e,0xe1,0xbb,0x82,0xbf,0xb1,0xa3,0x01,0xf6, 0x97,0xbe,0x2b,0xfa,0xf6,0xd7,0x7e,0x2d,0xcf,0x1e,0x3f,0xc2,0x1f,0x12,0x23,0x50, 0xc3,0x32,0x03,0x75,0x9c,0x07,0xea,0x46,0x06,0xdc,0x6d,0x02,0x37,0x3a,0xe0,0xe6, 0x0d,0xb4,0xb0,0x4c,0x41,0x4b,0x67,0xb2,0xb8,0xe6,0xa0,0xb5,0x43,0x1b,0x8b,0xcd, 0x00,0x00,0xa0,0x24,0xd8,0x6b,0xb1,0xbb,0x3e,0xb7,0xb2,0xd6,0xed,0x96,0x96,0xd8, 0xb7,0xb0,0xf6,0xf3,0xdd,0xaf,0x7c,0x37,0xbc,0xef,0x7e,0xe9,0x6f,0x14,0x5b,0x5f, 0xca,0xe7,0x7e,0xed,0x23,0xfc,0x21,0x33,0x02,0xe9,0xcc,0x80,0xbd,0x4d,0x50,0xcf, 0x32,0x04,0x0d,0x3d,0xa6,0xc0,0x35,0x06,0xcd,0xac,0x88,0x81,0x6b,0x12,0x5a,0x58, 0x66,0x01,0x00,0x00,0x8a,0x8f,0xbd,0x16,0x37,0xb7,0xbe,0xe8,0x9b,0x59,0x42,0x6f, 0x8b,0x7d,0x43,0x4b,0xf0,0xeb,0x79,0xc2,0xfb,0xe9,0x44,0x1f,0xe1,0x0f,0x91,0x11, 0xc8,0xc4,0x0c,0x78,0x0d,0xc1,0x46,0x96,0x29,0xb0,0x8d,0x81,0x6b,0x0e,0x1a,0x5a, 0x26,0xc1,0xa6,0x31,0x00,0x00,0x14,0x15,0xef,0x3a,0x6c,0xaf,0xd1,0x0d,0x3c,0x42, 0x5f,0xcf,0xf3,0x85,0x6f,0x0b,0x7e,0x26,0xa2,0x8f,0xf0,0x47,0xcc,0x0c,0xd8,0x86, 0xc0,0x1b,0x21,0x70,0x4d,0x81,0x6b,0x0c,0x5c,0x73,0xb0,0x91,0x65,0x12,0x12,0x51, 0x0f,0x00,0x00,0x0a,0x4a,0xb2,0xf5,0xd7,0x5e,0xa3,0xeb,0x58,0x42,0x5f,0xdb,0x5a, 0xd7,0x6d,0xb1,0xb7,0x05,0x1f,0xd1,0x2f,0x03,0x33,0x90,0x89,0x21,0xf0,0x9a,0x82, 0x1a,0x9e,0x88,0x41,0x4d,0x8f,0x51,0x00,0x00,0x80,0xd2,0xe2,0x5d,0x9f,0xed,0xb5, 0xdb,0x16,0xfb,0x4c,0x05,0x1f,0xd1,0x8f,0xa8,0x19,0x48,0x67,0x08,0x5c,0x53,0x50, 0xc5,0x63,0x0e,0x6c,0x83,0x90,0x8c,0xea,0x00,0x00,0x50,0x50,0xd2,0xad,0xc3,0x55, 0x3d,0x22,0x5f,0xc5,0x23,0xf6,0x99,0x08,0x3e,0xa2,0x5f,0xa6,0x86,0xc0,0x36,0x05, 0x89,0xcc,0x41,0xe5,0x14,0x66,0x01,0x00,0x00,0x8a,0x47,0xaa,0xb5,0xd9,0xbb,0x8e, 0x57,0x44,0xf0,0x19,0x99,0x9a,0x82,0x64,0xe6,0x20,0x15,0x95,0x00,0x00,0xa0,0xa0, 0x64,0xb3,0x26,0x27,0x5b,0xd7,0x19,0x0c,0x06,0x83,0xc1,0x60,0x30,0x18,0x0c,0x06, 0x83,0xc1,0x60,0x30,0x22,0x3c,0xfe,0x1f,0xfb,0xaa,0x4c,0x17,0x47,0x9a,0xc3,0xb9, 0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, }; lprint-1.0/static-resources/lprint-large.png000066400000000000000000000605141362261677400213130ustar00rootroot00000000000000PNG  IHDRxiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i(0ciTXtXML:com.adobe.xmp Michael Sweet Copyright 2019 Michael Sweet New Icon New Icon 8Y;IDATxEֆ%GE@Q((b@`T\wq 9E b*DQ0Is@ ;t/E;yzf{:9g]}[`0 `0 `0 `0 `0 `0 `0 FF4 o^1 *@AfM$0Ҋ}:!*PRO(jQ- [5;YHd 0T_%EM xg{dj!to-8ldQ7 $[5]u6 ^S! D@yľ%u,qw'Z}CCF@Q=a#D lC}[z%M ;J볻^7ƖIA TS -M-q׉RԡڡfP][YvKg-2 M=5v X/| E}pla0Ex^X |!(! Z6f +CIh+ln4"nt`#Od#`w+-WQ8RLy"/:`󡷅e Z[e[f&p"~7|WVx[XˋPv?W%:Xw dcy~g#~­—L|pc [Zf ys0D|mwض.>`r@f ;f DpsN~C!-DQ lkX;'Ѝ ll;"`'  ײP^SLZ𙧅Cr{hpkyd(ɾp}'! 4aFe9H dw8Yc@q)wk,F _\ΌkdR4T2S.P[&NVKL<8phP[نI#`@PmH,tr{n !N ^-'4l H'c-|Ƥyl݁r=].X\L@"wkz_LNV2 dv +tZxD"a2w4BBWR@& Dd?'¤𨰳% &Fg,1f5 8L@s2M/`w'/S& t_ɲ/L@& Yu@h2߄?lM@(&?n_S [>v["6 (zl}?ΟR?(W&0nu'X=Ie@}vA:e΅N -b5v4>@(]F탬}jῄnu%'mz l>@п7O;!`zv@tvtR$n+u!5S62`غzvfD% w!$raغvA Hw5q !ZvRoֿ7à@j^k(mdo* An"(^ȿ=QQU ,*cv5 ,ߏDP1U~ t"oTh` 1;{F@+V@l'V]"f`WYu=v܃;# YI{Tp??QMS ?zv˛󎖭g߈gP(=cH 6@{& 3LhbgA )ߜ ps+=*mDvZ @l^'S t$ozu@ jb,_Co`rCx-~LƋ L@h Y5@|+%Lĵ<^qa{Yd.Έ2G2/3P k K7@ @ lwkO7e=z"d9H 6۰h f<(W*Wf:4L&c7ߘno>鳯Y\&Q!8]] ~ 6Yu$`xp.9sLCMON2rYRs#3 fR1= Tὂ :T̰T_ڿ2~5a~yQw7F8#ʛbF_@]3TwʬxmSȡgf/O<)[pFw !R@ ;)cm)Ф_~|}96[ 1{rcݧM0/Qt&cܹۋ/5Kь03 \$qg*̻H` @1m u|=݈v2+ QemBW@mU ?.I"Zjrgo|ܳw4& L3pf k3gA:t]ի;v믋fV}qͧ`TpFbOp;e  fEyoUX$f`/|v@v=D33pnUPNC#*R5+V_{|1Xn&fyMղU @?ꫯM7dv}f[n)XjW'bo)aUa2c0[HVP ;2vZk=|y;D3,3p=hz@pY&?1Ļd350~ձmhFb3U *F`0PNrDs=Mjoon-Z93ҥf5יe;B= Dd䲜w - 2ļz__|aq3W3yYG0aB&"y܉y~7xcsꩧ{ά^:Rf`ߛ|AfIڈfyN4A%N0BL"pY {y6lh9cRPqX2<Ҽ[>awhDuլ㏼EOsc~>mt衇2+W_x|18^ffZ`*W'mbVIhϱl2sכ]w5 jժo߾fo(o7_zyhDì5@eL$MZŗ *x*ƍ3} {?u=ѣ}7 HBo6 jn! 1w _Lߨ1yuՌ9|ٟ~{ヲVZ9]SA7.4n>Q o6k 'ק;R? ,Hߣ>j>hӠA10??,~YKbUD64eAǤgԯK.ꫯ82Jz?O r͛l9S̙3*/ ٳdf@s4~ed>fqm@Q`JFeb޼ekK_7wb-rZ^8hР `V鮻ͧ7KjAx @jJhW]ꧡ\~l̀ aÆ.I&eU^5n~<|~Qݺ 3J @lhG1tY d@5a0kx7@KY @)4⯭iW.^\)PϷpv˺0f` /8˼jsĹH\mi?^wE?@U^xWdU^W 3㏷o^dP(PMmWaG)̀&M:5?? Mdu(z6֐[ԣfBsZ^0"S30tW拣@L_ 9 fkYܘ1c~#F e_*/Le,@F%!δ` *wnFfշ,"*PW[.)f@BiOyhA6其{[ﯾfn-\d` LB3)CWsc^Bܮ]v .0gp * n- } G:}9KÜ(_M-]]˖-ͩjf͚U+ޠL7]y 5E`q FƒY봧| uk[C߉\5jdlqrК? cr'6,y-g'0?+L%hN)Ӥ8MKՊ3_|3Z_L3`_oz~BA u!) O񟒥ǿQj$erZ.+ׯ0a6R-ʹPOP=/o `hls:GRUvu[^oHZ+ӽr? Ke2)/ݻĻ̒j݀1ȗ_m欬E*\it~kbտC +rl|s%-0E (KSP_Cwtvvyaxh>G"9  2Gx6'qѯbi|r;)0f`$ ~oD6`rA&kCCԽz*yC=4eyVs1L[ 7{!@i*<+?6>@iL フ[ \ײ]z !a ̈́y{ |@Ǐϻ0W3w7u톰bQt|s C(dC I[^أGxy& Y_v1Lh!AW?X#f@ǢEWnWtfZg?MVҴPӕj!Bn_&J0?#~y Q{j.@3gB?F(_,5iˑQ5ٖjA兹׏FD1>g$6C nBtj(/tȣfq4켈Cs$8t3! 0̻u"% 6,:ȴ̀&ujr^wBov h `'B^wӧOd-[֋P2nyFB,9s|q`3B"˟yћ,Yn)5jdſrțPm݌hblLN dSf܋7K̀Xr7ThF0` (ֿ^\ʶ  ,֣|s_G70(_p_&1 ӋOۋa6^|)bQ`Yڈ#Ud🠍l Ջ?ݻwƯӞBˀ6b Ȅ0@=n6BşP;iy& hV-藿У@F[d=ڈhSQDG0];s#q:k#ψRşP#*/eZܼ[1"aJF<< D.bűǛrZ^Μ9`f2>|D2)Myw@c QbW~{aV^(/LwfIeDQoeͳDs D (/TOW^PD+.pN"Fȓ D -*fdH5E syKY^ͻu#m6«0h apP 5)P5I0UyСCkid}-g==@N^"AǢ>j`B_4߭ GX?50p#ּ W_s ^B"]} bANĿpOr1/0Ȑ-5k"K)z\@x@WV.\|hf3ZA`Wi6 }Ǖ_J*T }!vYXk9_@'@ aAM7C]>|QC8Դև#3rbp@${zL3 6`}k}E/1=^}/?6cʕ>hӟyYGc0 +^r*Ï uY և"ٮc0|$T8(#!G~mouTx) NShԌ?|~fɂl@_~1KFDCnL{a0loϿ< 0{Ŀہ0( gC=ze\V\{'4Yvm (&X`0P.#4ܷ>3 \f>+cb 6}a¦ߌ8܌ѣ͌3̗_~itˎ̓y?v E)z0  SJUQ hon?dߎ(N 7`{97D/P s#8h]}OR1ԓ(0ۇ줿NfVRV8RVxqfছn2?Boxks!@oa 0xe"_/+.e`n>zK36ryJyAi-BZ 3K  ?aiSyd] Pƍg^yO?̃P*BWWx<9@0((h<{/sɧde&L`^{5/|g_sD{X/ u` š-yYY;̞=oh϶*W G( [mnsyel.r3qD3g,QgZB|a_5`  ̣?e̳[v^1thVf{1s5+V(Fa8#gw  Ͽ\9PNۚqGUYa̤I;c~V"{ ?#VVX|y… _UPCyV%&좀[c0PXv/ҼUyf'd}g( C gik&pP|?@\￷ C"TҲ­f0qY!I3^IJ~(=@a(24ӶC_~< r n/̎@~ ~)% y@Wv?K #<4 te{'ȓNTar=^PQ> ^kw (JBDֻVxwa0/c[zo߬2Khodu˴tw k h=ȧ);ےr; wUJ3Fi84Ϟenk^c_cʬY@1#"O# yZ f`9@ @pGwx?)UY1? Y`J56"u)🊜PrNpkX M}jXdYsZ @x\>n$LE7'(,29f{XM0CQh `վ'&?mI$`Zyr>cx0DK=3򗐑$a0CO%ya|/g#G"ILP4y,Ny7)zB)0P$,PZ+t5jr4w'ʖCI`dg1= V@o'Gȯ{;;roj&c0~M Ϙw5f `JG!= $[ _ϻ =I`J˵Eث-M̊ ~/'ʥ ,zcdǎ$a0"Yon"){u`.5+?PzP p,% gM~WC<310ӽ"]lh7`LergϺs2k4L DϺ3E$y;ȯ EVʞ>Ә9q)_ @0E-KEuo@O/8b =[s ~rfK]  8<p+VYB_s~ed̳?  XL т6Kd\hZZ; 9=#\;$b`A3|1jzΖN$a0/)hR,f]׮33w%;?dEp,l'w, M>~9?D@!?0Lfs,S1uyޣh΅?> T97 !wMEQ~m,/sKvtH gC00p—jhB}Hr<=Dxnr(VL/k_SR  @ --3Ӄj$Z}`kf9\5/Z-b@Ϟ?S?X~6,s2'n">'"jw1 N} ʋ2وo`k09"MHVMO?J}W^e=`ʋȡ`nb@j^AOV@<:_:b0ɋ, yz@N_<ypGkR{Re* @ĹRȳ@[9>z\4^O|%";s޼ey]7ױRXNWvҶȲԹ S_02 J 矪K]\" C3yr{ el("՜%b<@Qi Ϟ!'pOIE"[ μZL;CF1,Ľclh`; , h) }.#D _Rt"{"/0Lb>-w;8m/6s7z)0?c,Tc/J=R}[j,v=ڑuoR1+ȁGEibni@h;kX@)t8 * Ep̡=lQP[-7|/X e $$J'2/_rȔ)݃nboS@6t@GD^ W̽o {zȊf"񲘁!^9l=HI]8擀JFWd SСY0XP1sl2rr @h]X~p Y`M,_ <$:Y~  VЀu 0P(P 8D1`<3l(4P foº(R ^o͚(GcJΫ"mYdOJJ"XŦ%MmńN @Iܮ?`tEhT̥$(̓w; rXI (.P#`!f7ޑiO0<0B8K/cBt?0! }tȚE"#01$% @JI@RF2ZtD`?`0BS4Y^@s  @9RY+QI2\0O9D7 @p lHM8N@Du` ;(Y,c "\w0ȌFI3ZĿ"3`0=2Y^AceV 0To3^Ŀ ,`0/5<2QĿ)`0PXkd0IbMK`x d] J[. @xTZ]?` Γ( Oj M:Dag˜j; Nb큹7i; ݯ,1˼i{ $*pDb ^yҚ0-$*2F [D[ Q8,u`mPpY{l "/ "} "$*(о/ D#p4SU8HHT0 ` TTT^{r`РAf޼yfʕfڵ棏>2F2k` 4nشi&)u 5dJVLFLj՘Yp 7dw55j>` h|&՘2eJ!˗e˖~s=3}1-Z`8tŬY&彼꫹WqG 5b|f„ W^b?tдjɒ%kD?7]wln~i_O} R+V0]vYYek$ѰaC7 `iܡ9 }-s-P06:㎋9 -]ˍ|'0sL ?-[4[p)c9' 0\֢yI?ilN;xVUW]mϚ5+ퟯ &9QC'xYzu>}zYWI޷o9bN?fm~WӼyHϣwf0 F?ϝnݺ%:`0(5TR~VٌY1|p `kv]jժwΜI `k8蠃m3<s2bM7Mx{ נnh< A&tI אIK\z1m4 `k#3馛wZjJc\øqzy)9>}`k\t>+}ZxK_u3wyM.x|o߾9͞&Nhf̘]_K;~msϙ)SѣG&gkР9_| `t z `l5j9g\2ޛ Ѯ]x#LѤI6}'mt۴ic .G>;vlФLGg}u @)~u]vʿoM6Ig;vhxf͚E履~g1`im۶ O?zs뭷{^'̨į1{촋~)]vM*C% CkDOO{HQ>CN8ᄜg)U 0BS =4's xLz2sO( e]۪U++MP'Md*U5UkФtCS=^=|G\rI( &.W^;ϡ`gAkwqG3y䬾b}uQEA2ǏDgQ `PkPoٲe<\CZOG1P-?j{_&V<05ք'BOӰ69r馛oΝQ Yڶ>H Crnݺi;J1leA5_~eѮ9]{`p `P@kLPEbŊek~] 00oZ8,s 0  ZhQ2-f a08cٲe#c7|СC{(0%0ẑ ={ EdO8ᄲ6Ź31ez j @kw]\v2Wq@x/vaemiwĈ_|p`,*r2RJ7p5`0֭[_4mڔ5,$$S `6y0(_uk;v,kX9=@_Sԍmx&_p0\9nZ׏u,|% p3r>08gw(o؆efU؇i"B['1a '|P 65?U>(Q2W!dj)׿Olã%%:`'n FAd}|ۭ*2(U# #T3[{ɾ7|$/(@Qv4(l[QcV^us}@3 .ޤ@ $ KsmMse+`'j{N 퀩LPŸ7Sl}_7/پBl ;) ˤso'6f gM M@; 0F@]GK#_j?muyv@g )I&`@Pm.H_7ovGvt4m[h].M7G`'CӍ @gog'LJac _5#FR_:kՏ;Bp#d%p¿%={W?!h[.X2͜hxF/ndhQ tB<{Ze p&AS<ġ@Az[B%,Y{zDhGG+ Ǝ_//~?hp\#n NfpΞxvu&V`OghgqBD,:J}-qzi}:k7G \ѷp4w%v?^?_>GmdA7*rK ll1ݝ縇3l]wNBoh֖oh&5M 竿HрtFiGZYf` '2n`{gtu&ˎɡev {ucw};8kxgMw]h|7q$[竿@рL,X̀fC2,cCgӮwľG7s4ҷE ׷~ĿFN#͝u&˖ApMMG( %zb~Ể+~-?#P2uFm7: LAKg栵C$k>햖طݯ|7~o[_~#!3̀MP2 =5ͬkZXf7YBo}CKyD x F)kZ&1:l aiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*ikF&MciTXtXML:com.adobe.xmp Michael Sweet Copyright 2019 Michael Sweet New Icon New Icon 8JIDATx]tUHA =  $Ku)!$R"A Ma%,-KJH(C۰‚"CO^f g&oa{}OQԦ6G' BTx *ᾈgjD(C A灌_Ɖē57eP!(X_S/G BCTG1nv!!U2d"QQqŋEЎ` Dq3,ր^胈B2܂#"Вv2U%%ُRwy$3W;AƭOLY`g x"(tGe񀷥w5Pmo_ D,$O:#(/xW~(I x,M8Zo`<)K[LI?m;7A\)(ejD+D@leR qŰ0߳kg!0=5|S؉?>/7k/_t&(U)OY˛"^{7Aiq1dܢhb WŐߣ<M|~Vp+sr[(M[QC)~Je3sޕà]/ɂ]=S(u&0<ƎDt&M 99ϟgϞ5)ǷoÝ+d@UpŰ Ռ H=zʕ+aڵjՂ(3f |P^^^I OJJn8U-LԸa!]lr>v/ #2ܹСC 4χԩSe˖ {/_^I m+CᢉOc4E۷/l۶ ?~ W\LQ#=''zʼn!!!MPQQa(+Jk#GO/\E &yݯVѧ/^#4<<Ə8vi HRPjMNy|)ՖΝ; or5w<HLLއT{6#(tP`LXgZRz8͹ܨ~rss9KBY)t< x F5yz( sSk̹J&1.c& )hm[9]_ZTBk6lNĈ|-gtK.W?%1W#]Te|Bݻw׏#u0k,wWX#'ef?SEO;va ""a„ p]rOFl >*sf_Ko 6"'H$  Ś/;s}D'r-DWc68%k A\r!څԞOS]mQ ` >4Rh*!O+Nₐ[ `5|1ڥoJ~6G$4; 8/_Gnl"-cEmQ'؏iوLp^#S(Ob `¥)?%f7>X5Ũ+]!Ӣ 1|->Wf.#IU Nq$a~7{c o?6c={67i%}/JM{*Ydh|50Eⱥhcs,8%aڞ\r E`v AɟF{V,`R@oO Vu 3?P"W ͵_^D~/4֮}G$G/>qE&pQSAm+6 J,="~s8[tRr)MhwEhn K0oPhȻ~%w™g_Q.ׄ`6fi6 ͷP>(#h$^ָhӕ6fY5;% ńv SdM``,#"k*\r.g/]NE ~9S A;0!l0*NTOó;vW h˹"ʹA_:b(?2dcP{\*+NFƵAP]@ ʹd`+1Tf_2~9jܘ_:tq1 EcP>5r.~PmVrk࿛%B \2 vp@2i4G YiwbjyUS/mE~};9UΈdO9=%N`y 6m ,Ntlٲ;?`ݻw'boO@nn.9} "G9x<*nѢE [n .a}ӧCII ,YH'rU< zOOO۷/1+ KSS 4iN=޹sg5j$$$poڴ)w… !''ׯop]jj:uue`رPN =NZo^ر;wreff¬Y*ZkСCg7lw6}T{~ƌPsIY&iě>5SHU" ŋ\6THK [K̾ve"\EdTtt.FÇ\m*@9pY+Kn"#@*.9$ mnY ̛7Oh3kD'D$K_xClM bT(**#0dwE1B'۷Cf ,, BCCɈv:kO}}5 |})`\UPvm.Ml((R?kcE&[LвFF\eM*7o^w^4Ť6gΜJnܸav%V?AfUjyRzM6ԕVE\r(3u^7DQ S )Xƭѯ?$4Dv0~oFSR4"".貸L21׏ѵUU.K3N464f&LAjȏc1N=466Ї zx@(e_6hcwU6o, fBńb'TXMa>|gAo .SVb lprint-1.0/xcode/lprint.xcodeproj/project.xcworkspace/xcshareddata/000077500000000000000000000000001362261677400257375ustar00rootroot00000000000000lprint-1.0/xcode/lprint.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist000066400000000000000000000003561362261677400324210ustar00rootroot00000000000000 IDEDidComputeMac32BitWarning