예제 #1
0
/*
 * Call any postadmin procs.
 */
static int
admin_filesdoneproc (void *callerdat, int err, const char *repository,
                     const char *update_dir, List *entries)
{
    TRACE (TRACE_FUNCTION, "admin_filesdoneproc (%d, %s, %s)", err, repository,
           update_dir);
    Parse_Info (CVSROOTADM_POSTADMIN, repository, postadmin_proc, PIOPT_ALL,
                NULL);

    return err;
}
예제 #2
0
파일: logmsg.c 프로젝트: ryo/netbsd-src
/* Runs the user-defined verification script as part of the commit or import
   process.  This verification is meant to be run whether or not the user
   included the -m attribute.  unlike the do_editor function, this is
   independant of the running of an editor for getting a message.
 */
void
do_verify (char **messagep, const char *repository, List *changes)
{
    int err;
    struct verifymsg_proc_data data;
    struct stat post_stbuf;

    if (current_parsed_root->isremote)
        /* The verification will happen on the server.  */
        return;

    /* FIXME? Do we really want to skip this on noexec?  What do we do
       for the other administrative files?  */
    /* EXPLAIN: Why do we check for repository == NULL here? */
    if (noexec || repository == NULL)
        return;

    /* Get the name of the verification script to run  */

    data.message = *messagep;
    data.fname = NULL;
    data.changes = changes;
    if ((err = Parse_Info (CVSROOTADM_VERIFYMSG, repository,
                           verifymsg_proc, 0, &data)) != 0)
    {
        int saved_errno = errno;
        /* Since following error() exits, delete the temp file now.  */
        if (data.fname != NULL && unlink_file( data.fname ) < 0)
            error (0, errno, "cannot remove %s", data.fname);
        free (data.fname);

        errno = saved_errno;
        error (1, err == -1 ? errno : 0, "Message verification failed");
    }

    /* Return if no temp file was created.  That means that we didn't call any
     * verifymsg scripts.
     */
    if (data.fname == NULL)
        return;

    /* Get the mod time and size of the possibly new log message
     * in always and stat modes.
     */
    if (config->RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
            config->RereadLogAfterVerify == LOGMSG_REREAD_STAT)
    {
        if(stat (data.fname, &post_stbuf) != 0)
            error (1, errno, "cannot find size of temp file %s", data.fname);
    }

    /* And reread the log message in `always' mode or in `stat' mode when it's
     * changed.
     */
    if (config->RereadLogAfterVerify == LOGMSG_REREAD_ALWAYS ||
            (config->RereadLogAfterVerify == LOGMSG_REREAD_STAT &&
             (data.pre_stbuf.st_mtime != post_stbuf.st_mtime ||
              data.pre_stbuf.st_size != post_stbuf.st_size)))
    {
        /* put the entire message back into the *messagep variable */

        if (*messagep) free (*messagep);

        if (post_stbuf.st_size == 0)
            *messagep = NULL;
        else
        {
            char *line = NULL;
            int line_length;
            size_t line_chars_allocated = 0;
            char *p;
            FILE *fp;

            fp = xfopen (data.fname, "r");

            /* On NT, we might read less than st_size bytes,
               but we won't read more.  So this works.  */
            p = *messagep = (char *) xmalloc (post_stbuf.st_size + 1);
            *messagep[0] = '\0';

            for (;;)
            {
                line_length = getline( &line,
                                       &line_chars_allocated,
                                       fp);
                if (line_length == -1)
                {
                    if (ferror (fp))
                        /* Fail in this case because otherwise we will have no
                         * log message
                         */
                        error (1, errno, "cannot read %s", data.fname);
                    break;
                }
                if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
                    continue;
                (void) strcpy (p, line);
                p += line_length;
            }
            if (line) free (line);
            if (fclose (fp) < 0)
                error (0, errno, "warning: cannot close %s", data.fname);
        }
    }
    /* Delete the temp file  */
    if (unlink_file (data.fname) < 0)
        error (0, errno, "cannot remove `%s'", data.fname);
    free (data.fname);
}
예제 #3
0
파일: logmsg.c 프로젝트: ryo/netbsd-src
/*
 * Builds a temporary file using setup_tmpfile() and invokes the user's
 * editor on the file.  The header garbage in the resultant file is then
 * stripped and the log message is stored in the "message" argument.
 *
 * If REPOSITORY is non-NULL, process rcsinfo for that repository; if it
 * is NULL, use the CVSADM_TEMPLATE file instead.  REPOSITORY should be
 * NULL when running in client mode.
 *
 * GLOBALS
 *   Editor     Set to a default value by configure and overridable using the
 *              -e option to the CVS executable.
 */
void
do_editor (const char *dir, char **messagep, const char *repository,
           List *changes)
{
    static int reuse_log_message = 0;
    char *line;
    int line_length;
    size_t line_chars_allocated;
    char *fname;
    struct stat pre_stbuf, post_stbuf;
    int retcode = 0;

    assert (!current_parsed_root->isremote != !repository);

    if (noexec || reuse_log_message)
        return;

    /* Abort before creation of the temp file if no editor is defined. */
    if (strcmp (Editor, "") == 0)
        error(1, 0, "no editor defined, must use -e or -m");

again:
    /* Create a temporary file.  */
    if( ( fp = cvs_temp_file( &fname ) ) == NULL )
        error( 1, errno, "cannot create temporary file" );

    if (*messagep)
    {
        (void) fputs (*messagep, fp);

        if ((*messagep)[0] == '\0' ||
                (*messagep)[strlen (*messagep) - 1] != '\n')
            (void) fprintf (fp, "\n");
    }
    else
        (void) fprintf (fp, "\n");

    if (repository != NULL)
        /* tack templates on if necessary */
        (void) Parse_Info (CVSROOTADM_RCSINFO, repository, rcsinfo_proc,
                           PIOPT_ALL, NULL);
    else
    {
        FILE *tfp;
        char buf[1024];
        size_t n;
        size_t nwrite;

        /* Why "b"?  */
        tfp = CVS_FOPEN (CVSADM_TEMPLATE, "rb");
        if (tfp == NULL)
        {
            if (!existence_error (errno))
                error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
        }
        else
        {
            while (!feof (tfp))
            {
                char *p = buf;
                n = fread (buf, 1, sizeof buf, tfp);
                nwrite = n;
                while (nwrite > 0)
                {
                    n = fwrite (p, 1, nwrite, fp);
                    nwrite -= n;
                    p += n;
                }
                if (ferror (tfp))
                    error (1, errno, "cannot read %s", CVSADM_TEMPLATE);
            }
            if (fclose (tfp) < 0)
                error (0, errno, "cannot close %s", CVSADM_TEMPLATE);
        }
    }

    (void) fprintf (fp,
                    "%s----------------------------------------------------------------------\n",
                    CVSEDITPREFIX);
    (void) fprintf (fp,
                    "%sEnter Log.  Lines beginning with `%.*s' are removed automatically\n%s\n",
                    CVSEDITPREFIX, CVSEDITPREFIXLEN, CVSEDITPREFIX,
                    CVSEDITPREFIX);
    if (dir != NULL && *dir)
        (void) fprintf (fp, "%sCommitting in %s\n%s\n", CVSEDITPREFIX,
                        dir, CVSEDITPREFIX);
    if (changes != NULL)
        setup_tmpfile (fp, CVSEDITPREFIX, changes);
    (void) fprintf (fp,
                    "%s----------------------------------------------------------------------\n",
                    CVSEDITPREFIX);

    /* finish off the temp file */
    if (fclose (fp) == EOF)
        error (1, errno, "%s", fname);
    if (stat (fname, &pre_stbuf) == -1)
        pre_stbuf.st_mtime = 0;

    /* run the editor */
    run_setup (Editor);
    run_add_arg (fname);
    if ((retcode = run_exec (RUN_TTY, RUN_TTY, RUN_TTY,
                             RUN_NORMAL | RUN_SIGIGNORE | RUN_UNSETXID)) != 0)
        error (0, retcode == -1 ? errno : 0, "warning: editor session failed");

    /* put the entire message back into the *messagep variable */

    fp = xfopen (fname, "r");

    if (*messagep)
        free (*messagep);

    if (stat (fname, &post_stbuf) != 0)
        error (1, errno, "cannot find size of temp file %s", fname);

    if (post_stbuf.st_size == 0)
        *messagep = NULL;
    else
    {
        /* On NT, we might read less than st_size bytes, but we won't
           read more.  So this works.  */
        *messagep = (char *) xmalloc (post_stbuf.st_size + 1);
        (*messagep)[0] = '\0';
    }

    line = NULL;
    line_chars_allocated = 0;

    if (*messagep)
    {
        size_t message_len = post_stbuf.st_size + 1;
        size_t offset = 0;
        while (1)
        {
            line_length = getline (&line, &line_chars_allocated, fp);
            if (line_length == -1)
            {
                if (ferror (fp))
                    error (0, errno, "warning: cannot read %s", fname);
                break;
            }
            if (strncmp (line, CVSEDITPREFIX, CVSEDITPREFIXLEN) == 0)
                continue;
            if (offset + line_length >= message_len)
                expand_string (messagep, &message_len,
                               offset + line_length + 1);
            (void) strcpy (*messagep + offset, line);
            offset += line_length;
        }
    }
    if (fclose (fp) < 0)
        error (0, errno, "warning: cannot close %s", fname);

    /* canonicalize emply messages */
    if (*messagep != NULL &&
            (**messagep == '\0' || strcmp (*messagep, "\n") == 0))
    {
        free (*messagep);
        *messagep = NULL;
    }

    if (pre_stbuf.st_mtime == post_stbuf.st_mtime || *messagep == NULL)
    {
        for (;;)
        {
            (void) printf ("\nLog message unchanged or not specified\n");
            (void) printf ("a)bort, c)ontinue, e)dit, !)reuse this message unchanged for remaining dirs\n");
            (void) printf ("Action: (abort) ");
            (void) fflush (stdout);
            line_length = getline (&line, &line_chars_allocated, stdin);
            if (line_length < 0)
            {
                error (0, errno, "cannot read from stdin");
                if (unlink_file (fname) < 0)
                    error (0, errno,
                           "warning: cannot remove temp file %s", fname);
                error (1, 0, "aborting");
            }
            else if (line_length == 0
                     || *line == '\n' || *line == 'a' || *line == 'A')
            {
                if (unlink_file (fname) < 0)
                    error (0, errno, "warning: cannot remove temp file %s", fname);
                error (1, 0, "aborted by user");
            }
            if (*line == 'c' || *line == 'C')
                break;
            if (*line == 'e' || *line == 'E')
                goto again;
            if (*line == '!')
            {
                reuse_log_message = 1;
                break;
            }
            (void) printf ("Unknown input\n");
        }
    }
    if (line)
        free (line);
    if (unlink_file (fname) < 0)
        error (0, errno, "warning: cannot remove temp file %s", fname);
    free (fname);
}