/*create io handler*/
new_io_h = (io_handler *) calloc(1, sizeof(*new_io_h));
if (!new_io_h)
- return set_error(g_cc, ENOMEM, posix_error, "Not enough memory");
+ return set_error(g_cc, ENOMEM, POSIX_ERROR, "Not enough memory");
/* allocate memory and initialize io content*/
if ((err = init_io_content(g_cc ,new_io_h))){
}
if (!io_cc)
- return set_error(glb_cc, EINVAL, posix_error,
+ return set_error(glb_cc, EINVAL, POSIX_ERROR,
"IO handler not initialized");
done = 0;
ar.ent = (struct hostent *) calloc (1, sizeof(struct hostent));
if (ar.ent == NULL)
- return set_error(cc, ENOMEM, posix_error, "Not enough memory");
+ return set_error(cc, ENOMEM, POSIX_ERROR, "Not enough memory");
switch (err = asyn_getservbyname(ipver, &ar, host, NULL)) {
case NETDB_SUCCESS:
err = 0;
break;
case TRY_AGAIN:
- err = update_error(glb_cc, ETIMEDOUT, posix_error,
+ err = update_error(glb_cc, ETIMEDOUT, POSIX_ERROR,
"Cannot resolve the server hostname (%s)", host);
goto end;
case NETDB_INTERNAL:
- err = update_error(glb_cc, errno, posix_error,
+ err = update_error(glb_cc, errno, POSIX_ERROR,
"Cannot resolve the server hostname (%s)", host);
continue;
default:
- err = update_error(glb_cc, err, netdb_error,
+ err = update_error(glb_cc, err, NETDB_ERROR,
"Cannot resolve the server hostname (%s)", host);
continue;
}
end:
if (err) /* XXX: rather invent own error */
- err = update_error(glb_cc, ECONNREFUSED, posix_error,
+ err = update_error(glb_cc, ECONNREFUSED, POSIX_ERROR,
"Failed to make network connection to server %s", host);
if (ar.ent != NULL)
a_len = sizeof (struct sockaddr_in6);
break;
default:
- return set_error(glb_cc, EINVAL, posix_error,
+ return set_error(glb_cc, EINVAL, POSIX_ERROR,
"Unsupported address type (%d)", addrtype);
break;
}
sock = socket(a.ss_family, SOCK_STREAM, 0);
if (sock == -1)
- return set_error(glb_cc, errno, posix_error,
+ return set_error(glb_cc, errno, POSIX_ERROR,
"Failed to create network socket");
err = connect(sock,(struct sockaddr *) &a, a_len);
/* XXX timeouts missing */
if (err) {
- return set_error(glb_cc, errno, posix_error,
+ return set_error(glb_cc, errno, POSIX_ERROR,
"Failed to open network connection");
}
return EINVAL; /* XXX Should rather be a CANL error */
if (!io_cc)
- return set_error(cc, EINVAL, posix_error, "IO handler not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");
io_cc->sock = new_fd;
}
if (!io)
- return set_error(cc, EINVAL, posix_error, "IO handler not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");
if (io_cc->authn_mech.ctx) {
mech = find_mech(io_cc->authn_mech.oid);
}
if (!io_cc)
- return set_error(glb_cc, EINVAL, posix_error, "Invalid io handler");
+ return set_error(glb_cc, EINVAL, POSIX_ERROR, "Invalid io handler");
canl_io_close(cc, io);
return -1;
if (!io) {
- set_error(cc, EINVAL, posix_error, "IO handler not initialized");
+ set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");
return -1;
}
if (io_cc->authn_mech.ctx == NULL)
- return set_error(cc, EINVAL, posix_error, "Connection not secured");
+ return set_error(cc, EINVAL, POSIX_ERROR, "Connection not secured");
if (!buffer || !size) {
- set_error(cc, EINVAL, posix_error, "No memory to write into");
+ set_error(cc, EINVAL, POSIX_ERROR, "No memory to write into");
return -1;
}
return -1;
if (!io) {
- set_error(cc, EINVAL, posix_error, "IO handler not initialized");
+ set_error(cc, EINVAL, POSIX_ERROR, "IO handler not initialized");
return -1;
}
if (io_cc->authn_mech.ctx == NULL)
- return set_error(cc, EINVAL, posix_error, "Connection not secured");
+ return set_error(cc, EINVAL, POSIX_ERROR, "Connection not secured");
if (!buffer || !size) {
- set_error(cc, EINVAL, posix_error, "No memory to read from");
+ set_error(cc, EINVAL, POSIX_ERROR, "No memory to read from");
return -1;
}
if (!cc)
return EINVAL;
if(!cert)
- return set_error(glb_cc, EINVAL, posix_error, "invalid"
+ return set_error(glb_cc, EINVAL, POSIX_ERROR, "invalid"
"parameter value");
err = do_set_ctx_own_cert(glb_cc, cert, chain, key);
if (!cc)
return EINVAL;
if(!cert ) {
- set_error(glb_cc, EINVAL, posix_error, "invalid parameter value");
+ set_error(glb_cc, EINVAL, POSIX_ERROR, "invalid parameter value");
return EINVAL;
}
typedef void *canl_ctx;
typedef void *canl_principal;
-typedef long canl_err_code;
+typedef unsigned long canl_err_code;
typedef char (*canl_password_callback)(canl_ctx cc, void *userdata);
if (!cc->cert_key){
cc->cert_key = (cert_key_store *) calloc(1, sizeof(*(cc->cert_key)));
if (!cc->cert_key) {
- return set_error(cc, ENOMEM, posix_error, "not enought memory"
+ return set_error(cc, ENOMEM, POSIX_ERROR, "not enought memory"
" for the certificate storage");
}
}
key_file = fopen(key, "rb");
if (!key_file) {
err = errno;
- set_error(cc, err, posix_error, "cannot open file with key");
+ set_error(cc, err, POSIX_ERROR, "cannot open file with key");
return err;
}
*to = PEM_read_PrivateKey(key_file, NULL, NULL, NULL);
if (!(*to)) {
ssl_err = ERR_peek_error();
- set_error(cc, ssl_err, ssl_error, "error while writing key to context");
+ set_error(cc, ssl_err, SSL_ERROR, "error while writing key to context");
goto end;
}
if (fclose(key_file)){
err = errno;
- set_error(cc, err, posix_error, "cannot close file with key");
+ set_error(cc, err, POSIX_ERROR, "cannot close file with key");
return errno;
}
return 0;
end:
if (fclose(key_file)){
err = errno;
- update_error(cc, errno, posix_error, "cannot close file with key");
+ update_error(cc, errno, POSIX_ERROR, "cannot close file with key");
}
return 1;
}
cert_file = fopen(cert, "rb");
if (!cert_file) {
err = errno;
- set_error(cc, err, posix_error, "cannot open file with cert");
+ set_error(cc, err, POSIX_ERROR, "cannot open file with cert");
return err;
}
*to = PEM_read_X509(cert_file, NULL, NULL, NULL);
if (!(*to)) {
ssl_err = ERR_get_error();
- set_error(cc, ssl_err, ssl_error, "error while writing certificate"
+ set_error(cc, ssl_err, SSL_ERROR, "error while writing certificate"
" to context");
goto end;
}
if (fclose(cert_file)){
err = errno;
- set_error(cc, err, posix_error, "cannot close file with certificate");
+ set_error(cc, err, POSIX_ERROR, "cannot close file with certificate");
return errno;
}
return 0;
end:
if (fclose(cert_file)){
err = errno;
- update_error(cc, errno, posix_error, "cannot close file with certificate");
+ update_error(cc, errno, POSIX_ERROR, "cannot close file with certificate");
}
return 1;
}
#define ERR_CODE_LEN 512
-static CANL_ERROR resolve_error(glb_ctx *cc, unsigned long err_code,
- CANL_ERROR_ORIGIN err_orig);
+static canl_err_code resolve_error(glb_ctx *cc, unsigned long err_code,
+ canl_error_origin err_orig);
static void get_error_string(glb_ctx *cc, char *code_str);
/* TODO: produce error messages immediately (to chain them) */
/* Save error message into err_msg
* use NULL for empty err_format */
-int update_error (glb_ctx *cc, unsigned long err_code, CANL_ERROR_ORIGIN err_orig,
- const char *err_format, ...)
+canl_err_code update_error (glb_ctx *cc, unsigned long err_code,
+ canl_error_origin err_orig,
+ const char *err_format, ...)
{
unsigned int err_msg_len = 0;
unsigned int err_msg_sum = 0; // sum of msg and format lengths
}
/* If there was some error message in ctx, delete it and make new */
-int set_error (glb_ctx *cc, unsigned long err_code, CANL_ERROR_ORIGIN err_orig,
+canl_err_code set_error (glb_ctx *cc, unsigned long err_code,
+ canl_error_origin err_orig,
const char *err_format, ...)
{
va_list ap;
free(cc->err_msg);
cc->err_msg = NULL;
cc->err_code = 0;
- cc->err_orig = unknown_error;
+ cc->err_orig = UNKNOWN_ERROR;
}
/* Provide human readable information about errors */
canl_get_error(canl_ctx cc, char **reason)
{
int err = 0;
- int e_orig = unknown_error;
+ int e_orig = UNKNOWN_ERROR;
int error_length = 0;
char *new_error = NULL;
char code_str[ERR_CODE_LEN];
new_error = (char *) malloc ((error_length) * sizeof (char));
if (!new_error) {
err = ENOMEM;
- e_orig = posix_error;
+ e_orig = POSIX_ERROR;
goto end;
}
char *new_str = NULL;
switch (cc->err_orig) {
- case ssl_error:
+ case SSL_ERROR:
ERR_error_string_n(cc->err_code, code_str,
ERR_CODE_LEN);
break;
- case posix_error:
+ case POSIX_ERROR:
new_str = strerror(cc->err_code);
if (new_str) {
strncpy(code_str, new_str,
ERR_CODE_LEN);
code_str[ERR_CODE_LEN - 1] = '\0';
}
- case netdb_error:
+ case NETDB_ERROR:
new_str = (char *) hstrerror(cc->err_code);
if (new_str) {
strncpy(code_str, new_str,
break;
default:
snprintf(code_str, ERR_CODE_LEN,
- "Unknown error origin (%d) of error %d!",
- cc->err_orig, cc->err_code)
+ "Unknown error origin (%u) of error %lu!",
+ cc->err_orig, cc->err_code);
break;
}
}
-long
+canl_err_code
canl_get_error_code(canl_ctx cc)
{
glb_ctx *ctx = (glb_ctx*) cc;
/*if the error code is known to canl, assign appropriate canl code
TODO go through ssl errors and assign appr. canl code
?preserve original one? */
-static CANL_ERROR resolve_error(glb_ctx *cc, unsigned long err_code,
- CANL_ERROR_ORIGIN err_orig)
+static canl_err_code resolve_error(glb_ctx *cc, unsigned long err_code,
+ canl_error_origin err_orig)
{
- if (err_orig == canl_error) {
+ if (err_orig == CANL_ERROR) {
cc->err_code = err_code;
- cc->err_orig = canl_error;
+ cc->err_orig = CANL_ERROR;
return (int)err_code;
}
- if (err_orig == posix_error) {
+ if (err_orig == POSIX_ERROR) {
cc->err_code = err_code;
- cc->err_orig = posix_error;
+ cc->err_orig = POSIX_ERROR;
return (int)err_code;
}
- if (err_orig == netdb_error) {
+ if (err_orig == NETDB_ERROR) {
cc->err_code = err_code;
- cc->err_orig = netdb_error;
+ cc->err_orig = NETDB_ERROR;
return (int)err_code;
}
switch (err_code) {
- /*TODO map ssl_errors on canl errors*/
+ /*TODO map SSL_ERRORs on canl errors*/
default:
cc->err_code = err_code;
cc->err_orig = err_orig;
#ifndef _CANL_LOCL_H
#define _CANL_LOCL_H
-
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/time.h>
-
#include <arpa/inet.h>
#include <sys/socket.h>
#include <string.h>
#include "sslutils.h"
-
-
#include "canl.h"
typedef struct canl_err_desc {
- CANL_ERROR code;
+ canl_error code;
const char *desc;
unsigned long openssl_lib;
unsigned long openssl_reason;
} canl_err_desc;
-typedef enum _CANL_ERROR_ORIGIN
-{
- unknown_error = 0,
- posix_error = 1,
- ssl_error,
- canl_error,
- netdb_error,
-} CANL_ERROR_ORIGIN;
+typedef enum canl_error_origin {
+ UNKNOWN_ERROR = 0,
+ POSIX_ERROR,
+ SSL_ERROR,
+ CANL_ERROR,
+ NETDB_ERROR,
+} canl_error_origin;
typedef enum _CANL_AUTH_MECHANISM
{
{
char * err_msg;
unsigned long err_code;
- CANL_ERROR_ORIGIN err_orig;
+ canl_error_origin err_orig;
cert_key_store *cert_key;
} glb_ctx;
extern struct canl_mech canl_mech_ssl;
void reset_error (glb_ctx *cc, unsigned long err_code);
-int set_error (glb_ctx *cc, unsigned long err_code, CANL_ERROR_ORIGIN err_orig,
- const char *err_format, ...);
-int update_error (glb_ctx *cc, unsigned long err_code, CANL_ERROR_ORIGIN err_orig,
- const char *err_format, ...);
+canl_err_code set_error (glb_ctx *cc, unsigned long err_code,
+ canl_error_origin err_orig, const char *err_format, ...);
+canl_err_code update_error (glb_ctx *cc, unsigned long err_code,
+ canl_error_origin err_orig, const char *err_format, ...);
void free_hostent(struct hostent *h); //TODO is there some standard funcion to free hostent?
int asyn_getservbyname(int a_family, asyn_result *ares_result,char const *name,
struct timeval *timeout);
ssl_ctx = SSL_CTX_new(SSLv23_method());
if (!ssl_ctx)
- return set_error(cc, ERR_get_error(), ssl_error,
+ return set_error(cc, ERR_get_error(), SSL_ERROR,
"Cannot initialize SSL context");
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2);
//err = SSL_CTX_set_cipher_list(ssl_ctx, "ALL:!LOW:!EXP:!MD5:!MD2");
err = SSL_CTX_set_cipher_list(ssl_ctx, "ALL");
if (!err) {
- err = set_error(cc, ERR_get_error(), ssl_error,
+ err = set_error(cc, ERR_get_error(), SSL_ERROR,
"No cipher to use");
goto end;
}
return EINVAL;
if (ssl_ctx == NULL)
- return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized");
#if 0
err = proxy_get_filenames(0, &ca_cert_fn, &ca_cert_dirn, &user_proxy_fn,
ssl = SSL_new(ssl_ctx);
if (ssl == NULL)
- return set_error(cc, ERR_get_error(), ssl_error,
+ return set_error(cc, ERR_get_error(), SSL_ERROR,
"Failed to create SSL connection context");
/* XXX: should be only defined on the SSL level: */
err = SSL_CTX_use_certificate(ssl_ctx, cc->cert_key->cert);
if (err != 1) {
ssl_err = ERR_get_error();
- e_orig = ssl_error;
+ e_orig = SSL_ERROR;
goto end;
}
else
err = SSL_CTX_use_PrivateKey(ssl_ctx, cc->cert_key->key);
if (err != 1) {
ssl_err = ERR_get_error();
- e_orig = ssl_error;
+ e_orig = SSL_ERROR;
goto end;
}
else
}
}
else {
- set_error(cc, err, unknown_error, "server key or certificate missing");
+ set_error(cc, err, UNKNOWN_ERROR, "server key or certificate missing");
return 1;
}
/*Make sure the key and certificate file match*/
if ( (err = SSL_CTX_check_private_key(ssl_ctx)) != 1) {
ssl_err = ERR_get_error();
- e_orig = ssl_error;
+ e_orig = SSL_ERROR;
set_error(cc, ssl_err, e_orig, "Private key does not match"
" the certificate public key");
return 1;
return EINVAL;
if (ssl_ctx == NULL)
- return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized");
ssl = SSL_new(ssl_ctx);
if (ssl == NULL)
- return set_error(cc, ERR_get_error(), ssl_error,
+ return set_error(cc, ERR_get_error(), SSL_ERROR,
"Failed to create SSL connection context");
SSL_set_connect_state(ssl);
err = SSL_CTX_use_PrivateKey(ssl_ctx, cc->cert_key->key);
if (err != 1) {
ssl_err = ERR_get_error();
- e_orig = ssl_error;
+ e_orig = SSL_ERROR;
goto end;
}
}
err = SSL_CTX_use_certificate(ssl_ctx, cc->cert_key->cert);
if (err != 1) {
ssl_err = ERR_get_error();
- e_orig = ssl_error;
+ e_orig = SSL_ERROR;
goto end;
}
}
goto end;
}
if (ssl == NULL)
- return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized");
ctx = SSL_get_SSL_CTX(ssl);
}
}
else
- return set_error(cc, CANL_ERR_unknownMsg, canl_error,
+ return set_error(cc, CANL_ERR_unknownMsg, CANL_ERROR,
"Common name entry does not exist"); //TODO check
}
if (correspond)
return 0;
else {
- return set_error(cc, CANL_ERR_unknownMsg, canl_error,
+ return set_error(cc, CANL_ERR_unknownMsg, CANL_ERROR,
"Cannot validate server hostname against its certificate" );
//TODO check
}
goto end;
}
if (auth_ctx == NULL)
- return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized");
ctx = SSL_get_SSL_CTX(ssl);
int ret = -1, ret2 = -1;
unsigned long ssl_err = 0;
int err = 0;
- CANL_ERROR_ORIGIN e_orig = unknown_error;
+ canl_error_origin e_orig = UNKNOWN_ERROR;
long errorcode = 0;
int expected = 0;
int locl_timeout = -1;
ret2 = SSL_connect(ssl);
if (ret2 < 0) {
ssl_err = ERR_get_error();
- e_orig = ssl_error;
+ e_orig = SSL_ERROR;
}
expected = errorcode = SSL_get_error(ssl, ret2);
}
timeout->tv_sec=0;
timeout->tv_usec=0;
err = ETIMEDOUT;
- set_error (cc, err, posix_error, "Connection stuck during"
+ set_error (cc, err, POSIX_ERROR, "Connection stuck during"
" handshake: timeout reached");
}
else if (ret2 < 0)
return set_error(cc, ssl_err, e_orig, "Error during SSL handshake");
else if (ret2 == 0)//TODO is 0 (conn closed by the other side) error?
- set_error (cc, 0, ssl_error, "Connection closed"
+ set_error (cc, 0, SSL_ERROR, "Connection closed"
" by the other side");
else
- set_error (cc, err, unknown_error, "Error during SSL handshake");
+ set_error (cc, err, UNKNOWN_ERROR, "Error during SSL handshake");
return 1;
}
return 0;
int ret = -1, ret2 = -1;
unsigned long ssl_err = 0;
int err = 0;
- CANL_ERROR_ORIGIN e_orig = unknown_error;
+ canl_error_origin e_orig = UNKNOWN_ERROR;
long errorcode = 0;
int expected = 0;
int locl_timeout = -1;
ret2 = SSL_accept(ssl);
if (ret2 < 0) {
ssl_err = ERR_peek_error();
- e_orig = ssl_error;
+ e_orig = SSL_ERROR;
}
expected = errorcode = SSL_get_error(ssl, ret2);
}
timeout->tv_sec=0;
timeout->tv_usec=0;
err = ETIMEDOUT;
- set_error (cc, err, posix_error, "Connection stuck"
+ set_error (cc, err, POSIX_ERROR, "Connection stuck"
" during handshake: timeout reached");
}
else if (ret2 <= 0)
- set_error (cc, ssl_err, ssl_error, "Connection closed by"
+ set_error (cc, ssl_err, SSL_ERROR, "Connection closed by"
" the other side");
else
- set_error (cc, 0, unknown_error, "Error during SSL handshake");
+ set_error (cc, 0, UNKNOWN_ERROR, "Error during SSL handshake");
return 1;
}
return 0;
return EINVAL;
if (io == NULL)
- return set_error(cc, EINVAL, posix_error,
+ return set_error(cc, EINVAL, POSIX_ERROR,
"Connection not established");
if (ssl == NULL)
- return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized");
fd = BIO_get_fd(SSL_get_rbio(ssl), NULL);
str = buffer;//TODO !!!!!! text.c_str();
end:
if (err) {
errno = err;
- set_error (cc, err, posix_error, "Error during SSL write");
+ set_error (cc, err, POSIX_ERROR, "Error during SSL write");
return -1;
}
if (touted){
err = ETIMEDOUT;
- set_error(cc, err, posix_error, "Connection stuck during"
+ set_error(cc, err, POSIX_ERROR, "Connection stuck during"
" write: timeout reached");
return -1;
}
if (ret <=0){
err = -1;//TODO what to assign??????
- set_error (cc, err, unknown_error, "Error during SSL write");
+ set_error (cc, err, UNKNOWN_ERROR, "Error during SSL write");
}
return ret;
}
return EINVAL;
if (io == NULL)
- return set_error(cc, EINVAL, posix_error,
+ return set_error(cc, EINVAL, POSIX_ERROR,
"Connection not established");
if (ssl == NULL)
- return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized");
fd = BIO_get_fd(SSL_get_rbio(ssl), NULL);
str = buffer;//TODO !!!!!! text.c_str();
if (ret <= 0 || ret2 <= 0) { // what if ret2 == 0? conn closed?
err = -1; //TODO what to assign
if (timeout != -1 && (curtime - starttime >= timeout)){
- set_error(cc, ETIMEDOUT, posix_error, "Connection stuck"
+ set_error(cc, ETIMEDOUT, POSIX_ERROR, "Connection stuck"
" during read: timeout reached");
}
else
- set_error(cc, err, unknown_error, "Error during SSL read");
+ set_error(cc, err, UNKNOWN_ERROR, "Error during SSL read");
}
else
err = ret2;
if (!cc)
return EINVAL;
if (!io)
- return set_error(cc, EINVAL, posix_error,
+ return set_error(cc, EINVAL, POSIX_ERROR,
"Connection not initialized");
if (ssl == NULL)
- return set_error(cc, EINVAL, posix_error, "SSL not initialized");
+ return set_error(cc, EINVAL, POSIX_ERROR, "SSL not initialized");
ctx = SSL_get_SSL_CTX(ssl);
} while (TEST_SELECT(ret, ret2, timeout, curtime, starttime, error));
if (timeout != -1 && (curtime - starttime >= timeout)){
- set_error(cc, ETIMEDOUT, posix_error, "Connection stuck"
+ set_error(cc, ETIMEDOUT, POSIX_ERROR, "Connection stuck"
" during ssl shutdown : timeout reached");
return -1;
}
/* TODO set_error*/
if (ret < 0) {
- set_error(cc, 0, unknown_error, "Error during SSL shutdown");
+ set_error(cc, 0, UNKNOWN_ERROR, "Error during SSL shutdown");
return -1;
}
/* successful shutdown (uni/bi directional)*/
if (ret2 == 0 || ret2 == 1)
return ret2;
else {
- set_error(cc, ssl_err, ssl_error, "Error during SSL shutdown");
+ set_error(cc, ssl_err, SSL_ERROR, "Error during SSL shutdown");
return -1;
}
}
if (!cc)
return EINVAL;
if(!cert ) {
- set_error(glb_cc, EINVAL, posix_error, "invalid parameter value");
+ set_error(glb_cc, EINVAL, POSIX_ERROR, "invalid parameter value");
return EINVAL;
}
* Automatically generated file. Don't edit.
*/
-typedef enum _CANL_ERROR {);
+typedef enum canl_error {);
while (<STDIN>) {
chomp;
}
print STDOUT qq (
-} CANL_ERROR;
+} canl_error;
);