/* * Command line oriented Moira print queue tool. * * Code based on the blanche command line tool and the moira curses tool. * Copyright (C) 2009 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . * * Mark Manley, mmanley@MIT.EDU, 12/09 */ #include #include #include #include #include #include #include #include #include struct member { int type; char *name, *tag; }; const char *deflogserver = "WSLOGGER.MIT.EDU"; /* legacy variables that we need to set regardless */ const char *quotaserver = "[NONE]"; const char *pageprice = "10"; /* argument parsing macro */ #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b)) /* flags from command line */ int info_flag, verbose, noauth; int create_flag, setmac, delete_flag, rename_flag, ka, banner, update_flag; char *lpracl, *lpcacl; char *contact, *newname, *printserver, *type, *hwtype, *mac, *hostname, *queuename; char *duplexname, *logserver, *location, *realname; char *queuename, *whoami, *testqueue; void usage(char **argv); int show_printer_info(char *queuename); int save_printer_info(int argc, char **argv, void *hint); int save_hwaddr(int argc, char **argv, void *hint); void recursive_display_list_members(void); char *get_username(void); int wrap_mr_query(char *handle, int argc, char **argv, int (*callback)(int, char **, void *), void *callarg); void print_query(char *query_name, int argc, char **argv); int CountArgs(char **info); int main(int argc, char **argv) { int status, success; char **arg = argv; char *uargv[2]; char *pargv[PRN_END]; char *membervec[4]; struct member *memberstruct; char *server = NULL, *p; int i; /* clear all flags & lists */ i = info_flag = verbose = noauth = 0; setmac = ka = create_flag = delete_flag = update_flag = 0; location = lpracl = lpcacl = NULL; logserver = duplexname = realname = newname = printserver = type = hwtype = mac = hostname = NULL; contact = NULL; whoami = argv[0]; success = 1; /* parse args */ while (++arg - argv < argc) { if (**arg == '-') { if (argis("i", "info")) info_flag++; else if (argis("C", "create")) create_flag++; else if (argis("D", "delete")) delete_flag++; else if (argis("L", "location")) { if (arg - argv < argc - 1) { ++arg; update_flag++; location = *arg; } else usage(argv); } else if (argis("r", "remotename")) { if (arg - argv < argc - 1) { ++arg; update_flag++; realname = *arg; } else usage(argv); } else if (argis("T", "type")) { if (arg - argv < argc - 1) { ++arg; update_flag++; type = *arg; } else usage(argv); } else if (argis("s", "printserver")) { if (arg - argv < argc - 1) { ++arg; update_flag++; printserver = canonicalize_hostname(strdup(*arg)); } else usage(argv); } else if (argis("M", "model")) { if (arg - argv < argc - 1) { ++arg; update_flag++; hwtype = *arg; } else usage(argv); } else if (argis("K", "kerbauth")) { ka++; update_flag++; } else if (argis("NK", "nokerbauth")) { ka = 0; update_flag++; } else if (argis("H", "hostname")) { if (arg - argv < argc - 1) { ++arg; update_flag++; hostname = canonicalize_hostname(strdup(*arg)); } else usage(argv); } else if (argis("n", "noauth")) noauth++; else if (argis("v", "verbose")) verbose++; else if (argis("S", "server") || argis("db", "database")) { if (arg - argv < argc - 1) { ++arg; server = *arg; } else usage(argv); } else if (argis("c", "contact")) { if (arg - argv < argc - 1) { ++arg; contact = *arg; update_flag++; } else usage(argv); } else if (argis("l", "lpcacl")) { if (arg - argv < argc - 1) { ++arg; lpcacl = *arg; update_flag++; } else usage(argv); } else if (argis("ac", "lpracl")) { if (arg - argv < argc - 1) { ++arg; lpracl = *arg; update_flag++; } else usage(argv); } else if (argis("m", "mac")) { if (arg - argv < argc - 1) { ++arg; setmac++; mac = *arg; } else usage(argv); } else if (argis("b", "banner")) { update_flag++; banner = 1; } else if (argis("nb", "nobanner")) { update_flag++; banner = 0; } else if (argis("L", "logserver")) { if (arg - argv < argc - 1) { ++arg; update_flag++; logserver = canonicalize_hostname(strdup(*arg)); } else usage(argv); } else if (argis("R", "rename")) { if (arg - argv < argc - 1) { rename_flag++; update_flag++; ++arg; newname = *arg; } else usage(argv); } else if (argis("d", "duplex")) { if (arg - argv < argc - 1) { ++arg; update_flag++; duplexname = *arg; } else usage(argv); } else usage(argv); } else if (queuename == NULL) queuename = *arg; else usage(argv); } if (queuename == NULL) usage(argv); if (!update_flag && !rename_flag && !delete_flag && !create_flag && !setmac) info_flag++; /* fire up Moira */ status = mrcl_connect(server, "eunice", 10, !noauth); if (status == MRCL_AUTH_ERROR) { com_err(whoami, 0, "Authentication error while working on queue %s", queuename); com_err(whoami, 0, "Try the -noauth flag if you don't " "need authentication."); } if (status) exit(2); if (create_flag) { if (hostname == NULL || type == NULL || hwtype == NULL ) usage(argv); } for (i = 0; i < PRN_END; i++) pargv[i] = NULL; /* check for name conflicts. */ if (create_flag || rename_flag) { if (rename_flag) testqueue = newname; else testqueue = queuename; status = wrap_mr_query("get_printer", 1, &testqueue, NULL, NULL); if (status != MR_NO_MATCH) { fprintf(stderr, "ERROR: A queue by that name already exists.\n"); exit(1); } status = wrap_mr_query("get_printer_by_duplexname", 1, &testqueue, NULL, NULL); if (status != MR_NO_MATCH) { fprintf(stderr, "ERROR: A duplex queue by that name already exists.\n"); exit(1); } if (duplexname) { status = wrap_mr_query("get_printer_by_duplexname", 1, &testqueue, NULL, NULL); if (status != MR_NO_MATCH) { fprintf(stderr, "ERROR: A duplex queue by that name already exists.\n"); exit(1); } } } /* create if needed */ if (create_flag) { if (realname == NULL) realname = queuename; /* Variable for aliases */ if (logserver == NULL) logserver = (char *) canonicalize_hostname(strdup(deflogserver)); pargv[PRN_NAME] = queuename; pargv[PRN_TYPE] = type; pargv[PRN_HWTYPE] = hwtype; pargv[PRN_DUPLEXNAME] = (duplexname != NULL) ? duplexname : ""; pargv[PRN_HOSTNAME] = hostname; pargv[PRN_LOGHOST] = logserver; pargv[PRN_RM] = (printserver != NULL) ? printserver : "[ANY]"; pargv[PRN_CONTACT] = (contact != NULL) ? contact : ""; pargv[PRN_LOCATION] = (location != NULL) ? location : ""; pargv[PRN_RP] = realname; pargv[PRN_RQ] = (char *) quotaserver; pargv[PRN_KA] = (ka == 1) ? "1" : "0"; pargv[PRN_PC] = (char *) pageprice; if (lpracl != NULL) { status = wrap_mr_query("get_list_info", 1, &lpracl, NULL, NULL); if (status) { com_err(whoami, status, "while getting authentication list information"); exit(1); } pargv[PRN_AC] = lpracl; } else pargv[PRN_AC] = "[none]"; if (lpcacl != NULL) { status = wrap_mr_query("get_list_info", 1, &lpcacl, NULL, NULL); if (status) { com_err(whoami, status, "while getting authentication list information"); exit(1); } pargv[PRN_LPC_ACL] = lpcacl; } else pargv[PRN_LPC_ACL] = "[none]"; pargv[PRN_BANNER] = (banner == 1) ? "1" : "0"; status = wrap_mr_query("add_printer", CountArgs(pargv), pargv, NULL, NULL); if (status) { com_err(whoami, status, "while creating print queue."); exit(1); } else printf ("%s: queue %s created.\n", whoami, queuename); } else if (update_flag) { status = wrap_mr_query("get_printer", 1, &queuename, save_printer_info, pargv); if (status) { com_err(whoami, status, "while getting printer information"); exit(1); } pargv[0] = queuename; if (newname && rename_flag) pargv[PRN_NAME + 1] = newname; if (type != NULL) pargv[PRN_TYPE + 1] = type; if (hwtype != NULL) pargv[PRN_HWTYPE + 1] = hwtype; if (duplexname != NULL) pargv[PRN_DUPLEXNAME + 1] = duplexname; if (hostname != NULL) pargv[PRN_HOSTNAME + 1] = hostname; if (logserver != NULL) pargv[PRN_LOGHOST + 1] = logserver; if (printserver != NULL) pargv[PRN_RM + 1] = printserver; if (realname != NULL) pargv[PRN_RP + 1] = realname; if (quotaserver != NULL && strcmp(quotaserver,"[NONE]")) pargv[PRN_RQ + 1] = (char *) quotaserver; if (ka != -1) pargv[PRN_KA + 1] = ka ? "1" : "0"; if (lpracl != NULL) pargv[PRN_AC + 1] = lpracl; if (lpcacl != NULL) pargv[PRN_LPC_ACL + 1] = lpcacl; if (banner != -1) pargv[PRN_BANNER + 1] = banner ? "1" : "0"; if (location != NULL) pargv[PRN_LOCATION + 1] = location; if (contact != NULL) pargv[PRN_CONTACT + 1] = contact; pargv[PRN_MODBY + 1] = pargv[PRN_MODTIME + 1] = pargv[PRN_MODWITH + 1] = NULL; status = wrap_mr_query("update_printer", CountArgs(pargv), pargv, NULL, NULL); if (status) { com_err(whoami, status, "while updating print queue."); exit(1); } else { if (rename_flag) printf ("%s: queue %s renamed to %s.\n", whoami, queuename, newname); else printf ("%s: queue %s updated.\n", whoami, queuename); } } /* display printer info if requested to */ if (info_flag) show_printer_info(queuename); if (setmac) { status = wrap_mr_query("get_printer", 1, &queuename, save_printer_info, pargv); if (status) { com_err(whoami, status, "while getting printer information"); exit(1); } if (hostname == NULL) uargv[0] = (char *) strdup (pargv[PRN_HOSTNAME + 1]); else uargv[0] = (char *) strdup (hostname); uargv[1] = (char *) strdup (mac); if ((status = wrap_mr_query("update_host_hwaddr", 2, uargv, NULL, NULL))) com_err(whoami, status, "updating ethernet address."); } if (delete_flag) { status = wrap_mr_query("delete_printer", 1, &queuename, NULL, NULL); if (status) { com_err(whoami, status, "while deleting printer"); exit(1); } else printf ("%s: queue %s deleted.\n", whoami, queuename); } /* We're done! */ mr_disconnect(); exit(success ? 0 : 1); } void usage(char **argv) { #define USAGE_OPTIONS_FORMAT " %-39s%s\n" fprintf(stderr, "Usage: %s queue [options]\n", argv[0]); fprintf(stderr, "Options are\n"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose", "-C | -create"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete", "-R | -rename newname"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info", "-L | -location location"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-H | -hostname host", "-c | -contact contact"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-r | -remotename name", "-T | -type printer_type"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-M | -model model", "-s | -printserver print_server"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-K | -kerbauth", "-b | -banner"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-NK | -nokerbauth", "-nb | -nobanner"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-l | -lpcacl list", "-ac | -lpracl contact"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -duplex name", "-n | -noauth"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-m | -mac hwaddr", "-db | -database host[:port]"); exit(1); } int show_printer_info(char *queuename) { char hwaddr[20]; char *pargv[PRN_END]; int status, banner, i; for (i = 0; i < PRN_END; i++) pargv[i] = NULL; memset (hwaddr,'\0',sizeof(hwaddr)); status = wrap_mr_query("get_printer", 1, &queuename, save_printer_info, pargv); if (status) { com_err(whoami, status, "while getting printer information"); exit (1); } status = wrap_mr_query("get_host_hwaddr", 1, &pargv[PRN_HOSTNAME + 1], save_hwaddr, &hwaddr); if (status) sprintf (hwaddr,"none"); banner = atoi(pargv[PRN_BANNER + 1]); printf("Printer: %-18s Duplex queue: %-18s\n", pargv[PRN_NAME + 1], *pargv[PRN_DUPLEXNAME + 1] ? pargv[PRN_DUPLEXNAME + 1] : "[none]"); printf("Type: %-10s Hardware type: %-10s Hardware address: %s\n", pargv[PRN_TYPE + 1], pargv[PRN_HWTYPE + 1], hwaddr); printf("Printer hostname: %s\n", pargv[PRN_HOSTNAME + 1]); printf("Printer log host: %s\n", pargv[PRN_LOGHOST + 1]); printf("Spool host: %s\n", pargv[PRN_RM + 1]); printf("Remote Printer Name: %-10s Banner page: %s\n", pargv[PRN_RP + 1], banner ? ( banner == PRN_BANNER_FIRST ? "Yes" : "Last" ) : "No"); printf("Authentication: %-3s Price/page: %-3s Quota Server: %s\n", atoi(pargv[PRN_KA + 1]) ? "yes" : "no", pargv[PRN_PC + 1], pargv[PRN_RQ + 1]); printf("Restrict list: %-23s LPC ACL: %-23s\n", pargv[PRN_AC + 1], pargv[PRN_LPC_ACL + 1]); printf("Location: %s\n", pargv[PRN_LOCATION + 1]); printf("Contact: %s\n", pargv[PRN_CONTACT + 1]); printf("\n"); printf("Last mod by %s at %s with %s.\n", pargv[PRN_MODBY + 1], pargv[PRN_MODTIME + 1], pargv[PRN_MODWITH + 1]); return MR_CONT; } /* Copy retrieved information about a printer into a new argv */ int save_printer_info(int argc, char **argv, void *hint) { char **nargv = hint; for (argc = 0; argc < PRN_END; argc++) nargv[argc + 1] = strdup(argv[argc]); return MR_CONT; } int save_hwaddr(int argc, char **argv, void *hint) { char *p = hint; strcpy(p,argv[0]); return MR_CONT; } int wrap_mr_query(char *handle, int argc, char **argv, int (*callback)(int, char **, void *), void *callarg) { int status = 0; if (verbose) print_query(handle, argc, argv); status = mr_query(handle, argc, argv, callback, callarg); return (status); } void print_query(char *query_name, int argc, char **argv) { int cnt; printf("qy %s", query_name); for(cnt=0; cnt", argv[cnt]); printf("\n"); } char *get_username(void) { char *username; username = getenv("USER"); if (!username) { username = mrcl_krb_user(); if (!username) { com_err(whoami, 0, "Could not determine username"); exit(1); } } return username; } /* Function Name: CountArgs * Description: Retrieve the number of args in a null terminated * arglist. * Arguments: info - the argument list. * Returns: number if args in the list. */ int CountArgs(char **info) { int number = 0; while (*info) { number++; info++; } return number; }