aboutsummaryrefslogtreecommitdiff
path: root/src/wydawca.h
blob: af24e4765a5c945de0bc725990f175f38d89b647 (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
/* wydawca - automatic release submission daemon
   Copyright (C) 2007, 2008, 2009, 2010 Sergey Poznyakoff

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3 of the License, or (at your
   option) any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program. If not, see <http://www.gnu.org/licenses/>. */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <syslog.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <signal.h>
#include <limits.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <time.h>
#include <sysexits.h>

#include <mailutils/types.h>
#include <mailutils/url.h>
#include <mailutils/errno.h>

#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
#include "obstack.h"
#include "error.h"
#include "xalloc.h"
#include "progname.h"
#include "backupfile.h"
#include "inttostr.h"
#include "grecs.h"
#include "gl_list.h"
#include "wordsplit.h"

#define gettext(s) s
#define _(s) s
#define N_(s) s

#define SP(s) ((s) ? (s) : "NONE")

#define WYDAWCA_EX_AGAIN 1

/* The range of directive versions we accept (major * 100 + minor) */
#define MIN_DIRECTIVE_VERSION 101
#define MAX_DIRECTIVE_VERSION 101

/* Default modes for mkdir and creat commands: rely on the umask value */
#define MKDIR_PERMISSIONS 0777
#define CREAT_PERMISSIONS 0666

#define SUF_SIG ".sig"
#define SUF_SIG_LEN (sizeof (SUF_SIG) - 1)
#define SUF_DIR ".directive.asc"
#define SUF_DIR_LEN (sizeof (SUF_DIR) - 1)

#define __cat2__(a,b) a ## b
#define __cat3__(a,b,c) a ## b ## c
#define NITEMS(a) (sizeof(a)/sizeof((a)[0]))

enum dictionary_id {
  project_uploader_dict,  /* Contains names, gpg-keys, emails and
			     real names of the project uploaders */
  project_owner_dict,     /* Contains names and emails of the project
			     owners */
  dictionary_count
};

enum dictionary_type
  {
    dictionary_none,           /* Undefined or no dictionary */
    dictionary_sql,            /* Use SQL database */
    dictionary_builtin,        /* Use built-in facilities */
    dictionary_external        /* Invoke an external program */
  };

struct dictionary
{
  enum dictionary_id id;
  enum dictionary_type type;      /* Dictionary type */
  char *query;                    /* Query template */
  int parmc;                      /* Number of entries in paramv */
  char **parmv;                   /* Parameters. The semantics differs
				     depending on type. For SQL:
				      0 - Identifier of the SQL struct
				          to use; */

  int init_passed;                /* Initialization count */
  char *result;                   /* Result storage */
  size_t result_size;             /* Size of result */
  unsigned ncol;                  /* Number of columns per row */
  unsigned nrow;                  /* Number of rows */

  void *storage;
};


/* Archive types */

enum archive_type
  {
    archive_none,         /* No archivation requested */
    archive_directory,    /* Archive by moving files to a separate directory
			     hierarchy */
    archive_tar           /* Archive by appending to a tar file (tar -r) */
  };

struct archive_descr
{
  enum archive_type type;        /* Archivation type */
  char *name;                    /* Directory name if type==archive_directory,
				    archive file name if type==archive_tar */
  enum backup_type backup_type;  /* Requested backup type if
				    type == archive_directory */
};


/* Type of file in a triplet */
enum file_type
  {
    file_dist,             /* Something to be distributed */
    file_signature,        /* Detached signature (.sig) */
    file_directive,        /* Directive (.directive.asc) */
  };
#define FILE_TYPE_COUNT (file_directive+1)

/* Part of a triplet */
struct file_info
{
  enum file_type type;     /* Part type */
  char *name;              /* File name */
  unsigned root_len;       /* Length of root part in name */
  struct stat sb;
};

struct uploader_info
{
  struct uploader_info *next;
  char *name;
  char *realname;
  char *email;
  char *gpg_key;
  char *fpr;
};

/* File triplet */
struct file_triplet
{
  char *name;              /* Triplet base name */
  struct file_info file[FILE_TYPE_COUNT]; /* Components */
  const struct spool *spool;     /* Owning spool */
  char **directive;        /* Decoded directive pairs (key: value\0) */
  char *blurb;             /* Block of directives: directive[i] points here */
  char *tmp;               /* Temporary storage */
  size_t tmpsize;          /* Size of memory allocated in tmp */
  /* User data */
  size_t uploader_count;
  struct uploader_info *uploader_list;
  struct uploader_info *uploader;
  /* Special data for template formatting */
  char *project;           /* Triplet project name (if known) */
  int check_result;        /* Result of external check */
  char *check_diag;        /* External check diagnostics */
};

/* Macros to access owner UID and GID. */
/* The directive file is always present in the triplet */
#define TRIPLET_UID(t) ((t)->file[file_directive].sb.st_uid)
/* GID is filled in after the triplet is finalized and verified */
#define TRIPLET_GID(t) ((t)->file[file_directive].sb.st_gid)



struct virt_tab
{
  int (*test_url)      (mu_url_t url, grecs_locus_t *loc);
  int (*move_file)     (struct file_triplet *trp,
			const struct spool *spool,
			enum file_type file_id,
			const char *reldir);
  int (*archive_file)  (struct file_triplet *trp,
			const struct spool *spool,
			const char *reldir,
			const char *file_name);
  int (*symlink_file)  (struct file_triplet *trp,
			const struct spool *spool,
			const char *reldir,
			const char *wanted_src,
			const char *wanted_dst);
  int (*rmsymlink_file)(struct file_triplet *trp,
			const struct spool *spool,
			const char *reldir,
			const char *file_name);
};

/* An upload spool. This structure contains all data necessary for releasing 
   files from source to destination */
struct spool
{
  char *tag;
  gl_list_t aliases;
  char *url;                             /* Download URL */
  char *source_dir;                      /* Source directory */
  mu_url_t dest_url;                     /* Destination URL */
  const char *dest_dir;                  /* Directory part of the above */
  struct virt_tab vtab;                  /* Virtual method table */
  
  time_t file_sweep_time;                /* Remove invalid/unprocessed files
					    after this amount of time */
  struct dictionary *dictionary[dictionary_count];
  struct archive_descr archive;          /* Archivation data */
  struct notification *notification;
  char *check_script;
};


enum wydawca_stat
  {
    STAT_ERRORS,
    STAT_WARNINGS,
    STAT_BAD_SIGNATURE,
    STAT_ACCESS_VIOLATIONS,
    STAT_COMPLETE_TRIPLETS,
    STAT_INCOMPLETE_TRIPLETS,
    STAT_BAD_TRIPLETS,
    STAT_EXPIRED_TRIPLETS,
    STAT_TRIPLET_SUCCESS,
    STAT_UPLOADS,
    STAT_ARCHIVES,
    STAT_SYMLINKS,
    STAT_RMSYMLINKS,
    STAT_CHECK_FAIL,
    MAX_STAT
  };

#define STAT_MASK(c) (1<<(c))
#define STAT_MASK_NONE 0
#define STAT_MASK_ALL  (STAT_MASK(MAX_STAT) - 1)


enum notification_event
  {
    ev_success,
    ev_bad_ownership,
    ev_bad_directive_signature,
    ev_bad_detached_signature,
    ev_check_fail,
    MAX_EVENT
  };

enum notification_target
  {
    notify_read,         /* Read recipients from the message headers */
    notify_admin,        /* System administrator */
    notify_owner,        /* Project admin */
    notify_user          /* User (uploader) */
  };

struct notification
{
  struct notification *next;
  enum notification_event ev;
  enum notification_target tgt;
  const char *sign_keys;
  const char *msg;
};

void register_message_template (const char *name, const char *text);

void notify (struct notification *,
	     struct file_triplet *, enum notification_event);

const char *notification_event_str (enum notification_event evt);
const char *notification_target_str (enum notification_target tgt);


struct metadef
{
  char *kw;
  char *value;
  const char *(*expand) (struct metadef *, void *);
  char *storage;
  void *data;
};

char *meta_expand_string (const char *string, struct metadef *def, void *data,
			  struct dictionary *dict, void *handle);
void meta_free (struct metadef *def);


/* Global variables */
extern uid_t wydawca_uid;
extern gid_t wydawca_gid;
extern size_t wydawca_supp_groupc;
extern gid_t *wydawca_supp_groups;
extern char *conffile;         /* Configuration file name */
extern int debug_level;        /* Debugging level */
extern int dry_run_mode;       /* Dry run indicator */
extern int log_to_stderr;      /* Log to stderr instead of the syslog */
extern int log_facility;       /* Syslog facility to use if !log_to_stderr */
extern char *syslog_tag;       /* Syslog tag */
extern int syslog_include_prio;/* Syslog priority indication */
extern time_t file_sweep_time; /* Unlink stale file after this amount of time
				*/
extern char *tar_command_name; /* Name of the tar command */
extern unsigned wydawca_stat[MAX_STAT];
extern unsigned long print_stats;
extern int archive_signatures;

extern char *admin_stat_message;
extern char *admin_stat_sign_key;

extern char *pidfile;
extern int force_startup;

extern char *lockdir;
extern time_t lock_expire_time;
extern time_t lock_timeout;
extern int enable_locking;

extern int daemon_mode;
extern time_t wakeup_interval;
extern int foreground;
extern int single_process;
extern struct grecs_sockaddr listen_sockaddr;

extern gl_list_t all_spool_aliases;

extern char *wydawca_gpg_homedir;
extern char *default_check_script;
extern char *temp_homedir;

#define UPDATE_STATS(what)			\
  do						\
    {						\
      if (what >= MAX_STAT) abort();		\
      wydawca_stat[what]++;			\
    }						\
  while (0)

int stat_mask_p (unsigned long mask);
struct metadef *make_stat_expansion (size_t count);
void initstats (void);
void logstats (void);


/* Utility functions */
char *safe_file_name (char *file_name);
char *safe_file_name_alloc (const char *file_name);
size_t trim_length (const char *str);
size_t trim (char *str);
void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3);
int test_dir (const char *name, int *ec);
char *create_directory (const char *base, const char *name);
int create_hierarchy (char *dir, size_t baselen);
void parse_config (void);
void log_output (int prio, const char *prog, FILE *fp);

enum exec_result
  {
    exec_success,    /* Command executed and returned 0 */
    exec_fail,       /* Command executed and returned not 0 */
    exec_error       /* Command failed to execute */
  };

enum exec_result wydawca_exec (int argc, const char **argv, int *retcode);


/* Directory scanning and registering */
int scan_spool (const struct spool *spool, int uc, uid_t *uv);
int scan_all_spools (int, uid_t *);
void spool_create_timers (void);

void register_spool (struct spool *spool);
struct spool *wydawca_find_spool (const char *name);
void register_file (struct file_info *finfo);
void enumerate_triplets (const struct spool *);
size_t count_collected_triplets (void);
char *triplet_expand_param (const char *tmpl, struct file_triplet *trp);
char *triplet_expand_dictionary_query (struct dictionary *dict, void *handle,
				   struct file_triplet *trp);

/* General-purpose dictionary support */
struct dictionary *dictionary_new (enum dictionary_id id,
				  enum dictionary_type type);
int dictionary_init (struct dictionary *dict);
int dictionary_done (struct dictionary *dict);
void *dictionary_open (struct dictionary *dict);
int dictionary_close (struct dictionary *dict, void *handle);
int dictionary_lookup (struct dictionary *dict, void *handle, const char *cmd);
void dictionary_copy_result (struct dictionary *dict, const char *res,
			 size_t size);
const char *dictionary_result (struct dictionary *dict, void *handle,
			   unsigned nrow,
			   unsigned ncol);
int dictionary_quote_string (struct dictionary *dict, void *handle,
			 const char *input, char **poutput, size_t *psize);

unsigned dictionary_num_rows (struct dictionary *dict);
unsigned dictionary_num_cols (struct dictionary *dict);

/* Verification functions */
int verify_directive_file (struct file_triplet *trp,
			   const struct spool *spool);
int verify_directive_signature (struct file_triplet *trp,
				const struct spool *spool);
int verify_detached_signature (struct file_triplet *trp,
			       const struct spool *spool);
int fill_project_name (struct file_triplet *trp);
struct uploader_info *uploader_find_frp (struct uploader_info *list,
					 const char *frp);

/* Directive file support */
int directive_parse (struct file_triplet *trp);
int directive_get_value (struct file_triplet *trp, const char *key,
			 const char **pval);
int directive_pack_version (const char *val, unsigned *pversion);
int directive_version_in_range_p (struct file_triplet *trp,
				  unsigned from, unsigned to);
int verify_directive_format (struct file_triplet *trp);
int directive_first (struct file_triplet *trp,
		     const char **pkey, const char **pval);
int directive_next (struct file_triplet *trp, int n,
		    const char **pkey, const char **pval);
int process_directives (struct file_triplet *trp,
			const struct spool *spool);

int enabled_spool_p (const struct spool *spool);
int selected_spools (void);



int parse_time_interval (const char *str, time_t *pint, const char **endp);


/* config.c */
void config_init (void);
void config_help (void);
int assert_string_arg (grecs_locus_t *, enum grecs_callback_command,
		       const grecs_value_t *);


/* vtab.c */
int url_to_vtab (mu_url_t url, struct virt_tab *vtab);

int
move_file (struct file_triplet *trp, const struct spool *spool,
	   enum file_type file_id, const char *reldir);	  
int
archive_file (struct file_triplet *trp, const struct spool *spool,
	      const char *reldir, const char *file_name);	  
int
symlink_file (struct file_triplet *trp, const struct spool *spool,
	      const char *reldir,
	      const char *wanted_src, const char *wanted_dst);
int
rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
		const char *reldir, const char *file_name);


/* diskio.c */
char *concat_dir (const char *base, const char *name, size_t *pbaselen);
int copy_file (const char *file, const char *dst_file);

int dir_test_url (mu_url_t url, grecs_locus_t *locus);
int dir_move_file (struct file_triplet *trp, const struct spool *spool,
		   enum file_type file_id, const char *reldir);
int dir_archive_file (struct file_triplet *trp, const struct spool *spool,
		      const char *file_name, const char *reldir);
int dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
		      const char *reldir,
		      const char *wanted_src, const char *wanted_dst);
int dir_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
			const char *reldir, const char *file_name);

/* null.c */
int null_move_file (struct file_triplet *trp, const struct spool *spool,
		    enum file_type file_id, const char *reldir);
int null_archive_file (struct file_triplet *trp, const struct spool *spool,
		       const char *file_name, const char *reldir);
int null_symlink_file (struct file_triplet *trp, const struct spool *spool,
		       const char *reldir,
		       const char *wanted_src, const char *wanted_dst);
int null_rmsymlink_file (struct file_triplet *trp, const struct spool *spool,
			 const char *reldir, const char *file_name);


/* timer.c */
typedef struct timer_slot *wydawca_timer_t;

wydawca_timer_t timer_get (const char *name);
wydawca_timer_t timer_start (const char *name);
wydawca_timer_t timer_stop (const char *name);
wydawca_timer_t timer_reset (const char *name);
double timer_get_real (wydawca_timer_t t);
double timer_get_user (wydawca_timer_t t);
double timer_get_system (wydawca_timer_t t);
char *timer_format_time (double t);
size_t timer_get_count (void);
void timer_fill_meta (struct metadef *def, size_t num);
void timer_free_meta (struct metadef *def, size_t num);


void report_init (void);
void report_add (const char *fmt, ...);
void report_finish (void);
extern char *report_string;


/* job.c */
void schedule_job (const struct spool *spool, uid_t uid);
void job_init (void);
void job_queue_runner (void);


/* profile.c */
void check_pidfile (void);
void remove_pidfile (void);


/* net.c */
void wydawca_listener (void);
void trim_crlf (char *s);


#define LOCK_OK          0
#define LOCK_CONFLICT    1
#define LOCK_RETRY       2
#define LOCK_INVALID     3
#define LOCK_FAILURE     4

char *wydawca_lockname (const char *tag);
int wydawca_lock (const char *lockname);
void wydawca_unlock (const char *lockname);
void wydawca_lock_init (void);


/* tcpwrap.h */
extern struct grecs_keyword tcpwrapper_kw[];
int tcpwrap_access(int fd);

/* userprivs.c */
int wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp);

Return to:

Send suggestions and report system problems to the System administrator.