diff options
Diffstat (limited to 'contrib/cvs/src/modules.c')
-rw-r--r-- | contrib/cvs/src/modules.c | 146 |
1 files changed, 77 insertions, 69 deletions
diff --git a/contrib/cvs/src/modules.c b/contrib/cvs/src/modules.c index b2ded8d..a784a86 100644 --- a/contrib/cvs/src/modules.c +++ b/contrib/cvs/src/modules.c @@ -3,7 +3,8 @@ * Copyright (c) 1989-1992, Brian Berliner * * You may distribute under the terms of the GNU General Public License - * as specified in the README file that comes with the CVS source distribution. + * as specified in the README file that comes with the CVS source + * distribution. * * Modules * @@ -30,7 +31,7 @@ /* Options in modules file. Note that it is OK to use GNU getopt features; we already are arranging to make sure we are using the getopt distributed with CVS. */ -#define CVSMODULE_OPTS "+ad:i:lo:e:s:t:u:" +#define CVSMODULE_OPTS "+ad:lo:e:s:t:" /* Special delimiter. */ #define CVSMODULE_SPEC '&' @@ -91,14 +92,17 @@ close_module (db) dbm_close (db); } + + /* * This is the recursive function that processes a module name. * It calls back the passed routine for each directory of a module * It runs the post checkout or post tag proc from the modules file */ -int -do_module (db, mname, m_type, msg, callback_proc, where, shorten, - local_specified, run_module_prog, build_dirs, extra_arg) +static int +my_module (db, mname, m_type, msg, callback_proc, where, shorten, + local_specified, run_module_prog, build_dirs, extra_arg, + stack) DBM *db; char *mname; enum mtype m_type; @@ -110,12 +114,11 @@ do_module (db, mname, m_type, msg, callback_proc, where, shorten, int run_module_prog; int build_dirs; char *extra_arg; + List *stack; { - char *checkin_prog = NULL; char *checkout_prog = NULL; char *export_prog = NULL; char *tag_prog = NULL; - char *update_prog = NULL; struct saved_cwd cwd; int cwd_saved = 0; char *line; @@ -150,7 +153,7 @@ do_module (db, mname, m_type, msg, callback_proc, where, shorten, + strlen (msg) + (where ? strlen (where) : 0) + (extra_arg ? strlen (extra_arg) : 0)); - sprintf (buf, "%s-> do_module (%s, %s, %s, %s)\n", + sprintf (buf, "%s-> my_module (%s, %s, %s, %s)\n", CLIENT_SERVER_STR, mname, msg, where ? where : "", extra_arg ? extra_arg : ""); @@ -170,6 +173,13 @@ do_module (db, mname, m_type, msg, callback_proc, where, shorten, if (isabsolute (mname)) error (1, 0, "Absolute module reference invalid: `%s'", mname); + /* Similarly for directories that attempt to step above the root of the + * repository. + */ + if (pathname_levels (mname) > 0) + error (1, 0, "up-level in module reference (`..') invalid: `%s'.", + mname); + /* if this is a directory to ignore, add it to that list */ if (mname[0] == '!' && mname[1] != '\0') { @@ -238,7 +248,8 @@ do_module (db, mname, m_type, msg, callback_proc, where, shorten, *acp = '/'; } else - (void) sprintf (attic_file, "%s/%s/%s%s", current_parsed_root->directory, + (void) sprintf (attic_file, "%s/%s/%s%s", + current_parsed_root->directory, CVSATTIC, mname, RCSEXT); if (isdir (file)) @@ -440,12 +451,6 @@ do_module (db, mname, m_type, msg, callback_proc, where, shorten, mwhere = xstrdup (optarg); nonalias_opt = 1; break; - case 'i': - if (checkin_prog) - free (checkin_prog); - checkin_prog = xstrdup (optarg); - nonalias_opt = 1; - break; case 'l': local_specified = 1; nonalias_opt = 1; @@ -468,12 +473,6 @@ do_module (db, mname, m_type, msg, callback_proc, where, shorten, tag_prog = xstrdup (optarg); nonalias_opt = 1; break; - case 'u': - if (update_prog) - free (update_prog); - update_prog = xstrdup (optarg); - nonalias_opt = 1; - break; case '?': error (0, 0, "modules file has invalid option for key %s value %s", @@ -510,14 +509,33 @@ do_module (db, mname, m_type, msg, callback_proc, where, shorten, for (i = 0; i < modargc; i++) { - if (strcmp (mname, modargv[i]) == 0) + /* + * Recursion check: if an alias module calls itself or a module + * which causes the first to be called again, print an error + * message and stop recursing. + * + * Algorithm: + * + * 1. Check that MNAME isn't in the stack. + * 2. Push MNAME onto the stack. + * 3. Call do_module(). + * 4. Pop MNAME from the stack. + */ + if (stack && findnode (stack, mname)) error (0, 0, "module `%s' in modules file contains infinite loop", mname); else - err += do_module (db, modargv[i], m_type, msg, callback_proc, - where, shorten, local_specified, - run_module_prog, build_dirs, extra_arg); + { + if (!stack) stack = getlist(); + push_string (stack, mname); + err += my_module (db, modargv[i], m_type, msg, callback_proc, + where, shorten, local_specified, + run_module_prog, build_dirs, extra_arg, + stack); + pop_string (stack); + if (isempty (stack)) dellist (&stack); + } } goto do_module_return; } @@ -552,7 +570,7 @@ module `%s' is a request for a file in a module which is not a directory", /* XXX - think about making null repositories at each dir here instead of just at the bottom */ make_directories (dir); - if ( CVS_CHDIR (dir) < 0) + if (CVS_CHDIR (dir) < 0) { error (0, errno, "cannot chdir to %s", dir); spec_opt = NULL; @@ -654,9 +672,10 @@ module `%s' is a request for a file in a module which is not a directory", error (0, 0, "Mal-formed %c option for module %s - ignored", CVSMODULE_SPEC, mname); else - err += do_module (db, spec_opt, m_type, msg, callback_proc, - (char *) NULL, 0, local_specified, - run_module_prog, build_dirs, extra_arg); + err += my_module (db, spec_opt, m_type, msg, callback_proc, + (char *) NULL, 0, local_specified, + run_module_prog, build_dirs, extra_arg, + stack); spec_opt = next_opt; } @@ -668,40 +687,6 @@ module `%s' is a request for a file in a module which is not a directory", } #endif - /* run/write out the checkin/update prog files if necessary */ - if (err == 0 && !noexec && m_type == CHECKOUT && run_module_prog) - { -#ifdef SERVER_SUPPORT - if (server_active) { - if (checkin_prog != NULL) - server_prog (where ? where : mwhere ? mwhere : mname, checkin_prog, PROG_CHECKIN); - if (update_prog != NULL) - server_prog (where ? where : mwhere ? mwhere : mname, update_prog, PROG_UPDATE); - } - else - { -#endif - FILE *fp; - - if (checkin_prog != NULL) - { - fp = open_file (CVSADM_CIPROG, "w+"); - (void) fprintf (fp, "%s\n", checkin_prog); - if (fclose (fp) == EOF) - error (1, errno, "cannot close %s", CVSADM_CIPROG); - } - if (update_prog != NULL) - { - fp = open_file (CVSADM_UPROG, "w+"); - (void) fprintf (fp, "%s\n", update_prog); - if (fclose (fp) == EOF) - error (1, errno, "cannot close %s", CVSADM_UPROG); - } -#ifdef SERVER_SUPPORT - } -#endif - } - /* cd back to where we started */ if (restore_cwd (&cwd, NULL)) error_exit (); @@ -750,7 +735,7 @@ module `%s' is a request for a file in a module which is not a directory", { cvs_output (program_name, 0); cvs_output (" ", 1); - cvs_output (command_name, 0); + cvs_output (cvs_cmd_name, 0); cvs_output (": Executing '", 0); run_print (stdout); cvs_output ("'\n", 0); @@ -769,16 +754,12 @@ module `%s' is a request for a file in a module which is not a directory", free_names (&xmodargc, xmodargv); if (mwhere) free (mwhere); - if (checkin_prog) - free (checkin_prog); if (checkout_prog) free (checkout_prog); if (export_prog) free (export_prog); if (tag_prog) free (tag_prog); - if (update_prog) - free (update_prog); if (cwd_saved) free_cwd (&cwd); if (value != NULL) @@ -789,6 +770,33 @@ module `%s' is a request for a file in a module which is not a directory", return (err); } + + +/* External face of do_module so that we can have an internal version which + * accepts a stack argument to track alias recursion. + */ +int +do_module (db, mname, m_type, msg, callback_proc, where, shorten, + local_specified, run_module_prog, build_dirs, extra_arg) + DBM *db; + char *mname; + enum mtype m_type; + char *msg; + CALLBACKPROC callback_proc; + char *where; + int shorten; + int local_specified; + int run_module_prog; + int build_dirs; + char *extra_arg; +{ + return my_module (db, mname, m_type, msg, callback_proc, where, shorten, + local_specified, run_module_prog, build_dirs, extra_arg, + NULL); +} + + + /* - Read all the records from the modules database into an array. - Sort the array depending on what format is desired. - Print the array in the format desired. @@ -799,7 +807,7 @@ module `%s' is a request for a file in a module which is not a directory", files and the comment field: (Including aliases) modulename -s switches, one per line, even if - -i it has many switches. + it has many switches. Directories and files involved, formatted to cover multiple lines if necessary. # Comment, also formatted to cover multiple |