static char rcsid[] = "@(#)$Id: elmregister.c,v 1.42.2.2 2007/09/02 13:31:06 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.42.2.2 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "defs_major.h"
#include "patchlevel.h"
#include "reghelper.h"
/* Protocol in PIPE:
*
* file descriptor given on $ELM_INSTALLER
* installer root given on $ELM_ROOT
*
* filenames are relative to $ELM_ROOT
*
* -- module
* 'm' module {rest of line}
*
* -- copy file
*
* 'F' user group mode filename '\n'
* 'd' user group mode filename '\n' (document)
* 's' user group mode filename '\n' (stage file)
*
* -- create directory
*
* 'M' user group mode filename '\n'
*
* -- execute
* {n} user group mode filename '\n'
* {n} user group mode filename'\n'
*
* 'E' filename {n} xx yy {n} '\n'
*
* -- config file touched on replay time
*
* 'C' user group mode filename'\n'
*
* -- remove files
*
* 'R' file file file '\n'
*
* -- link file
*
* 'L' file file '\n'
*
*/
#define IMPARGDIR "{--implicit-stage-directory--}"
/* putenv.c */
#ifndef PUTENV
extern int putenv P_((char *));
#endif
/* strstr.c */
#ifndef STRSTR
extern char *strstr P_((char *,char *));
#endif
#ifdef PWDINSYS
# include <sys/pwd.h>
# include <sys/grp.h> /* TODO: Not necessary correct .... */
#else
# include <pwd.h>
# include <grp.h>
#endif
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
#if defined(BSD_TYPE) && !defined(WEXITSTATUS)
typedef union wait S__;
#else
typedef int S__;
#endif
static char * filelist = SYSTEM_DEFAULT_FILELIST;
static char * stage_dir = STAGE_DIR;
static char * register_pipe = "$ELM_INSTALLER"; /* To be assigned */
int register_fd = -1;
static char * installer_root = "$ELM_ROOT"; /* To be assigned */
char * program_name = "elmregister"; /* To be assigned */
char * register_module = NULL;
static int create_pipe P_((int argc, char *argv[], int x, int *PID,
char *root, char *module));
static int create_pipe(argc,argv,x,PID,root,module)
int argc;
char *argv[];
int x;
int *PID;
char *root;
char *module;
{
static char array[] = "ELM_INSTALLER=XXXX";
int filedes[2];
int z = pipe(filedes);
char *command;
int pid;
if (z < 0) {
fprintf(stderr,"%s: pipe() failed\n",program_name);
exit(1);
}
if (x >= argc) {
fprintf(stderr,"%s: No command given\n",program_name);
exit(1);
}
command = argv[x];
fflush(stdout);
pid = fork(); /* BRANCH child process */
if (0 == pid) {
int l = strlen(root) + 12;
char *array2 = malloc(l);
sprintf(array,"ELM_INSTALLER=%d",filedes[1]);
if (!array2) {
fprintf(stderr,"%s: malloc %d bytes failed\n",program_name,l);
exit(1);
}
sprintf(array2,"ELM_ROOT=%s",root);
if (0 != putenv(array)) {
fprintf(stderr,"%s: putenv() failed\n",program_name);
exit(1);
}
if (0 != putenv(array2)) {
fprintf(stderr,"%s: putenv() failed\n",program_name);
exit(1);
}
if (module) {
int l = strlen(root) + 15;
char *array3 = malloc(l);
sprintf(array3,"ELM_MODULE=%s",module);
if (0 != putenv(array3)) {
fprintf(stderr,"%s: putenv() failed\n",program_name);
exit(1);
}
}
close(filedes[0]); /* read end */
fprintf(stdout,"%s: Running %s ...\n",
program_name,command);
execvp(command,argv+x);
fprintf(stderr,
"%s: Failed to EXECute %s\n",program_name,command);
fflush(stderr);
_exit(127);
}
if (pid < 0) {
fprintf(stderr,"%s: fork() failed\n",program_name);
exit(1);
}
close(filedes[1]); /*write end */
*PID=pid;
return filedes[0];
}
#define MAX_ARGS 300
static void make_package_dir P_((char *y,char *root));
static void make_package_dir(y,root)
char *y;
char *root;
{
int l = strlen(root);
char *Z;
char *x;
if (l < 2)
return;
Z = strdup(y);
if (0 != strncmp(Z,root,l)) {
free(Z);
return ;
}
for (x = Z + l; *x; x++) {
if ('/' == *x) {
*x = '\0';
if (0 == mkdir(Z,0755)) {
fprintf(stdout,
"%s: parent directory %s created (of %s)\n",
program_name,Z,y);
}
*x = '/';
}
}
free(Z);
}
struct log_record {
char * buffer;
int buffer_len;
char * module_ptr;
int command_letter;
char * command_ptr;
/* Following points to space on buffer ... */
char * user_ptr;
char * group_ptr;
char * mode_ptr;
char ** arg_ptrs;
};
struct log_entries {
char * version;
struct log_record * log;
int log_count;
};
struct log_instance {
FILE *file;
char *filename;
struct log_entries * entries;
int entries_count;
};
static void clear_log_instance P_((struct log_instance *LI));
static void clear_log_instance(LI)
struct log_instance *LI;
{
LI->file = NULL;
LI->filename = NULL;
LI->entries = NULL;
LI->entries_count = 0;
}
static void add_bytes P_((FILE *F,char * buffer, int *ptr));
static void add_bytes(F,buffer,ptr)
FILE *F;
char * buffer;
int *ptr;
{
while (1) {
int c = fgetc(F);
if (EOF == c) {
fprintf(stderr,"%s: Failed to read from pipe or file (or EOF)\n",
program_name);
exit(1);
}
if (*ptr > MAX_PIPE_LOG) {
fprintf(stderr,"%s: Record from pipe or file too long\n",
program_name);
exit(1);
}
buffer[*ptr] = c;
(*ptr)++;
if (0 == c) {
/* END OF RECORD MARK */
return;
}
}
}
static void parse_log_tail P_((
struct log_record *l,
char buffer1[MAX_PIPE_LOG +10 ],
int ptr,
int module_ptr,
int command_ptr,
int user_ptr,
int group_ptr,
int mode_ptr,
int args_ptr[MAX_ARGS],
int argnum));
static void parse_log P_((FILE *F, struct log_record *l));
static void parse_log(F,l)
FILE *F;
struct log_record *l;
{
char buffer1[MAX_PIPE_LOG +10 ]; /* write routines quarantee that
this is enough! */
int ptr = 0;
int c = fgetc(F);
int module_ptr = -1;
int command_ptr = -1;
int user_ptr = -1;
int group_ptr = -1;
int mode_ptr = -1;
int args_ptr[MAX_ARGS];
int argnum = 0;
l->buffer = NULL;
l->buffer_len = 0;
l->module_ptr = NULL;
l->command_ptr = NULL;
l->user_ptr = NULL;
l->group_ptr = NULL;
l->mode_ptr = NULL;
l->arg_ptrs = NULL;
if (EOF == c) {
/* EOF or error */
l->command_letter = EOF;
return;
}
ungetc(c,F); /* add_bytes reread character */
command_ptr = ptr; add_bytes(F,buffer1,&ptr);
if (buffer1[0] != c) {
fprintf(stderr,"%s: Character %c not buffered (reading from pipe or file)\n",
program_name,c);
exit(1);
}
if ('m' == c) {
module_ptr = ptr; add_bytes(F,buffer1,&ptr); /* module */
command_ptr = ptr; add_bytes(F,buffer1,&ptr); /* command */
c = buffer1[command_ptr];
}
l->command_letter = c;
switch (c) {
case 'F':
case 'd':
user_ptr = ptr; add_bytes(F,buffer1,&ptr); /* user */
group_ptr = ptr; add_bytes(F,buffer1,&ptr); /* group */
mode_ptr = ptr; add_bytes(F,buffer1,&ptr); /* mode */
args_ptr[0] = ptr; add_bytes(F,buffer1,&ptr); /* target file */
argnum = 1;
break;
case '{':
/* .... filename variable already readed */
user_ptr = ptr; add_bytes(F,buffer1,&ptr); /* user */
group_ptr = ptr; add_bytes(F,buffer1,&ptr); /* group */
mode_ptr = ptr; add_bytes(F,buffer1,&ptr); /* mode */
args_ptr[0] = ptr; add_bytes(F,buffer1,&ptr); /* target file */
argnum = 1;
break;
case 'C':
case 'M':
case 's':
user_ptr = ptr; add_bytes(F,buffer1,&ptr); /* user */
group_ptr = ptr; add_bytes(F,buffer1,&ptr); /* group */
mode_ptr = ptr; add_bytes(F,buffer1,&ptr); /* mode */
args_ptr[0] = ptr; add_bytes(F,buffer1,&ptr); /* target file */
argnum = 1;
break;
case 'L':
args_ptr[0] = ptr; add_bytes(F,buffer1,&ptr); /* file1 file */
args_ptr[1] = ptr; add_bytes(F,buffer1,&ptr); /* file2 file */
argnum = 2;
break;
case 'R':
case 'E':
do {
int n = ptr;
c = fgetc(F);
if (EOF == c) {
fprintf(stderr,"%s: unexpected EOF\n",
program_name);
exit(1);
}
ungetc(c,F); /* add_bytes reread character */
if ('\n' == c)
break;
if (argnum >= MAX_ARGS) {
fprintf(stderr,"%s: Too many arguments on pipe or file\n",
program_name);
exit(1);
}
args_ptr[argnum++] = ptr; add_bytes(F,buffer1,&ptr);
if (buffer1[n] != c) {
fprintf(stderr,"%s: Character %c not buffered (reading from pipe or file)\n",
program_name,c);
exit(1);
}
} while(1);
break;
default:
fprintf(stderr,"%s: Bad command letter: %c (reading from pipe or file)\n",
program_name,c);
exit(1);
}
c = fgetc(F);
if ('\n' != c) {
fprintf(stderr,"%s: newline expected: %c (reading from pipe or file)\n",
program_name,c);
exit(1);
}
l->buffer_len = ptr;
l->buffer = malloc(l->buffer_len);
if (! l->buffer ) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l->buffer_len);
exit(1); /* FAILURE */
}
parse_log_tail(l,buffer1,ptr,module_ptr,command_ptr,user_ptr,
group_ptr,mode_ptr,args_ptr,argnum);
}
static void parse_log_tail(l,buffer1,ptr,module_ptr,command_ptr,user_ptr,
group_ptr,mode_ptr,args_ptr,argnum)
struct log_record *l;
char buffer1[MAX_PIPE_LOG +10 ]; /* write routines quarantee that
this is enough! */
int ptr;
int module_ptr;
int command_ptr;
int user_ptr;
int group_ptr;
int mode_ptr;
int args_ptr[MAX_ARGS];
int argnum;
{
memcpy(l->buffer,buffer1,l->buffer_len);
if (module_ptr != -1)
l->module_ptr = l->buffer + module_ptr;
if (command_ptr != -1)
l->command_ptr = l->buffer + command_ptr;
if (user_ptr != -1)
l->user_ptr = l->buffer + user_ptr;
if (group_ptr != -1)
l->group_ptr = l->buffer + group_ptr;
if (mode_ptr != -1)
l->mode_ptr = l->buffer + mode_ptr;
if (argnum > 0) {
int i;
l->arg_ptrs = malloc((argnum +1) * sizeof (l->arg_ptrs[0]));
if (!l->arg_ptrs) {
fprintf(stderr,"%s: malloc %d items failed\n",
program_name,argnum+1);
exit(1); /* FAILURE */
}
for (i = 0; i < argnum; i++)
l->arg_ptrs[i] = l->buffer + args_ptr[i];
l->arg_ptrs[argnum] = NULL;
}
}
static void add_entries P_((struct log_instance *LI));
static void add_entries(LI)
struct log_instance *LI;
{
struct log_entries * last = NULL;
do {
int c = fgetc(LI->file);
if (EOF == c) {
/* EOF or error */
return;
}
ungetc(c,LI->file); /* add_bytes reread character */
if ('[' == c) {
char version_buffer[MAX_PIPE_LOG];
int ptr = 0;
add_bytes(LI->file,version_buffer,&ptr);
if (version_buffer[0] != c) {
fprintf(stderr,"%s: Character %c not buffered (reading from file %s)\n",
program_name,c,LI->filename);
exit(1);
}
if (ptr <3 || version_buffer[ptr-2] != ']') {
fprintf(stderr,
"%s: File %s is not elmregister filelist\n",
program_name,LI->filename);
exit(1);
}
c = fgetc(LI->file);
if ('\n' != c) {
fprintf(stderr,"%s: newline expected: %c (reading from file %s)\n",
program_name,c,LI->filename);
exit(1);
}
LI->entries = realloc(LI->entries,(LI->entries_count+1) * sizeof (LI->entries[0]));
if (! LI->entries) {
fprintf(stderr,
"%s: Failed to realloc %d items (file %s)\n",
program_name,LI->entries_count+1,LI->filename);
exit(1);
}
last = & (LI->entries[LI->entries_count]);
LI->entries_count++;
last -> version = strdup(version_buffer);
if (!last -> version) {
fprintf(stderr,
"%s: Failed to strdup string (%d bytes?): %s (file %s)\n",
program_name,ptr,version_buffer,LI->filename);
exit(1);
}
last -> log = NULL;
last -> log_count = 0;
} else if (!last) {
fprintf(stderr,"%s: OOPS (file %s)!\n",
program_name,LI->filename);
exit(1);
} else {
last -> log = realloc(last -> log,
(last -> log_count+1) * sizeof (last -> log[0]));
if (! last->log) {
fprintf(stderr,
"%s: Failed to realloc %d items (file %s)\n",
program_name,last -> log_count+1,LI->filename);
exit(1);
}
parse_log(LI->file,&( last -> log[last -> log_count] ));
last -> log_count++;
}
} while (1);
}
static struct log_entries * add_last P_((struct log_instance *LI));
static struct log_entries * add_last(LI)
struct log_instance *LI;
{
char buffer[ MAX_PIPE_LOG];
char *ptr;
struct log_entries * last = NULL;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
/* Write version header --- */
ptr = buffer;
add_to_buffer(buffer, sizeof buffer,&ptr,my_version,strlen (my_version));
*ptr++ = '\n'; /* Terminating NL on line */
if (ptr-buffer != fwrite(buffer,1,ptr-buffer,LI->file)) {
fprintf(stderr,"%s: write error (file %s)\n",
program_name,LI->filename);
fclose(LI->file);
exit (1); /* FAILURE */
}
LI->entries =
realloc(LI->entries,(LI->entries_count+1) *
sizeof (LI->entries[0]));
if (!LI->entries) {
fprintf(stderr,
"%s: Failed to realloc %d items (file %s)\n",
program_name,LI->entries_count+1,LI->filename);
fclose(LI->file);
exit (1); /* FAILURE */
}
last = & (LI->entries[LI->entries_count]);
LI->entries_count++;
last -> version = strdup(my_version);
if (!last -> version) {
fprintf(stderr,
"%s: Failed to strdup string (%d bytes?): %s\n",
program_name,ptr-buffer-1,my_version);
fclose(LI->file);
exit(1); /* FAILURE */
}
last -> log = NULL;
last -> log_count = 0;
return last;
}
static int take_arg P_((char *buffer, char *ptr, int L));
static int take_arg(buffer,ptr,L)
char *buffer;
char *ptr;
int L;
{
int n;
if (!ptr)
return -1;
n = ptr - buffer;
if (n < 0 || n >= L) {
fprintf(stderr,"%s: [take_arg] bad argument\n",program_name);
exit(1);
}
return n;
}
static void move_record P_((struct log_instance *LI,struct log_entries * last,
struct log_record *L));
static void move_record(LI,last,L)
struct log_instance *LI;
struct log_entries * last;
struct log_record *L;
{
int module_ptr;
int command_ptr;
int user_ptr;
int group_ptr;
int mode_ptr;
int args_ptr[MAX_ARGS];
int argnum = 0;
last -> log = realloc(last -> log,
(last -> log_count+1) * sizeof (last -> log[0]));
last -> log[last -> log_count].buffer = malloc(L->buffer_len);
if (!last -> log[last -> log_count].buffer) {
fprintf(stderr,"%s: malloc %d bytes failed\n",program_name,
L->buffer_len);
exit(1);
}
last -> log[last -> log_count].buffer_len = L->buffer_len;
last -> log[last -> log_count].module_ptr = NULL;
last -> log[last -> log_count].command_letter = L->command_letter;
last -> log[last -> log_count].command_ptr = NULL;
last -> log[last -> log_count].user_ptr = NULL;
last -> log[last -> log_count].group_ptr = NULL;
last -> log[last -> log_count].mode_ptr = NULL;
last -> log[last -> log_count].arg_ptrs = NULL;
module_ptr = take_arg(L->buffer,L->module_ptr,L->buffer_len);
command_ptr = take_arg(L->buffer,L->command_ptr,L->buffer_len);
user_ptr = take_arg(L->buffer,L->user_ptr,L->buffer_len);
group_ptr = take_arg(L->buffer,L->group_ptr,L->buffer_len);
mode_ptr = take_arg(L->buffer,L->mode_ptr,L->buffer_len);
while (L->arg_ptrs && L->arg_ptrs[argnum] && argnum < MAX_ARGS) {
args_ptr[argnum] = take_arg(L->buffer,L->arg_ptrs[argnum],
L->buffer_len);
argnum++;
}
if (L->buffer_len != fwrite(L->buffer,1,L->buffer_len,LI->file)) {
fprintf(stderr,
"%s: write error (file %s)\n",
program_name,LI->filename);
fclose(LI->file);
exit (1); /* FAILURE */
}
putc('\n',LI->file);
parse_log_tail(& last -> log[last -> log_count],
L->buffer,
L->buffer_len,
module_ptr,
command_ptr,
user_ptr,
group_ptr,
mode_ptr,
args_ptr,
argnum);
last -> log_count++;
}
static void log_copy_loop P_((FILE *fd, struct log_instance *target,
struct log_entries * last));
static void log_copy_loop(fd,target,last)
FILE *fd;
struct log_instance *target;
struct log_entries * last;
{
while(1) {
struct log_record L;
parse_log(fd,&L);
if (EOF != L.command_letter) {
move_record(target,last,&L);
}
/* L.buffer and L.arg_ptrs are only think what are malloced */
if (L.buffer) {
free(L.buffer);
L.buffer = NULL;
}
if (L.arg_ptrs) {
free(L.arg_ptrs);
L.arg_ptrs = NULL;
}
if (EOF == L.command_letter) {
fprintf(stderr,"%s: EOF from pipe\n",program_name);
break;
}
}
}
static void remove_unlinked1 P_((struct log_instance *target,int Z,
char *relative, int *count));
static void remove_unlinked1(target,Z,relative,count)
struct log_instance *target;
int Z;
char *relative;
int *count;
{
int i;
for (i = 0; i < target->entries_count && i < Z; i++) {
struct log_record * ptr2;
for (ptr2 = target->entries[i].log;
ptr2 < target->entries[i].log +
target->entries[i].log_count;
ptr2++) {
switch (ptr2->command_letter) {
case 'M':
case '{':
case 's':
case 'F':
case 'd':
case 'C':
if (ptr2->arg_ptrs && ptr2->arg_ptrs[0] &&
0 == strcmp(ptr2->arg_ptrs[0],relative)) {
(*count) ++;
if (ptr2->buffer) {
free(ptr2->buffer);
ptr2->buffer = NULL;
}
if (ptr2->arg_ptrs) {
free(ptr2->arg_ptrs);
ptr2->arg_ptrs = NULL;
}
ptr2->command_letter = '\0'; /* ENTRY DELETED */
}
break;
case 'L': /* SECOND ARGUMENT IS NEW NAME */
if (ptr2->arg_ptrs && ptr2->arg_ptrs[1] &&
0 == strcmp(ptr2->arg_ptrs[1],relative)) {
(*count) ++;
if (ptr2->buffer) {
free(ptr2->buffer);
ptr2->buffer = NULL;
}
if (ptr2->arg_ptrs) {
free(ptr2->arg_ptrs);
ptr2->arg_ptrs = NULL;
}
ptr2->command_letter = '\0'; /* ENTRY DELETED */
}
break;
}
}
}
}
static char * make_rooted P_((struct log_record * ptr, char *rel, char *root));
static char * make_rooted(ptr,rel,root)
struct log_record * ptr;
char *rel;
char *root;
{
int L = strlen(root);
int l = strlen(rel) + 2 + L;
char * translated = malloc(l);
if (!translated) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
exit (1); /* FAILURE */
}
strcpy(translated,root);
if ('/' == rel[0]) {
fprintf(stderr,
"%s: entry '%c' -- Not relative? %s\n",
program_name,ptr->command_letter,rel);
} else {
if (L < 1 || root[L-1] != '/') {
translated[L] = '/';
translated[L+1] = '\0';
}
}
strcat(translated,rel);
return translated;
}
static void remove_unlinked P_((struct log_instance *target,char *root,
int *remove_count));
static void remove_unlinked(target,root,remove_count)
struct log_instance *target;
char *root;
int *remove_count;
{
int i;
int y = 0;
*remove_count = 0;
for (i = 0; i < target->entries_count; i++) {
struct log_record * ptr2;
for (ptr2 = target->entries[i].log;
ptr2 < target->entries[i].log +
target->entries[i].log_count;
ptr2++) {
switch (ptr2->command_letter) {
int j;
case 'R': /* FILE DELETED */
if (!y) {
y++;
fprintf(stdout,
"%s: Trimming unlinked files from %s\n",
program_name,target->filename);
}
for (j = 0;
ptr2->arg_ptrs[j] && j < MAX_ARGS;
j++) {
int count = 0;
char * translated =
make_rooted(ptr2,ptr2->arg_ptrs[j],root);
struct stat X;
if (stat(translated,&X) < 0) {
remove_unlinked1(target,i,ptr2->arg_ptrs[j],
&count);
if (count > 0) {
fprintf(stdout,
"%s: (%s) File %s is removed -- removing from log\n",
program_name,translated,ptr2->arg_ptrs[j]);
*remove_count += count;
}
}
free(translated);
}
break;
}
}
}
}
static void rewrite_list P_((struct log_instance *target));
static void rewrite_list(target)
struct log_instance *target;
{
FILE * new_fd;
char *tempname;
int l = strlen(target->filename);
int i;
tempname = malloc(l+4);
if (!tempname) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
exit(1); /* FAILURE */
}
strcpy(tempname,target->filename);
strcat(tempname,"~N~");
if (0 == unlink(tempname)) {
fprintf(stderr,"%s: %s unlinked\n",program_name,tempname);
}
new_fd = fopen(tempname,"w+");
if (!new_fd) {
fail:
fprintf(stderr,
"%s: Failed to create %s -- %s not rewritten\n",
program_name,tempname,target->filename);
free(tempname);
return;
}
fprintf(stdout,"%s: Rewriting %s\n",program_name,target->filename);
for (i = 0; i < target->entries_count; i++) {
char buffer[ MAX_PIPE_LOG];
char *ptr;
struct log_record * ptr2;
/* Write version header --- */
ptr = buffer;
add_to_buffer(buffer, sizeof buffer,&ptr,
target->entries[i].version,
strlen (target->entries[i].version));
*ptr++ = '\n'; /* Terminating NL on line */
if (ptr-buffer != fwrite(buffer,1,ptr-buffer,new_fd)) {
fprintf(stderr,"%s: write error (file %s)\n",
program_name,tempname);
fclose(new_fd);
goto fail;
}
for (ptr2 = target->entries[i].log;
ptr2 < target->entries[i].log +
target->entries[i].log_count;
ptr2++) {
switch (ptr2->command_letter) {
case '\0': /* ENTRY DELETED */
break;
default:
if (ptr2->buffer) {
if (ptr2->buffer_len !=
fwrite(ptr2->buffer,1,ptr2->buffer_len,new_fd)) {
fprintf(stderr,
"%s: write error (file %s)\n",
program_name,tempname);
fclose(new_fd);
goto fail;
}
putc('\n',new_fd);
}
break;
}
}
}
if (EOF == fflush(new_fd)) {
fprintf(stderr,
"%s: Failed to write %s\n",
program_name,tempname);
fclose(new_fd);
goto fail;
}
if (-1 == rename(tempname,target->filename)) {
fprintf(stderr,
"%s: Failed to replace %s\n",
program_name,target->filename);
fclose(new_fd);
goto fail;
}
fclose(target->file);
target->file = new_fd;
free(tempname);
}
static int master P_((int argc, char *argv[], int x));
static int master(argc, argv, x)
int argc;
char *argv[];
int x;
{
int read_pipe;
int t;
int c;
int PID;
int w;
S__ status;
FILE *fd = NULL;
struct log_entries * last = NULL;
struct stat X;
char *X1;
int remove_count;
struct log_instance LI;
clear_log_instance(&LI);
installer_root = "/";
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-R", argv[x])) {
installer_root = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
register_module = argv[x+1];
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if ('\0' == installer_root[0]) {
fprintf(stderr,"%s: -R '' invalid\n",
argv[0]);
return 1; /* FAILURE */
}
if (stat(installer_root,&X) < 0) {
fprintf(stderr,"%s: -R %s invalid\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
! S_ISDIR(X.st_mode)
#else
S_IFDIR != (X.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,"%s: -R %s invalid (not a directory)\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
/* We use open instead of fopen so that we can create file
and not truncate existing file
*/
LI.filename = filelist;
if (0 != strcmp(installer_root,"/")) {
int l = strlen(filelist) + strlen(installer_root) +2;
LI.filename = malloc(l);
if (!LI.filename) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
return 1; /* FAILURE */
}
sprintf(LI.filename,"%s%s",installer_root,filelist);
}
/* HACK */
X1 = strrchr(LI.filename,'/');
if (X1) {
char *Z = strdup(LI.filename);
if (Z) {
X1 = strrchr(Z,'/');
*X1 = '\0';
make_package_dir(Z,installer_root);
if (0 == mkdir(Z,0755)) {
fprintf(stdout,
"%s: Directory %s created\n",
program_name,Z);
} else if (errno != EEXIST) {
fprintf(stderr,
"%s: Failed to create %s directory\n",
program_name,Z);
exit(1);
}
free(Z);
}
}
t = open(LI.filename,O_RDWR|O_CREAT,0644);
if (t < 0) {
fprintf(stderr,
"%s: Failed to create or open file %s on %s: %s\n",
program_name,filelist,installer_root, LI.filename);
return 1; /* FAILURE */
}
fprintf(stdout,"%s: Creating %s\n",program_name,LI.filename);
LI.file = fdopen(t,"r+");
if (! LI.file) {
fprintf(stderr,"%s: fdopen() failed\n",program_name);
close(t);
return 1; /* FAILURE */
}
c = fgetc(LI.file);
if (EOF != c) {
if (c != '[') {
fprintf(stderr,
"%s: File %s is not elmregister filelist\n",
program_name,LI.filename);
close(t);
return 1; /* FAILURE */
}
ungetc(c,LI.file); /* add_bytes reread character */
add_entries(& LI);
}
last = add_last(&LI);
read_pipe = create_pipe(argc,argv,x,&PID,installer_root,register_module);
fd = fdopen(read_pipe,"r");
if (!fd) {
fprintf(stderr,"%s: fdopen() failed\n",program_name);
close(read_pipe);
return 1; /* FAILURE */
}
log_copy_loop(fd,&LI,last);
remove_unlinked(&LI,installer_root,&remove_count);
if (remove_count > 0)
rewrite_list(&LI);
if (EOF == fclose(LI.file)) {
fprintf(stderr,
"%s: Write(?) failed on closing of file: %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
fclose(fd);
while ((w =
#ifdef HASWAITPID
waitpid(PID,&status,0)
#else
wait(status)
#endif
) != PID)
if (w == -1 && errno != EINTR)
break;
if (w != PID || status != 0) {
fprintf(stderr,
"%s: Failed to run %s\n",
program_name,argv[x]);
return 1; /* FAILURE */
}
/* NOTE: LI leaked ... */
return 0;
}
static char * rel_path = ""; /* Path to prepended
to log written on pipe
?? is this needed ??
*/
/* Returns: 'S' relpath is relative to source
'T' relpath is relative to installer_root
"//" on arg is supposed to be mark for $ELM_ROOT
*/
static int split_file P_((char *arg, char **fullpath, char **relpath));
static int split_file(arg,fullpath,relpath)
char *arg;
char **fullpath;
char **relpath; /* relpath have rel_path prepended
is original was relative */
{
char *ptr = strstr(arg,"//");
int L = strlen(installer_root);
while (L > 0 && '/' == installer_root[L-1])
L--;
if (ptr && '/' == arg[0]) { /* TARGET FILE -- installer prefix given */
if (ptr-arg != L &&
0 != strncmp(arg,installer_root,L)) {
fprintf(stderr,
"%s: prefix %.*s on %s do not match with $ELM_ROOT=%s\n",
program_name,ptr-arg,arg,arg,installer_root);
exit(1); /* FAILURE */
}
*fullpath = strdup(arg);
if (!*fullpath) {
fprintf(stderr,
"%s: strdup failed\n",
program_name);
exit(1); /* FAILURE */
}
while ('/' == *ptr)
ptr++;
*relpath = strdup(ptr);
if (!*relpath) {
fprintf(stderr,
"%s: strdup failed\n",
program_name);
exit(1); /* FAILURE */
}
return 'T'; /* relpath is relative to installer_root */
} else if ('/' == arg[0]) { /* TARGET FILE -- installer prefix not given */
int x = L + 3 + strlen(arg);
char *Y = arg;
while('/' == *Y)
Y++;
*fullpath = malloc(x);
if (!*fullpath) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,x);
exit(1); /* FAILURE */
}
strncpy(*fullpath,installer_root,L);
strcpy(*fullpath +L,"//");
strcpy(*fullpath +L+2,Y);
*relpath = strdup(Y);
if (!*relpath) {
fprintf(stderr,
"%s: strdup failed\n",
program_name);
exit(1); /* FAILURE */
}
return 'T'; /* relpath is relative to installer_root */
} else { /* SOURCE FILE ... */
int y = strlen(rel_path);
int x = y + strlen(arg) + 1;
*fullpath = strdup(arg);
if (!*fullpath) {
fprintf(stderr,
"%s: strdup failed\n",
program_name);
exit(1); /* FAILURE */
}
*relpath = malloc(x);
if (!*relpath) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,x);
exit(1); /* FAILURE */
}
strcpy(*relpath,rel_path);
strcpy(*relpath + y, arg);
return 'S'; /* relpath is relative to source */
}
}
static char * gen_tempname P_((char * target));
static char * gen_tempname(target)
char * target;
{
int l = strlen(target) + 10;
char *tempname = malloc(l);
if (!tempname) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
exit(1); /* FAILURE */
}
strcpy(tempname,target);
strcat(tempname,"~_~");
return tempname;
}
/* 0 == OK */
static int install_file P_((char * source, char * target,
uid_t user, gid_t group, int mode));
static int install_file(source,target,user,group,mode)
char * source;
char * target;
uid_t user;
gid_t group;
int mode;
{
char * tempname;
FILE * F, *S;
int c;
/* HACK */
char *Z = strdup(target);
if (Z) {
char * X1 = strrchr(Z,'/');
if (X1) {
*X1 = '\0';
if (0 == mkdir(Z,0755)) {
int r = 0;
if (user != (uid_t)-1 || group != (gid_t)-1) {
r = chown(Z,user,group);
}
fprintf(stdout,
"%s: Directory %s created%s\n",
program_name,Z,
r == -1 ? " (failed to set owner)" : "");
} else if (errno != EEXIST) {
fprintf(stderr,
"%s: Failed to create %s directory\n",
program_name,Z);
free(Z);
return 1; /* FAILURE */
}
}
free(Z);
}
tempname = gen_tempname(target);
if (0 == unlink(tempname)) {
fprintf(stderr,"%s: %s unlinked\n",program_name,tempname);
}
F = fopen(tempname,"w");
if (!F) {
fprintf(stderr,"%s: Failed to create %s\n",
program_name,tempname);
return 1; /* FAILURE */
}
S = fopen(source,"r");
if (!F) {
fprintf(stderr,"%s: Failed to read %s\n",
program_name,source);
fclose(F);
unlink(tempname);
return 1; /* FAILURE */
}
while (EOF != (c = getc(S))) {
if (putc(c,F) == EOF) {
fclose(F);
fail:
fprintf(stderr,"%s: Failed to write %s\n",
program_name,tempname);
fclose(S);
unlink(tempname);
return 1; /* FAILURE */
}
}
if (ferror(S)) {
fprintf(stderr,"%s: Failed to read %s\n",
program_name,source);
fclose(S);
fclose(F);
unlink(tempname);
return 1; /* FAILURE */
}
if (EOF == fclose(F)) {
goto fail;
}
if (-1 == rename(tempname,target)) {
fprintf(stderr,
"%s: Failed to replace %s\n",
program_name,target);
goto fail;
}
if (user != (uid_t)-1 || group != (gid_t)-1) {
if (-1 == chown(target,user,group)) {
fprintf(stderr,"%s: Failed to set owner of %s\n",
program_name,target);
}
}
if (-1 == chmod(target,mode)) {
fprintf(stderr,"%s: Failed to set mode of %s\n",
program_name,target);
}
fprintf(stdout,"%s: File %s installed\n",
program_name,target);
fclose(S);
free(tempname);
return 0;
}
static void copy_dir P_((char *src,char *trg, char *rel,
struct log_instance *LI,
struct log_entries * last,
char *register_module));
#ifdef DIROPS
#if DIROPS == USE_DIRENT
#include <dirent.h>
#endif /* DIROPS == USE_DIRENT */
#if DIROPS == USE_SYSDIR
#include <sys/dir.h>
#endif /* DIROPS == USE_SYSDIR */
static void copy_dir(src,trg,rel,LI,last, register_module)
char *src;
char *trg;
char *rel;
struct log_instance *LI;
struct log_entries * last;
char *register_module;
{
DIR * handle;
#if DIROPS == USE_DIRENT
struct dirent * Xptr;
#endif /* DIROPS == USE_DIRENT */
#if DIROPS == USE_SYSDIR
struct direct * Xptr;
#endif /* DIROPS == USE_SYSDIR */
int slen = strlen(src);
int tlen = strlen(trg);
int rlen = strlen(rel);
handle = opendir(src);
if (!handle) {
fprintf(stderr,
"%s: Failed to open directory %s\n",
program_name,src);
exit(1); /* FAILURE */
}
fprintf(stdout,
"%s: Copying directory %s -> %s:\n",
program_name,src,trg);
if (0 == mkdir(trg,0755)) {
fprintf(stdout,
"%s: Directory %s created\n",
program_name,trg);
} else if (errno != EEXIST) {
fprintf(stderr,
"%s: Failed to create %s directory\n",
program_name,trg);
exit (1); /* FAILURE */
}
while (NULL != (Xptr = readdir(handle))) {
if ('.' != Xptr->d_name[0]) {
int L;
struct stat X;
char *fullname;
int elen;
#if DIROPS == USE_DIRENT
char * entryname = strdup(Xptr->d_name);
if (!entryname) {
fprintf(stderr,"%s: strdup failed: %s\n",
program_name,Xptr->d_name);
exit(1); /* FAILURE */
}
#endif /* DIROPS == USE_DIRENT */
#if DIROPS == USE_SYSDIR
char * entryname = malloc(Xptr->d_namlen+1);
if (!entryname) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,Xptr->d_namlen+1);
exit(1); /* FAILURE */
}
strncpy(entryname,Xptr->d_name,Xptr->d_namlen);
entryname[Xptr->d_namlen] = '\0';
#endif /* DIROPS == USE_SYSDIR */
elen = strlen(entryname);
L = elen + 3 + slen;
fullname = malloc(L);
if (!fullname) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,L);
exit(1); /* FAILURE */
}
strcpy(fullname,src);
strcat(fullname,"/");
strcat(fullname,entryname);
if (stat(fullname,&X) < 0) {
fprintf(stderr,"%s: Can't stat %s\n",
program_name,fullname);
exit(1); /* FAILURE */
}
if (
#ifdef S_ISREG
S_ISREG(X.st_mode)
#else
S_IFREG == (buf.st_mode & S_IFMT)
#endif
) {
int l2 = tlen + 3 + elen;
char * fulltrgname = malloc(l2);
char * relname;
int l3;
if (!fulltrgname) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l2);
exit(1); /* FAILURE */
}
strcpy(fulltrgname,trg);
strcat(fulltrgname,"/");
strcat(fulltrgname,entryname);
if (0 != install_file(fullname,fulltrgname, (uid_t)-1, (gid_t)-1,
X.st_mode & 0777)) {
fprintf(stderr,
"%s: Install %s -> %s failed\n",
program_name,
fullname,fulltrgname);
exit(1); /* FAILURE */
}
l3 = rlen + 3 + elen;
relname = malloc(l3);
if (!relname) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l3);
exit(1); /* FAILURE */
}
strcpy(relname,rel);
strcat(relname,"/");
strcat(relname,entryname);
if (!last)
log_it("s",relname,"-","-", X.st_mode & 0777,
register_module);
else {
char buffer[ MAX_PIPE_LOG];
char *ptr;
char mode_s[6];
int rname = strlen(relname);
int L;
struct log_record L1;
int module_ptr = -1;
int command_ptr = -1;
int user_ptr = -1;
int group_ptr = -1;
int mode_ptr = -1;
int args_ptr[1];
int argnum = 0;
sprintf(mode_s,"%05o",X.st_mode & 0777);
ptr = buffer;
if (register_module) {
int l = strlen(register_module);
add_to_buffer(buffer, sizeof buffer,&ptr,"m",1);
module_ptr = ptr-buffer; add_to_buffer(buffer, sizeof buffer,&ptr,
register_module,l);
}
command_ptr = ptr-buffer; add_to_buffer(buffer, sizeof buffer,&ptr,"s",1);
user_ptr = ptr-buffer; add_to_buffer(buffer, sizeof buffer,&ptr,"-",1);
group_ptr = ptr-buffer; add_to_buffer(buffer, sizeof buffer,&ptr,"-",1);
mode_ptr = ptr-buffer; add_to_buffer(buffer, sizeof buffer,&ptr,mode_s,5);
args_ptr[argnum++] =
ptr-buffer; add_to_buffer(buffer, sizeof buffer,&ptr,relname,rname);
/* NO terminating NL to buffer */
L = ptr - buffer;
if (L > MAX_PIPE_LOG-2) {
fprintf(stderr,"%s: Can't register file, string too long: %d\n",
program_name,L);
exit(1);
}
L1.buffer = malloc(L);
if (!L1.buffer) {
fprintf(stderr,"%s: malloc %d bytes failed\n",program_name,
L);
exit(1);
}
L1.buffer_len = L;
L1.command_letter = 's';
parse_log_tail(&L1,buffer,L,module_ptr,command_ptr,user_ptr,
group_ptr,mode_ptr,args_ptr,argnum);
last -> log = realloc(last -> log,
(last -> log_count+1) *
sizeof (last -> log[0]));
if (! last->log) {
fprintf(stderr,
"%s: Failed to realloc %d items (file %s)\n",
program_name,last -> log_count+1,LI->filename);
exit(1);
}
last -> log[last -> log_count] = L1;
last -> log_count++;
if (L1.buffer_len != fwrite(L1.buffer,1,L1.buffer_len,LI->file)) {
fprintf(stderr,
"%s: write error (file %s)\n",
program_name,LI->filename);
fclose(LI->file);
exit (1); /* FAILURE */
}
putc('\n',LI->file);
}
free(fulltrgname);
free(relname);
}
free(entryname);
free(fullname);
}
}
closedir(handle);
}
#else
static void copy_dir(src,trg, char *rel,LI,last,register_module)
char *src;
char *trg;
char *rel;
struct log_instance *LI;
struct log_entries * last;
char *register_module;
{
char * x = strrchr(trg,'/');
int w;
int pid;
S__ status;
if (!x) {
fprintf(stderr,"%s: No / on path: %s\n",
program_name,trg);
exit(1); /* FAILURE */
}
fflush(stdout);
pid = fork();
if (-1 == pid) {
fprintf(stderr,"%s: fork failed\n",
program_name);
exit(1); /* FAILURE */
}
if (0 == pid) {
/* because this is fork()ed, this have
on own address space, and trg
on parent is NOT affected...
*/
*x = '\0';
fprintf(stdout,
"%s: Copying %s to %s(/%s) with %s -r\n",
program_name,src,trg,x+1,ELMREGISTER_CP);
fflush(stdout);
execlp(ELMREGISTER_CP,ELMREGISTER_CP,"-r",
src,trg,NULL);
fprintf(stderr,
"%s: Failed to EXECute %s\n",program_name,ELMREGISTER_CP);
fflush(stderr);
_exit(127);
}
while ((w =
#ifdef HASWAITPID
waitpid(pid,&status,0)
#else
wait(status)
#endif
) != pid)
if (w == -1 && errno != EINTR)
break;
if (w != pid || status != 0) {
fprintf(stderr,
"%s: Failed to copy %s to %s (with using %s)\n",
program_name,src,trg,ELMREGISTER_CP);
exit(1); /* FAILURE */
}
}
#endif /* DIROPS */
static void make_argcopy P_((char *arg, int arg_len, char * stage_subdir,
char *register_module));
static void make_argcopy(arg,arg_len, stage_subdir, register_module)
char *arg;
int arg_len;
char * stage_subdir;
char *register_module;
{
struct stat X;
char bufferz[256];
int p;
int n;
int R;
char *y;
char * source_f = NULL;
char * source_r = NULL;
char * target_f = NULL;
char * target_r = NULL;
if (arg_len >= 256) {
fprintf(stderr,
"%s: Argument too long: %s\n",
program_name,arg);
return; /* FAILURE */
}
strcpy(bufferz,arg+1);
if (bufferz[arg_len-2] != '}') {
fprintf(stderr,
"%s: OOPS %s\n",
program_name,
bufferz);
exit(1);
}
bufferz[arg_len-2] = '\0';
R = stat(bufferz,&X);
p = split_file(bufferz, &source_f, &source_r);
if ('T' == p) {
/* if ARG is already on target on, just register it ...
May also be directory
*/
if (0 != R)
log_it(arg,source_r,"-", "-", 0444, register_module);
else
log_it(arg,source_r,"-", "-", X.st_mode & 0777,
register_module);
free(source_r);
free(source_f);
return;
}
if (0 != R) {
fprintf(stderr,
"%s: Argument %s (filename %s) does not exists?\n",
program_name,arg, bufferz);
exit(1);
}
if ('/' != stage_dir[0]) {
fprintf(stderr,
"%s: stage dir %s does not have absolute\n",
program_name,stage_dir);
exit(1);
}
n = strlen(stage_dir) + arg_len;
if (stage_subdir) {
n += strlen(stage_subdir) + 1;
}
target_r = malloc(n);
if (!target_r) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,n);
exit(1); /* FAILURE */
}
strcpy(target_r,stage_dir+1);
strcat(target_r,"/");
if (stage_subdir) {
char * Y;
int n1;
strcat(target_r,stage_subdir);
n1 = strlen(installer_root) + strlen(target_r) + 3;
Y = malloc(n1);
if (!Y) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,n1);
exit(1); /* FAILURE */
}
strcpy(Y,installer_root);
strcat(Y,"/");
strcat(Y,target_r);
if (0 == mkdir(Y,0755)) {
fprintf(stdout,
"%s: Directory %s created\n",
program_name,Y);
/* HACK -- Do not use letter 'M', because it can break handling of
* stored argument list
*/
log_it(IMPARGDIR,target_r,"-", "-", 0755,
register_module);
} else if (errno != EEXIST) {
fprintf(stderr,
"%s: Failed to create %s directory\n",
program_name,Y);
exit(1);
}
free(Y);
strcat(target_r,"/");
}
y = strrchr(bufferz,'/');
if (y)
strcat(target_r,y+1);
else
strcat(target_r,bufferz);
n = strlen(installer_root) + strlen(target_r) + 3;
target_f = malloc(n);
if (!target_f) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,n);
exit(1); /* FAILURE */
}
strcpy(target_f,installer_root);
strcat(target_f,"/");
strcat(target_f,target_r);
if (
#ifdef S_ISDIR
S_ISDIR(X.st_mode)
#else
S_IFDIR == (buf.st_mode & S_IFMT)
#endif
) {
copy_dir(bufferz,target_f,target_r,NULL,NULL,register_module);
log_it(arg,target_r,"-", "-", X.st_mode & 0777,
register_module);
}
else {
/* Just normal file */
if (0 != install_file(source_f,target_f, (uid_t)-1, (gid_t)-1,
X.st_mode & 0777)) {
fprintf(stderr,
"%s: Install %s -> %s failed\n",
program_name,
source_r,target_r);
exit(1); /* FAILURE */
}
log_it(arg,target_r,"-", "-", X.st_mode & 0777,
register_module);
}
free(source_r);
free(source_f);
free(target_r);
free(target_f);
}
static int command P_((int argc, char *argv[], int x));
static int command(argc, argv, x)
int argc;
char *argv[];
int x;
{
int fd;
struct stat X;
char * cmd;
if (!register_pipe) {
fprintf(stderr,"%s: $ELM_INSTALLER is missing\n",
argv[0]);
return 1; /* FAILURE */
}
if (!installer_root) {
fprintf(stderr,"%s: $ELM_ROOT is missing\n",
argv[0]);
return 1; /* FAILURE */
}
fd = atoi(register_pipe);
if (fd < 1) {
fprintf(stderr,"%s: $ELM_INSTALLER=%s invalid\n",
argv[0],register_pipe);
return 1; /* FAILURE */
}
if (fstat(fd,&X) < 0) {
fprintf(stderr,"%s: $ELM_INSTALLER=%s invalid\n",
argv[0],register_pipe);
return 1; /* FAILURE */
}
register_fd = fd;
if (stat(installer_root,&X) < 0) {
fprintf(stderr,"%s: $ELM_ROOT=%s invalid\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
! S_ISDIR(X.st_mode)
#else
S_IFDIR != (buf.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,"%s: $ELM_ROOT=%s invalid (not a directory)\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-R", argv[x])) {
int l;
rel_path = argv[x+1];
x += 2;
l = strlen(rel_path);
if (l > 0 && '/' != rel_path[l-1]) {
char * X = malloc(l+2);
if (!X) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
argv[0],l+2);
return 1; /* FAILURE */
}
strncpy(X,rel_path,l+2);
X[l] = '/';
fprintf(stdout,"%s: Adding / to -R %s: %s\n",
argv[0],rel_path,X);
rel_path = X;
}
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
register_module = argv[x+1];
x += 2;
} else {
break;
}
}
/* COPY mode ?? */
if (x < argc &&
0 == strcmp("rm", argv[x])) {
char buffer[ MAX_PIPE_LOG];
char *ptr;
int j;
char * translated [MAX_ARGS+1];
char * relative [MAX_ARGS+1];
int i;
int L = 4;
x++;
if (argc - x >= MAX_ARGS) {
fprintf(stderr,
"%s: %s too many arguments\n",
argv[0], argv[x-1]);
return 1; /* FAILURE */
}
i = 0;
for (j = x; j < argc; j++) {
if ('T' != split_file(argv[j],& translated[i], & relative[i])) {
fprintf(stderr,
"%s: file %s does not look like remove target\n",
argv[0],argv[x]);
return 1; /* FAILURE */
}
i++;
L += strlen(argv[j]) +1;
}
translated[i] = NULL;
relative[i] = NULL;
if (L > MAX_PIPE_LOG-2) {
fprintf(stderr,"%s: Can't register command, string too long: %d\n",
program_name,L);
return 1; /* FAILURE */
}
for (j = 0; j < i; j++) {
if (0 == unlink(translated[j])) {
fprintf(stdout,
"%s: File %s removed\n",
program_name,translated[j]);
}
}
ptr = buffer;
if (register_module) {
int l = strlen(register_module);
add_to_buffer(buffer, sizeof buffer,&ptr,"m",1);
add_to_buffer(buffer, sizeof buffer,&ptr,register_module,l);
}
add_to_buffer(buffer, sizeof buffer,&ptr,"R",1);
for (j = 0; j < i; j++) {
int l = strlen(relative[j]);
add_to_buffer(buffer, sizeof buffer,&ptr,relative[j],l);
}
*ptr++ = '\n'; /* Terminating NL on line */
L = ptr - buffer;
if (L > MAX_PIPE_LOG-2) {
fprintf(stderr,"%s: Can't register command, string too long: %d\n",
program_name,L);
return 1; /* FAILURE */
}
/* We have better to able write whole string at ONCE,
or otherwise two different writes from different processes
are mixed on pipe ... (ie. if paraller make)
*/
write_once(register_fd,buffer,L);
} else if (x < argc &&
0 == strcmp("link", argv[x])) {
char buffer[ MAX_PIPE_LOG];
char *ptr;
char * translated [2];
char * relative [2];
char * tempname;
int L = 4;
int i,j;
int Exit_it = 0;
x++;
if (argc - x != 2) {
fprintf(stderr,
"%s: %s: 2 arguments required\n",
argv[0], argv[x-1]);
return 1; /* FAILURE */
}
i = 0;
for (j = x; j < argc; j++) {
if ('T' != split_file(argv[j],& translated[i], & relative[i])) {
fprintf(stderr,
"%s: file %s does not look like link target\n",
argv[0],argv[x]);
return 1; /* FAILURE */
}
i++;
L += strlen(argv[j]) +1;
}
if (L > MAX_PIPE_LOG-2) {
fprintf(stderr,"%s: Can't register command, string too long: %d\n",
program_name,L);
return 1; /* FAILURE */
}
tempname = gen_tempname(translated[1]);
if (0 == unlink(tempname)) {
fprintf(stderr,"%s: %s unlinked\n",program_name,tempname);
}
if (-1 == link(translated[0],tempname)) {
fprintf(stderr,
"%s: Failed to link %s to %s\n",
program_name,translated[0],tempname);
Exit_it = 1;
goto fail3;
}
if (-1 == rename(tempname,translated[1])) {
fprintf(stderr,
"%s: Failed to replace %s\n",
program_name,translated[1]);
Exit_it = 1;
goto fail3;
}
fprintf(stdout,"%s: Link %s == %s installed\n",program_name,translated[1],translated[0]);
ptr = buffer;
if (register_module) {
int l = strlen(register_module);
add_to_buffer(buffer, sizeof buffer,&ptr,"m",1);
add_to_buffer(buffer, sizeof buffer,&ptr,register_module,l);
}
add_to_buffer(buffer, sizeof buffer,&ptr,"L",1);
for (j = 0; j < i; j++) {
int l = strlen(relative[j]);
add_to_buffer(buffer, sizeof buffer,&ptr,relative[j],l);
}
*ptr++ = '\n'; /* Terminating NL on line */
L = ptr - buffer;
if (L > MAX_PIPE_LOG-2) {
fprintf(stderr,"%s: Can't register command, string too long: %d\n",
program_name,L);
return 1; /* FAILURE */
}
/* We have better to able write whole string at ONCE,
or otherwise two different writes from different processes
are mixed on pipe ... (ie. if paraller make)
*/
write_once(register_fd,buffer,L);
fail3:
free(tempname);
for (i =0; i < 2; i++) {
free(translated[i]);
free(relative[i]);
}
if (Exit_it)
return Exit_it; /* FAILURE */
} else if (x < argc &&
(cmd = argv[x]) &&
(
0 == strcmp("copy", argv[x]) ||
0 == strcmp("copydoc", argv[x]) ||
0 == strcmp("mkdir", argv[x])
)) {
uid_t id_user = (uid_t)-1;
gid_t id_group = (gid_t)-1;
char * s_user = "-";
char * s_group = "-";
mode_t f_mode = 0; /* Use mode of source file */
x++;
while (x < argc && '-' == argv[x][0]) {
if (0 == strcmp(argv[x],"-o")) {
struct passwd * p;
if ((uid_t)-1 != id_user) {
fprintf(stderr,
"%s: Duplicate -o option\n",
argv[0]);
return 1; /* FAILURE */
}
if (x+1 >= argc) {
fprintf(stderr,"%s: Missing user after -o option\n",
argv[0]);
return 1; /* FAILURE */
}
p = getpwnam(argv[x+1]);
if (!p) {
fprintf(stderr,
"%s: -o option: user %s do not found\n",
argv[0],
argv[x+1]);
return 1; /* FAILURE */
}
id_user = p->pw_uid;
s_user = argv[x+1];
if ((gid_t)-1 == id_group)
id_group = p->pw_gid;
x += 2;
}
else if (0 == strcmp(argv[x],"-g")) {
struct group *g;
if (x+1 >= argc) {
fprintf(stderr,
"%s: Missing group after -g option\n",
argv[0]);
return 1; /* FAILURE */
}
g = getgrnam(argv[x+1]);
if (!g) {
fprintf(stderr,
"%s: -g option: group %s do not found\n",
argv[0],
argv[x+1]);
return 1; /* FAILURE */
}
id_group = g->gr_gid;
s_group = argv[x+1];
x += 2;
}
else if (0 == strcmp(argv[x],"-m")) {
char * ptr;
if (x+1 >= argc) {
fprintf(stderr,
"%s: Missing octal mode after -m option\n",
argv[0]);
return 1; /* FAILURE */
}
f_mode = strtol(argv[x+1],&ptr,8);
if (*ptr != '\0') {
fprintf(stderr,
"%s: -m option: bad octal mode %s (character %c) \n",
argv[0],
argv[x+1],*ptr);
return 1; /* FAILURE */
}
x += 2;
}
else {
fprintf(stderr,
"%s: %s option unknown\n",
argv[0],argv[x]);
return 1; /* FAILURE */
}
}
if (0 == strcmp(cmd,"mkdir")) {
char * target_f = NULL;
char * target_r = NULL;
if ('T' != split_file(argv[x],&target_f,&target_r)) {
fprintf(stderr,
"%s: directory %s does not look like install target\n",
argv[0],argv[x]);
return 1; /* FAILURE */
}
x++;
if (x < argc) {
fprintf(stderr,
"%s: Too many arguments\n",argv[0]);
return 1; /* FAILURE */
}
if (0 == f_mode)
f_mode = 0755;
make_package_dir(target_f,installer_root);
if (0 == mkdir(target_f,f_mode)) {
int r = 0;
if (id_user != (uid_t)-1 || id_group != (gid_t)-1) {
r = chown(target_f,id_user,id_group);
}
fprintf(stdout,
"%s: Directory %s created%s\n",
program_name,target_f,
r == -1 ? " (failed to set owner)" : "");
} else if (errno != EEXIST) {
fprintf(stderr,
"%s: Failed to create %s directory\n",
program_name,target_f);
return 1; /* FAILURE */
}
log_it("M",target_r,s_user, s_group, f_mode,
register_module);
free(target_r); free(target_f);
} else {
struct stat X;
char * source_f = NULL;
char * source_r = NULL;
char * target_f = NULL;
char * target_r = NULL;
if (x >= argc) {
fprintf(stderr,
"%s: source file not given\n",argv[0]);
return 1; /* FAILURE */
}
if ('S' != split_file(argv[x],&source_f,&source_r)) {
fprintf(stderr,
"%s: file %s does not look like install source\n",
argv[0],argv[x]);
return 1; /* FAILURE */
}
x++;
if ('T' != split_file(argv[x],&target_f,&target_r)) {
fprintf(stderr,
"%s: file %s does not look like install target\n",
argv[0],argv[x]);
return 1; /* FAILURE */
}
x++;
if (x < argc) {
fprintf(stderr,
"%s: Too many arguments\n",argv[0]);
return 1; /* FAILURE */
}
if (0 != stat(source_f,&X)) {
fprintf(stderr,
"%s: File %s does not exists?\n",
program_name,source_f);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
S_ISDIR(X.st_mode)
#else
S_IFDIR == (buf.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,
"%s: %s is directory\n",
program_name,source_f);
return 1; /* FAILURE */
}
if (0 == f_mode)
f_mode = X.st_mode & 0777;
if (f_mode > 07777) {
fprintf(stderr,
"%s: file mode %05o illegal\n",
argv[0],
f_mode);
return 1; /* FAILURE */
}
if (0 != install_file(source_f,target_f, id_user, id_group, f_mode)) {
fprintf(stderr,
"%s: Install %s -> %s failed\n",
argv[0],
source_r,target_r);
return 1; /* FAILURE */
}
if (0 == strcmp("copydoc",cmd))
log_it("d",target_r,s_user, s_group, f_mode, register_module);
else
log_it("F",target_r,s_user, s_group, f_mode, register_module);
free(source_r); free(source_f);
free(target_r); free(target_f);
}
} else {
int j;
/* Execute program ( actually delay executing )*/
char buffer[ MAX_PIPE_LOG];
char *ptr;
char * stage_subdir = NULL;
int L = 4;
if (x < argc -1 && 0 == strcmp("-s", argv[x])) {
int l;
stage_subdir = argv[x+1];
x += 2;
}
if (argc - x >= MAX_ARGS) {
fprintf(stderr,
"%s: %s too many arguments\n",
argv[0], argv[x]);
return 1; /* FAILURE */
}
for (j = x; j < argc; j++) {
int z;
if ('{' == argv[j][0] && (z = strlen(argv[j])) && '}' == argv[j][z-1]) {
make_argcopy(argv[j],z, stage_subdir,register_module);
}
L += strlen(argv[j]) +1;
}
if (L > MAX_PIPE_LOG-2) {
fprintf(stderr,"%s: Can't register command, string too long: %d\n",
program_name,L);
return 1; /* FAILURE */
}
ptr = buffer;
if (register_module) {
int l = strlen(register_module);
add_to_buffer(buffer, sizeof buffer,&ptr,"m",1);
add_to_buffer(buffer, sizeof buffer,&ptr,register_module,l);
}
add_to_buffer(buffer, sizeof buffer,&ptr,"E",1);
for (j = x; j < argc; j++) {
int l = strlen(argv[j]);
add_to_buffer(buffer, sizeof buffer,&ptr,argv[j],l);
}
*ptr++ = '\n'; /* Terminating NL on line */
L = ptr - buffer;
if (L > MAX_PIPE_LOG-2) {
fprintf(stderr,"%s: Can't register command, string too long: %d\n",
program_name,L);
return 1; /* FAILURE */
}
/* We have better to able write whole string at ONCE,
or otherwise two different writes from different processes
are mixed on pipe ... (ie. if paraller make)
*/
write_once(register_fd,buffer,L);
}
return 0;
}
static void pick_one P_((struct log_record * ptr,
char **src,
int L,
uid_t *id_user,
gid_t *id_group,
int *mode,
int *is_dir));
static void pick_one(ptr,src,L,id_user,id_group,mode,is_dir)
struct log_record * ptr;
char **src;
int L;
uid_t *id_user;
gid_t *id_group;
int *mode;
int *is_dir;
{
struct passwd * p = NULL;
struct group * g = NULL;
struct stat X;
if (!ptr->arg_ptrs || !ptr->arg_ptrs[0]) {
fprintf(stderr,
"%s: [pick_one] '%c' no arg 0 \n",
program_name,ptr->command_letter);
exit(1); /* FAILURE */
}
*src = make_rooted(ptr,ptr->arg_ptrs[0],installer_root);
if (ptr->user_ptr && 0 != strcmp(ptr->user_ptr,"-")) {
p = getpwnam(ptr->user_ptr);
if (!p)
fprintf(stderr,
"%s: [pick_one] '%c' User %s not found\n",
program_name,ptr->command_letter,
ptr->user_ptr);
}
if (ptr->group_ptr && 0 != strcmp(ptr->group_ptr,"-")) {
g = getgrnam(ptr->group_ptr);
if (!g)
fprintf(stderr,
"%s: [pick_one] '%c' Group %s not found\n",
program_name,ptr->command_letter,
ptr->group_ptr);
}
if (stat(*src,&X) < 0) {
fprintf(stderr,
"%s: (note) %s : %s not accessible\n",
program_name,
ptr->arg_ptrs[0],*src);
*is_dir = -1;
*id_user = (uid_t)-1;
*id_group = (gid_t)-1;
*mode = 0555;
return;
}
if (p)
*id_user = p->pw_uid;
else
*id_user = X.st_uid;
if (g)
*id_group = g->gr_gid;
else if (p)
*id_group = p->pw_gid;
else
*id_group = X.st_gid;
if (ptr->mode_ptr && 0 != strcmp(ptr->mode_ptr,"-") &&
0 != strcmp(ptr->mode_ptr,"0")) {
char * x;
*mode = strtol(ptr->mode_ptr,&x,8);
if (*x || 0 == *mode)
goto failmode;
}
else {
failmode:
*mode = X.st_mode & 0777;
}
/* if directory ... */
if (
#ifdef S_ISDIR
S_ISDIR(X.st_mode)
#else
S_IFDIR == (buf.st_mode & S_IFMT)
#endif
) {
*is_dir = 1;
} else {
/* REGULAR */
*is_dir = 0;
}
}
static char * make_absolute P_((struct log_record * ptr, char *rel));
static char * make_absolute(ptr,rel)
struct log_record * ptr;
char *rel;
{
int l = strlen(rel) + 2;
char * translated = malloc(l);
if (!translated) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
exit (1); /* FAILURE */
}
if ('/' == rel[0]) {
fprintf(stderr,
"%s: entry '%c' -- Not relative? %s\n",
program_name,ptr->command_letter,rel);
translated[0] = '\0';
} else {
translated[0] = '/';
translated[1] = '\0';
}
strcat(translated,rel);
return translated;
}
static int filter_record P_((struct log_record *record,
char **module, int match_all));
static int filter_record(record,module,match_all)
struct log_record *record;
char **module;
int match_all;
{
int i;
if (module && module[0] &&
0 == strcmp(module[0], "all"))
return 1;
if (! record->module_ptr) {
if (!module)
return 1;
return 0;
}
if (match_all &&
0 == strcmp(record->module_ptr,"all"))
return 1;
if (!module)
return 0;
for (i = 0; module[i]; i++) {
if (0 == strcmp(record->module_ptr,
module[i]))
return 1;
}
return 0;
}
static int copy_list P_((struct log_entries *entry,
struct log_instance *source,
struct log_instance *target,
struct log_entries *last,
char **module));
static int copy_list(entry,source,target,last, module)
struct log_entries *entry;
struct log_instance *source;
struct log_instance *target;
struct log_entries *last;
char **module;
{
struct log_record * ptr;
int L = strlen(installer_root);
for (ptr = entry->log; ptr < entry->log + entry->log_count; ptr++) {
char * src = NULL;
uid_t id_user = (uid_t)-1;
gid_t id_group = (gid_t)-1;
int mode = 0555;
int is_dir = 0;
if (! filter_record(ptr,module,1))
continue;
switch (ptr->command_letter) {
char *trg;
case '\0': /* ENTRY DELETED */
break;
case 'E':
/* We do not execute on copy ... */
break;
case 'R':
{
int i;
for (i = 0; ptr->arg_ptrs[i] && i < MAX_ARGS; i++) {
char * translated = make_absolute(ptr,ptr->arg_ptrs[i]);
if (0 == unlink(translated)) {
fprintf(stdout,
"%s: File %s removed\n",
program_name,translated);
}
free(translated);
}
move_record(target,last,ptr);
}
break;
case 's':
/* Copying of directory does this ... */
break;
case '{': /* MUST BE handled on execute ... */
break;
case 'C':
fprintf(stdout,
"%s: Config file %s (%s) not copied\n",
program_name,ptr->arg_ptrs[0],src);
break;
case 'L':
/* Handled now on execute ... */
break;
case 'M':
pick_one(ptr,&src,L,&id_user,&id_group,&mode,&is_dir);
trg = src + L;
if (is_dir < 0) {
fprintf(stderr,
"%s: 'Source' directory %s does not exists\n",
program_name, src);
} else if (!is_dir) {
fprintf(stderr,
"%s: [copy_list] '%c' %s is NOT directory\n",
program_name,ptr->command_letter,
src);
free(src);
return 1; /* FAILURE */
}
if (0 == mkdir(trg,mode)) {
int r = chown(trg,id_user,id_group);
fprintf(r == -1 ? stderr : stdout,
"%s: Directory %s created%s\n",
program_name,trg,
r == -1 ? " (failed to set owner)" : "");
move_record(target,last,ptr);
} else if (errno != EEXIST) {
fprintf(stderr,
"%s: Failed to create %s directory\n",
program_name,trg);
free(src);
return 1; /* FAILURE */
}
break;
case 'F':
case 'd':
pick_one(ptr,&src,L,&id_user,&id_group,&mode,&is_dir);
trg = src + L;
if (is_dir < 0) {
fprintf(stderr,
"%s: [copy_list] '%c' Source file %s does not exists\n",
program_name,ptr->command_letter,
src);
free(src);
return 1; /* FAILURE */
} else if (is_dir) {
fprintf(stderr,
"%s: [copy_list] '%c' %s is directory\n",
program_name,ptr->command_letter,
src);
free(src);
return 1; /* FAILURE */
}
if (0 != install_file(src,trg,id_user,id_group,mode)) {
fprintf(stderr,
"%s: [copy_list] '%c' Failed to install %s : %s -> %s\n",
program_name,ptr->command_letter,
ptr->arg_ptrs[0],src,trg);
free(src);
return 1; /* FAILURE */
}
move_record(target,last,ptr);
break;
default:
fprintf(stderr,
"%s: [copy_list] Bad command letter: %c \n",
program_name,ptr->command_letter);
return 1;
}
if (src)
free(src);
}
return 0;
}
static struct log_record * on_other_module P_((struct log_instance *LI,
char *entry,
char **module));
static struct log_record * on_other_module(LI,entry,module)
struct log_instance *LI;
char *entry;
char **module;
{
int i;
for (i = 0; i < LI->entries_count; i++) {
struct log_record * ptr;
for (ptr = LI->entries[i].log;
ptr < LI->entries[i].log +
LI->entries[i].log_count; ptr++) {
/* Check if entry is mentioned on filtered module */
if (!filter_record(ptr,module,1)) {
switch (ptr->command_letter) {
case '\0': /* ENTRY DELETED */
break;
case '{':
case 's':
case 'F':
case 'd':
case 'C':
case 'M':
if (ptr->arg_ptrs && ptr->arg_ptrs[0] &&
0 == strcmp(ptr->arg_ptrs[0],entry))
return ptr;
break;
case 'L':
/* second argument is new name */
if (ptr->arg_ptrs && ptr->arg_ptrs[1] &&
0 == strcmp(ptr->arg_ptrs[1],entry))
return ptr;
break;
case 'E':
/* execute ... */
break;
case 'R':
/* remove ... */
break;
default:
fprintf(stderr,
"%s: [on_other_module] Bad command letter: %c \n",
program_name,ptr->command_letter);
}
}
}
}
return NULL;
}
static int on_current P_((struct log_instance *LI,char *entry));
static int on_current(LI,entry)
struct log_instance *LI;
char *entry;
{
int i;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
for (i = 0; i < LI->entries_count; i++) {
if (0 == strcmp(LI->entries[i].version, my_version)) {
struct log_record * ptr;
for (ptr = LI->entries[i].log;
ptr < LI->entries[i].log +
LI->entries[i].log_count; ptr++) {
switch (ptr->command_letter) {
case '\0': /* ENTRY DELETED */
break;
case '{':
case 's':
case 'F':
case 'd':
case 'C':
case 'M':
if (ptr->arg_ptrs && ptr->arg_ptrs[0] &&
0 == strcmp(ptr->arg_ptrs[0],entry))
return 1;
break;
case 'L':
/* second argument is new name */
if (ptr->arg_ptrs && ptr->arg_ptrs[1] &&
0 == strcmp(ptr->arg_ptrs[1],entry))
return 1;
break;
case 'E':
/* execute ... */
break;
case 'R':
/* remove ... */
break;
default:
fprintf(stderr,
"%s: [on_current] Bad command letter: %c \n",
program_name,ptr->command_letter);
}
}
}
}
return 0;
}
static void trim_list P_((struct log_entries *entry,
struct log_instance *source,
char **module));
static void trim_list(entry,source,module)
struct log_entries *entry;
struct log_instance *source;
char **module;
{
struct log_record * ptr;
for (ptr = entry->log; ptr < entry->log + entry->log_count; ptr++) {
if (! filter_record(ptr,module,0))
continue;
switch (ptr->command_letter) {
case '\0': /* ENTRY DELETED */
break;
case 'L':
/* second arg is new name */
if (ptr->arg_ptrs && ptr->arg_ptrs[1]) {
if (!on_current(source,ptr->arg_ptrs[1])) {
fprintf(stdout,
"%s: (%s) Keeping link %s from old version (was %s)\n",
program_name,source->filename,ptr->arg_ptrs[1],
ptr->arg_ptrs[0]
);
continue;
}
}
goto trim;
case 's':
if (ptr->arg_ptrs && ptr->arg_ptrs[0]) {
if (!on_current(source,ptr->arg_ptrs[0])) {
fprintf(stdout,
"%s: (%s) Stage file %s from old version found -- incomplete install?\n",
program_name,source->filename,ptr->arg_ptrs[0]);
continue;
}
}
goto trim;
case 'M':
case '{':
case 'F':
case 'd':
case 'C':
if (ptr->arg_ptrs && ptr->arg_ptrs[0]) {
if (!on_current(source,ptr->arg_ptrs[0])) {
if ('M' != ptr->command_letter)
fprintf(stdout,
"%s: (%s) Keeping file %s from old version\n",
program_name,source->filename,ptr->arg_ptrs[0]);
continue;
}
}
/* FALLTHRU */
case 'R': /* Trim delete ... */
case 'E': /* Trim execute ... */
trim:
if (ptr->buffer) {
free(ptr->buffer);
ptr->buffer = NULL;
}
if (ptr->arg_ptrs) {
free(ptr->arg_ptrs);
ptr->arg_ptrs = NULL;
}
ptr->command_letter = '\0'; /* ENTRY DELETED */
break;
default:
fprintf(stderr,
"%s: [trim_list] Bad command letter: %c \n",
program_name,ptr->command_letter);
}
}
}
static int unstage_list P_((struct log_entries *entry,
struct log_instance *source,
char **module));
static int unstage_list(entry,source,module)
struct log_entries *entry;
struct log_instance *source;
char **module;
{
int exit_stat = 0;
struct log_record * ptr;
int X = strlen(stage_dir);
for (ptr = entry->log; ptr < entry->log + entry->log_count; ptr++) {
int ok = 0;
if (! filter_record(ptr,module,0))
continue;
switch (ptr->command_letter) {
case '\0': /* ENTRY DELETED */
break;
case 'E':
ok = 1; /* JUST CLEAN */
break;
case 's':
case '{':
if (ptr->arg_ptrs && ptr->arg_ptrs[0]) {
char *ab = make_absolute(ptr,ptr->arg_ptrs[0]);
if (0 == strncmp(stage_dir,ab,X)) {
struct log_record *other =
on_other_module(source,ptr->arg_ptrs[0],module);
struct stat X;
if (stat(ab,&X) < 0)
ok = 1; /* Assume that cleared */
else if (
#ifdef S_ISDIR
S_ISDIR(X.st_mode)
#else
S_IFDIR == (buf.st_mode & S_IFMT)
#endif
) {
if (0 == rmdir(ab)) {
fprintf(stdout,
"%s: Stage directory %s uninstalled\n",
program_name,ab);
ok = 1;
}
} else {
if (other) {
fprintf(stdout,
"%s: Keeping stage file %s, used by %s package/module\n",
program_name,ab,
other->module_ptr ? other->module_ptr : "main");
ok = 1; /* Remove double reference */
} else if (0 == unlink(ab)) {
fprintf(stdout,
"%s: Stage file %s uninstalled\n",
program_name,ab);
ok = 1;
} else {
fprintf(stderr,
"%s: Can't unlink %s\n",
program_name,ab);
exit_stat = 1;
}
}
} else {
fprintf(stdout,
"%s: Ignoring entry %s -- not in stage area (%s)\n",
program_name,ab,stage_dir);
ok = 1; /* JUST CLEAN */
}
free(ab);
}
break;
}
if (ok) {
if (ptr->buffer) {
free(ptr->buffer);
ptr->buffer = NULL;
}
if (ptr->arg_ptrs) {
free(ptr->arg_ptrs);
ptr->arg_ptrs = NULL;
}
ptr->command_letter = '\0'; /* ENTRY DELETED */
}
}
return exit_stat;
}
static dev_t this_program_dev = 0;
static ino_t this_program_ino = 0;
static int this_program = 0;
static int uninstall_list P_((struct log_entries *entry,
struct log_instance *source,
char **module));
static int uninstall_list(entry,source,module)
struct log_entries *entry;
struct log_instance *source;
char **module;
{
int exit_stat = 0;
struct log_record * ptr;
int X = strlen(stage_dir);
for (ptr = entry->log; ptr < entry->log + entry->log_count; ptr++) {
int ok = 0;
if (! filter_record(ptr,module,0))
continue;
switch (ptr->command_letter) {
case '\0': /* ENTRY DELETED */
break;
case 'L':
/* second arg is new name */
if (ptr->arg_ptrs && ptr->arg_ptrs[1]) {
char *ab = make_absolute(ptr,ptr->arg_ptrs[1]);
struct log_record *other =
on_other_module(source,ptr->arg_ptrs[1],module);
struct stat X;
if (stat(ab,&X) < 0) {
if (ENOENT == errno)
ok = 1;
else {
fprintf(stderr,
"%s: Can't stat %s\n",
program_name,ab);
exit_stat = 1;
}
} else if (
#ifdef S_ISLNK
! S_ISREG(X.st_mode)
#else
S_IFREG != (X.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,
"%s: Name %s is not regular file (link)\n",
program_name,ab);
} else if (other) {
fprintf(stdout,
"%s: Keeping link %s, used by %s package/module\n",
program_name,ab,
other->module_ptr ? other->module_ptr : "main");
ok = 1; /* Remove double reference */
} else if ((!module || !module[0] || 0 != strcmp(module[0],"all")) &&
(X.st_dev == this_program_dev &&
X.st_ino == this_program_ino ||
0 == strcmp(program_name,ab))) {
fprintf(stdout,
"%s: Keeping link %s, is this program\n",
program_name,ab);
this_program++;
} else if (0 == unlink(ab)) {
fprintf(stdout,
"%s: Link %s uninstalled\n",
program_name,ab);
ok = 1;
} else if (ENOENT == errno)
ok = 1;
else {
fprintf(stderr,
"%s: Can't unlink %s\n",
program_name,ab);
exit_stat = 1;
}
free(ab);
}
break;
case 'M': /* No failure if directory can't be uninstalled */
if (ptr->arg_ptrs && ptr->arg_ptrs[0]) {
char *ab = make_absolute(ptr,ptr->arg_ptrs[0]);
if (0 == rmdir(ab)) {
fprintf(stdout,
"%s: Directory %s uninstalled\n",
program_name,ab);
ok = 1;
} else if (ENOENT == errno)
ok = 1;
free(ab);
}
break;
case 'E':
case 'R':
ok = 1; /* JUST CLEAN */
break;
case 'F':
case 'd':
case 's': /* also handled by unstage_list() */
if (ptr->arg_ptrs && ptr->arg_ptrs[0]) {
char *ab = make_absolute(ptr,ptr->arg_ptrs[0]);
struct log_record *other =
on_other_module(source,ptr->arg_ptrs[0],module);
struct stat X;
if (stat(ab,&X) < 0) {
if (ENOENT == errno)
ok = 1;
else {
fprintf(stderr,
"%s: Can't stat %s\n",
program_name,ab);
exit_stat = 1;
}
} else if (
#ifdef S_ISREG
! S_ISREG(X.st_mode)
#else
S_IFREG != (X.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,
"%s: Name %s is not regular file\n",
program_name,ab);
} else if (other) {
fprintf(stdout,
"%s: Keeping file %s, used by %s package/module\n",
program_name,ab,
other->module_ptr ? other->module_ptr : "main");
ok = 1; /* Remove double reference */
} else if ((!module || !module[0] || 0 != strcmp(module[0],"all")) &&
(X.st_dev == this_program_dev &&
X.st_ino == this_program_ino ||
0 == strcmp(program_name,ab))) {
fprintf(stdout,
"%s: Keeping file %s, is this program\n",
program_name,ab);
this_program++;
} else if (0 == unlink(ab)) {
fprintf(stdout,
"%s: File %s uninstalled\n",
program_name,ab);
ok = 1;
} else if (ENOENT == errno)
ok = 1;
else {
fprintf(stdout,
"%s: Can't unlink %s\n",
program_name,ab);
exit_stat = 1;
}
free(ab);
}
break;
case 'C':
if (ptr->arg_ptrs && ptr->arg_ptrs[0]) {
char *ab = make_absolute(ptr,ptr->arg_ptrs[0]);
struct log_record *other =
on_other_module(source,ptr->arg_ptrs[0],module);
struct stat X;
if (stat(ab,&X) < 0) {
if (ENOENT == errno)
ok = 1;
else {
fprintf(stderr,
"%s: Can't stat %s\n",
program_name,ab);
exit_stat = 1;
}
} else if (
#ifdef S_ISREG
! S_ISREG(X.st_mode)
#else
S_IFREG != (X.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,
"%s: Name %s is not regular file\n",
program_name,ab);
} else if (other) {
fprintf(stdout,
"%s: Keeping config file %s, used by %s package/module\n",
program_name,ab,
other->module_ptr ? other->module_ptr : "main");
ok = 1; /* Remove double reference */
} else if (0 == unlink(ab)) {
fprintf(stdout,
"%s: Config file %s uninstalled\n",
program_name,ab);
ok = 1;
} else if (ENOENT == errno)
ok = 1;
else {
fprintf(stdout,
"%s: Can't unlink %s\n",
program_name,ab);
exit_stat = 1;
}
free(ab);
}
break;
case '{': /* SHOULD ALREADY BE HANDLED unstage_list() */
break;
}
if (ok) {
if (ptr->buffer) {
free(ptr->buffer);
ptr->buffer = NULL;
}
if (ptr->arg_ptrs) {
free(ptr->arg_ptrs);
ptr->arg_ptrs = NULL;
}
ptr->command_letter = '\0'; /* ENTRY DELETED */
}
}
return exit_stat;
}
static int replay_list P_((struct log_entries *entry,
struct log_instance *source,
struct log_instance *target,
struct log_entries * last,
char **module));
static int replay_list(entry,source,target,last, module)
struct log_entries *entry;
struct log_instance *source;
struct log_instance *target;
struct log_entries * last;
char **module;
{
struct log_record * ptr;
struct log_record * LAST_ARG = NULL;
int Exit_status = 0;
int L = strlen(installer_root);
int n;
for (n = 0; n < entry->log_count; n++) {
/* Log copy loop adds new entries to array
so we can't just increment ptr
*/
ptr = & entry->log[n];
if (! filter_record(ptr,module,1)) {
LAST_ARG = NULL;
continue;
}
switch (ptr->command_letter) {
case '\0': /* ENTRY DELETED */
break;
case '{':
if (!LAST_ARG) {
LAST_ARG = ptr;
}
break;
case 'F':
case 'd':
case 'C':
case 'M':
case 'R':
LAST_ARG = NULL;
break;
case 'L': /* link */
{
int Exit_it = 0;
char * file1 = make_absolute(ptr,ptr->arg_ptrs[0]);
char * file2 = make_absolute(ptr,ptr->arg_ptrs[1]);
char * tempname = gen_tempname(file2);
if (0 == unlink(tempname)) {
fprintf(stderr,"%s: %s unlinked\n",program_name,tempname);
}
if (-1 == link(file1,tempname)) {
fprintf(stderr,
"%s: Failed to link %s to %s\n",
program_name,file1,tempname);
Exit_it = 1;
goto fail3;
}
if (-1 == rename(tempname,file2)) {
fprintf(stderr,
"%s: Failed to replace %s\n",
program_name,file2);
Exit_it = 1;
goto fail3;
}
fprintf(stdout,"%s: Link %s == %s installed\n",program_name,file2,file1);
fail3:
free(tempname);
free(file1);
free(file2);
if (Exit_it)
return Exit_it; /* FAILURE */
if (target != source)
move_record(target,last,ptr);
LAST_ARG = NULL;
}
break;
case 's':
/* NOT BREAK LAST_ARG -- is content of directory specified as arg */
break;
case 'E': /* EXECUTE ... */
{
char * translated [MAX_ARGS+1];
int i,j;
int pid,pipefd;
FILE *fd;
int w;
S__ status;
for (i = 0; ptr->arg_ptrs[i] && i < MAX_ARGS; i++) {
int z;
if ('{' == ptr->arg_ptrs[i][0] &&
( z = strlen(ptr->arg_ptrs[i])) &&
'}' == ptr->arg_ptrs[i][z-1]) {
struct log_record *k;
if (!LAST_ARG) {
fprintf(stderr,
"%s: [replay_list] No arguments stored... %s\n",
program_name,ptr->arg_ptrs[i]);
return 1; /* FAILURE */
}
for (k = LAST_ARG; k < ptr; k++) {
if ('{' == k->command_letter &&
k->command_ptr &&
0 == strcmp(ptr->arg_ptrs[i],
k->command_ptr))
break;
}
if (k == ptr) {
fprintf(stderr,
"%s: [replay_list] Argument %s not found\n",
program_name,ptr->arg_ptrs[i]);
return 1; /* FAILURE */
}
if (source != target) {
/* NEED COPY */
char * src = NULL;
char * trg;
uid_t id_user = (uid_t)-1;
gid_t id_group = (gid_t)-1;
int mode;
int is_dir;
pick_one(k,&src,L,&id_user,&id_group,&mode,&is_dir);
trg = src + L;
if (is_dir < 0) {
/* Assumed to be target file */
} else if (is_dir) {
copy_dir(src,trg,k->arg_ptrs[0],target,last,
k->module_ptr);
} else {
if (0 != install_file(src,trg,id_user,id_group,mode)) {
fprintf(stderr,
"%s: [replay_list] '%c' Failed to install %s : %s -> %s\n",
program_name,k->command_letter,
k->arg_ptrs[0],src,trg);
return 1; /* FAILURE */
}
}
move_record(target,last,k);
translated[i] = strdup(trg);
if (!translated[i]) {
fprintf(stderr,
"%s: [replay_list] strdup failed: %s \n",
program_name,trg);
Exit_status = 1; /* FAILURE */
goto fail;
}
free(src);
} else {
/* Just translate reference ... */
int l = strlen(k->arg_ptrs[0]) + 2;
translated[i] = malloc(l);
if (!translated[i]) {
fprintf(stderr,
"%s: [replay_list] malloc %d bytes failed\n",
program_name,l);
Exit_status = 1; /* FAILURE */
goto fail;
}
strcpy(translated[i],"/");
strcat(translated[i],k->arg_ptrs[0]);
}
} else {
translated[i] = strdup(ptr->arg_ptrs[i]);
if (!translated[i]) {
fprintf(stderr,
"%s: [replay_list] strdup failed: %s \n",
program_name,ptr->arg_ptrs[i]);
Exit_status = 1;
goto fail;
}
}
}
translated[i] = NULL;
fprintf(stdout,
"%s: Executing",program_name);
for (j = 0; j < i; j++)
fprintf(stdout," %s",
ptr->arg_ptrs[j]);
fprintf(stdout,
"\n%s: As",program_name);
for (j = 0; j < i; j++)
fprintf(stdout," %s",
translated[j]);
fprintf(stdout,"\n");
fflush(stdout);
pipefd = create_pipe(i,translated,0,&pid,"/",
ptr->module_ptr);
fd = fdopen(pipefd,"r");
if (!fd) {
fprintf(stderr,"%s: fdopen() failed\n",program_name);
close(pipefd);
Exit_status = 1; /* FAILURE */
goto fail;
}
log_copy_loop(fd,target,last);
fclose(fd);
while ((w =
#ifdef HASWAITPID
waitpid(pid,&status,0)
#else
wait(status)
#endif
) != pid)
if (w == -1 && errno != EINTR)
break;
if (w != pid || status != 0) {
fprintf(stderr,
"%s: Failed to run %s\n",
program_name,translated[0]);
Exit_status = 1; /* FAILURE */
}
fail:
for (; i >= 0; i--) {
if (translated[i]) {
free(translated[i]);
translated[i] = NULL;
}
}
if (Exit_status)
return Exit_status;
}
LAST_ARG = NULL;
break;
default:
fprintf(stderr,
"%s: [replay_list] Bad command letter: %c \n",
program_name,ptr->command_letter);
return 1;
}
}
/* Fixing permissions */
for (ptr = entry->log;
ptr < entry->log + entry->log_count;
ptr++) {
if (! filter_record(ptr,module,1))
continue;
switch (ptr->command_letter) {
char *X;
struct passwd * p;
struct group * g;
struct stat X1;
int mode;
uid_t user;
gid_t group;
case 'M':
case 'F':
case 'd':
case 'C':
p = NULL;
g = NULL;
mode = -1;
user = (uid_t)-1;
group = (gid_t)-1;
if (!ptr->arg_ptrs || !ptr->arg_ptrs[0]) {
fprintf(stderr,
"%s: [replay_list] '%c' no arg 0 \n",
program_name,ptr->command_letter);
exit(1); /* FAILURE */
}
X = make_rooted(ptr,ptr->arg_ptrs[0],"/");
if (ptr->user_ptr && 0 != strcmp(ptr->user_ptr,"-")) {
p = getpwnam(ptr->user_ptr);
if (!p)
fprintf(stderr,
"%s: [replay_list] '%c' User %s not found\n",
program_name,ptr->command_letter,
ptr->user_ptr);
else {
user = p->pw_uid;
group = p->pw_gid;
}
}
if (ptr->group_ptr && 0 != strcmp(ptr->group_ptr,"-")) {
g = getgrnam(ptr->group_ptr);
if (!g)
fprintf(stderr,
"%s: [replay_list] '%c' Group %s not found\n",
program_name,ptr->command_letter,
ptr->group_ptr);
else
group = g->gr_gid;
}
if (ptr->mode_ptr && 0 != strcmp(ptr->mode_ptr,"-") &&
0 != strcmp(ptr->mode_ptr,"0")) {
char * x;
mode = strtol(ptr->mode_ptr,&x,8);
if (*x || 0 == mode)
mode = -1;
}
if (stat(X,&X1) < 0) {
fprintf(stderr,
"%s: (note) %s : %s not accessible\n",
program_name,
ptr->arg_ptrs[0],X);
Exit_status = 1; /* FAILURE */
goto failure1;
}
if (
#ifdef S_ISDIR
S_ISDIR(X1.st_mode)
#else
S_IFDIR == (X1.st_mode & S_IFMT)
#endif
) {
if (ptr->command_letter != 'M') {
fprintf(stderr,
"%s: (note) %s : %s is directory when should not\n",
program_name,
ptr->arg_ptrs[0],X);
Exit_status = 1; /* FAILURE */
goto failure1;
}
} else {
if (ptr->command_letter == 'M') {
fprintf(stderr,
"%s: (note) %s : %s is not a directory\n",
program_name,
ptr->arg_ptrs[0],X);
Exit_status = 1; /* FAILURE */
goto failure1;
}
}
if (user != (uid_t)-1 || group != (gid_t)-1) {
if (X1.st_uid != user || X1.st_gid != group) {
if (-1 == chown(X,user,group)) {
fprintf(stderr,"%s: Failed to set owner/group of %s\n",
program_name,X);
Exit_status = 1; /* FAILURE */
goto failure1;
}
} else {
fprintf(stdout,"%s: Fixed owner/group of %s\n",
program_name,X);
}
/* Recheck mode */
if (stat(X,&X1) < 0) {
fprintf(stderr,
"%s: (note) %s : %s not accessible\n",
program_name,
ptr->arg_ptrs[0],X);
Exit_status = 1; /* FAILURE */
goto failure1;
}
}
if (mode > 0) {
if ((X1.st_mode & 0777) != mode) {
if (-1 == chmod(X,mode)) {
fprintf(stderr,"%s: Failed to set mode of %s\n",
program_name,X);
Exit_status = 1; /* FAILURE */
} else {
fprintf(stdout,"%s: Mode of %s fixed\n",
program_name,X);
}
}
}
failure1:
free(X); X = 0;
break;
default:
break;
}
}
return Exit_status;
}
static int replay P_((int argc, char *argv[], int x));
static int replay(argc, argv, x)
int argc;
char *argv[];
int x;
{
struct stat X;
struct log_instance * target = NULL;
int i;
int r = 0;
struct log_instance LI_source;
struct log_instance LI_target;
struct log_entries * last = NULL;
char **module_filter = NULL;
int module_count = 0;
int remove_count;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
clear_log_instance(&LI_source);
clear_log_instance(&LI_target);
installer_root = "/";
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-R", argv[x])) {
installer_root = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
module_filter = realloc(module_filter,
(module_count+2) *
sizeof (module_filter[0]));
if (! module_filter) {
fprintf(stderr,
"%s: Failed to realloc -M option\n",
program_name);
exit(1);
}
module_filter[module_count++] = argv[x+1];
module_filter[module_count] = NULL;
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if (stat(installer_root,&X) < 0) {
fprintf(stderr,"%s: -R %s invalid\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
! S_ISDIR(X.st_mode)
#else
S_IFDIR != (buf.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,"%s: -R %s invalid (not a directory)\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (x < argc) {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
LI_source.filename = filelist;
if (0 != strcmp(installer_root,"/")) {
int l = strlen(filelist) + strlen(installer_root) +2;
LI_source.filename = malloc(l);
if (!LI_source.filename) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
return 1; /* FAILURE */
}
sprintf(LI_source.filename,"%s%s",installer_root,filelist);
}
LI_source.file = fopen(LI_source.filename,"r+");
if (!LI_source.file) {
fprintf(stderr,
"%s: Failed to open file %s on %s: %s\n",
program_name,filelist,installer_root,LI_source.filename);
return 1; /* FAILURE */
}
add_entries(&LI_source);
if (LI_source.entries_count < 1 ||
0 != strcmp(LI_source.entries[LI_source.entries_count-1].version,
my_version)) {
fprintf(stderr,
"%s: Last version on file %s on %s (file %s) is not %s\n",
program_name,filelist,installer_root,
LI_source.filename,
my_version);
fclose(LI_source.file);
return 1; /* FAILURE */
}
if (0 != strcmp(installer_root,"/")) {
int i;
int t;
fprintf (stdout,
"%s: Copying ELM files from %s to / \n",
program_name,installer_root);
LI_target.filename = filelist;
if (0 == mkdir(ETCHOME,0755)) {
fprintf(stdout,
"%s: Directory %s created\n",
program_name,ETCHOME);
} else if (errno != EEXIST) {
fprintf(stderr,
"%s: Failed to create %s directory\n",
program_name,ETCHOME);
return 1; /* FAILURE */
}
t = open(LI_target.filename,O_RDWR|O_CREAT,0644);
if (t < 0) {
fprintf(stderr,
"%s: Failed to open file %s on target (/): %s\n",
program_name,filelist,LI_target.filename);
fclose(LI_source.file);
return 1; /* FAILURE */
}
LI_target.file = fdopen(t,"r+");
if (!LI_target.file) {
fprintf(stderr,
"%s: Failed to fdopen file %s on target (/): %s\n",
program_name,filelist,LI_target.filename);
fclose(LI_source.file);
close(t);
return 1; /* FAILURE */
}
add_entries(&LI_target);
target = &LI_target;
last = add_last(target);
/* Copy files marked for current version ...
* replay_list() will copy '{' files
*/
for (i = 0; i < LI_source.entries_count; i++) {
if (0 == strcmp(LI_source.entries[i].version, my_version)) {
r = copy_list(& LI_source.entries[i], &LI_source, &LI_target,
last, module_filter);
if (0 != r)
goto fail;
} else {
fprintf(stderr,
"%s: On source area (%s) have files for version %s -- NOT COPIED\n",
program_name,installer_root,
LI_source.entries[i].version);
}
}
if (0 != fflush(LI_target.file)) {
fprintf(stderr,
"%s: Failed to write file %s on target (/): %s\n",
program_name,filelist,LI_target.filename);
fclose(LI_source.file);
return 1; /* FAILURE */
}
} else {
target = & LI_source;
last = & LI_source.entries[LI_source.entries_count-1];
}
/* EXECUTE commands and fix permissions */
r = replay_list(&LI_source.entries[LI_source.entries_count-1],
&LI_source,target,last,
module_filter);
/* Trim files marked for other versions ...
LAST entry is current so not need handle it ...
*/
for (i = 0; i < target->entries_count-1; i++) {
if (0 != strcmp(target->entries[i].version, my_version)) {
trim_list(& target->entries[i], target, module_filter);
}
}
remove_unlinked(target,"/",&remove_count);
rewrite_list(target);
if (EOF == fclose(target->file)) {
fprintf(stderr,
"%s: Write(?) failed on closing of file: %s\n",
program_name,target->filename);
return 1; /* FAILURE */
}
fail:
return r;
}
static int uninstall P_((int argc, char *argv[], int x));
static int uninstall(argc, argv, x)
int argc;
char *argv[];
int x;
{
int r = 0;
struct log_instance LI;
int remove_count;
int i;
char **module_filter = NULL;
int module_count = 0;
struct stat X;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
clear_log_instance(&LI);
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
module_filter = realloc(module_filter,
(module_count+2) *
sizeof (module_filter[0]));
if (! module_filter) {
fprintf(stderr,
"%s: Failed to realloc -M option\n",
program_name);
exit(1);
}
module_filter[module_count++] = argv[x+1];
module_filter[module_count] = NULL;
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if (x < argc) {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
if (module_count != 1 ||
0 != strcmp(module_filter[0],"all")) {
if (stat(program_name,&X) < 0) {
fprintf(stderr,
"%s: Failed to stat this program name -- needed to avoid unistalling this program\n",
program_name);
r = 1;
} else {
this_program_dev = X.st_dev;
this_program_ino = X.st_ino;
}
}
LI.filename = filelist;
LI.file = fopen(LI.filename,"r+");
if (!LI.file) {
fprintf(stderr,
"%s: Failed to open file %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
add_entries(&LI);
if (LI.entries_count < 1 ||
0 != strcmp(LI.entries[LI.entries_count-1].version,
my_version)) {
fprintf(stderr,
"%s: Last version on file %s is not %s\n",
program_name,
LI.filename,
my_version);
r = 1;
}
remove_unlinked(&LI,"/",&remove_count);
for (i = 0; i < LI.entries_count; i++) {
if (0 != unstage_list(& LI.entries[i], &LI,module_filter))
r = 1;
if (0 != uninstall_list(& LI.entries[i], &LI,module_filter))
r = 1;
}
rewrite_list(&LI);
if (EOF == fclose(LI.file)) {
fprintf(stderr,
"%s: Write(?) failed on closing of file: %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
if (this_program) {
fprintf(stdout,
"%s: To unistall this program use %s -M all\n",
program_name,program_name);
}
return r;
}
static int unstage P_((int argc, char *argv[], int x));
static int unstage(argc, argv, x)
int argc;
char *argv[];
int x;
{
int r = 0;
struct log_instance LI;
int remove_count;
int i;
char **module_filter = NULL;
int module_count = 0;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
clear_log_instance(&LI);
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
module_filter = realloc(module_filter,
(module_count+2) *
sizeof (module_filter[0]));
if (! module_filter) {
fprintf(stderr,
"%s: Failed to realloc -M option\n",
program_name);
exit(1);
}
module_filter[module_count++] = argv[x+1];
module_filter[module_count] = NULL;
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if (x < argc) {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
LI.filename = filelist;
LI.file = fopen(LI.filename,"r+");
if (!LI.file) {
fprintf(stderr,
"%s: Failed to open file %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
add_entries(&LI);
if (LI.entries_count < 1 ||
0 != strcmp(LI.entries[LI.entries_count-1].version,
my_version)) {
fprintf(stderr,
"%s: Last version on file %s is not %s\n",
program_name,
LI.filename,
my_version);
r = 1;
}
remove_unlinked(&LI,"/",&remove_count);
for (i = 0; i < LI.entries_count; i++) {
if (0 != unstage_list(& LI.entries[i], &LI, module_filter))
r = 1;
}
rewrite_list(&LI);
if (EOF == fclose(LI.file)) {
fprintf(stderr,
"%s: Write(?) failed on closing of file: %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
return r;
}
static int dir_list P_((int argc, char *argv[], int x));
static int dir_list(argc, argv, x)
int argc;
char *argv[];
int x;
{
int r = 0;
struct stat X;
struct log_instance LI;
int i;
char **module_filter = NULL;
int module_count = 0;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
clear_log_instance(&LI);
installer_root = "/";
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-R", argv[x])) {
installer_root = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
module_filter = realloc(module_filter,
(module_count+2) *
sizeof (module_filter[0]));
if (! module_filter) {
fprintf(stderr,
"%s: Failed to realloc -M option\n",
program_name);
exit(1);
}
module_filter[module_count++] = argv[x+1];
module_filter[module_count] = NULL;
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if (x < argc) {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
if (stat(installer_root,&X) < 0) {
fprintf(stderr,"%s: -R %s invalid\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
! S_ISDIR(X.st_mode)
#else
S_IFDIR != (buf.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,"%s: -R %s invalid (not a directory)\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
LI.filename = filelist;
if (0 != strcmp(installer_root,"/")) {
int l = strlen(filelist) + strlen(installer_root) +2;
LI.filename = malloc(l);
if (!LI.filename) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
return 1; /* FAILURE */
}
sprintf(LI.filename,"%s%s",installer_root,filelist);
}
LI.file = fopen(LI.filename,"r");
if (!LI.file) {
fprintf(stderr,
"%s: Failed to open file %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
add_entries(&LI);
if (LI.entries_count < 1 ||
0 != strcmp(LI.entries[LI.entries_count-1].version,
my_version)) {
fprintf(stderr,
"%s: Last version on file %s is not %s\n",
program_name,
LI.filename,
my_version);
r = 1;
}
for (i = 0; i < LI.entries_count; i++) {
struct log_entries *I = &(LI.entries[i]);
int r;
/* Skip error message if list is actually empty */
if (I->log_count < 1)
continue;
if (0 != strcmp(I->version,my_version)) {
fprintf(stderr,
"%s: File %s includes version %s entries (current %s)\n",
program_name,
LI.filename,
I->version,
my_version);
}
for (r = 0; r < I->log_count; r++) {
struct log_record * R = & (I->log[r]);
char * file = NULL;;
if (! filter_record(R,module_filter,1))
continue;
if (R->arg_ptrs && R->arg_ptrs[0])
file = R->arg_ptrs[0];
if (!file)
continue;
if ('/' == file[0])
file++;
switch (R->command_letter) {
case 'M':
fputs(file,stdout);
fputc('\n',stdout);
case 'd': /* doc */
case 'F':
case 's':
case 'C': /* config */
case 'E':
case 'R':
case 'L':
break;
case '{': {
char *F = make_rooted(R,file,installer_root);
struct stat X;
if (stat(F,&X) < 0) {
if (ENOENT != errno)
fprintf(stderr,
"%s: '%c' File %s (%s) not accessible\n",
program_name,R->command_letter,
file,F);
} else if (
#ifdef S_ISDIR
S_ISDIR(X.st_mode)
#else
S_IFDIR == (X.st_mode & S_IFMT)
#endif
) {
fputs(file,stdout);
fputc('/',stdout);
fputc('\n',stdout);
}
free(F);
}
break;
default:
fprintf(stderr,
"%s: '%c' Bad command letter\n",
program_name,R->command_letter);
}
}
}
if (EOF == fclose(LI.file)) {
fprintf(stderr,
"%s: Failed on closing of file: %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
return r;
}
static int tar_list P_((int argc, char *argv[], int x));
static int tar_list(argc, argv, x)
int argc;
char *argv[];
int x;
{
int r = 0;
struct stat X;
struct log_instance LI;
int i;
char **module_filter = NULL;
int module_count = 0;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
clear_log_instance(&LI);
installer_root = "/";
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-R", argv[x])) {
installer_root = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
module_filter = realloc(module_filter,
(module_count+2) *
sizeof (module_filter[0]));
if (! module_filter) {
fprintf(stderr,
"%s: Failed to realloc -M option\n",
program_name);
exit(1);
}
module_filter[module_count++] = argv[x+1];
module_filter[module_count] = NULL;
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if (x < argc) {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
if (stat(installer_root,&X) < 0) {
fprintf(stderr,"%s: -R %s invalid\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
! S_ISDIR(X.st_mode)
#else
S_IFDIR != (buf.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,"%s: -R %s invalid (not a directory)\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
LI.filename = filelist;
if (0 != strcmp(installer_root,"/")) {
int l = strlen(filelist) + strlen(installer_root) +2;
LI.filename = malloc(l);
if (!LI.filename) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
return 1; /* FAILURE */
}
sprintf(LI.filename,"%s%s",installer_root,filelist);
}
LI.file = fopen(LI.filename,"r");
if (!LI.file) {
fprintf(stderr,
"%s: Failed to open file %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
add_entries(&LI);
if (LI.entries_count < 1 ||
0 != strcmp(LI.entries[LI.entries_count-1].version,
my_version)) {
fprintf(stderr,
"%s: Last version on file %s is not %s\n",
program_name,
LI.filename,
my_version);
r = 1;
}
for (i = 0; i < LI.entries_count; i++) {
struct log_entries *I = &(LI.entries[i]);
int r;
/* Skip error message if list is actually empty */
if (I->log_count < 1)
continue;
if (0 != strcmp(I->version,my_version)) {
fprintf(stderr,
"%s: File %s includes version %s entries (current %s)\n",
program_name,
LI.filename,
I->version,
my_version);
}
for (r = 0; r < I->log_count; r++) {
struct log_record * R = & (I->log[r]);
char * file = NULL;;
if (! filter_record(R,module_filter,1))
continue;
if (R->arg_ptrs && R->arg_ptrs[0])
file = R->arg_ptrs[0];
if (!file)
continue;
if ('/' == file[0])
file++;
switch (R->command_letter) {
case 'M': /* Directories not listed */
break;
case 'd': /* doc */
case 'F':
case 's':
case 'C': /* config */
fputs(file,stdout);
fputc('\n',stdout);
break;
case 'E':
break;
case 'R':
break;
case 'L':
/* Hard links not listed (although OK) */
break;
case '{': {
char *F = make_rooted(R,file,installer_root);
struct stat X;
if (stat(F,&X) < 0) {
if (ENOENT != errno)
fprintf(stderr,
"%s: '%c' File %s (%s) not accessible\n",
program_name,R->command_letter,
file,F);
} else if (
#ifdef S_ISDIR
S_ISDIR(X.st_mode)
#else
S_IFDIR == (X.st_mode & S_IFMT)
#endif
) {
#if 0
fprintf(stderr,
"%s: '%c' File %s (%s) is directory\n",
program_name,R->command_letter,
file,F);
#endif
#ifndef DIROPS
if (! R->command_ptr || 0 != strcmp(R->command_ptr,IMPARGDIR)) {
/* If no DIROPS, then files are not listed, so include dir to listing */
fputs(file,stdout);
fputc('/',stdout);
fputc('\n',stdout);
}
#endif
} else {
fputs(file,stdout);
fputc('\n',stdout);
}
free(F);
}
break;
default:
fprintf(stderr,
"%s: '%c' Bad command letter\n",
program_name,R->command_letter);
}
}
}
if (EOF == fclose(LI.file)) {
fprintf(stderr,
"%s: Failed on closing of file: %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
return r;
}
static int rpm_list P_((int argc, char *argv[], int x));
static int rpm_list(argc, argv, x)
int argc;
char *argv[];
int x;
{
int r = 0;
struct stat X;
struct log_instance LI;
int i;
char *user1 = "-";
char *group1 = "-";
char **module_filter = NULL;
int module_count = 0;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
clear_log_instance(&LI);
installer_root = "/";
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-u", argv[x])) {
user1 = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-g", argv[x])) {
group1 = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-R", argv[x])) {
installer_root = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
module_filter = realloc(module_filter,
(module_count+2) *
sizeof (module_filter[0]));
if (! module_filter) {
fprintf(stderr,
"%s: Failed to realloc -M option\n",
program_name);
exit(1);
}
module_filter[module_count++] = argv[x+1];
module_filter[module_count] = NULL;
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if (x < argc) {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
if (stat(installer_root,&X) < 0) {
fprintf(stderr,"%s: -R %s invalid\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
! S_ISDIR(X.st_mode)
#else
S_IFDIR != (buf.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,"%s: -R %s invalid (not a directory)\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
LI.filename = filelist;
if (0 != strcmp(installer_root,"/")) {
int l = strlen(filelist) + strlen(installer_root) +2;
LI.filename = malloc(l);
if (!LI.filename) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
return 1; /* FAILURE */
}
sprintf(LI.filename,"%s%s",installer_root,filelist);
}
LI.file = fopen(LI.filename,"r");
if (!LI.file) {
fprintf(stderr,
"%s: Failed to open file %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
add_entries(&LI);
if (LI.entries_count < 1 ||
0 != strcmp(LI.entries[LI.entries_count-1].version,
my_version)) {
fprintf(stderr,
"%s: Last version on file %s is not %s\n",
program_name,
LI.filename,
my_version);
r = 1;
}
for (i = 0; i < LI.entries_count; i++) {
struct log_entries *I = &(LI.entries[i]);
int r;
/* Skip error message if list is actually empty */
if (I->log_count < 1)
continue;
if (0 != strcmp(I->version,my_version)) {
fprintf(stderr,
"%s: File %s includes version %s entries (current %s)\n",
program_name,
LI.filename,
I->version,
my_version);
}
for (r = 0; r < I->log_count; r++) {
struct log_record * R = & (I->log[r]);
char * user = R->user_ptr;
char * group = R->group_ptr;
char * mode = R->mode_ptr;
char * file = NULL;;
if (! filter_record(R,module_filter,1))
continue;
if (R->arg_ptrs && R->arg_ptrs[0])
file = R->arg_ptrs[0];
if (!user || 0 == strcmp(user,"-"))
user = user1;
if (!group || 0 == strcmp(group,"-"))
group = group1;
if (!mode || 0 == atoi(mode))
mode = "-";
if (!file)
continue;
switch (R->command_letter) {
case 'M':
fputs("%dir ",stdout);
if (0 != strcmp(user,"-") ||
0 != strcmp(group,"-") ||
0 != strcmp(mode,"-"))
printf("%%attr(%s,%s,%s) ",mode,user,group);
printf("%s%s\n",
file[0] != '/' ? "/" : "",
file);
break;
case 'd':
fputs("%doc ",stdout);
if (0 != strcmp(user,"-") ||
0 != strcmp(group,"-") ||
0 != strcmp(mode,"-"))
printf("%%attr(%s,%s,%s) ",mode,user,group);
printf("%s%s\n",
file[0] != '/' ? "/" : "",
file);
break;
case 'F':
case 's':
if (0 != strcmp(user,"-") ||
0 != strcmp(group,"-") ||
0 != strcmp(mode,"-"))
printf("%%attr(%s,%s,%s) ",mode,user,group);
printf("%s%s\n",
file[0] != '/' ? "/" : "",
file);
break;
case 'C':
fputs("%config ",stdout);
if (0 != strcmp(user,"-") ||
0 != strcmp(group,"-") ||
0 != strcmp(mode,"-"))
printf("%%attr(%s,%s,%s) ",mode,user,group);
printf("%s%s\n",
file[0] != '/' ? "/" : "",
file);
break;
case 'E':
break;
case 'R':
break;
case 'L': /* SECOND ARGUMENT IS NEW NAME
hard links need not to put archive -- they are created on
elmregister replay
*/
if (R->arg_ptrs && R->arg_ptrs[1]) {
char *new_file = R->arg_ptrs[1];
printf("%%ghost %s%s\n",
new_file[0] != '/' ? "/" : "",
new_file);
}
break;
case '{': {
char *F = make_rooted(R,file,installer_root);
struct stat X;
if (stat(F,&X) < 0) {
if (ENOENT != errno)
fprintf(stderr,
"%s: '%c' File %s (%s) not accessible\n",
program_name,R->command_letter,
file,F);
} else if (
#ifdef S_ISDIR
S_ISDIR(X.st_mode)
#else
S_IFDIR == (X.st_mode & S_IFMT)
#endif
) {
#if 0
fprintf(stderr,
"%s: '%c' File %s (%s) is directory\n",
program_name,R->command_letter,
file,F);
#endif
if (R->command_ptr && 0 == strcmp(R->command_ptr,IMPARGDIR))
fputs("%dir ",stdout);
#ifdef DIROPS
else
/* Files are already logged ... */
fputs("%dir ",stdout);
#endif
if (0 != strcmp(user,"-") ||
0 != strcmp(group,"-") ||
0 != strcmp(mode,"-"))
printf("%%attr(%s,%s,%s) ",mode,user,group);
printf("%s%s\n",
file[0] != '/' ? "/" : "",
file);
} else {
if (0 != strcmp(user,"-") ||
0 != strcmp(group,"-") ||
0 != strcmp(mode,"-"))
printf("%%attr(%s,%s,%s) ",mode,user,group);
printf("%s%s\n",
file[0] != '/' ? "/" : "",
file);
}
free(F);
}
break;
default:
fprintf(stderr,
"%s: '%c' Bad command letter\n",
program_name,R->command_letter);
}
}
}
if (EOF == fclose(LI.file)) {
fprintf(stderr,
"%s: Failed on closing of file: %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
return r;
}
static int filter P_((int argc, char *argv[], int x));
static int filter(argc, argv, x)
int argc;
char *argv[];
int x;
{
int r = 0;
struct stat X;
struct log_instance * target = NULL;
struct log_entries * last = NULL;
struct log_instance LI;
struct log_instance LI_target;
int i;
char **module_filter = NULL;
int module_count = 0;
#if ANSI_C
char my_version[] = "[ELM" VERSION " " PATCHLEVEL "]";
#else
char my_version[40];
sprintf(my_version,"[ELM %s %s]",VERSION,PATCHLEVEL);
#endif
clear_log_instance(&LI);
clear_log_instance(&LI_target);
installer_root = "/";
while (x < argc && '-' == argv[x][0]) {
if (x < argc -1 && 0 == strcmp("-F", argv[x])) {
filelist = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-w", argv[x])) {
char * file = argv[x+1];
int t;
x += 2;
if (LI_target.filename) {
fprintf(stderr,
"%s: Duplicate -w option\n",
program_name);
exit(1);
}
LI_target.filename = file;
t = open(LI_target.filename,O_RDWR|O_CREAT,0644);
if (t < 0) {
fprintf(stderr,
"%s: Failed to open file %s on targe: %s\n",
program_name,filelist,LI_target.filename);
fclose(LI.file);
return 1; /* FAILURE */
}
LI_target.file = fdopen(t,"r+");
if (!LI_target.file) {
fprintf(stderr,
"%s: Failed to fdopen file %s on target (/): %s\n",
program_name,filelist,LI_target.filename);
fclose(LI.file);
close(t);
return 1; /* FAILURE */
}
add_entries(&LI_target);
target = &LI_target;
last = add_last(target);
} else if (x < argc -1 && 0 == strcmp("-R", argv[x])) {
installer_root = argv[x+1];
x += 2;
} else if (x < argc -1 && 0 == strcmp("-M", argv[x])) {
module_filter = realloc(module_filter,
(module_count+2) *
sizeof (module_filter[0]));
if (! module_filter) {
fprintf(stderr,
"%s: Failed to realloc -M option\n",
program_name);
exit(1);
}
module_filter[module_count++] = argv[x+1];
module_filter[module_count] = NULL;
x += 2;
} else {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
}
if (x < argc) {
fprintf(stderr,
"%s: Bad option %s\n",
program_name,argv[x]);
exit(1);
}
if (stat(installer_root,&X) < 0) {
fprintf(stderr,"%s: -R %s invalid\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (
#ifdef S_ISDIR
! S_ISDIR(X.st_mode)
#else
S_IFDIR != (buf.st_mode & S_IFMT)
#endif
) {
fprintf(stderr,"%s: -R %s invalid (not a directory)\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
LI.filename = filelist;
if (0 != strcmp(installer_root,"/")) {
int l = strlen(filelist) + strlen(installer_root) +2;
LI.filename = malloc(l);
if (!LI.filename) {
fprintf(stderr,"%s: malloc %d bytes failed\n",
program_name,l);
return 1; /* FAILURE */
}
sprintf(LI.filename,"%s%s",installer_root,filelist);
}
LI.file = fopen(LI.filename,"r");
if (!LI.file) {
fprintf(stderr,
"%s: Failed to open file %s\n",
program_name,LI.filename);
return 1; /* FAILURE */
}
add_entries(&LI);
if (LI.entries_count < 1 ||
0 != strcmp(LI.entries[LI.entries_count-1].version,
my_version)) {
fprintf(stderr,
"%s: Last version on file %s is not %s\n",
program_name,
LI.filename,
my_version);
r = 1;
}
if (target) {
for (i = 0; i < LI.entries_count; i++) {
struct log_entries *I = &(LI.entries[i]);
int r;
/* Skip error message if list is actually empty */
if (I->log_count < 1)
continue;
if (0 != strcmp(I->version,my_version)) {
fprintf(stderr,
"%s: File %s includes version %s entries (current %s)\n",
program_name,
LI.filename,
I->version,
my_version);
}
for (r = 0; r < I->log_count; r++) {
struct log_record * R = & (I->log[r]);
if (! filter_record(R,module_filter,1))
continue;
move_record(target,last,R);
}
}
if (EOF == fclose(target->file)) {
fprintf(stderr,
"%s: Write(?) failed on closing of file: %s\n",
program_name,target->filename);
return 1; /* FAILURE */
}
}
return r;
}
int main P_((int argc, char *argv[]));
int main(argc, argv)
int argc;
char *argv[];
{
int x = 1;
int r = 1;
char *y;
enum register_mode {
register_master,
register_command,
register_replay,
register_uninstall,
register_unstage,
register_dir_list,
register_tar_list,
register_rpm_list,
register_filter
} mode = register_command;
register_pipe = getenv("ELM_INSTALLER");
installer_root = getenv("ELM_ROOT");
register_module = getenv("ELM_MODULE");
program_name = argv[0];
#if defined(ANSI_C) || defined(SETLINEBUF)
setlinebuf(stdout);
#endif
#if 0
if (register_pipe)
fprintf(stderr,"%s: $ELM_INSTALLER=%s\n",program_name,register_pipe);
if (installer_root)
fprintf(stderr,"%s: $ELM_ROOT=%s\n",program_name,installer_root);
#endif
if (x < argc -1 && 0 == strcmp("-S", argv[x])) {
stage_dir = argv[x+1];
x += 2;
}
#if 0
if (stage_dir)
fprintf(stderr,"%s: STAGE_DIR=%s\n",program_name,stage_dir);
#endif
if ((y = strrchr(program_name,'/')) &&
0 == strcmp("/elmuninstall",y)) {
mode = register_uninstall;
} else if (x < argc && 0 == strcmp("uninstall", argv[x])) {
x += 1;
mode = register_uninstall;
} if (x < argc && 0 == strcmp("master", argv[x])) {
x += 1;
mode = register_master;
} else if (x < argc && 0 == strcmp("replay", argv[x])) {
x += 1;
mode = register_replay;
} else if (x < argc && 0 == strcmp("unstage", argv[x])) {
x += 1;
mode = register_unstage;
} else if (x < argc && 0 == strcmp("list", argv[x])) {
x += 1;
mode = register_tar_list;
} else if (x < argc && 0 == strcmp("list-directories", argv[x])) {
x += 1;
mode = register_dir_list;
} else if (x < argc && 0 == strcmp("rpm-list", argv[x])) {
x += 1;
mode = register_rpm_list;
} else if (x < argc && 0 == strcmp("filter", argv[x])) {
x += 1;
mode = register_filter;
}
if (mode != register_command) {
if (register_pipe) {
fprintf(stderr,
"%s: $ELM_INSTALLER=%s incompatible with arguments 'master' and 'replay', 'unstage'\n",
argv[0],register_pipe);
return 1; /* FAILURE */
}
if (installer_root) {
fprintf(stderr,"%s: $ELM_ROOT=%s incompatible with arguments 'master' and 'replay, 'unstage'\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
if (installer_root) {
fprintf(stderr,"%s: $ELM_MODULE=%s incompatible with arguments 'master' and 'replay, 'unstage'\n",
argv[0],installer_root);
return 1; /* FAILURE */
}
}
switch(mode) {
case register_master: r = master(argc,argv,x); break;
case register_command: r = command(argc,argv,x); break;
case register_replay: r = replay(argc,argv,x); break;
case register_uninstall: r = uninstall(argc,argv,x); break;
case register_unstage: r = unstage(argc,argv,x); break;
case register_tar_list: r = tar_list(argc,argv,x); break;
case register_dir_list: r = dir_list(argc,argv,x); break;
case register_rpm_list: r = rpm_list(argc,argv,x); break;
case register_filter: r = filter(argc,argv,x); break;
}
return r;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1