~ubuntu-branches/ubuntu/hoary/lpr/hoary

« back to all changes in this revision

Viewing changes to lpc/lpc.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-03-15 14:54:38 UTC
  • Revision ID: james.westby@ubuntu.com-20030315145438-3n1sxzrmv1g34n4t
Tags: upstream-2000.05.07
ImportĀ upstreamĀ versionĀ 2000.05.07

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*      $OpenBSD: lpc.c,v 1.5 1997/01/17 16:12:37 millert Exp $ */
 
2
 
 
3
/*
 
4
 * Copyright (c) 1983, 1993
 
5
 *      The Regents of the University of California.  All rights reserved.
 
6
 *
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer.
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 * 3. All advertising materials mentioning features or use of this software
 
17
 *    must display the following acknowledgement:
 
18
 *      This product includes software developed by the University of
 
19
 *      California, Berkeley and its contributors.
 
20
 * 4. Neither the name of the University nor the names of its contributors
 
21
 *    may be used to endorse or promote products derived from this software
 
22
 *    without specific prior written permission.
 
23
 *
 
24
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
25
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
27
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
28
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
29
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
30
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
31
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
33
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
34
 * SUCH DAMAGE.
 
35
 */
 
36
 
 
37
#ifndef lint
 
38
static char copyright[] =
 
39
"@(#) Copyright (c) 1983, 1993\n\
 
40
        The Regents of the University of California.  All rights reserved.\n";
 
41
#endif /* not lint */
 
42
 
 
43
#ifndef lint
 
44
#if 0
 
45
static char sccsid[] = "@(#)lpc.c       8.3 (Berkeley) 4/28/95";
 
46
#else
 
47
static char rcsid[] = "$OpenBSD: lpc.c,v 1.5 1997/01/17 16:12:37 millert Exp $";
 
48
#endif
 
49
#endif /* not lint */
 
50
 
 
51
#include <sys/param.h>
 
52
 
 
53
#include <dirent.h>
 
54
#include <signal.h>
 
55
#include <setjmp.h>
 
56
#include <syslog.h>
 
57
#include <unistd.h>
 
58
#include <stdlib.h>
 
59
#include <stdio.h>
 
60
#include <ctype.h>
 
61
#include <string.h>
 
62
#include <grp.h>
 
63
#include <sys/param.h>
 
64
#include "lp.h"
 
65
#include "lpc.h"
 
66
#include "extern.h"
 
67
 
 
68
#ifndef LPR_OPER
 
69
#define LPR_OPER        "operator"      /* group name of lpr operators */
 
70
#endif
 
71
 
 
72
/*
 
73
 * lpc -- line printer control program
 
74
 */
 
75
 
 
76
#define MAX_CMDLINE     200
 
77
#define MAX_MARGV       20
 
78
int     fromatty;
 
79
 
 
80
char    cmdline[MAX_CMDLINE];
 
81
int     margc;
 
82
char    *margv[MAX_MARGV];
 
83
int     top;
 
84
uid_t   uid, euid;
 
85
 
 
86
jmp_buf toplevel;
 
87
 
 
88
static void              cmdscanner __P((int));
 
89
static struct cmd       *getcmd __P((char *));
 
90
static void              intr __P((int));
 
91
static void              makeargv __P((void));
 
92
static int               ingroup __P((char *));
 
93
 
 
94
int
 
95
main(argc, argv)
 
96
        int argc;
 
97
        char *argv[];
 
98
{
 
99
        register struct cmd *c;
 
100
 
 
101
        euid = geteuid();
 
102
        uid = getuid();
 
103
        seteuid(uid);
 
104
        name = argv[0];
 
105
        openlog("lpd", 0, LOG_LPR);
 
106
 
 
107
        if (--argc > 0) {
 
108
                c = getcmd(*++argv);
 
109
                if (c == (struct cmd *)-1) {
 
110
                        printf("?Ambiguous command\n");
 
111
                        exit(1);
 
112
                }
 
113
                if (c == 0) {
 
114
                        printf("?Invalid command\n");
 
115
                        exit(1);
 
116
                }
 
117
                if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
 
118
                        printf("?Privileged command\n");
 
119
                        exit(1);
 
120
                }
 
121
                (*c->c_handler)(argc, argv);
 
122
                exit(0);
 
123
        }
 
124
        fromatty = isatty(fileno(stdin));
 
125
        top = setjmp(toplevel) == 0;
 
126
        if (top)
 
127
                signal(SIGINT, intr);
 
128
        for (;;) {
 
129
                cmdscanner(top);
 
130
                top = 1;
 
131
        }
 
132
}
 
133
 
 
134
static void
 
135
intr(signo)
 
136
        int signo;
 
137
{
 
138
        if (!fromatty)
 
139
                exit(0);
 
140
        longjmp(toplevel, 1);
 
141
}
 
142
 
 
143
/*
 
144
 * Command parser.
 
145
 */
 
146
static void
 
147
cmdscanner(top)
 
148
        int top;
 
149
{
 
150
        register struct cmd *c;
 
151
 
 
152
        if (!top)
 
153
                putchar('\n');
 
154
        for (;;) {
 
155
                if (fromatty) {
 
156
                        printf("lpc> ");
 
157
                        fflush(stdout);
 
158
                }
 
159
                if (fgets(cmdline, MAX_CMDLINE, stdin) == 0)
 
160
                        quit(0, NULL);
 
161
                if (cmdline[0] == 0 || cmdline[0] == '\n')
 
162
                        break;
 
163
                makeargv();
 
164
                c = getcmd(margv[0]);
 
165
                if (c == (struct cmd *)-1) {
 
166
                        printf("?Ambiguous command\n");
 
167
                        continue;
 
168
                }
 
169
                if (c == 0) {
 
170
                        printf("?Invalid command\n");
 
171
                        continue;
 
172
                }
 
173
                if (c->c_priv && getuid() && ingroup(LPR_OPER) == 0) {
 
174
                        printf("?Privileged command\n");
 
175
                        continue;
 
176
                }
 
177
                (*c->c_handler)(margc, margv);
 
178
        }
 
179
        longjmp(toplevel, 0);
 
180
}
 
181
 
 
182
static struct cmd *
 
183
getcmd(name)
 
184
        register char *name;
 
185
{
 
186
        register char *p, *q;
 
187
        register struct cmd *c, *found;
 
188
        register int nmatches, longest;
 
189
 
 
190
        longest = 0;
 
191
        nmatches = 0;
 
192
        found = 0;
 
193
        for (c = cmdtab; (p = c->c_name); c++) {
 
194
                for (q = name; *q == *p++; q++)
 
195
                        if (*q == 0)            /* exact match? */
 
196
                                return(c);
 
197
                if (!*q) {                      /* the name was a prefix */
 
198
                        if (q - name > longest) {
 
199
                                longest = q - name;
 
200
                                nmatches = 1;
 
201
                                found = c;
 
202
                        } else if (q - name == longest)
 
203
                                nmatches++;
 
204
                }
 
205
        }
 
206
        if (nmatches > 1)
 
207
                return((struct cmd *)-1);
 
208
        return(found);
 
209
}
 
210
 
 
211
/*
 
212
 * Slice a string up into argc/argv.
 
213
 */
 
214
static void
 
215
makeargv()
 
216
{
 
217
        register char *cp;
 
218
        register char **argp = margv;
 
219
        register int n = 0;
 
220
 
 
221
        margc = 0;
 
222
        for (cp = cmdline; *cp && (cp - cmdline) < sizeof(cmdline) &&
 
223
            n < MAX_MARGV; n++) {
 
224
                while (isspace(*cp))
 
225
                        cp++;
 
226
                if (*cp == '\0')
 
227
                        break;
 
228
                *argp++ = cp;
 
229
                margc += 1;
 
230
                while (*cp != '\0' && !isspace(*cp))
 
231
                        cp++;
 
232
                if (*cp == '\0')
 
233
                        break;
 
234
                *cp++ = '\0';
 
235
        }
 
236
        *argp++ = 0;
 
237
}
 
238
 
 
239
#define HELPINDENT (sizeof ("directory"))
 
240
 
 
241
/*
 
242
 * Help command.
 
243
 */
 
244
void
 
245
help(argc, argv)
 
246
        int argc;
 
247
        char *argv[];
 
248
{
 
249
        register struct cmd *c;
 
250
 
 
251
        if (argc == 1) {
 
252
                register int i, j, w;
 
253
                int columns, width = 0, lines;
 
254
                extern int NCMDS;
 
255
 
 
256
                printf("Commands may be abbreviated.  Commands are:\n\n");
 
257
                for (c = cmdtab; c->c_name; c++) {
 
258
                        int len = strlen(c->c_name);
 
259
 
 
260
                        if (len > width)
 
261
                                width = len;
 
262
                }
 
263
                width = (width + 8) &~ 7;
 
264
                columns = 80 / width;
 
265
                if (columns == 0)
 
266
                        columns = 1;
 
267
                lines = (NCMDS + columns - 1) / columns;
 
268
                for (i = 0; i < lines; i++) {
 
269
                        for (j = 0; j < columns; j++) {
 
270
                                c = cmdtab + j * lines + i;
 
271
                                if (c->c_name)
 
272
                                        printf("%s", c->c_name);
 
273
                                if (c + lines >= &cmdtab[NCMDS]) {
 
274
                                        printf("\n");
 
275
                                        break;
 
276
                                }
 
277
                                w = strlen(c->c_name);
 
278
                                while (w < width) {
 
279
                                        w = (w + 8) &~ 7;
 
280
                                        putchar('\t');
 
281
                                }
 
282
                        }
 
283
                }
 
284
                return;
 
285
        }
 
286
        while (--argc > 0) {
 
287
                register char *arg;
 
288
                arg = *++argv;
 
289
                c = getcmd(arg);
 
290
                if (c == (struct cmd *)-1)
 
291
                        printf("?Ambiguous help command %s\n", arg);
 
292
                else if (c == (struct cmd *)0)
 
293
                        printf("?Invalid help command %s\n", arg);
 
294
                else
 
295
                        printf("%-*s\t%s\n", HELPINDENT,
 
296
                                c->c_name, c->c_help);
 
297
        }
 
298
}
 
299
 
 
300
/*
 
301
 * return non-zero if the user is a member of the given group
 
302
 */
 
303
static int
 
304
ingroup(grname)
 
305
        char *grname;
 
306
{
 
307
        static struct group *gptr=NULL;
 
308
        static gid_t groups[NGROUPS];
 
309
        register gid_t gid;
 
310
        register int i;
 
311
 
 
312
        if (gptr == NULL) {
 
313
                if ((gptr = getgrnam(grname)) == NULL) {
 
314
                        fprintf(stderr, "Warning: unknown group '%s'\n",
 
315
                                grname);
 
316
                        return(0);
 
317
                }
 
318
                if (getgroups(NGROUPS, groups) < 0) {
 
319
                        perror("getgroups");
 
320
                        exit(1);
 
321
                }
 
322
        }
 
323
        gid = gptr->gr_gid;
 
324
        for (i = 0; i < NGROUPS; i++)
 
325
                if (gid == groups[i])
 
326
                        return(1);
 
327
        return(0);
 
328
}