aboutsummaryrefslogtreecommitdiff
path: root/src/triplet.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-08-26 13:03:32 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-08-26 13:03:32 +0000
commitb89ece30bebb5b9dd06e4e061537b6bf068566f2 (patch)
treec7f65b64fccfac2f0e7e134e5f7666a4fb1907d1 /src/triplet.c
parent338c0d9c35c56f35c636df1c1da0852a466e731f (diff)
downloadwydawca-b89ece30bebb5b9dd06e4e061537b6bf068566f2.tar.gz
wydawca-b89ece30bebb5b9dd06e4e061537b6bf068566f2.tar.bz2
Implement project owner notifications.
* wydawca/wydawca.c (syslog_printer): Reduce the number of memory reallocations (make_stat_expansion): Update * wydawca/method.c: Implement a new framework: methods may return 2-dimensional arrays of strings. * wydawca/sql.c, wydawca/sql.h: Implement the new method framework. * wydawca/verify.c (expand_param): kw_expansion may provide expansion functions. An additional argument supplies user-defined data for expansions. (escape_kwexp): Extern (free_kwexp): Improve (get_project_name): New function (make_default_kwexp): New function (check_access_rights): Call get_project_name. Use make_default_kwexp to initialize expansions (verify_directive_file): Use make_default_kwexp to initialize expansions * wydawca/wydawca.h (NITEMS): New macro (enum access_method_type): New members: ncol, nrow (struct directory_pair): New members url,project_owner_method, user_data_method (struct file_info): Replace mtime, uid with struct stat sb (struct file_triplet): New members project, dpair, user_data (TRIPLET_UID): Take into account the changes to struct file_info (enum notification_event): New data type (notify_project_owner, notify_admin, notify): New functions (struct kw_expansion): New members static_p, expand and data. (escape_kwexp,make_default_kwexp): New proto (expand_param): Change signature (triplet_expand_param): New function (method_result): Change prototype (method_num_rows,method_num_cols): New functions * wydawca/config.c: New statements project-owner, user-data, admin-address, mail-user, user-message directory can take an optional argument specifying base URL for notification messages * wydawca/gpg.c (verify_directive_signature): Expand directives even if the signature does not match. Useful for notifications. Add notifications. * wydawca/process.c: Add notifications. * wydawca/directive.c: Add notifications * wydawca/wydawca.rc: Update * wydawca/mail.c, wydawca/mail.h: Implement project owner notifications * wydawca/triplet.c (triplet_expand_param): New function * lib/cfg.c (read_cont_line): Fix counting of input lines. git-svn-id: file:///svnroot/wydawca/trunk@297 6bb4bd81-ecc2-4fd4-a2d4-9571d19c0d33
Diffstat (limited to 'src/triplet.c')
-rw-r--r--src/triplet.c324
1 files changed, 320 insertions, 4 deletions
diff --git a/src/triplet.c b/src/triplet.c
index daf3265..46c6011 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -51,7 +51,14 @@ hash_triplet_free (void *data)
free (tp->directive);
free (tp->blurb);
free (tp->tmp);
-
+
+ if (tp->user_data)
+ {
+ for (i = 0; i < NITEMS (tp->user_data); i++)
+ free (tp->user_data[i]);
+ free (tp->user_data);
+ }
+
free (tp);
}
@@ -96,7 +103,7 @@ triplet_expired_p (struct file_triplet *trp, time_t ttl)
for (i = 0; i < FILE_TYPE_COUNT; i++)
{
if (trp->file[i].name
- && (now - trp->file[i].mtime) > ttl)
+ && (now - trp->file[i].sb.st_mtime) > ttl)
{
if (debug_level)
logmsg (LOG_DEBUG, "File %s expired", trp->file[i].name);
@@ -131,8 +138,10 @@ check_triplet_state (struct file_triplet *trp)
else if (trp->file[file_dist].name
&& trp->file[file_signature].name)
{
- if (trp->file[file_dist].uid == trp->file[file_signature].uid
- && trp->file[file_dist].uid == trp->file[file_directive].uid)
+ if (trp->file[file_dist].sb.st_uid ==
+ trp->file[file_signature].sb.st_uid
+ && trp->file[file_dist].sb.st_uid ==
+ trp->file[file_directive].sb.st_uid)
return triplet_complete;
else
{
@@ -172,6 +181,8 @@ triplet_processor (void *data, void *proc_data)
struct file_triplet *trp = data;
struct directory_pair *dpair = proc_data;
+ trp->dpair = dpair;
+
if (debug_level)
logmsg (LOG_DEBUG, "FILE %s, DIST=%s, SIG=%s, DIRECTIVE=%s",
trp->name,
@@ -234,3 +245,308 @@ count_collected_triplets ()
return triplet_table ? hash_get_n_entries (triplet_table) : 0;
}
+
+static char *
+expand_project_base (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ return trp->project;
+}
+
+static char *
+expand_url (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ return trp->dpair->url;
+}
+
+static char *
+expand_relative_dir (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ directive_get_value (trp, "directory", &exp->value);
+ exp->static_p = 1;
+ return exp->value;
+}
+
+static char *
+expand_dest_dir (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ return trp->dpair->dest_dir;
+}
+
+static char *
+expand_source_dir (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ return trp->dpair->source_dir;
+}
+
+static void
+decode_file_mode (mode_t mode, char *string)
+{
+ *string++ = mode & S_IRUSR ? 'r' : '-';
+ *string++ = mode & S_IWUSR ? 'w' : '-';
+ *string++ = (mode & S_ISUID
+ ? (mode & S_IXUSR ? 's' : 'S')
+ : (mode & S_IXUSR ? 'x' : '-'));
+ *string++ = mode & S_IRGRP ? 'r' : '-';
+ *string++ = mode & S_IWGRP ? 'w' : '-';
+ *string++ = (mode & S_ISGID
+ ? (mode & S_IXGRP ? 's' : 'S')
+ : (mode & S_IXGRP ? 'x' : '-'));
+ *string++ = mode & S_IROTH ? 'r' : '-';
+ *string++ = mode & S_IWOTH ? 'w' : '-';
+ *string++ = (mode & S_ISVTX
+ ? (mode & S_IXOTH ? 't' : 'T')
+ : (mode & S_IXOTH ? 'x' : '-'));
+ *string = '\0';
+}
+
+/* Width of "user/group size", with initial value chosen
+ heuristically. This grows as needed, though this may cause some
+ stairstepping in the output. Make it too small and the output will
+ almost always look ragged. Make it too large and the output will
+ be spaced out too far. */
+static int ugswidth = 19;
+
+static int
+format_file_data (struct file_triplet *trp, enum file_type type, char **pret)
+{
+ char modes[11];
+ struct file_info *info = trp->file + type;
+ char timebuf[sizeof "YYYY-MM-DD HH:MM:SS +0000"];
+ struct passwd *pw;
+ struct group *grp;
+ char sbuf[INT_BUFSIZE_BOUND (uintmax_t)];
+ char *sptr;
+ size_t slen;
+ int pad;
+ char *user_name;
+ char *group_name;
+ struct tm *tm;
+ char *buf;
+
+ if (!info->name)
+ return 1;
+
+ /* MODE OWNER GROUP SIZE MTIME FILE_NAME MD5SUM? */
+
+ modes[0] = '-'; /* Only regular files are allowed */
+ decode_file_mode (info->sb.st_mode, modes + 1);
+
+ /* File time */
+ tm = localtime (&info->sb.st_mtime);
+ strftime (timebuf, sizeof timebuf, "%Y-%m-%d %H:%M:%S %z", tm);
+
+ /* FIXME: owner and group name should be store in TRP after verification */
+ pw = getpwuid (TRIPLET_UID (trp));
+ if (!pw)
+ user_name = "UNKNOWN"; /* should not happen */
+ else
+ user_name = pw->pw_name;
+
+ grp = getgrgid (TRIPLET_GID (trp));
+ if (!grp)
+ group_name = "UNKNOWN"; /* should not happen */
+ else
+ group_name = grp->gr_name;
+
+ /* Size */
+ sptr = umaxtostr (info->sb.st_size, sbuf);
+
+ /* Figure out padding and format the buffer */
+ slen = strlen (sptr);
+ pad = strlen (user_name) + 1 + strlen (group_name) + 1 + slen;
+ if (pad > ugswidth)
+ ugswidth = pad;
+
+ asprintf (&buf,
+ "%s %s %s %*s %s %s",
+ modes, user_name, group_name, ugswidth - pad + slen, sptr,
+ timebuf, info->name);
+ *pret = buf;
+ return 0;
+}
+
+static char *
+expand_triplet_full (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ char *buf[FILE_TYPE_COUNT] = { NULL, NULL, NULL };
+
+ format_file_data (trp, file_dist, &buf[file_dist]);
+ format_file_data (trp, file_signature, &buf[file_signature]);
+ format_file_data (trp, file_directive, &buf[file_directive]);
+
+ exp->value = xmalloc (strlen (buf[file_dist]) + 1
+ + strlen (buf[file_signature]) + 1
+ + strlen (buf[file_directive]) + 1);
+ sprintf (exp->value, "%s\n%s\n%s", buf[file_dist], buf[file_signature],
+ buf[file_directive]);
+
+ free (buf[file_dist]);
+ free (buf[file_signature]);
+ free (buf[file_directive]);
+
+ exp->static_p = 0;
+ return exp->value;
+}
+
+static char *
+expand_triplet_upload (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ char *buf[2] = { NULL, NULL };
+
+ format_file_data (trp, file_dist, &buf[file_dist]);
+ format_file_data (trp, file_signature, &buf[file_signature]);
+
+ exp->value = xmalloc (strlen (buf[file_dist]) + 1
+ + strlen (buf[file_signature]) + 1);
+ sprintf (exp->value, "%s\n%s", buf[file_dist], buf[file_signature]);
+
+ free (buf[file_dist]);
+ free (buf[file_signature]);
+
+ exp->static_p = 0;
+ return exp->value;
+}
+
+static char *
+expand_triplet_dist (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ format_file_data (trp, file_dist, &exp->value);
+ exp->static_p = 0;
+ return exp->value;
+}
+
+static char *
+expand_triplet_sig (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ format_file_data (trp, file_signature, &exp->value);
+ exp->static_p = 0;
+ return exp->value;
+}
+
+static char *
+expand_triplet_directive (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ format_file_data (trp, file_directive, &exp->value);
+ exp->static_p = 0;
+ return exp->value;
+}
+
+static char *
+expand_user_name (struct kw_expansion *exp, void *data)
+{
+ struct passwd *pw;
+ struct file_triplet *trp = data;
+
+ /* FIXME: should user name be stored in the triplet? */
+ pw = getpwuid (TRIPLET_UID (trp));
+ if (!pw)
+ return NULL;
+ exp->value = xstrdup (pw->pw_name);
+ exp->static_p = 0;
+ return exp->value;
+}
+
+static void
+fill_user_data (struct file_triplet *trp)
+{
+ int rc;
+ struct access_method *method = trp->dpair->user_data_method;
+ char *text;
+ unsigned nrows, ncols;
+ struct kw_expansion kwexp[4];
+ struct passwd *pw;
+
+ if (trp->user_data)
+ return;
+
+ if (method->type == method_none)
+ return;
+
+ if (method_init (method))
+ return;
+
+ pw = getpwuid (TRIPLET_UID (trp));
+ if (!pw)
+ return;
+ make_default_kwexp (kwexp, pw->pw_name, trp->project);
+ escape_kwexp (method, kwexp, NITEMS (kwexp));
+ text = expand_param (method->param[1], kwexp, NITEMS (kwexp), NULL);
+
+ rc = method_run (method, text);
+ free (text);
+ if (rc)
+ return;
+
+ nrows = method_num_rows (method);
+ ncols = method_num_cols (method);
+
+ if (nrows > 0)
+ {
+ int i;
+ trp->user_data = xcalloc (ncols, sizeof (trp->user_data[0]));
+ for (i = 0; i < ncols; i++)
+ {
+ const char *str = method_result (method, 0, i);
+ if (str)
+ trp->user_data[i] = xstrdup (str);
+ }
+ }
+}
+
+static char *
+expand_user_real_name (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ fill_user_data (trp);
+ if (trp->user_data[0])
+ return trp->user_data[0];
+ exp->value = "UNKNOWN";
+ exp->static_p = 1;
+ return exp->value;
+}
+
+static char *
+expand_user_email (struct kw_expansion *exp, void *data)
+{
+ struct file_triplet *trp = data;
+ fill_user_data (trp);
+ if (trp->user_data[1])
+ return trp->user_data[1];
+ exp->value = "UNKNOWN";
+ exp->static_p = 1;
+ return exp->value;
+}
+
+struct kw_expansion triplet_exp[] = {
+ { "project", NULL, 0, expand_project_base, NULL },
+ { "url", NULL, 0, expand_url, NULL },
+ { "dir", NULL, 0, expand_relative_dir, NULL },
+ { "dest-dir", NULL, 0, expand_dest_dir, NULL },
+ { "source-dir", NULL, 0, expand_source_dir, NULL },
+ { "triplet:full", NULL, 0, expand_triplet_full, NULL },
+ { "triplet:upload", NULL, 0, expand_triplet_upload, NULL },
+ { "triplet:dist", NULL, 0, expand_triplet_dist, NULL },
+ { "triplet:sig", NULL, 0, expand_triplet_sig, NULL },
+ { "triplet:dir", NULL, 0, expand_triplet_directive, NULL },
+ { "user", NULL, 0, expand_user_name, NULL },
+ { "user:name", NULL, 0, expand_user_name, NULL },
+ { "user:real-name", NULL, 0, expand_user_real_name, NULL },
+ { "user:email", NULL, 0, expand_user_email, NULL },
+};
+
+char *
+triplet_expand_param (const char *tmpl, struct file_triplet *trp)
+{
+ free_kwexp (triplet_exp, NITEMS (triplet_exp));
+ return expand_param (tmpl, triplet_exp, NITEMS (triplet_exp), trp);
+}

Return to:

Send suggestions and report system problems to the System administrator.