diff options
Diffstat (limited to 'contrib/cvs/src/edit.c')
-rw-r--r-- | contrib/cvs/src/edit.c | 1164 |
1 files changed, 0 insertions, 1164 deletions
diff --git a/contrib/cvs/src/edit.c b/contrib/cvs/src/edit.c deleted file mode 100644 index 4e0cf1e..0000000 --- a/contrib/cvs/src/edit.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* Implementation for "cvs edit", "cvs watch on", and related commands - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - 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 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; -{ - char *watched = fileattr_get0 (finfo->file, "_watched"); - fileattr_set (finfo->file, "_watched", turning_on ? "" : NULL); - if (watched != NULL) - free (watched); - return 0; -} - - - -static int onoff_filesdoneproc PROTO ((void *, int, const char *, const char *, - List *)); - -static int -onoff_filesdoneproc (callerdat, err, repository, update_dir, entries) - void *callerdat; - int err; - const char *repository; - const char *update_dir; - List *entries; -{ - if (setting_default) - { - char *watched = fileattr_get0 (NULL, "_watched"); - fileattr_set (NULL, "_watched", turning_on ? "" : NULL); - if (watched != NULL) - free (watched); - } - return err; -} - -static int -watch_onoff (argc, argv) - int argc; - char **argv; -{ - int c; - int local = 0; - int err; - - optind = 0; - while ((c = getopt (argc, argv, "+lR")) != -1) - { - switch (c) - { - case 'l': - local = 1; - break; - case 'R': - local = 0; - break; - case '?': - default: - usage (watch_usage); - break; - } - } - argc -= optind; - argv += optind; - -#ifdef CLIENT_SUPPORT - if (current_parsed_root->isremote) - { - start_server (); - - ign_setup (); - - if (local) - send_arg ("-l"); - send_arg ("--"); - send_files (argc, argv, local, 0, SEND_NO_CONTENTS); - send_file_names (argc, argv, SEND_EXPAND_WILD); - send_to_server (turning_on ? "watch-on\012" : "watch-off\012", 0); - return get_responses_and_close (); - } -#endif /* CLIENT_SUPPORT */ - - setting_default = (argc <= 0); - - lock_tree_for_write (argc, argv, local, W_LOCAL, 0); - - err = start_recursion (onoff_fileproc, onoff_filesdoneproc, - (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, - argc, argv, local, W_LOCAL, 0, CVS_LOCK_NONE, - (char *) NULL, 0, (char *) NULL); - - Lock_Cleanup (); - return err; -} - -int -watch_on (argc, argv) - int argc; - char **argv; -{ - turning_on = 1; - return watch_onoff (argc, argv); -} - -int -watch_off (argc, argv) - int argc; - char **argv; -{ - turning_on = 0; - return watch_onoff (argc, argv); -} - -static int dummy_fileproc PROTO ((void *callerdat, struct file_info *finfo)); - -static int -dummy_fileproc (callerdat, finfo) - void *callerdat; - struct file_info *finfo; -{ - /* This is a pretty hideous hack, but the gist of it is that recurse.c - won't call cvs_notify_check unless there is a fileproc, so we - can't just pass NULL for fileproc. */ - return 0; -} - -static int ncheck_fileproc PROTO ((void *callerdat, struct file_info *finfo)); - -/* Check for and process notifications. Local only. I think that doing - this as a fileproc is the only way to catch all the - cases (e.g. foo/bar.c), even though that means checking over and over - for the same CVSADM_NOTIFY file which we removed the first time we - processed the directory. */ - -static int -ncheck_fileproc (callerdat, finfo) - void *callerdat; - struct file_info *finfo; -{ - int notif_type; - char *filename; - char *val; - char *cp; - char *watches; - - FILE *fp; - char *line = NULL; - size_t line_len = 0; - - /* We send notifications even if noexec. I'm not sure which behavior - is most sensible. */ - - fp = CVS_FOPEN (CVSADM_NOTIFY, "r"); - if (fp == NULL) - { - if (!existence_error (errno)) - error (0, errno, "cannot open %s", CVSADM_NOTIFY); - return 0; - } - - while (getline (&line, &line_len, fp) > 0) - { - notif_type = line[0]; - if (notif_type == '\0') - continue; - filename = line + 1; - cp = strchr (filename, '\t'); - if (cp == NULL) - continue; - *cp++ = '\0'; - val = cp; - cp = strchr (val, '\t'); - if (cp == NULL) - continue; - *cp++ = '+'; - cp = strchr (cp, '\t'); - if (cp == NULL) - continue; - *cp++ = '+'; - cp = strchr (cp, '\t'); - if (cp == NULL) - continue; - *cp++ = '\0'; - watches = cp; - cp = strchr (cp, '\n'); - if (cp == NULL) - continue; - *cp = '\0'; - - notify_do (notif_type, filename, getcaller (), val, watches, - finfo->repository); - } - free (line); - - if (ferror (fp)) - error (0, errno, "cannot read %s", CVSADM_NOTIFY); - if (fclose (fp) < 0) - error (0, errno, "cannot close %s", CVSADM_NOTIFY); - - if ( CVS_UNLINK (CVSADM_NOTIFY) < 0) - error (0, errno, "cannot remove %s", CVSADM_NOTIFY); - - return 0; -} - -static int send_notifications PROTO ((int, char **, int)); - -/* Look through the CVSADM_NOTIFY file and process each item there - accordingly. */ -static int -send_notifications (argc, argv, local) - int argc; - char **argv; - int local; -{ - int err = 0; - -#ifdef CLIENT_SUPPORT - /* OK, we've done everything which needs to happen on the client side. - Now we can try to contact the server; if we fail, then the - notifications stay in CVSADM_NOTIFY to be sent next time. */ - if (current_parsed_root->isremote) - { - if (strcmp (cvs_cmd_name, "release") != 0) - { - start_server (); - ign_setup (); - } - - err += start_recursion (dummy_fileproc, (FILESDONEPROC) NULL, - (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, - argc, argv, local, W_LOCAL, 0, 0, (char *)NULL, - 0, (char *) NULL); - - send_to_server ("noop\012", 0); - if (strcmp (cvs_cmd_name, "release") == 0) - err += get_server_responses (); - else - err += get_responses_and_close (); - } - else -#endif - { - /* Local. */ - - lock_tree_for_write (argc, argv, local, W_LOCAL, 0); - err += start_recursion (ncheck_fileproc, (FILESDONEPROC) NULL, - (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, - argc, argv, local, W_LOCAL, 0, 0, (char *)NULL, - 0, (char *) NULL); - Lock_Cleanup (); - } - 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 - 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; - } - - fp = open_file (CVSADM_NOTIFY, "a"); - - (void) time (&now); - ascnow = asctime (gmtime (&now)); - ascnow[24] = '\0'; - /* Fix non-standard format. */ - if (ascnow[8] == '0') ascnow[8] = ' '; - fprintf (fp, "E%s\t%s GMT\t%s\t%s\t", finfo->file, - ascnow, hostname, CurDir); - if (setting_tedit) - fprintf (fp, "E"); - if (setting_tunedit) - fprintf (fp, "U"); - if (setting_tcommit) - fprintf (fp, "C"); - fprintf (fp, "\n"); - - if (fclose (fp) < 0) - { - if (finfo->update_dir[0] == '\0') - error (0, errno, "cannot close %s", CVSADM_NOTIFY); - else - error (0, errno, "cannot close %s/%s", finfo->update_dir, - CVSADM_NOTIFY); - } - - xchmod (finfo->file, 1); - - /* Now stash the file away in CVSADM so that unedit can revert even if - it can't communicate with the server. We stash away a writable - copy so that if the user removes the working file, then restores it - with "cvs update" (which clears _editors but does not update - CVSADM_BASE), then a future "cvs edit" can still win. */ - /* Could save a system call by only calling mkdir_if_needed if - trying to create the output file fails. But copy_file isn't - set up to facilitate that. */ - mkdir_if_needed (CVSADM_BASE); - basefilename = xmalloc (10 + sizeof CVSADM_BASE + strlen (finfo->file)); - strcpy (basefilename, CVSADM_BASE); - strcat (basefilename, "/"); - strcat (basefilename, finfo->file); - 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] [-a <action>]... [<file>]...\n", - "-l\tLocal directory only, not recursive.\n", - "-R\tProcess directories recursively (default).\n", - "-a\tSpecify action to register for temporary watch, one of:\n", - " \t`edit', `unedit', `commit', `all', or `none' (defaults to `all').\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) - { - setting_tedit = 1; - setting_tunedit = 1; - setting_tcommit = 1; - } - else if (strcmp (optarg, "none") == 0) - { - setting_tedit = 0; - setting_tunedit = 0; - setting_tcommit = 0; - } - else - usage (edit_usage); - break; - case '?': - default: - usage (edit_usage); - break; - } - } - argc -= optind; - argv += optind; - - if (a_omitted) - { - 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 = start_recursion (edit_fileproc, (FILESDONEPROC) NULL, - (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, - argc, argv, local, W_LOCAL, 0, 0, (char *) NULL, - 0, (char *) NULL); - - 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; - - if (noexec) - return 0; - - basefilename = xmalloc (10 + sizeof CVSADM_BASE + strlen (finfo->file)); - strcpy (basefilename, CVSADM_BASE); - strcat (basefilename, "/"); - strcat (basefilename, finfo->file); - if (!isfile (basefilename)) - { - /* This file apparently was never cvs edit'd (e.g. we are uneditting - a directory where only some of the files were cvs edit'd. */ - free (basefilename); - return 0; - } - - if (xcmp (finfo->file, basefilename) != 0) - { - printf ("%s has been modified; revert changes? ", finfo->fullname); - if (!yesno ()) - { - /* "no". */ - free (basefilename); - return 0; - } - } - rename_file (basefilename, finfo->file); - free (basefilename); - - fp = open_file (CVSADM_NOTIFY, "a"); - - (void) time (&now); - ascnow = asctime (gmtime (&now)); - ascnow[24] = '\0'; - /* Fix non-standard format. */ - if (ascnow[8] == '0') ascnow[8] = ' '; - fprintf (fp, "U%s\t%s GMT\t%s\t%s\t\n", finfo->file, - ascnow, hostname, CurDir); - - if (fclose (fp) < 0) - { - if (finfo->update_dir[0] == '\0') - error (0, errno, "cannot close %s", CVSADM_NOTIFY); - else - error (0, errno, "cannot close %s/%s", finfo->update_dir, - CVSADM_NOTIFY); - } - - /* Now update the revision number in CVS/Entries from CVS/Baserev. - The basic idea here is that we are reverting to the revision - that the user edited. If we wanted "cvs update" to update - CVS/Base as we go along (so that an unedit could revert to the - current repository revision), we would need: - - update (or all send_files?) (client) needs to send revision in - new Entry-base request. update (server/local) needs to check - revision against repository and send new Update-base response - (like Update-existing in that the file already exists. While - we are at it, might try to clean up the syntax by having the - mode only in a "Mode" response, not in the Update-base itself). */ - { - char *baserev; - Node *node; - Entnode *entdata; - - baserev = base_get (finfo); - node = findnode_fn (finfo->entries, finfo->file); - /* The case where node is NULL probably should be an error or - something, but I don't want to think about it too hard right - now. */ - if (node != NULL) - { - entdata = node->data; - if (baserev == NULL) - { - /* This can only happen if the CVS/Baserev file got - corrupted. We suspect it might be possible if the - user interrupts CVS, although I haven't verified - that. */ - error (0, 0, "%s not mentioned in %s", finfo->fullname, - CVSADM_BASEREV); - - /* Since we don't know what revision the file derives from, - keeping it around would be asking for trouble. */ - if (unlink_file (finfo->file) < 0) - error (0, errno, "cannot remove %s", finfo->fullname); - - /* This is cheesy, in a sense; why shouldn't we do the - update for the user? However, doing that would require - contacting the server, so maybe this is OK. */ - error (0, 0, "run update to complete the unedit"); - return 0; - } - Register (finfo->entries, finfo->file, baserev, entdata->timestamp, - entdata->options, entdata->tag, entdata->date, - entdata->conflict); - } - free (baserev); - base_deregister (finfo); - } - - xchmod (finfo->file, 0); - return 0; -} - -static const char *const unedit_usage[] = -{ - "Usage: %s %s [-lR] [<file>]...\n", - "-l\tLocal directory only, not recursive.\n", - "-R\tProcess directories recursively (default).\n", - "(Specify the --help global option for a list of other help options.)\n", - NULL -}; - -int -unedit (argc, argv) - int argc; - char **argv; -{ - int local = 0; - int c; - int err; - - if (argc == -1) - usage (unedit_usage); - - optind = 0; - while ((c = getopt (argc, argv, "+lR")) != -1) - { - switch (c) - { - case 'l': - local = 1; - break; - case 'R': - local = 0; - break; - case '?': - default: - usage (unedit_usage); - break; - } - } - argc -= optind; - argv += optind; - - /* No need to readlock since we aren't doing anything to the - repository. */ - err = start_recursion (unedit_fileproc, (FILESDONEPROC) NULL, - (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, - argc, argv, local, W_LOCAL, 0, 0, (char *)NULL, - 0, (char *) NULL); - - err += send_notifications (argc, argv, local); - - return err; -} - -void -mark_up_to_date (file) - const char *file; -{ - char *base; - - /* The file is up to date, so we better get rid of an out of - date file in CVSADM_BASE. */ - base = xmalloc (strlen (file) + 80); - strcpy (base, CVSADM_BASE); - strcat (base, "/"); - strcat (base, file); - if (unlink_file (base) < 0 && ! existence_error (errno)) - error (0, errno, "cannot remove %s", file); - free (base); -} - - - -void -editor_set (filename, editor, val) - const char *filename; - const char *editor; - const char *val; -{ - char *edlist; - char *newlist; - - edlist = fileattr_get0 (filename, "_editors"); - newlist = fileattr_modify (edlist, editor, val, '>', ','); - /* If the attributes is unchanged, don't rewrite the attribute file. */ - if (!((edlist == NULL && newlist == NULL) - || (edlist != NULL - && newlist != NULL - && strcmp (edlist, newlist) == 0))) - fileattr_set (filename, "_editors", newlist); - if (edlist != NULL) - free (edlist); - if (newlist != NULL) - free (newlist); -} - -struct notify_proc_args { - /* What kind of notification, "edit", "tedit", etc. */ - const char *type; - /* User who is running the command which causes notification. */ - const char *who; - /* User to be notified. */ - const char *notifyee; - /* File. */ - const char *file; -}; - - - -/* Pass as a static until we get around to fixing Parse_Info to pass along - a void * where we can stash it. */ -static struct notify_proc_args *notify_args; - - - -static int notify_proc PROTO ((const char *repository, const char *filter)); - -static int -notify_proc (repository, filter) - const char *repository; - const char *filter; -{ - FILE *pipefp; - char *prog; - char *expanded_prog; - const char *p; - char *q; - const char *srepos; - struct notify_proc_args *args = notify_args; - - srepos = Short_Repository (repository); - prog = xmalloc (strlen (filter) + strlen (args->notifyee) + 1); - /* Copy FILTER to PROG, replacing the first occurrence of %s with - the notifyee. We only allocated enough memory for one %s, and I doubt - there is a need for more. */ - for (p = filter, q = prog; *p != '\0'; ++p) - { - if (p[0] == '%') - { - if (p[1] == 's') - { - strcpy (q, args->notifyee); - q += strlen (q); - strcpy (q, p + 2); - q += strlen (q); - break; - } - else - continue; - } - *q++ = *p; - } - *q = '\0'; - - /* FIXME: why are we calling expand_proc? Didn't we already - expand it in Parse_Info, before passing it to notify_proc? */ - expanded_prog = expand_path (prog, "notify", 0); - if (!expanded_prog) - { - free (prog); - return 1; - } - - pipefp = run_popen (expanded_prog, "w"); - if (pipefp == NULL) - { - error (0, errno, "cannot write entry to notify filter: %s", prog); - free (prog); - free (expanded_prog); - return 1; - } - - fprintf (pipefp, "%s %s\n---\n", srepos, args->file); - fprintf (pipefp, "Triggered %s watch on %s\n", args->type, repository); - fprintf (pipefp, "By %s\n", args->who); - - /* Lots more potentially useful information we could add here; see - logfile_write for inspiration. */ - - free (prog); - free (expanded_prog); - return (pclose (pipefp)); -} - -/* FIXME: this function should have a way to report whether there was - an error so that server.c can know whether to report Notified back - to the client. */ -void -notify_do (type, filename, who, val, watches, repository) - int type; - const char *filename; - const char *who; - const char *val; - const char *watches; - const char *repository; -{ - static struct addremove_args blank; - struct addremove_args args; - char *watchers; - char *p; - char *endp; - char *nextp; - - /* Initialize fields to 0, NULL, or 0.0. */ - args = blank; - switch (type) - { - case 'E': - if (strpbrk (val, ",>;=\n") != NULL) - { - error (0, 0, "invalid character in editor value"); - return; - } - editor_set (filename, who, val); - break; - case 'U': - case 'C': - editor_set (filename, who, NULL); - break; - default: - return; - } - - watchers = fileattr_get0 (filename, "_watchers"); - p = watchers; - while (p != NULL) - { - char *q; - char *endq; - char *nextq; - char *notif; - - endp = strchr (p, '>'); - if (endp == NULL) - break; - nextp = strchr (p, ','); - - if ((size_t)(endp - p) == strlen (who) && strncmp (who, p, endp - p) == 0) - { - /* Don't notify user of their own changes. Would perhaps - be better to check whether it is the same working - directory, not the same user, but that is hairy. */ - p = nextp == NULL ? nextp : nextp + 1; - continue; - } - - /* Now we point q at a string which looks like - "edit+unedit+commit,"... and walk down it. */ - q = endp + 1; - notif = NULL; - while (q != NULL) - { - endq = strchr (q, '+'); - if (endq == NULL || (nextp != NULL && endq > nextp)) - { - if (nextp == NULL) - endq = q + strlen (q); - else - endq = nextp; - nextq = NULL; - } - else - nextq = endq + 1; - - /* If there is a temporary and a regular watch, send a single - notification, for the regular watch. */ - if (type == 'E' && endq - q == 4 && strncmp ("edit", q, 4) == 0) - { - notif = "edit"; - } - else if (type == 'U' - && endq - q == 6 && strncmp ("unedit", q, 6) == 0) - { - notif = "unedit"; - } - else if (type == 'C' - && endq - q == 6 && strncmp ("commit", q, 6) == 0) - { - notif = "commit"; - } - else if (type == 'E' - && endq - q == 5 && strncmp ("tedit", q, 5) == 0) - { - if (notif == NULL) - notif = "temporary edit"; - } - else if (type == 'U' - && endq - q == 7 && strncmp ("tunedit", q, 7) == 0) - { - if (notif == NULL) - notif = "temporary unedit"; - } - else if (type == 'C' - && endq - q == 7 && strncmp ("tcommit", q, 7) == 0) - { - if (notif == NULL) - notif = "temporary commit"; - } - q = nextq; - } - if (nextp != NULL) - ++nextp; - - if (notif != NULL) - { - struct notify_proc_args args; - size_t len = endp - p; - FILE *fp; - char *usersname; - char *line = NULL; - size_t line_len = 0; - - args.notifyee = NULL; - usersname = xmalloc (strlen (current_parsed_root->directory) - + sizeof CVSROOTADM - + sizeof CVSROOTADM_USERS - + 20); - strcpy (usersname, current_parsed_root->directory); - strcat (usersname, "/"); - strcat (usersname, CVSROOTADM); - strcat (usersname, "/"); - strcat (usersname, CVSROOTADM_USERS); - fp = CVS_FOPEN (usersname, "r"); - if (fp == NULL && !existence_error (errno)) - error (0, errno, "cannot read %s", usersname); - if (fp != NULL) - { - while (getline (&line, &line_len, fp) >= 0) - { - if (strncmp (line, p, len) == 0 - && line[len] == ':') - { - char *cp; - args.notifyee = xstrdup (line + len + 1); - - /* There may or may not be more - colon-separated fields added to this in the - future; in any case, we ignore them right - now, and if there are none we make sure to - chop off the final newline, if any. */ - cp = strpbrk (args.notifyee, ":\n"); - - if (cp != NULL) - *cp = '\0'; - break; - } - } - if (ferror (fp)) - error (0, errno, "cannot read %s", usersname); - if (fclose (fp) < 0) - error (0, errno, "cannot close %s", usersname); - } - free (usersname); - if (line != NULL) - free (line); - - if (args.notifyee == NULL) - { - char *tmp; - tmp = xmalloc (endp - p + 1); - strncpy (tmp, p, endp - p); - tmp[endp - p] = '\0'; - args.notifyee = tmp; - } - - notify_args = &args; - args.type = notif; - args.who = who; - args.file = filename; - - (void) Parse_Info (CVSROOTADM_NOTIFY, repository, notify_proc, 1); - - /* It's okay to cast out the const for the free() below since we - * just allocated this a few lines above. The const was for - * everybody else. - */ - free ((char *)args.notifyee); - } - - p = nextp; - } - if (watchers != NULL) - free (watchers); - - switch (type) - { - case 'E': - if (*watches == 'E') - { - args.add_tedit = 1; - ++watches; - } - if (*watches == 'U') - { - args.add_tunedit = 1; - ++watches; - } - if (*watches == 'C') - { - args.add_tcommit = 1; - } - watch_modify_watchers (filename, &args); - break; - case 'U': - case 'C': - args.remove_temp = 1; - watch_modify_watchers (filename, &args); - break; - } -} - -#ifdef CLIENT_SUPPORT -/* Check and send notifications. This is only for the client. */ -void -cvs_notify_check (repository, update_dir) - const char *repository; - const char *update_dir; -{ - FILE *fp; - char *line = NULL; - size_t line_len = 0; - - if (! server_started) - /* We are in the midst of a command which is not to talk to - the server (e.g. the first phase of a cvs edit). Just chill - out, we'll catch the notifications on the flip side. */ - return; - - /* We send notifications even if noexec. I'm not sure which behavior - is most sensible. */ - - fp = CVS_FOPEN (CVSADM_NOTIFY, "r"); - if (fp == NULL) - { - if (!existence_error (errno)) - error (0, errno, "cannot open %s", CVSADM_NOTIFY); - return; - } - while (getline (&line, &line_len, fp) > 0) - { - int notif_type; - char *filename; - char *val; - char *cp; - - notif_type = line[0]; - if (notif_type == '\0') - continue; - filename = line + 1; - cp = strchr (filename, '\t'); - if (cp == NULL) - continue; - *cp++ = '\0'; - val = cp; - - client_notify (repository, update_dir, filename, notif_type, val); - } - if (line) - free (line); - if (ferror (fp)) - error (0, errno, "cannot read %s", CVSADM_NOTIFY); - if (fclose (fp) < 0) - error (0, errno, "cannot close %s", CVSADM_NOTIFY); - - /* Leave the CVSADM_NOTIFY file there, until the server tells us it - has dealt with it. */ -} -#endif /* CLIENT_SUPPORT */ - - -static const char *const editors_usage[] = -{ - "Usage: %s %s [-lR] [<file>]...\n", - "-l\tProcess this directory only (not recursive).\n", - "-R\tProcess directories recursively (default).\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) - { - switch (c) - { - case 'l': - local = 1; - break; - case 'R': - local = 0; - break; - case '?': - default: - usage (editors_usage); - break; - } - } - argc -= optind; - argv += optind; - -#ifdef CLIENT_SUPPORT - if (current_parsed_root->isremote) - { - start_server (); - ign_setup (); - - if (local) - send_arg ("-l"); - send_arg ("--"); - send_files (argc, argv, local, 0, SEND_NO_CONTENTS); - send_file_names (argc, argv, SEND_EXPAND_WILD); - send_to_server ("editors\012", 0); - return get_responses_and_close (); - } -#endif /* CLIENT_SUPPORT */ - - return start_recursion (editors_fileproc, (FILESDONEPROC) NULL, - (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL, - argc, argv, local, W_LOCAL, 0, 1, (char *) NULL, - 0, (char *) NULL); -} |