Comments
Patch
new file mode 100644
@@ -0,0 +1,171 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "client.h"
+#include "utils.h"
+
+#define HGPATH "hg"
+
+/*
+ * The function will read the header from the command server and will
+ * save it to handle pointer
+ * */
+hg_header *hg_read_header(hg_handle *handle)
+{
+ uint32_t length;
+ char ch_char;
+
+ if(!handle) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if(handle->bytes_on_pipe == 0){
+ if(read(handle->p_read, &ch_char, 1) < 0){
+ return NULL;
+ }
+ if(read(handle->p_read, &length, sizeof(uint32_t)) < 0){
+ return NULL;
+ }
+ handle->header->length = swap_uint32(length);
+ handle->bytes_on_pipe = handle->header->length;
+ switch(ch_char){
+ case 'o':
+ handle->header->channel = o;
+ break;
+ case 'e':
+ handle->header->channel = e;
+ break;
+ case 'r':
+ handle->header->channel = r;
+ break;
+ case 'I':
+ handle->header->channel = I;
+ break;
+ case 'L':
+ handle->header->channel = L;
+ break;
+ default:
+ handle->header->channel = wrong_channel;
+ break;
+ }
+ }
+ return handle->header;
+}
+
+/**
+ * \brief Reading the hello msg from cmd server.
+ *
+ * After the connection, the command server sends a hello message.
+ * The message contains the command server capabilities and the messages
+ * encoding.
+ * \param handle The handle of the connection, wherewith I want to communicate
+ * \retval 0 if succesfull
+ * \retval -1 to indicate an error, with errno set appropriately
+ *
+ * errno can be:
+ * - EINVAL - Invalid argument (handle it's set to a null pointer)
+ * - read(2) command errors
+ * */
+int read_hello(hg_handle *handle)
+{
+ char *buffer;
+ hg_header *ch;
+ int nc;
+
+ if(!handle) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ch = hg_read_header(handle);
+
+ if(ch->length == 0){
+ return -1;
+ }
+
+ buffer = malloc(ch->length + 1);
+
+ if(nc = read(handle->p_read, buffer, ch->length), nc < 0){
+ free(buffer);
+ return -1;
+ }
+ buffer[ch->length] = '\0';
+ handle->bytes_on_pipe -= nc;
+
+ free(buffer);
+
+ return 0;
+}
+
+/*
+ * Open the connection with the mercurial command server.
+ * */
+hg_handle *hg_open(const char *path, char *encoding)
+{
+ hg_handle *handle = malloc(sizeof(hg_handle));
+ handle->header = malloc(sizeof(hg_header));
+ /* len("%s serve --cmdserver pipe --config ui.interactive=True") = 52 */
+ char *command = malloc(strlen(HGPATH) + 53);
+ int wpipe[2];
+ int rpipe[2];
+ int c_write;
+ int c_read;
+ pid_t childpid;
+
+ sprintf(command,
+ "%s serve --cmdserver pipe --config ui.interactive=True",
+ HGPATH);
+
+ if (path){
+ command = realloc(command, strlen(command) + strlen(path) + 5);
+ sprintf(command, "%s -R %s", command, path);
+ }
+
+ if (pipe(wpipe) < 0 || pipe(rpipe) < 0) {
+ return NULL;
+ }
+ handle->p_read = rpipe[0];
+ c_write = rpipe[1];
+ c_read = wpipe[0];
+ handle->p_write = wpipe[1];
+ handle->protect = 0;
+ handle->bytes_on_pipe = 0;
+
+ if ((childpid = fork()) < 0) {
+ return NULL;
+
+ } else if (childpid == 0) { /* child */
+ close(handle->p_write);
+ close(handle->p_read);
+ if(dup2(c_read, STDIN_FILENO) < 0){
+ return NULL;
+ }
+ close(c_read);
+ if(dup2(c_write, STDOUT_FILENO) < 0){
+ return NULL;
+ }
+ close(c_write);
+ if(execl("/bin/sh", "sh", "-c", command, NULL) < 0){
+ return NULL;
+ }
+ } else { /* parent */
+ close(c_read);
+ close(c_write);
+ }
+
+ free(command);
+
+ if(read_hello(handle) < 0)
+ return NULL;
+
+ handle->out_data = NULL;
+ handle->out_data_size = 0;
+ return handle;
+}
+
@@ -1,4 +1,4 @@
-ifndef _CLIENT_H_
+#ifndef _CLIENT_H_
#define _CLIENT_H_
#include <errno.h>
new file mode 100644
@@ -0,0 +1,17 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "utils.h"
+
+/*
+ * Byte swap unsigned int
+ * */
+uint32_t swap_uint32(uint32_t val)
+{
+ val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF);
+ return (val << 16) | (val >> 16);
+}
+
new file mode 100644
@@ -0,0 +1,13 @@
+#ifndef _UTILS_CHG_H_
+#define _UTILS_CHG_H_
+
+#include <stdint.h>
+
+/**
+ * \brief Byte swap unsigned int
+ * \param val an uint32_t integer
+ * \retval uint32_t the bigendian form of val value
+ * */
+uint32_t swap_uint32(uint32_t val);
+
+#endif