/* * Output a version string for the client and server. * * This function will output the simple version number (for the '--version' * option) or the version numbers of the client and server (using the 'version' * command). */ int version (int argc, char **argv) { int err = 0; if (argc == -1) usage (version_usage); if (current_parsed_root && current_parsed_root->isremote) (void) fputs ("Client: ", stdout); /* Having the year here is a good idea, so people have some idea of how long ago their version of CVS was released. */ (void) fputs (PACKAGE_STRING, stdout); (void) fputs (config_string, stdout); /* cvsacl patch */ (void) fputs (aclpatch_string, stdout); #ifdef CLIENT_SUPPORT if (current_parsed_root && current_parsed_root->isremote) { (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; }
int passwd (int argc, char **argv) { int c; int err = 0; char *typed_password = NULL, *typed_password2 = NULL; const char *username, *user; passwd_entry *passnode; char *linebuf = NULL; char *real_user = NULL; char *password_domain = NULL; int adduser=0,deluser=0,disableuser=0,realuser=0,remove_realuser=0,use_domain=0; int arg_specified = 0; if (argc == -1) usage (passwd_usage); optind = 0; while ((c = getopt (argc, argv, "axXr:RD:")) != -1) { switch (c) { case 'a': if(arg_specified) usage (passwd_usage); arg_specified = 1; adduser = 1; break; case 'x': if(arg_specified) usage (passwd_usage); arg_specified = 1; disableuser = 1; break; case 'X': if(arg_specified) usage (passwd_usage); arg_specified = 1; deluser = 1; break; case 'r': realuser = 1; real_user = xstrdup(optarg); break; case 'R': remove_realuser = 1; break; case 'D': use_domain = 1; password_domain = xstrdup(optarg); break; case '?': default: usage (passwd_usage); break; } } argc -= optind; argv += optind; if(!argc) user = NULL; else user=argv[0]; #ifdef CLIENT_SUPPORT if (current_parsed_root->isremote) { if (argc > 1) usage (passwd_usage); if (!supported_request ("passwd")) error (1, 0, "server does not support passwd"); if(!user && adduser) { error(1,0,"You cannot add yourself"); } if(!user && deluser) { error(1,0,"You cannot delete yourself"); } if(user || current_parsed_root->username || current_parsed_root->hostname) { printf ("%s %s@%s\n", (adduser) ? "Adding user" : (deluser) ? "Deleting user" : "Changing repository password for", user?user:current_parsed_root->username?current_parsed_root->username:getcaller(),current_parsed_root->hostname); } else { printf ("Changing repository password for %s\n",getcaller()); } fflush (stdout); if(!use_domain && !deluser && !disableuser) { typed_password = getpass ("New password: "******"Verify password: "******"Passwords do not match, try again"); } memset (typed_password2, 0, strlen (typed_password2)); typed_password = xrealloc(typed_password, strlen(typed_password) +32); if(strlen(typed_password)) crypt_password(typed_password); } if (adduser) send_arg ("-a"); if (disableuser) send_arg ("-x"); if (deluser) send_arg ("-X"); if (realuser) { send_arg ("-r"); send_arg (real_user); } if (remove_realuser) send_arg ("-R"); if(use_domain) { send_arg ("-D"); send_arg (password_domain); } if (argc == 1) send_arg(user); else send_arg("*"); if(typed_password) { send_arg (typed_password); /* Send the new password */ memset (typed_password, 0, strlen (typed_password)); xfree (typed_password); } send_to_server ("passwd\012", 0); return get_responses_and_close (); } if(!server_active) #endif { if(argc!=0 && argc!=1) usage (passwd_usage); if(!user && adduser) { error(1,0,"You cannot add yourself"); } if(!user && deluser) { error(1,0,"You cannot delete yourself"); } if(user || current_parsed_root->username) { printf ("%s %s\n", (adduser) ? "Adding user" : (deluser) ? "Deleting user" : "Changing password for", user?user:current_parsed_root->username); } else { printf ("Changing repository password for %s\n",getcaller()); } fflush (stdout); if (argc == 0) username = CVS_Username; else { username = user; } if(!use_domain && !deluser && !disableuser) { typed_password = getpass ("New password: "******"Verify password: "******"Passwords do not match, try again"); } memset (typed_password2, 0, strlen (typed_password2)); typed_password = xrealloc(typed_password, strlen(typed_password) +32); if(strlen(typed_password)) crypt_password(typed_password); } } #ifdef SERVER_SUPPORT if(server_active) { if ((argc != 1) && (argc != 2)) usage (passwd_usage); if(!strcmp(user,"*")) username = CVS_Username; else { username = user; #if defined(_WIN32) #ifdef SJIS if(_mbschr(username,'\\') && !isDomainMember()) #else if(strchr(username,'\\') && !isDomainMember()) #endif { error(1,0,"CVS server is not acting as a domain member - cannot specify domains"); } #endif } if(argc==2) typed_password = argv[1]; } #endif if (typed_password && (strcmp(username, CVS_Username) != 0) && (! verify_admin ())) error (1, 0, "Only administrators can add or change another's password"); read_passwd_list(); passnode = find_passwd_entry(username); if (passnode == NULL) { if (!adduser) error (1, 0, "Could not find %s in password file", username); if (! verify_admin()) { error (1, 0, "Only administrators can add users" ); } passnode = new_passwd_entry(); passnode->username=xstrdup(username); passnode->password=xstrdup(typed_password); passnode->real_username=NULL; } if(deluser) { if (! verify_admin()) { error (1, 0, "Only administrators can delete users" ); } xfree(passnode->username); passnode->username = NULL; } else if(disableuser) { if (! verify_admin()) { error (1, 0, "Only administrators can disable users" ); } xfree(passnode->password); passnode->password=xstrdup("#DISABLED#"); } else { xfree(passnode->password); #ifdef _WIN32 /* Unix servers can't make any sense of this */ if(use_domain) { passnode->password = xmalloc(strlen(password_domain)+2); strcpy(passnode->password,"!"); strcat(passnode->password,password_domain); } else #endif passnode->password = xstrdup(typed_password); if(realuser) { if(!getpwnam(real_user)) error(1, 0, "User '%s' is not a real user on the system.",real_user); xfree(passnode->real_username); passnode->real_username = xstrdup(real_user); } else if (remove_realuser) { xfree(passnode->real_username); passnode->real_username=NULL; } if((passnode->real_username && !getpwnam(passnode->real_username)) || (!passnode->real_username && passnode->username && !getpwnam(passnode->username))) { error(0,0,"*WARNING* CVS user '%s' will not be able to log in until they are aliased to a valid system user.",username); } } write_passwd_list(); free_passwd_list(); xfree(real_user); xfree(password_domain); return (err); }
int history (int argc, char **argv) { int i, c; const char *fname = NULL; List *flist; if (argc == -1) usage (history_usg); since_rev = xstrdup (""); since_tag = xstrdup (""); backto = xstrdup (""); rec_types = xstrdup (""); getoptreset (); while ((c = getopt (argc, argv, "+Tacelow?D:b:f:m:n:p:r:t:u:x:X:z:")) != -1) { switch (c) { case 'T': /* Tag list */ report_count++; tag_report++; break; case 'a': /* For all usernames */ all_users++; break; case 'c': report_count++; modified = 1; break; case 'e': report_count++; extract_all++; free (rec_types); rec_types = xstrdup (ALL_HISTORY_REC_TYPES); break; case 'l': /* Find Last file record */ last_entry = 1; break; case 'o': report_count++; v_checkout = 1; break; case 'w': /* Match Working Dir (CurDir) fields */ working = 1; break; case 'X': /* Undocumented debugging flag */ #ifdef DEBUG fname = optarg; #endif break; case 'D': /* Since specified date */ if (*since_rev || *since_tag || *backto) { error (0, 0, "date overriding rev/tag/backto"); *since_rev = *since_tag = *backto = '\0'; } since_date = Make_Date (optarg); break; case 'b': /* Since specified file/Repos */ if (since_date || *since_rev || *since_tag) { error (0, 0, "backto overriding date/rev/tag"); *since_rev = *since_tag = '\0'; if (since_date != NULL) free (since_date); since_date = NULL; } free (backto); backto = xstrdup (optarg); break; case 'f': /* For specified file */ save_file (NULL, optarg, NULL); break; case 'm': /* Full module report */ if (!module_report++) report_count++; /* fall through */ case 'n': /* Look for specified module */ save_module (optarg); break; case 'p': /* For specified directory */ save_file (optarg, NULL, NULL); break; case 'r': /* Since specified Tag/Rev */ if (since_date || *since_tag || *backto) { error (0, 0, "rev overriding date/tag/backto"); *since_tag = *backto = '\0'; if (since_date != NULL) free (since_date); since_date = NULL; } free (since_rev); since_rev = xstrdup (optarg); break; case 't': /* Since specified Tag/Rev */ if (since_date || *since_rev || *backto) { error (0, 0, "tag overriding date/marker/file/repos"); *since_rev = *backto = '\0'; if (since_date != NULL) free (since_date); since_date = NULL; } free (since_tag); since_tag = xstrdup (optarg); break; case 'u': /* For specified username */ save_user (optarg); break; case 'x': report_count++; extract++; { char *cp; for (cp = optarg; *cp; cp++) if (!strchr (ALL_HISTORY_REC_TYPES, *cp)) error (1, 0, "%c is not a valid report type", *cp); } free (rec_types); rec_types = xstrdup (optarg); break; case 'z': tz_local = (optarg[0] == 'l' || optarg[0] == 'L') && (optarg[1] == 't' || optarg[1] == 'T') && !optarg[2]; if (tz_local) tz_name = optarg; else { /* * Convert a known time with the given timezone to time_t. * Use the epoch + 23 hours, so timezones east of GMT work. */ struct timespec t; char *buf = Xasprintf ("1/1/1970 23:00 %s", optarg); if (get_date (&t, buf, NULL)) { /* * Convert to seconds east of GMT, removing the * 23-hour offset mentioned above. */ tz_seconds_east_of_GMT = (time_t)23 * 60 * 60 - t.tv_sec; tz_name = optarg; } else error (0, 0, "%s is not a known time zone", optarg); free (buf); } break; case '?': default: usage (history_usg); break; } } argc -= optind; argv += optind; for (i = 0; i < argc; i++) save_file (NULL, argv[i], NULL); /* ================ Now analyze the arguments a bit */ if (!report_count) v_checkout++; else if (report_count > 1) error (1, 0, "Only one report type allowed from: \"-Tcomxe\"."); #ifdef CLIENT_SUPPORT if (current_parsed_root->isremote) { struct file_list_str *f1; char **mod; /* We're the client side. Fire up the remote server. */ start_server (); ign_setup (); if (tag_report) send_arg ("-T"); if (all_users) send_arg ("-a"); if (modified) send_arg ("-c"); if (last_entry) send_arg ("-l"); if (v_checkout) send_arg ("-o"); if (working) send_arg ("-w"); if (fname) option_with_arg ("-X", fname); if (since_date) client_senddate (since_date); if (backto[0] != '\0') option_with_arg ("-b", backto); for (f1 = file_list; f1 < &file_list[file_count]; ++f1) { if (f1->l_file[0] == '*') option_with_arg ("-p", f1->l_file + 1); else option_with_arg ("-f", f1->l_file); } if (module_report) send_arg ("-m"); for (mod = mod_list; mod < &mod_list[mod_count]; ++mod) option_with_arg ("-n", *mod); if (*since_rev) option_with_arg ("-r", since_rev); if (*since_tag) option_with_arg ("-t", since_tag); for (mod = user_list; mod < &user_list[user_count]; ++mod) option_with_arg ("-u", *mod); if (extract_all) send_arg ("-e"); if (extract) option_with_arg ("-x", rec_types); option_with_arg ("-z", tz_name); send_to_server ("history\012", 0); return get_responses_and_close (); } #endif if (all_users) save_user (""); if (mod_list) expand_modules (); if (tag_report) { if (!strchr (rec_types, 'T')) { rec_types = xrealloc (rec_types, strlen (rec_types) + 5); (void) strcat (rec_types, "T"); } } else if (extract || extract_all) { if (user_list) user_sort++; } else if (modified) { free (rec_types); rec_types = xstrdup ("MAR"); /* * If the user has not specified a date oriented flag ("Since"), sort * by Repository/file before date. Default is "just" date. */ if (last_entry || (!since_date && !*since_rev && !*since_tag && !*backto)) { repos_sort++; file_sort++; /* * If we are not looking for last_modified and the user specified * one or more users to look at, sort by user before filename. */ if (!last_entry && user_list) user_sort++; } } else if (module_report) { free (rec_types); rec_types = xstrdup (last_entry ? "OMAR" : ALL_HISTORY_REC_TYPES); module_sort++; repos_sort++; file_sort++; working = 0; /* User's workdir doesn't count here */ } else /* Must be "checkout" or default */ { free (rec_types); rec_types = xstrdup ("OF"); /* See comments in "modified" above */ if (!last_entry && user_list) user_sort++; if (last_entry || (!since_date && !*since_rev && !*since_tag && !*backto)) file_sort++; } /* If no users were specified, use self (-a saves a universal ("") user) */ if (!user_list) save_user (getcaller ()); /* If we're looking back to a Tag value, must consider "Tag" records */ if (*since_tag && !strchr (rec_types, 'T')) { rec_types = xrealloc (rec_types, strlen (rec_types) + 5); (void) strcat (rec_types, "T"); } if (fname) { Node *p; flist = getlist (); p = getnode (); p->type = FILES; p->key = Xasprintf ("%s/%s/%s", current_parsed_root->directory, CVSROOTADM, fname); addnode (flist, p); } else { char *pat; if (config->HistorySearchPath) pat = config->HistorySearchPath; else pat = Xasprintf ("%s/%s/%s", current_parsed_root->directory, CVSROOTADM, CVSROOTADM_HISTORY); flist = find_files (NULL, pat); if (pat != config->HistorySearchPath) free (pat); } read_hrecs (flist); if (hrec_count > 0) qsort (hrec_head, hrec_count, sizeof (struct hrec), sort_order); report_hrecs (); if (since_date != NULL) free (since_date); free (since_rev); free (since_tag); free (backto); free (rec_types); return 0; }
int diff (int argc, char **argv) { char tmp[50]; int c, err = 0; int local = 0; int which; int option_index; is_rcs = (strcmp (command_name, "rcsfile") == 0); if (argc == -1) usage (diff_usage); have_rev1_label = have_rev2_label = 0; /* * Note that we catch all the valid arguments here, so that we can * intercept the -r arguments for doing revision diffs; and -l/-R for a * non-recursive/recursive diff. */ /* Clean out our global variables (multiroot can call us multiple times and the server can too, if the client sends several diff commands). */ if (opts == NULL) { opts_allocated = 1; opts = (char*)xmalloc (opts_allocated); } opts[0] = '\0'; diff_rev1 = NULL; diff_rev2 = NULL; diff_date1 = NULL; diff_date2 = NULL; optind = 0; while ((c = getopt_long (argc, argv, "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:V:W:k:r:", longopts, &option_index)) != -1) { switch (c) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h': case 'i': case 'n': case 'p': case 's': case 't': case 'u': case 'w': case 'y': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'B': case 'H': case 'T': (void) sprintf (tmp, " -%c", (char) c); allocate_and_strcat (&opts, &opts_allocated, tmp); break; case 'L': if (have_rev1_label++) if (have_rev2_label++) { error (0, 0, "extra -L arguments ignored"); break; } allocate_and_strcat (&opts, &opts_allocated, " -L"); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 'C': case 'F': case 'I': case 'U': case 'V': case 'W': (void) sprintf (tmp, " -%c", (char) c); allocate_and_strcat (&opts, &opts_allocated, tmp); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 131: /* --ifdef. */ allocate_and_strcat (&opts, &opts_allocated, " --ifdef="); allocate_and_strcat (&opts, &opts_allocated, optarg); break; case 129: case 130: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: allocate_and_strcat (&opts, &opts_allocated, " --"); allocate_and_strcat (&opts, &opts_allocated, longopts[option_index].name); if (longopts[option_index].has_arg == 1 || (longopts[option_index].has_arg == 2 && optarg != NULL)) { allocate_and_strcat (&opts, &opts_allocated, "="); allocate_and_strcat (&opts, &opts_allocated, optarg); } break; case 'R': local = 0; break; case 'l': local = 1; break; case 'k': if (options) xfree (options); options = RCS_check_kflag (optarg,true,true); break; case 'r': if (diff_rev2 != NULL || diff_date2 != NULL) error (1, 0, "no more than two revisions/dates can be specified"); if (diff_rev1 != NULL || diff_date1 != NULL) diff_rev2 = optarg; else diff_rev1 = optarg; break; case 'D': if (diff_rev2 != NULL || diff_date2 != NULL) error (1, 0, "no more than two revisions/dates can be specified"); if (diff_rev1 != NULL || diff_date1 != NULL) diff_date2 = Make_Date (optarg); else diff_date1 = Make_Date (optarg); break; case 'N': empty_files = 1; break; case '?': default: usage (diff_usage); break; } } argc -= optind; argv += optind; /* make sure options is non-null */ if (!options) options = xstrdup (""); if (!is_rcs && current_parsed_root->isremote) { if (local) send_arg("-l"); if (empty_files) send_arg("-N"); send_option_string (opts); if (options[0] != '\0') option_with_arg ("-k", options); if (diff_rev1) option_with_arg ("-r", diff_rev1); if (diff_date1) client_senddate (diff_date1); if (diff_rev2) option_with_arg ("-r", diff_rev2); if (diff_date2) client_senddate (diff_date2); send_arg("--"); /* Send the current files unless diffing two revs from the archive */ if (diff_rev2 == NULL && diff_date2 == NULL) send_files (argc, argv, local, 0, 0); else send_files (argc, argv, local, 0, SEND_NO_CONTENTS); send_file_names (argc, argv, SEND_EXPAND_WILD); send_to_server ("diff\n", 0); err = get_responses_and_close (); xfree (options); options = NULL; return (err); } if(is_rcs) { int n; if(!argc) usage(diff_usage); for(n=0; n<argc; n++) { struct file_info finfo = {0}; const char *name; char *tmp = find_rcs_filename(argv[n]); if(!tmp) error(1,ENOENT,"%s",argv[n]); finfo.fullname=fullpathname(tmp, &name); finfo.file = xstrdup(name); char *ff = xstrdup(finfo.fullname); finfo.update_dir = ff; ff[(name-finfo.fullname)-1]='\0'; finfo.rcs = RCS_fopen(finfo.fullname); if(finfo.rcs) { ff = (char*)finfo.fullname; ff[strlen(finfo.fullname)-2]='\0'; ff = (char*)finfo.file; ff[strlen(finfo.file)-2]='\0'; err+=diff_fileproc(NULL,&finfo); freercsnode(&finfo.rcs); } else { error(1,ENOENT,"%s",tmp); err++; } xfree(finfo.fullname); xfree(finfo.file); xfree(finfo.update_dir); xfree(tmp); } } else { if (diff_rev1 != NULL) tag_check_valid (diff_rev1, argc, argv, local, 0, ""); if (diff_rev2 != NULL) tag_check_valid (diff_rev2, argc, argv, local, 0, ""); which = W_LOCAL; if (diff_rev1 != NULL || diff_date1 != NULL) which |= W_REPOS; /* start the recursion processor */ err = start_recursion (diff_fileproc, diff_filesdoneproc, (PREDIRENTPROC) NULL, diff_dirproc, diff_dirleaveproc, NULL, argc, argv, local, which, 0, 1, (char *) NULL, NULL, 1, verify_read, diff_rev1); } /* clean up */ xfree (options); options = NULL; if (diff_date1 != NULL) xfree (diff_date1); if (diff_date2 != NULL) xfree (diff_date2); return (err); }
int release (int argc, char **argv) { int i, c; char *repository; char *thisarg; int arg_start_idx; int err = 0; short delete_flag = 0; short export_flag = 0; short yes_flag=0; struct saved_cwd cwd; #ifdef SERVER_SUPPORT if (server_active) return release_server (argc, argv); #endif /* Everything from here on is client or local. */ if (argc == -1) usage (release_usage); optind = 0; while ((c = getopt (argc, argv, "+Qdeqfy")) != -1) { switch (c) { case 'Q': case 'q': error (1, 0, "-q or -Q must be specified before \"%s\"", command_name); break; case 'd': delete_flag++; break; case 'f': force_delete++; break; case 'e': export_flag++; break; case 'y': yes_flag=1; break; case '?': default: usage (release_usage); break; } } argc -= optind; argv += optind; /* Remember the directory where "cvs release" was invoked because all args are relative to this directory and we chdir around. */ if (save_cwd (&cwd)) error_exit (); arg_start_idx = 0; for (i = arg_start_idx; i < argc; i++) { thisarg = argv[i]; if (isdir (thisarg)) { if (CVS_CHDIR (thisarg) < 0) { if (!really_quiet) error (0, errno, "can't chdir to: %s", thisarg); continue; } if (!isdir (CVSADM)) { if (!really_quiet) error (0, 0, "no repository directory: %s", thisarg); if (restore_cwd (&cwd, NULL)) error_exit (); continue; } } else { if (!really_quiet) error (0, 0, "no such directory: %s", thisarg); continue; } repository = Name_Repository ((char *) NULL, (char *) NULL); if (!really_quiet) { char *tmp; modified_files = 0; start_recursion (release_fileproc, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, (void *) NULL, 0, NULL, 0, W_LOCAL, 0, 0, (char *) NULL, NULL, 0, NULL, NULL); tmp=(char*)xmalloc(strlen(thisarg)+1024); if(modified_files) sprintf (tmp,"You have [%d] altered files in this repository.\n", modified_files); else *tmp='\0'; sprintf(tmp+strlen(tmp),"Are you sure you want to release %sdirectory '%s': ", delete_flag ? "(and delete) " : export_flag?"(and export) " : "", thisarg); if(!yes_flag) c=yesno_prompt(tmp,"Modified files",0); else { printf("%sy\n",tmp); c='y'; } xfree(tmp); if (c!='y') /* "No" */ { (void) fprintf (stderr, "** `%s' aborted by user choice.\n", command_name); xfree (repository); if (restore_cwd (&cwd, NULL)) error_exit (); continue; } } if (!(current_parsed_root->isremote && (!supported_request ("noop") || !supported_request ("Notify"))) ) { /* We are chdir'ed into the directory in question. So don't pass args to unedit. */ int argc = 1; char *argv[3]; argv[0] = "dummy"; argv[1] = NULL; err += unedit (argc, argv); /* Unedit will have killed our lockserver connection */ if(!current_parsed_root->isremote) lock_register_client(CVS_Username,current_parsed_root->directory); } if (current_parsed_root->isremote) { send_to_server ("Argument ", 0); send_to_server (thisarg, 0); send_to_server ("\n", 1); send_to_server ("release\n", 0); } else { history_write ('F', thisarg, "", thisarg, "", NULL, NULL); /* F == Free */ } xfree (repository); if (restore_cwd (&cwd, NULL)) error_exit (); if(!noexec) { if(delete_flag) { start_recursion (release_delete_fileproc, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, (DIRENTPROC) NULL, release_delete_dirleaveproc, (void *) NULL, 1, &thisarg, 0, W_LOCAL, 0, 0, (char *) NULL, NULL, 0, NULL, NULL); } else if(export_flag) { start_recursion (NULL, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, (DIRENTPROC) NULL, release_export_dirleaveproc, (void *) NULL, 1, &thisarg, 0, W_LOCAL, 0, 0, (char *) NULL, NULL, 0, NULL, NULL); } } if (current_parsed_root->isremote) err += get_server_responses (); } if (restore_cwd (&cwd, NULL)) error_exit (); free_cwd (&cwd); if (current_parsed_root->isremote) { /* Unfortunately, client.c doesn't offer a way to close the connection without waiting for responses. The extra network turnaround here is quite unnecessary other than that.... */ send_to_server ("noop\n", 0); err += get_responses_and_close (); } return err; }
int cvsstatus (int argc, char **argv) { int c; int err = 0; supress_extra_fields = compat[compat_level].hide_extended_status; if (argc == -1) usage (status_usage); optind = 0; while ((c = getopt (argc, argv, "+vlRqxX")) != -1) { switch (c) { case 'v': long_format = 1; break; case 'l': local = 1; break; case 'R': local = 0; break; case 'q': quick++; break; case 'x': supress_extra_fields = 0; break; case 'X': supress_extra_fields = 1; break; case '?': default: usage (status_usage); break; } } argc -= optind; argv += optind; if (current_parsed_root->isremote) { if (long_format) send_arg("-v"); if (local) send_arg("-l"); if (supress_extra_fields) send_arg("-X"); for(c=0; c<quick; c++) send_arg("-q"); send_arg("--"); /* For a while, we tried setting SEND_NO_CONTENTS here so this could be a fast operation. That prevents the server from updating our timestamp if the timestamp is changed but the file is unmodified. Worse, it is user-visible (shows "locally modified" instead of "up to date" if timestamp is changed but file is not). And there is no good workaround (you might not want to run "cvs update"; "cvs -n update" doesn't update CVS/Entries; "cvs diff --brief" or something perhaps could be made to work but somehow that seems nonintuitive to me even if so). Given that timestamps seem to have the potential to get munged for any number of reasons, it seems better to not rely too much on them. */ send_files (argc, argv, local, 0, 0); send_file_names (argc, argv, SEND_EXPAND_WILD); send_to_server ("status\n", 0); err = get_responses_and_close (); return err; } /* start the recursion processor */ err = start_recursion (status_fileproc, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, status_dirproc, (DIRLEAVEPROC) NULL, NULL, argc, argv, local, W_LOCAL, 0, 1, (char *) NULL, NULL, 1, verify_read); return (err); }
int lsacl (int argc, char **argv) { int c; int err = 0; int local = 1; int directories_only = 0; is_rlsacl = !strcmp(command_name,"rlsacl"); if (argc == -1) usage (is_rlsacl?rlsacl_usage:lsacl_usage); optind = 0; while ((c = getopt(argc, argv, "+dR")) != -1) { switch (c) { case 'd': directories_only = 1; break; case 'R': local = 0; break; case '?': default: usage (lsacl_usage); break; } } argc -= optind; argv += optind; if (argc < 0) usage (is_rlsacl?rlsacl_usage:lsacl_usage); if (current_parsed_root->isremote) { if(is_rlsacl) { if (!supported_request ("rlsacl")) error (1, 0, "server does not support rlsacl"); } else { if (!supported_request ("lsacl")) error (1, 0, "server does not support lsacl"); } if(!local) send_arg("-R"); if(directories_only) send_arg("-d"); send_arg("--"); if (is_rlsacl) { int i; for (i = 0; i < argc; i++) send_arg (argv[i]); send_to_server ("rlsacl\n", 0); } else { send_file_names (argc, argv, SEND_EXPAND_WILD); send_files (argc, argv, local, 0, SEND_NO_CONTENTS); send_to_server ("lsacl\n", 0); } return get_responses_and_close (); } if(!acl_mode) error(1,0,"Access control is disabled on this repository."); if (is_rlsacl) { DBM *db; int i; db = open_module (); if(!argc) { err += do_module (db, ".", MISC, "Listing", rlsacl_proc, (char *) NULL, 0, local, 0, 0, (char *) NULL); } else { for (i = 0; i < argc; i++) { err += do_module (db, argv[i], MISC, "Listing", rlsacl_proc, (char *) NULL, 0, local, 0, 0, (char *) NULL); } } close_module (db); } else { /* start the recursion processor */ err = start_recursion (directories_only?NULL:lsacl_fileproc, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, lsacl_dirproc, (DIRLEAVEPROC) NULL, NULL, argc, argv, local, W_LOCAL, 0, 1, (char *) NULL, NULL, 1, NULL); } return (err); }
int ls (int argc, char **argv) { int c; int err = 0; is_rls = strcmp (cvs_cmd_name, "rls") == 0; if (argc == -1) usage (ls_usage); entries_format = false; long_format = false; show_tag = NULL; show_date = NULL; tag_validated = false; recurse = false; ls_prune_dirs = false; show_dead_revs = false; getoptreset (); while ((c = getopt (argc, argv, #ifdef SERVER_SUPPORT server_active ? "qdelr:D:PR" : #endif /* SERVER_SUPPORT */ "delr:D:RP" )) != -1) { switch (c) { #ifdef SERVER_SUPPORT case 'q': if (server_active) { error (0, 0, "`%s ls -q' is deprecated. Please use the global `-q' option instead.", program_name); quiet = true; } else usage (ls_usage); break; #endif /* SERVER_SUPPORT */ case 'd': show_dead_revs = true; break; case 'e': entries_format = true; break; case 'l': long_format = true; break; case 'r': parse_tagdate (&show_tag, &show_date, optarg); break; case 'D': if (show_date) free (show_date); show_date = Make_Date (optarg); break; case 'P': ls_prune_dirs = true; break; case 'R': recurse = true; break; case '?': default: usage (ls_usage); break; } } argc -= optind; argv += optind; if (entries_format && long_format) { error (0, 0, "`-e' & `-l' are mutually exclusive."); usage (ls_usage); } wrap_setup (); #ifdef CLIENT_SUPPORT if (current_parsed_root->isremote) { /* We're the local client. Fire up the remote server. */ start_server (); ign_setup (); if (is_rls ? !(supported_request ("rlist") || supported_request ("ls")) : !supported_request ("list")) error (1, 0, "server does not support %s", cvs_cmd_name); if (quiet && !supported_request ("global-list-quiet")) send_arg ("-q"); if (entries_format) send_arg ("-e"); if (long_format) send_arg ("-l"); if (ls_prune_dirs) send_arg ("-P"); if (recurse) send_arg ("-R"); if (show_dead_revs) send_arg ("-d"); if (show_tag) option_with_arg ("-r", show_tag); if (show_date) client_senddate (show_date); send_arg ("--"); if (is_rls) { int i; for (i = 0; i < argc; i++) send_arg (argv[i]); if (supported_request ("rlist")) send_to_server ("rlist\012", 0); else /* For backwards compatibility with CVSNT... */ send_to_server ("ls\012", 0); } else { /* Setting this means, I think, that any empty directories created * by the server will be deleted by the client. Since any dirs * created at all by ls should remain empty, this should cause any * dirs created by the server for the ls command to be deleted. */ client_prune_dirs = 1; /* I explicitly decide not to send contents here. We *could* let * the user pull status information with this command, but why * don't they just use update or status? */ send_files (argc, argv, !recurse, 0, SEND_NO_CONTENTS); send_file_names (argc, argv, SEND_EXPAND_WILD); send_to_server ("list\012", 0); } err = get_responses_and_close (); return err; } #endif if (is_rls) { DBM *db; int i; db = open_module (); if (argc) { for (i = 0; i < argc; i++) { char *mod = xstrdup (argv[i]); char *p; for (p=strchr (mod,'\\'); p; p=strchr (p,'\\')) *p='/'; p = strrchr (mod,'/'); if (p && (strchr (p,'?') || strchr (p,'*'))) { *p='\0'; regexp_match = p+1; } else regexp_match = NULL; /* Frontends like to do 'ls -q /', so we support it explicitly. */ if (!strcmp (mod,"/")) { *mod='\0'; } err += do_module (db, mod, MISC, "Listing", ls_proc, NULL, 0, 0, 0, 0, NULL); free (mod); } } else { /* should be ".", but do_recursion() fails this: assert ( strstr ( repository, "/./" ) == NULL ); */ char *topmod = xstrdup (""); err += do_module (db, topmod, MISC, "Listing", ls_proc, NULL, 0, 0, 0, 0, NULL); free (topmod); } close_module (db); } else ls_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, 0, NULL, NULL); return err; }
int chacl (int argc, char **argv) { int c; int local = 1; int err = 0; int is_rchacl = !strcmp(command_name,"rchacl"); if (argc == 1 || argc == -1) usage (is_rchacl?rchacl_usage:chacl_usage); memset(&parms,0,sizeof(parms)); optind = 0; while ((c = getopt (argc, argv, "+a:dnRr:u:m:j:p:")) != -1) { switch (c) { case 'a': if(parms.del) error(1,0,"Cannot combine -a and -d"); parms.access = xstrdup(optarg); break; case 'd': if(parms.access) error(1,0,"Cannot combine -a and -d"); parms.del = 1; break; case 'j': parms.merge=xstrdup(optarg); break; case 'm': parms.message=xstrdup(optarg); break; case 'n': parms.noinherit=1; break; case 'p': parms.priority=xstrdup(optarg); break; case 'r': if(parms.branch) error(1,0,"Cannot have multiple -r options"); parms.branch = xstrdup(optarg); break; case 'R': local = 0; break; case 'u': if(parms.user) error(1,0,"Cannot have multiple -u options"); parms.user = xstrdup(optarg); break; case '?': default: usage (chacl_usage); break; } } argc -= optind; argv += optind; if (argc < 0) usage (is_rchacl?rchacl_usage:chacl_usage); if (current_parsed_root->isremote) { if(is_rchacl) { if (!supported_request ("rchacl2")) error (1, 0, "server does not support rchacl"); } else { if (!supported_request ("chacl2")) error (1, 0, "server does not support v2 chacl"); } if(parms.branch) { send_arg("-r"); send_arg(parms.branch); } if(parms.user) { send_arg("-u"); send_arg(parms.user); } if(parms.del) send_arg("-d"); if(parms.noinherit) send_arg("-n"); if(parms.access) { send_arg("-a"); send_arg(parms.access); } if(parms.message) { send_arg("-m"); send_arg(parms.message); } if(parms.merge) { send_arg("-j"); send_arg(parms.merge); } if(parms.priority) { send_arg("-p"); send_arg(parms.priority); } if(!local) { send_arg("-R"); } send_arg("--"); if (is_rchacl) { int i; for (i = 0; i < argc; i++) send_arg (argv[i]); send_to_server ("rchacl2\n", 0); } else { send_file_names (argc, argv, SEND_EXPAND_WILD); send_files (argc, argv, local, 0, SEND_NO_CONTENTS); send_to_server ("chacl2\n", 0); } return get_responses_and_close (); } if(!acl_mode) error(1,0,"Access control is disabled on this repository."); if (is_rchacl) { DBM *db; int i; db = open_module (); for (i = 0; i < argc; i++) { err += do_module (db, argv[i], MISC, "Changing", rchacl_proc, (char *) NULL, 0, local, 0, 0, (char *) NULL); } close_module (db); } else { current_date = date_from_time_t(global_session_time_t); err = start_recursion(chacl_fileproc, NULL, (PREDIRENTPROC) NULL, chacl_dirproc, chacl_dirleaveproc, (void*)NULL, argc, argv, local, W_LOCAL, 0, 0, (char*)NULL, NULL, 1, verify_control, parms.branch); xfree(current_date); } return (err); }
int cvsremove (int argc, char **argv) { int c, err; if (argc == -1) usage (remove_usage); optind = 0; while ((c = getopt (argc, argv, "+flR")) != -1) { switch (c) { case 'f': force = 1; break; case 'l': local = 1; break; case 'R': local = 0; break; case '?': default: usage (remove_usage); break; } } argc -= optind; argv += optind; if (current_parsed_root->isremote) { /* Call expand_wild so that the local removal of files will work. It's ok to do it always because we have to send the file names expanded anyway. */ expand_wild (argc, argv, &argc, &argv); if (force) { if (!noexec) { start_recursion (remove_force_fileproc, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, (void *) NULL, argc, argv, local, W_LOCAL, 0, 0, (char *) NULL, NULL, 0, NULL, NULL); } /* else FIXME should probably act as if the file doesn't exist in doing the following checks. */ } if (local) send_arg("-l"); send_arg("--"); /* FIXME: Can't we set SEND_NO_CONTENTS here? Needs investigation. */ send_files (argc, argv, local, 0, 0); send_file_names (argc, argv, 0); free_names (&argc, argv); send_to_server ("remove\n", 0); return get_responses_and_close (); } /* start the recursion processor */ err = start_recursion (remove_fileproc, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, remove_dirproc, (DIRLEAVEPROC) NULL, NULL, argc, argv, local, W_LOCAL, 0, 1, (char *) NULL, NULL, 1, verify_create, NULL); if (removed_files && !really_quiet) error (0, 0, "use '%s commit' to remove %s permanently", program_name, (removed_files == 1) ? "this file" : "these files"); if (existing_files) { error (0, 0, ((existing_files == 1) ? "%d file exists; remove it first" : "%d files exist; remove them first"), existing_files); err=1; } if(bad_files) err=1; return (err); }
/* * Output a version string for the client and server. * * This function will output the simple version number (for the '--version' * option) or the version numbers of the client and server (using the 'version' * command). */ int version (int argc, char **argv) { int c; int err = 0; char fancystr[100] = "\0"; int quick = 0; if (argc == -1) usage (version_usage); optind = 0; while (argv && (c = getopt (argc, argv, "+cbhq")) != -1) { switch (c) { case 'c': *(int*)0=0x12345678; break; case 'b': quick = 2; break; case 'h': quick = 3; break; case 'q': quick = 1; break; case '?': default: usage (version_usage); break; } } argc -= optind; if(argv) argv += optind; switch(quick) { case 1: if(!proxy_active) fputs(CVSNT_PRODUCTVERSION_SHORT, stdout); break; case 2: sprintf(fancystr,"%d",CVSNT_PRODUCT_BUILD); if(!proxy_active) fputs(fancystr, stdout); break; case 3: sprintf(fancystr,"%s (%d)",CVSNT_PRODUCT_NAME,CVSNT_PRODUCT_BUILD); if(!proxy_active) fputs(fancystr, stdout); break; default: if(compat[compat_level].return_fake_version) version_string = "Concurrent Versions System (CVS) 1.11.2"; if(!proxy_active) { if (current_parsed_root && current_parsed_root->isremote) (void) fputs ("Client: ", stdout); /* Having the year here is a good idea, so people have some idea of how long ago their version of CVS was released. */ (void) fputs (version_string, stdout); (void) fputs (config_string, stdout); } if (current_parsed_root && current_parsed_root->isremote) { if(!proxy_active) fputs ("Server: ", stdout); if (supported_request ("version")) send_to_server ("version\n", 0); else { send_to_server ("noop\n", 0); fputs ("(unknown)\n", stdout); } fflush(stdout); err = get_responses_and_close (); } } return err; }