~ubuntu-branches/ubuntu/lucid/rlpr/lucid

« back to all changes in this revision

Viewing changes to src/rlpq.c

  • Committer: Bazaar Package Importer
  • Author(s): Brian Mays
  • Date: 2002-03-20 11:21:15 UTC
  • Revision ID: james.westby@ubuntu.com-20020320112115-whl7m242ig71nu3h
Tags: upstream-2.02
ImportĀ upstreamĀ versionĀ 2.02

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1998, 1999 peter memishian (meem), meem@gnu.org
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2, or (at your option)
 
7
 * any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
12
 * General Public License for more details.
 
13
 *
 
14
 * $Id: rlpq.c,v 1.8 1999/05/04 01:45:24 meem Exp $
 
15
 */
 
16
 
 
17
#include <sys/types.h>
 
18
#include <errno.h>
 
19
#include <pwd.h>
 
20
#include <stdlib.h>
 
21
#include <string.h>
 
22
#include <getopt.h>
 
23
#include <unistd.h>
 
24
#include <stdio.h>
 
25
#include <lib.h>
 
26
 
 
27
#include "intl.h"
 
28
#include "component.h"
 
29
#include "msg.h"
 
30
#include "util.h"
 
31
#include "client.h"
 
32
#include "rlprrc.h"
 
33
#include "rlpq.h"
 
34
#include "rfc1179.h"
 
35
 
 
36
static struct component *components[] =
 
37
{
 
38
    &comp_msg,
 
39
    &comp_component,
 
40
    &comp_client,
 
41
    &comp_rlpq,
 
42
    0
 
43
};
 
44
 
 
45
const char              *program_name;
 
46
const char              *bsd_program_name = "lpq";
 
47
 
 
48
static struct rlpr_rlpq *rlpr_rlpq;
 
49
 
 
50
static const char       *make_queue_request(const char *, char * const *);
 
51
 
 
52
int
 
53
main(int argc, char *argv[])
 
54
{
 
55
    const char         *req;
 
56
    struct component   *comp;
 
57
    char               *user_argv[] = { 0, 0 };
 
58
    char * const       *user_list = user_argv;
 
59
    int                 sock_fd;
 
60
    int                 retval = EXIT_SUCCESS;
 
61
 
 
62
    program_name = argv[0];
 
63
    toggle_root();
 
64
 
 
65
    setlocale(LC_ALL, "");
 
66
    bindtextdomain(PACKAGE, LOCALEDIR);
 
67
    textdomain(PACKAGE);
 
68
 
 
69
    if ((comp = component_init(components, argc, argv)) != 0)
 
70
        msg(R_FATAL, 0, "component `%s': init() failed!", comp->name);
 
71
 
 
72
    /*
 
73
     * if --mine is specified, then use a two-element argv[] that
 
74
     * has the first element set to the current user
 
75
     */
 
76
 
 
77
    if (rlpr_rlpq->mine_only)
 
78
        user_argv[0] = rlpr_rlpq->user;
 
79
    else
 
80
        user_list    = &argv[optind];
 
81
 
 
82
    /*
 
83
     * make the queue request message (which we need to make as
 
84
     * one message because some lpd's are broken and require that
 
85
     * they reap the message in one read(2)).  then connect to
 
86
     * the lpd, send the request and read the reply.
 
87
     */
 
88
 
 
89
    req = make_queue_request(client_get_printer(), user_list);
 
90
 
 
91
    sock_fd = client_open(rlpr_rlpq->timeout);
 
92
    if (sock_fd == -1)
 
93
        msg(R_FATAL, 0, "client_open(): cannot connect to lpd");
 
94
 
 
95
    if (client_command_noack(sock_fd, req, rlpr_rlpq->timeout, "queue request")
 
96
        == 0)
 
97
        msg(R_FATAL, 0, "unable to send queue request to lpd");
 
98
 
 
99
    if (msg_is_quiet()) {
 
100
 
 
101
        char            buffer[BUFSIZ];
 
102
        int             pipe_fd[2];
 
103
        ssize_t         n_read;
 
104
 
 
105
        /*
 
106
         * we'd like to see if there's a "no entries\n" string
 
107
         * returned or not from the lpd.  however, we want to respect
 
108
         * timeouts retrieving this information -- ideally, we'd use
 
109
         * copy_file() since it knows about timeouts.  what to do?
 
110
         * pipes to the rescue.  we're so friggin' clever sometimes.
 
111
         */
 
112
 
 
113
        if (pipe(pipe_fd) == -1)
 
114
            msg(R_FATAL, errno, "pipe");
 
115
 
 
116
        if (copy_file(sock_fd, pipe_fd[1], rlpr_rlpq->timeout, 0, "pipe") == 0)
 
117
            msg(R_FATAL, 0, "unable to get queue output from lpd");
 
118
 
 
119
        if ((n_read = read(pipe_fd[0], buffer, sizeof buffer - 1)) == -1)
 
120
            msg(R_FATAL, errno, "read of piped data from lpd");
 
121
 
 
122
        buffer[n_read] = '\0';
 
123
        if (strcasecmp("no entries\n", buffer) == 0)
 
124
            retval = EXIT_FAILURE;
 
125
 
 
126
    } else {
 
127
 
 
128
        if (copy_file(sock_fd, STDOUT_FILENO, rlpr_rlpq->timeout, 0, "stdout")
 
129
            == 0)
 
130
            msg(R_FATAL, 0, "unable to get queue output from lpd");
 
131
    }
 
132
 
 
133
    close(sock_fd);
 
134
 
 
135
    if ((comp = component_fini(components)) != 0)
 
136
        msg(R_FATAL, 0, "component `%s': fini() failed!", comp->name);
 
137
 
 
138
    return retval;
 
139
}
 
140
 
 
141
static const char *
 
142
make_queue_request(const char *printer, char * const *user_list)
 
143
{
 
144
    unsigned int        request_size = 3; /* "\003\n" */
 
145
    char               *request;
 
146
    unsigned int        i;
 
147
 
 
148
    request_size += strlen(printer);
 
149
    for (i = 0; user_list[i] != 0; i++)
 
150
        request_size += strlen(user_list[i]) + 1;
 
151
 
 
152
    request = xmalloc(request_size);
 
153
    sprintf(request, "%c%s", rlpr_rlpq->long_output ? SENDQL : SENDQS, printer);
 
154
 
 
155
    for (i = 0; user_list[i] != 0; i++) {
 
156
        strcat(request, " ");
 
157
        strcat(request, user_list[i]);
 
158
    }
 
159
 
 
160
    strcat(request, "\n");
 
161
    return request;
 
162
}
 
163
 
 
164
static int
 
165
rlpq_init(void)
 
166
{
 
167
    struct rlpr_rlpq    rlpr_rlpq_tmpl = { 0 };
 
168
    struct passwd      *pwd;
 
169
 
 
170
    /*
 
171
     * we perform a structure copy on a zero-initialized structure
 
172
     * instead of using memset() since memset is a raw bit-oriented
 
173
     * function, which means that it will generate potentially
 
174
     * incorrect results with non-integer types.
 
175
     */
 
176
 
 
177
    rlpr_rlpq   = xmalloc(sizeof (struct rlpr_rlpq));
 
178
    *rlpr_rlpq  = rlpr_rlpq_tmpl;
 
179
    pwd = getpwuid(getuid());
 
180
 
 
181
    if (pwd == 0 || pwd->pw_name == 0) {
 
182
        msg(R_ERROR, errno, "unable to resolve your username");
 
183
        return 0;
 
184
    }
 
185
 
 
186
    rlpr_rlpq->timeout  = R_TIMEOUT_DEFAULT;
 
187
    rlpr_rlpq->user     = xstrdup(pwd->pw_name);
 
188
    return 1;
 
189
}
 
190
 
 
191
static int
 
192
rlpq_parse_args(int opt)
 
193
{
 
194
    switch (opt) {
 
195
 
 
196
    case 'l':
 
197
        rlpr_rlpq->long_output++;
 
198
        break;
 
199
 
 
200
    case 'm':
 
201
        rlpr_rlpq->mine_only++;
 
202
        break;
 
203
 
 
204
    case -500:
 
205
        msg(R_STDOUT, 0, "usage: %s [-Hprinthost] [-Pprinter] [-Xproxy]"
 
206
            " [OPTIONS]\nplease see the manpage for detailed help",
 
207
            program_name);
 
208
        exit(EXIT_SUCCESS);
 
209
        break;
 
210
 
 
211
    case -501:
 
212
        rlpr_rlpq->timeout = strtol(optarg, 0, 0);
 
213
        break;
 
214
 
 
215
    case 'V':
 
216
        msg(R_STDOUT, 0, "version "VERSION" from " __DATE__" "__TIME__
 
217
            " -- meem@gnu.org");
 
218
        exit(EXIT_SUCCESS);
 
219
        break;
 
220
 
 
221
    case EOF:
 
222
        break;
 
223
    }
 
224
 
 
225
    return 1;
 
226
}
 
227
 
 
228
static struct option rlpq_opts[] = {
 
229
    { "help",           0, 0, -500  },
 
230
    { "long",           0, 0, 'l'   },
 
231
    { "mine",           0, 0, 'm'   },
 
232
    { "timeout",        1, 0, -501  },
 
233
    { "version",        0, 0, 'V'   },
 
234
    { 0,                0, 0,  0    }
 
235
};
 
236
 
 
237
static const char rlpq_opt_list[] = "lmV";
 
238
 
 
239
struct component comp_rlpq = {
 
240
    "rlpq", rlpq_init, 0,
 
241
    { { rlpq_opts, rlpq_opt_list, rlpq_parse_args } }
 
242
};