summaryrefslogtreecommitdiff
path: root/parser.y
blob: 4cd90245562101518b16ea5f3efdb8f7f729bede (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
%{
/*
 * parser.y -- parser for the rcfile
 */

/*
 * Adapted from fetchmail's rcfile_y.y by José Fonseca
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libesmtp.h>

/* parser reads these */
char *rcfile = NULL;		/* path name of dot file */

/* parser sets these */
int yydebug;			/* in case we didn't generate with -- debug */

extern char *host;
extern char *user;
extern char *pass;
extern enum starttls_option starttls;
extern char *certificate_passphrase;

/* using Bison, this arranges that yydebug messages will show actual tokens */
extern char * yytext;
#define YYPRINT(fp, type, val)	fprintf(fp, " = \"%s\"", yytext)

void yyerror (const char *s);
%}

%union {
  int number;
  char *sval;
}

%token HOSTNAME USERNAME PASSWORD STARTTLS CERTIFICATE_PASSPHRASE 

%token MAP

%token DISABLED ENABLED REQUIRED
%token <sval>  STRING
%token <number> NUMBER

%%

rcfile		: /* empty */
		| statement_list
		;

statement_list	: statement
		| statement_list statement
		;

/* future global options should also have the form SET <name> optmap <value> */
statement	: HOSTNAME MAP STRING	{ host = strdup($3); }
		| USERNAME MAP STRING	{ user = strdup($3); }
		| PASSWORD MAP STRING	{ pass = strdup($3); }
		| STARTTLS MAP DISABLED	{ starttls = Starttls_DISABLED; }
		| STARTTLS MAP ENABLED	{ starttls = Starttls_ENABLED; }
		| STARTTLS MAP REQUIRED	{ starttls = Starttls_REQUIRED; }
		| CERTIFICATE_PASSPHRASE MAP STRING	{ certificate_passphrase = strdup($3); }
		;

%%

/* lexer interface */
extern char *rcfile;
extern int lineno;
extern char *yytext;
extern FILE *yyin;

void yyerror (const char *s)
/* report a syntax error */
{
    fprintf(stderr, "%s:%d: %s at %s\n", rcfile, lineno, s, 
		   (yytext && yytext[0]) ? yytext : "end of input");
}

#define RCFILE ".esmtprc"
void parse_rcfile (void)
{
    char *home;

    /* Setup the rcfile name. */
    if (!(home = getenv("HOME")))
   	return;
	
    if (!(rcfile = malloc(strlen(home) + sizeof(RCFILE) + 2)))
    	return;

    strcpy(rcfile, home);
    if (rcfile[strlen(rcfile) - 1] != '/')
      strcat(rcfile, "/");
    strcat(rcfile, RCFILE);
  
    /* Open the configuration file and feed it to the lexer. */
    if (!(yyin = fopen(rcfile, "r"))) {
    	if (errno != ENOENT) {
	    fprintf(stderr, "open: %s: %s\n", rcfile, strerror(errno));
	}
    }
    else 
    {
	yyparse();		/* parse entire file */

	fclose(yyin);	/* not checking this should be safe, file mode was r */
    }
    
    free(rcfile);
}

/* easier to do this than cope with variations in where the library lives */
int yywrap(void) { return 1; }