char *db = "moira/moira";
char *divide = "##############################################################";
-#define ML_WID 72
-#define AL_MAX_WID 592
+#define MAX_LINE_WIDTH 72
+#define MAX_ALIAS_WIDTH 592
#define FALSE 0
#define TRUE (!FALSE)
FILE *out = stdout;
-struct hash *users, *machines, *strings, *lists, *names;
+struct hash *users, *machines, *strings, *lists;
struct user {
char *login;
- char *first;
- char *last;
- char mi;
char *pobox;
};
struct member {
int acl_id;
struct member *m;
};
-struct names {
- char *name;
- struct names *next;
- int keep;
- int id;
-};
void get_info(void);
void save_mlist(int id, void *list, void *force);
-void insert_login(int id, void *user, void *hint);
-void insert_names(int id, void *user, void *hint);
-void insert_name(char *s, int id, int nodups, int copy);
-int hashstr(char *s);
-void sort_info(void);
-void output_data(int dummy, void *names, void *out);
+int check_string(char *s);
+void output_login(int dummy, void *names, void *out);
void output_mlist(int id, struct list *l);
-void do_member(FILE *out, char *s);
void put_fill(FILE *aliases, char *string);
void do_people(void);
+int incount = 0;
+
int main(int argc, char **argv)
{
- long tm = time(NULL);
- char filename[64], *targetfile;
+ time_t tm = time(NULL);
+ char filename[MAXPATHLEN], *targetfile;
struct stat sb;
- EXEC SQL BEGIN DECLARE SECTION;
- int flag;
- EXEC SQL END DECLARE SECTION;
+ int flag1, flag2;
EXEC SQL CONNECT :db;
{
if (stat(argv[1], &sb) == 0)
{
- if (ModDiff (&flag, "users", sb.st_mtime))
+ if (ModDiff(&flag1, "users", sb.st_mtime) ||
+ ModDiff(&flag2, "list", sb.st_mtime))
exit(MR_DATE);
- if (flag < 0)
+ if (flag1 < 0 && flag2 < 0)
{
fprintf(stderr, "File %s does not need to be rebuilt.\n",
argv[1]);
EXEC SQL COMMIT;
- fprintf(stderr, "Sorting Info\n");
- sort_info();
+ incount = 0;
+ fprintf(out, "\n%s\n# Mailing lists\n%s\n\n", divide, divide);
+ hash_step(lists, save_mlist, FALSE);
+ fprintf(stderr, "Output %d lists\n", incount);
- fprintf(stderr, "Dumping information\n");
- do_people();
+ incount = 0;
+ fprintf(out, "\n%s\n# People\n%s\n\n", divide, divide);
+ hash_step(users, output_login, out);
+ fprintf(stderr, "Output %d users\n", incount);
fprintf(out, "\n%s\n# End of aliases file\n", divide);
{
EXEC SQL BEGIN DECLARE SECTION;
int id, pid, bid, cnt, maillistp, acl, mid;
- char name[129], type[9], fname[17], mname[17], lname[17], buf[257];
+ char mname[MACHINE_NAME_SIZE], str[STRINGS_STRING_SIZE];
+ char login[USERS_LOGIN_SIZE], potype[USERS_POTYPE_SIZE];
+ char lname[LIST_NAME_SIZE], desc[LIST_DESCRIPTION_SIZE];
+ char type[LIST_ACL_TYPE_SIZE];
EXEC SQL END DECLARE SECTION;
char *s;
struct user *u;
EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
cnt = 0;
- machines = create_hash(1000);
+ machines = create_hash(100);
EXEC SQL DECLARE m_cursor CURSOR FOR
SELECT mach_id, name
FROM machine
WHERE status = 1
+ AND mach_id IN ( SELECT UNIQUE pop_id FROM users )
ORDER BY mach_id;
EXEC SQL OPEN m_cursor;
while (1)
{
- EXEC SQL FETCH m_cursor INTO :id, :name;
+ EXEC SQL FETCH m_cursor INTO :id, :mname;
if (sqlca.sqlcode)
break;
- if ((s = strchr(name, '.')))
+ if ((s = strchr(mname, '.')))
*s = '\0';
else
- strtrim(name);
+ strtrim(mname);
#ifdef ATHENA
- strcat(name, ".LOCAL");
+ strcat(mname, ".LOCAL");
#endif
- if (hash_store(machines, id, strdup(name)) < 0)
+ if (hash_store(machines, id, strdup(mname)) < 0)
{
fprintf(stderr, "Out of memory!\n");
exit(MR_NO_MEM);
EXEC SQL OPEN s_cursor;
while (1)
{
- EXEC SQL FETCH s_cursor INTO :id, :name;
+ EXEC SQL FETCH s_cursor INTO :id, :str;
if (sqlca.sqlcode)
break;
- if (hash_store(strings, id, strdup(strtrim(name))) < 0)
+ if (hash_store(strings, id, strdup(strtrim(str))) < 0)
{
fprintf(stderr, "Out of memory!\n");
exit(MR_NO_MEM);
users = create_hash(13001);
EXEC SQL DECLARE u_cursor CURSOR FOR
- SELECT users_id, login, first, middle, last, potype, pop_id, box_id
+ SELECT users_id, login, potype, pop_id, box_id
FROM users
WHERE status != 3
ORDER BY users_id;
EXEC SQL OPEN u_cursor;
while (1)
{
- EXEC SQL FETCH u_cursor INTO :id, :name, :fname, :mname, :lname,
- :type, :pid, :bid;
+ EXEC SQL FETCH u_cursor INTO :id, :login, :potype, :pid, :bid;
if (sqlca.sqlcode)
break;
u = malloc(sizeof(struct user));
- u->login = strdup(strtrim(name));
- u->first = strdup(strtrim(fname));
- u->last = strdup(strtrim(lname));
- if (mname[0] != ' ')
- u->mi = mname[0];
- else
- u->mi = 0;
+ u->login = strdup(strtrim(login));
- if (type[0] == 'P' && (s = hash_lookup(machines, pid)))
+ if (potype[0] == 'P' && (s = hash_lookup(machines, pid)))
{
+ char *buf = malloc(strlen(u->login) + strlen(s) + 2);
sprintf(buf, "%s@%s", u->login, s);
- u->pobox = strdup(buf);
+ u->pobox = buf;
}
- else if (type[0] == 'S')
+ else if (potype[0] == 'S')
u->pobox = hash_lookup(strings, bid);
else
u->pobox = NULL;
+
+ check_string(u->login);
if (hash_store(users, id, u) < 0)
{
fprintf(stderr, "Out of memory!\n");
EXEC SQL OPEN l_cursor;
while (1)
{
- EXEC SQL FETCH l_cursor INTO :id, :name, :maillistp, :buf, :type, :acl;
+ EXEC SQL FETCH l_cursor INTO :id, :lname, :maillistp, :desc, :type, :acl;
if (sqlca.sqlcode)
break;
l = malloc(sizeof(struct list));
- l->name = strdup(strtrim(name));
+ l->name = strdup(strtrim(lname));
l->maillist = maillistp;
- l->description = strdup(strtrim(buf));
+ l->description = strdup(strtrim(desc));
l->acl_t = type[0];
l->acl_id = acl;
l->m = NULL;
struct member *m;
struct list *l = list, *l1;
- if (l->maillist > 1 || (l->maillist == 0 && !force))
+ if (l->maillist > 1 || (l->maillist == 0 && !force) ||
+ !check_string(l->name))
return;
+ /* If user group appears on list, replace with user. */
if (l->m && l->m->next == NULL && !strcasecmp(l->name, l->m->name))
{
l->maillist = 3;
return;
}
l->maillist = 2;
- insert_name(l->name, -1, TRUE, FALSE);
output_mlist(id, l);
if (l->acl_t == 'L' && (l1 = hash_lookup(lists, l->acl_id)))
}
}
-
-void insert_login(int id, void *user, void *hint)
-{
- struct user *u = user;
- if (u->pobox && u->login[0] != '#')
- insert_name(u->login, id, TRUE, FALSE);
-}
-
-void insert_names(int id, void *user, void *hint)
+void output_login(int dummy, void *user, void *out)
{
- char buffer[256];
struct user *u = user;
- insert_name(u->last, id, FALSE, FALSE);
- sprintf(buffer, "%s_%s", u->first, u->last);
- insert_name(buffer, id, FALSE, TRUE);
-#if 0
- sprintf(buffer, "%c_%s", u->first[0], u->last);
- insert_name(buffer, id, FALSE, TRUE);
-#endif
- if (u->mi)
- {
- sprintf(buffer, "%s_%c_%s", u->first, u->mi, u->last);
- insert_name(buffer, id, FALSE, TRUE);
- }
-}
-
-int incount = 0;
-
-void insert_name(char *s, int id, int nodups, int copy)
-{
- int code;
- struct names *ns;
-
incount++;
- code = hashstr(s);
- ns = hash_lookup(names, code);
- if (!ns)
- {
- if (!(ns = malloc(sizeof(struct names))))
- {
- fprintf(stderr, "ran out of memory inserting name (sorting)\n");
- exit(MR_NO_MEM);
- }
- if (copy)
- ns->name = strdup(s);
- else
- ns->name = s;
- ns->keep = nodups;
- ns->id = id;
- ns->next = NULL;
- if (hash_store(names, code, ns) < 0)
- {
- fprintf(stderr, "Out of memory!\n");
- exit(MR_NO_MEM);
- }
- return;
- }
- if (strcasecmp(ns->name, s))
- {
- while (ns->next)
- {
- ns = ns->next;
- if (!strcasecmp(ns->name, s))
- goto foundns;
- }
- if (!(ns->next = malloc(sizeof(struct names))))
- {
- fprintf(stderr, "ran out of memory insterting name (sorting)\n");
- exit(MR_NO_MEM);
- }
- ns = ns->next;
- if (copy)
- ns->name = strdup(s);
- else
- ns->name = s;
- ns->keep = nodups;
- ns->id = id;
- ns->next = NULL;
- return;
- }
-foundns:
- if (nodups || ns->keep)
- {
- if (nodups && ns->keep)
- fprintf(stderr, "duplicated name: %s\n", s);
- return;
- }
- ns->id = 0;
+ if (u->pobox && check_string(u->login) && u->login[0] != '#')
+ fprintf(out, "%s: %s\n", u->login, u->pobox);
}
-
-/* Illegal chars: ! " % ( ) , / : ; < = > @ [ \ ] ^ { | } */
-
-static int illegalchars[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
- 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, /* SPACE - / */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, /* 0 - ? */
- 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, /* P - _ */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-};
-
-
-/* While hashing the string, punt any illegal characters */
-
-int hashstr(char *s)
-{
- int result;
- int c;
-
- for (result = 0; (c = *s); s++)
- {
- if (illegalchars[c])
- {
- char *p;
- for (p = s; *p; p++)
- *p = p[1];
- continue;
- }
- if (isupper(c))
- c = *s = tolower(c);
- result = (result << 5) - result + c - '`';
- }
- return result < 0 ? -result : result;
-}
-
-
-void sort_info(void)
-{
- names = create_hash(20001);
- hash_step(users, insert_login, NULL);
- incount = 0;
- fprintf(out, "\n%s\n# Mailing lists\n%s\n", divide, divide);
- hash_step(lists, save_mlist, FALSE);
- fprintf(stderr, "Output %d lists\n", incount);
-#ifdef NAME_ALIASES
- hash_step(users, insert_names, NULL);
- fprintf(stderr, "Inserted %d names\n", incount);
-#endif
-}
-
-
-void output_data(int dummy, void *names, void *out)
-{
- struct names *ns, *nms = names;
- struct user *u;
-
- incount++;
- for (ns = nms; ns; ns = ns->next)
- {
- if (!ns->name[0] || !ns->name[1])
- {
- fprintf(stderr, "punting %s due to short name\n", ns->name);
- continue;
- }
- if (ns->id > 0)
- {
- u = hash_lookup(users, ns->id);
- if (u->pobox)
- fprintf(out, "%s: %s\n", ns->name, u->pobox);
-#ifdef NAME_ALIASES
- else
- fprintf(out, "%s: =%s=@nobox\n", ns->name, ns->name);
-#endif
- }
-#ifdef NAME_ALIASES
- else if (ns->id == 0)
- fprintf(out, "%s: =%s=@ambig\n", ns->name, ns->name);
-#endif
- }
-}
-
-
-int lwid, bol, awid;
-
void output_mlist(int id, struct list *l)
{
struct list *l1;
struct member *m;
struct user *u;
+ int line_width, alias_width, word_width, beginning;
+ static int cont = 1;
+ char str[8];
put_fill(out, l->description);
if (l->acl_t == 'L' && (l1 = hash_lookup(lists, l->acl_id)))
else
fprintf(out, "%s: ", l->name);
- lwid = strlen(l->name) + 2;
- bol = 1;
+ alias_width = line_width = strlen(l->name) + 2;
+ beginning = 1;
for (m = l->m; m; m = m->next)
- do_member(out, m->name);
+ {
+ word_width = strlen(m->name);
+
+ if (!beginning && alias_width + word_width + 2 > MAX_ALIAS_WIDTH)
+ {
+ /* Make a continuation. */
+ sprintf(str, "%c%c%c%c%c%c", rand() % 26 + 97, rand() % 26 + 97,
+ rand() % 26 + 97, rand() % 26 + 97,
+ rand() % 26 + 97, rand() % 26 + 97);
+ fprintf(out, ",\n\tcont%d-%s\ncont%d-%s: ", cont, str, cont, str);
+ cont++;
+ alias_width = line_width = 17 + word_width;
+ fputs(m->name, out);
+ }
+ else if (beginning)
+ {
+ /* Beginning of alias, so don't wrap. */
+ line_width += word_width;
+ alias_width = line_width;
+ fputs(m->name, out);
+ beginning = 0;
+ }
+ else if (line_width + word_width + 2 > MAX_LINE_WIDTH)
+ {
+ /* Wrap. */
+ fprintf(out, ",\n\t%s", m->name);
+ alias_width += line_width + word_width + 2;
+ line_width = word_width + 8;
+ }
+ else
+ {
+ /* Continue line. */
+ line_width += word_width + 2;
+ fprintf(out, ", %s", m->name);
+ }
+ }
if (!l->m)
fprintf(out, "/dev/null");
fprintf(out, "\n\n");
incount++;
}
-
-/* print out strings separated by commas, doing line breaks as appropriate */
-
-void do_member(FILE *out, char *s)
-{
- int wwid;
- static int cont = 1;
- char str[8];
-
- wwid = strlen(s);
-
- if (!bol && awid + wwid + 2 > AL_MAX_WID)
- {
- sprintf(str, "%c%c%c%c%c%c", rand() % 26 + 97, rand() % 26 + 97,
- rand() % 26 + 97, rand() % 26 + 97,
- rand() % 26 + 97, rand() % 26 + 97);
- str[6] = '\0';
- fprintf(out, ",\n\tcont%d-%s\ncont%d-%s: ", cont, str, cont, str);
- cont++;
- awid = lwid = 17 + wwid;
- fputs(s, out);
- return;
- }
-
- if (bol)
- {
- lwid += wwid;
- awid = lwid;
- fputs(s, out);
- bol = 0;
- return;
- }
- if (lwid + wwid + 2 > ML_WID)
- {
- fprintf(out, ",\n\t%s", s);
- awid += lwid + wwid + 2;
- lwid = wwid + 8;
- return;
- }
- lwid += wwid + 2;
- fprintf(out, ", %s", s);
-}
-
-
+/* Write a word-wrapped list description to the aliases file as a
+ * comment. */
void put_fill(FILE *aliases, char *string)
{
char *c;
- int lwid;
- int wwid;
+ int line_width;
+ int word_width;
if (!string || !*string)
return;
fputs("# ", aliases);
- lwid = 3;
+ line_width = 3;
while (1)
{
string++;
c = strchr(string, ' ');
if (!c)
- wwid = strlen(string);
+ word_width = strlen(string);
else
{
- wwid = c - string;
+ word_width = c - string;
*c = '\0';
}
- if ((lwid + wwid) > ML_WID)
+ if (line_width + word_width > MAX_LINE_WIDTH)
{
fputs("\n# ", aliases);
- lwid = 3;
+ line_width = 3;
fputs(string, aliases);
}
else
break;
/* add a space after the word */
fputc(' ', aliases);
- wwid++;
- lwid += wwid;
- string += wwid;
+ word_width++;
+ line_width += word_width;
+ string += word_width;
/* add another if after a period */
if (*--c == '.')
{
fputc(' ', aliases);
- lwid++;
+ line_width++;
}
}
}
-void do_people(void)
+/* Illegal chars: this should correspond to the array used by
+ * setup_alis. */
+
+static int illegalchars[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
+ 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, /* SPACE - / */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+int check_string(char *s)
{
- incount = 0;
- fprintf(out, "\n%s\n# People\n%s\n", divide, divide);
- hash_step(names, output_data, out);
- fprintf(stderr, "Output %d entries\n", incount);
+ for (; *s; s++)
+ {
+ if (isupper(*s))
+ *s = tolower(*s);
+
+ if (illegalchars[(unsigned) *s])
+ return 0;
+ }
+ return 1;
}