1b8ba871bSPeter Wemm /*- 2b8ba871bSPeter Wemm * Copyright (c) 1992, 1993, 1994 3b8ba871bSPeter Wemm * The Regents of the University of California. All rights reserved. 4b8ba871bSPeter Wemm * Copyright (c) 1992, 1993, 1994, 1995, 1996 5b8ba871bSPeter Wemm * Keith Bostic. All rights reserved. 6b8ba871bSPeter Wemm * 7b8ba871bSPeter Wemm * See the LICENSE file for redistribution information. 8b8ba871bSPeter Wemm */ 9b8ba871bSPeter Wemm 10b8ba871bSPeter Wemm #include "config.h" 11b8ba871bSPeter Wemm 12b8ba871bSPeter Wemm #ifndef lint 13f0957ccaSPeter Wemm static const char sccsid[] = "$Id: ex_init.c,v 10.33 2012/04/11 19:12:34 zy Exp $"; 14b8ba871bSPeter Wemm #endif /* not lint */ 15b8ba871bSPeter Wemm 16f0957ccaSPeter Wemm #include <sys/types.h> 17b8ba871bSPeter Wemm #include <sys/queue.h> 18b8ba871bSPeter Wemm #include <sys/stat.h> 19b8ba871bSPeter Wemm 20b8ba871bSPeter Wemm #include <bitstring.h> 21b8ba871bSPeter Wemm #include <fcntl.h> 22b8ba871bSPeter Wemm #include <limits.h> 23b8ba871bSPeter Wemm #include <stdio.h> 24b8ba871bSPeter Wemm #include <stdlib.h> 25b8ba871bSPeter Wemm #include <string.h> 26b8ba871bSPeter Wemm #include <unistd.h> 27b8ba871bSPeter Wemm 28b8ba871bSPeter Wemm #include "../common/common.h" 29b8ba871bSPeter Wemm #include "tag.h" 30b8ba871bSPeter Wemm #include "pathnames.h" 31b8ba871bSPeter Wemm 32b8ba871bSPeter Wemm enum rc { NOEXIST, NOPERM, RCOK }; 33*c271fa92SBaptiste Daroussin static enum rc exrc_isok(SCR *, struct stat *, char *, int, int); 34b8ba871bSPeter Wemm 35*c271fa92SBaptiste Daroussin static int ex_run_file(SCR *, char *); 36b8ba871bSPeter Wemm 37b8ba871bSPeter Wemm /* 38b8ba871bSPeter Wemm * ex_screen_copy -- 39b8ba871bSPeter Wemm * Copy ex screen. 40b8ba871bSPeter Wemm * 41*c271fa92SBaptiste Daroussin * PUBLIC: int ex_screen_copy(SCR *, SCR *); 42b8ba871bSPeter Wemm */ 43b8ba871bSPeter Wemm int 44f0957ccaSPeter Wemm ex_screen_copy(SCR *orig, SCR *sp) 45b8ba871bSPeter Wemm { 46b8ba871bSPeter Wemm EX_PRIVATE *oexp, *nexp; 47b8ba871bSPeter Wemm 48b8ba871bSPeter Wemm /* Create the private ex structure. */ 49b8ba871bSPeter Wemm CALLOC_RET(orig, nexp, EX_PRIVATE *, 1, sizeof(EX_PRIVATE)); 50b8ba871bSPeter Wemm sp->ex_private = nexp; 51b8ba871bSPeter Wemm 52b8ba871bSPeter Wemm /* Initialize queues. */ 53f0957ccaSPeter Wemm TAILQ_INIT(nexp->tq); 54f0957ccaSPeter Wemm TAILQ_INIT(nexp->tagfq); 55f0957ccaSPeter Wemm SLIST_INIT(nexp->cscq); 56b8ba871bSPeter Wemm 57b8ba871bSPeter Wemm if (orig == NULL) { 58b8ba871bSPeter Wemm } else { 59b8ba871bSPeter Wemm oexp = EXP(orig); 60b8ba871bSPeter Wemm 61b8ba871bSPeter Wemm if (oexp->lastbcomm != NULL && 62f0957ccaSPeter Wemm (nexp->lastbcomm = v_wstrdup(sp, oexp->lastbcomm, 63f0957ccaSPeter Wemm STRLEN(oexp->lastbcomm))) == NULL) { 64b8ba871bSPeter Wemm msgq(sp, M_SYSERR, NULL); 65b8ba871bSPeter Wemm return(1); 66b8ba871bSPeter Wemm } 67b8ba871bSPeter Wemm if (ex_tag_copy(orig, sp)) 68b8ba871bSPeter Wemm return (1); 69b8ba871bSPeter Wemm } 70b8ba871bSPeter Wemm return (0); 71b8ba871bSPeter Wemm } 72b8ba871bSPeter Wemm 73b8ba871bSPeter Wemm /* 74b8ba871bSPeter Wemm * ex_screen_end -- 75b8ba871bSPeter Wemm * End a vi screen. 76b8ba871bSPeter Wemm * 77*c271fa92SBaptiste Daroussin * PUBLIC: int ex_screen_end(SCR *); 78b8ba871bSPeter Wemm */ 79b8ba871bSPeter Wemm int 80f0957ccaSPeter Wemm ex_screen_end(SCR *sp) 81b8ba871bSPeter Wemm { 82b8ba871bSPeter Wemm EX_PRIVATE *exp; 83b8ba871bSPeter Wemm int rval; 84b8ba871bSPeter Wemm 85b8ba871bSPeter Wemm if ((exp = EXP(sp)) == NULL) 86b8ba871bSPeter Wemm return (0); 87b8ba871bSPeter Wemm 88b8ba871bSPeter Wemm rval = 0; 89b8ba871bSPeter Wemm 90b8ba871bSPeter Wemm /* Close down script connections. */ 91b8ba871bSPeter Wemm if (F_ISSET(sp, SC_SCRIPT) && sscr_end(sp)) 92b8ba871bSPeter Wemm rval = 1; 93b8ba871bSPeter Wemm 94b8ba871bSPeter Wemm if (argv_free(sp)) 95b8ba871bSPeter Wemm rval = 1; 96b8ba871bSPeter Wemm 97b8ba871bSPeter Wemm if (exp->ibp != NULL) 98b8ba871bSPeter Wemm free(exp->ibp); 99b8ba871bSPeter Wemm 100b8ba871bSPeter Wemm if (exp->lastbcomm != NULL) 101b8ba871bSPeter Wemm free(exp->lastbcomm); 102b8ba871bSPeter Wemm 103f0957ccaSPeter Wemm if (exp->ibcw.bp1.c != NULL) 104f0957ccaSPeter Wemm free(exp->ibcw.bp1.c); 105f0957ccaSPeter Wemm 106b8ba871bSPeter Wemm if (ex_tag_free(sp)) 107b8ba871bSPeter Wemm rval = 1; 108b8ba871bSPeter Wemm 109f0957ccaSPeter Wemm if (cscope_end(sp)) 110f0957ccaSPeter Wemm rval = 1; 111f0957ccaSPeter Wemm 112b8ba871bSPeter Wemm /* Free private memory. */ 113b8ba871bSPeter Wemm free(exp); 114b8ba871bSPeter Wemm sp->ex_private = NULL; 115b8ba871bSPeter Wemm 116b8ba871bSPeter Wemm return (rval); 117b8ba871bSPeter Wemm } 118b8ba871bSPeter Wemm 119b8ba871bSPeter Wemm /* 120b8ba871bSPeter Wemm * ex_optchange -- 121b8ba871bSPeter Wemm * Handle change of options for ex. 122b8ba871bSPeter Wemm * 123*c271fa92SBaptiste Daroussin * PUBLIC: int ex_optchange(SCR *, int, char *, u_long *); 124b8ba871bSPeter Wemm */ 125b8ba871bSPeter Wemm int 126f0957ccaSPeter Wemm ex_optchange(SCR *sp, int offset, char *str, u_long *valp) 127b8ba871bSPeter Wemm { 128b8ba871bSPeter Wemm switch (offset) { 129b8ba871bSPeter Wemm case O_TAGS: 130b8ba871bSPeter Wemm return (ex_tagf_alloc(sp, str)); 131b8ba871bSPeter Wemm } 132b8ba871bSPeter Wemm return (0); 133b8ba871bSPeter Wemm } 134b8ba871bSPeter Wemm 135b8ba871bSPeter Wemm /* 136b8ba871bSPeter Wemm * ex_exrc -- 137b8ba871bSPeter Wemm * Read the EXINIT environment variable and the startup exrc files, 138b8ba871bSPeter Wemm * and execute their commands. 139b8ba871bSPeter Wemm * 140*c271fa92SBaptiste Daroussin * PUBLIC: int ex_exrc(SCR *); 141b8ba871bSPeter Wemm */ 142b8ba871bSPeter Wemm int 143f0957ccaSPeter Wemm ex_exrc(SCR *sp) 144b8ba871bSPeter Wemm { 145b8ba871bSPeter Wemm struct stat hsb, lsb; 146f0957ccaSPeter Wemm char *p, *path; 147f0957ccaSPeter Wemm CHAR_T *wp; 148f0957ccaSPeter Wemm size_t wlen; 149b8ba871bSPeter Wemm 150b8ba871bSPeter Wemm /* 151b8ba871bSPeter Wemm * Source the system, environment, $HOME and local .exrc values. 152b8ba871bSPeter Wemm * Vi historically didn't check $HOME/.exrc if the environment 153b8ba871bSPeter Wemm * variable EXINIT was set. This is all done before the file is 154b8ba871bSPeter Wemm * read in, because things in the .exrc information can set, for 155b8ba871bSPeter Wemm * example, the recovery directory. 156b8ba871bSPeter Wemm * 157b8ba871bSPeter Wemm * !!! 158b8ba871bSPeter Wemm * While nvi can handle any of the options settings of historic vi, 159b8ba871bSPeter Wemm * the converse is not true. Since users are going to have to have 160b8ba871bSPeter Wemm * files and environmental variables that work with both, we use nvi 161b8ba871bSPeter Wemm * versions of both the $HOME and local startup files if they exist, 162b8ba871bSPeter Wemm * otherwise the historic ones. 163b8ba871bSPeter Wemm * 164b8ba871bSPeter Wemm * !!! 165b8ba871bSPeter Wemm * For a discussion of permissions and when what .exrc files are 166b8ba871bSPeter Wemm * read, see the comment above the exrc_isok() function below. 167b8ba871bSPeter Wemm * 168b8ba871bSPeter Wemm * !!! 169b8ba871bSPeter Wemm * If the user started the historic of vi in $HOME, vi read the user's 170b8ba871bSPeter Wemm * .exrc file twice, as $HOME/.exrc and as ./.exrc. We avoid this, as 171b8ba871bSPeter Wemm * it's going to make some commands behave oddly, and I can't imagine 172b8ba871bSPeter Wemm * anyone depending on it. 173b8ba871bSPeter Wemm */ 174b8ba871bSPeter Wemm switch (exrc_isok(sp, &hsb, _PATH_SYSEXRC, 1, 0)) { 175b8ba871bSPeter Wemm case NOEXIST: 176b8ba871bSPeter Wemm case NOPERM: 177b8ba871bSPeter Wemm break; 178b8ba871bSPeter Wemm case RCOK: 179b8ba871bSPeter Wemm if (ex_run_file(sp, _PATH_SYSEXRC)) 180b8ba871bSPeter Wemm return (1); 181b8ba871bSPeter Wemm break; 182b8ba871bSPeter Wemm } 183b8ba871bSPeter Wemm 184b8ba871bSPeter Wemm /* Run the commands. */ 185b8ba871bSPeter Wemm if (EXCMD_RUNNING(sp->gp)) 186b8ba871bSPeter Wemm (void)ex_cmd(sp); 187b8ba871bSPeter Wemm if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) 188b8ba871bSPeter Wemm return (0); 189b8ba871bSPeter Wemm 190b8ba871bSPeter Wemm if ((p = getenv("NEXINIT")) != NULL) { 191f0957ccaSPeter Wemm CHAR2INT(sp, p, strlen(p) + 1, wp, wlen); 192f0957ccaSPeter Wemm if (ex_run_str(sp, "NEXINIT", wp, wlen - 1, 1, 0)) 193b8ba871bSPeter Wemm return (1); 194b8ba871bSPeter Wemm } else if ((p = getenv("EXINIT")) != NULL) { 195f0957ccaSPeter Wemm CHAR2INT(sp, p, strlen(p) + 1, wp, wlen); 196f0957ccaSPeter Wemm if (ex_run_str(sp, "EXINIT", wp, wlen - 1, 1, 0)) 197b8ba871bSPeter Wemm return (1); 198b8ba871bSPeter Wemm } else if ((p = getenv("HOME")) != NULL && *p) { 199f0957ccaSPeter Wemm int st = 0; 200f0957ccaSPeter Wemm 201f0957ccaSPeter Wemm if ((path = join(p, _PATH_NEXRC)) == NULL) { 202f0957ccaSPeter Wemm msgq(sp, M_SYSERR, NULL); 203f0957ccaSPeter Wemm return (1); 204f0957ccaSPeter Wemm } 205b8ba871bSPeter Wemm switch (exrc_isok(sp, &hsb, path, 0, 1)) { 206b8ba871bSPeter Wemm case NOEXIST: 207f0957ccaSPeter Wemm free(path); 208f0957ccaSPeter Wemm if ((path = join(p, _PATH_EXRC)) == NULL) { 209f0957ccaSPeter Wemm msgq(sp, M_SYSERR, NULL); 210f0957ccaSPeter Wemm return (1); 211f0957ccaSPeter Wemm } 212b8ba871bSPeter Wemm if (exrc_isok(sp, 213b8ba871bSPeter Wemm &hsb, path, 0, 1) == RCOK && ex_run_file(sp, path)) 214f0957ccaSPeter Wemm st = 1; 215b8ba871bSPeter Wemm break; 216b8ba871bSPeter Wemm case NOPERM: 217b8ba871bSPeter Wemm break; 218b8ba871bSPeter Wemm case RCOK: 219b8ba871bSPeter Wemm if (ex_run_file(sp, path)) 220f0957ccaSPeter Wemm st = 1; 221b8ba871bSPeter Wemm break; 222b8ba871bSPeter Wemm } 223f0957ccaSPeter Wemm free(path); 224f0957ccaSPeter Wemm if (st) 225f0957ccaSPeter Wemm return st; 226b8ba871bSPeter Wemm } 227b8ba871bSPeter Wemm 228b8ba871bSPeter Wemm /* Run the commands. */ 229b8ba871bSPeter Wemm if (EXCMD_RUNNING(sp->gp)) 230b8ba871bSPeter Wemm (void)ex_cmd(sp); 231b8ba871bSPeter Wemm if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) 232b8ba871bSPeter Wemm return (0); 233b8ba871bSPeter Wemm 234b8ba871bSPeter Wemm /* Previous commands may have set the exrc option. */ 235b8ba871bSPeter Wemm if (O_ISSET(sp, O_EXRC)) { 236b8ba871bSPeter Wemm switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0, 0)) { 237b8ba871bSPeter Wemm case NOEXIST: 238b8ba871bSPeter Wemm if (exrc_isok(sp, &lsb, _PATH_EXRC, 0, 0) == RCOK && 239b8ba871bSPeter Wemm (lsb.st_dev != hsb.st_dev || 240b8ba871bSPeter Wemm lsb.st_ino != hsb.st_ino) && 241b8ba871bSPeter Wemm ex_run_file(sp, _PATH_EXRC)) 242b8ba871bSPeter Wemm return (1); 243b8ba871bSPeter Wemm break; 244b8ba871bSPeter Wemm case NOPERM: 245b8ba871bSPeter Wemm break; 246b8ba871bSPeter Wemm case RCOK: 247b8ba871bSPeter Wemm if ((lsb.st_dev != hsb.st_dev || 248b8ba871bSPeter Wemm lsb.st_ino != hsb.st_ino) && 249b8ba871bSPeter Wemm ex_run_file(sp, _PATH_NEXRC)) 250b8ba871bSPeter Wemm return (1); 251b8ba871bSPeter Wemm break; 252b8ba871bSPeter Wemm } 253b8ba871bSPeter Wemm /* Run the commands. */ 254b8ba871bSPeter Wemm if (EXCMD_RUNNING(sp->gp)) 255b8ba871bSPeter Wemm (void)ex_cmd(sp); 256b8ba871bSPeter Wemm if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) 257b8ba871bSPeter Wemm return (0); 258b8ba871bSPeter Wemm } 259b8ba871bSPeter Wemm 260b8ba871bSPeter Wemm return (0); 261b8ba871bSPeter Wemm } 262b8ba871bSPeter Wemm 263b8ba871bSPeter Wemm /* 264b8ba871bSPeter Wemm * ex_run_file -- 265b8ba871bSPeter Wemm * Set up a file of ex commands to run. 266b8ba871bSPeter Wemm */ 267b8ba871bSPeter Wemm static int 268f0957ccaSPeter Wemm ex_run_file(SCR *sp, char *name) 269b8ba871bSPeter Wemm { 270b8ba871bSPeter Wemm EXCMD cmd; 271f0957ccaSPeter Wemm CHAR_T *wp; 272f0957ccaSPeter Wemm size_t wlen; 273b8ba871bSPeter Wemm 274f0957ccaSPeter Wemm ex_cinit(sp, &cmd, C_SOURCE, 0, OOBLNO, OOBLNO, 0); 275f0957ccaSPeter Wemm CHAR2INT(sp, name, strlen(name)+1, wp, wlen); 276f0957ccaSPeter Wemm argv_exp0(sp, &cmd, wp, wlen - 1); 277b8ba871bSPeter Wemm return (ex_source(sp, &cmd)); 278b8ba871bSPeter Wemm } 279b8ba871bSPeter Wemm 280b8ba871bSPeter Wemm /* 281b8ba871bSPeter Wemm * ex_run_str -- 282b8ba871bSPeter Wemm * Set up a string of ex commands to run. 283b8ba871bSPeter Wemm * 284*c271fa92SBaptiste Daroussin * PUBLIC: int ex_run_str(SCR *, char *, CHAR_T *, size_t, int, int); 285b8ba871bSPeter Wemm */ 286b8ba871bSPeter Wemm int 287f0957ccaSPeter Wemm ex_run_str(SCR *sp, char *name, CHAR_T *str, size_t len, int ex_flags, int nocopy) 288b8ba871bSPeter Wemm { 289b8ba871bSPeter Wemm GS *gp; 290b8ba871bSPeter Wemm EXCMD *ecp; 291b8ba871bSPeter Wemm 292b8ba871bSPeter Wemm gp = sp->gp; 293b8ba871bSPeter Wemm if (EXCMD_RUNNING(gp)) { 294b8ba871bSPeter Wemm CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD)); 295f0957ccaSPeter Wemm SLIST_INSERT_HEAD(gp->ecq, ecp, q); 296b8ba871bSPeter Wemm } else 297b8ba871bSPeter Wemm ecp = &gp->excmd; 298b8ba871bSPeter Wemm 299b8ba871bSPeter Wemm F_INIT(ecp, 300b8ba871bSPeter Wemm ex_flags ? E_BLIGNORE | E_NOAUTO | E_NOPRDEF | E_VLITONLY : 0); 301b8ba871bSPeter Wemm 302b8ba871bSPeter Wemm if (nocopy) 303b8ba871bSPeter Wemm ecp->cp = str; 304b8ba871bSPeter Wemm else 305f0957ccaSPeter Wemm if ((ecp->cp = v_wstrdup(sp, str, len)) == NULL) 306b8ba871bSPeter Wemm return (1); 307b8ba871bSPeter Wemm ecp->clen = len; 308b8ba871bSPeter Wemm 309b8ba871bSPeter Wemm if (name == NULL) 310b8ba871bSPeter Wemm ecp->if_name = NULL; 311b8ba871bSPeter Wemm else { 312b8ba871bSPeter Wemm if ((ecp->if_name = v_strdup(sp, name, strlen(name))) == NULL) 313b8ba871bSPeter Wemm return (1); 314b8ba871bSPeter Wemm ecp->if_lno = 1; 315b8ba871bSPeter Wemm F_SET(ecp, E_NAMEDISCARD); 316b8ba871bSPeter Wemm } 317b8ba871bSPeter Wemm 318b8ba871bSPeter Wemm return (0); 319b8ba871bSPeter Wemm } 320b8ba871bSPeter Wemm 321b8ba871bSPeter Wemm /* 322b8ba871bSPeter Wemm * exrc_isok -- 323b8ba871bSPeter Wemm * Check a .exrc file for source-ability. 324b8ba871bSPeter Wemm * 325b8ba871bSPeter Wemm * !!! 326b8ba871bSPeter Wemm * Historically, vi read the $HOME and local .exrc files if they were owned 327b8ba871bSPeter Wemm * by the user's real ID, or the "sourceany" option was set, regardless of 328b8ba871bSPeter Wemm * any other considerations. We no longer support the sourceany option as 329b8ba871bSPeter Wemm * it's a security problem of mammoth proportions. We require the system 330b8ba871bSPeter Wemm * .exrc file to be owned by root, the $HOME .exrc file to be owned by the 331b8ba871bSPeter Wemm * user's effective ID (or that the user's effective ID be root) and the 332b8ba871bSPeter Wemm * local .exrc files to be owned by the user's effective ID. In all cases, 333b8ba871bSPeter Wemm * the file cannot be writeable by anyone other than its owner. 334b8ba871bSPeter Wemm * 335b8ba871bSPeter Wemm * In O'Reilly ("Learning the VI Editor", Fifth Ed., May 1992, page 106), 336b8ba871bSPeter Wemm * it notes that System V release 3.2 and later has an option "[no]exrc". 337b8ba871bSPeter Wemm * The behavior is that local .exrc files are read only if the exrc option 338b8ba871bSPeter Wemm * is set. The default for the exrc option was off, so, by default, local 339b8ba871bSPeter Wemm * .exrc files were not read. The problem this was intended to solve was 340b8ba871bSPeter Wemm * that System V permitted users to give away files, so there's no possible 341b8ba871bSPeter Wemm * ownership or writeability test to ensure that the file is safe. 342b8ba871bSPeter Wemm * 343b8ba871bSPeter Wemm * POSIX 1003.2-1992 standardized exrc as an option. It required the exrc 344b8ba871bSPeter Wemm * option to be off by default, thus local .exrc files are not to be read 345b8ba871bSPeter Wemm * by default. The Rationale noted (incorrectly) that this was a change 346b8ba871bSPeter Wemm * to historic practice, but correctly noted that a default of off improves 347b8ba871bSPeter Wemm * system security. POSIX also required that vi check the effective user 348b8ba871bSPeter Wemm * ID instead of the real user ID, which is why we've switched from historic 349b8ba871bSPeter Wemm * practice. 350b8ba871bSPeter Wemm * 351b8ba871bSPeter Wemm * We initialize the exrc variable to off. If it's turned on by the system 352b8ba871bSPeter Wemm * or $HOME .exrc files, and the local .exrc file passes the ownership and 353b8ba871bSPeter Wemm * writeability tests, then we read it. This breaks historic 4BSD practice, 354b8ba871bSPeter Wemm * but it gives us a measure of security on systems where users can give away 355b8ba871bSPeter Wemm * files. 356b8ba871bSPeter Wemm */ 357b8ba871bSPeter Wemm static enum rc 358f0957ccaSPeter Wemm exrc_isok(SCR *sp, struct stat *sbp, char *path, int rootown, int rootid) 359b8ba871bSPeter Wemm { 360b8ba871bSPeter Wemm enum { ROOTOWN, OWN, WRITER } etype; 361b8ba871bSPeter Wemm uid_t euid; 362b8ba871bSPeter Wemm int nf1, nf2; 363f0957ccaSPeter Wemm char *a, *b, *buf; 364b8ba871bSPeter Wemm 365b8ba871bSPeter Wemm /* Check for the file's existence. */ 366b8ba871bSPeter Wemm if (stat(path, sbp)) 367b8ba871bSPeter Wemm return (NOEXIST); 368b8ba871bSPeter Wemm 369b8ba871bSPeter Wemm /* Check ownership permissions. */ 370b8ba871bSPeter Wemm euid = geteuid(); 371b8ba871bSPeter Wemm if (!(rootown && sbp->st_uid == 0) && 372b8ba871bSPeter Wemm !(rootid && euid == 0) && sbp->st_uid != euid) { 373b8ba871bSPeter Wemm etype = rootown ? ROOTOWN : OWN; 374b8ba871bSPeter Wemm goto denied; 375b8ba871bSPeter Wemm } 376b8ba871bSPeter Wemm 377b8ba871bSPeter Wemm /* Check writeability. */ 378b8ba871bSPeter Wemm if (sbp->st_mode & (S_IWGRP | S_IWOTH)) { 379b8ba871bSPeter Wemm etype = WRITER; 380b8ba871bSPeter Wemm goto denied; 381b8ba871bSPeter Wemm } 382b8ba871bSPeter Wemm return (RCOK); 383b8ba871bSPeter Wemm 384b8ba871bSPeter Wemm denied: a = msg_print(sp, path, &nf1); 385f0957ccaSPeter Wemm if (strchr(path, '/') == NULL && (buf = getcwd(NULL, 0)) != NULL) { 386f0957ccaSPeter Wemm char *p; 387f0957ccaSPeter Wemm 388b8ba871bSPeter Wemm b = msg_print(sp, buf, &nf2); 389f0957ccaSPeter Wemm if ((p = join(b, a)) == NULL) { 390f0957ccaSPeter Wemm msgq(sp, M_SYSERR, NULL); 391f0957ccaSPeter Wemm goto err; 392f0957ccaSPeter Wemm } 393b8ba871bSPeter Wemm switch (etype) { 394b8ba871bSPeter Wemm case ROOTOWN: 395b8ba871bSPeter Wemm msgq(sp, M_ERR, 396f0957ccaSPeter Wemm "128|%s: not sourced: not owned by you or root", p); 397b8ba871bSPeter Wemm break; 398b8ba871bSPeter Wemm case OWN: 399b8ba871bSPeter Wemm msgq(sp, M_ERR, 400f0957ccaSPeter Wemm "129|%s: not sourced: not owned by you", p); 401b8ba871bSPeter Wemm break; 402b8ba871bSPeter Wemm case WRITER: 403b8ba871bSPeter Wemm msgq(sp, M_ERR, 404f0957ccaSPeter Wemm "130|%s: not sourced: writeable by a user other than the owner", p); 405b8ba871bSPeter Wemm break; 406b8ba871bSPeter Wemm } 407f0957ccaSPeter Wemm free(p); 408f0957ccaSPeter Wemm err: free(buf); 409b8ba871bSPeter Wemm if (nf2) 410b8ba871bSPeter Wemm FREE_SPACE(sp, b, 0); 411b8ba871bSPeter Wemm } else 412b8ba871bSPeter Wemm switch (etype) { 413b8ba871bSPeter Wemm case ROOTOWN: 414b8ba871bSPeter Wemm msgq(sp, M_ERR, 415b8ba871bSPeter Wemm "128|%s: not sourced: not owned by you or root", a); 416b8ba871bSPeter Wemm break; 417b8ba871bSPeter Wemm case OWN: 418b8ba871bSPeter Wemm msgq(sp, M_ERR, 419b8ba871bSPeter Wemm "129|%s: not sourced: not owned by you", a); 420b8ba871bSPeter Wemm break; 421b8ba871bSPeter Wemm case WRITER: 422b8ba871bSPeter Wemm msgq(sp, M_ERR, 423b8ba871bSPeter Wemm "130|%s: not sourced: writeable by a user other than the owner", a); 424b8ba871bSPeter Wemm break; 425b8ba871bSPeter Wemm } 426b8ba871bSPeter Wemm 427b8ba871bSPeter Wemm if (nf1) 428b8ba871bSPeter Wemm FREE_SPACE(sp, a, 0); 429b8ba871bSPeter Wemm return (NOPERM); 430b8ba871bSPeter Wemm } 431