? enh-reservations.diff
? src/edit.c-0
? vms/Makefile
Index: src/ChangeLog
===================================================================
RCS file: /home/nyap/.cvsroot/cvs/src/ChangeLog,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -C16 -w -r1.1.1.1 -r1.1.1.1.2.1
*** src/ChangeLog	2001/03/06 16:21:21	1.1.1.1
--- src/ChangeLog	2001/03/07 23:01:32	1.1.1.1.2.1
***************
*** 1,16 ****
--- 1,27 ----
+ 2001-03-07  Noel Yap <yap_noel@yahoo.com>
+ 
+ 	* client.c (to_server_buffer_flush, from_server_buffer_read): created
+ 	functions.
+ 
+ 	* commit.c (commit, check_fileproc): "-c" option added to check for valid
+ 	edit.
+ 
+ 	* edit.c (editors_output, check_fileproc, check_edits, edit): "-c" option
+ 	added to check for existing editors.  "-f" option added to force edit.
+ 
  2000-09-19  Larry Jones  <larry.jones@sdrc.com>
  
  	* version.c: Version 1.11.
  
  2000-09-07  Larry Jones  <larry.jones@sdrc.com>
  
  	* Makefile.in: Use @bindir@, @libdir@, @infodir@, and @mandir@
  	from autoconf.
  
  2000-08-23  Larry Jones  <larry.jones@sdrc.com>
  
  	* mkmodules.c (init): Create an empty val-tags file if it doesn't
  	already exist to avoid problems with users not having sufficient
  	permissions to create it later.
  
  2000-09-06  Jim Kingdon  <jkingdon@dhcp-net200-89.su.valinux.com>
Index: src/client.c
===================================================================
RCS file: /home/nyap/.cvsroot/cvs/src/client.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -C16 -w -r1.1.1.1 -r1.1.1.1.2.1
*** src/client.c	2001/03/06 16:21:21	1.1.1.1
--- src/client.c	2001/03/07 23:01:32	1.1.1.1.2.1
***************
*** 5821,5839 ****
--- 5821,5853 ----
  client_senddate (date)
      const char *date;
  {
      char buf[MAXDATELEN];
  
      date_to_internet (buf, (char *)date);
      option_with_arg ("-D", buf);
  }
  
  void
  send_init_command ()
  {
      /* This is here because we need the CVSroot_directory variable.  */
      send_to_server ("init ", 0);
      send_to_server (CVSroot_directory, 0);
      send_to_server ("\012", 0);
+ }
+ 
+ void
+ to_server_buffer_flush (void)
+ {
+     buf_flush (to_server, 1);
+ }
+ 
+ void
+ from_server_buffer_read (line, lenp)
+     char **line;
+     int *lenp;
+ {
+     buf_read_line (from_server, line, lenp);
  }
  
  #endif /* CLIENT_SUPPORT */
Index: src/client.h
===================================================================
RCS file: /home/nyap/.cvsroot/cvs/src/client.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -C16 -w -r1.1.1.1 -r1.1.1.1.2.1
*** src/client.h	2001/03/06 16:21:21	1.1.1.1
--- src/client.h	2001/03/07 23:01:32	1.1.1.1.2.1
***************
*** 185,201 ****
--- 185,204 ----
  extern void client_send_expansions PROTO((int local, char *where,
  					  int build_dirs));
  extern void client_nonexpanded_setup PROTO((void));
  
  extern void send_init_command PROTO ((void));
  
  extern char **failed_patches;
  extern int failed_patches_count;
  extern char *toplevel_wd;
  extern void client_import_setup PROTO((char *repository));
  extern int client_process_import_file
      PROTO((char *message, char *vfile, char *vtag,
  	   int targc, char *targv[], char *repository, int all_files_binary,
  	   int modtime));
  extern void client_import_done PROTO((void));
  extern void client_notify PROTO((char *, char *, char *, int, char *));
+ 
+ extern void from_server_buffer_read PROTO((char **, int *));
+ extern void to_server_buffer_flush PROTO((void));
  #endif /* CLIENT_SUPPORT */
Index: src/commit.c
===================================================================
RCS file: /home/nyap/.cvsroot/cvs/src/commit.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -C16 -w -r1.1.1.1 -r1.1.1.1.2.1
*** src/commit.c	2001/03/06 16:21:21	1.1.1.1
--- src/commit.c	2001/03/07 23:01:33	1.1.1.1.2.1
***************
*** 56,103 ****
  static void masterlist_delproc PROTO((Node *p));
  static char *locate_rcs PROTO((char *file, char *repository));
  
  struct commit_info
  {
      Ctype status;			/* as returned from Classify_File() */
      char *rev;				/* a numeric rev, if we know it */
      char *tag;				/* any sticky tag, or -r option */
      char *options;			/* Any sticky -k option */
  };
  struct master_lists
  {
      List *ulist;			/* list for Update_Logfile */
      List *cilist;			/* list with commit_info structs */
  };
  
  static int force_ci = 0;
  static int got_message;
  static int run_module_prog = 1;
  static int aflag;
  static char *saved_tag;
  static char *write_dirtag;
  static int write_dirnonbranch;
  static char *logfile;
  static List *mulist;
  static List *saved_ulist;
  static char *saved_message;
  static time_t last_register_time;
  
  static const char *const commit_usage[] =
  {
!     "Usage: %s %s [-nRlf] [-m msg | -F logfile] [-r rev] files...\n",
      "\t-n\tDo not run the module program (if any).\n",
      "\t-R\tProcess directories recursively.\n",
      "\t-l\tLocal directory only (not recursive).\n",
      "\t-f\tForce the file to be committed; disables recursion.\n",
      "\t-F file\tRead the log message from file.\n",
      "\t-m msg\tLog message.\n",
      "\t-r rev\tCommit to this branch or trunk revision.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
  
  #ifdef CLIENT_SUPPORT
  /* Identify a file which needs "? foo" or a Questionable request.  */
  struct question {
      /* The two fields for the Directory request.  */
      char *dir;
--- 56,105 ----
  static void masterlist_delproc PROTO((Node *p));
  static char *locate_rcs PROTO((char *file, char *repository));
  
  struct commit_info
  {
      Ctype status;			/* as returned from Classify_File() */
      char *rev;				/* a numeric rev, if we know it */
      char *tag;				/* any sticky tag, or -r option */
      char *options;			/* Any sticky -k option */
  };
  struct master_lists
  {
      List *ulist;			/* list for Update_Logfile */
      List *cilist;			/* list with commit_info structs */
  };
  
+ static int check_valid_edit = 0;
  static int force_ci = 0;
  static int got_message;
  static int run_module_prog = 1;
  static int aflag;
  static char *saved_tag;
  static char *write_dirtag;
  static int write_dirnonbranch;
  static char *logfile;
  static List *mulist;
  static List *saved_ulist;
  static char *saved_message;
  static time_t last_register_time;
  
  static const char *const commit_usage[] =
  {
!     "Usage: %s %s [-cnRlf] [-m msg | -F logfile] [-r rev] files...\n",
!     "\t-c\tCheck for valid edits before committing.\n",
      "\t-n\tDo not run the module program (if any).\n",
      "\t-R\tProcess directories recursively.\n",
      "\t-l\tLocal directory only (not recursive).\n",
      "\t-f\tForce the file to be committed; disables recursion.\n",
      "\t-F file\tRead the log message from file.\n",
      "\t-m msg\tLog message.\n",
      "\t-r rev\tCommit to this branch or trunk revision.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
  
  #ifdef CLIENT_SUPPORT
  /* Identify a file which needs "? foo" or a Questionable request.  */
  struct question {
      /* The two fields for the Directory request.  */
      char *dir;
***************
*** 345,410 ****
  #  ifdef CLIENT_SUPPORT
  	/* Who we are on the client side doesn't affect logging.  */
  	&& !client_active
  #  endif
  	)
      {
  	struct passwd *pw;
  
  	if ((pw = (struct passwd *) getpwnam (getcaller ())) == NULL)
  	    error (1, 0, "you are unknown to this system");
  	if (pw->pw_uid == (uid_t) 0)
  	    error (1, 0, "cannot commit files as 'root'");
      }
  #endif /* CVS_BADROOT */
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+nlRm:fF:r:")) != -1)
      {
  	switch (c)
  	{
  	    case 'n':
  		run_module_prog = 0;
  		break;
  	    case 'm':
  #ifdef FORCE_USE_EDITOR
  		use_editor = 1;
  #else
  		use_editor = 0;
  #endif
  		if (saved_message)
  		{
  		    free (saved_message);
  		    saved_message = NULL;
  		}
  
  		saved_message = xstrdup(optarg);
  		break;
  	    case 'r':
  		if (saved_tag)
  		    free (saved_tag);
  		saved_tag = xstrdup (optarg);
  		break;
  	    case 'l':
  		local = 1;
  		break;
  	    case 'R':
  		local = 0;
  		break;
  	    case 'f':
  		force_ci = 1;
  		local = 1;		/* also disable recursion */
  		break;
  	    case 'F':
  #ifdef FORCE_USE_EDITOR
  		use_editor = 1;
  #else
  		use_editor = 0;
  #endif
  		logfile = optarg;
  		break;
  	    case '?':
  	    default:
  		usage (commit_usage);
  		break;
  	}
      }
--- 347,416 ----
  #  ifdef CLIENT_SUPPORT
  	/* Who we are on the client side doesn't affect logging.  */
  	&& !client_active
  #  endif
  	)
      {
  	struct passwd *pw;
  
  	if ((pw = (struct passwd *) getpwnam (getcaller ())) == NULL)
  	    error (1, 0, "you are unknown to this system");
  	if (pw->pw_uid == (uid_t) 0)
  	    error (1, 0, "cannot commit files as 'root'");
      }
  #endif /* CVS_BADROOT */
  
      optind = 0;
!     while ((c = getopt (argc, argv, "+cnlRm:fF:r:")) != -1)
      {
  	switch (c)
  	{
+             case 'c':
+                 check_valid_edit = 1;
+                 break;
  	    case 'n':
  		run_module_prog = 0;
  		break;
  	    case 'm':
  #ifdef FORCE_USE_EDITOR
  		use_editor = 1;
  #else
  		use_editor = 0;
  #endif
  		if (saved_message)
  		{
  		    free (saved_message);
  		    saved_message = NULL;
  		}
  
  		saved_message = xstrdup(optarg);
  		break;
  	    case 'r':
  		if (saved_tag)
  		    free (saved_tag);
  		saved_tag = xstrdup (optarg);
  		break;
  	    case 'l':
  		local = 1;
  		break;
  	    case 'R':
  		local = 0;
  		break;
  	    case 'f':
  		force_ci = 1;
+                 check_valid_edit = 0;
  		local = 1;		/* also disable recursion */
  		break;
  	    case 'F':
  #ifdef FORCE_USE_EDITOR
  		use_editor = 1;
  #else
  		use_editor = 0;
  #endif
  		logfile = optarg;
  		break;
  	    case '?':
  	    default:
  		usage (commit_usage);
  		break;
  	}
      }
***************
*** 535,566 ****
--- 541,574 ----
  
  		    send_to_server ("Questionable ", 0);
  		    send_to_server (p->file, 0);
  		    send_to_server ("\012", 1);
  		}
  		free (p->dir);
  		free (p->repos);
  		free (p->file);
  		q = p->next;
  		free (p);
  		p = q;
  	    }
  	}
  
  	if (local)
  	    send_arg("-l");
+         if (check_valid_edit)
+             send_arg("-c");
  	if (force_ci)
  	    send_arg("-f");
  	if (!run_module_prog)
  	    send_arg("-n");
  	option_with_arg ("-r", saved_tag);
  
  	/* FIXME: This whole find_args.force/SEND_FORCE business is a
  	   kludge.  It would seem to be a server bug that we have to
  	   say that files are modified when they are not.  This makes
  	   "cvs commit -r 2" across a whole bunch of files a very slow
  	   operation (and it isn't documented in cvsclient.texi).  I
  	   haven't looked at the server code carefully enough to be
  	   _sure_ why this is needed, but if it is because the "ci"
  	   program, which we used to call, wanted the file to exist,
  	   then it would be relatively simple to fix in the server.  */
  	send_files (find_args.argc, find_args.argv, local, 0,
***************
*** 809,840 ****
--- 817,851 ----
  
      switch (status)
      {
  	case T_CHECKOUT:
  #ifdef SERVER_SUPPORT
  	case T_PATCH:
  #endif
  	case T_NEEDS_MERGE:
  	case T_CONFLICT:
  	case T_REMOVE_ENTRY:
  	    error (0, 0, "Up-to-date check failed for `%s'", finfo->fullname);
  	    freevers_ts (&vers);
  	    return (1);
  	case T_MODIFIED:
  	case T_ADDED:
  	case T_REMOVED:
+         {
+             char *editor = NULL;
+ 
  	    /*
  	     * some quick sanity checks; if no numeric -r option specified:
  	     *	- can't have a sticky date
  	     *	- can't have a sticky tag that is not a branch
  	     * Also,
  	     *	- if status is T_REMOVED, can't have a numeric tag
  	     *	- if status is T_ADDED, rcs file must not exist unless on
  	     *    a branch
  	     *	- if status is T_ADDED, can't have a non-trunk numeric rev
  	     *	- if status is T_MODIFIED and a Conflict marker exists, don't
  	     *    allow the commit if timestamp is identical or if we find
  	     *    an RCS_MERGE_PAT in the file.
  	     */
  	    if (!saved_tag || !isdigit ((unsigned char) *saved_tag))
  	    {
  		if (vers->date)
***************
*** 982,1013 ****
--- 993,1074 ----
  		    xmalloc (sizeof (struct master_lists));
  		ml->ulist = ulist;
  		ml->cilist = cilist;
  		p->data = (char *) ml;
  		p->delproc = masterlist_delproc;
  		(void) addnode (mulist, p);
  	    }
  
  	    /* first do ulist, then cilist */
  	    p = getnode ();
  	    p->key = xstrdup (finfo->file);
  	    p->type = UPDATE;
  	    p->delproc = update_delproc;
  	    li = ((struct logfile_info *)
  		  xmalloc (sizeof (struct logfile_info)));
  	    li->type = status;
+ 
+             {
+                 char *editors = NULL;
+ 
+                 editors = fileattr_get0 (finfo->file, "_editors");
+                 if (editors != NULL)
+                 {
+                     char *caller = getcaller ();
+                     char *p = NULL;
+                     char *p0 = NULL;
+ 
+                     p = editors;
+                     p0 = p;
+                     while (*p != '\0')
+                     {
+                         p = strchr (p, '>');
+                         if (p == NULL)
+                         {
+                             break;
+                         }
+                         *p = '\0';
+                         if (strcmp (caller, p0) == 0)
+                         {
+                             break;
+                         }
+                         p = strchr (p + 1, ',');
+                         if (p == NULL)
+                         {
+                             break;
+                         }
+                         ++p;
+                         p0 = p;
+                     }
+ 
+                     if (strcmp (caller, p0) == 0)
+                     {
+                         editor = caller;
+                     }
+ 
+                     free (editors);
+                 }
+             }
+ 
+             if (check_valid_edit && editor == NULL)
+             {
+                 error (0, 0, "Valid edit does not exist for %s", finfo->fullname);
+                 freevers_ts (&vers);
+                 return 1;
+             }
+ 
  	    li->tag = xstrdup (vers->tag);
  	    li->rev_old = xstrdup (vers->vn_rcs);
  	    li->rev_new = NULL;
  	    p->data = (char *) li;
  	    (void) addnode (ulist, p);
  
  	    p = getnode ();
  	    p->key = xstrdup (finfo->file);
  	    p->type = UPDATE;
  	    p->delproc = ci_delproc;
  	    ci = (struct commit_info *) xmalloc (sizeof (struct commit_info));
  	    ci->status = status;
  	    if (vers->tag)
  		if (isdigit ((unsigned char) *vers->tag))
  		    ci->rev = xstrdup (vers->tag);
  		else
***************
*** 1042,1073 ****
--- 1103,1136 ----
  		   we're doing a remove operation? */
  		if (linkp != NULL)
  		{
  		    /* Create a new hardlink_info node, which will record
  		       the current file's status and the links listed in its
  		       `hardlinks' delta field.  We will append this
  		       hardlink_info node to the appropriate hardlist entry. */
  		    hlinfo = (struct hardlink_info *)
  			xmalloc (sizeof (struct hardlink_info));
  		    hlinfo->status = status;
  		    linkp->data = (char *) hlinfo;
  		}
  	    }
  #endif
  
  	    break;
+         }
+ 
  	case T_UNKNOWN:
  	    error (0, 0, "nothing known about `%s'", finfo->fullname);
  	    freevers_ts (&vers);
  	    return (1);
  	case T_UPTODATE:
  	    break;
  	default:
  	    error (0, 0, "CVS internal error: unknown status %d", status);
  	    break;
      }
  
      freevers_ts (&vers);
      return (0);
  }
  
  /*
Index: src/edit.c
===================================================================
RCS file: /home/nyap/.cvsroot/cvs/src/edit.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -C16 -w -r1.1.1.1 -r1.1.1.1.2.1
*** src/edit.c	2001/03/06 16:21:21	1.1.1.1
--- src/edit.c	2001/03/07 23:01:33	1.1.1.1.2.1
***************
*** 5,36 ****
--- 5,37 ----
     the Free Software Foundation; either version 2, or (at your option)
     any later version.
  
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.  */
  
  #include "cvs.h"
  #include "getline.h"
  #include "watch.h"
  #include "edit.h"
  #include "fileattr.h"
  
  static int watch_onoff PROTO ((int, char **));
  
+ static int check_edited = 0;
  static int setting_default;
  static int turning_on;
  
  static int setting_tedit;
  static int setting_tunedit;
  static int setting_tcommit;
  
  static int onoff_fileproc PROTO ((void *callerdat, struct file_info *finfo));
  
  static int
  onoff_fileproc (callerdat, finfo)
      void *callerdat;
      struct file_info *finfo;
  {
      fileattr_set (finfo->file, "_watched", turning_on ? "" : NULL);
      return 0;
***************
*** 256,287 ****
--- 257,529 ----
      }
      else
  #endif
      {
  	/* Local.  */
  
  	lock_tree_for_write (argc, argv, local, 0);
  	err += start_recursion (ncheck_fileproc, (FILESDONEPROC) NULL,
  				(DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
  				argc, argv, local, W_LOCAL, 0, 0, (char *)NULL,
  				0);
  	Lock_Cleanup ();
      }
      return err;
  }
  
+ 
+ static int editors_output PROTO ((struct file_info *finfo));
+ 
+ static int
+     editors_output (finfo)
+     struct file_info *finfo;
+ {
+     char *them;
+     char *p;
+ 
+     them = fileattr_get0 (finfo->file, "_editors");
+     if (them == NULL)
+         return 0;
+ 
+     cvs_output (finfo->fullname, 0);
+ 
+     p = them;
+     while (1)
+     {
+         cvs_output ("\t", 1);
+         while (*p != '>' && *p != '\0')
+             cvs_output (p++, 1);
+         if (*p == '\0')
+         {
+             /* Only happens if attribute is misformed.  */
+             cvs_output ("\n", 1);
+             break;
+         }
+         ++p;
+         cvs_output ("\t", 1);
+         while (1)
+         {
+             while (*p != '+' && *p != ',' && *p != '\0')
+                 cvs_output (p++, 1);
+             if (*p == '\0')
+             {
+                 cvs_output ("\n", 1);
+                 goto out;
+             }
+             if (*p == ',')
+             {
+                 ++p;
+                 break;
+             }
+             ++p;
+             cvs_output ("\t", 1);
+         }
+         cvs_output ("\n", 1);
+     }
+ 
+ out:
+     free (them);
+ 
+     return 0;
+ }
+ 
+ 
+ static int check_fileproc PROTO ((void *callerdat, struct file_info *finfo));
+ 
+ /* check file that is to be edited if it's already being edited */
+ 
+ static int
+ check_fileproc (callerdat, finfo)
+     void *callerdat;
+     struct file_info *finfo;
+ {
+     char *editors = NULL;
+     int editors_found = 0;
+     FILE *fp;
+     time_t now;
+     int status;
+     char *ascnow;
+     char *basefilename;
+ 
+ #ifdef CLIENT_SUPPORT
+     if (client_active)
+     {
+         int len = 0;
+         int possibly_more_editors = 0;
+ 
+         send_file_names (1, &finfo->fullname, SEND_EXPAND_WILD);
+         send_to_server ("editors\012", 0);
+ 
+         do
+         {
+             possibly_more_editors = 0;
+ 
+             to_server_buffer_flush ();
+             from_server_buffer_read (&editors, &len);
+ 
+             if (editors != NULL)
+             {
+                 if (strcmp (editors, "ok") != 0)
+                 {
+                     possibly_more_editors = 1;
+ 
+                     if (editors[0] == 'M')
+                     {
+                         editors_found = 1;
+ 
+                         if(!really_quiet)
+                         {
+                             cvs_output (editors + 2, 0);
+                             cvs_output ("\n", 0);
+                         }
+                     }
+                     else
+                     {
+                         struct response *rs = NULL;
+                         char *cmd = NULL;
+ 
+                         cmd = editors;
+ 
+                         for (rs = responses; rs->name != NULL; ++rs)
+                         {
+                             if (strncmp (cmd, rs->name, strlen (rs->name)) == 0)
+                             {
+                                 int cmdlen = strlen (rs->name);
+                                 if (cmd[cmdlen] == ' ')
+                                     ++cmdlen;
+                                 else if (cmd[cmdlen] != '\0')
+                                     /*
+                                      * The first len characters match, but it's a different
+                                      * response.  e.g. the response is "oklahoma" but we
+                                      * matched "ok".
+                                      */
+                                     continue;
+                                 (*rs->func) (cmd + cmdlen, len - cmdlen);
+                                 break;
+                             }
+                         }
+ 
+                         if (rs->name == NULL)
+                         {
+                             /* It's OK to print just to the first '\0'.  */
+                             /* We might want to handle control characters and the like
+                                in some other way other than just sending them to stdout.
+                                One common reason for this error is if people use :ext:
+                                with a version of rsh which is doing CRLF translation or
+                                something, and so the client gets "ok^M" instead of "ok".
+                                Right now that will tend to print part of this error
+                                message over the other part of it.  It seems like we could
+                                do better (either in general, by quoting or omitting all
+                                control characters, and/or specifically, by detecting the CRLF
+                                case and printing a specific error message).  */
+                             error (0, 0,
+                                    "warning: unrecognized response `%s' from cvs server",
+                                    cmd);
+                         }
+                     }
+                 }
+ 
+                 free(editors);
+             }
+         } while (possibly_more_editors);
+     }
+     else
+ #endif /* CLIENT_SUPPORT */
+     {
+         /* This is a somewhat screwy way to check for this, because it
+            doesn't help errors other than the nonexistence of the file
+            (e.g. permissions problems).  It might be better to rearrange
+            the code so that CVSADM_NOTIFY gets written only after the
+            various actions succeed (but what if only some of them
+            succeed).  */
+         if (!isfile (finfo->file))
+         {
+             error (0, 0, "no such file %s; ignored", finfo->fullname);
+             return 0;
+         }
+ 
+         editors = fileattr_get0 (finfo->file, "_editors");
+         if(!really_quiet && editors != NULL)
+         {
+             editors_output (finfo);
+         }
+ 
+         if(editors != NULL)
+         {
+             editors_found = 1;
+ 
+             free (editors);
+         }
+     }
+ 
+     if(check_edited && editors_found)
+     {
+         status = 1;
+     }
+     else
+     {
+         status = 0;
+     }
+ 
+     return status;
+ }
+ 
+ static int check_edits PROTO ((int, char **, int));
+ 
+ /* Look through the CVS/fileattr file and check for editors */
+ static int
+ check_edits (argc, argv, local)
+     int argc;
+     char **argv;
+     int local;
+ {
+     int err = 0;
+ 
+ #ifdef CLIENT_SUPPORT
+     if (client_active)
+     {
+         if (strcmp (command_name, "release") != 0)
+         {
+             start_server ();
+             ign_setup ();
+         }
+ 
+         if (local)
+             send_arg ("-l");
+         send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
+     }
+ #endif
+ 
+ 	err += start_recursion (check_fileproc, (FILESDONEPROC) NULL,
+                             (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
+                             argc, argv, local, W_LOCAL, 0, 0, (char *)NULL,
+                             0);
+ 
+ #ifdef CLIENT_SUPPORT
+     if (client_active)
+     {
+         send_to_server ("noop\012", 0);
+         if (strcmp (command_name, "release") == 0)
+             err += get_server_responses ();
+         else
+             err += get_responses_and_close ();
+     }
+ #endif
+     return err;
+ }
+ 
  static int edit_fileproc PROTO ((void *callerdat, struct file_info *finfo));
  
  static int
  edit_fileproc (callerdat, finfo)
      void *callerdat;
      struct file_info *finfo;
  {
      FILE *fp;
      time_t now;
      char *ascnow;
      char *basefilename;
  
      if (noexec)
  	return 0;
  
      /* This is a somewhat screwy way to check for this, because it
***************
*** 338,400 ****
      copy_file (finfo->file, basefilename);
      free (basefilename);
  
      {
  	Node *node;
  
  	node = findnode_fn (finfo->entries, finfo->file);
  	if (node != NULL)
  	    base_register (finfo, ((Entnode *) node->data)->version);
      }
  
      return 0;
  }
  
  static const char *const edit_usage[] =
  {
!     "Usage: %s %s [-lR] [files...]\n",
      "-l: Local directory only, not recursive\n",
      "-R: Process directories recursively\n",
      "-a: Specify what actions for temporary watch, one of\n",
      "    edit,unedit,commit,all,none\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
  
  int
  edit (argc, argv)
      int argc;
      char **argv;
  {
      int local = 0;
      int c;
!     int err;
      int a_omitted;
  
      if (argc == -1)
  	usage (edit_usage);
  
      a_omitted = 1;
      setting_tedit = 0;
      setting_tunedit = 0;
      setting_tcommit = 0;
      optind = 0;
!     while ((c = getopt (argc, argv, "+lRa:")) != -1)
      {
  	switch (c)
  	{
  	    case 'l':
  		local = 1;
  		break;
  	    case 'R':
  		local = 0;
  		break;
  	    case 'a':
  		a_omitted = 0;
  		if (strcmp (optarg, "edit") == 0)
  		    setting_tedit = 1;
  		else if (strcmp (optarg, "unedit") == 0)
  		    setting_tunedit = 1;
  		else if (strcmp (optarg, "commit") == 0)
  		    setting_tcommit = 1;
  		else if (strcmp (optarg, "all") == 0)
  		{
--- 580,650 ----
      copy_file (finfo->file, basefilename);
      free (basefilename);
  
      {
  	Node *node;
  
  	node = findnode_fn (finfo->entries, finfo->file);
  	if (node != NULL)
  	    base_register (finfo, ((Entnode *) node->data)->version);
      }
  
      return 0;
  }
  
  static const char *const edit_usage[] =
  {
!     "Usage: %s %s [-cflR] [files...]\n",
!     "-c: Check that working files are unedited\n",
!     "-f: Force edit if working files are edited (default)\n",
      "-l: Local directory only, not recursive\n",
      "-R: Process directories recursively\n",
      "-a: Specify what actions for temporary watch, one of\n",
      "    edit,unedit,commit,all,none\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
  
  int
  edit (argc, argv)
      int argc;
      char **argv;
  {
      int local = 0;
      int c;
!     int err = 0;
      int a_omitted;
  
      if (argc == -1)
  	usage (edit_usage);
  
      a_omitted = 1;
      setting_tedit = 0;
      setting_tunedit = 0;
      setting_tcommit = 0;
      optind = 0;
!     while ((c = getopt (argc, argv, "+cflRa:")) != -1)
      {
  	switch (c)
  	{
+             case 'c':
+                 check_edited = 1;
+                 break;
+             case 'f':
+                 check_edited = 0;
+                 break;
  	    case 'l':
  		local = 1;
  		break;
  	    case 'R':
  		local = 0;
  		break;
  	    case 'a':
  		a_omitted = 0;
  		if (strcmp (optarg, "edit") == 0)
  		    setting_tedit = 1;
  		else if (strcmp (optarg, "unedit") == 0)
  		    setting_tunedit = 1;
  		else if (strcmp (optarg, "commit") == 0)
  		    setting_tcommit = 1;
  		else if (strcmp (optarg, "all") == 0)
  		{
***************
*** 425,462 ****
--- 675,720 ----
  	setting_tedit = 1;
  	setting_tunedit = 1;
  	setting_tcommit = 1;
      }
  
      if (strpbrk (hostname, "+,>;=\t\n") != NULL)
  	error (1, 0,
  	       "host name (%s) contains an invalid character (+,>;=\\t\\n)",
  	       hostname);
      if (strpbrk (CurDir, "+,>;=\t\n") != NULL)
  	error (1, 0,
  "current directory (%s) contains an invalid character (+,>;=\\t\\n)",
  	       CurDir);
  
      /* No need to readlock since we aren't doing anything to the
         repository.  */
+     err = check_edits (argc, argv, local);
+     if(err)
+     {
+         error (1, 0, "files being edited!");
+     }
+     else
+     {
      err = start_recursion (edit_fileproc, (FILESDONEPROC) NULL,
  			   (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
  			   argc, argv, local, W_LOCAL, 0, 0, (char *)NULL,
  			   0);
  
      err += send_notifications (argc, argv, local);
+     }
  
      return err;
  }
  
  static int unedit_fileproc PROTO ((void *callerdat, struct file_info *finfo));
  
  static int
  unedit_fileproc (callerdat, finfo)
      void *callerdat;
      struct file_info *finfo;
  {
      FILE *fp;
      time_t now;
      char *ascnow;
      char *basefilename;
  
***************
*** 1021,1098 ****
  
  static const char *const editors_usage[] =
  {
      "Usage: %s %s [-lR] [files...]\n",
      "\t-l\tProcess this directory only (not recursive).\n",
      "\t-R\tProcess directories recursively.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
  
  static int editors_fileproc PROTO ((void *callerdat, struct file_info *finfo));
  
  static int
  editors_fileproc (callerdat, finfo)
      void *callerdat;
      struct file_info *finfo;
- {
-     char *them;
-     char *p;
- 
-     them = fileattr_get0 (finfo->file, "_editors");
-     if (them == NULL)
- 	return 0;
- 
-     cvs_output (finfo->fullname, 0);
- 
-     p = them;
-     while (1)
-     {
- 	cvs_output ("\t", 1);
- 	while (*p != '>' && *p != '\0')
- 	    cvs_output (p++, 1);
- 	if (*p == '\0')
- 	{
- 	    /* Only happens if attribute is misformed.  */
- 	    cvs_output ("\n", 1);
- 	    break;
- 	}
- 	++p;
- 	cvs_output ("\t", 1);
- 	while (1)
- 	{
- 	    while (*p != '+' && *p != ',' && *p != '\0')
- 		cvs_output (p++, 1);
- 	    if (*p == '\0')
- 	    {
- 		cvs_output ("\n", 1);
- 		goto out;
- 	    }
- 	    if (*p == ',')
  	    {
! 		++p;
! 		break;
! 	    }
! 	    ++p;
! 	    cvs_output ("\t", 1);
! 	}
! 	cvs_output ("\n", 1);
!     }
!   out:;
!     free (them);
!     return 0;
  }
  
  int
  editors (argc, argv)
      int argc;
      char **argv;
  {
      int local = 0;
      int c;
  
      if (argc == -1)
  	usage (editors_usage);
  
      optind = 0;
      while ((c = getopt (argc, argv, "+lR")) != -1)
      {
--- 1279,1312 ----
  
  static const char *const editors_usage[] =
  {
      "Usage: %s %s [-lR] [files...]\n",
      "\t-l\tProcess this directory only (not recursive).\n",
      "\t-R\tProcess directories recursively.\n",
      "(Specify the --help global option for a list of other help options)\n",
      NULL
  };
  
  static int editors_fileproc PROTO ((void *callerdat, struct file_info *finfo));
  
  static int
  editors_fileproc (callerdat, finfo)
      void *callerdat;
      struct file_info *finfo;
  {
!     return editors_output (finfo);
  }
  
  int
  editors (argc, argv)
      int argc;
      char **argv;
  {
      int local = 0;
      int c;
  
      if (argc == -1)
  	usage (editors_usage);
  
      optind = 0;
      while ((c = getopt (argc, argv, "+lR")) != -1)
      {
Index: src/version.c
===================================================================
RCS file: /home/nyap/.cvsroot/cvs/src/version.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -C16 -w -r1.1.1.1 -r1.1.1.1.2.1
*** src/version.c	2001/03/06 16:21:21	1.1.1.1
--- src/version.c	2001/03/07 23:01:33	1.1.1.1.2.1
***************
*** 1,31 ****
  /*
   * Copyright (c) 1994 david d `zoo' zuhn
   * Copyright (c) 1994 Free Software Foundation, Inc.
   * Copyright (c) 1992, Brian Berliner and Jeff Polk
   * 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 this  CVS source distribution.
   * 
   * version.c - the CVS version number
   */
  
  #include "cvs.h"
  
! char *version_string = "Concurrent Versions System (CVS) 1.11";
  
  #ifdef CLIENT_SUPPORT
  #ifdef SERVER_SUPPORT
  char *config_string = " (client/server)\n";
  #else
  char *config_string = " (client)\n";
  #endif
  #else
  #ifdef SERVER_SUPPORT
  char *config_string = " (server)\n";
  #else
  char *config_string = "\n";
  #endif
  #endif
  
  static const char *const version_usage[] =
--- 1,31 ----
  /*
   * Copyright (c) 1994 david d `zoo' zuhn
   * Copyright (c) 1994 Free Software Foundation, Inc.
   * Copyright (c) 1992, Brian Berliner and Jeff Polk
   * 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 this  CVS source distribution.
   *
   * version.c - the CVS version number
   */
  
  #include "cvs.h"
  
! char *version_string = "Concurrent Versions System (CVS) 1.11 (reservations)";
  
  #ifdef CLIENT_SUPPORT
  #ifdef SERVER_SUPPORT
  char *config_string = " (client/server)\n";
  #else
  char *config_string = " (client)\n";
  #endif
  #else
  #ifdef SERVER_SUPPORT
  char *config_string = " (server)\n";
  #else
  char *config_string = "\n";
  #endif
  #endif
  
  static const char *const version_usage[] =
***************
*** 59,75 ****
      if (client_active)
      {
  	(void) fputs ("Server: ", stdout);
  	start_server ();
  	if (supported_request ("version"))
  	    send_to_server ("version\012", 0);
  	else
  	{
  	    send_to_server ("noop\012", 0);
  	    fputs ("(unknown)\n", stdout);
  	}
  	err = get_responses_and_close ();
      }
  #endif
      return err;
  }
- 	
--- 59,74 ----
