rsalz@bbn.com (Rich Salz) (02/24/88)
Submitted-by: Scooter Morris <scooter@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@uunet.uu.net.