/* * $Id: ram-output.c,v 0.43 2003/07/12 22:26:34 ceder Exp $ * Copyright (C) 1991, 1993-1999, 2001-2002 Lysator Academic Computer Association. * * This file is part of the LysKOM server. * * LysKOM 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 1, or (at your option) * any later version. * * LysKOM 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 LysKOM; see the file COPYING. If not, write to * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN, * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, * MA 02139, USA. * * Please mail bug reports to bug-lyskom@lysator.liu.se. */ /* * ram-output.c - write objects to disk. * * This is a hack. It shouldn't be used except for debugging and as a * temporary substitute for what Willf|r is (or should:-) be doing. * * Written by ceder 1990-07-13. Rewritten 1990-08-31. * Some functions rewritten for speed by Inge Wallin. * (It worked - now saving is twice as fast.) */ #ifdef HAVE_CONFIG_H # include #endif #include #include "timewrap.h" #include #include "s-string.h" #include "kom-types.h" #include "ram-output.h" #include "lyskomd.h" #include "log.h" #include "local-to-global.h" /* Forward declarations. */ static void foutput_aux_item_list(FILE *, const Aux_item_list *); static void foutput_conf_type (FILE *, Conf_type); static void foutput_mark(FILE *, Mark); static void foutput_mark_list(FILE *, const Mark_list); static void foutput_member(FILE *, Member); static void foutput_member_list(FILE *, Member_list); static void foutput_membership_list(FILE *, Membership_list); static void foutput_misc_info(FILE *, Misc_info); static void foutput_personal_flags(FILE *, Personal_flags); static void foutput_priv_bits(FILE *, Priv_bits); static void foutput_string(FILE *, String); static void foutput_text_list(FILE *, const Local_to_global *); static void foutput_time(FILE *, time_t); static void foutput_ulong(unsigned long, FILE *); static int output_format = 2; void set_output_format(int fmt) { output_format = fmt; switch (fmt) { case 0: case 1: case 2: break; default: restart_kom("unknown output format selected: %d\n", fmt); break; } } static void foutput_info_0(FILE *fp, Info *info) { fprintf(fp, " %lu %lu %lu %lu %lu", (unsigned long)info->conf_pres_conf, (unsigned long)info->pers_pres_conf, (unsigned long)info->motd_conf, (unsigned long)info->kom_news_conf, (unsigned long)info->motd_of_lyskom); } static void foutput_info_2(FILE *fp, Info *info) { fprintf(fp, " %lu %lu %lu %lu %lu %lu", (unsigned long)info->conf_pres_conf, (unsigned long)info->pers_pres_conf, (unsigned long)info->motd_conf, (unsigned long)info->kom_news_conf, (unsigned long)info->motd_of_lyskom, (unsigned long)info->highest_aux_no); foutput_aux_item_list(fp, &info->aux_item_list); } void foutput_info(FILE *fp, Info *info) { switch(output_format) { case 0: case 1: foutput_info_0(fp, info); break; case 2: foutput_info_2(fp, info); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_person_0 (FILE *fp, const Person *person) { foutput_string (fp, person->username); foutput_priv_bits (fp, person->privileges); foutput_personal_flags (fp, person->flags); foutput_text_list (fp, &person->created_texts); foutput_mark_list (fp, person->marks); foutput_membership_list (fp, person->conferences); foutput_time(fp, person->last_login); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu %lu %lu", (unsigned long) person -> user_area, (unsigned long) person -> total_time_present, /* This is not a time, * but a number of seconds. */ (unsigned long) person -> sessions, (unsigned long) person -> created_lines, (unsigned long) person -> created_bytes, (unsigned long) person -> read_texts, (unsigned long) person -> no_of_text_fetches, (unsigned long) person -> created_persons, (unsigned long) person -> created_confs); } static void foutput_person_2(FILE *fp, const Person *person) { foutput_string (fp, person->username); foutput_priv_bits (fp, person->privileges); foutput_personal_flags (fp, person->flags); putc(' ', fp); l2g_write (fp, &person->created_texts); foutput_mark_list (fp, person->marks); foutput_membership_list (fp, person->conferences); foutput_time(fp, person->last_login); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu %lu %lu", (unsigned long) person -> user_area, (unsigned long) person -> total_time_present, /* This is not a time, * but a number of seconds. */ (unsigned long) person -> sessions, (unsigned long) person -> created_lines, (unsigned long) person -> created_bytes, (unsigned long) person -> read_texts, (unsigned long) person -> no_of_text_fetches, (unsigned long) person -> created_persons, (unsigned long) person -> created_confs); } extern void foutput_person (FILE *fp, const Person *person) { switch(output_format) { case 0: case 1: foutput_person_0(fp, person); break; case 2: foutput_person_2(fp, person); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_conference_2(FILE *fp, const Conference *conf_c) { foutput_string(fp, conf_c->name); foutput_member_list(fp, conf_c->members); putc(' ', fp); l2g_write(fp, &conf_c->texts); foutput_conf_type(fp, conf_c->type); foutput_time(fp, conf_c -> creation_time ); foutput_time(fp, conf_c -> last_written ); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu", (unsigned long) conf_c -> creator, (unsigned long) conf_c -> presentation, (unsigned long) conf_c -> supervisor, (unsigned long) conf_c -> permitted_submitters, (unsigned long) conf_c -> super_conf, (unsigned long) conf_c -> msg_of_day, (unsigned long) conf_c -> nice); foutput_ulong((unsigned long) conf_c->keep_commented, fp); foutput_ulong((unsigned long) conf_c->expire, fp); foutput_ulong((unsigned long) conf_c->highest_aux, fp); foutput_aux_item_list(fp, &conf_c->aux_item_list); } static void foutput_conference_1 (FILE *fp, Conference *conf_c) { foutput_string(fp, conf_c->name); foutput_member_list(fp, conf_c->members); foutput_text_list(fp, &conf_c->texts); foutput_conf_type(fp, conf_c->type); foutput_time(fp, conf_c -> creation_time ); foutput_time(fp, conf_c -> last_written ); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu", (unsigned long) conf_c -> creator, (unsigned long) conf_c -> presentation, (unsigned long) conf_c -> supervisor, (unsigned long) conf_c -> permitted_submitters, (unsigned long) conf_c -> super_conf, (unsigned long) conf_c -> msg_of_day, (unsigned long) conf_c -> nice); } static void foutput_conference_0 (FILE *fp, Conference *conf_c) { foutput_string(fp, conf_c->name); foutput_member_list(fp, conf_c->members); foutput_text_list(fp, &conf_c->texts); foutput_conf_type(fp, conf_c->type); foutput_time(fp, conf_c -> creation_time ); foutput_time(fp, conf_c -> last_written ); fprintf (fp, " %lu %lu %lu %lu %lu %lu %lu", (unsigned long) conf_c -> creator, (unsigned long) conf_c -> presentation, (unsigned long) conf_c -> supervisor, (unsigned long) conf_c -> permitted_submitters, (unsigned long) conf_c -> super_conf, (unsigned long) conf_c -> msg_of_day, (unsigned long) conf_c -> nice); } void foutput_conference(FILE *fp, Conference *conf_c) { switch(output_format) { case 0: foutput_conference_0(fp, conf_c); break; case 1: foutput_conference_1(fp, conf_c); break; case 2: foutput_conference_2(fp, conf_c); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_text_stat_0(FILE *fp, Text_stat *t_stat) { int i; foutput_time(fp, t_stat->creation_time); foutput_ulong((unsigned long) t_stat->author, fp); foutput_ulong((unsigned long) t_stat->file_pos, fp); foutput_ulong((unsigned long) t_stat->no_of_lines, fp); foutput_ulong((unsigned long) t_stat->no_of_chars, fp); foutput_ulong((unsigned long) t_stat->no_of_marks, fp); foutput_ulong((unsigned long) t_stat->no_of_misc, fp); if ( t_stat->misc_items != NULL && t_stat->no_of_misc > 0 ) { fputs(" {", fp); for ( i = 0; i < t_stat->no_of_misc; i++ ) foutput_misc_info(fp, t_stat->misc_items[ i ]); fputs(" }", fp); } else fputs(" *", fp); } static void foutput_text_stat_2(FILE *fp, Text_stat *t_stat) { int i; foutput_time(fp, t_stat->creation_time); foutput_ulong((unsigned long) t_stat->author, fp); foutput_ulong((unsigned long) t_stat->file_pos, fp); foutput_ulong((unsigned long) t_stat->no_of_lines, fp); foutput_ulong((unsigned long) t_stat->no_of_chars, fp); foutput_ulong((unsigned long) t_stat->no_of_marks, fp); foutput_ulong((unsigned long) t_stat->no_of_misc, fp); if ( t_stat->misc_items != NULL && t_stat->no_of_misc > 0 ) { fputs(" {", fp); for ( i = 0; i < t_stat->no_of_misc; i++ ) foutput_misc_info(fp, t_stat->misc_items[ i ]); fputs(" }", fp); } else fputs(" *", fp); foutput_ulong((unsigned long) t_stat->highest_aux, fp); foutput_aux_item_list(fp, &t_stat->aux_item_list); } void foutput_text_stat(FILE *fp, Text_stat *t_stat) { switch (output_format) { case 0: case 1: foutput_text_stat_0(fp, t_stat); break; case 2: foutput_text_stat_2(fp, t_stat); break; default: restart_kom("unknown database format: %d\n", output_format); break; } } static void foutput_aux_flags(FILE *fp, Aux_item_flags f) { putc(' ', fp); putc(f.deleted + '0', fp); putc(f.inherit + '0', fp); putc(f.secret + '0', fp); putc(f.hide_creator + '0', fp); putc(f.dont_garb + '0', fp); putc(f.reserved3 + '0', fp); putc(f.reserved4 + '0', fp); putc(f.reserved5 + '0', fp); } static void foutput_aux_item_link(FILE *fp, Aux_item_link *link) { foutput_ulong((unsigned long) link->target_type, fp); foutput_ulong((unsigned long) link->target_item, fp); switch (link->target_type) { case CONF_OBJECT_TYPE: foutput_ulong((unsigned long) link->target_object.conf, fp); break; case TEXT_OBJECT_TYPE: foutput_ulong((unsigned long) link->target_object.text, fp); break; default: ; } } static void foutput_aux_item(FILE *fp, Aux_item *a_item) { foutput_ulong((unsigned long) a_item->aux_no, fp); foutput_ulong((unsigned long) a_item->tag, fp); foutput_ulong((unsigned long) a_item->creator, fp); foutput_time(fp, a_item->sent_at); foutput_aux_flags(fp, a_item->flags); foutput_ulong((unsigned long) a_item->inherit_limit, fp); foutput_string(fp, a_item->data); foutput_aux_item_link(fp, &a_item->linked_item); } static void foutput_aux_item_list(FILE *fp, const Aux_item_list *aux) { int i; foutput_ulong((unsigned long) aux->length, fp); if (aux->items && aux->length > 0) { fputs(" {", fp); for (i = 0; i < aux->length; i++) foutput_aux_item(fp, &aux->items[i]); fputs(" }", fp); } else fputs(" *", fp); } static void foutput_membership_type(FILE *fp, Membership_type type) { putc(' ', fp); putc(type.invitation + '0', fp); putc(type.passive + '0', fp); putc(type.secret + '0', fp); putc(type.passive_message_invert + '0', fp); putc(type.reserved2 + '0', fp); putc(type.reserved3 + '0', fp); putc(type.reserved4 + '0', fp); putc(type.reserved5 + '0', fp); } static void foutput_read_ranges_0(FILE *fp, Membership *mship) { if (mship->read_ranges == NULL && mship->no_of_read_ranges != 0 ) { kom_log("foutput_read_ranges_0(): no_of_read_ranges forced to 0" " in a membership in %lu.\n", (unsigned long)mship->conf_no); mship->no_of_read_ranges = 0; } if (mship->no_of_read_ranges == 0) fprintf(fp, " 0 0 *"); else { struct read_range *begin; struct read_range *end; begin = &mship->read_ranges[0]; end = begin + mship->no_of_read_ranges; if (begin->first_read == 1) { fprintf(fp, " %lu", begin->last_read); begin++; } else fprintf(fp, " 0"); if (begin == end) fprintf(fp, " 0 *"); else { unsigned long no_of_read = 0; const struct read_range *ptr; for (ptr = begin; ptr < end; ++ptr) no_of_read += ptr->last_read - ptr->first_read + 1; fprintf(fp, " %lu {", no_of_read); for (ptr = begin; ptr < end; ++ptr) { Local_text_no lno; for (lno = ptr->first_read; lno <= ptr->last_read; lno++) fprintf(fp, " %lu", (unsigned long)lno); } fprintf(fp, " }"); } } } static void foutput_membership_0(FILE *fp, Membership *mship) { foutput_time(fp, mship->last_time_read ); fprintf(fp, " %lu %lu", (unsigned long)mship->conf_no, (unsigned long)mship->priority); foutput_read_ranges_0(fp, mship); } static void foutput_membership_2(FILE *fp, Membership *mship) { foutput_time(fp, mship->last_time_read ); fprintf(fp, " %lu %lu", (unsigned long)mship->conf_no, (unsigned long)mship->priority); foutput_read_ranges_0(fp, mship); fprintf(fp, " %lu", (unsigned long)mship->added_by); foutput_time(fp, mship->added_at); foutput_membership_type(fp, mship->type); } extern void foutput_membership(FILE *fp, Membership *mship) { switch (output_format) { case 0: case 1: foutput_membership_0(fp, mship); break; case 2: foutput_membership_2(fp, mship); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_string(FILE *fp, String str) { foutput_ulong((unsigned long)str.len, fp); putc('H', fp); if (str.len) fwrite(str.string, str.len, 1, fp); } static void foutput_priv_bits(FILE *fp, Priv_bits bits) { putc(' ', fp); putc(bits.wheel + '0', fp); putc(bits.admin + '0', fp); putc(bits.statistic + '0', fp); putc(bits.create_pers + '0', fp); putc(bits.create_conf + '0', fp); putc(bits.change_name + '0', fp); putc(bits.flg7 + '0', fp); putc(bits.flg8 + '0', fp); putc(bits.flg9 + '0', fp); putc(bits.flg10 + '0', fp); putc(bits.flg11 + '0', fp); putc(bits.flg12 + '0', fp); putc(bits.flg13 + '0', fp); putc(bits.flg14 + '0', fp); putc(bits.flg15 + '0', fp); putc(bits.flg16 + '0', fp); } static void foutput_personal_flags(FILE *fp, Personal_flags flags) { putc(' ', fp); putc(flags.unread_is_secret + '0', fp); putc(flags.flg2 + '0', fp); putc(flags.flg3 + '0', fp); putc(flags.flg4 + '0', fp); putc(flags.flg5 + '0', fp); putc(flags.flg6 + '0', fp); putc(flags.flg7 + '0', fp); putc(flags.flg8 + '0', fp); } static void foutput_text_list(FILE *fp, const Local_to_global *text_list) { Local_text_no first; Local_text_no end; first = l2g_next_key(text_list, 0); end = l2g_first_appendable_key(text_list); if (first == 0) first = end; foutput_ulong((unsigned long)first, fp); foutput_ulong((unsigned long)(end - first), fp); if (first < end) { fputs(" {", fp); while (first < end) foutput_ulong((unsigned long)l2g_lookup(text_list, first++), fp); fputs(" }", fp); } else fprintf(fp, " *"); } static void foutput_mark_list(FILE *fp, const Mark_list mark_list) { int i; fprintf(fp, " %lu", (unsigned long)mark_list.no_of_marks); if ( mark_list.marks != NULL && mark_list.no_of_marks > 0 ) { fprintf(fp, " {"); for ( i = 0; i < mark_list.no_of_marks; i++ ) foutput_mark(fp, mark_list.marks[ i ]); fprintf(fp, " }"); } else fprintf(fp, " *"); } static void foutput_mark(FILE *fp, Mark mark) { fprintf(fp, " %lu %lu", (unsigned long)mark.text_no, (unsigned long)mark.mark_type); } static void foutput_membership_list_0 (FILE * fp, Membership_list mlist) { int i; fprintf(fp, " %lu", (unsigned long)mlist.no_of_confs); if ( mlist.confs != NULL && mlist.no_of_confs > 0 ) { fprintf(fp, " {"); for ( i = 0; i < mlist.no_of_confs; i++) foutput_membership_0(fp, mlist.confs + i); fprintf(fp, " }"); } else fprintf(fp, " *"); } static void foutput_membership_list_2 (FILE * fp, Membership_list mlist) { int i; fprintf(fp, " %lu", (unsigned long)mlist.no_of_confs); if ( mlist.confs != NULL && mlist.no_of_confs > 0 ) { fprintf(fp, " {"); for ( i = 0; i < mlist.no_of_confs; i++) foutput_membership_2(fp, mlist.confs + i); fprintf(fp, " }"); } else fprintf(fp, " *"); } static void foutput_membership_list(FILE * fp, Membership_list mlist) { switch (output_format) { case 0: case 1: foutput_membership_list_0(fp, mlist); break; case 2: foutput_membership_list_2(fp, mlist); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_time(FILE *fp, time_t clk) { foutput_ulong((unsigned long) clk, fp); } static void foutput_member_list(FILE *fp, Member_list m_list) { int i; fprintf(fp, " %lu", (unsigned long)m_list.no_of_members); if ( m_list.members != NULL && m_list.no_of_members > 0 ) { fprintf(fp, " {"); for ( i = 0; i < m_list.no_of_members; i++ ) foutput_member(fp, m_list.members[ i ]); fprintf(fp, " }"); } else fprintf(fp, " *"); } static void foutput_member_0(FILE *fp, Member member) { fprintf(fp, " %lu", (unsigned long)member.member); } static void foutput_member_2(FILE *fp, Member member) { fprintf(fp, " %lu %lu", (unsigned long)member.member, (unsigned long)member.added_by); foutput_time(fp, member.added_at); foutput_membership_type(fp, member.type); } static void foutput_member(FILE *fp, Member member) { switch (output_format) { case 0: case 1: foutput_member_0(fp, member); break; case 2: foutput_member_2(fp, member); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_conf_type_1(FILE *fp, Conf_type type) { putc(' ', fp); putc(type.rd_prot + '0', fp); putc(type.original + '0', fp); putc(type.secret + '0', fp); putc(type.letter_box + '0', fp); putc(type.allow_anon + '0', fp); putc(type.forbid_secret + '0', fp); putc(type.reserved2 + '0', fp); putc(type.reserved3 + '0', fp); } static void foutput_conf_type_0(FILE *fp, Conf_type type) { putc(' ', fp); putc(type.rd_prot + '0', fp); putc(type.original + '0', fp); putc(type.secret + '0', fp); putc(type.letter_box + '0', fp); } static void foutput_conf_type (FILE *fp, Conf_type type) { switch (output_format) { case 0: foutput_conf_type_0(fp, type); break; case 1: case 2: foutput_conf_type_1(fp, type); break; default: restart_kom("unknown database format: %d", output_format); break; } } static void foutput_misc_info(FILE *fp, Misc_info misc) { foutput_ulong((unsigned long)misc.type, fp); switch(misc.type) { case recpt: case cc_recpt: case bcc_recpt: foutput_ulong((unsigned long)misc.datum.recipient, fp); break; case loc_no: foutput_ulong((unsigned long)misc.datum.local_no, fp); break; case rec_time: foutput_time(fp, misc.datum.received_at); break; case comm_to: case comm_in: case footn_to: case footn_in: foutput_ulong((unsigned long)misc.datum.text_link, fp); break; case sent_by: foutput_ulong((unsigned long)misc.datum.sender, fp); break; case sent_at: foutput_time(fp, misc.datum.sent_at); break; #ifndef COMPILE_CHECKS default: #endif case unknown_info: restart_kom("prot_a_output_misc_info: Illegal misc\n"); } } /* * Output the unsigned long L in the fastest way possible to the file * FP. Ok, it's ugly, but it's fast (or is it?). */ static void foutput_ulong (unsigned long l, FILE *fp) { static char buf[sizeof(unsigned long) * 3 + 1]; char *cp; putc(' ', fp); if (l < 10) putc("0123456789"[l], fp); else { cp = buf + sizeof(buf); while (l > 0) { *--cp = (l % 10) + '0'; l /= 10; } fwrite(cp, buf + sizeof(buf) - cp, 1, fp); } }