Line data Source code
1 : #include "popd.h"
2 :
3 0 : int usage(char* filename){
4 0 : printf("%s - Part of the cmail internet mail processing suite\n", VERSION);
5 0 : printf("Provide POP3 access to mailboxes\n");
6 0 : printf("Usage: %s <conffile> [options]\n", filename);
7 0 : printf("Recognized options:\n");
8 0 : printf("\tnodrop\t\tDo not drop privileges\n");
9 0 : printf("\tnodetach\tDo not detach from console\n");
10 0 : return EXIT_FAILURE;
11 : }
12 :
13 1 : int main(int argc, char** argv){
14 1 : FILE* pid_file = NULL;
15 1 : ARGUMENTS args = {
16 : .drop_privileges = true,
17 : .daemonize = true,
18 : .config_file = NULL
19 : };
20 :
21 1 : CONFIGURATION config = {
22 : .listeners = {
23 : .count = 0,
24 : .conns = NULL
25 : },
26 : .database = {
27 : .conn = NULL,
28 : .query_authdata = NULL,
29 : .query_userdatabase = NULL,
30 : .update_lock = NULL,
31 : .list_master = NULL,
32 : .fetch_master = NULL,
33 : .mark_deletion = NULL,
34 : .unmark_deletions = NULL,
35 : .delete_master = NULL
36 : },
37 : .log = {
38 : .stream = stderr,
39 : .verbosity = 0,
40 : .log_secondary = false,
41 : .print_timestamp = true
42 : },
43 : .privileges = {
44 : .uid = 0,
45 : .gid= 0
46 : },
47 : .pid_file = NULL
48 : };
49 :
50 1 : if(argc < 2){
51 0 : return usage(argv[0]);
52 : }
53 :
54 : //parse arguments
55 1 : if(!args_parse(&args, argc - 1, argv + 1)){
56 0 : return usage(argv[0]);
57 : }
58 :
59 : #ifndef CMAIL_NO_TLS
60 1 : if(gnutls_global_init()){
61 0 : fprintf(stderr, "Failed to initialize GnuTLS\n");
62 0 : exit(EXIT_FAILURE);
63 : }
64 : #endif
65 :
66 : //read config file
67 1 : if(config_parse(config.log, &config, args.config_file) < 0){
68 0 : config_free(&config);
69 0 : TLSSUPPORT(gnutls_global_deinit());
70 0 : return EXIT_FAILURE;
71 : }
72 :
73 : //initialize database
74 1 : if(database_initialize(config.log, &(config.database)) < 0){
75 0 : config_free(&config);
76 0 : TLSSUPPORT(gnutls_global_deinit());
77 0 : return EXIT_FAILURE;
78 : }
79 :
80 : //set up signal masks //TODO error check this
81 1 : signal_init(config.log);
82 :
83 : //if needed, open pid file handle before dropping privileges
84 1 : if(config.pid_file){
85 1 : pid_file = fopen(config.pid_file, "w");
86 1 : if(!pid_file){
87 0 : logprintf(config.log, LOG_ERROR, "Failed to open pidfile for writing\n");
88 : }
89 : }
90 :
91 : //drop privileges
92 1 : if(getuid() == 0 && args.drop_privileges){
93 0 : if(privileges_drop(config.log, config.privileges) < 0){
94 0 : config_free(&config);
95 0 : TLSSUPPORT(gnutls_global_deinit());
96 0 : exit(EXIT_FAILURE);
97 : }
98 : }
99 : else{
100 1 : logprintf(config.log, LOG_INFO, "Not dropping privileges%s\n", (args.drop_privileges ? " (Because you are not root)":""));
101 : }
102 :
103 : //detach from console
104 1 : if(args.daemonize && config.log.stream != stderr){
105 1 : logprintf(config.log, LOG_INFO, "Detaching from parent process\n");
106 :
107 : //flush the stream so we do not get everything twice
108 1 : fflush(config.log.stream);
109 :
110 : //stop secondary log output
111 1 : config.log.log_secondary = false;
112 :
113 1 : switch(daemonize(config.log, pid_file)){
114 : case 0:
115 1 : break;
116 : case 1:
117 1 : logprintf(config.log, LOG_INFO, "Parent process going down\n");
118 1 : config_free(&config);
119 1 : TLSSUPPORT(gnutls_global_deinit());
120 1 : exit(EXIT_SUCCESS);
121 : break;
122 : case -1:
123 0 : config_free(&config);
124 0 : TLSSUPPORT(gnutls_global_deinit());
125 0 : exit(EXIT_FAILURE);
126 : }
127 1 : }
128 : else{
129 0 : logprintf(config.log, LOG_INFO, "Not detaching from console%s\n", (args.daemonize ? " (Because the log output stream is stderr)":""));
130 0 : if(pid_file){
131 0 : fclose(pid_file);
132 : }
133 : }
134 :
135 : //run core loop
136 1 : core_loop(config.log, config.listeners, &(config.database));
137 :
138 : //cleanup
139 1 : config_free(&config);
140 1 : TLSSUPPORT(gnutls_global_deinit());
141 :
142 1 : return 0;
143 : }
|