/* FixWho.C -- Program to fix up PPN file */ /* ** This program reads in one or more PPN files, sorts and ** re-merges the data found therein, and writes a new file. */ #include #if defined(__TURBOC__) #include #else #include #endif #include #include #include #include #define PPNFUNC 1 #include "wtppn.h" /**********************/ /* ***** MACROS ***** */ /**********************/ #define PROG_VER "WizWho 1.00 (C) SirSloth 09/94" #define MAX_PPNS 1000 #define WRITE_TMP 1 #define WRITE_FIX 2 #define WRITE_BOTH (WRITE_TMP | WRITE_FIX) /********************************/ /* ***** GLOBAL VARIABLES ***** */ /********************************/ int gargc; int gargn; char **gargv; struct ffblk ffblk; /* file control block for findfirst */ int in_flist = 0; /* tells if we are in a file list */ char f_drive[MAXDRIVE]; /* file name components for fnsplit */ char f_dir[MAXDIR]; char f_name[MAXFILE]; char f_ext[MAXEXT]; char f_path[MAXPATH]; FILE *fp_dat; /* one of the input data files */ char *fn_dat; FILE *fp_tmp; /* temporary file, only uids */ char *fn_tmp = TMPFILENAME; FILE *fp_fix; /* fixed file */ char *fn_fix = FIXFILENAME; t_ppnrec ppn_irec; /* input record */ t_ppnrec *ppn_buff = NULL; /* buffer for all stored ppns */ t_ppnrec *ppn_ptr; /* pointer into above buffer */ unsigned ppn_count = 0; /* number of records in buffer */ t_ppnrec *last_ppn = NULL; /* last PPN in buffer */ const t_user user_nil = { " ", " ", 0 }; t_user user_min; /* lower bound on input user */ /* ========================================================= ** first_file(): Get the first file name, from command line ** or from the find_first function. */ int first_file(void) { gargn = 1; in_flist = 0; return next_file(); } /* end first_file() */ /* ========================================================= ** next_file(): Get the next file name, from command line ** or from the find_next function. */ int next_file(void) { char nil_drive[MAXDRIVE]; char nil_dir[MAXDIR]; for ( ; ; ) { if (in_flist == 0) { if (gargn >= gargc) return 0; (void) fnsplit(gargv[gargn], f_drive, f_dir, f_name, f_ext); (void) fnmerge(f_path, f_drive, f_dir, f_name, f_ext); if (findfirst(f_path, &ffblk, 0) != 0) { gargn++; } else { in_flist = 1; break; } } else if (in_flist == 1) { if (findnext(&ffblk) == 0) break; in_flist = 0; gargn++; } } /* end for */ (void) fnsplit(ffblk.ff_name, nil_drive, nil_dir, f_name, f_ext); (void) fnmerge(f_path, f_drive, f_dir, f_name, f_ext); return 1; } /* end next_file() */ /* ========================================================= ** scan_file(): read through input file, extracting the ** (up to) 1000 smallest users. */ void scan_file(char *filename, cmpfunc *comp) { FILE *fp_inp; int stat; /* file read status */ t_ppnrec *ppn_ptr0; t_ppnrec *ppn_ptr1; fp_inp = fopen(filename, "rb"); if (fp_inp == NULL) { perror(filename); exit(7); } rewind(fp_inp); while (! feof(fp_inp)) { stat = fread(&ppn_irec, sizeof(t_ppnrec), 1, fp_inp); if (stat != 1) { if (feof(fp_inp)) { break; } else if (ferror(fp_inp)) { perror(fn_dat); fprintf(stderr, "File %s: read error!\n", fn_dat); exit(5); } } /* ===== check data and decide where to put it ===== */ if ((*comp)(&ppn_irec, &user_min) <= 0) { /* --- new data is from a previous range, ignore it --- */ } else if (ppn_count == 0) { /* --- no data yet -- we'll take anything --- */ last_ppn = &ppn_buff[ppn_count++]; *last_ppn = ppn_irec; } else if ((*comp)(&ppn_irec, last_ppn) > 0) { /* --- data bigger than our biggest PPN --- */ if (ppn_count < MAX_PPNS) { /* --- there is room -- take it unconditionally. --- */ last_ppn = &ppn_buff[ppn_count++]; *last_ppn = ppn_irec; } else { /* --- no more room -- skip it this time --- */ ; } } else if ((ppn_ptr=bsearch(&ppn_irec, ppn_buff, ppn_count, sizeof(t_ppnrec), &cmp_by_uids)) != NULL) { /* --- found in buffer -- update. --- */ if (ppn_irec.user.mxlv > ppn_ptr->user.mxlv) { ppn_ptr->user.mxlv = ppn_irec.user.mxlv; } if (strncmp(ppn_irec.date1, ppn_ptr->date1, CDATE_LEN) < 0) { strncpy(ppn_ptr->date1, ppn_irec.date1, CDATE_LEN); } if (strncmp(ppn_irec.date2, ppn_ptr->date2, CDATE_LEN) > 0) { strncpy(ppn_ptr->date2, ppn_irec.date2, CDATE_LEN); } } else { /* not in buffer -- insert. */ /*** if (filename == fn_tmp) { printf(" Inserting %.*s...\n", NAME_LEN, ppn_irec.user.name); } ***/ for (ppn_ptr0=ppn_ptr1=last_ppn+1; ; ppn_ptr1--) { if (ppn_ptr1 == ppn_buff) break; ppn_ptr0--; *ppn_ptr1 = *ppn_ptr0; if ((*comp)(&ppn_irec, ppn_ptr1) > 0) break; } /* end for */ *ppn_ptr1 = ppn_irec; if (ppn_count < MAX_PPNS) { last_ppn = &ppn_buff[ppn_count++]; } } /* End if */ } /* End while !feof */ fclose(fp_inp); } /* End scan_file() */ /* ========================================================= ** write_ppns(): write all ppn records from ppn_buff to file. */ void write_ppns(int whereto) { unsigned nwritten = 0; int stat; ppn_ptr = ppn_buff; for (nwritten=0; nwritten < ppn_count; nwritten++) { if (whereto & WRITE_TMP) { stat = fwrite(ppn_ptr, sizeof(t_ppnrec), 1, fp_tmp); if (stat != 1) { fprintf(stderr, "Error writing file %s!\n", TMPFILENAME); exit(7); } } if (whereto & WRITE_FIX) { stat = fwrite(ppn_ptr, sizeof(t_ppnrec), 1, fp_fix); if (stat != 1) { fprintf(stderr, "Error writing file %s!\n", FIXFILENAME); exit(7); } } ppn_ptr++; } } /* End write_ppns() */ /* ========================================================= ** main(): main program. */ void main(int argc, char *argv[]) { int jfile; /* loop counter over file names */ int passno; long total_written = 0; char *default_parms[] = { "", "BL*.LOG", "" }; /* say hello */ printf("%s\n", PROG_VER); /* --- make argc and argv globally available --- */ if (argc > 1) { gargc = argc; gargv = argv; } else { gargc = 2; default_parms[0] = argv[0]; gargv = default_parms; } /* --- try to open all filenames to check for existence --- */ for (first_file(); next_file(); ) { fn_dat = f_path; fp_dat = fopen(fn_dat, "rb"); if (fp_dat == NULL) { perror(fn_dat); exit(2); } fclose(fp_dat); } /* allocate buffer for ppn records */ ppn_buff = calloc(MAX_PPNS+1, sizeof(t_ppnrec)); if (ppn_buff == NULL) { fprintf(stderr, "Error: Not enough memory for ppn list!\n"); exit(6); } ppn_count = 0; /* try to open tmp file */ fp_tmp = fopen(TMPFILENAME, "wb"); if (fp_tmp == NULL) { perror(TMPFILENAME); exit(3); } /* try to open fix file */ fp_fix = fopen(FIXFILENAME, "wb"); if (fp_fix == NULL) { perror(FIXFILENAME); exit(3); } /* ===== cycle through all the given input files, extracting up to 1000 users at a time. ===== */ user_min = user_nil; for (passno=1; ; passno++) { last_ppn = (t_ppnrec *)(&user_nil); ppn_count = 0; printf("Starting pass %u\n", passno); for (first_file(); next_file(); ) { fn_dat = f_path; scan_file(fn_dat, &cmp_by_uids); } /* End for jfile */ write_ppns(WRITE_BOTH); total_written += ppn_count; user_min = last_ppn->user; printf("End pass %u; Records written: %6lu\n", passno, total_written); if (ppn_count < MAX_PPNS) break; } /* End for passno */ /* ===== Close TMP file and re-open for sorting by names ===== */ if (fclose(fp_tmp)) { perror(TMPFILENAME); fprintf(stderr, "Error closing file %s!\n", TMPFILENAME); } /* ===== Scan through the TMP file, (now called fp_dat!) extracting up to 1000 sorted PPNs per pass. ===== */ printf("Now sorting by names. " "Please be patient, this could take a while...\n"); user_min = user_nil; for (++passno; ; passno++) { last_ppn = (t_ppnrec *)(&user_nil); ppn_count = 0; printf("Starting pass %u\n", passno); scan_file(fn_tmp, &cmp_by_name); write_ppns(WRITE_FIX); total_written += ppn_count; user_min = last_ppn->user; printf("End pass %u; Records written: %6lu\n", passno, total_written); if (ppn_count < MAX_PPNS) break; } /* End for passno */ fclose(fp_fix); printf("*** End FixWho ***\n"); } /* End main() */