v13i065: Tools to help automate backups
Rich Salz
rsalz at bbn.com
Wed Feb 24 21:00:18 AEST 1988
Submitted-by: Scooter Morris <scooter at genie.gene.com>
Posting-number: Volume 13, Issue 65
Archive-name: backups
This is a little backup utility that to somewhat automate a backup
schedule. The main advantage that it has is that it will "quietize" the
system before performing the dumps.
The program reads a control file, and determines which filesystems to dump
at which level, and when. It is designed to work with the UCB "dump(8)"
program.
/r$
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# README Makefile backup.8 backup.c backup.h convdate.c parser.y
# proclist.c quietize.c restart.c scanner.l shutdown.c ulist.h
# genie_dates backup_dates
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
backup
This program should be run set-uid root. At genentech, we set the
permissions to 4550 with group operator. Backup was originally a
simple experiment to play around with yacc, it has proven to be
a very useful tool. Daily backups are normally performed using
the "-m" option, which allows the system to continue running. Without
this option, all running processes are sent "SIGHUP", any processes
remaining after the SIGHUP are SIGSTOPped for the duration of the
backup. After backup is complete, a SIGCONT is sent to all of the
stopped processes.
Some notes about exclusions and special cases:
There is a list of processes to be excluded from either HUP or
STOP in proclist.c. In addition, some programs such as daemons,
etc. require special restarting. The table for this is in
proclist.c also.
10/2/87
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# $Header: Makefile,v 1.3 85/04/05 17:16:57 scooter Exp $
VPATH = .:./RCS
SOURCES = backup.c quietize.c shutdown.c proclist.c restart.c convdate.c \
parser.y scanner.l
OBJECTS = backup.o quietize.o shutdown.o proclist.o restart.o convdate.o \
y.tab.o
INCLUDES = backup.h ulist.h
CFLAGS = -O -DDEBUG
YFLAGS = -d
.SUFFIXES: .c,v .l,v .y,v
backup: $(OBJECTS)
cc $(CFLAGS) -o backup $(OBJECTS)
y.tab.o: y.tab.c lex.yy.c y.tab.h
cc $(CFLAGS) -c y.tab.c
lex.yy.c:scanner.l
lex scanner.l
y.tab.c: parser.y
yacc $(YFLAGS) parser.y
.y,v.y:
co $<
.l,v.l:
co $<
.c,v.o:
co $<
cc $(CFLAGS) -c $<
SHAR_EOF
fi # end of overwriting check
if test -f 'backup.8'
then
echo shar: will not over-write existing file "'backup.8'"
else
cat << \SHAR_EOF > 'backup.8'
.TH BACKUP 8
.SH NAME
backup \- perform tape backups
.SH SYNOPSIS
.B backup
[ options ] [ date ]
.SH DESCRIPTION
.vs -1p
.I backup
reads the file
.B /etc/backup_dates
and runs
.B dump(8)
to backup the specified filesystems. If no
.I date
is given, the current date is used.
The
.I backup_dates
file consists of lines of 6 fields each. The fields are separated by spaces
of tabs. The fields specify the day of the week (Sun-Sat), the week of the
month (1-5), the month (Jan-Dec), the dump level to perform (0-9), the
filesystem, and an arbitrary message to be delivered to the operator upon
completion of the dump. Each of these fields may contain a range or
a comma-separated list, or an asterisk meaning all legal values.
.PP
Options for
.I backup
are:
.TP
.B \-m
Run
.I backup
in multiuser mode. Usually backup will kill any forground processes
and suspend any background processes so that the filesystems will be
guaranteed to be quiescent. When run in multiuser mode, no action
is taken to insure that there is no filesystem activity.
.TP
.BI \-b blocksize
Sets the tape blocking factor to
.I blocksize.
The default is 32.
.TP
.BI \-s tapelength
Sets the assumed length of the tape to
.I tapelength.
This defines how many blocks are written to each tape. The default is
2300 feet.
.TP
.BI \-d density
Sets the tape density to
.I density.
This is normally 6250 BPI.
.TP
.BI \-t device
Sets the device to use to
.I device.
This is /dev/rmt9 on our systems which corresponds to the TU78 tape drives
at 6250 BPI.
.TP
.BI \-f file
Causes backup to read the filesystem dump schedule from the file
.I file
instead of from /etc/backup_dates.
.TP
.BI \-w minutes
Sets the warning time to give users when running in single-user mode.
.SH BACKUP_DATES Example
.nf
# Backup schedule for Genie - Genentech, Inc.
# Daily level 9's
Tue-Fri * * 9 /va "/va dump complete"
# Monday dumps - level 1's
Mon 2-5 * 1 / "root dump complete"
Mon 2,3,4,5 * 1 /va "/va dump complete"
# Monthly level 0's
Mon 1 * 0 / "root dump complete"
Mon 1 * 0 /va "/va dump complete"
.fi
.SH AUTHOR
Scooter Morris - Genentech, Inc.
.SH SEE ALSO
dump(8), shutdown(8), backup_dates(5)
.SH BUGS
SHAR_EOF
fi # end of overwriting check
if test -f 'backup.c'
then
echo shar: will not over-write existing file "'backup.c'"
else
cat << \SHAR_EOF > 'backup.c'
#ifdef lint
static char rcsid[] = "$Header: backup.c,v 1.9 86/10/20 18:37:34 scooter Exp $";
#endif lint
/*
* backup - a program to control daily dumps
*
* This program has been written to control the daily dumping
* of all of the system's files. Backup reads from the file
* /etc/backup_dates to get the days and times that a filesystem
* should be backed up. The format of backup_dates is:
*
* Day_of_week Week_of_month Month Level Filesystem Message
*
* where:
* Day_of_week is one of {Mon,Tue,Wed,Thu,Fri,Sat,Sun}
* Week_of_month is 1-5
* Month is one of {Jan,Feb,...,Dec}
* Level is 0-9
* Filesystem is the NAME of the filesystem
* Message is a message to be printed to the operator upon
* completion of the dump
*
* For example, backup_dates might look like:
*
* # Backup schedule for Genie - Genentech, Inc.
* # Daily level 9's
* Tue-Fri * * 9 /va "/va dump complete"
* # Monday dumps - level 1's
* Mon 2-5 * 1 / "root dump complete"
* Mon 2,3,4,5 * 1 /va "/va dump complete"
* # Monthly level 0's
* Mon 1 * 0 / "root dump complete"
* Mon 1 * 0 /va "/va dump complete"
*
* Note that the "#" character is used as a comment, and that ranges
* as well as the "*" may be used. Obviously ranges and wildcards are
* only allowed in the Day_of_week and Week_of_month fields.
*
* Usage:
* backup [-b blocksize] [-s tapelength] [-t device] [-f file ] [-m] [-w n]
* [-d density] [date]
*
* Diagnostics:
* Backup will complain if the input file is garbaged or if the
* filesystem is mounted. The return status from dump is monitored
* to track the progress of the dump and to determine if dump
* fails. If it fails, the operator will be prompted to determine
* if they want to retry this filesystem.
*
* Author: Scooter Morris, Genentech
* Date: March, 1985
*
*/
#include <stdio.h>
#include <sys/time.h>
#include <fstab.h>
#include <signal.h>
#include <errno.h>
#include <sys/reboot.h>
#include "backup.h"
struct tm *localtime();
struct tm *convdate();
struct fstab *fsent;
char line[180];
extern int errno;
int x_opt = NO;
char *day_names[7] =
{ "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday" };
char *month_names[12] =
{ "January","February","March","April","May","June","July","August",
"September","October","November","December" };
main(argc, argv)
int argc; char *argv[];
{
FILE *file;
char *ptr;
char fname[BUFSIZ]; /* file name */
char tname[BUFSIZ]; /* tape name */
char fsname[BUFSIZ];
char dump_comm[BUFSIZ];
char *tmp,*rindex();
int f_opt = NO;
int t_opt = NO;
int m_opt = NO;
int date_opt = 0;
int ret = 0;
int minutes = 5;
int tape_block = BLOCK_SIZE;
int tape_size = TAPE_LENGTH;
int tape_density = TAPE_DENSITY;
long tmptime; /* place to put time */
struct tm *curtim; /* current time structure */
int week_day,month_week,month,day,year;
argc--, argv++;
while (argc > 0) {
ptr = *argv;
while (*ptr) switch (*ptr++) {
case '-':
break;
case 'm':
case 'M':
m_opt = YES;
break;
case 'f':
case 'F':
f_opt = YES;
if (*ptr == 0) {
argv++;
argc--;
if (*argv == 0) {
fprintf(stderr,
"backup: no file given with '-f'.\n");
exit(1);
}
strcpy(fname,*argv);
}
else {
strcpy(fname,ptr);
*ptr = 0;
}
break;
case 't':
case 'T':
t_opt = YES;
if (*ptr == 0) {
argv++;
argc--;
if (*argv == 0) {
fprintf(stderr,
"backup: no device given with '-t'.\n");
exit(1);
}
strcpy(tname,*argv);
}
else {
strcpy(fname,ptr);
*ptr = 0;
}
break;
case 'b':
case 'B':
if (*ptr == 0) {
argv++;
argc--;
if (*argv == 0) {
fprintf(stderr,
"backup: no blocking factor given with '-b'.\n");
exit(1);
}
tape_block = atoi(*argv);
}
else {
tape_block = atoi(ptr);
*ptr = 0;
}
break;
case 'd':
case 'D':
if (*ptr == 0) {
argv++;
argc--;
if (*argv == 0) {
fprintf(stderr,
"backup: no density given with '-d'.\n");
exit(1);
}
tape_density = atoi(*argv);
}
else {
tape_density = atoi(ptr);
*ptr = 0;
}
break;
case 's':
case 'S':
if (*ptr == 0) {
argv++;
argc--;
if (*argv == 0) {
fprintf(stderr,
"backup: no size given with '-s'.\n");
exit(1);
}
tape_size = atoi(*argv);
}
else {
tape_size = atoi(ptr);
*ptr = 0;
}
break;
case 'w':
case 'W':
if (*ptr == 0) {
argv++;
argc--;
if (*argv == 0) {
fprintf(stderr,
"backup: warning time in minutes not given with '-w'.\n");
exit(1);
}
minutes = atoi(*argv);
}
else {
minutes = atoi(ptr);
*ptr = 0;
}
break;
case 'X':
case 'x':
x_opt = YES;
printf("*** Debugging ***\n");
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
month = day = year = 0;
date_opt = sscanf(--ptr,"%d/%d/%d",&month,&day,&year);
if (date_opt < 2)
{
fprintf(stderr,
"backup: illegal date specification\n");
exit(1);
}
*ptr = 0;
break;
default:
fprintf(stderr,
"Unknown option '%c' - ignored\n",ptr[-1]);
}
argc--, argv++;
*ptr = 0;
}
quiet = 0;
/* Ignore impatience */
signal(SIGTERM,SIG_IGN);
signal(SIGHUP,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
/* get current date */
if (date_opt)
{
curtim = convdate(month,day,year);
} else {
time(&tmptime);
curtim = localtime(&tmptime);
}
week_day = curtim -> tm_wday;
month_week = ( (curtim -> tm_mday - 1) / 7 ) + 1;
month = curtim -> tm_mon;
/* get dates file name */
if (! f_opt) sprintf(fname,"%s",BACKUPFILE);
if (! t_opt) sprintf(tname,"%s",DEVICE);
/*
* Open up the input file
*/
file = fopen(fname,"r");
if (file == NULL)
{
perror(file);
exit(errno);
}
/*
* Give introduction
*/
printf("backup: Performing backup for %s %s %d, %d\n",
day_names[week_day],month_names[month],curtim->tm_mday,
curtim->tm_year+1900);
line_count = 0;
while (fgets(line,180,file) != NULL)
{
line_count++;
lineptr = 0;
if(yyparse() || ignore == YES)continue;
if (x_opt)
{
printf("Today: %dw %dd %dm\n",month_week,week_day,month);
printres("Weeks: ",weeks,week_lst,week_ptr);
printres("Days: ",days,day_lst,day_ptr);
printres("Months: ",months,month_lst,month_ptr);
}
if (check_per(month_week,weeks,week_lst,week_ptr))continue;
if (check_per(week_day,days,day_lst,day_ptr))continue;
if (check_per(month,months,month_lst,month_ptr))continue;
fsent = getfsfile(filesys);
if (fsent == NULL)
{
fprintf(stderr,"*** No filesystem %s\n",filesys);
continue;
}
if (m_opt == NO)
{
/*
* Single user - if we already haven't quietize the system
*/
if (!quiet)
{
fprintf(stderr,"%s\n%s",
"*** You are about ready to kick off all users!!! ***",
"*** Are you SURE you want to do this? ");
gets(dump_comm);
if (dump_comm[0] != 'y' &&
dump_comm[0] != 'Y') abort();
fprintf(stderr,
"*** Are you POSITIVE??? ");
gets(dump_comm);
if (dump_comm[0] != 'y' &&
dump_comm[0] != 'Y') abort();
fprintf(stderr,
"*** Beginning system shutdown....");
quietize(minutes);
quiet++;
}
}
tmp = rindex(fsent->fs_spec,'/');
fsname[0] = '\0';
strncpy(fsname,fsent->fs_spec,(int)tmp-(int)(fsent->fs_spec)+1);
fsname[(int)tmp-(int)(fsent->fs_spec)+1] = '\0';
strncat(fsname,"r",1);
strcat(fsname,++tmp);
printf("To perform level %d dump of %s\n",level,filesys);
dump_comm[0] = '0';
retry: while (*dump_comm != 'r' && *dump_comm != 'q')
{
printf("mount first tape and press 'r' RETURN when ready: ");
gets(dump_comm);
}
if (*dump_comm == 'q') continue;
sprintf(dump_comm,"%s %1dnufsdb %s %d %d %d %s\n",
DUMPCOM,level,tname,
tape_size,tape_density,tape_block,
fsname);
ret = system(dump_comm);
sprintf(line,"mt -t %s offl\n",tname);
system(line);
printf("*** %s ***\n",string);
}
printf("Backup is now complete!\n");
if (m_opt == NO)
{
restart(); /* Restart the System */
}
}
char
getnextchar()
{
return((char)line[lineptr++]);
}
check_per(today,target,list,count)
int today,target,count;
int list[];
{
int i;
if (target == ALL)
return(0);
else if (target == LIST)
{
for (i = 0 ; i < count ; i++)
{
if(list[i] == today)return(0);
}
}
else if (target == RANGE && today >= list[0] && today <= list[1])
return(0);
return(1);
}
printres(string,today,list,count)
char *string;
int today;
int list[];
int count;
{
int i;
printf("%s ",string);
switch(today)
{
case ALL:
printf("ALL ");
break;
case LIST:
printf("LIST ");
break;
case RANGE:
printf("RANGE ");
break;
}
printf("(%d)",count);
for (i = 0 ; i < count ; i++)
{
printf(" %d,",list[i]);
}
printf("\n");
}
abort()
{
fprintf(stderr,"*** Backup aborted ***\n");
exit(1);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'backup.h'
then
echo shar: will not over-write existing file "'backup.h'"
else
cat << \SHAR_EOF > 'backup.h'
/* $Header: backup.h,v 1.3 86/10/14 01:36:46 scooter Exp $ */
/*
* backup.h - defines and defaults for backup
*/
#define BLOCK_SIZE 32 /* Default blocking factor */
#define TAPE_LENGTH 2300 /* Default tape length */
#define TAPE_DENSITY 6250 /* Default tape density */
#define DEVICE "/dev/rmt9" /* Default device for dumps */
#define BACKUPFILE "/etc/backup_dates"
#define DUMPCOM "/etc/dump"
#define YES 1
#define NO 0
#define ALL -1
#define RANGE 0
#define LIST 1
int ignore,days,weeks,months;
int week_ptr,week_lst[5];
int month_ptr,month_lst[12];
int day_ptr,day_lst[7];
int level,line_count,lineptr;
char string[180];
char filesys[180];
int quiet;
extern int x_opt;
SHAR_EOF
fi # end of overwriting check
if test -f 'convdate.c'
then
echo shar: will not over-write existing file "'convdate.c'"
else
cat << \SHAR_EOF > 'convdate.c'
#ifndef lint
static char RCSid[] = "$Header: convdate.c,v 1.1 85/05/22 15:53:36 scooter Exp $";
#endif lint
/*
* Module to convert date from mm/dd/yy format to a "tm" structure
*/
#include <stdio.h>
#include <sys/time.h>
#include <tzfile.h>
static int dmsize[13] =
{ -1,31,28,31,30,31,30,31,31,30,31,30,31 };
struct tm *
convdate(month,day,year)
int month,day,year;
{
int i;
struct tm *today;
struct timeval tv;
struct timezone tz;
gettimeofday(&tv,&tz);
today = localtime(&tv.tv_sec);
if (year == 0)year = today->tm_year;
if (month == 0)month = today->tm_mon+1;
if (day == 0)day = today->tm_mday;
if (year < 1000)year += 1900;
tv.tv_sec = 0;
if (isleap(year) && month > 2)
++tv.tv_sec;
for (--year;year >= EPOCH_YEAR;--year)
tv.tv_sec += isleap(year) ? DAYS_PER_LYEAR : DAYS_PER_NYEAR;
while (--month)
tv.tv_sec += dmsize[month];
tv.tv_sec += day - 1;
tv.tv_sec = HOURS_PER_DAY * tv.tv_sec;
tv.tv_sec = MINS_PER_HOUR * tv.tv_sec;
tv.tv_sec = SECS_PER_MIN * tv.tv_sec;
/* Now convert to local timezone */
tv.tv_sec += (long)tz.tz_minuteswest*SECS_PER_MIN;
if (localtime(&tv.tv_sec)->tm_isdst) tv.tv_sec -= SECS_PER_HOUR;
return(localtime(&tv.tv_sec));
}
SHAR_EOF
fi # end of overwriting check
if test -f 'parser.y'
then
echo shar: will not over-write existing file "'parser.y'"
else
cat << \SHAR_EOF > 'parser.y'
%{
static char rcsid[] = "$Header: parser.y,v 1.2 85/04/05 17:15:02 scooter Exp $";
#include "backup.h"
%}
%start pgm
%token COMMENT DAY STRING NUM FILESYS STAR DASH NEWLINE MONTH COMMA
%%
pgm : COMMENT NEWLINE
{ ignore = YES; YYACCEPT; }
| day_spec week_spec month_spec level filesys end_spec NEWLINE
{ ignore = NO; YYACCEPT; }
| error '\n'
{ yyerrok; }
;
level: NUM
{ level = $1; }
;
filesys: FILESYS
{ strcpy(filesys,yytext); }
;
day_spec: STAR
{ days = ALL; }
| day_list
{ days = LIST; }
| DAY DASH DAY
{ days = RANGE; day_lst[0] = $1;
day_lst[1] = $3; day_ptr = 2;}
;
day_list: DAY
{ day_ptr = 0; day_lst[day_ptr++] = $1; }
| day_list COMMA DAY
{ day_lst[day_ptr++] = $3; }
;
week_spec:STAR
{ weeks = ALL; }
| num_list
{ weeks = LIST; }
| NUM DASH NUM
{ weeks = RANGE; week_lst[0] = $1;
week_lst[1] = $3; week_ptr = 2;}
;
num_list: NUM
{ week_ptr = 0; week_lst[week_ptr++] = $1; }
| num_list COMMA NUM
{ week_lst[week_ptr++] = $3; }
;
month_spec: STAR
{ months = ALL; }
| month_list
{ months = LIST; }
| MONTH DASH MONTH
{ months = RANGE; month_lst[0] = $1;
month_lst[1] = $3; month_ptr = 2;}
;
month_list: MONTH
{ month_ptr = 0; month_lst[month_ptr++] = $1; }
| month_list COMMA MONTH
{ month_lst[month_ptr++] = $3; }
;
end_spec: /* empty */
| STRING
| STRING COMMENT
| COMMENT
;
%%
#include "lex.yy.c"
yyerror(s)
char *s;
{
fprintf(stderr,"%s:line = %d, char = %d\n",s,line_count,lineptr);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'proclist.c'
then
echo shar: will not over-write existing file "'proclist.c'"
else
cat << \SHAR_EOF > 'proclist.c'
static char rcsid[] = "$Header: proclist.c,v 1.6 87/05/25 16:55:54 scooter Exp $";
/*
* proclist
*
* This routine returns a list of candidate procedures for
* killing.
*
* $Log: proclist.c,v $
* Revision 1.6 87/05/25 16:55:54 scooter
* Added Appleshare stuff to "special processing" list
*
* Revision 1.5 86/10/15 09:26:13 scooter
* Added syslogd to the exclusion list
*
* Revision 1.4 86/10/14 01:33:46 scooter
* Added process specific startup/shutdown stuff
*
*
*/
#include "backup.h"
#include "ulist.h"
#include <stdio.h>
/*
* Table of offsets for portions of the ps -l line
*/
#define UID 7
#define PID 12
#define PPID 18
#define STAT 61
#define CMD 75
/*
* List of processes to exclude
*/
char *exlist[] =
{ "init",
"swapper",
"pagedaemon",
"/etc/timed",
"/etc/named",
"/etc/syslogd",
"/etc/atalkad", /* Kinetics route info server */
"/usr/local/lib/lsrv", /* Appletalk spooler */
"/usr/local/lib/atis", /* Appletalk name server */
"- std.9600",
"- std.4800",
"- std.1200",
"- P4800",
"- P1200",
"- D1200",
"- Console",
0 };
/*
* Processes which require special shutdown/restart
*/
struct proc_struct
{
char *pr_name;
char *pr_shutdown;
char *pr_restart;
} special_procs[] = {
{"/etc/rjecop","opr 0 .d","/etc/hsp_reload"},
{"genie Aufs Daemon","kill -TERM %d","cd /usr/adm;/usr/local/lib/aufs -V AppleSharePublicVolumes -U 20"},
{"jinn Aufs Daemon","kill -TERM %d","cd /usr/adm;/usr/local/lib/aufs -U 20"},
{0,0,0}
};
struct ulist *
proclist()
{
struct ulist *head=NULL;
struct ulist *tail=NULL;
FILE *pschan,*popen();
char string[180],*tmp,*rindex();
int i,ex_flag;
pschan = popen("/bin/ps -lgaxw","r");
if (pschan == NULL)
{
fprintf(stderr,"*** Unable to get ps listing ***");
exit (1);
}
fgets(string,180,pschan); /* Skip the header */
while ( fgets(string,180,pschan) != NULL )
{
/*
* Check for excluded processes
*/
i = ex_flag = 0;
while ( tmp = exlist[i++] )
{
if (!strncmp(string+CMD,tmp,strlen(tmp)))
{
ex_flag = 1;
break;
}
}
if (ex_flag) continue;
if (head == NULL)
{
head = tail = (struct ulist *)
malloc(sizeof(struct ulist));
} else
{
tail->next = (struct ulist *)
malloc(sizeof(struct ulist));
tail = tail->next;
}
tail->uid = atoi(string+UID);
tail->pid = atoi(string+PID);
tail->ppid = atoi(string+PPID);
strncpy(tail->stat,string+STAT,4);
strncpy(tail->cmd,string+CMD,39);
tmp = rindex(tail->cmd,'\n');
if (tmp != NULL)*tmp = '\0';
tail->special_flag = 0;
tail->next = NULL;
/*
* Check for special shutdown/startup
*/
i = 0;
while ( tmp = special_procs[i].pr_name )
{
if (!strncmp(tail->cmd,tmp,strlen(tmp)))
{
tail->special_flag++;
/* Allow single argument (pid) -- this will allow special signals */
sprintf(tail->proc_shutdn, special_procs[i].pr_shutdown, tail->pid);
sprintf(tail->proc_restart, special_procs[i].pr_restart, tail->pid);
break;
}
i++;
}
#ifdef DEBUG
if (x_opt)
printf("%6d, %6d, %6d, %4s, %s\n",tail->uid,tail->pid,
tail->ppid,tail->stat,tail->cmd);
#endif DEBUG
}
pclose(pschan);
return(head);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'quietize.c'
then
echo shar: will not over-write existing file "'quietize.c'"
else
cat << \SHAR_EOF > 'quietize.c'
static char rcsid[] = "$Header: quietize.c,v 1.7 86/10/14 01:34:03 scooter Exp $";
/*
* quietize
*
* This module controls all of the procedures necessary to bring
* the system to a quiescent state. Basically this can be summarized
* by the following:
*
* 1. Do a shutdown to tell the users goodbye (/etc/shutdown)
* 2. Get a listing of all the processes running (/bin/ps)
* 3. Send a SIGHUP to all user processes and handle special shutdown
* 4. Get another listing
* 5. Send a SIGSTOP to everything but gettys and inits
*
* $Log: quietize.c,v $
* Revision 1.7 86/10/14 01:34:03 scooter
* Added process specific startup/shutdown stuff
*
*
*/
#include "backup.h"
#include "ulist.h"
#include <stdio.h>
#include <signal.h>
struct ulist *u_list,*proclist(),*proc;
int our_pid;
int our_ppid;
quietize(minutes)
int minutes;
{
int fixlog(),procont();
/*
* Begin by going through all of the warning stuff
*/
fprintf(stderr,"\n*** Warning users ...");
if (minutes <= 0)minutes = 5;
signal(SIGINT,fixlog);
#ifdef DEBUG
if (x_opt == NO)
shutdown(minutes);
#else DEBUG
shutdown(minutes);
#endif DEBUG
/*
* Get our pid
*/
our_pid = getpid();
/*
* Get the list of processes on the system
*/
fprintf(stderr,"\n*** Finding processes ...");
u_list = proclist();
/*
* Blow them away
*/
fprintf(stderr,"\n*** Hanging up processes ...");
for (proc = u_list ; proc != NULL ; proc = proc->next)
{
if (proc->pid == our_pid)our_ppid = proc->ppid;
}
#ifdef DEBUG
if (x_opt)
printf("Our pid = %d, our ppid = %d\n",our_pid,our_ppid);
#endif DEBUG
for (proc = u_list ; proc != NULL ; proc = proc->next)
{
if (proc->pid == our_pid ||
proc->pid == our_ppid ||
proc->special_flag)continue;
#ifdef DEBUG
if (x_opt)
printf("Hanging up proces %s (%d)\n",proc->cmd,proc->pid);
else
#endif DEBUG
kill(proc->pid,SIGHUP);
}
/*
* Make an attempt to be clean by freeing up the memory
*/
for (proc = u_list ; proc != NULL ; )
{
free(proc->cmd);
u_list = proc;
proc = proc->next;
free(u_list);
}
/*
* Get the left-over list
*/
u_list = proclist();
/*
* Stop them
*/
fprintf(stderr,"\n*** Stopping up processes ...");
signal(SIGINT,procont);
for (proc = u_list ; proc != NULL ; proc = proc->next)
{
if ( proc->pid == our_pid ||
proc->pid == our_ppid)continue;
#ifdef DEBUG
if (x_opt)
{
if (proc->special_flag)
printf("Special shutdown of %s (%d) with %s\n",
proc->cmd,proc->pid,proc->proc_shutdn);
else
printf("Stopping up process %s (%d)\n",proc->cmd,
proc->pid);
} else
#endif DEBUG
if (proc->special_flag)
system(proc->proc_shutdn);
else
kill(proc->pid,SIGSTOP);
}
/*
* Now that things should be quiet, sync the disks
*/
sync();
sleep(1);
sync();
sleep(5);
}
fixlog()
{
unlink("/etc/nologin");
fprintf(stderr,"*** Backup aborted ***\n");
exit(0);
}
procont()
{
int restart();
restart();
fprintf(stderr,"*** Backup aborted ***\n");
exit(0);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'restart.c'
then
echo shar: will not over-write existing file "'restart.c'"
else
cat << \SHAR_EOF > 'restart.c'
static char rcsid[] = "$Header: restart.c,v 1.3 86/10/14 01:34:06 scooter Exp $";
/*
* restart
*
* This module controls the system restart after backup is complete
*
* $Log: restart.c,v $
* Revision 1.3 86/10/14 01:34:06 scooter
* Added process specific startup/shutdown stuff
*
*
*/
#include <stdio.h>
#include "backup.h"
#include "ulist.h"
#include <signal.h>
extern struct ulist *u_list;
extern int our_pid,our_ppid;
restart()
{
FILE *fs;
struct ulist *proc;
/*
* Restart stopped processes
*/
fprintf(stderr,"\n*** Restarting processes ...");
for (proc = u_list ; proc != NULL ; proc = proc->next)
{
if (proc->pid < 5 || proc->pid == our_pid ||
proc->pid == our_ppid)continue;
#ifdef DEBUG
if (x_opt)
if (proc->special_flag)
printf("restarting %s with %s\n",
proc->cmd,proc->proc_restart);
else
printf("starting process %d\n",proc->pid);
else
#endif DEBUG
if (proc->special_flag)
system(proc->proc_restart);
else
kill(proc->pid,SIGCONT);
}
unlink("/etc/nologin"); /* Make sure users can log in */
unlink("/dev/printer"); /* Restart all of the printers */
system("/usr/lib/lpd"); /* Start the deaemon */
return(0);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'scanner.l'
then
echo shar: will not over-write existing file "'scanner.l'"
else
cat << \SHAR_EOF > 'scanner.l'
%{
/* $Header: scanner.l,v 1.3 85/04/08 09:59:35 scooter Exp $ */
#include "y.tab.h"
#undef input
#undef output
#undef unput
#define allprint(c) (putchar(c))
#define sprint(str) (printf("%s",str))
#define output(c) (putchar(c))
#define input() (yytchar=yysptr>yysbuf?U(*--yysptr):getnextchar())
#define unput(c) (*yysptr++=(c))
#define yywrap() 1
%}
star \*
dash \-
filesys \/[0-9a-zA-Z/]*
slash \/
space [ \t]
nu [0-9][0-9]*
arb [a-zA-Z]*
string \"[^"]*\"
comm \#.*
quote \"
comma \,
newline [\n]
a [aA]
b [bB]
c [cC]
d [dD]
e [eE]
f [fF]
g [gG]
h [hH]
i [iI]
j [jJ]
k [kK]
l [lL]
m [mM]
n [nN]
o [oO]
p [pP]
q [qQ]
r [rR]
s [sS]
t [tT]
u [uU]
v [vV]
w [wW]
x [xX]
y [yY]
z [zZ]
%%
{comm}{arb} {return(COMMENT);}
{string} {strcpy(string,yytext);return(STRING);}
{star}{space} {yylval=0;return(STAR);}
{nu} {sscanf(yytext,"%d",&yylval);
return(NUM);}
{dash} {return(DASH);}
{s}{u}{n}{arb} {yylval=0;return(DAY);}
{m}{o}{n}{arb} {yylval=1;return(DAY);}
{t}{u}{e}{arb} {yylval=2;return(DAY);}
{w}{e}{d}{arb} {yylval=3;return(DAY);}
{t}{h}{u}{arb} {yylval=4;return(DAY);}
{f}{r}{i}{arb} {yylval=5;return(DAY);}
{s}{a}{t}{arb} {yylval=6;return(DAY);}
{j}{a}{n}{arb} {yylval=0;return(MONTH);}
{f}{e}{b}{arb} {yylval=1;return(MONTH);}
{m}{a}{r}{arb} {yylval=2;return(MONTH);}
{a}{p}{r}{arb} {yylval=3;return(MONTH);}
{m}{a}{y}{arb} {yylval=4;return(MONTH);}
{j}{u}{n}{arb} {yylval=5;return(MONTH);}
{j}{u}{l}{arb} {yylval=6;return(MONTH);}
{a}{u}{g}{arb} {yylval=7;return(MONTH);}
{s}{e}{p}{arb} {yylval=8;return(MONTH);}
{o}{c}{t}{arb} {yylval=9;return(MONTH);}
{n}{o}{v}{arb} {yylval=10;return(MONTH);}
{d}{e}{c}{arb} {yylval=11;return(MONTH);}
{filesys} {return(FILESYS);}
{newline} {return(NEWLINE);}
{comma} {return(COMMA);}
[ \t,] ;
SHAR_EOF
fi # end of overwriting check
if test -f 'shutdown.c'
then
echo shar: will not over-write existing file "'shutdown.c'"
else
cat << \SHAR_EOF > 'shutdown.c'
static char rcsid[] = "$Header: shutdown.c,v 1.1 85/04/05 17:14:09 scooter Exp $";
/*
* shutdown
*
* This module controls the system shutdown message stuff.
*/
#include <stdio.h>
#include "backup.h"
shutdown(minutes)
int minutes;
{
char temp[180];
FILE *nlfl;
/*
* Begin by formatting the shutdown command
*/
sprintf(temp,"/etc/shutdown -k +%d %s",minutes,
"System going down for system backups");
system (temp);
/*
* Now sleep until shutdown is complete
*/
sleep(minutes*60 + 5);
/*
* Since shutdown unlinks /etc/nologin when it exits, we must re-do it
*/
nlfl = fopen("/etc/nologin","w");
if (nlfl == NULL)
{
fprintf(stderr,"*** Warning: unable to disable logins\n");
} else {
fprintf(nlfl,"NO LOGINS: System backups in progress\n");
fflush(nlfl);
fclose(nlfl);
}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'ulist.h'
then
echo shar: will not over-write existing file "'ulist.h'"
else
cat << \SHAR_EOF > 'ulist.h'
/* $Header: ulist.h,v 1.2 86/10/14 01:34:47 scooter Exp $ */
struct ulist {
int pid; /* Process id */
int ppid; /* Parent process id */
int uid; /* Uid of the process */
int stat[4]; /* The process state */
char cmd[40]; /* The command name */
int special_flag; /* Special startup/shutdown? */
char proc_shutdn[80]; /* shutdown command */
char proc_restart[80]; /* restart command */
struct ulist *next;
};
SHAR_EOF
fi # end of overwriting check
if test -f 'genie_dates'
then
echo shar: will not over-write existing file "'genie_dates'"
else
cat << \SHAR_EOF > 'genie_dates'
# Backup schedule for Genie - Genentech, Inc.
# Daily level 2's
Mon-Thu * * 2 /va "Dump complete - Label tape /va level 2 Today's date "
Mon-Thu * * 2 /usr/src "Dump complete - Label tape /usr/src level 2 Today's date"
Mon-Thu * * 2 /usr "Dump complete - Label tape /usr level 2 Today's date"
Mon-Thu * * 2 /usr/spool "Dump complete - Label tape /usr/spool level 2 Today's date"
Mon-Thu * * 2 /nmr "Dump complete - Label tape /nmr level 2 Today's date"
# Weekly level 1's
Fri 1-5 * 1 / "Dump complete - Label tape / level 1 Today's date"
Fri 1-5 * 1 /va "Dump complete - Label tape /va level 1 Today's date"
Fri 1-5 * 1 /usr/src "Dump complete - Label tape /usr/src level 1 Today's date"
Fri 1-5 * 1 /usr "Dump complete - Label tape /usr level 1 Today's date"
Fri 1-5 * 1 /usr/spool "Dump complete - Label tape /usr/spool level 1 Today's date"
Fri 1-5 * 1 /nmr "Dump complete - Label tape /nmr level 1 Today's date"
Fri 1-5 * 1 /usr/seqdb "Dump complete - Label tape /usr/seqdb level 1 Today's date"
Fri 1-5 * 1 /usr/src/contrib "Dump complete - Label tape /usr/src/contrib level 1 Today's date"
# Monthly level 0's
Sun 1 * 0 / "Dump complete - Label tape root level 0 Today's date"
Sun 1 * 0 /va "Dump complete - Label tapes /va level 0 Today's date Vol #"
Sun 1 * 0 /usr/src "Dump complete - Label tape /usr/src level 0 Today's date"
Sun 1 * 0 /usr "Dump complete - Label tapes /usr level 0 Today's date Vol #"
Sun 1 * 0 /usr/spool "Dump complete - Label tape /usr/spool level 0 Today's date Vol #"
Sun 1 * 0 /nmr "Dump complete - Label tape /nmr level 0 Today's date Vol #"
SHAR_EOF
fi # end of overwriting check
if test -f 'backup_dates'
then
echo shar: will not over-write existing file "'backup_dates'"
else
cat << \SHAR_EOF > 'backup_dates'
# Backup schedule for Genie - Genentech, Inc.
# Daily level 9's
Tue,Fri * * 9 /va "/va dump complete"
Tue,Wed,Fri * * 9 /vb "/vb dump complete"
Tue,Wed,Fri * * 9 /vc "/vc dump complete"
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
--
For comp.sources.unix stuff, mail to sources at uunet.uu.net.
More information about the Comp.sources.unix
mailing list