/* * TULP - Unix Mailing List manager * (sub-set of FRECP's Bitnet Listserv tool) * * Copyright (C) 1991-2000 Kimmo Suominen, Christophe Wolfhugel * * Please read the files COPYRIGHT and AUTHORS for the extended * copyrights refering to this file. * * 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 1, 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include "conf.h" #include "ext.h" #include "str.h" #include #ifdef FAKESYSLOG # include "fakesyslog.h" #else # include #endif /* FAKESYSLOG */ RCSID("@(#)lp.c,v 1.7 2000/03/07 22:16:30 kim Exp") extern char From[], To[]; struct ITEM { struct ITEM *next; char *value; }; static struct ITEM *commentList = NULL, *commentPtr = NULL; static struct ITEM *editorList = NULL, *editorPtr = NULL; static struct ITEM *ownerList = NULL, *ownerPtr = NULL; static struct ITEM *userList = NULL, *userPtr = NULL; static char review[16], send[16], subscription[16]; static char lname[64], replyto[128], errorsto[128]; static char buf2[512]; int IsEditor(char *s) { struct ITEM *p; for (p = editorList; p != NULL; p = p->next) { if (strspacecmp(p->value, s) == 0) return (1); } return (0); } int IsOwner(char *s) { struct ITEM *p; for (p = ownerList; p != NULL; p = p->next) { if (strspacecmp(p->value, s) == 0) return (1); } return (0); } int IsUser(char *s) { struct ITEM *p; for (p = userList; p != NULL; p = p->next) { if (strspacecmp(p->value, s) == 0) return (1); } return (0); } void RewindUserList() { userPtr = userList; } char *GetUser(char *s) { struct ITEM *p; if (userPtr == NULL) return (NULL); p = userPtr; userPtr = userPtr->next; if (s != NULL) strcpy(s, p->value); return (p->value); } void RewindCommentList() { commentPtr = commentList; } char *GetComment(char *s) { struct ITEM *p; if (commentPtr == NULL) return (NULL); p = commentPtr; commentPtr = commentPtr->next; if (s != NULL) strcpy(s, p->value); return (p->value); } void RewindEditorList() { editorPtr = editorList; } char *GetEditor(char *s) { struct ITEM *p; if (editorPtr == NULL) return (NULL); p = editorPtr; editorPtr = editorPtr->next; if (s != NULL) strcpy(s, p->value); return (p->value); } void RewindOwnerList() { ownerPtr = ownerList; } char *GetOwner(char *s) { struct ITEM *p; if (ownerPtr == NULL) return (NULL); p = ownerPtr; ownerPtr = ownerPtr->next; if (s != NULL) strcpy(s, p->value); return (p->value); } /* * Returns 0 if new entry, 1 if updated. */ int AddItem(struct ITEM **head, char *s) { struct ITEM *p, *q, *r; q = NULL; for (p = *head; p != NULL; p = p->next) { if (p->value[0] == '#') { q = p; continue; } if (stradrcmp(s, p->value) == 0) { p->value = (char *) realloc(p->value, strlen(s) + 1); strcpy(p->value, s); return (1); } if (stradrcmp(s, p->value) < 0) { r = (struct ITEM *) malloc(sizeof(struct ITEM)); r->value = (char *) malloc(strlen(s) + 1); if (q == NULL) *head = r; else q->next = r; r->next = p; strcpy(r->value, s); return (0); } q = p; } p = (struct ITEM *) malloc(sizeof(struct ITEM)); p->value = (char *) malloc(strlen(s) + 1); p->next = NULL; strcpy(p->value, s); if (q != NULL) q->next = p; else *head = p; return (0); } /* * Returns 0 if OK, -1 if key not found. */ int DelItem(struct ITEM **head, char *s) { struct ITEM *p, *q; q = NULL; for (p = *head; p != NULL; p = p->next) { if (strspacecmp(s, p->value) == 0) { if (q == NULL) *head = p->next; else q->next = p->next; free(p->value); free(p); return (0); } q = p; } return (-1); } int DelUser(char *s) { return (DelItem(&userList, s)); } int AddUser(char *s) { return (AddItem(&userList, s)); } void AddEditor(char *s) { AddItem(&editorList, s); } void AddOwner(char *s) { AddItem(&ownerList, s); } void DelList(struct ITEM **head) { struct ITEM *p; while (*head != NULL) { p = *head; *head = p->next; free(p->value); free(p); } *head = NULL; } #define DELIM "# =\r\n\t" void parseComment(char *s) { char *kw; kw = strtok(buf2, DELIM); if (kw == NULL) return; if (strcasecmp(kw, "owner") == 0) { kw = strtok(NULL, DELIM); if (kw != NULL) AddItem(&ownerList, kw); return; } if (strcasecmp(kw, "editor") == 0) { kw = strtok(NULL, DELIM); if (kw != NULL) AddItem(&editorList, kw); return; } if (strcasecmp(kw, "review") == 0) { kw = strtok(NULL, DELIM); if (kw != NULL) strcpy(review, kw); return; } if (strcasecmp(kw, "send") == 0) { kw = strtok(NULL, DELIM); if (kw != NULL) strcpy(send, kw); return; } if (strcasecmp(kw, "subscription") == 0) { kw = strtok(NULL, DELIM); if (kw != NULL) strcpy(subscription, kw); return; } if (strcasecmp(kw, "reply-to") == 0) { kw = strtok(NULL, DELIM); if (kw != NULL) strcpy(replyto, kw); return; } if (strcasecmp(kw, "errors-to") == 0) { kw = strtok(NULL, DELIM); if (kw != NULL) strcpy(errorsto, kw); return; } } /* * Returns 0 on success, -1 is list.u file not found. */ int ReadUserList(char *s) { FILE *f; strcpy(review, "all"); strcpy(send, "all"); strcpy(subscription, "open"); strcpy(replyto, "list,respect"); errorsto[0] = 0; sprintf(lname, "%s.u", s); f = fopen(lname, "r"); if (f == NULL) { syslog(LOG_ERR, "can't open %s", lname); return (-1); } while (fgets(buf2, 256, f) != NULL) { strtok(buf2, "\r\n"); if (buf2[0] == 0) continue; if (buf2[0] == '#') { AddItem(&commentList, buf2); parseComment(buf2); continue; } AddUser(buf2); } fclose(f); return (0); } void WriteUserList() { FILE *f; f = fopen("tmpfile", "w"); RewindCommentList(); RewindUserList(); while (GetComment(buf2) != NULL) fprintf(f, "%s\n", buf2); while (GetUser(buf2) != NULL) fprintf(f, "%s\n", buf2); fclose(f); rename("tmpfile", lname); unlink("tmpfile"); } void CloseUserList() { DelList(&userList); DelList(&editorList); DelList(&ownerList); DelList(&commentList); } char *GetSubscription() { return (subscription); } char *GetReview() { return (review); } char *GetSend() { return (send); } char *GetReplyTo() { return (replyto); } char *GetErrorsTo() { return (errorsto); }