]>
Commit | Line | Data |
---|---|---|
1 | /* $Id$ | |
2 | * | |
3 | * This is the file printer.c for the Moira Client, which allows users | |
4 | * to quickly and easily maintain most parts of the Moira database. | |
5 | * It Contains: Functions for handling the printers. | |
6 | * | |
7 | * Created: 8/16/88 | |
8 | * By: Theodore Y. Ts'o | |
9 | * | |
10 | * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. | |
11 | * For copying and distribution information, please see the file | |
12 | * <mit-copyright.h>. | |
13 | */ | |
14 | ||
15 | #include <mit-copyright.h> | |
16 | #include <moira.h> | |
17 | #include <moira_site.h> | |
18 | #include "defs.h" | |
19 | #include "f_defs.h" | |
20 | #include "globals.h" | |
21 | ||
22 | #include <stdio.h> | |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | ||
26 | RCSID("$Header$"); | |
27 | ||
28 | void RealDeletePrn(char **info, Bool one_item); | |
29 | void ChangePrn(char **info, Bool one_item); | |
30 | extern int GetAliasValue(int argc, char **argv, void *retval); | |
31 | int StoreHWAddr(int argc, char **argv, void *retval); | |
32 | ||
33 | #define BY_NAME 0 | |
34 | #define BY_ETHERNET 1 | |
35 | #define BY_HOSTNAME 2 | |
36 | #define BY_RM 3 | |
37 | #define BY_LOCATION 4 | |
38 | #define BY_CONTACT 5 | |
39 | ||
40 | #define DEFAULT_LOGHOST "WSLOGGER.MIT.EDU" | |
41 | ||
42 | int StoreHWAddr(int argc, char **argv, void *retval) | |
43 | { | |
44 | char **p = retval; | |
45 | *p = strdup(argv[0]); | |
46 | return MR_CONT; | |
47 | } | |
48 | ||
49 | /* Function Name: SetDefaults | |
50 | * Description: sets the default values for filesystem additions. | |
51 | * Arguments: info - an array of char pointers to recieve defaults. | |
52 | * Returns: char ** (this array, now filled). | |
53 | */ | |
54 | ||
55 | static char **SetDefaults(char **info, char *name) | |
56 | { | |
57 | info[PRN_NAME] = strdup(name); | |
58 | info[PRN_TYPE] = strdup("PRIVATE"); | |
59 | info[PRN_HWTYPE] = strdup("HP"); | |
60 | info[PRN_DUPLEXNAME] = strdup(""); | |
61 | info[PRN_HOSTNAME] = strdup(name); | |
62 | info[PRN_LOGHOST] = strdup(DEFAULT_LOGHOST); | |
63 | info[PRN_RM] = strdup("[ANY]"); | |
64 | info[PRN_RP] = strdup(name); | |
65 | info[PRN_RQ] = strdup("[NONE]"); | |
66 | info[PRN_KA] = strdup("1"); | |
67 | info[PRN_PC] = strdup("10"); | |
68 | info[PRN_AC] = strdup("[none]"); | |
69 | info[PRN_LPC_ACL] = strdup("[none]"); | |
70 | info[PRN_LOCATION] = strdup(""); | |
71 | info[PRN_CONTACT] = strdup(""); | |
72 | info[PRN_MODTIME] = info[PRN_MODBY] = info[PRN_MODWITH] = NULL; | |
73 | ||
74 | info[PRN_END] = NULL; | |
75 | return info; | |
76 | } | |
77 | ||
78 | /* Function Name: GetPrnInfo | |
79 | * Description: Stores the info in a queue. | |
80 | * Arguments: name - name of the item to get information on. | |
81 | * Returns: a pointer to the first element in the queue or null | |
82 | * if printer not found. | |
83 | */ | |
84 | ||
85 | static struct mqelem *GetPrnInfo(char *name, int how) | |
86 | { | |
87 | int stat; | |
88 | struct mqelem *elem = NULL; | |
89 | ||
90 | switch (how) | |
91 | { | |
92 | case BY_NAME: | |
93 | stat = do_mr_query("get_printer", 1, &name, StoreInfo, &elem); | |
94 | if (stat == MR_NO_MATCH) | |
95 | { | |
96 | stat = do_mr_query("get_printer_by_duplexname", 1, &name, | |
97 | StoreInfo, &elem); | |
98 | } | |
99 | break; | |
100 | case BY_ETHERNET: | |
101 | stat = do_mr_query("get_printer_by_ethernet", 1, &name, | |
102 | StoreInfo, &elem); | |
103 | break; | |
104 | case BY_HOSTNAME: | |
105 | name = canonicalize_hostname(strdup(name)); | |
106 | stat = do_mr_query("get_printer_by_hostname", 1, &name, | |
107 | StoreInfo, &elem); | |
108 | free(name); | |
109 | break; | |
110 | case BY_RM: | |
111 | name = canonicalize_hostname(strdup(name)); | |
112 | stat = do_mr_query("get_printer_by_rm", 1, &name, | |
113 | StoreInfo, &elem); | |
114 | free(name); | |
115 | break; | |
116 | case BY_LOCATION: | |
117 | stat = do_mr_query("get_printer_by_location", 1, &name, | |
118 | StoreInfo, &elem); | |
119 | break; | |
120 | case BY_CONTACT: | |
121 | stat = do_mr_query("get_printer_by_contact", 1, &name, | |
122 | StoreInfo, &elem); | |
123 | break; | |
124 | } | |
125 | ||
126 | if (stat) | |
127 | { | |
128 | com_err(program_name, stat, " in GetPrnInfo"); | |
129 | return NULL; | |
130 | } | |
131 | return QueueTop(elem); | |
132 | } | |
133 | ||
134 | /* Function Name: PrintPrnInfo | |
135 | * Description: Yet another specialized print function. | |
136 | * Arguments: info - all info about this Printer. | |
137 | * Returns: printer name | |
138 | */ | |
139 | ||
140 | static char *PrintPrnInfo(char **info) | |
141 | { | |
142 | char buf[BUFSIZ], *hwaddr; | |
143 | int status; | |
144 | ||
145 | if (!info) /* If no informaion */ | |
146 | { | |
147 | Put_message("PrintPrnInfo called with null info!"); | |
148 | return NULL; | |
149 | } | |
150 | Put_message(""); | |
151 | sprintf(buf, "Printer: %-18s Duplex queue: %-18s", info[PRN_NAME], | |
152 | *info[PRN_DUPLEXNAME] ? info[PRN_DUPLEXNAME] : "[none]"); | |
153 | Put_message(buf); | |
154 | sprintf(buf, "Type: %-10s Hardware type: %-10s Hardware address: ", | |
155 | info[PRN_TYPE], info[PRN_HWTYPE]); | |
156 | status = do_mr_query("get_host_hwaddr", 1, &info[PRN_HOSTNAME], | |
157 | StoreHWAddr, &hwaddr); | |
158 | if (status == MR_SUCCESS) | |
159 | { | |
160 | strcat(buf, hwaddr); | |
161 | free(hwaddr); | |
162 | } | |
163 | else | |
164 | strcat(buf, "none"); | |
165 | Put_message(buf); | |
166 | sprintf(buf, "Printer hostname: %s", info[PRN_HOSTNAME]); | |
167 | Put_message(buf); | |
168 | sprintf(buf, "Printer log host: %s", info[PRN_LOGHOST]); | |
169 | Put_message(buf); | |
170 | sprintf(buf, "Spool host: %s", info[PRN_RM]); | |
171 | Put_message(buf); | |
172 | sprintf(buf, "Remote Printer Name: %s", info[PRN_RP]); | |
173 | Put_message(buf); | |
174 | sprintf(buf, "Authentication: %-3s Price/page: %-3s Quota Server: %s", | |
175 | atoi(info[PRN_KA]) ? "yes" : "no", info[PRN_PC], info[PRN_RQ]); | |
176 | Put_message(buf); | |
177 | sprintf(buf, "Restrict list: %-23s LPC ACL: %-23s", | |
178 | info[PRN_AC], info[PRN_LPC_ACL]); | |
179 | Put_message(buf); | |
180 | sprintf(buf, "Location: %s", info[PRN_LOCATION]); | |
181 | Put_message(buf); | |
182 | sprintf(buf, "Contact: %s", info[PRN_CONTACT]); | |
183 | Put_message(buf); | |
184 | sprintf(buf, MOD_FORMAT, info[PRN_MODBY], info[PRN_MODTIME], | |
185 | info[PRN_MODWITH]); | |
186 | Put_message(buf); | |
187 | ||
188 | return info[PRN_NAME]; | |
189 | } | |
190 | ||
191 | /* Function Name: AskPrnInfo. | |
192 | * Description: This function askes the user for information about a | |
193 | * printer and saves it into a structure. | |
194 | * Arguments: info - a pointer the the structure to put the | |
195 | * info into. | |
196 | * Returns: none. | |
197 | */ | |
198 | ||
199 | static char **AskPrnInfo(char **info) | |
200 | { | |
201 | char temp_buf[BUFSIZ]; | |
202 | char *args[3], *lpc_acl; | |
203 | char *s, *d; | |
204 | int status; | |
205 | ||
206 | Put_message(""); | |
207 | sprintf(temp_buf, "Printer entry for %s.", info[PRN_NAME]); | |
208 | Put_message(temp_buf); | |
209 | Put_message(""); | |
210 | ||
211 | if (GetTypeFromUser("Type of Printer", "printertype", &info[PRN_TYPE]) == | |
212 | SUB_ERROR) | |
213 | return NULL; | |
214 | if (GetTypeFromUser("Hardware Type", "printerhwtype", &info[PRN_HWTYPE]) == | |
215 | SUB_ERROR) | |
216 | return NULL; | |
217 | if (GetValueFromUser("Duplex spool name", &info[PRN_DUPLEXNAME]) == | |
218 | SUB_ERROR) | |
219 | return NULL; | |
220 | if (GetValueFromUser("Printer hostname (or [none])", &info[PRN_HOSTNAME]) == | |
221 | SUB_ERROR) | |
222 | return NULL; | |
223 | info[PRN_HOSTNAME] = canonicalize_hostname(info[PRN_HOSTNAME]); | |
224 | if (GetValueFromUser("Log host", &info[PRN_LOGHOST]) == SUB_ERROR) | |
225 | return NULL; | |
226 | info[PRN_LOGHOST] = canonicalize_hostname(info[PRN_LOGHOST]); | |
227 | if (GetValueFromUser("Spool host (or [any])", &info[PRN_RM]) == SUB_ERROR) | |
228 | return NULL; | |
229 | info[PRN_RM] = canonicalize_hostname(info[PRN_RM]); | |
230 | if (GetValueFromUser("Remote printer name", &info[PRN_RP]) == SUB_ERROR) | |
231 | return NULL; | |
232 | if (GetValueFromUser("Quota server", &info[PRN_RQ]) == SUB_ERROR) | |
233 | return NULL; | |
234 | info[PRN_RQ] = canonicalize_hostname(info[PRN_RQ]); | |
235 | if (GetYesNoValueFromUser("Kerberos authenticated", &info[PRN_KA]) == | |
236 | SUB_ERROR) | |
237 | return NULL; | |
238 | if (GetValueFromUser("Price per page", &info[PRN_PC]) == SUB_ERROR) | |
239 | return NULL; | |
240 | if (GetValueFromUser("Restrict list", &info[PRN_AC]) == SUB_ERROR) | |
241 | return NULL; | |
242 | args[0] = info[PRN_TYPE]; | |
243 | args[1] = "LPC_ACL"; | |
244 | args[2] = "*"; | |
245 | status = do_mr_query("get_alias", 3, args, GetAliasValue, &lpc_acl); | |
246 | if (status == MR_SUCCESS) | |
247 | { | |
248 | free(info[PRN_LPC_ACL]); | |
249 | info[PRN_LPC_ACL] = lpc_acl; | |
250 | } | |
251 | if (GetValueFromUser("LPC ACL", &info[PRN_LPC_ACL]) == SUB_ERROR) | |
252 | return NULL; | |
253 | if (GetValueFromUser("Location", &info[PRN_LOCATION]) == SUB_ERROR) | |
254 | return NULL; | |
255 | if (GetValueFromUser("Contact", &info[PRN_CONTACT]) == SUB_ERROR) | |
256 | return NULL; | |
257 | ||
258 | FreeAndClear(&info[PRN_MODTIME], TRUE); | |
259 | FreeAndClear(&info[PRN_MODBY], TRUE); | |
260 | FreeAndClear(&info[PRN_MODWITH], TRUE); | |
261 | ||
262 | return info; | |
263 | } | |
264 | ||
265 | /* ---------------- Printer Menu ------------------ */ | |
266 | ||
267 | /* Function Name: GetPrn | |
268 | * Description: Get Printer information | |
269 | * Arguments: argc, argv - name of printer in argv[1]. | |
270 | * Returns: DM_NORMAL. | |
271 | */ | |
272 | ||
273 | int GetPrn(int argc, char **argv) | |
274 | { | |
275 | struct mqelem *top; | |
276 | ||
277 | top = GetPrnInfo(argv[1], BY_NAME); /* get info. */ | |
278 | Loop(top, (void *) PrintPrnInfo); | |
279 | FreeQueue(top); /* clean the queue. */ | |
280 | return DM_NORMAL; | |
281 | } | |
282 | ||
283 | int GetPrnByEthernet(int argc, char **argv) | |
284 | { | |
285 | struct mqelem *top; | |
286 | ||
287 | top = GetPrnInfo(argv[1], BY_ETHERNET); /* get info. */ | |
288 | Loop(top, (void *) PrintPrnInfo); | |
289 | FreeQueue(top); /* clean the queue. */ | |
290 | return DM_NORMAL; | |
291 | } | |
292 | ||
293 | int GetPrnByHostname(int argc, char **argv) | |
294 | { | |
295 | struct mqelem *top; | |
296 | ||
297 | top = GetPrnInfo(argv[1], BY_HOSTNAME); /* get info. */ | |
298 | Loop(top, (void *) PrintPrnInfo); | |
299 | FreeQueue(top); /* clean the queue. */ | |
300 | return DM_NORMAL; | |
301 | } | |
302 | ||
303 | int GetPrnByRM(int argc, char **argv) | |
304 | { | |
305 | struct mqelem *top; | |
306 | ||
307 | top = GetPrnInfo(argv[1], BY_RM); /* get info. */ | |
308 | Loop(top, (void *) PrintPrnInfo); | |
309 | FreeQueue(top); /* clean the queue. */ | |
310 | return DM_NORMAL; | |
311 | } | |
312 | ||
313 | int GetPrnByLocation(int argc, char **argv) | |
314 | { | |
315 | struct mqelem *top; | |
316 | ||
317 | top = GetPrnInfo(argv[1], BY_LOCATION); /* get info. */ | |
318 | Loop(top, (void *) PrintPrnInfo); | |
319 | FreeQueue(top); /* clean the queue. */ | |
320 | return DM_NORMAL; | |
321 | } | |
322 | ||
323 | int GetPrnByContact(int argc, char **argv) | |
324 | { | |
325 | struct mqelem *top; | |
326 | ||
327 | top = GetPrnInfo(argv[1], BY_CONTACT); /* get info. */ | |
328 | Loop(top, (void *) PrintPrnInfo); | |
329 | FreeQueue(top); /* clean the queue. */ | |
330 | return DM_NORMAL; | |
331 | } | |
332 | ||
333 | ||
334 | /* Function Name: RealDeletePrn | |
335 | * Description: Does the real deletion work. | |
336 | * Arguments: info - array of char *'s containing all useful info. | |
337 | * one_item - a Boolean that is true if only one item | |
338 | * in queue that dumped us here. | |
339 | * Returns: none. | |
340 | */ | |
341 | ||
342 | void RealDeletePrn(char **info, Bool one_item) | |
343 | { | |
344 | int stat; | |
345 | ||
346 | if ((stat = do_mr_query("delete_printer", 1, &info[PRN_NAME], NULL, NULL))) | |
347 | com_err(program_name, stat, " printer not deleted."); | |
348 | else | |
349 | Put_message("Printer deleted."); | |
350 | } | |
351 | ||
352 | /* Function Name: DeletePrn | |
353 | * Description: Delete a printer given its name. | |
354 | * Arguments: argc, argv - argv[1] is the name of the printer. | |
355 | * Returns: none. | |
356 | */ | |
357 | ||
358 | int DeletePrn(int argc, char **argv) | |
359 | { | |
360 | struct mqelem *elem = GetPrnInfo(argv[1], BY_NAME); | |
361 | QueryLoop(elem, PrintPrnInfo, RealDeletePrn, "Delete Printer"); | |
362 | ||
363 | FreeQueue(elem); | |
364 | return DM_NORMAL; | |
365 | } | |
366 | ||
367 | /* Function Name: AddPrn | |
368 | * Description: Add a printer | |
369 | * Arguments: arc, argv - name of printer in argv[1]. | |
370 | * Returns: DM_NORMAL. | |
371 | */ | |
372 | ||
373 | int AddPrn(int argc, char **argv) | |
374 | { | |
375 | char *info[MAX_ARGS_SIZE], **args; | |
376 | int stat; | |
377 | ||
378 | if (!ValidName(argv[1])) | |
379 | return DM_NORMAL; | |
380 | ||
381 | if (!(stat = do_mr_query("get_printer", 1, argv + 1, NULL, NULL)) || | |
382 | !(stat = do_mr_query("get_printer_by_duplexname", 1, argv + 1, | |
383 | NULL, NULL))) | |
384 | { | |
385 | Put_message ("A Printer by that name already exists."); | |
386 | return DM_NORMAL; | |
387 | } | |
388 | else if (stat != MR_NO_MATCH) | |
389 | { | |
390 | com_err(program_name, stat, " in AddPrn"); | |
391 | return DM_NORMAL; | |
392 | } | |
393 | ||
394 | args = AskPrnInfo(SetDefaults(info, argv[1])); | |
395 | if (!args) | |
396 | { | |
397 | Put_message("Aborted."); | |
398 | return DM_NORMAL; | |
399 | } | |
400 | ||
401 | if ((stat = do_mr_query("add_printer", CountArgs(args), args, NULL, NULL))) | |
402 | com_err(program_name, stat, " in AddPrn"); | |
403 | ||
404 | if (stat == MR_SUCCESS && strcasecmp(info[PRN_HOSTNAME], "[NONE]")) | |
405 | UpdateHWAddr(2, &info[PRN_HOSTNAME - 1]); | |
406 | ||
407 | FreeInfo(info); | |
408 | return DM_NORMAL; | |
409 | } | |
410 | ||
411 | ||
412 | /* Function Name: ChangePrn | |
413 | * Description: Do the work of changing a Prn | |
414 | * Arguments: argc, argv - printcap info | |
415 | * Returns: | |
416 | */ | |
417 | ||
418 | void ChangePrn(char **info, Bool one_item) | |
419 | { | |
420 | int stat; | |
421 | char **oldinfo; | |
422 | ||
423 | oldinfo = CopyInfo(info); | |
424 | if (!AskPrnInfo(info)) | |
425 | return; | |
426 | if ((stat = do_mr_query("delete_printer", 1, &info[PRN_NAME], NULL, NULL))) | |
427 | { | |
428 | com_err(program_name, stat, " printer not updated."); | |
429 | return; | |
430 | } | |
431 | if ((stat = do_mr_query("add_printer", CountArgs(info), info, NULL, NULL))) | |
432 | { | |
433 | com_err(program_name, stat, " in ChngPrn"); | |
434 | if ((stat = do_mr_query("add_printer", CountArgs(oldinfo) - 3, | |
435 | oldinfo, NULL, NULL))) | |
436 | com_err(program_name, stat, " while attempting to put old info back"); | |
437 | } | |
438 | FreeInfo(oldinfo); | |
439 | return; | |
440 | } | |
441 | ||
442 | ||
443 | /* Function Name: ChngPrn | |
444 | * Description: Update the printcap information | |
445 | * Arguments: argc, argv - name of printer in argv[1]. | |
446 | * Returns: DM_NORMAL. | |
447 | */ | |
448 | ||
449 | int ChngPrn(int argc, char **argv) | |
450 | { | |
451 | struct mqelem *elem = GetPrnInfo(argv[1], BY_NAME); | |
452 | QueryLoop(elem, NullPrint, ChangePrn, "Change the printer"); | |
453 | FreeQueue(elem); | |
454 | return DM_NORMAL; | |
455 | } | |
456 | ||
457 | ||
458 | int UpdateHWAddr(int argc, char **argv) | |
459 | { | |
460 | int stat; | |
461 | char *name, *hwaddr, *s, *d, *uargv[2]; | |
462 | ||
463 | name = canonicalize_hostname(strdup(argv[1])); | |
464 | stat = do_mr_query("get_host_hwaddr", 1, &name, StoreHWAddr, &hwaddr); | |
465 | if (stat != MR_SUCCESS) | |
466 | { | |
467 | free(name); | |
468 | com_err(program_name, stat, " checking host ethernet address"); | |
469 | return DM_NORMAL; | |
470 | } | |
471 | ||
472 | if (GetValueFromUser("Hardware ethernet address", &hwaddr) == SUB_ERROR) | |
473 | { | |
474 | free(name); | |
475 | return DM_NORMAL; | |
476 | } | |
477 | ||
478 | s = d = hwaddr; | |
479 | do | |
480 | { | |
481 | if (*s != ':') | |
482 | *d++ = *s; | |
483 | } | |
484 | while (*s++); | |
485 | ||
486 | uargv[0] = name; | |
487 | uargv[1] = hwaddr; | |
488 | if ((stat = do_mr_query("update_host_hwaddr", 2, uargv, NULL, NULL))) | |
489 | com_err(program_name, stat, " updating ethernet address."); | |
490 | ||
491 | free(name); | |
492 | free(hwaddr); | |
493 | return DM_NORMAL; | |
494 | } |