home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / EDITOR / NVI179B / NVI179B.ZIP / ex / ex_init.c < prev    next >
C/C++ Source or Header  |  1997-06-20  |  11KB  |  429 lines

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