PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/usr.sbin/lpr/common_source/printcap.c

https://bitbucket.org/freebsd/freebsd-base
C | 447 lines | 286 code | 38 blank | 123 comment | 43 complexity | 0bef534b728b67aff99f55c197bc772c MD5 | raw file
  1. /*-
  2. * SPDX-License-Identifier: BSD-4-Clause
  3. *
  4. * Copyright (c) 1983, 1993
  5. * The Regents of the University of California. All rights reserved.
  6. * (c) UNIX System Laboratories, Inc.
  7. * All or some portions of this file are derived from material licensed
  8. * to the University of California by American Telephone and Telegraph
  9. * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  10. * the permission of UNIX System Laboratories, Inc.
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * 3. All advertising materials mentioning features or use of this software
  21. * must display the following acknowledgement:
  22. * This product includes software developed by the University of
  23. * California, Berkeley and its contributors.
  24. * 4. Neither the name of the University nor the names of its contributors
  25. * may be used to endorse or promote products derived from this software
  26. * without specific prior written permission.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38. * SUCH DAMAGE.
  39. */
  40. #if 0
  41. #ifndef lint
  42. static char sccsid[] = "@(#)printcap.c 8.2 (Berkeley) 4/28/95";
  43. #endif /* not lint */
  44. #endif
  45. #include "lp.cdefs.h" /* A cross-platform version of <sys/cdefs.h> */
  46. __FBSDID("$FreeBSD$");
  47. #include <errno.h>
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include <unistd.h>
  52. #include <sys/param.h> /* required for lp.h, but not used here */
  53. #include <sys/dirent.h> /* ditto */
  54. #include "lp.h"
  55. #include "lp.local.h"
  56. #include "pathnames.h"
  57. /*
  58. * Routines and data used in processing the printcap file.
  59. */
  60. static char *printcapdb[] = { __DECONST(char *, _PATH_PRINTCAP), NULL };
  61. static char *capdb_canonical_name(const char *_bp);
  62. static int capdb_getaltlog(char *_bp, const char *_shrt,
  63. const char *_lng);
  64. static int capdb_getaltnum(char *_bp, const char *_shrt,
  65. const char *_lng, long _dflt, long *_result);
  66. static int capdb_getaltstr(char *_bp, const char *_shrt,
  67. const char *lng, const char *_dflt, char **_result);
  68. static int getprintcap_int(char *_bp, struct printer *_pp);
  69. /*
  70. * Change the name of the printcap file. Used by chkprintcap(8),
  71. * but could be used by other members of the suite with appropriate
  72. * security measures.
  73. */
  74. void
  75. setprintcap(char *newfile)
  76. {
  77. printcapdb[0] = newfile;
  78. }
  79. /*
  80. * Read the printcap database for printer `printer' into the
  81. * struct printer pointed by `pp'. Return values are as for
  82. * cgetent(3): -1 means we could not find what we wanted, -2
  83. * means a system error occurred (and errno is set), -3 if a
  84. * reference (`tc=') loop was detected, and 0 means success.
  85. *
  86. * Copied from lpr; should add additional capabilities as they
  87. * are required by the other programs in the suite so that
  88. * printcap-reading is consistent across the entire family.
  89. */
  90. int
  91. getprintcap(const char *printer, struct printer *pp)
  92. {
  93. int status;
  94. char *bp;
  95. if ((status = cgetent(&bp, printcapdb, printer)) < 0)
  96. return status;
  97. status = getprintcap_int(bp, pp);
  98. free(bp);
  99. return status;
  100. }
  101. /*
  102. * Map the status values returned by cgetfirst/cgetnext into those
  103. * used by cgetent, returning truth if there are more records to
  104. * examine. This points out what is arguably a bug in the cget*
  105. * interface (or at least a nasty wart).
  106. */
  107. static int
  108. firstnextmap(int *status)
  109. {
  110. switch (*status) {
  111. case 0:
  112. return 0;
  113. case 1:
  114. *status = 0;
  115. return 1;
  116. case 2:
  117. *status = 1;
  118. return 1;
  119. case -1:
  120. *status = -2;
  121. return 0;
  122. case -2:
  123. *status = -3;
  124. return 1;
  125. default:
  126. return 0;
  127. }
  128. }
  129. /*
  130. * Scan through the database of printers using cgetfirst/cgetnext.
  131. * Return false of error or end-of-database; else true.
  132. */
  133. int
  134. firstprinter(struct printer *pp, int *error)
  135. {
  136. int status;
  137. char *bp;
  138. init_printer(pp);
  139. status = cgetfirst(&bp, printcapdb);
  140. if (firstnextmap(&status) == 0) {
  141. if (error)
  142. *error = status;
  143. return 0;
  144. }
  145. if (error)
  146. *error = status;
  147. status = getprintcap_int(bp, pp);
  148. free(bp);
  149. if (error && status)
  150. *error = status;
  151. return 1;
  152. }
  153. int
  154. nextprinter(struct printer *pp, int *error)
  155. {
  156. int status;
  157. char *bp;
  158. free_printer(pp);
  159. status = cgetnext(&bp, printcapdb);
  160. if (firstnextmap(&status) == 0) {
  161. if (error)
  162. *error = status;
  163. return 0;
  164. }
  165. if (error)
  166. *error = status;
  167. status = getprintcap_int(bp, pp);
  168. free(bp);
  169. if (error && status)
  170. *error = status;
  171. return 1;
  172. }
  173. void
  174. lastprinter(void)
  175. {
  176. cgetclose();
  177. }
  178. /*
  179. * This must match the order of declaration of enum filter in lp.h.
  180. */
  181. static const char *filters[] = {
  182. "cf", "df", "gf", "if", "nf", "of", "rf", "tf", "vf"
  183. };
  184. static const char *longfilters[] = {
  185. "filt.cifplot", "filt.dvi", "filt.plot", "filt.input", "filt.ditroff",
  186. "filt.output", "filt.fortran", "filt.troff", "filt.raster"
  187. };
  188. /*
  189. * Internal routine for both getprintcap() and nextprinter().
  190. * Actually parse the printcap entry using cget* functions.
  191. * Also attempt to figure out the canonical name of the printer
  192. * and store a malloced copy of it in pp->printer.
  193. */
  194. static int
  195. getprintcap_int(char *bp, struct printer *pp)
  196. {
  197. enum lpd_filters filt;
  198. char *rp_name;
  199. int error;
  200. if ((pp->printer = capdb_canonical_name(bp)) == NULL)
  201. return PCAPERR_OSERR;
  202. #define CHK(x) do {if ((x) == PCAPERR_OSERR) return PCAPERR_OSERR;}while(0)
  203. CHK(capdb_getaltstr(bp, "af", "acct.file", 0, &pp->acct_file));
  204. CHK(capdb_getaltnum(bp, "br", "tty.rate", 0, &pp->baud_rate));
  205. CHK(capdb_getaltnum(bp, "ct", "remote.timeout", DEFTIMEOUT,
  206. &pp->conn_timeout));
  207. CHK(capdb_getaltnum(bp, "du", "daemon.user", DEFUID,
  208. &pp->daemon_user));
  209. CHK(capdb_getaltstr(bp, "ff", "job.formfeed", DEFFF, &pp->form_feed));
  210. CHK(capdb_getaltstr(bp, "lf", "spool.log", _PATH_CONSOLE,
  211. &pp->log_file));
  212. CHK(capdb_getaltstr(bp, "lo", "spool.lock", DEFLOCK, &pp->lock_file));
  213. CHK(capdb_getaltstr(bp, "lp", "tty.device", _PATH_DEFDEVLP, &pp->lp));
  214. CHK(capdb_getaltnum(bp, "mc", "max.copies", DEFMAXCOPIES,
  215. &pp->max_copies));
  216. CHK(capdb_getaltstr(bp, "ms", "tty.mode", 0, &pp->mode_set));
  217. CHK(capdb_getaltnum(bp, "mx", "max.blocks", DEFMX, &pp->max_blocks));
  218. CHK(capdb_getaltnum(bp, "pc", "acct.price", 0, &pp->price100));
  219. CHK(capdb_getaltnum(bp, "pl", "page.length", DEFLENGTH,
  220. &pp->page_length));
  221. CHK(capdb_getaltnum(bp, "pw", "page.width", DEFWIDTH,
  222. &pp->page_width));
  223. CHK(capdb_getaltnum(bp, "px", "page.pwidth", 0, &pp->page_pwidth));
  224. CHK(capdb_getaltnum(bp, "py", "page.plength", 0, &pp->page_plength));
  225. CHK(capdb_getaltstr(bp, "rg", "daemon.restrictgrp", 0,
  226. &pp->restrict_grp));
  227. CHK(capdb_getaltstr(bp, "rm", "remote.host", 0, &pp->remote_host));
  228. CHK(capdb_getaltstr(bp, "rp", "remote.queue", DEFLP,
  229. &pp->remote_queue));
  230. CHK(capdb_getaltstr(bp, "sd", "spool.dir", _PATH_DEFSPOOL,
  231. &pp->spool_dir));
  232. CHK(capdb_getaltstr(bp, "sr", "stat.recv", 0, &pp->stat_recv));
  233. CHK(capdb_getaltstr(bp, "ss", "stat.send", 0, &pp->stat_send));
  234. CHK(capdb_getaltstr(bp, "st", "spool.status", DEFSTAT,
  235. &pp->status_file));
  236. CHK(capdb_getaltstr(bp, "tr", "job.trailer", 0, &pp->trailer));
  237. pp->resend_copies = capdb_getaltlog(bp, "rc", "remote.resend_copies");
  238. pp->restricted = capdb_getaltlog(bp, "rs", "daemon.restricted");
  239. pp->short_banner = capdb_getaltlog(bp, "sb", "banner.short");
  240. pp->no_copies = capdb_getaltlog(bp, "sc", "job.no_copies");
  241. pp->no_formfeed = capdb_getaltlog(bp, "sf", "job.no_formfeed");
  242. pp->no_header = capdb_getaltlog(bp, "sh", "banner.disable");
  243. pp->header_last = capdb_getaltlog(bp, "hl", "banner.last");
  244. pp->rw = capdb_getaltlog(bp, "rw", "tty.rw");
  245. pp->tof = !capdb_getaltlog(bp, "fo", "job.topofform");
  246. /*
  247. * Decide if the remote printer name matches the local printer name.
  248. * If no name is given then we assume they mean them to match.
  249. * If a name is given see if the rp_name is one of the names for
  250. * this printer.
  251. */
  252. pp->rp_matches_local = 1;
  253. CHK((error = capdb_getaltstr(bp, "rp", "remote.queue", 0, &rp_name)));
  254. if (error != PCAPERR_NOTFOUND && rp_name != NULL) {
  255. if (cgetmatch(bp,rp_name) != 0)
  256. pp->rp_matches_local = 0;
  257. free(rp_name);
  258. }
  259. /*
  260. * Filters:
  261. */
  262. for (filt = 0; filt < LPF_COUNT; filt++) {
  263. CHK(capdb_getaltstr(bp, filters[filt], longfilters[filt], 0,
  264. &pp->filters[filt]));
  265. }
  266. return 0;
  267. }
  268. /*
  269. * Decode the error codes returned by cgetent() using the names we
  270. * made up for them from "lp.h".
  271. * This would have been much better done with Common Error, >sigh<.
  272. * Perhaps this can be fixed in the next incarnation of cget*.
  273. */
  274. const char *
  275. pcaperr(int error)
  276. {
  277. switch(error) {
  278. case PCAPERR_TCOPEN:
  279. return "unresolved tc= expansion";
  280. case PCAPERR_SUCCESS:
  281. return "no error";
  282. case PCAPERR_NOTFOUND:
  283. return "printer not found";
  284. case PCAPERR_OSERR:
  285. return strerror(errno);
  286. case PCAPERR_TCLOOP:
  287. return "loop detected in tc= expansion";
  288. default:
  289. return "unknown printcap error";
  290. }
  291. }
  292. /*
  293. * Initialize a `struct printer' to contain values harmless to
  294. * the other routines in liblpr.
  295. */
  296. void
  297. init_printer(struct printer *pp)
  298. {
  299. static struct printer zero;
  300. *pp = zero;
  301. }
  302. /*
  303. * Free the dynamically-allocated strings in a `struct printer'.
  304. * Idempotent.
  305. */
  306. void
  307. free_printer(struct printer *pp)
  308. {
  309. enum lpd_filters filt;
  310. #define cfree(x) do { if (x) free(x); } while(0)
  311. cfree(pp->printer);
  312. cfree(pp->acct_file);
  313. for (filt = 0; filt < LPF_COUNT; filt++)
  314. cfree(pp->filters[filt]);
  315. cfree(pp->form_feed);
  316. cfree(pp->log_file);
  317. cfree(pp->lock_file);
  318. cfree(pp->lp);
  319. cfree(pp->restrict_grp);
  320. cfree(pp->remote_host);
  321. cfree(pp->remote_queue);
  322. cfree(pp->spool_dir);
  323. cfree(pp->stat_recv);
  324. cfree(pp->stat_send);
  325. cfree(pp->status_file);
  326. cfree(pp->trailer);
  327. cfree(pp->mode_set);
  328. init_printer(pp);
  329. }
  330. /*
  331. * The following routines are part of what would be a sensible library
  332. * interface to capability databases. Maybe someday this will become
  333. * the default.
  334. */
  335. /*
  336. * It provides similar functionality to cgetstr(),
  337. * except that it provides for both a long and a short
  338. * capability name and allows for a default to be specified.
  339. */
  340. static int
  341. capdb_getaltstr(char *bp, const char *shrt, const char *lng,
  342. const char *dflt, char **result)
  343. {
  344. int status;
  345. status = cgetstr(bp, lng, result);
  346. if (status >= 0 || status == PCAPERR_OSERR)
  347. return status;
  348. status = cgetstr(bp, shrt, result);
  349. if (status >= 0 || status == PCAPERR_OSERR)
  350. return status;
  351. if (dflt) {
  352. *result = strdup(dflt);
  353. if (*result == NULL)
  354. return PCAPERR_OSERR;
  355. return strlen(*result);
  356. }
  357. return PCAPERR_NOTFOUND;
  358. }
  359. /*
  360. * The same, only for integers.
  361. */
  362. static int
  363. capdb_getaltnum(char *bp, const char *shrt, const char *lng, long dflt,
  364. long *result)
  365. {
  366. int status;
  367. status = cgetnum(bp, lng, result);
  368. if (status >= 0)
  369. return status;
  370. status = cgetnum(bp, shrt, result);
  371. if (status >= 0)
  372. return status;
  373. *result = dflt;
  374. return 0;
  375. }
  376. /*
  377. * Likewise for logical values. There's no need for a default parameter
  378. * because the default is always false.
  379. */
  380. static int
  381. capdb_getaltlog(char *bp, const char *shrt, const char *lng)
  382. {
  383. if (cgetcap(bp, lng, ':'))
  384. return 1;
  385. if (cgetcap(bp, shrt, ':'))
  386. return 1;
  387. return 0;
  388. }
  389. /*
  390. * Also should be a part of a better cget* library.
  391. * Given a capdb entry, attempt to figure out what its canonical name
  392. * is, and return a malloced copy of it. The canonical name is
  393. * considered to be the first one listed.
  394. */
  395. static char *
  396. capdb_canonical_name(const char *bp)
  397. {
  398. char *retval;
  399. const char *nameend;
  400. nameend = strpbrk(bp, "|:");
  401. if (nameend == NULL)
  402. nameend = bp + 1;
  403. if ((retval = malloc(nameend - bp + 1)) != NULL) {
  404. retval[0] = '\0';
  405. strncat(retval, bp, nameend - bp);
  406. }
  407. return retval;
  408. }