root/usr/src/cmd/print/bsd-sysv-commands/lpc.c
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 */

/* $Id: lpc.c 146 2006-03-24 00:26:54Z njacobs $ */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <locale.h>
#include <libintl.h>
#include <papi.h>
#include "common.h"

typedef int (cmd_handler_t)(papi_service_t, char **);

static papi_encryption_t encryption = PAPI_ENCRYPT_NEVER;

/* ARGSUSED0 */
static int
lpc_exit(papi_service_t svc, char **args)
{
        exit(0);
        /* NOTREACHED */
        return (0);
}

static int
lpc_status(papi_service_t svc, char **args)
{
        papi_status_t status;
        papi_printer_t p = NULL;
        char *pattrs[] = { "printer-state", "printer-state-reasons",
                                "printer-is-accepting-jobs", NULL };
        char *destination = args[1];

        status = papiPrinterQuery(svc, destination, pattrs, NULL, &p);
        if (status == PAPI_OK) {
                papi_attribute_t **list = papiPrinterGetAttributeList(p);
                char accepting = 0;
                int32_t state = 0;

                printf("%s:\n", destination);

                (void) papiAttributeListGetBoolean(list, NULL,
                                "printer-is-accepting-jobs", &accepting);
                printf(gettext("\tqueueing is %s\n"),
                        (accepting ? gettext("enabled") : gettext("disabled")));

                (void) papiAttributeListGetInteger(list, NULL,
                                        "printer-state", &state);
                printf("\tprinting is %s\n",
                        ((state != 0x05) ? gettext("enabled") :
                                gettext("disabled")));

                if (state != 0x03) {    /* !idle */
                        papi_job_t *jobs = NULL;
                        int i = 0;

                        (void) papiPrinterListJobs(svc, destination, NULL,
                                        PAPI_LIST_JOBS_ALL, 0, &jobs);
                        if (jobs != NULL) {
                                for (i = 0; jobs[i] != NULL; i++);
                                papiJobListFree(jobs);
                        }
                        printf(gettext("\t%d entries in spool area\n"), i);
                } else
                        printf(gettext("\tno entries\n"));

                if (state == 0x04)
                        printf(gettext("\tdaemon present\n"));

        } else {
                fprintf(stderr, "%s: %s\n", destination,
                        verbose_papi_message(svc, status));
                return (-1);
        }

        papiPrinterFree(p);

        return (0);
}

static int
lpc_abort(papi_service_t svc, char **args)
{
        papi_status_t status;
        char *destination = args[1];

        if (destination == NULL) {
                fprintf(stderr, gettext("Usage: abort (destination)\n"));
                return (-1);
        }

        status = papiPrinterPause(svc, destination, "paused via lpc abort");
        if (status == PAPI_OK) {
                printf(gettext("%s: processing disabled after current job\n"),
                        destination);
        } else {
                fprintf(stderr, "%s: %s\n", destination,
                        verbose_papi_message(svc, status));
        }

        return (0);
}

static int
lpc_clean(papi_service_t svc, char **args)
{
        papi_status_t status;
        papi_job_t *jobs = NULL;
        char *destination = args[1];

        if (destination == NULL) {
                fprintf(stderr, gettext("Usage: clean (destination)\n"));
                return (-1);
        }

        status = papiPrinterPurgeJobs(svc, destination, &jobs);
        if (status != PAPI_OK) {
                fprintf(stderr, gettext("clean: %s: %s\n"), destination,
                        verbose_papi_message(svc, status));
                return (-1);
        }

        if (jobs != NULL) {
                int i;

                for (i = 0; jobs[i] != NULL; i++)
                        printf(gettext("\t%s-%d: cancelled\n"), destination,
                                papiJobGetId(jobs[i]));

                papiJobListFree(jobs);
        }

        return (0);
}

static int
lpc_disable(papi_service_t svc, char **args)
{
        papi_status_t status;
        char *destination = args[1];

        if (destination == NULL) {
                fprintf(stderr, gettext("Usage: disable: (destination)\n"));
                return (-1);
        }

        status = papiPrinterDisable(svc, destination, NULL);
        if (status != PAPI_OK) {
                fprintf(stderr, gettext("disable: %s: %s\n"), destination,
                        verbose_papi_message(svc, status));
                return (-1);
        }

        return (0);
}

static int
lpc_enable(papi_service_t svc, char **args)
{
        papi_status_t status;
        char *destination = args[1];

        if (destination == NULL) {
                fprintf(stderr, gettext("Usage: enable: (destination)\n"));
                return (-1);
        }

        status = papiPrinterEnable(svc, destination);
        if (status != PAPI_OK) {
                fprintf(stderr, gettext("enable: %s: %s\n"), destination,
                        verbose_papi_message(svc, status));
                return (-1);
        }

        return (0);
}

static int
lpc_restart(papi_service_t svc, char **args)
{
        int rc = 0;

        rc += lpc_disable(svc, args);
        rc += lpc_enable(svc, args);

        return (rc);
}

static int
lpc_start(papi_service_t svc, char **args)
{
        papi_status_t status;
        char *destination = args[1];

        if (destination == NULL) {
                fprintf(stderr, gettext("Usage: start (destination)\n"));
                return (-1);
        }

        status = papiPrinterResume(svc, destination);
        if (status != PAPI_OK) {
                fprintf(stderr, gettext("start: %s: %s\n"), destination,
                        verbose_papi_message(svc, status));
                return (-1);
        }

        return (0);
}

static int
lpc_stop(papi_service_t svc, char **args)
{
        papi_status_t status;
        char *destination = args[1];

        if (destination == NULL) {
                fprintf(stderr, gettext("Usage: stop (destination)\n"));
                return (-1);
        }

        status = papiPrinterPause(svc, destination, "paused via lpc");
        if (status != PAPI_OK) {
                fprintf(stderr, gettext("stop: %s: %s\n"), destination,
                        verbose_papi_message(svc, status));
                return (-1);
        }

        return (0);
}

static int
lpc_topq(papi_service_t svc, char **args)
{
        papi_status_t status;
        char *destination = args[1];
        char *idstr = args[2];
        int32_t id;

        if (destination == NULL || idstr == NULL) {
                fprintf(stderr, gettext("Usage: topq (destination) (id)\n"));
                return (-1);
        }
        id = atoi(idstr);

        status = papiJobPromote(svc, destination, id);
        if (status != PAPI_OK) {
                fprintf(stderr, gettext("topq: %s-%d: %s\n"), destination, id,
                    verbose_papi_message(svc, status));
                return (-1);
        }

        return (0);
}

static int
lpc_up(papi_service_t svc, char **args)
{
        int rc = 0;

        rc += lpc_enable(svc, args);
        rc += lpc_start(svc, args);

        return (rc);
}

static int
lpc_down(papi_service_t svc, char **args)
{
        int rc = 0;

        rc += lpc_disable(svc, args);
        rc += lpc_stop(svc, args);

        return (rc);
}

static int lpc_help(papi_service_t svc, char **args);   /* forward reference */

static char help_help[] = "get help on commands";
static char help_exit[] = "exit lpc";
static char help_status[] = "show status of daemon and queue";
static char help_abort[] =
                "disable print queue terminating any active job processing";
static char help_clean[] = "remove all jobs from a queue";
static char help_disable[] = "turn off spooling to a queue";
static char help_down[] =
                "turn off queueing and printing for a queue and set a reason";
static char help_enable[] = "turn on spooling to a queue";
static char help_restart[] = "restart job processing for a queue";
static char help_start[] = "turn on printing from a queue";
static char help_stop[] = "turn off printing from a queue";
static char help_up[] = "turn on queueing and printing for a queue";
static char help_topq[] = "put a job at the top of the queue";

static struct {
        char *cmd;
        int (*handler)(papi_service_t svc, char **args);
        char *help_string;
        int num_args;
} cmd_tab[] = {
        { "?",          lpc_help,       help_help,      0 },
        { "help",       lpc_help,       help_help,      0 },
        { "exit",       lpc_exit,       help_exit,      0 },
        { "quit",       lpc_exit,       help_exit,      0 },
        { "status",     lpc_status,     help_status,    1 },
        { "abort",      lpc_abort,      help_abort,     1 },
        { "clean",      lpc_clean,      help_clean,     1 },
        { "disable",    lpc_disable,    help_disable,   1 },
        { "down",       lpc_down,       help_down,      2 },
        { "enable",     lpc_enable,     help_enable,    1 },
        { "restart",    lpc_restart,    help_restart,   1 },
        { "start",      lpc_start,      help_start,     1 },
        { "stop",       lpc_stop,       help_stop,      1 },
        { "up",         lpc_up,         help_up,        1 },
        { "topq",       lpc_topq,       help_topq,      2 },
        { NULL,         NULL,           NULL,           0 }
};

static int
lpc_handler(char *cmd, cmd_handler_t **handler)
{
        int i;

        for (i = 0; cmd_tab[i].cmd != NULL; i++)
                if (strcmp(cmd, cmd_tab[i].cmd) == 0) {
                        *handler = cmd_tab[i].handler;
                        return (cmd_tab[i].num_args);
                }
        return (-1);
}

static char *
lpc_helptext(char *cmd)
{
        int i;

        for (i = 0; cmd_tab[i].cmd != NULL; i++)
                if (strcmp(cmd, cmd_tab[i].cmd) == 0)
                        return (gettext(cmd_tab[i].help_string));
        return (NULL);
}

/* ARGSUSED0 */
static int
lpc_help(papi_service_t svc, char **args)
{
        if (args[1] == NULL) {
                int i;

                printf(gettext("Commands are:\n\n"));
                for (i = 0; cmd_tab[i].cmd != NULL; i++) {
                        printf("\t%s", cmd_tab[i].cmd);
                        if ((i % 7) == 6)
                                printf("\n");
                }
                if ((i % 7) != 6)
                        printf("\n");
        } else {
                char *helptext = lpc_helptext(args[1]);

                if (helptext == NULL)
                        helptext = gettext("no such command");

                printf("%s: %s\n", args[1], helptext);
        }

        return (0);
}

static int
process_one(int (*handler)(papi_service_t, char **), char **av, int expected)
{
        int rc = -1;
        papi_status_t status = PAPI_OK;
        papi_service_t svc = NULL;
        char *printer = av[1];

        if ((printer != NULL) && (expected != 0)) {
                status = papiServiceCreate(&svc, printer, NULL, NULL,
                                        cli_auth_callback, encryption, NULL);
                if (status != PAPI_OK) {
                        fprintf(stderr, gettext(
                                "Failed to contact service for %s: %s\n"),
                                printer, verbose_papi_message(svc, status));
                }
        }

        if (status == PAPI_OK)
                rc = handler(svc, av);

        if (svc != NULL)
                papiServiceDestroy(svc);

        return (rc);
}

static int
process_all(int (*handler)(papi_service_t, char **), char **av, int expected)
{
        papi_status_t status;
        papi_service_t svc = NULL;
        char **printers;
        int rc = 0;

        status = papiServiceCreate(&svc, NULL, NULL, NULL, NULL,
                                encryption, NULL);
        if (status != PAPI_OK) {
                fprintf(stderr, gettext("Failed to contact service: %s\n"),
                        verbose_papi_message(svc, status));
                return (-1);
        }

        if ((printers = interest_list(svc)) != NULL) {
                int i;

                for (i = 0; printers[i] != NULL; i++) {
                        av[1] = printers[i];
                        rc += process_one(handler, av, expected);
                }
        }

        papiServiceDestroy(svc);

        return (rc);
}

static int
process(int ac, char **av)
{
        int (*handler)(papi_service_t, char **) = NULL;
        int num_args = -1;

        char *printer = av[1];
        int rc = -1;

        if ((num_args = lpc_handler(av[0], &handler)) < 0) {
                printf(gettext("%s: invalid command\n"), av[0]);
                return (-1);
        }

        if (((ac == 0) && (num_args == 1)) ||
            ((printer != NULL) && strcmp(printer, "all") == 0))
                rc = process_all(handler, av, num_args);
        else if (num_args < ac) {
                int i;
                char *argv[4];

                memset(argv, 0, sizeof (argv));
                argv[0] = av[0];

                if (strcmp(av[0], "topq") == 0) {
                        argv[1] = av[1];
                        for (i = 2; i <= ac; i++) {
                                argv[2] = av[i];
                                process_one(handler, argv, num_args);
                        }
                } else
                        for (i = 1; i <= ac; i++) {
                                argv[1] = av[i];
                                process_one(handler, argv, num_args);
                        }
        } else
                rc = process_one(handler, av, num_args);

        return (rc);
}

static void
usage(char *program)
{
        char *name;

        if ((name = strrchr(program, '/')) == NULL)
                name = program;
        else
                name++;

        fprintf(stdout,
                gettext("Usage: %s [ command [ parameter...]]\n"),
                name);
        exit(1);
}

static void
lpc_shell()
{
        for (;;) {
                char line[256];
                char **av = NULL;
                int ac = 0;

                /* prompt */
                fprintf(stdout, "lpc> ");
                fflush(stdout);

                /* get command */
                if (fgets(line, sizeof (line), stdin) == NULL)
                        exit(1);
                if ((av = strsplit(line, " \t\n")) != NULL)
                        for (ac = 0; av[ac] != NULL; ac++);
                else
                        continue;

                if (ac > 0)
                        (void) process(ac - 1, av);
                free(av);
        }
}

int
main(int ac, char *av[])
{
        int result = 0;
        int c;

        (void) setlocale(LC_ALL, "");
        (void) textdomain("SUNW_OST_OSCMD");

        while ((c = getopt(ac, av, "E")) != EOF)
                switch (c) {
                case 'E':
                        encryption = PAPI_ENCRYPT_ALWAYS;
                        break;
                default:
                        usage(av[0]);
                }

        if (optind == ac)
                lpc_shell();
        else
                result = process(ac - optind - 1, &av[optind]);

        return (result);
}