scripts/mailCRANS.c
saut f05b00d6a8 Je veux rentrer dans l'histoire aussi. Version initiale.
darcs-hash:20000523205115-b92a9-d4947e0175aedff70c10ecbadbea29fa5a1ca316.gz
2000-05-23 22:51:15 +02:00

281 lines
5.9 KiB
C

/*
* Mail a tous les adherents de CRANS.
*
* Copyright (c) 1999 Association CRANS.
*
* Auteur: Olivier Saut <Olivier.Saut@CRANS.ENS-Cachan.Fr>
*
* A faire : sécuriser les strcat, faire la gestion des bats avec la libregex...
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <err.h>
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/uio.h>
#define kPCGuestUID 502
#define kCorbeauUID 536
#define kNobodyUID 65534
#define kRealUsers 500
/* Prototypes */
int mk_tmpfile();
void edit();
int sendmail(char *name);
void help();
int isValidUID(uid_t uid);
void mySig_handler(int iInt);
/* Variables globales */
char *gTempname;
uid_t gCurrent_UID;
uid_t gUid_start;
uid_t gUid_stop;
int gVerbose;
int gSimulate;
/* Programme principal */
int main(int argc, char *argv[])
{
struct passwd *passwd_ent;
struct passwd *user;
char buf[1024];
extern char *optarg;
extern int optind;
int ch ;
struct stat begin, end;
sig_t previous_handler;
char tildefn[MAXPATHLEN];
int fd=-1;
gUid_start=kRealUsers;
gUid_stop=kNobodyUID;
gVerbose=0;
gSimulate=0;
while ((ch = getopt(argc, argv, "svhf:d:a:")) != -1)
switch (ch) {
case 'h':
help();
break;
case 'v':
gVerbose=1;
break;
case 's':
gVerbose=1;
gSimulate=1;
break;
case 'f':
gTempname=optarg;
if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
(void)fprintf(stderr,
"myname: %s: %s\n", optarg, strerror(errno));
exit(1);
}
break;
case 'd':
gUid_start=atoi(optarg);
break;
case 'a':
gUid_stop=atoi(optarg);
break;
}
argc -= optind;
argv += optind;
previous_handler = signal(SIGTERM & SIGINT,(sig_t) mySig_handler);
if(previous_handler==SIG_ERR) {
(void)fprintf(stderr,"Erreur lors de l'installation du sighandler.");
exit(EXIT_FAILURE);
}
if(gVerbose)
fprintf(stdout,"mailCRANS by OS. Version 0.1\n");
if(fd==-1) {
fd=mk_tmpfile();
user=getpwuid(getuid());
sprintf(buf,"From: %s\nSubject: \nReply-To: \nContent-Type: text/plain; charset=iso-8859-1", user->pw_name);
if (write (fd,(void *)buf,strlen(buf)) < 0) {
close(fd);
fprintf(stderr, "Erreur en écriture.");
exit(EXIT_FAILURE);
}
(void) fsync(fd);
if(fstat(fd,&begin)) {
perror("Erreur stat(1)");
close(fd);
exit(EXIT_FAILURE);
}
(void) edit();
if(stat(gTempname,&end)) {
perror("Erreur stat(2)");
close(fd);
exit(EXIT_FAILURE);
}
if (begin.st_mtime == end.st_mtime) {
warnx("No changes made : exiting");
close(fd);
(void)unlink(gTempname);
exit(EXIT_FAILURE);
}
}
setpwent();
while((int)(passwd_ent=(struct passwd *)getpwent())) {
gCurrent_UID=passwd_ent->pw_uid;
if(isValidUID(gCurrent_UID))
if(sendmail(passwd_ent->pw_name )) {
exit(EXIT_FAILURE);
}
else
usleep(250000);
}
endpwent();
(void)unlink(gTempname);
/* Bon on efface le fichier parasite */
(void)strcpy((char *)tildefn,gTempname);
(void)strcat((char *)tildefn,"~");
if(!access(tildefn,F_OK))
(void)unlink(tildefn);
return 0;
}
int isValidUID(uid_t uid) {
if(uid<gUid_start)
return 0;
if(uid>gUid_stop)
return 0;
if((uid==kPCGuestUID)|| (uid==kCorbeauUID) || (uid==kNobodyUID))
return 0;
return 1;
}
void mySig_handler(int iInt) {
(void) fprintf(stdout,"\n Signal %d intercepté.\n",iInt);
(void) fprintf(stderr,"Le programme s'est arreté sur l'uid : %d\n",gCurrent_UID);
exit(EXIT_SUCCESS);
}
int mk_tmpfile()
{
int fd;
char p[MAXPATHLEN];
p[MAXPATHLEN-1]='\0';
strcpy(p, "/tmp/EAll.XXXXXX");
if ((fd = mkstemp(p)) == -1)
err(1, "%s", p);
gTempname = malloc(strlen(p));
(void)strncpy(gTempname,p,strlen(p));
if(gVerbose)
fprintf(stdout,"Tempfile name : %s\n",gTempname);
return (fd);
}
void edit()
{
int pstat;
int editpid;
char *p, *editor;
if (!(editor = getenv("EDITOR")))
editor = _PATH_VI;
if ((p = strrchr(editor, '/')))
++p;
else
p = editor;
if (!(editpid = fork())) {
errno = 0;
execlp(editor, p, gTempname, NULL);
_exit(errno);
}
for (;;) {
editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
errno = WEXITSTATUS(pstat);
(void) fprintf(stderr,"\n *** %d ***\n",WEXITSTATUS(pstat));
if (editpid == -1)
exit(EXIT_FAILURE);
else if (WIFSTOPPED(pstat))
raise(WSTOPSIG(pstat));
else if (WIFEXITED(pstat) && errno == 0)
break;
else
exit(EXIT_FAILURE);
}
editpid = -1;
}
int sendmail(char *pw_name) {
int res=0;
char *buff;
int length;
buff=malloc(1024);
buff[1023]='\0';
buff[0]='\0';
(void)strcat((char *)buff,(const char *)"cat ");
(void)strcat(buff,(const char *) gTempname);
(void)strcat(buff, " | sendmail ");
(void)strcat(buff, pw_name);
if(gVerbose)
fprintf(stdout,"\n ** %s ** \n", buff);
if(!gSimulate)
res=system(buff);
return res;
}
void help() {
fprintf(stdout,"usage: mailCRANS [-v] [-s] [-f filename] [-{d,a} uid]\n");
fprintf(stdout," -v : mode bavard\n");
fprintf(stdout," -f filename : envoie le fichier en argument\n");
fprintf(stdout," (rajouter une ligne Subject: en première ligne du fichier pour avoir un sujet\n");
fprintf(stdout," -d uid : envoie à partir de l'UID argument\n");
fprintf(stdout," -a uid : arrete après l'UID argument\n");
fprintf(stdout," -s : mode simulation.");
exit(EXIT_SUCCESS);
}