mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
bitkeeper revision 1.1403 (4284c2edzLTGTr4gHmGzYsZMuetTRQ)
Switch to using unix-domain interface on xend instead of http via libcurl. Sundry other merges and fixes. Signed-off-by: Mike Wray <mike.wray@hp.com>
This commit is contained in:
1 parent
21eaf26c10
commit
007d7b6e1e
18 files changed
+1703
-1158
No files matched your search
@@ -754,6 +754,8 @@
|
||||
41a216cav5JJbtDQnusfuMa_1x_Xpw tools/libxutil/debug.h
|
||||
40e9808eyjiahG5uF6AMelNVujBzCg tools/libxutil/enum.c
|
||||
40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/libxutil/enum.h
|
||||
4284c2ecWyadIhHF1u_QSgWqIXkaLA tools/libxutil/fd_stream.c
|
||||
4284c2ecEOOcF6fZUf_NsZzYAoNo-w tools/libxutil/fd_stream.h
|
||||
40e03332p5Dc_owJQRuN72ymJZddFQ tools/libxutil/file_stream.c
|
||||
40e03332jWfB2viAhLSkq1WK0r_iDQ tools/libxutil/file_stream.h
|
||||
40e03332rUjNMGg11n2rN6V4DCrvOg tools/libxutil/gzip_stream.c
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* An IOStream implementation using fds.
|
||||
*/
|
||||
#ifndef __KERNEL__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "allocate.h"
|
||||
#include "fd_stream.h"
|
||||
|
||||
#define MODULE_NAME "fd_stream"
|
||||
#define DEBUG 1
|
||||
//#undef DEBUG
|
||||
#include "debug.h"
|
||||
|
||||
static int fd_read(IOStream *s, void *buf, size_t n);
|
||||
static int fd_write(IOStream *s, const void *buf, size_t n);
|
||||
static int fd_error(IOStream *s);
|
||||
static int fd_close(IOStream *s);
|
||||
static void fd_free(IOStream *s);
|
||||
static int fd_flush(IOStream *s);
|
||||
|
||||
/** Methods used by a fd IOStream. */
|
||||
static const IOMethods fd_methods = {
|
||||
read: fd_read,
|
||||
write: fd_write,
|
||||
error: fd_error,
|
||||
close: fd_close,
|
||||
free: fd_free,
|
||||
flush: fd_flush,
|
||||
};
|
||||
|
||||
/** Get the fd data.
|
||||
*
|
||||
* @param io fd stream
|
||||
* @return data
|
||||
*/
|
||||
static inline FDData * fd_data(IOStream *io){
|
||||
return (FDData *)io->data;
|
||||
}
|
||||
|
||||
/** Test if a stream is a fd stream.
|
||||
*
|
||||
* @param io stream
|
||||
* @return 0 if a fd stream, -EINVAL if not
|
||||
*/
|
||||
int fd_stream_check(IOStream *io){
|
||||
return (io && io->methods == &fd_methods ? 0 : -EINVAL);
|
||||
}
|
||||
|
||||
/** Get the data for a fd stream.
|
||||
*
|
||||
* @param io stream
|
||||
* @param data return value for the data
|
||||
* @return 0 if a fd stream, -EINVAL if not
|
||||
*/
|
||||
int fd_stream_data(IOStream *io, FDData **data){
|
||||
int err = fd_stream_check(io);
|
||||
if(err){
|
||||
*data = NULL;
|
||||
} else {
|
||||
*data = fd_data(io);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/** Write to the underlying fd.
|
||||
*
|
||||
* @param stream input
|
||||
* @param buf where to put input
|
||||
* @param n number of bytes to write
|
||||
* @return number of bytes written
|
||||
*/
|
||||
static int fd_write(IOStream *s, const void *buf, size_t n){
|
||||
FDData *data = fd_data(s);
|
||||
int k;
|
||||
k = write(data->fd, buf, n);
|
||||
return k;
|
||||
}
|
||||
|
||||
/** Read from the underlying stream;
|
||||
*
|
||||
* @param stream input
|
||||
* @param buf where to put input
|
||||
* @param n number of bytes to read
|
||||
* @return number of bytes read
|
||||
*/
|
||||
static int fd_read(IOStream *s, void *buf, size_t n){
|
||||
FDData *data = fd_data(s);
|
||||
int k;
|
||||
k = read(data->fd, buf, n);
|
||||
//printf("> fd_read> buf=%p n=%d --> k=%d\n", buf, n, k);
|
||||
return k;
|
||||
}
|
||||
|
||||
/** Flush the fd (no-op).
|
||||
*
|
||||
* @param s fd stream
|
||||
* @return 0 on success, error code otherwise
|
||||
*/
|
||||
static int fd_flush(IOStream *s){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Check if a fd stream has an error (no-op).
|
||||
*
|
||||
* @param s fd stream
|
||||
* @return 1 if has an error, 0 otherwise
|
||||
*/
|
||||
static int fd_error(IOStream *s){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Close a fd stream.
|
||||
*
|
||||
* @param s fd stream to close
|
||||
* @return result of the close
|
||||
*/
|
||||
static int fd_close(IOStream *s){
|
||||
FDData *data = fd_data(s);
|
||||
return close(data->fd);
|
||||
}
|
||||
|
||||
/** Free a fd stream.
|
||||
*
|
||||
* @param s fd stream
|
||||
*/
|
||||
static void fd_free(IOStream *s){
|
||||
FDData *data = fd_data(s);
|
||||
deallocate(data);
|
||||
}
|
||||
|
||||
/** Create an IOStream for a fd.
|
||||
*
|
||||
* @param fd fd to wtap
|
||||
* @return new IOStream using fd for i/o
|
||||
*/
|
||||
IOStream *fd_stream_new(int fd){
|
||||
int err = -ENOMEM;
|
||||
IOStream *io = NULL;
|
||||
FDData *data = NULL;
|
||||
|
||||
io = ALLOCATE(IOStream);
|
||||
if(!io) goto exit;
|
||||
io->methods = &fd_methods;
|
||||
data = ALLOCATE(FDData);
|
||||
if(!data) goto exit;
|
||||
io->data = data;
|
||||
data->fd = fd;
|
||||
err = 0;
|
||||
exit:
|
||||
if(err){
|
||||
if(io){
|
||||
if(data) deallocate(data);
|
||||
deallocate(io);
|
||||
io = NULL;
|
||||
}
|
||||
}
|
||||
return io;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _XMC_FD_STREAM_H_
|
||||
#define _XMC_FD_STREAM_H_
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include "iostream.h"
|
||||
|
||||
/** Data associated with a fd stream. */
|
||||
typedef struct FDData {
|
||||
/** The socket file descriptor. */
|
||||
int fd;
|
||||
} FDData;
|
||||
|
||||
extern IOStream *fd_stream_new(int fd);
|
||||
extern int fd_stream_data(IOStream *io, FDData **data);
|
||||
extern int fd_stream_check(IOStream *io);
|
||||
|
||||
#endif
|
||||
#endif /* !_XMC_FD_STREAM_H_ */
|
||||
@@ -34,7 +34,7 @@
|
||||
#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
|
||||
|
||||
/** Class of separator characters. */
|
||||
#define sep_class "{}()<>[]@!;"
|
||||
#define sep_class "{}()<>[]!;\"'"
|
||||
|
||||
#define comment_class "#"
|
||||
|
||||
|
||||
+365
-115
@@ -28,6 +28,19 @@
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/random.h>
|
||||
|
||||
int rand(void){
|
||||
int v;
|
||||
get_random_bytes(&v, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#undef free
|
||||
|
||||
/** @file
|
||||
@@ -42,41 +55,51 @@
|
||||
static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int atom_equal(Sxpr x, Sxpr y);
|
||||
static void atom_free(Sxpr obj);
|
||||
static Sxpr atom_copy(Sxpr obj);
|
||||
|
||||
static int string_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int string_equal(Sxpr x, Sxpr y);
|
||||
static void string_free(Sxpr obj);
|
||||
static Sxpr string_copy(Sxpr obj);
|
||||
|
||||
static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int cons_equal(Sxpr x, Sxpr y);
|
||||
static void cons_free(Sxpr obj);
|
||||
static Sxpr cons_copy(Sxpr obj);
|
||||
|
||||
static int null_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int none_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int int_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int err_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
static int nomem_print(IOStream *io, Sxpr obj, unsigned flags);
|
||||
|
||||
/** Type definitions. */
|
||||
static SxprType types[1024] = {
|
||||
[T_NONE] { type: T_NONE, name: "none", print: none_print },
|
||||
[T_NULL] { type: T_NULL, name: "null", print: null_print },
|
||||
[T_UINT] { type: T_UINT, name: "int", print: int_print, },
|
||||
[T_BOOL] { type: T_BOOL, name: "bool", print: bool_print, },
|
||||
[T_ATOM] { type: T_ATOM, name: "atom", print: atom_print,
|
||||
pointer: TRUE,
|
||||
free: atom_free,
|
||||
equal: atom_equal,
|
||||
},
|
||||
[T_STRING] { type: T_STRING, name: "string", print: string_print,
|
||||
pointer: TRUE,
|
||||
free: string_free,
|
||||
equal: string_equal,
|
||||
},
|
||||
[T_CONS] { type: T_CONS, name: "cons", print: cons_print,
|
||||
pointer: TRUE,
|
||||
free: cons_free,
|
||||
equal: cons_equal,
|
||||
},
|
||||
[T_NONE] { .type= T_NONE, .name= "none", .print= none_print },
|
||||
[T_NULL] { .type= T_NULL, .name= "null", .print= null_print },
|
||||
[T_UINT] { .type= T_UINT, .name= "int", .print= int_print, },
|
||||
[T_BOOL] { .type= T_BOOL, .name= "bool", .print= bool_print, },
|
||||
[T_ERR] { .type= T_ERR, .name= "err", .print= err_print, },
|
||||
[T_NOMEM] { .type= T_ERR, .name= "nomem", .print= nomem_print, },
|
||||
[T_ATOM] { .type= T_ATOM, .name= "atom", .print= atom_print,
|
||||
.pointer= TRUE,
|
||||
.free= atom_free,
|
||||
.equal= atom_equal,
|
||||
.copy= atom_copy,
|
||||
},
|
||||
[T_STRING] { .type= T_STRING, .name= "string", .print= string_print,
|
||||
.pointer= TRUE,
|
||||
.free= string_free,
|
||||
.equal= string_equal,
|
||||
.copy= string_copy,
|
||||
},
|
||||
[T_CONS] { .type= T_CONS, .name= "cons", .print= cons_print,
|
||||
.pointer= TRUE,
|
||||
.free= cons_free,
|
||||
.equal= cons_equal,
|
||||
.copy= cons_copy,
|
||||
},
|
||||
};
|
||||
|
||||
/** Number of entries in the types array. */
|
||||
@@ -157,12 +180,29 @@ int objprint(IOStream *io, Sxpr x, unsigned flags){
|
||||
int k = 0;
|
||||
if(!io) return k;
|
||||
if(flags & PRINT_TYPE){
|
||||
k += IOStream_print(io, "%s:", def->name);
|
||||
k += IOStream_print(io, "%s:", def->name);
|
||||
}
|
||||
if(def->pointer && (flags & PRINT_ADDR)){
|
||||
k += IOStream_print(io, "<%p>", get_ptr(x));
|
||||
}
|
||||
k += print_fn(io, x, flags);
|
||||
return k;
|
||||
}
|
||||
|
||||
Sxpr objcopy(Sxpr x){
|
||||
SxprType *def = get_sxpr_type(get_type(x));
|
||||
ObjCopyFn *copy_fn = (def ? def->copy : NULL);
|
||||
Sxpr v;
|
||||
if(copy_fn){
|
||||
v = copy_fn(x);
|
||||
} else if(def->pointer){
|
||||
v = ONOMEM;
|
||||
} else {
|
||||
v = x;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/** General sxpr free function.
|
||||
* Frees an sxpr using the free function for its type.
|
||||
* Free functions must recursively free any subsxprs.
|
||||
@@ -176,11 +216,11 @@ void objfree(Sxpr x){
|
||||
SxprType *def = get_sxpr_type(get_type(x));
|
||||
|
||||
if(def){
|
||||
if(def->free){
|
||||
def->free(x);
|
||||
} else if (def->pointer){
|
||||
hfree(x);
|
||||
}
|
||||
if(def->free){
|
||||
def->free(x);
|
||||
} else if (def->pointer){
|
||||
hfree(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,9 +324,9 @@ Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
|
||||
*/
|
||||
int cons_subset(Sxpr s, Sxpr t){
|
||||
for( ; CONSP(t); t = CDR(t)){
|
||||
if(!CONSP(cons_member(s, CAR(t)))){
|
||||
return 0;
|
||||
}
|
||||
if(!CONSP(cons_member(s, CAR(t)))){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -365,18 +405,27 @@ Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
|
||||
#endif /* USE_GC */
|
||||
|
||||
/** Create a new atom with the given name.
|
||||
* Makes an integer sxpr if the name can be parsed as an int.
|
||||
*
|
||||
* @param name the name
|
||||
* @return new atom
|
||||
*/
|
||||
Sxpr atom_new(char *name){
|
||||
Sxpr n, obj = ONOMEM;
|
||||
long v;
|
||||
|
||||
n = string_new(name);
|
||||
if(NOMEMP(n)) goto exit;
|
||||
obj = HALLOC(ObjAtom, T_ATOM);
|
||||
if(NOMEMP(obj)) goto exit;
|
||||
OBJ_ATOM(obj)->name = n;
|
||||
if(convert_atol(name, &v) == 0){
|
||||
obj = OINT(v);
|
||||
} else {
|
||||
n = string_new(name);
|
||||
if(NOMEMP(n)) goto exit;
|
||||
obj = HALLOC(ObjAtom, T_ATOM);
|
||||
if(NOMEMP(obj)){
|
||||
string_free(n);
|
||||
goto exit;
|
||||
}
|
||||
OBJ_ATOM(obj)->name = n;
|
||||
}
|
||||
exit:
|
||||
return obj;
|
||||
}
|
||||
@@ -392,6 +441,20 @@ void atom_free(Sxpr obj){
|
||||
hfree(obj);
|
||||
}
|
||||
|
||||
/** Copy an atom.
|
||||
*
|
||||
* @param obj to copy
|
||||
*/
|
||||
Sxpr atom_copy(Sxpr obj){
|
||||
Sxpr v;
|
||||
if(OBJ_ATOM(obj)->interned){
|
||||
v = obj;
|
||||
} else {
|
||||
v = atom_new(atom_name(obj));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Print an atom. Prints the atom name.
|
||||
*
|
||||
* @param io stream to print to
|
||||
@@ -400,8 +463,7 @@ void atom_free(Sxpr obj){
|
||||
* @return number of bytes printed
|
||||
*/
|
||||
int atom_print(IOStream *io, Sxpr obj, unsigned flags){
|
||||
//return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
|
||||
return string_print(io, OBJ_ATOM(obj)->name, flags);
|
||||
return objprint(io, OBJ_ATOM(obj)->name, flags);
|
||||
}
|
||||
|
||||
/** Atom equality.
|
||||
@@ -430,13 +492,17 @@ char * atom_name(Sxpr obj){
|
||||
return string_string(OBJ_ATOM(obj)->name);
|
||||
}
|
||||
|
||||
int atom_length(Sxpr obj){
|
||||
return string_length(OBJ_ATOM(obj)->name);
|
||||
}
|
||||
|
||||
/** Get the C string from a string sxpr.
|
||||
*
|
||||
* @param obj string sxpr
|
||||
* @return string
|
||||
*/
|
||||
char * string_string(Sxpr obj){
|
||||
return OBJ_STRING(obj);
|
||||
return OBJ_STRING(obj)->data;
|
||||
}
|
||||
|
||||
/** Get the length of a string.
|
||||
@@ -445,7 +511,7 @@ char * string_string(Sxpr obj){
|
||||
* @return length
|
||||
*/
|
||||
int string_length(Sxpr obj){
|
||||
return strlen(OBJ_STRING(obj));
|
||||
return OBJ_STRING(obj)->len;
|
||||
}
|
||||
|
||||
/** Create a new string. The input string is copied,
|
||||
@@ -456,12 +522,28 @@ int string_length(Sxpr obj){
|
||||
*/
|
||||
Sxpr string_new(char *s){
|
||||
int n = (s ? strlen(s) : 0);
|
||||
return string_new_n(s, n);
|
||||
}
|
||||
|
||||
/** Create a new string. The input string is copied,
|
||||
* and need not be null-terminated.
|
||||
*
|
||||
* @param s characters to put in the string (may be null)
|
||||
* @param n string length
|
||||
* @return new sxpr
|
||||
*/
|
||||
Sxpr string_new_n(char *s, int n){
|
||||
Sxpr obj;
|
||||
obj = halloc(n+1, T_STRING);
|
||||
obj = halloc(sizeof(ObjString) + n + 1, T_STRING);
|
||||
if(!NOMEMP(obj)){
|
||||
char *str = OBJ_STRING(obj);
|
||||
strncpy(str, s, n);
|
||||
str[n] = '\0';
|
||||
char *str = OBJ_STRING(obj)->data;
|
||||
OBJ_STRING(obj)->len = n;
|
||||
if(s){
|
||||
memcpy(str, s, n);
|
||||
str[n] = '\0';
|
||||
} else {
|
||||
memset(str, 0, n + 1);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@@ -474,70 +556,180 @@ void string_free(Sxpr obj){
|
||||
hfree(obj);
|
||||
}
|
||||
|
||||
/** Copy a string.
|
||||
*
|
||||
* @param obj to copy
|
||||
*/
|
||||
Sxpr string_copy(Sxpr obj){
|
||||
return string_new_n(string_string(obj), string_length(obj));
|
||||
}
|
||||
|
||||
/** Determine if a string needs escapes when printed
|
||||
* using the given flags.
|
||||
*
|
||||
* @param str string to check
|
||||
* @param n string length
|
||||
* @param flags print flags
|
||||
* @return 1 if needs escapes, 0 otherwise
|
||||
*/
|
||||
int needs_escapes(char *str, unsigned flags){
|
||||
int needs_escapes(char *str, int n, unsigned flags){
|
||||
char *c;
|
||||
int i;
|
||||
int val = 0;
|
||||
|
||||
if(str){
|
||||
for(c=str; *c; c++){
|
||||
if(in_alpha_class(*c)) continue;
|
||||
if(in_decimal_digit_class(*c)) continue;
|
||||
if(in_class(*c, "/._+:@~-")) continue;
|
||||
val = 1;
|
||||
break;
|
||||
}
|
||||
for(i=0, c=str; i<n; i++, c++){
|
||||
if(in_alpha_class(*c)) continue;
|
||||
if(in_decimal_digit_class(*c)) continue;
|
||||
if(in_class(*c, "/._+:@~-")) continue;
|
||||
val = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//printf("\n> val=%d str=|%s|\n", val, str);
|
||||
return val;
|
||||
}
|
||||
|
||||
char randchar(void){
|
||||
int r;
|
||||
char c;
|
||||
for( ; ; ){
|
||||
r = rand();
|
||||
c = (r >> 16) & 0xff;
|
||||
if('a' <= c && c <= 'z') break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int string_contains(char *s, int s_n, char *k, int k_n){
|
||||
int i, n = s_n - k_n;
|
||||
for(i=0; i < n; i++){
|
||||
if(!memcmp(s+i, k, k_n)) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int string_delim(char *s, int s_n, char *d, int d_n){
|
||||
int i;
|
||||
if(d_n < 4) return -1;
|
||||
memset(d, 0, d_n+1);
|
||||
for(i=0; i<3; i++){
|
||||
d[i] = randchar();
|
||||
}
|
||||
for( ; i < d_n; i++){
|
||||
if(!string_contains(s, s_n, d, i)){
|
||||
return i;
|
||||
}
|
||||
d[i] = randchar();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Print the bytes in a string as-is.
|
||||
*
|
||||
* @param io stream
|
||||
* @param str string
|
||||
* @param n length
|
||||
* @return bytes written or error code
|
||||
*/
|
||||
int _string_print_raw(IOStream *io, char *str, int n){
|
||||
int k = 0;
|
||||
k = IOStream_write(io, str, n);
|
||||
return k;
|
||||
}
|
||||
|
||||
/** Print a string in counted data format.
|
||||
*
|
||||
* @param io stream
|
||||
* @param str string
|
||||
* @param n length
|
||||
* @return bytes written or error code
|
||||
*/
|
||||
int _string_print_counted(IOStream *io, char *str, int n){
|
||||
int k = 0;
|
||||
k += IOStream_print(io, "%c%c%d%c",
|
||||
c_data_open, c_data_count, n, c_data_count);
|
||||
k += IOStream_write(io, str, n);
|
||||
return k;
|
||||
}
|
||||
|
||||
/** Print a string in quoted data format.
|
||||
*
|
||||
* @param io stream
|
||||
* @param str string
|
||||
* @param n length
|
||||
* @return bytes written or error code
|
||||
*/
|
||||
int _string_print_quoted(IOStream *io, char *str, int n){
|
||||
int k = 0;
|
||||
char d[10];
|
||||
int d_n;
|
||||
d_n = string_delim(str, n, d, sizeof(d) - 1);
|
||||
k += IOStream_print(io, "%c%c%s%c",
|
||||
c_data_open, c_data_quote, d, c_data_quote);
|
||||
k += IOStream_write(io, str, n);
|
||||
k += IOStream_print(io, "%c%s%c", c_data_quote, d, c_data_quote);
|
||||
return k;
|
||||
}
|
||||
|
||||
/** Print a string as a quoted string.
|
||||
*
|
||||
* @param io stream
|
||||
* @param str string
|
||||
* @param n length
|
||||
* @return bytes written or error code
|
||||
*/
|
||||
int _string_print_string(IOStream *io, char *str, int n){
|
||||
int k = 0;
|
||||
|
||||
k += IOStream_print(io, "\"");
|
||||
if(str){
|
||||
char *s, *t;
|
||||
for(s = str, t = str + n; s < t; s++){
|
||||
if(*s < ' ' || *s >= 127 ){
|
||||
switch(*s){
|
||||
case '\a': k += IOStream_print(io, "\\a"); break;
|
||||
case '\b': k += IOStream_print(io, "\\b"); break;
|
||||
case '\f': k += IOStream_print(io, "\\f"); break;
|
||||
case '\n': k += IOStream_print(io, "\\n"); break;
|
||||
case '\r': k += IOStream_print(io, "\\r"); break;
|
||||
case '\t': k += IOStream_print(io, "\\t"); break;
|
||||
case '\v': k += IOStream_print(io, "\\v"); break;
|
||||
default:
|
||||
// Octal escape;
|
||||
k += IOStream_print(io, "\\%o", *s);
|
||||
break;
|
||||
}
|
||||
} else if(*s == c_double_quote ||
|
||||
*s == c_single_quote ||
|
||||
*s == c_escape){
|
||||
k += IOStream_print(io, "\\%c", *s);
|
||||
} else {
|
||||
k+= IOStream_print(io, "%c", *s);
|
||||
}
|
||||
}
|
||||
}
|
||||
k += IOStream_print(io, "\"");
|
||||
return k;
|
||||
}
|
||||
|
||||
/** Print a string to a stream, with escapes if necessary.
|
||||
*
|
||||
* @param io stream to print to
|
||||
* @param str string
|
||||
* @param n string length
|
||||
* @param flags print flags
|
||||
* @return number of bytes written
|
||||
*/
|
||||
int _string_print(IOStream *io, char *str, unsigned flags){
|
||||
int _string_print(IOStream *io, char *str, int n, unsigned flags){
|
||||
int k = 0;
|
||||
if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
|
||||
k += IOStream_print(io, str);
|
||||
if((flags & PRINT_COUNTED)){
|
||||
k = _string_print_counted(io, str, n);
|
||||
} else if((flags & PRINT_RAW) || !needs_escapes(str, n, flags)){
|
||||
k = _string_print_raw(io, str, n);
|
||||
} else if(n > 50){
|
||||
k = _string_print_quoted(io, str, n);
|
||||
} else {
|
||||
k += IOStream_print(io, "\"");
|
||||
if(str){
|
||||
char *s;
|
||||
for(s = str; *s; s++){
|
||||
if(*s < ' ' || *s >= 127 ){
|
||||
switch(*s){
|
||||
case '\a': k += IOStream_print(io, "\\a"); break;
|
||||
case '\b': k += IOStream_print(io, "\\b"); break;
|
||||
case '\f': k += IOStream_print(io, "\\f"); break;
|
||||
case '\n': k += IOStream_print(io, "\\n"); break;
|
||||
case '\r': k += IOStream_print(io, "\\r"); break;
|
||||
case '\t': k += IOStream_print(io, "\\t"); break;
|
||||
case '\v': k += IOStream_print(io, "\\v"); break;
|
||||
default:
|
||||
// Octal escape;
|
||||
k += IOStream_print(io, "\\%o", *s);
|
||||
break;
|
||||
}
|
||||
} else if(*s == c_double_quote ||
|
||||
*s == c_single_quote ||
|
||||
*s == c_escape){
|
||||
k += IOStream_print(io, "\\%c", *s);
|
||||
} else {
|
||||
k+= IOStream_print(io, "%c", *s);
|
||||
}
|
||||
}
|
||||
}
|
||||
k += IOStream_print(io, "\"");
|
||||
k = _string_print_string(io, str, n);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
@@ -550,7 +742,14 @@ int _string_print(IOStream *io, char *str, unsigned flags){
|
||||
* @return number of bytes written
|
||||
*/
|
||||
int string_print(IOStream *io, Sxpr obj, unsigned flags){
|
||||
return _string_print(io, OBJ_STRING(obj), flags);
|
||||
return _string_print(io,
|
||||
OBJ_STRING(obj)->data,
|
||||
OBJ_STRING(obj)->len,
|
||||
flags);
|
||||
}
|
||||
|
||||
int string_eq(char *s, int s_n, char *t, int t_n){
|
||||
return (s_n == t_n) && (memcmp(s, t, s_n) == 0);
|
||||
}
|
||||
|
||||
/** Compare an sxpr with a string for equality.
|
||||
@@ -563,9 +762,13 @@ int string_equal(Sxpr x, Sxpr y){
|
||||
int ok = 0;
|
||||
ok = eq(x,y);
|
||||
if(ok) goto exit;
|
||||
ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
|
||||
ok = has_type(y, T_STRING) &&
|
||||
string_eq(OBJ_STRING(x)->data, OBJ_STRING(x)->len,
|
||||
OBJ_STRING(y)->data, OBJ_STRING(y)->len);
|
||||
if(ok) goto exit;
|
||||
ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
|
||||
ok = has_type(y, T_ATOM) &&
|
||||
string_eq(OBJ_STRING(x)->data, OBJ_STRING(x)->len,
|
||||
atom_name(y), atom_length(y));
|
||||
exit:
|
||||
return ok;
|
||||
}
|
||||
@@ -613,15 +816,38 @@ int cons_push(Sxpr *list, Sxpr elt){
|
||||
void cons_free(Sxpr obj){
|
||||
Sxpr next;
|
||||
for(; CONSP(obj); obj = next){
|
||||
next = CDR(obj);
|
||||
objfree(CAR(obj));
|
||||
hfree(obj);
|
||||
next = CDR(obj);
|
||||
objfree(CAR(obj));
|
||||
hfree(obj);
|
||||
}
|
||||
if(!NULLP(obj)){
|
||||
objfree(obj);
|
||||
objfree(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/** Copy a cons. Recursively copies the car and cdr.
|
||||
*
|
||||
* @param obj to copy
|
||||
*/
|
||||
Sxpr cons_copy(Sxpr obj){
|
||||
Sxpr v = ONULL;
|
||||
Sxpr l = ONULL, x = ONONE;
|
||||
for(l = obj; CONSP(l); l = CDR(l)){
|
||||
x = objcopy(CAR(l));
|
||||
if(NOMEMP(x)) goto exit;
|
||||
x = cons_new(x, v);
|
||||
if(NOMEMP(x)) goto exit;
|
||||
v = x;
|
||||
}
|
||||
v = nrev(v);
|
||||
exit:
|
||||
if(NOMEMP(x)){
|
||||
objfree(v);
|
||||
v = ONOMEM;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/** Free a cons and its cdr cells, but not the car sxprs.
|
||||
* Does nothing if called on something that is not a cons.
|
||||
*
|
||||
@@ -630,8 +856,8 @@ void cons_free(Sxpr obj){
|
||||
void cons_free_cells(Sxpr obj){
|
||||
Sxpr next;
|
||||
for(; CONSP(obj); obj = next){
|
||||
next = CDR(obj);
|
||||
hfree(obj);
|
||||
next = CDR(obj);
|
||||
hfree(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -698,26 +924,26 @@ int cons_length(Sxpr obj){
|
||||
*/
|
||||
Sxpr nrev(Sxpr l){
|
||||
if(CONSP(l)){
|
||||
// Iterate down the cells in the list making the cdr of
|
||||
// each cell point to the previous cell. The last cell
|
||||
// is the head of the reversed list.
|
||||
Sxpr prev = ONULL;
|
||||
Sxpr cell = l;
|
||||
Sxpr next;
|
||||
// Iterate down the cells in the list making the cdr of
|
||||
// each cell point to the previous cell. The last cell
|
||||
// is the head of the reversed list.
|
||||
Sxpr prev = ONULL;
|
||||
Sxpr cell = l;
|
||||
Sxpr next;
|
||||
|
||||
while(1){
|
||||
next = CDR(cell);
|
||||
CDR(cell) = prev;
|
||||
if(!CONSP(next)) break;
|
||||
prev = cell;
|
||||
cell = next;
|
||||
}
|
||||
l = cell;
|
||||
while(1){
|
||||
next = CDR(cell);
|
||||
CDR(cell) = prev;
|
||||
if(!CONSP(next)) break;
|
||||
prev = cell;
|
||||
cell = next;
|
||||
}
|
||||
l = cell;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/** Print the null sxpr.
|
||||
/** Print the null sxpr.
|
||||
*
|
||||
* @param io stream to print to
|
||||
* @param obj to print
|
||||
@@ -761,6 +987,30 @@ static int bool_print(IOStream *io, Sxpr obj, unsigned flags){
|
||||
return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
|
||||
}
|
||||
|
||||
/** Print an error.
|
||||
*
|
||||
* @param io stream to print to
|
||||
* @param obj to print
|
||||
* @param flags print flags
|
||||
* @return number of bytes written
|
||||
*/
|
||||
static int err_print(IOStream *io, Sxpr obj, unsigned flags){
|
||||
int err = OBJ_INT(obj);
|
||||
if(err < 0) err = -err;
|
||||
return IOStream_print(io, "[error:%d:%s]", err, strerror(err));
|
||||
}
|
||||
|
||||
/** Print the 'nomem' sxpr.
|
||||
*
|
||||
* @param io stream to print to
|
||||
* @param obj to print
|
||||
* @param flags print flags
|
||||
* @return number of bytes written
|
||||
*/
|
||||
static int nomem_print(IOStream *io, Sxpr obj, unsigned flags){
|
||||
return IOStream_print(io, "[ENOMEM]");
|
||||
}
|
||||
|
||||
int sxprp(Sxpr obj, Sxpr name){
|
||||
return CONSP(obj) && objequal(CAR(obj), name);
|
||||
}
|
||||
@@ -781,8 +1031,8 @@ Sxpr sxpr_name(Sxpr obj){
|
||||
}
|
||||
|
||||
int sxpr_is(Sxpr obj, char *s){
|
||||
if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
|
||||
if(STRINGP(obj)) return !strcmp(string_string(obj), s);
|
||||
if(ATOMP(obj)) return string_eq(atom_name(obj), atom_length(obj), s, strlen(s));
|
||||
if(STRINGP(obj)) return string_eq(string_string(obj), string_length(obj), s, strlen(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -915,11 +1165,11 @@ static int sym_equal_fn(void *x, void *y){
|
||||
*/
|
||||
static void sym_free_fn(HashTable *table, HTEntry *entry){
|
||||
if(entry){
|
||||
objfree(((ObjAtom*)entry->value)->name);
|
||||
HTEntry_free(entry);
|
||||
objfree(((ObjAtom*)entry->value)->name);
|
||||
HTEntry_free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Initialize the symbol table.
|
||||
*
|
||||
* @return 0 on sucess, error code otherwise
|
||||
@@ -929,7 +1179,7 @@ static int init_symbols(void){
|
||||
if(symbols){
|
||||
symbols->key_hash_fn = sym_hash_fn;
|
||||
symbols->key_equal_fn = sym_equal_fn;
|
||||
symbols->entry_free_fn = sym_free_fn;
|
||||
symbols->entry_free_fn = sym_free_fn;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
@@ -950,8 +1200,8 @@ void cleanup_symbols(void){
|
||||
Sxpr get_symbol(char *sym){
|
||||
HTEntry *entry;
|
||||
if(!symbols){
|
||||
if(init_symbols()) return ONOMEM;
|
||||
return ONULL;
|
||||
if(init_symbols()) return ONOMEM;
|
||||
return ONULL;
|
||||
}
|
||||
entry = HashTable_get_entry(symbols, sym);
|
||||
if(entry){
|
||||
@@ -969,10 +1219,10 @@ Sxpr get_symbol(char *sym){
|
||||
Sxpr intern(char *sym){
|
||||
Sxpr symbol = get_symbol(sym);
|
||||
if(NULLP(symbol)){
|
||||
if(!symbols) return ONOMEM;
|
||||
if(!symbols) return ONOMEM;
|
||||
symbol = atom_new(sym);
|
||||
if(!NOMEMP(symbol)){
|
||||
OBJ_ATOM(symbol)->interned = TRUE;
|
||||
OBJ_ATOM(symbol)->interned = TRUE;
|
||||
HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
|
||||
}
|
||||
}
|
||||
|
||||
+176
-160
@@ -52,142 +52,13 @@ typedef struct Sxpr {
|
||||
/** Sxpr type. */
|
||||
TypeCode type;
|
||||
union {
|
||||
/** Sxpr value. */
|
||||
/** Sxpr value. */
|
||||
unsigned long ul;
|
||||
/** Pointer. */
|
||||
/** Pointer. */
|
||||
void *ptr;
|
||||
} v;
|
||||
} Sxpr;
|
||||
|
||||
/** Sxpr type to indicate out of memory. */
|
||||
#define T_NOMEM ((TypeCode)-1)
|
||||
/** The 'unspecified' sxpr. */
|
||||
#define T_NONE ((TypeCode)0)
|
||||
/** The empty list. */
|
||||
#define T_NULL ((TypeCode)1)
|
||||
/** Unsigned integer. */
|
||||
#define T_UINT ((TypeCode)2)
|
||||
/** A string. */
|
||||
#define T_STRING ((TypeCode)3)
|
||||
/** An atom. */
|
||||
#define T_ATOM ((TypeCode)4)
|
||||
/** A boolean. */
|
||||
#define T_BOOL ((TypeCode)5)
|
||||
|
||||
/** A cons (pair or list). */
|
||||
#define T_CONS ((TypeCode)10)
|
||||
|
||||
/** An error. */
|
||||
#define T_ERR ((TypeCode)40)
|
||||
|
||||
/** An atom. */
|
||||
typedef struct ObjAtom {
|
||||
Sxpr name;
|
||||
Hashcode hashcode;
|
||||
int interned;
|
||||
} ObjAtom;
|
||||
|
||||
/** A cons (pair). */
|
||||
typedef struct ObjCons {
|
||||
Sxpr car;
|
||||
Sxpr cdr;
|
||||
} ObjCons;
|
||||
|
||||
/** A vector. */
|
||||
typedef struct ObjVector {
|
||||
int n;
|
||||
Sxpr data[0];
|
||||
} ObjVector;
|
||||
|
||||
/** Flags for sxpr printing. */
|
||||
enum PrintFlags {
|
||||
PRINT_RAW = 0x001,
|
||||
PRINT_TYPE = 0x002,
|
||||
PRINT_PRETTY = 0x004,
|
||||
PRINT_NUM = 0x008,
|
||||
};
|
||||
|
||||
/** An integer sxpr.
|
||||
*
|
||||
* @param ty type
|
||||
* @param val integer value
|
||||
*/
|
||||
#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
|
||||
|
||||
/** A pointer sxpr.
|
||||
* If the pointer is non-null, returns an sxpr containing it.
|
||||
* If the pointer is null, returns ONOMEM.
|
||||
*
|
||||
* @param ty type
|
||||
* @param val pointer
|
||||
*/
|
||||
#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
|
||||
|
||||
/** Make an integer sxpr containing a pointer.
|
||||
*
|
||||
* @param val pointer
|
||||
*/
|
||||
#define PTR(val) OBJP(T_UINT, (void*)(val))
|
||||
|
||||
/** Make an integer sxpr.
|
||||
* @param x value
|
||||
*/
|
||||
#define OINT(x) OBJI(T_UINT, x)
|
||||
|
||||
/** Make an error sxpr.
|
||||
*
|
||||
* @param x value
|
||||
*/
|
||||
#define OERR(x) OBJI(T_ERR, x)
|
||||
|
||||
/** Out of memory constant. */
|
||||
#define ONOMEM OBJI(T_NOMEM, 0)
|
||||
|
||||
/** The `unspecified' constant. */
|
||||
#define ONONE OBJI(T_NONE, 0)
|
||||
|
||||
/** Empty list constant. */
|
||||
#define ONULL OBJI(T_NULL, 0)
|
||||
|
||||
/** False constant. */
|
||||
#define OFALSE OBJI(T_BOOL, 0)
|
||||
|
||||
/** True constant. */
|
||||
#define OTRUE OBJI(T_BOOL, 1)
|
||||
|
||||
/* Recognizers for the various sxpr types. */
|
||||
#define ATOMP(obj) has_type(obj, T_ATOM)
|
||||
#define BOOLP(obj) has_type(obj, T_BOOL)
|
||||
#define CONSP(obj) has_type(obj, T_CONS)
|
||||
#define ERRP(obj) has_type(obj, T_ERR)
|
||||
#define INTP(obj) has_type(obj, T_UINT)
|
||||
#define NOMEMP(obj) has_type(obj, T_NOMEM)
|
||||
#define NONEP(obj) has_type(obj, T_NONE)
|
||||
#define NULLP(obj) has_type(obj, T_NULL)
|
||||
#define STRINGP(obj) has_type(obj, T_STRING)
|
||||
|
||||
#define TRUEP(obj) get_ul(obj)
|
||||
|
||||
/** Convert an sxpr to an unsigned integer. */
|
||||
#define OBJ_UINT(x) get_ul(x)
|
||||
/** Convert an sxpr to an integer. */
|
||||
#define OBJ_INT(x) (int)get_ul(x)
|
||||
|
||||
/* Conversions of sxprs to their values.
|
||||
* No checking is done.
|
||||
*/
|
||||
#define OBJ_STRING(x) ((char*)get_ptr(x))
|
||||
#define OBJ_CONS(x) ((ObjCons*)get_ptr(x))
|
||||
#define OBJ_ATOM(x) ((ObjAtom*)get_ptr(x))
|
||||
#define OBJ_SET(x) ((ObjSet*)get_ptr(x))
|
||||
#define CAR(x) (OBJ_CONS(x)->car)
|
||||
#define CDR(x) (OBJ_CONS(x)->cdr)
|
||||
|
||||
#define CAAR(x) (CAR(CAR(x)))
|
||||
#define CADR(x) (CAR(CDR(x)))
|
||||
#define CDAR(x) (CDR(CAR(x)))
|
||||
#define CDDR(x) (CDR(CDR(x)))
|
||||
|
||||
/** Get the integer value from an sxpr.
|
||||
*
|
||||
* @param obj sxpr
|
||||
@@ -208,22 +79,22 @@ static inline void * get_ptr(Sxpr obj){
|
||||
|
||||
/** Create an sxpr containing a pointer.
|
||||
*
|
||||
* @param type typecode
|
||||
* @param ty typecode
|
||||
* @param val pointer
|
||||
* @return sxpr
|
||||
*/
|
||||
static inline Sxpr obj_ptr(TypeCode type, void *val){
|
||||
return (Sxpr){ type: type, v: { ptr: val } };
|
||||
static inline Sxpr obj_ptr(TypeCode ty, void *val){
|
||||
return (Sxpr){ .type= ty, .v= { .ptr= val } };
|
||||
}
|
||||
|
||||
/** Create an sxpr containing an integer.
|
||||
*
|
||||
* @param type typecode
|
||||
* @param ty typecode
|
||||
* @param val integer
|
||||
* @return sxpr
|
||||
*/
|
||||
static inline Sxpr obj_ul(TypeCode type, unsigned long val){
|
||||
return (Sxpr){ type: type, v: { ul: val } };
|
||||
static inline Sxpr obj_ul(TypeCode ty, unsigned long val){
|
||||
return (Sxpr){ .type= ty, .v= { .ul= val } };
|
||||
}
|
||||
|
||||
/** Get the type of an sxpr.
|
||||
@@ -255,6 +126,160 @@ static inline int eq(Sxpr x, Sxpr y){
|
||||
return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
|
||||
}
|
||||
|
||||
/** The 'unspecified' sxpr. */
|
||||
#define T_NONE ((TypeCode)0)
|
||||
/** The empty list. */
|
||||
#define T_NULL ((TypeCode)1)
|
||||
/** Unsigned integer. */
|
||||
#define T_UINT ((TypeCode)2)
|
||||
/** A string. */
|
||||
#define T_STRING ((TypeCode)3)
|
||||
/** An atom. */
|
||||
#define T_ATOM ((TypeCode)4)
|
||||
/** A boolean. */
|
||||
#define T_BOOL ((TypeCode)5)
|
||||
|
||||
/** A cons (pair or list). */
|
||||
#define T_CONS ((TypeCode)10)
|
||||
|
||||
/** An error. */
|
||||
#define T_ERR ((TypeCode)40)
|
||||
/** Sxpr type to indicate out of memory. */
|
||||
#define T_NOMEM ((TypeCode)41)
|
||||
|
||||
typedef struct ObjString {
|
||||
int len;
|
||||
char data[];
|
||||
} ObjString;
|
||||
|
||||
/** An atom. */
|
||||
typedef struct ObjAtom {
|
||||
Sxpr name;
|
||||
Hashcode hashcode;
|
||||
int interned;
|
||||
} ObjAtom;
|
||||
|
||||
/** A cons (pair). */
|
||||
typedef struct ObjCons {
|
||||
Sxpr car;
|
||||
Sxpr cdr;
|
||||
} ObjCons;
|
||||
|
||||
/** Flags for sxpr printing. */
|
||||
enum PrintFlags {
|
||||
PRINT_RAW = 0x001,
|
||||
PRINT_TYPE = 0x002,
|
||||
PRINT_PRETTY = 0x004,
|
||||
PRINT_COUNTED = 0x008,
|
||||
PRINT_ADDR = 0x010,
|
||||
};
|
||||
|
||||
extern int _string_print(IOStream *io, char *str, int n, unsigned flags);
|
||||
extern int _string_print_raw(IOStream *io, char *str, int n);
|
||||
extern int _string_print_counted(IOStream *io, char *str, int n);
|
||||
extern int _string_print_quoted(IOStream *io, char *str, int n);
|
||||
extern int _string_print_string(IOStream *io, char *str, int n);
|
||||
|
||||
/** An integer sxpr.
|
||||
*
|
||||
* @param ty type
|
||||
* @param val integer value
|
||||
*/
|
||||
#define OBJI(ty, val) obj_ul(ty, val)
|
||||
|
||||
/** Make an integer sxpr.
|
||||
* @param x value
|
||||
*/
|
||||
#define OINT(x) OBJI(T_UINT, x)
|
||||
|
||||
/** Make an error sxpr.
|
||||
*
|
||||
* @param x value
|
||||
*/
|
||||
#define OERR(x) OBJI(T_ERR, x)
|
||||
|
||||
/** Out of memory constant. */
|
||||
#define ONOMEM OBJI(T_NOMEM, 0)
|
||||
|
||||
/** The `unspecified' constant. */
|
||||
#define ONONE OBJI(T_NONE, 0)
|
||||
|
||||
/** Empty list constant. */
|
||||
#define ONULL OBJI(T_NULL, 0)
|
||||
|
||||
/** False constant. */
|
||||
#define OFALSE OBJI(T_BOOL, 0)
|
||||
|
||||
/** True constant. */
|
||||
#define OTRUE OBJI(T_BOOL, 1)
|
||||
|
||||
/** A pointer sxpr.
|
||||
* If the pointer is non-null, returns an sxpr containing it.
|
||||
* If the pointer is null, returns ONOMEM.
|
||||
*
|
||||
* @param ty type
|
||||
* @param val pointer
|
||||
*/
|
||||
static inline Sxpr OBJP(int ty, void *val){
|
||||
return (val ? obj_ptr(ty, val) : ONOMEM);
|
||||
}
|
||||
|
||||
/** Make an integer sxpr containing a pointer.
|
||||
*
|
||||
* @param val pointer
|
||||
*/
|
||||
#define PTR(val) OBJP(T_UINT, (void*)(val))
|
||||
|
||||
/** Allocate some memory and return an sxpr containing it.
|
||||
* Returns ONOMEM if allocation failed.
|
||||
*
|
||||
* @param n number of bytes to allocate
|
||||
* @param ty typecode
|
||||
* @return sxpr
|
||||
*/
|
||||
#define halloc(_n, _ty) OBJP(_ty, allocate(_n))
|
||||
|
||||
/** Allocate an sxpr containing a pointer to the given type.
|
||||
*
|
||||
* @param _ctype type (uses sizeof to determine how many bytes to allocate)
|
||||
* @param _tycode typecode
|
||||
* @return sxpr, ONOMEM if allocation failed
|
||||
*/
|
||||
#define HALLOC(_ctype, _tycode) halloc(sizeof(_ctype), _tycode)
|
||||
|
||||
/* Recognizers for the various sxpr types. */
|
||||
#define ATOMP(obj) has_type(obj, T_ATOM)
|
||||
#define BOOLP(obj) has_type(obj, T_BOOL)
|
||||
#define CONSP(obj) has_type(obj, T_CONS)
|
||||
#define ERRP(obj) has_type(obj, T_ERR)
|
||||
#define INTP(obj) has_type(obj, T_UINT)
|
||||
#define NOMEMP(obj) has_type(obj, T_NOMEM)
|
||||
#define NONEP(obj) has_type(obj, T_NONE)
|
||||
#define NULLP(obj) has_type(obj, T_NULL)
|
||||
#define STRINGP(obj) has_type(obj, T_STRING)
|
||||
|
||||
#define TRUEP(obj) get_ul(obj)
|
||||
|
||||
/** Convert an sxpr to an unsigned integer. */
|
||||
#define OBJ_UINT(x) get_ul(x)
|
||||
/** Convert an sxpr to an integer. */
|
||||
#define OBJ_INT(x) (int)get_ul(x)
|
||||
|
||||
/* Conversions of sxprs to their values.
|
||||
* No checking is done.
|
||||
*/
|
||||
#define OBJ_STRING(x) ((ObjString*)get_ptr(x))
|
||||
#define OBJ_CONS(x) ((ObjCons*)get_ptr(x))
|
||||
#define OBJ_ATOM(x) ((ObjAtom*)get_ptr(x))
|
||||
#define OBJ_SET(x) ((ObjSet*)get_ptr(x))
|
||||
#define CAR(x) (OBJ_CONS(x)->car)
|
||||
#define CDR(x) (OBJ_CONS(x)->cdr)
|
||||
|
||||
#define CAAR(x) (CAR(CAR(x)))
|
||||
#define CADR(x) (CAR(CDR(x)))
|
||||
#define CDAR(x) (CDR(CAR(x)))
|
||||
#define CDDR(x) (CDR(CDR(x)))
|
||||
|
||||
/** Checked version of CAR
|
||||
*
|
||||
* @param x sxpr
|
||||
@@ -273,28 +298,10 @@ static inline Sxpr cdr(Sxpr x){
|
||||
return (CONSP(x) ? CDR(x) : ONULL);
|
||||
}
|
||||
|
||||
/** Allocate some memory and return an sxpr containing it.
|
||||
* Returns ONOMEM if allocation failed.
|
||||
*
|
||||
* @param n number of bytes to allocate
|
||||
* @param ty typecode
|
||||
* @return sxpr
|
||||
*/
|
||||
static inline Sxpr halloc(size_t n, TypeCode ty){
|
||||
return OBJP(ty, allocate(n));
|
||||
}
|
||||
|
||||
/** Allocate an sxpr containing a pointer to the given type.
|
||||
*
|
||||
* @param ty type (uses sizeof to determine how many bytes to allocate)
|
||||
* @param code typecode
|
||||
* @return sxpr, ONOMEM if allocation failed
|
||||
*/
|
||||
#define HALLOC(ty, code) halloc(sizeof(ty), code)
|
||||
|
||||
typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
|
||||
typedef int ObjEqualFn(Sxpr obj, Sxpr other);
|
||||
typedef void ObjFreeFn(Sxpr obj);
|
||||
typedef Sxpr ObjCopyFn(Sxpr obj);
|
||||
|
||||
/** An sxpr type definition. */
|
||||
typedef struct SxprType {
|
||||
@@ -304,6 +311,7 @@ typedef struct SxprType {
|
||||
ObjPrintFn *print;
|
||||
ObjEqualFn *equal;
|
||||
ObjFreeFn *free;
|
||||
ObjCopyFn *copy;
|
||||
} SxprType;
|
||||
|
||||
|
||||
@@ -321,6 +329,7 @@ static inline void hfree(Sxpr x){
|
||||
extern int objprint(IOStream *io, Sxpr x, unsigned flags);
|
||||
extern int objequal(Sxpr x, Sxpr y);
|
||||
extern void objfree(Sxpr x);
|
||||
extern Sxpr objcopy(Sxpr x);
|
||||
|
||||
extern void cons_free_cells(Sxpr obj);
|
||||
extern Sxpr intern(char *s);
|
||||
@@ -341,8 +350,10 @@ extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
|
||||
|
||||
extern Sxpr atom_new(char *name);
|
||||
extern char * atom_name(Sxpr obj);
|
||||
extern int atom_length(Sxpr obj);
|
||||
|
||||
extern Sxpr string_new(char *s);
|
||||
extern Sxpr string_new_n(char *s, int n);
|
||||
extern char * string_string(Sxpr obj);
|
||||
extern int string_length(Sxpr obj);
|
||||
|
||||
@@ -405,15 +416,20 @@ static inline Sxpr mkbool(int b){
|
||||
#define k_true "true"
|
||||
#define k_false "false"
|
||||
|
||||
#define c_var '$'
|
||||
#define c_escape '\\'
|
||||
#define c_single_quote '\''
|
||||
#define c_double_quote '"'
|
||||
#define c_string_open c_double_quote
|
||||
#define c_string_close c_double_quote
|
||||
#define c_data_open '['
|
||||
#define c_data_close ']'
|
||||
#define c_binary '*'
|
||||
|
||||
#define c_data_open '<'
|
||||
#define c_data_quote '<'
|
||||
#define c_data_count '*'
|
||||
//#define c_data_open '['
|
||||
//#define c_data_close ']'
|
||||
//#define c_binary '*'
|
||||
|
||||
#define c_var '$'
|
||||
#define c_eval '!'
|
||||
#define c_concat_open '{'
|
||||
#define c_concat_close '}'
|
||||
|
||||
+631
-580
File diff suppressed because it is too large.
Load diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
|
||||
* Copyright (C) 2001 - 2005 Mike Wray <mike.wray@hp.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
@@ -25,10 +25,13 @@
|
||||
* Sxpr parsing definitions.
|
||||
*/
|
||||
|
||||
/** Size of a parser input buffer.
|
||||
* Tokens read must fit into this size (including trailing null).
|
||||
/** Initial size of a parser input buffer.
|
||||
*/
|
||||
#define PARSER_BUF_SIZE 4096
|
||||
#define PARSER_BUF_SIZE 512
|
||||
|
||||
/** Input buffer size increment (when it's full).
|
||||
*/
|
||||
#define PARSER_BUF_INCREMENT 512
|
||||
|
||||
struct Parser;
|
||||
typedef int ParserStateFn(struct Parser *, char c);
|
||||
@@ -43,13 +46,14 @@ typedef struct ParserState {
|
||||
char *name;
|
||||
} ParserState;
|
||||
|
||||
/** Structure representing an input source for the parser.
|
||||
* Can read from any IOStream implementation.
|
||||
*/
|
||||
typedef struct Parser {
|
||||
/** Initial state function. */
|
||||
ParserStateFn *begin;
|
||||
/** Parse value. */
|
||||
Sxpr val;
|
||||
/** Error reporting stream (null for no reports). */
|
||||
IOStream *error_out;
|
||||
/** End-of-file flag, */
|
||||
int eof;
|
||||
/** Error flag. Non-zero if there has been a read error. */
|
||||
int err;
|
||||
@@ -57,13 +61,11 @@ typedef struct Parser {
|
||||
int line_no;
|
||||
/** Column number of input (reset on new line). */
|
||||
int char_no;
|
||||
/** Lookahead character. */
|
||||
char c;
|
||||
/** Buffer for reading tokens. */
|
||||
char buf[PARSER_BUF_SIZE];
|
||||
/** Size of token buffer. */
|
||||
int buf_n;
|
||||
int buf_i;
|
||||
char *buf;
|
||||
char *buf_end;
|
||||
char *tok;
|
||||
char *tok_end;
|
||||
/** Line the last token started on. */
|
||||
int tok_begin_line;
|
||||
/** Character number the last token started on. */
|
||||
@@ -95,7 +97,7 @@ typedef enum {
|
||||
* @param in parser
|
||||
* @param flags flags mask
|
||||
*/
|
||||
inline static void parser_flags_raise(Parser *in, int flags){
|
||||
inline static void Parser_flags_raise(Parser *in, int flags){
|
||||
in->flags |= flags;
|
||||
}
|
||||
|
||||
@@ -104,7 +106,7 @@ inline static void parser_flags_raise(Parser *in, int flags){
|
||||
* @param in parser
|
||||
* @param flags flags mask
|
||||
*/
|
||||
inline static void parser_flags_lower(Parser *in, int flags){
|
||||
inline static void Parser_flags_lower(Parser *in, int flags){
|
||||
in->flags &= ~flags;
|
||||
}
|
||||
|
||||
@@ -112,7 +114,7 @@ inline static void parser_flags_lower(Parser *in, int flags){
|
||||
*
|
||||
* @param in parser
|
||||
*/
|
||||
inline static void parser_flags_clear(Parser *in){
|
||||
inline static void Parser_flags_clear(Parser *in){
|
||||
in->flags = 0;
|
||||
}
|
||||
|
||||
@@ -121,14 +123,32 @@ extern Parser * Parser_new(void);
|
||||
extern int Parser_input(Parser *p, char *buf, int buf_n);
|
||||
extern int Parser_input_eof(Parser *p);
|
||||
extern int Parser_input_char(Parser *p, char c);
|
||||
extern void set_error_stream(Parser *z, IOStream *error_out);
|
||||
extern void Parser_set_error_stream(Parser *z, IOStream *error_out);
|
||||
|
||||
extern int parse_error_message(Parser *in, char *buf, int n);
|
||||
extern int has_error(Parser *in);
|
||||
extern int at_eof(Parser *in);
|
||||
extern int Parser_error_message(Parser *in, char *buf, int n);
|
||||
extern int Parser_has_error(Parser *in);
|
||||
extern int Parser_at_eof(Parser *in);
|
||||
|
||||
int Parser_ready(Parser *p);
|
||||
Sxpr Parser_get_val(Parser *p);
|
||||
Sxpr Parser_get_all(Parser *p);
|
||||
extern int Parser_ready(Parser *p);
|
||||
extern Sxpr Parser_get_val(Parser *p);
|
||||
extern Sxpr Parser_get_all(Parser *p);
|
||||
|
||||
/* Internal parser api. */
|
||||
void Parser_pop(Parser *p);
|
||||
int Parser_push(Parser *p, ParserStateFn *fn, char *name);
|
||||
int Parser_return(Parser *p);
|
||||
int Parser_at_eof(Parser *p);
|
||||
int Parser_error(Parser *in);
|
||||
int Parser_set_value(Parser *p, Sxpr val);
|
||||
int Parser_intern(Parser *p);
|
||||
int Parser_string(Parser *p);
|
||||
int Parser_data(Parser *p);
|
||||
int Parser_uint(Parser *p);
|
||||
|
||||
char *peek_token(Parser *p);
|
||||
char *copy_token(Parser *p);
|
||||
void new_token(Parser *p);
|
||||
int save_char(Parser *p, char c);
|
||||
int token_len(Parser *p);
|
||||
|
||||
#endif /* ! _XUTIL_SXPR_PARSER_H_ */
|
||||
@@ -49,6 +49,27 @@ inline static const char * convert_set_base(const char *s, int *base){
|
||||
return s;
|
||||
}
|
||||
|
||||
/** Set the sign to use for converting a string to a number.
|
||||
* Value is 1 for positive, -1 for negative.
|
||||
*
|
||||
* @param s input string
|
||||
* @param sign where to put the sign
|
||||
* @return rest of s to parse as a number
|
||||
*/
|
||||
inline static const char * convert_set_sign(const char *s, int *sign){
|
||||
*sign = 1;
|
||||
if(s){
|
||||
if(*s == '+'){
|
||||
*sign = 1;
|
||||
s++;
|
||||
} else if (*s == '-'){
|
||||
*sign = -1;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/** Get the numerical value of a digit in the given base.
|
||||
*
|
||||
* @param c digit character
|
||||
@@ -103,6 +124,40 @@ int convert_atoul(const char *str, unsigned long *val){
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Convert a string to a long by parsing it as a number.
|
||||
* Will accept hex or decimal in usual C syntax.
|
||||
*
|
||||
* @param str input string
|
||||
* @param val where to put the result
|
||||
* @return 0 if converted OK, negative otherwise
|
||||
*/
|
||||
int convert_atol(const char *str, long *val){
|
||||
int err = 0;
|
||||
unsigned long v = 0;
|
||||
int base, sign = 1;
|
||||
const char *s = str;
|
||||
|
||||
if(!s) {
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
s = convert_set_sign(s, &sign);
|
||||
s = convert_set_base(s, &base);
|
||||
for( ; !err && *s; s++){
|
||||
int digit = convert_get_digit(*s, base);
|
||||
if(digit<0){
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
v *= base;
|
||||
v += digit;
|
||||
}
|
||||
if(sign < 0) v = -v;
|
||||
exit:
|
||||
*val = (err ? 0 : v);
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Combine a directory path with a relative path to produce
|
||||
* a new path.
|
||||
*
|
||||
|
||||
@@ -86,6 +86,7 @@ static inline size_t strnlen(const char *s, size_t n){
|
||||
/*============================================================================*/
|
||||
|
||||
extern int convert_atoul(const char *s, unsigned long *v);
|
||||
extern int convert_atol(const char *s, long *v);
|
||||
extern int path_concat(char *s, char *t, char **val);
|
||||
|
||||
#endif /* !_XUTIL_SYS_STRING_H_ */
|
||||
@@ -60,7 +60,6 @@ class Daemon:
|
||||
if not pm: continue
|
||||
xm = xendre.match(pm.group('cmd'))
|
||||
if not xm: continue
|
||||
#print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
|
||||
pids.append(int(pm.group('pid')))
|
||||
return pids
|
||||
|
||||
@@ -313,7 +312,7 @@ class Daemon:
|
||||
os.setuid(pwd.getpwnam(XEND_USER)[2])
|
||||
return 0
|
||||
except KeyError, error:
|
||||
print "Error: no such user '%s'" % XEND_USER
|
||||
print >>sys.stderr, "Error: no such user '%s'" % XEND_USER
|
||||
return 1
|
||||
|
||||
def stop(self):
|
||||
@@ -328,7 +327,6 @@ class Daemon:
|
||||
self.listenChannels()
|
||||
servers = SrvServer.create()
|
||||
self.daemonize()
|
||||
print 'running serverthread...'
|
||||
servers.start()
|
||||
except Exception, ex:
|
||||
print >>sys.stderr, 'Exception starting xend:', ex
|
||||
@@ -342,14 +340,12 @@ class Daemon:
|
||||
|
||||
def listenChannels(self):
|
||||
def virqReceived(virq):
|
||||
print 'virqReceived>', virq
|
||||
eserver.inject('xend.virq', virq)
|
||||
|
||||
self.channelF.setVirqHandler(virqReceived)
|
||||
self.channelF.start()
|
||||
|
||||
def exit(self, rc=0):
|
||||
#reactor.disconnectAll()
|
||||
if self.channelF:
|
||||
self.channelF.stop()
|
||||
# Calling sys.exit() raises a SystemExit exception, which only
|
||||
|
||||
@@ -3,17 +3,13 @@ import StringIO
|
||||
|
||||
from xen.web import reactor, protocol
|
||||
|
||||
from xen.lowlevel import xu
|
||||
|
||||
from xen.xend import sxp
|
||||
from xen.xend import PrettyPrint
|
||||
from xen.xend import EventServer
|
||||
eserver = EventServer.instance()
|
||||
from xen.xend import EventServer; eserver = EventServer.instance()
|
||||
from xen.xend.XendError import XendError
|
||||
|
||||
from xen.xend import XendRoot; xroot = XendRoot.instance()
|
||||
|
||||
DEBUG = 1
|
||||
DEBUG = 0
|
||||
|
||||
class EventProtocol(protocol.Protocol):
|
||||
"""Asynchronous handler for a connected event socket.
|
||||
@@ -30,7 +26,7 @@ class EventProtocol(protocol.Protocol):
|
||||
self.pretty = 0
|
||||
|
||||
# For debugging subscribe to everything and make output pretty.
|
||||
self.subscribe(['*'])
|
||||
#self.subscribe(['*'])
|
||||
self.pretty = 1
|
||||
|
||||
def dataReceived(self, data):
|
||||
@@ -45,10 +41,7 @@ class EventProtocol(protocol.Protocol):
|
||||
except SystemExit:
|
||||
raise
|
||||
except:
|
||||
if DEBUG:
|
||||
raise
|
||||
else:
|
||||
self.send_error()
|
||||
self.send_error()
|
||||
|
||||
def loseConnection(self):
|
||||
if self.transport:
|
||||
@@ -73,7 +66,11 @@ class EventProtocol(protocol.Protocol):
|
||||
return 0
|
||||
|
||||
def send_result(self, res):
|
||||
return self.send_reply(['ok', res])
|
||||
if res is None:
|
||||
resp = ['ok']
|
||||
else:
|
||||
resp = ['ok', res]
|
||||
return self.send_reply(resp)
|
||||
|
||||
def send_error(self):
|
||||
(extype, exval) = sys.exc_info()[:2]
|
||||
@@ -129,7 +126,6 @@ class EventProtocol(protocol.Protocol):
|
||||
|
||||
def op_pretty(self, name, req):
|
||||
self.pretty = 1
|
||||
return ['ok']
|
||||
|
||||
def op_console_disconnect(self, name, req):
|
||||
id = sxp.child_value(req, 'id')
|
||||
@@ -137,7 +133,6 @@ class EventProtocol(protocol.Protocol):
|
||||
raise XendError('Missing console id')
|
||||
id = int(id)
|
||||
self.daemon.console_disconnect(id)
|
||||
return ['ok']
|
||||
|
||||
def op_info(self, name, req):
|
||||
val = ['info']
|
||||
@@ -151,13 +146,11 @@ class EventProtocol(protocol.Protocol):
|
||||
# (sys.subscribe event*)
|
||||
# Subscribe to the events:
|
||||
self.subscribe(v[1:])
|
||||
return ['ok']
|
||||
|
||||
def op_sys_inject(self, name, v):
|
||||
# (sys.inject event)
|
||||
event = v[1]
|
||||
eserver.inject(sxp.name(event), event)
|
||||
return ['ok']
|
||||
|
||||
def op_trace(self, name, v):
|
||||
mode = (v[1] == 'on')
|
||||
@@ -181,6 +174,27 @@ class EventProtocol(protocol.Protocol):
|
||||
import controller
|
||||
controller.DEBUG = (mode == 'on')
|
||||
|
||||
def op_domain_ls(self, name, v):
|
||||
xd = xroot.get_component("xen.xend.XendDomain")
|
||||
return xd.domain_ls()
|
||||
|
||||
def op_domain_configure(self, name, v):
|
||||
domid = sxp.child_value(v, "dom")
|
||||
config = sxp.child_value(v, "config")
|
||||
if domid is None:
|
||||
raise XendError("missing domain id")
|
||||
if config is None:
|
||||
raise XendError("missing domain config")
|
||||
xd = xroot.get_component("xen.xend.XendDomain")
|
||||
xd.domain_configure(domid, config)
|
||||
|
||||
def op_domain_unpause(self, name, v):
|
||||
domid = sxp.child_value(v, "dom")
|
||||
if domid is None:
|
||||
raise XendError("missing domain id")
|
||||
xd = xroot.get_component("xen.xend.XendDomain")
|
||||
xd.domain_unpause(domid)
|
||||
|
||||
class EventFactory(protocol.ServerFactory):
|
||||
"""Asynchronous handler for the event server socket.
|
||||
"""
|
||||
|
||||
@@ -6,6 +6,7 @@ UTIL_LIB = libutil.a
|
||||
UTIL_LIB_SRC =
|
||||
UTIL_LIB_SRC += allocate.c
|
||||
UTIL_LIB_SRC += enum.c
|
||||
UTIL_LIB_SRC += fd_stream.c
|
||||
UTIL_LIB_SRC += file_stream.c
|
||||
UTIL_LIB_SRC += gzip_stream.c
|
||||
UTIL_LIB_SRC += hash_table.c
|
||||
@@ -19,7 +20,7 @@ UTIL_LIB_SRC += sxpr_parser.c
|
||||
UTIL_LIB_SRC += sys_net.c
|
||||
UTIL_LIB_SRC += sys_string.c
|
||||
#UTIL_LIB_SRC += util.c
|
||||
UTIL_LIB_SRC += xdr.c
|
||||
#UTIL_LIB_SRC += xdr.c
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Xfrd.
|
||||
|
||||
+1
-14
@@ -26,18 +26,11 @@ UTIL_LIB_OBJ = $(UTIL_LIB_SRC:.c=.o)
|
||||
XFRD_PROG_OBJ = $(XFRD_PROG_SRC:.c=.o)
|
||||
XFRD_PROG_OBJ += $(UTIL_LIB)
|
||||
|
||||
# Flag controlling whether to use stubs.
|
||||
# Define to use stubs, undefine to use the real Xen functions.
|
||||
#CPPFLAGS += -D _XEN_XFR_STUB_
|
||||
|
||||
ifeq ($(SXPR_DEBUG),1)
|
||||
CPPFLAGS += -D _XEN_XFR_STUB_ -D SXPR_PARSER_MAIN
|
||||
endif
|
||||
|
||||
CC := gcc
|
||||
|
||||
CFLAGS += -Wall -Werror -O3 -fno-strict-aliasing
|
||||
CFLAGS += $(INCLUDES)
|
||||
|
||||
# Make gcc generate dependencies.
|
||||
CFLAGS += -Wp,-MD,.$(@F).d
|
||||
PROG_DEP = .*.d
|
||||
@@ -55,12 +48,6 @@ XFRD_LIBS += -L $(XEN_LIBXUTIL) -lxutil
|
||||
# zlib library.
|
||||
XFRD_LIBS += -lz
|
||||
|
||||
CURL_FLAGS = $(shell curl-config --cflags)
|
||||
CURL_LIBS = $(shell curl-config --libs)
|
||||
CFLAGS += $(CURL_FLAGS)
|
||||
# libcurl libraries.
|
||||
XFRD_LIBS += $(CURL_LIBS)
|
||||
|
||||
#$(warning XFRD_LIBS = $(XFRD_LIBS))
|
||||
|
||||
all: build
|
||||
|
||||
@@ -171,7 +171,7 @@ int Conn_sxpr(Conn *conn, Sxpr *sxpr){
|
||||
dprintf(">\n");
|
||||
if(!conn->parser){
|
||||
conn->parser = Parser_new();
|
||||
set_error_stream(conn->parser, iostdout);
|
||||
Parser_set_error_stream(conn->parser, iostdout);
|
||||
}
|
||||
while(!err && c >= 0 && !Parser_ready(conn->parser)){
|
||||
c = IOStream_getc(conn->in);
|
||||
|
||||
@@ -475,7 +475,6 @@ static int lzi_close(IOStream *io){
|
||||
*/
|
||||
static void lzi_free(IOStream *s){
|
||||
LZIState *state = lzi_state(s);
|
||||
IOStream_free(state->io);
|
||||
LZIState_free(state);
|
||||
s->data = NULL;
|
||||
}
|
||||
@@ -525,8 +524,8 @@ IOStream *lzi_stream_fdopen(int fd, const char *mode){
|
||||
err = 0;
|
||||
exit:
|
||||
if(err){
|
||||
IOStream_free(io);
|
||||
IOStream_free(zio);
|
||||
IOStream_close(io);
|
||||
IOStream_close(zio);
|
||||
zio = NULL;
|
||||
}
|
||||
return zio;
|
||||
|
||||
+171
-232
@@ -1,17 +1,18 @@
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#ifdef _XEN_XFR_STUB_
|
||||
typedef unsigned long u32;
|
||||
#else
|
||||
#include "xc.h"
|
||||
#include "xc_io.h"
|
||||
#endif
|
||||
|
||||
#include "sxpr.h"
|
||||
#include "sxpr_parser.h"
|
||||
#include "file_stream.h"
|
||||
#include "fd_stream.h"
|
||||
|
||||
#include "xen_domain.h"
|
||||
#include "marshal.h"
|
||||
#include "xdr.h"
|
||||
#include "xfrd.h"
|
||||
|
||||
#define MODULE_NAME "XFRD"
|
||||
@@ -33,7 +34,6 @@ int domain_configure(void *data, u32 dom, char *vmconfig, int vmconfig_n){
|
||||
return xen_domain_configure(dom, vmconfig, vmconfig_n);
|
||||
}
|
||||
|
||||
#ifndef _XEN_XFR_STUB_
|
||||
static int xc_handle = 0;
|
||||
|
||||
int xcinit(void){
|
||||
@@ -50,7 +50,6 @@ void xcfini(void){
|
||||
xc_handle = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Write domain state.
|
||||
*
|
||||
@@ -62,31 +61,6 @@ int xen_domain_snd(Conn *xend, IOStream *io,
|
||||
char *vmconfig, int vmconfig_n,
|
||||
int live, int resource){
|
||||
int err = 0;
|
||||
#ifdef _XEN_XFR_STUB_
|
||||
char buf[1024];
|
||||
int n, k, d, buf_n;
|
||||
dprintf("> dom=%d\n", dom);
|
||||
err = marshal_uint32(io, dom);
|
||||
if(err) goto exit;
|
||||
err = marshal_string(io, vmconfig, vmconfig_n);
|
||||
if(err) goto exit;
|
||||
n = 32 * 1024 * 1024;
|
||||
n = 32 * 1024;
|
||||
buf_n = sizeof(buf);
|
||||
err = marshal_uint32(io, n);
|
||||
for(k = 0; k < n; k += d){
|
||||
d = n - k;
|
||||
if(d > buf_n) d = buf_n;
|
||||
err = marshal_bytes(io, buf, d);
|
||||
if(err) goto exit;
|
||||
dprintf("> k=%d n=%d\n", k, n);
|
||||
}
|
||||
|
||||
dom = 99;
|
||||
err = domain_suspend(xend, dom);
|
||||
IOStream_close(io);
|
||||
exit:
|
||||
#else
|
||||
XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
|
||||
ioctxt->domain = dom;
|
||||
ioctxt->io = io;
|
||||
@@ -101,7 +75,6 @@ int xen_domain_snd(Conn *xend, IOStream *io,
|
||||
}
|
||||
ioctxt->resource = resource;
|
||||
err = xc_linux_save(xcinit(), ioctxt);
|
||||
#endif
|
||||
dprintf("< err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
@@ -114,25 +87,6 @@ int xen_domain_rcv(IOStream *io,
|
||||
char **vmconfig, int *vmconfig_n,
|
||||
int *configured){
|
||||
int err = 0;
|
||||
#ifdef _XEN_XFR_STUB_
|
||||
char buf[1024];
|
||||
int n, k, d, buf_n;
|
||||
dprintf(">\n");
|
||||
err = unmarshal_uint32(io, dom);
|
||||
if(err) goto exit;
|
||||
err = unmarshal_new_string(io, vmconfig, vmconfig_n);
|
||||
if(err) goto exit;
|
||||
err = unmarshal_uint32(io, &n);
|
||||
buf_n = sizeof(buf);
|
||||
for(k = 0; k < n; k += d){
|
||||
d = n - k;
|
||||
if(d > buf_n) d = buf_n;
|
||||
err = unmarshal_bytes(io, buf, d);
|
||||
if(err) goto exit;
|
||||
dprintf("> k=%d n=%d\n", k, n);
|
||||
}
|
||||
exit:
|
||||
#else
|
||||
XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
|
||||
dprintf(">\n");
|
||||
ioctxt->io = io;
|
||||
@@ -147,137 +101,182 @@ int xen_domain_rcv(IOStream *io,
|
||||
*vmconfig = ioctxt->vmconfig;
|
||||
*vmconfig_n = ioctxt->vmconfig_n;
|
||||
*configured = (ioctxt->flags & XCFLAGS_CONFIGURE);
|
||||
#endif
|
||||
dprintf("< err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "http.h"
|
||||
typedef struct xend {
|
||||
int fd;
|
||||
IOStream *io;
|
||||
Parser *parser;
|
||||
int seeneof;
|
||||
} Xend;
|
||||
|
||||
/** Flag indicating whether we need to initialize libcurl.
|
||||
*/
|
||||
static int do_curl_global_init = 1;
|
||||
|
||||
/** Get a curl handle, initializing libcurl if needed.
|
||||
*
|
||||
* @return curl handle
|
||||
*/
|
||||
static CURL *curlinit(void){
|
||||
if(do_curl_global_init){
|
||||
do_curl_global_init = 0;
|
||||
// Stop libcurl using the proxy. There's a curl option to
|
||||
// set the proxy - but no option to defeat it.
|
||||
unsetenv("http_proxy");
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
}
|
||||
return curl_easy_init();
|
||||
char *xend_server_addr(void){
|
||||
char * val = getenv("XEND_EVENT_ADDR");
|
||||
return (val ? val : "/var/lib/xend/event-socket");
|
||||
}
|
||||
|
||||
/** Curl debug function.
|
||||
/** Open a unix-domain socket to the xend server.
|
||||
*/
|
||||
int curldebug(CURL *curl, curl_infotype ty, char *buf, int buf_n, void *data){
|
||||
// printf("%*s\n", buf_n, buf); /* Does not compile correctly on non 32bit platforms */
|
||||
fwrite(data, buf_n, 1, stdout);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Setup a curl handle with a url.
|
||||
* Creates the url by formatting 'fmt' and the remaining arguments.
|
||||
*
|
||||
* @param pcurl return parameter for the curl handle
|
||||
* @param url url buffer
|
||||
* @param url_n size of url
|
||||
* @param fmt url format string, followed by parameters
|
||||
* @return 0 on success, error code otherwise
|
||||
*/
|
||||
static int curlsetup(CURL **pcurl, struct curl_slist **pheaders, char *url, int url_n, char *fmt, ...){
|
||||
int xend_open_fd(void){
|
||||
struct sockaddr_un addr_un = { .sun_family = AF_UNIX };
|
||||
struct sockaddr *addr = (struct sockaddr*)&addr_un;
|
||||
int addr_n = sizeof(addr_un);
|
||||
int err = 0;
|
||||
va_list args;
|
||||
CURL *curl = NULL;
|
||||
struct curl_slist *headers = NULL;
|
||||
int n = 0;
|
||||
|
||||
curl = curlinit();
|
||||
if(!curl){
|
||||
eprintf("> Could not init libcurl\n");
|
||||
err = -ENOMEM;
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if(fd < 0){
|
||||
err = -errno;
|
||||
perror("socket");
|
||||
goto exit;
|
||||
}
|
||||
url_n -= 1;
|
||||
va_start(args, fmt);
|
||||
n = vsnprintf(url, url_n, fmt, args);
|
||||
va_end(args);
|
||||
if(n <= 0 || n >= url_n){
|
||||
err = -ENOMEM;
|
||||
eprintf("> Out of memory in url\n");
|
||||
strcpy(addr_un.sun_path, xend_server_addr());
|
||||
if(connect(fd, addr, addr_n) < 0){
|
||||
err = -errno;
|
||||
perror("connect");
|
||||
goto exit;
|
||||
}
|
||||
dprintf("> url=%s\n", url);
|
||||
#if DEBUG
|
||||
// Verbose.
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
// Call the debug function on data received.
|
||||
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curldebug);
|
||||
#else
|
||||
// No progress meter.
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
|
||||
// Completely quiet.
|
||||
curl_easy_setopt(curl, CURLOPT_MUTE, 1);
|
||||
#endif
|
||||
// Set the URL.
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
|
||||
headers = curl_slist_append(headers, "Expect:");
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||
exit:
|
||||
if(err && (fd >= 0)){
|
||||
close(fd);
|
||||
}
|
||||
|
||||
exit:
|
||||
if(err && curl){
|
||||
curl_easy_cleanup(curl);
|
||||
curl = NULL;
|
||||
}
|
||||
*pcurl = curl;
|
||||
if (pheaders)
|
||||
*pheaders = headers;
|
||||
return err;
|
||||
return (err ? err : fd);
|
||||
}
|
||||
|
||||
static void curlcleanup(CURL **pcurl, struct curl_slist **pheaders){
|
||||
if (*pcurl)
|
||||
curl_easy_cleanup(*pcurl);
|
||||
if (*pheaders)
|
||||
curl_slist_free_all(*pheaders);
|
||||
*pcurl = NULL;
|
||||
*pheaders = NULL;
|
||||
}
|
||||
/** Make the http request stored in the curl handle and get
|
||||
* the result code from the curl code and the http return code.
|
||||
/** Close a connection to the server.
|
||||
*
|
||||
* @param curl curl handle
|
||||
* @return 0 for success, error code otherwise
|
||||
*/
|
||||
int curlresult(CURL *curl){
|
||||
int err = 0;
|
||||
CURLcode curlcode = 0;
|
||||
long httpcode = 0;
|
||||
* @param xend connection
|
||||
*/
|
||||
void xend_close(Xend *xend){
|
||||
if(!xend) return;
|
||||
close(xend->fd);
|
||||
Parser_free(xend->parser);
|
||||
}
|
||||
|
||||
curlcode = curl_easy_perform(curl);
|
||||
if(curlcode){
|
||||
eprintf("> curlcode=%d\n", curlcode);
|
||||
err = -EINVAL;
|
||||
/** Open a connection to the server.
|
||||
*
|
||||
* @param xend result parameter for the connection
|
||||
* @return 0 on success, negative error code otherwise
|
||||
*/
|
||||
int xend_open(Xend **xend){
|
||||
int err = 0;
|
||||
Xend *val = ALLOCATE(Xend);
|
||||
|
||||
val->fd = xend_open_fd();
|
||||
|
||||
if(val->fd < 0){
|
||||
err = val->fd;
|
||||
goto exit;
|
||||
}
|
||||
curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &httpcode);
|
||||
if(httpcode != HTTP_OK){
|
||||
eprintf("> httpcode=%d\n", (int)httpcode);
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
val->io = fd_stream_new(val->fd);
|
||||
val->parser = Parser_new();
|
||||
exit:
|
||||
if(err) xend_close(val);
|
||||
*xend = (err ? NULL : val);
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Read a response from a server connection.
|
||||
*/
|
||||
int xend_read_resp(Xend *xend, Sxpr *resp){
|
||||
int err = 0;
|
||||
Sxpr val = ONONE;
|
||||
char buf[1024];
|
||||
int buf_n = sizeof(buf), n;
|
||||
|
||||
for( ; ; ){
|
||||
if(Parser_ready(xend->parser)){
|
||||
val = Parser_get_val(xend->parser);
|
||||
goto exit;
|
||||
}
|
||||
if(xend->seeneof){
|
||||
err = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
memset(buf, 0, buf_n);
|
||||
n = IOStream_read(xend->io, buf, 100);
|
||||
if(n <= 0){
|
||||
xend->seeneof = 1;
|
||||
err = Parser_input_eof(xend->parser);
|
||||
} else {
|
||||
err = Parser_input(xend->parser, buf, n);
|
||||
}
|
||||
}
|
||||
exit:
|
||||
*resp = (err < 0 ? ONONE : val);
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Read a response from a server connection and decode the value.
|
||||
*
|
||||
* @param xend server connection
|
||||
* @param resp result parameter for the response value
|
||||
* @return 0 on success, negative error code otherwise
|
||||
*/
|
||||
int xend_read(Xend *xend, Sxpr *resp){
|
||||
int err = 0;
|
||||
Sxpr val = ONONE;
|
||||
|
||||
dprintf(">\n");
|
||||
for( ; ; ){
|
||||
err = xend_read_resp(xend, &val);
|
||||
if(err < 0) goto exit;
|
||||
|
||||
if(sxpr_is(sxpr_name(val), "event")){
|
||||
// We don't care about events, try again.
|
||||
err = 0;
|
||||
continue;
|
||||
} else if(sxpr_is(sxpr_name(val), "err")){
|
||||
eprintf("> "); objprint(iostderr, val, 0); fprintf(stderr, "\n");
|
||||
err = -EINVAL;
|
||||
break;
|
||||
} else {
|
||||
err = 0;
|
||||
val = sxpr_child0(val, ONULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
dprintf("> OK ");
|
||||
objprint(iostdout, val, 0);
|
||||
printf("\n");
|
||||
#endif
|
||||
exit:
|
||||
if(resp){
|
||||
*resp = (err < 0 ? ONONE : val);
|
||||
}
|
||||
dprintf("> err=%d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/** Send a request to the server and return the result value in resp.
|
||||
*
|
||||
* @param xend server connection
|
||||
* @param resp result parameter for the response value
|
||||
* @param format request format followed by args to print
|
||||
* @return 0 on success, negative error code otherwise
|
||||
*/
|
||||
int xend_call(Xend *xend, Sxpr *resp, char *format, ...){
|
||||
va_list args;
|
||||
int err;
|
||||
|
||||
dprintf("> ");
|
||||
va_start(args, format);
|
||||
#ifdef DEBUG
|
||||
vprintf(format, args); printf("\n");
|
||||
#endif
|
||||
err = IOStream_vprint(xend->io, format, args);
|
||||
va_end(args);
|
||||
if(err < 0) goto exit;
|
||||
IOStream_flush(xend->io);
|
||||
err = xend_read(xend, resp);
|
||||
exit:
|
||||
dprintf("> err=%d\n", err);
|
||||
return (err < 0 ? err : 0);
|
||||
}
|
||||
|
||||
/** Get xend to list domains.
|
||||
* We use this to force xend to refresh its domain list.
|
||||
*
|
||||
@@ -285,18 +284,12 @@ int curlresult(CURL *curl){
|
||||
*/
|
||||
int xen_domain_ls(void){
|
||||
int err = 0;
|
||||
CURL *curl = NULL;
|
||||
struct curl_slist *headers = NULL;
|
||||
char url[128] = {};
|
||||
int url_n = sizeof(url);
|
||||
|
||||
dprintf(">\n");
|
||||
err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain", XEND_PORT);
|
||||
Xend *xend = NULL;
|
||||
err = xend_open(&xend);
|
||||
if(err) goto exit;
|
||||
err = curlresult(curl);
|
||||
err = xend_call(xend, NULL, "(domain.ls)");
|
||||
exit:
|
||||
curlcleanup(&curl, &headers);
|
||||
dprintf("< err=%d\n", err);
|
||||
xend_close(xend);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -309,49 +302,18 @@ int xen_domain_ls(void){
|
||||
*/
|
||||
int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n){
|
||||
int err = 0;
|
||||
CURL *curl = NULL;
|
||||
struct curl_slist *headers = NULL;
|
||||
char url[128] = {};
|
||||
int url_n = sizeof(url);
|
||||
struct curl_httppost *form = NULL, *last = NULL;
|
||||
CURLFORMcode formcode = 0;
|
||||
|
||||
Xend *xend = NULL;
|
||||
dprintf("> dom=%u\n", dom);
|
||||
// List domains so that xend will update its domain list and notice the new domain.
|
||||
xen_domain_ls();
|
||||
|
||||
err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
|
||||
// Now configure it.
|
||||
err = xend_open(&xend);
|
||||
if(err) goto exit;
|
||||
|
||||
// Config field - set from vmconfig.
|
||||
formcode = curl_formadd(&form, &last,
|
||||
CURLFORM_COPYNAME, "config",
|
||||
CURLFORM_BUFFER, "config",
|
||||
CURLFORM_BUFFERPTR, vmconfig,
|
||||
CURLFORM_BUFFERLENGTH, vmconfig_n,
|
||||
CURLFORM_CONTENTTYPE, "application/octet-stream",
|
||||
CURLFORM_END);
|
||||
if(formcode){
|
||||
eprintf("> Error adding config field.\n");
|
||||
goto exit;
|
||||
}
|
||||
// Op field.
|
||||
formcode = curl_formadd(&form, &last,
|
||||
CURLFORM_COPYNAME, "op",
|
||||
CURLFORM_COPYCONTENTS, "configure",
|
||||
CURLFORM_END);
|
||||
if(formcode){
|
||||
eprintf("> Error adding op field.\n");
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
// POST the form.
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
|
||||
err = curlresult(curl);
|
||||
err = xend_call(xend, NULL, "(domain.configure (dom %d) (config %*s))",
|
||||
dom, vmconfig_n, vmconfig);
|
||||
exit:
|
||||
curlcleanup(&curl, &headers);
|
||||
if(form) curl_formfree(form);
|
||||
dprintf("< err=%d\n", err);
|
||||
xend_close(xend);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -362,34 +324,11 @@ int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n){
|
||||
*/
|
||||
int xen_domain_unpause(uint32_t dom){
|
||||
int err = 0;
|
||||
CURL *curl = NULL;
|
||||
struct curl_slist *headers = NULL;
|
||||
char url[128] = {};
|
||||
int url_n = sizeof(url);
|
||||
struct curl_httppost *form = NULL, *last = NULL;
|
||||
CURLFORMcode formcode = 0;
|
||||
|
||||
dprintf("> dom=%u\n", dom);
|
||||
|
||||
err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
|
||||
Xend *xend = NULL;
|
||||
err = xend_open(&xend);
|
||||
if(err) goto exit;
|
||||
|
||||
// Op field.
|
||||
formcode = curl_formadd(&form, &last,
|
||||
CURLFORM_COPYNAME, "op",
|
||||
CURLFORM_COPYCONTENTS, "unpause",
|
||||
CURLFORM_END);
|
||||
if(formcode){
|
||||
eprintf("> Error adding op field.\n");
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
// POST the form.
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
|
||||
err = curlresult(curl);
|
||||
err = xend_call(xend, NULL, "(domain.unpause (dom %d))", dom);
|
||||
exit:
|
||||
curlcleanup(&curl, &headers);
|
||||
if(form) curl_formfree(form);
|
||||
dprintf("< err=%d\n", err);
|
||||
xend_close(xend);
|
||||
return err;
|
||||
}
|
||||
+1
-7
@@ -188,7 +188,6 @@ enum {
|
||||
XFR_MAX
|
||||
};
|
||||
|
||||
#ifndef SXPR_PARSER_MAIN
|
||||
/** Short options. Options followed by ':' take an argument. */
|
||||
static char *short_opts = (char[]){
|
||||
OPT_PORT, ':',
|
||||
@@ -213,7 +212,6 @@ static Args _args = {};
|
||||
|
||||
/** Xfrd arguments. */
|
||||
static Args *args = &_args;
|
||||
#endif
|
||||
|
||||
/** Initialize an array element for a constant to its string name. */
|
||||
#define VALDEF(val) { val, #val }
|
||||
@@ -782,7 +780,6 @@ int xfr_save(Args *args, XfrState *state, Conn *xend, char *file){
|
||||
exit:
|
||||
if(io){
|
||||
IOStream_close(io);
|
||||
IOStream_free(io);
|
||||
}
|
||||
if(err){
|
||||
unlink(file);
|
||||
@@ -798,7 +795,7 @@ int xfr_save(Args *args, XfrState *state, Conn *xend, char *file){
|
||||
int xfr_restore(Args *args, XfrState *state, Conn *xend, char *file){
|
||||
int err = 0;
|
||||
IOStream *io = NULL;
|
||||
int configured=0;
|
||||
int configured = 0;
|
||||
|
||||
dprintf("> file=%s\n", file);
|
||||
io = gzip_stream_fopen(file, "rb");
|
||||
@@ -820,7 +817,6 @@ int xfr_restore(Args *args, XfrState *state, Conn *xend, char *file){
|
||||
exit:
|
||||
if(io){
|
||||
IOStream_close(io);
|
||||
IOStream_free(io);
|
||||
}
|
||||
if(err){
|
||||
xfr_error(xend, err);
|
||||
@@ -1215,7 +1211,6 @@ int xfrd_main(Args *args){
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifndef SXPR_PARSER_MAIN
|
||||
/** Parse command-line arguments and call the xfrd main program.
|
||||
*
|
||||
* @param arg argument count
|
||||
@@ -1271,4 +1266,3 @@ int main(int argc, char *argv[]){
|
||||
}
|
||||
return (err ? 1 : 0);
|
||||
}
|
||||
#endif
|
||||