/* 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 #include #include #include #include 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; }