1156230Smux/*- 2156230Smux * Copyright (c) 2003-2006, Maxime Henrion <mux@FreeBSD.org> 3156230Smux * All rights reserved. 4156230Smux * 5156230Smux * Redistribution and use in source and binary forms, with or without 6156230Smux * modification, are permitted provided that the following conditions 7156230Smux * are met: 8156230Smux * 1. Redistributions of source code must retain the above copyright 9156230Smux * notice, this list of conditions and the following disclaimer. 10156230Smux * 2. Redistributions in binary form must reproduce the above copyright 11156230Smux * notice, this list of conditions and the following disclaimer in the 12156230Smux * documentation and/or other materials provided with the distribution. 13156230Smux * 14156230Smux * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15156230Smux * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16156230Smux * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17156230Smux * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18156230Smux * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19156230Smux * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20156230Smux * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21156230Smux * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22156230Smux * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23156230Smux * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24156230Smux * SUCH DAMAGE. 25156230Smux * 26156230Smux * $FreeBSD$ 27156230Smux */ 28156230Smux 29156230Smux#include <sys/types.h> 30156230Smux#include <sys/stat.h> 31156230Smux 32156230Smux#include <errno.h> 33156230Smux#include <fcntl.h> 34156230Smux#include <stdio.h> 35156230Smux#include <stdlib.h> 36156230Smux#include <string.h> 37156230Smux#include <unistd.h> 38156230Smux 39156230Smux#include "config.h" 40156230Smux#include "globtree.h" 41156230Smux#include "keyword.h" 42156230Smux#include "misc.h" 43156230Smux#include "parse.h" 44156230Smux#include "stream.h" 45156230Smux#include "token.h" 46156230Smux 47156230Smuxstatic int config_parse_refusefiles(struct coll *); 48156230Smuxstatic int config_parse_refusefile(struct coll *, char *); 49156230Smux 50156230Smuxextern FILE *yyin; 51156230Smux 52156230Smux/* These are globals because I can't think of a better way with yacc. */ 53156230Smuxstatic STAILQ_HEAD(, coll) colls; 54156230Smuxstatic struct coll *cur_coll; 55156230Smuxstatic struct coll *defaults; 56156701Smuxstatic struct coll *ovcoll; 57156701Smuxstatic int ovmask; 58156230Smuxstatic const char *cfgfile; 59156230Smux 60156230Smux/* 61156230Smux * Extract all the configuration information from the config 62156230Smux * file and some command line parameters. 63156230Smux */ 64156230Smuxstruct config * 65156230Smuxconfig_init(const char *file, struct coll *override, int overridemask) 66156230Smux{ 67156230Smux struct config *config; 68156230Smux struct coll *coll; 69156230Smux size_t slen; 70156230Smux char *prefix; 71156230Smux int error; 72156230Smux mode_t mask; 73156230Smux 74156230Smux config = xmalloc(sizeof(struct config)); 75156230Smux memset(config, 0, sizeof(struct config)); 76156230Smux STAILQ_INIT(&colls); 77156230Smux 78156230Smux defaults = coll_new(NULL); 79156230Smux /* Set the default umask. */ 80156230Smux mask = umask(0); 81156230Smux umask(mask); 82156230Smux defaults->co_umask = mask; 83156701Smux ovcoll = override; 84156701Smux ovmask = overridemask; 85156230Smux 86156230Smux /* Extract a list of collections from the configuration file. */ 87156230Smux cur_coll = coll_new(defaults); 88156230Smux yyin = fopen(file, "r"); 89156230Smux if (yyin == NULL) { 90156701Smux lprintf(-1, "Cannot open \"%s\": %s\n", file, strerror(errno)); 91156230Smux goto bad; 92156230Smux } 93156230Smux cfgfile = file; 94156230Smux error = yyparse(); 95156230Smux fclose(yyin); 96156230Smux if (error) 97156230Smux goto bad; 98156230Smux 99156230Smux memcpy(&config->colls, &colls, sizeof(colls)); 100156230Smux if (STAILQ_EMPTY(&config->colls)) { 101156230Smux lprintf(-1, "Empty supfile\n"); 102156230Smux goto bad; 103156230Smux } 104156230Smux 105156230Smux /* Fixup the list of collections. */ 106156230Smux STAILQ_FOREACH(coll, &config->colls, co_next) { 107156230Smux if (coll->co_base == NULL) 108156230Smux coll->co_base = xstrdup("/usr/local/etc/cvsup"); 109156230Smux if (coll->co_colldir == NULL) 110156230Smux coll->co_colldir = "sup"; 111156230Smux if (coll->co_prefix == NULL) { 112156230Smux coll->co_prefix = xstrdup(coll->co_base); 113156230Smux /* 114156230Smux * If prefix is not an absolute pathname, it is 115156230Smux * interpreted relative to base. 116156230Smux */ 117156230Smux } else if (coll->co_prefix[0] != '/') { 118156230Smux slen = strlen(coll->co_base); 119156230Smux if (slen > 0 && coll->co_base[slen - 1] != '/') 120156230Smux xasprintf(&prefix, "%s/%s", coll->co_base, 121156230Smux coll->co_prefix); 122156230Smux else 123156230Smux xasprintf(&prefix, "%s%s", coll->co_base, 124156230Smux coll->co_prefix); 125156230Smux free(coll->co_prefix); 126156230Smux coll->co_prefix = prefix; 127156230Smux } 128156230Smux coll->co_prefixlen = strlen(coll->co_prefix); 129156230Smux /* Determine whether to checksum RCS files or not. */ 130156230Smux if (coll->co_options & CO_EXACTRCS) 131156230Smux coll->co_options |= CO_CHECKRCS; 132156230Smux else 133156230Smux coll->co_options &= ~CO_CHECKRCS; 134156230Smux /* In recent versions, we always try to set the file modes. */ 135156230Smux coll->co_options |= CO_SETMODE; 136156230Smux coll->co_options |= CO_NORSYNC; 137156230Smux error = config_parse_refusefiles(coll); 138156230Smux if (error) 139156230Smux goto bad; 140156230Smux } 141156230Smux 142156230Smux coll_free(cur_coll); 143156230Smux coll_free(defaults); 144156230Smux config->host = STAILQ_FIRST(&config->colls)->co_host; 145156230Smux return (config); 146156230Smuxbad: 147156230Smux coll_free(cur_coll); 148156230Smux coll_free(defaults); 149156230Smux config_free(config); 150156230Smux return (NULL); 151156230Smux} 152156230Smux 153156230Smuxint 154156230Smuxconfig_checkcolls(struct config *config) 155156230Smux{ 156156230Smux char linkname[4]; 157156230Smux struct stat sb; 158156230Smux struct coll *coll; 159156230Smux int error, numvalid, ret; 160156230Smux 161156230Smux numvalid = 0; 162156230Smux STAILQ_FOREACH(coll, &config->colls, co_next) { 163156230Smux error = stat(coll->co_prefix, &sb); 164156230Smux if (error || !S_ISDIR(sb.st_mode)) { 165156230Smux /* Skip this collection, and warn about it unless its 166156230Smux prefix is a symbolic link pointing to "SKIP". */ 167156230Smux coll->co_options |= CO_SKIP; 168156230Smux ret = readlink(coll->co_prefix, linkname, 169156230Smux sizeof(linkname)); 170156230Smux if (ret != 4 || memcmp(linkname, "SKIP", 4) != 0) { 171156230Smux lprintf(-1,"Nonexistent prefix \"%s\" for " 172156230Smux "%s/%s\n", coll->co_prefix, coll->co_name, 173156230Smux coll->co_release); 174156230Smux } 175156230Smux continue; 176156230Smux } 177156230Smux numvalid++; 178156230Smux } 179156230Smux return (numvalid); 180156230Smux} 181156230Smux 182156230Smuxstatic int 183156230Smuxconfig_parse_refusefiles(struct coll *coll) 184156230Smux{ 185156230Smux char *collstem, *suffix, *supdir, *path; 186156230Smux int error; 187156230Smux 188156230Smux if (coll->co_colldir[0] == '/') 189156230Smux supdir = xstrdup(coll->co_colldir); 190156230Smux else 191156230Smux xasprintf(&supdir, "%s/%s", coll->co_base, coll->co_colldir); 192156230Smux 193156230Smux /* First, the global refuse file that applies to all collections. */ 194156230Smux xasprintf(&path, "%s/refuse", supdir); 195156230Smux error = config_parse_refusefile(coll, path); 196156230Smux free(path); 197156230Smux if (error) { 198156230Smux free(supdir); 199156230Smux return (error); 200156230Smux } 201156230Smux 202156230Smux /* Next the per-collection refuse files that applies to all release/tag 203156230Smux combinations. */ 204156230Smux xasprintf(&collstem, "%s/%s/refuse", supdir, coll->co_name); 205156230Smux free(supdir); 206156230Smux error = config_parse_refusefile(coll, collstem); 207156230Smux if (error) { 208156230Smux free(collstem); 209156230Smux return (error); 210156230Smux } 211156230Smux 212156230Smux /* Finally, the per-release and per-tag refuse file. */ 213156230Smux suffix = coll_statussuffix(coll); 214156230Smux if (suffix != NULL) { 215156230Smux xasprintf(&path, "%s%s", collstem, suffix); 216156230Smux free(suffix); 217156230Smux error = config_parse_refusefile(coll, path); 218156230Smux free(path); 219156230Smux } 220156230Smux free(collstem); 221156230Smux return (error); 222156230Smux} 223156230Smux 224156230Smux/* 225156230Smux * Parses a "refuse" file, and records the relevant information in 226156230Smux * coll->co_refusals. If the file does not exist, it is silently 227156230Smux * ignored. 228156230Smux */ 229156230Smuxstatic int 230156230Smuxconfig_parse_refusefile(struct coll *coll, char *path) 231156230Smux{ 232156230Smux struct stream *rd; 233156701Smux char *cp, *line, *pat; 234156230Smux 235156230Smux rd = stream_open_file(path, O_RDONLY); 236156230Smux if (rd == NULL) 237156230Smux return (0); 238156701Smux while ((line = stream_getln(rd, NULL)) != NULL) { 239156701Smux pat = line; 240156701Smux for (;;) { 241156701Smux /* Trim leading whitespace. */ 242156701Smux pat += strspn(pat, " \t"); 243156701Smux if (pat[0] == '\0') 244156701Smux break; 245156701Smux cp = strpbrk(pat, " \t"); 246156701Smux if (cp != NULL) 247156701Smux *cp = '\0'; 248156701Smux pattlist_add(coll->co_refusals, pat); 249156701Smux if (cp == NULL) 250156701Smux break; 251156701Smux pat = cp + 1; 252156701Smux } 253156701Smux } 254156230Smux if (!stream_eof(rd)) { 255156230Smux stream_close(rd); 256156230Smux lprintf(-1, "Read failure from \"%s\": %s\n", path, 257156230Smux strerror(errno)); 258156230Smux return (-1); 259156230Smux } 260156230Smux stream_close(rd); 261156230Smux return (0); 262156230Smux} 263156230Smux 264156230Smuxvoid 265156230Smuxconfig_free(struct config *config) 266156230Smux{ 267156230Smux struct coll *coll; 268156230Smux 269156230Smux while (!STAILQ_EMPTY(&config->colls)) { 270156230Smux coll = STAILQ_FIRST(&config->colls); 271156230Smux STAILQ_REMOVE_HEAD(&config->colls, co_next); 272156230Smux coll_free(coll); 273156230Smux } 274156230Smux if (config->server != NULL) 275156230Smux stream_close(config->server); 276156230Smux if (config->laddr != NULL) 277156230Smux free(config->laddr); 278156230Smux free(config); 279156230Smux} 280156230Smux 281156230Smux/* Create a new collection, inheriting options from the default collection. */ 282156230Smuxstruct coll * 283156230Smuxcoll_new(struct coll *def) 284156230Smux{ 285156230Smux struct coll *new; 286156230Smux 287156230Smux new = xmalloc(sizeof(struct coll)); 288156230Smux memset(new, 0, sizeof(struct coll)); 289156230Smux if (def != NULL) { 290156230Smux new->co_options = def->co_options; 291156230Smux new->co_umask = def->co_umask; 292156230Smux if (def->co_host != NULL) 293156230Smux new->co_host = xstrdup(def->co_host); 294156230Smux if (def->co_base != NULL) 295156230Smux new->co_base = xstrdup(def->co_base); 296156230Smux if (def->co_date != NULL) 297156230Smux new->co_date = xstrdup(def->co_date); 298156230Smux if (def->co_prefix != NULL) 299156230Smux new->co_prefix = xstrdup(def->co_prefix); 300156230Smux if (def->co_release != NULL) 301156230Smux new->co_release = xstrdup(def->co_release); 302156230Smux if (def->co_tag != NULL) 303156230Smux new->co_tag = xstrdup(def->co_tag); 304156230Smux if (def->co_listsuffix != NULL) 305156230Smux new->co_listsuffix = xstrdup(def->co_listsuffix); 306156230Smux } else { 307156230Smux new->co_tag = xstrdup("."); 308156230Smux new->co_date = xstrdup("."); 309156230Smux } 310156230Smux new->co_keyword = keyword_new(); 311156230Smux new->co_accepts = pattlist_new(); 312156230Smux new->co_refusals = pattlist_new(); 313156230Smux new->co_attrignore = FA_DEV | FA_INODE; 314156230Smux return (new); 315156230Smux} 316156230Smux 317156230Smuxvoid 318156230Smuxcoll_override(struct coll *coll, struct coll *from, int mask) 319156230Smux{ 320156230Smux size_t i; 321156230Smux int newoptions, oldoptions; 322156230Smux 323156230Smux newoptions = from->co_options & mask; 324156230Smux oldoptions = coll->co_options & (CO_MASK & ~mask); 325156230Smux 326156230Smux if (from->co_release != NULL) { 327156230Smux if (coll->co_release != NULL) 328156230Smux free(coll->co_release); 329156230Smux coll->co_release = xstrdup(from->co_release); 330156230Smux } 331156230Smux if (from->co_host != NULL) { 332156230Smux if (coll->co_host != NULL) 333156230Smux free(coll->co_host); 334156230Smux coll->co_host = xstrdup(from->co_host); 335156230Smux } 336156230Smux if (from->co_base != NULL) { 337156230Smux if (coll->co_base != NULL) 338156230Smux free(coll->co_base); 339156230Smux coll->co_base = xstrdup(from->co_base); 340156230Smux } 341156230Smux if (from->co_colldir != NULL) 342156230Smux coll->co_colldir = from->co_colldir; 343156230Smux if (from->co_prefix != NULL) { 344156230Smux if (coll->co_prefix != NULL) 345156230Smux free(coll->co_prefix); 346156230Smux coll->co_prefix = xstrdup(from->co_prefix); 347156230Smux } 348156230Smux if (newoptions & CO_CHECKOUTMODE) { 349156230Smux if (from->co_tag != NULL) { 350156230Smux if (coll->co_tag != NULL) 351156230Smux free(coll->co_tag); 352156230Smux coll->co_tag = xstrdup(from->co_tag); 353156230Smux } 354156230Smux if (from->co_date != NULL) { 355156230Smux if (coll->co_date != NULL) 356156230Smux free(coll->co_date); 357156230Smux coll->co_date = xstrdup(from->co_date); 358156230Smux } 359156230Smux } 360156230Smux if (from->co_listsuffix != NULL) { 361156230Smux if (coll->co_listsuffix != NULL) 362156230Smux free(coll->co_listsuffix); 363156230Smux coll->co_listsuffix = xstrdup(from->co_listsuffix); 364156230Smux } 365156230Smux for (i = 0; i < pattlist_size(from->co_accepts); i++) { 366156230Smux pattlist_add(coll->co_accepts, 367156230Smux pattlist_get(from->co_accepts, i)); 368156230Smux } 369156230Smux for (i = 0; i < pattlist_size(from->co_refusals); i++) { 370156230Smux pattlist_add(coll->co_refusals, 371156230Smux pattlist_get(from->co_refusals, i)); 372156230Smux } 373156230Smux coll->co_options = oldoptions | newoptions; 374156230Smux} 375156230Smux 376156230Smuxchar * 377156230Smuxcoll_statussuffix(struct coll *coll) 378156230Smux{ 379156230Smux const char *tag; 380156230Smux char *suffix; 381156230Smux 382156230Smux if (coll->co_listsuffix != NULL) { 383156230Smux xasprintf(&suffix, ".%s", coll->co_listsuffix); 384156230Smux } else if (coll->co_options & CO_USERELSUFFIX) { 385156230Smux if (coll->co_tag == NULL) 386156230Smux tag = "."; 387156230Smux else 388156230Smux tag = coll->co_tag; 389156230Smux if (coll->co_release != NULL) { 390156230Smux if (coll->co_options & CO_CHECKOUTMODE) { 391156230Smux xasprintf(&suffix, ".%s:%s", 392156230Smux coll->co_release, tag); 393156230Smux } else { 394156230Smux xasprintf(&suffix, ".%s", coll->co_release); 395156230Smux } 396156230Smux } else if (coll->co_options & CO_CHECKOUTMODE) { 397156230Smux xasprintf(&suffix, ":%s", tag); 398156230Smux } 399156230Smux } else 400156230Smux suffix = NULL; 401156230Smux return (suffix); 402156230Smux} 403156230Smux 404156230Smuxchar * 405156230Smuxcoll_statuspath(struct coll *coll) 406156230Smux{ 407156230Smux char *path, *suffix; 408156230Smux 409156230Smux suffix = coll_statussuffix(coll); 410156230Smux if (suffix != NULL) { 411156230Smux if (coll->co_colldir[0] == '/') 412156230Smux xasprintf(&path, "%s/%s/checkouts%s", coll->co_colldir, 413156230Smux coll->co_name, suffix); 414156230Smux else 415156230Smux xasprintf(&path, "%s/%s/%s/checkouts%s", coll->co_base, 416156230Smux coll->co_colldir, coll->co_name, suffix); 417156230Smux } else { 418156230Smux if (coll->co_colldir[0] == '/') 419156230Smux xasprintf(&path, "%s/%s/checkouts", coll->co_colldir, 420156230Smux coll->co_name); 421156230Smux else 422156230Smux xasprintf(&path, "%s/%s/%s/checkouts", coll->co_base, 423156230Smux coll->co_colldir, coll->co_name); 424156230Smux } 425156230Smux free(suffix); 426156230Smux return (path); 427156230Smux} 428156230Smux 429156230Smuxvoid 430156230Smuxcoll_add(char *name) 431156230Smux{ 432156230Smux struct coll *coll; 433156230Smux 434156230Smux cur_coll->co_name = name; 435156701Smux coll_override(cur_coll, ovcoll, ovmask); 436156230Smux if (cur_coll->co_release == NULL) { 437156230Smux lprintf(-1, "Release not specified for collection " 438156230Smux "\"%s\"\n", cur_coll->co_name); 439156230Smux exit(1); 440156230Smux } 441156230Smux if (cur_coll->co_host == NULL) { 442156230Smux lprintf(-1, "Host not specified for collection " 443156230Smux "\"%s\"\n", cur_coll->co_name); 444156230Smux exit(1); 445156230Smux } 446156230Smux if (!STAILQ_EMPTY(&colls)) { 447156230Smux coll = STAILQ_LAST(&colls, coll, co_next); 448156230Smux if (strcmp(coll->co_host, cur_coll->co_host) != 0) { 449156230Smux lprintf(-1, "All \"host\" fields in the supfile " 450156230Smux "must be the same\n"); 451156230Smux exit(1); 452156230Smux } 453156230Smux } 454156230Smux STAILQ_INSERT_TAIL(&colls, cur_coll, co_next); 455156230Smux cur_coll = coll_new(defaults); 456156230Smux} 457156230Smux 458156230Smuxvoid 459156230Smuxcoll_free(struct coll *coll) 460156230Smux{ 461156230Smux 462156230Smux if (coll == NULL) 463156230Smux return; 464156230Smux if (coll->co_host != NULL) 465156230Smux free(coll->co_host); 466156230Smux if (coll->co_base != NULL) 467156230Smux free(coll->co_base); 468156230Smux if (coll->co_date != NULL) 469156230Smux free(coll->co_date); 470156230Smux if (coll->co_prefix != NULL) 471156230Smux free(coll->co_prefix); 472156230Smux if (coll->co_release != NULL) 473156230Smux free(coll->co_release); 474156230Smux if (coll->co_tag != NULL) 475156230Smux free(coll->co_tag); 476156230Smux if (coll->co_cvsroot != NULL) 477156230Smux free(coll->co_cvsroot); 478156230Smux if (coll->co_name != NULL) 479156230Smux free(coll->co_name); 480156230Smux if (coll->co_listsuffix != NULL) 481156230Smux free(coll->co_listsuffix); 482156230Smux keyword_free(coll->co_keyword); 483156230Smux if (coll->co_dirfilter != NULL) 484156230Smux globtree_free(coll->co_dirfilter); 485156230Smux if (coll->co_dirfilter != NULL) 486156230Smux globtree_free(coll->co_filefilter); 487156701Smux if (coll->co_norsync != NULL) 488156701Smux globtree_free(coll->co_norsync); 489156230Smux if (coll->co_accepts != NULL) 490156230Smux pattlist_free(coll->co_accepts); 491156230Smux if (coll->co_refusals != NULL) 492156230Smux pattlist_free(coll->co_refusals); 493156230Smux free(coll); 494156230Smux} 495156230Smux 496156230Smuxvoid 497156230Smuxcoll_setopt(int opt, char *value) 498156230Smux{ 499156230Smux struct coll *coll; 500156701Smux int error, mask; 501156230Smux 502156230Smux coll = cur_coll; 503156230Smux switch (opt) { 504156230Smux case PT_HOST: 505156230Smux if (coll->co_host != NULL) 506156230Smux free(coll->co_host); 507156230Smux coll->co_host = value; 508156230Smux break; 509156230Smux case PT_BASE: 510156230Smux if (coll->co_base != NULL) 511156230Smux free(coll->co_base); 512156230Smux coll->co_base = value; 513156230Smux break; 514156230Smux case PT_DATE: 515156230Smux if (coll->co_date != NULL) 516156230Smux free(coll->co_date); 517156230Smux coll->co_date = value; 518156230Smux coll->co_options |= CO_CHECKOUTMODE; 519156230Smux break; 520156230Smux case PT_PREFIX: 521156230Smux if (coll->co_prefix != NULL) 522156230Smux free(coll->co_prefix); 523156230Smux coll->co_prefix = value; 524156230Smux break; 525156230Smux case PT_RELEASE: 526156230Smux if (coll->co_release != NULL) 527156230Smux free(coll->co_release); 528156230Smux coll->co_release = value; 529156230Smux break; 530156230Smux case PT_TAG: 531156230Smux if (coll->co_tag != NULL) 532156230Smux free(coll->co_tag); 533156230Smux coll->co_tag = value; 534156230Smux coll->co_options |= CO_CHECKOUTMODE; 535156230Smux break; 536156230Smux case PT_LIST: 537156230Smux if (strchr(value, '/') != NULL) { 538156230Smux lprintf(-1, "Parse error in \"%s\": \"list\" suffix " 539156230Smux "must not contain slashes\n", cfgfile); 540156230Smux exit(1); 541156230Smux } 542156230Smux if (coll->co_listsuffix != NULL) 543156230Smux free(coll->co_listsuffix); 544156230Smux coll->co_listsuffix = value; 545156230Smux break; 546156230Smux case PT_UMASK: 547156701Smux error = asciitoint(value, &mask, 8); 548156230Smux free(value); 549156701Smux if (error) { 550156230Smux lprintf(-1, "Parse error in \"%s\": Invalid " 551156230Smux "umask value\n", cfgfile); 552156230Smux exit(1); 553156230Smux } 554156701Smux coll->co_umask = mask; 555156230Smux break; 556156230Smux case PT_USE_REL_SUFFIX: 557156230Smux coll->co_options |= CO_USERELSUFFIX; 558156230Smux break; 559156230Smux case PT_DELETE: 560156230Smux coll->co_options |= CO_DELETE | CO_EXACTRCS; 561156230Smux break; 562156230Smux case PT_COMPRESS: 563156230Smux coll->co_options |= CO_COMPRESS; 564156230Smux break; 565156701Smux case PT_NORSYNC: 566156701Smux coll->co_options |= CO_NORSYNC; 567156701Smux break; 568156230Smux } 569156230Smux} 570156230Smux 571156230Smux/* Set "coll" as being the default collection. */ 572156230Smuxvoid 573156230Smuxcoll_setdef(void) 574156230Smux{ 575156230Smux 576156230Smux coll_free(defaults); 577156230Smux defaults = cur_coll; 578156230Smux cur_coll = coll_new(defaults); 579156230Smux} 580