/* mklist.c - create a mailing list subscriber file
 * by Alan Schwartz 1996
 *
 * Usage: mklist listname
 * Creates an empty file called "listname" in LISTDIR, and gives the
 * user some instructions.
 *
 * If your aliases file is world-readable, and your system supports
 * the sticky bit on directories, you can make LISTDIR rwxrwxrwt and
 * this program won't need to run as root.  Otherwise, you must make
 * this program setuid root.
 */

#include <stdio.h>
#include <ctype.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>


int main(argc,argv)
     int argc;
     char *argv[];
{
  struct stat buf;
  int uid;
  FILE *fp;
  
  if (argc != 2) {
    fprintf(stderr,"Usage: mklist listname\n");
    exit(1);
  }
  if (chdir(LISTDIR) < 0) {
    fprintf(stderr,"Unable to access %s\n",LISTDIR);
    exit(1);
  }
  if (badname(argv[1]))
    exit(1);
  uid = getuid();
  if (stat(argv[1],&buf) == 0) {
    /* The file already exists! */
    if (buf.st_uid == uid)
      fprintf(stderr,"You've already created that mailing list.\n");
    else
      fprintf(stderr,"Someone else is using that name.\n");
    exit(1);
  }
  /* Ok, let's create the file */
  if ((fp = fopen(argv[1],"w")) == NULL) {
    fprintf(stderr,"Unable to create %s/%s\n",LISTDIR,argv[1]);
    exit(1);
  }
  fclose(fp);
  if (uid != geteuid()) {
    /* We're running setuid root. chown the file we created */
    chown(argv[1],uid,-1);
  }
  chmod(argv[1],0700);
  /* Success. */
  printf("Congratulations on your new mailing list, %s\n",argv[1]);
  printf("You may add or remove subscribers from the list by editing the file\n");
  printf("%s/%s\n",LISTDIR,argv[1]);
  printf("The file should contain the list of subscribers, one email address per line.\n");
  printf("Within 15 minutes, the %s address and %s-request\n",argv[1],argv[1]);
  printf("(which is forwarded to you) will be activated.\n");
  printf("To delete this list, use the command: rmlist %s\n",argv[1]);
#ifdef TROUBLEADDR
  printf("If you have problems, contact %s\n",TROUBLEADDR);
#endif
  exit(0);
}
    
  
int badname(name)
  char *name;
{
  FILE *aliases;
  char *p;
  char buffer[256];
  
  /* Disallow names that are <9 chars, which could be mistaken for
   * a user name
   */
  if (strlen(name) < 9) {
    fprintf(stderr,"List names must be longer than 8 characters.\n");
    return 1;
  }

  /* Disallow names of more than 20 characters */
  if (strlen(name) > 20) {
    fprintf(stderr,"List names must be shorter than 20 characters.\n");
    return 1;
  }

  /* Names must start with a letter */
  if (!isalpha(*name)) {
    fprintf(stderr,"List names must start with a letter.\n");
    return 1;
  }
  
  /* Disallow names which use any character other than [-_A-Za-z0-9] */
  p = name;
  while (*p) {
    if (!(isalnum(*p) || *p == '-' || *p == '_')) {
      fprintf(stderr,"List names may only contain letters, numbers, hyphens, and underscores\n");
      return 1;
    }
    p++;
  }
     
  /* Disallow aliases which are already defined in /etc/aliases so we
   * don't get someone doing a "postmaster" list.
   */
  if ((aliases = fopen(ALIASES,"r")) == NULL) {
    fprintf(stderr,"Unable to open %s\n",ALIASES);
    return 1;
  }
  fgets(buffer,255,aliases);
  while (!feof(aliases)) {
    if (isalpha(buffer[0])) {
      if ((p = index(buffer,':')) != NULL) {
	*p = '\0';
	if (strcasecmp(buffer,name) == 0) {
	  fprintf(stderr,"That list name is already used as an alias.\n");
	  fclose(aliases);
	  return 1;
	}
      }
    }
    fgets(buffer,255,aliases);
  }
  fclose(aliases);
  
  return 0;
}
