1 /* $OpenBSD: commit.c,v 1.2 2004/07/30 01:49:22 jfb Exp $ */ 2 /* 3 * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 18 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 30 #include <errno.h> 31 #include <stdio.h> 32 #include <fcntl.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <sysexits.h> 37 38 #include "cvs.h" 39 #include "log.h" 40 #include "proto.h" 41 42 43 44 45 static char* cvs_commit_openmsg (const char *); 46 47 48 49 50 /* 51 * cvs_commit() 52 * 53 * Handler for the `cvs commit' command. 54 */ 55 56 int 57 cvs_commit(int argc, char **argv) 58 { 59 int ch, recurse; 60 char *msg, *mfile; 61 62 recurse = 1; 63 mfile = NULL; 64 msg = NULL; 65 66 while ((ch = getopt(argc, argv, "F:flm:R")) != -1) { 67 switch (ch) { 68 case 'F': 69 mfile = optarg; 70 break; 71 case 'f': 72 recurse = 0; 73 break; 74 case 'l': 75 recurse = 0; 76 break; 77 case 'm': 78 msg = optarg; 79 break; 80 case 'R': 81 recurse = 1; 82 break; 83 default: 84 return (EX_USAGE); 85 } 86 } 87 88 if ((msg != NULL) && (mfile != NULL)) { 89 cvs_log(LP_ERR, "the -F and -m flags are mutually exclusive"); 90 return (EX_USAGE); 91 } 92 93 if ((mfile != NULL) && (msg = cvs_commit_openmsg(mfile)) == NULL) 94 return (EX_DATAERR); 95 96 argc -= optind; 97 argv += optind; 98 99 return (0); 100 } 101 102 103 /* 104 * cvs_commit_openmsg() 105 * 106 * Open the file specified by <path> and allocate a buffer large enough to 107 * hold all of the file's contents. The returned value must later be freed 108 * using the free() function. 109 * Returns a pointer to the allocated buffer on success, or NULL on failure. 110 */ 111 112 static char* 113 cvs_commit_openmsg(const char *path) 114 { 115 int fd; 116 size_t sz; 117 char *msg; 118 struct stat st; 119 120 if (stat(path, &st) == -1) { 121 cvs_log(LP_ERRNO, "failed to stat `%s'", path); 122 return (NULL); 123 } 124 125 sz = st.st_size + 1; 126 127 msg = (char *)malloc(sz); 128 if (msg == NULL) { 129 cvs_log(LP_ERRNO, "failed to allocate message buffer"); 130 return (NULL); 131 } 132 133 fd = open(path, O_RDONLY, 0); 134 if (fd == -1) { 135 cvs_log(LP_ERRNO, "failed to open message file `%s'", path); 136 return (NULL); 137 } 138 139 if (read(fd, msg, sz - 1) == -1) { 140 cvs_log(LP_ERRNO, "failed to read CVS commit message"); 141 return (NULL); 142 } 143 msg[sz - 1] = '\0'; 144 145 return (msg); 146 } 147