X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famcheck.c;h=9e83962ea1ba19cdf84a5241a592870213b6a933;hb=cdbbeef9cde260e429854dd313bc0bf7560e1e24;hp=36ab3d957e10cfdfdb009495ae6c001b477c5fab;hpb=6663e25ecad46c729d9be4f8585c51b523ac9044;p=debian%2Famanda diff --git a/server-src/amcheck.c b/server-src/amcheck.c index 36ab3d9..9e83962 100644 --- a/server-src/amcheck.c +++ b/server-src/amcheck.c @@ -24,7 +24,7 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: amcheck.c,v 1.121 2006/02/06 22:17:09 ktill Exp $ + * $Id: amcheck.c,v 1.149 2006/08/24 01:57:16 paddy_s Exp $ * * checks for common problems in server and clients */ @@ -50,7 +50,7 @@ #define BUFFER_SIZE 32768 -static int conf_ctimeout; +static time_t conf_ctimeout; static int overwrite; static disklist_t origq; @@ -59,16 +59,17 @@ static uid_t uid_dumpuser; /* local functions */ -void usage P((void)); -int start_client_checks P((int fd)); -int start_server_check P((int fd, int do_localchk, int do_tapechk)); -int main P((int argc, char **argv)); -int test_server_pgm P((FILE *outf, char *dir, char *pgm, - int suid, uid_t dumpuid)); +void usage(void); +pid_t start_client_checks(int fd); +pid_t start_server_check(int fd, int do_localchk, int do_tapechk); +int main(int argc, char **argv); +int test_server_pgm(FILE *outf, char *dir, char *pgm, int suid, uid_t dumpuid); -void usage() +void +usage(void) { - error("Usage: amcheck%s [-M ] [-mawsclt] [host [disk]* ]*", versionsuffix()); + error("Usage: amcheck%s [-am] [-w] [-sclt] [-M
] [host [disk]* ]* [-o configoption]*", versionsuffix()); + /*NOTREACHED*/ } static unsigned long malloc_hist_1, malloc_size_1; @@ -79,18 +80,20 @@ static char *our_feature_string = NULL; static char *displayunit; static long int unitdivisor; -int main(argc, argv) -int argc; -char **argv; +int +main( + int argc, + char ** argv) { char buffer[BUFFER_SIZE]; char *version_string; char *mainfname = NULL; char pid_str[NUM_STR_SIZE]; - int do_clientchk, clientchk_pid, client_probs; - int do_localchk, do_tapechk, serverchk_pid, server_probs; - int chk_flag; - int opt, size, tempfd, mainfd; + int do_clientchk, client_probs; + int do_localchk, do_tapechk, server_probs; + pid_t clientchk_pid, serverchk_pid; + int opt, tempfd, mainfd; + ssize_t size; amwait_t retstat; pid_t pid; extern int optind; @@ -104,6 +107,9 @@ char **argv; char *dumpuser; struct passwd *pw; uid_t uid_me; + int new_argc, my_argc; + char **new_argv, **my_argv; + char *errstr; safe_fd(-1, 0); safe_cd(); @@ -113,11 +119,12 @@ char **argv; /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); - dbopen(); + dbopen(DBG_SUBDIR_SERVER); + memset(buffer, 0, sizeof(buffer)); malloc_size_1 = malloc_inuse(&malloc_hist_1); - snprintf(pid_str, sizeof(pid_str), "%ld", (long)getpid()); + snprintf(pid_str, SIZEOF(pid_str), "%ld", (long)getpid()); erroutput_type = ERR_INTERACTIVE; @@ -131,15 +138,23 @@ char **argv; alwaysmail = mailout = overwrite = 0; do_localchk = do_tapechk = do_clientchk = 0; - chk_flag = 0; server_probs = client_probs = 0; tempfd = mainfd = -1; + parse_server_conf(argc, argv, &new_argc, &new_argv); + my_argc = new_argc; + my_argv = new_argv; + /* process arguments */ - while((opt = getopt(argc, argv, "M:mawsclt")) != EOF) { + while((opt = getopt(my_argc, my_argv, "M:mawsclt")) != EOF) { switch(opt) { case 'M': mailto=stralloc(optarg); + if(!validate_mailto(mailto)){ + printf("Invalid characters in mail address\n"); + exit(1); + } + /*FALLTHROUGH*/ case 'm': #ifdef MAILER mailout = 1; @@ -159,43 +174,77 @@ char **argv; exit(1); #endif break; - case 's': do_localchk = 1; do_tapechk = 1; - chk_flag = 1; + case 's': do_localchk = do_clientchk = do_tapechk = 1; break; case 'c': do_clientchk = 1; - chk_flag = 1; break; case 'l': do_localchk = 1; - chk_flag = 1; break; - case 'w': do_tapechk = 1; overwrite = 1; - chk_flag = 1; + case 'w': overwrite = 1; break; case 't': do_tapechk = 1; - chk_flag = 1; break; case '?': default: usage(); } } - argc -= optind, argv += optind; - if(! chk_flag) { + my_argc -= optind, my_argv += optind; + if(my_argc < 1) usage(); + + + if ((do_localchk | do_clientchk | do_tapechk) == 0) { + /* Check everything if individual checks were not asked for */ do_localchk = do_clientchk = do_tapechk = 1; } - if(argc < 1) usage(); + if(overwrite) + do_tapechk = 1; - config_name = stralloc(*argv); + config_name = stralloc(*my_argv); config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL); conffile = stralloc2(config_dir, CONFFILE_NAME); if(read_conffile(conffile)) { error("errors processing config file \"%s\"", conffile); + /*NOTREACHED*/ } + + dbrename(config_name, DBG_SUBDIR_SERVER); + + report_bad_conf_arg(); + amfree(conffile); + if(mailout && !mailto && + (getconf_seen(CNF_MAILTO)==0 || strlen(getconf_str(CNF_MAILTO)) == 0)) { + printf("\nNo mail address configured in amanda.conf\n"); + if(alwaysmail) + printf("When using -a option please specify -Maddress also\n\n"); + else + printf("Use -Maddress instead of -m\n\n"); + exit(1); + } + if(mailout && !mailto) + { + if(getconf_seen(CNF_MAILTO) && + strlen(getconf_str(CNF_MAILTO)) > 0) { + if(!validate_mailto(getconf_str(CNF_MAILTO))){ + printf("\nMail address in amanda.conf has invalid characters"); + printf("\nNo email will be sent\n"); + mailout = 0; + } + } + else { + printf("\nNo mail address configured in amanda.conf\n"); + if(alwaysmail) + printf("When using -a option please specify -Maddress also\n\n"); + else + printf("Use -Maddress instead of -m\n\n"); + exit(1); + } + } - conf_ctimeout = getconf_int(CNF_CTIMEOUT); + conf_ctimeout = getconf_time(CNF_CTIMEOUT); conf_diskfile = getconf_str(CNF_DISKFILE); if (*conf_diskfile == '/') { @@ -205,8 +254,13 @@ char **argv; } if(read_diskfile(conf_diskfile, &origq) < 0) { error("could not load disklist %s", conf_diskfile); + /*NOTREACHED*/ + } + errstr = match_disklist(&origq, my_argc-1, my_argv+1); + if (errstr) { + printf("%s",errstr); + amfree(errstr); } - match_disklist(&origq, argc-1, argv+1); amfree(conf_diskfile); /* @@ -215,15 +269,17 @@ char **argv; dumpuser = getconf_str(CNF_DUMPUSER); if ((pw = getpwnam(dumpuser)) == NULL) { error("cannot look up dump user \"%s\"", dumpuser); + /*NOTREACHED*/ } uid_dumpuser = pw->pw_uid; if ((pw = getpwuid(uid_me)) == NULL) { error("cannot look up my own uid (%ld)", (long)uid_me); + /*NOTREACHED*/ } if (uid_me != uid_dumpuser) { error("running as user \"%s\" instead of \"%s\"", - pw->pw_name, - dumpuser); + pw->pw_name, dumpuser); + /*NOTREACHED*/ } displayunit = getconf_str(CNF_DISPLAYUNIT); @@ -240,8 +296,10 @@ char **argv; if(do_clientchk && (do_localchk || do_tapechk)) { /* we need the temp file */ tempfname = vstralloc(AMANDA_TMPDIR, "/amcheck.temp.", pid_str, NULL); - if((tempfd = open(tempfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) + if((tempfd = open(tempfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) { error("could not open %s: %s", tempfname, strerror(errno)); + /*NOTREACHED*/ + } unlink(tempfname); /* so it goes away on close */ amfree(tempfname); } @@ -249,8 +307,10 @@ char **argv; if(mailout) { /* the main fd is a file too */ mainfname = vstralloc(AMANDA_TMPDIR, "/amcheck.main.", pid_str, NULL); - if((mainfd = open(mainfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) + if((mainfd = open(mainfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) { error("could not open %s: %s", mainfname, strerror(errno)); + /*NOTREACHED*/ + } unlink(mainfname); /* so it goes away on close */ amfree(mainfname); } @@ -289,11 +349,13 @@ char **argv; char number[NUM_STR_SIZE]; char *wait_msg = NULL; - snprintf(number, sizeof(number), "%ld", (long)pid); + snprintf(number, SIZEOF(number), "%ld", (long)pid); wait_msg = vstralloc("parent: reaped bogus pid ", number, "\n", NULL); - if (fullwrite(mainfd, wait_msg, strlen(wait_msg)) < 0) + if (fullwrite(mainfd, wait_msg, strlen(wait_msg)) < 0) { error("write main file: %s", strerror(errno)); + /*NOTREACHED*/ + } amfree(wait_msg); } } @@ -301,23 +363,31 @@ char **argv; /* copy temp output to main output and write tagline */ if(do_clientchk && (do_localchk || do_tapechk)) { - if(lseek(tempfd, 0, 0) == -1) + if(lseek(tempfd, (off_t)0, 0) == (off_t)-1) { error("seek temp file: %s", strerror(errno)); + /*NOTREACHED*/ + } - while((size=fullread(tempfd, buffer, sizeof(buffer))) > 0) { - if (fullwrite(mainfd, buffer, size) < 0) + while((size = fullread(tempfd, buffer, SIZEOF(buffer))) > 0) { + if (fullwrite(mainfd, buffer, (size_t)size) < 0) { error("write main file: %s", strerror(errno)); + /*NOTREACHED*/ + } } - if(size < 0) + if(size < 0) { error("read temp file: %s", strerror(errno)); + /*NOTREACHED*/ + } aclose(tempfd); } version_string = vstralloc("\n", "(brought to you by Amanda ", version(), ")\n", NULL); - if (fullwrite(mainfd, version_string, strlen(version_string)) < 0) + if (fullwrite(mainfd, version_string, strlen(version_string)) < 0) { error("write main file: %s", strerror(errno)); + /*NOTREACHED*/ + } amfree(version_string); amfree(config_dir); amfree(config_name); @@ -344,10 +414,8 @@ char **argv; char *subject; char **a; amwait_t retstat; - pid_t mailpid; - pid_t wpid; - int r; - int w; + ssize_t r; + ssize_t w; char *err = NULL; char *extra_info = NULL; char *line = NULL; @@ -357,8 +425,9 @@ char **argv; char number[NUM_STR_SIZE]; fflush(stdout); - if(lseek(mainfd, (off_t)0, SEEK_SET) == -1) { + if(lseek(mainfd, (off_t)0, SEEK_SET) == (off_t)-1) { error("lseek main file: %s", strerror(errno)); + /*NOTREACHED*/ } if(alwaysmail && !(server_probs || client_probs)) { subject = stralloc2(getconf_str(CNF_ORG), @@ -375,19 +444,20 @@ char **argv; * Remember that split() returns the original input string in * argv[0], so we have to skip over that. */ - a = (char **) alloc((MAILTO_LIMIT + 1) * sizeof(char *)); - memset(a, 0, (MAILTO_LIMIT + 1) * sizeof(char *)); + a = (char **) alloc((MAILTO_LIMIT + 1) * SIZEOF(char *)); + memset(a, 0, (MAILTO_LIMIT + 1) * SIZEOF(char *)); if(mailto) { a[1] = mailto; a[2] = NULL; } else { - r = split(getconf_str(CNF_MAILTO), a, MAILTO_LIMIT, " "); + r = (ssize_t)split(getconf_str(CNF_MAILTO), a, MAILTO_LIMIT, " "); a[r + 1] = NULL; } if((nullfd = open("/dev/null", O_RDWR)) < 0) { error("nullfd: /dev/null: %s", strerror(errno)); + /*NOTREACHED*/ } - mailpid = pipespawn(MAILER, STDIN_PIPE | STDERR_PIPE, + pipespawn(MAILER, STDIN_PIPE | STDERR_PIPE, &mailfd, &nullfd, &errfd, MAILER, "-s", subject, @@ -402,28 +472,36 @@ char **argv; * cases, the pipe will break and we will exit out of the loop. */ signal(SIGPIPE, SIG_IGN); - while((r = fullread(mainfd, buffer, sizeof(buffer))) > 0) { - if((w = fullwrite(mailfd, buffer, r)) != r) { + while((r = fullread(mainfd, buffer, SIZEOF(buffer))) > 0) { + if((w = fullwrite(mailfd, buffer, (size_t)r)) != (ssize_t)r) { if(w < 0 && errno == EPIPE) { strappend(extra_info, "EPIPE writing to mail process\n"); break; } else if(w < 0) { error("mailfd write: %s", strerror(errno)); + /*NOTREACHED*/ } else { error("mailfd write: wrote %d instead of %d", w, r); + /*NOTREACHED*/ } } } aclose(mailfd); ferr = fdopen(errfd, "r"); + if (!ferr) { + error("Can't fdopen: %s", strerror(errno)); + /*NOTREACHED*/ + } for(; (line = agets(ferr)) != NULL; free(line)) { + if (line[0] == '\0') + continue; strappend(extra_info, line); strappend(extra_info, "\n"); } afclose(ferr); errfd = -1; rc = 0; - while ((wpid = wait(&retstat)) != -1) { + while (wait(&retstat) != -1) { if (WIFSIGNALED(retstat)) { ret = 0; rc = sig = WTERMSIG(retstat); @@ -438,7 +516,7 @@ char **argv; } else { strappend(err, "returned "); } - snprintf(number, sizeof(number), "%d", ret); + snprintf(number, SIZEOF(number), "%d", ret); strappend(err, number); } } @@ -448,9 +526,13 @@ char **argv; amfree(extra_info); } error("error running mailer %s: %s", MAILER, err); + /*NOTREACHED*/ } } #endif + free_new_argv(new_argc, new_argv); + free_server_config(); + dbclose(); return (server_probs || client_probs); } @@ -463,58 +545,71 @@ char *first_match_label = NULL, *first_match = NULL, *found_device = NULL; char *label; char *searchlabel, *labelstr; tape_t *tp; -FILE *errf; - -int test_server_pgm(outf, dir, pgm, suid, dumpuid) -FILE *outf; -char *dir; -char *pgm; -int suid; -uid_t dumpuid; +FILE *errf = NULL; + +int +test_server_pgm( + FILE * outf, + char * dir, + char * pgm, + int suid, + uid_t dumpuid) { struct stat statbuf; int pgmbad = 0; + char *quoted; pgm = vstralloc(dir, "/", pgm, versionsuffix(), NULL); + quoted = quote_string(pgm); if(stat(pgm, &statbuf) == -1) { fprintf(outf, "ERROR: program %s: does not exist\n", - pgm); + quoted); pgmbad = 1; } else if (!S_ISREG(statbuf.st_mode)) { fprintf(outf, "ERROR: program %s: not a file\n", - pgm); + quoted); pgmbad = 1; } else if (access(pgm, X_OK) == -1) { fprintf(outf, "ERROR: program %s: not executable\n", - pgm); + quoted); pgmbad = 1; } else if (suid \ && dumpuid != 0 && (statbuf.st_uid != 0 || (statbuf.st_mode & 04000) == 0)) { - fprintf(outf, "WARNING: program %s: not setuid-root\n", - pgm); + fprintf(outf, "ERROR: program %s: not setuid-root\n", + quoted); + pgmbad = 1; } + amfree(quoted); amfree(pgm); return pgmbad; } -int start_server_check(fd, do_localchk, do_tapechk) - int fd; - int do_localchk, do_tapechk; +pid_t +start_server_check( + int fd, + int do_localchk, + int do_tapechk) { char *tapename; generic_fs_stats_t fs; - FILE *outf; + FILE *outf = NULL; holdingdisk_t *hdp; - int pid; + pid_t pid; int confbad = 0, tapebad = 0, disklow = 0, logbad = 0; int userbad = 0, infobad = 0, indexbad = 0, pgmbad = 0; int testtape = do_tapechk; tapetype_t *tp = NULL; + char *quoted; switch(pid = fork()) { - case -1: error("could not fork server check: %s", strerror(errno)); - case 0: break; + case -1: + error("could not fork server check: %s", strerror(errno)); + /*NOTREACHED*/ + + case 0: + break; + default: return pid; } @@ -526,8 +621,10 @@ int start_server_check(fd, do_localchk, do_tapechk) startclock(); - if((outf = fdopen(fd, "w")) == NULL) + if((outf = fdopen(fd, "w")) == NULL) { error("fdopen %d: %s", fd, strerror(errno)); + /*NOTREACHED*/ + } errf = outf; fprintf(outf, "Amanda Tape Server Host Check\n"); @@ -551,7 +648,7 @@ int start_server_check(fd, do_localchk, do_tapechk) amfree(errstr); confbad = 1; } - lbl_templ = tp->lbl_templ; + lbl_templ = tapetype_get_lbl_templ(tp); if(strcmp(lbl_templ, "") != 0) { if(strchr(lbl_templ, '/') == NULL) { lbl_templ = stralloc2(config_dir, lbl_templ); @@ -570,61 +667,61 @@ int start_server_check(fd, do_localchk, do_tapechk) confbad = 1; #endif } + + /* check that localhost is resolvable */ + if ((gethostbyname("localhost")) == NULL) { + fprintf(outf, "ERROR: Cannot resolve `localhost'.\n"); + } } /* * Look up the programs used on the server side. */ if(do_localchk) { - int suid_check=1; -#ifdef SSH_SECURITY - suid_check=0; -#endif + /* + * entreprise version will do planner/dumper suid check + */ if(access(libexecdir, X_OK) == -1) { + quoted = quote_string(libexecdir); fprintf(outf, "ERROR: program dir %s: not accessible\n", - libexecdir); + quoted); pgmbad = 1; + amfree(quoted); } else { - pgmbad = pgmbad \ - || test_server_pgm(outf, libexecdir, "planner", - suid_check, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, libexecdir, "dumper", - suid_check, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, libexecdir, "driver", - 0, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, libexecdir, "taper", - 0, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, libexecdir, "amtrmidx", - 0, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, libexecdir, "amlogroll", - 0, uid_dumpuser); + if(test_server_pgm(outf, libexecdir, "planner", 1, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, libexecdir, "dumper", 1, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, libexecdir, "driver", 0, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, libexecdir, "taper", 0, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, libexecdir, "amtrmidx", 0, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, libexecdir, "amlogroll", 0, uid_dumpuser)) + pgmbad = 1; } if(access(sbindir, X_OK) == -1) { + quoted = quote_string(sbindir); fprintf(outf, "ERROR: program dir %s: not accessible\n", sbindir); pgmbad = 1; + amfree(quoted); } else { - pgmbad = pgmbad \ - || test_server_pgm(outf, sbindir, "amgetconf", - 0, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, sbindir, "amcheck", - 1, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, sbindir, "amdump", - 0, uid_dumpuser); - pgmbad = pgmbad \ - || test_server_pgm(outf, sbindir, "amreport", - 0, uid_dumpuser); + if(test_server_pgm(outf, sbindir, "amgetconf", 0, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, sbindir, "amcheck", 1, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, sbindir, "amdump", 0, uid_dumpuser)) + pgmbad = 1; + if(test_server_pgm(outf, sbindir, "amreport", 0, uid_dumpuser)) + pgmbad = 1; } if(access(COMPRESS_PATH, X_OK) == -1) { + quoted = quote_string(COMPRESS_PATH); fprintf(outf, "WARNING: %s is not executable, server-compression and indexing will not work\n", - COMPRESS_PATH); + quoted); + amfree(quoted); } } @@ -660,31 +757,47 @@ int start_server_check(fd, do_localchk, do_tapechk) */ } if(access(tape_dir, W_OK) == -1) { - fprintf(outf, "ERROR: tapelist dir %s: not writable.\n", tape_dir); + quoted = quote_string(tape_dir); + fprintf(outf, "ERROR: tapelist dir %s: not writable.\n", quoted); tapebad = 1; + amfree(quoted); } else if(stat(tapefile, &statbuf) == -1) { - fprintf(outf, "ERROR: tapefile %s: %s, you must create an empty file.\n", - tapefile, strerror(errno)); + quoted = quote_string(tape_dir); + fprintf(outf, "ERROR: tapefile %s (%s), " + "you must create an empty file.\n", + quoted, strerror(errno)); tapebad = 1; + amfree(quoted); } else if(!S_ISREG(statbuf.st_mode)) { - fprintf(outf, "ERROR: tapefile %s: should be a regular file.\n", tapefile); + quoted = quote_string(tapefile); + fprintf(outf, "ERROR: tapefile %s: should be a regular file.\n", + quoted); tapebad = 1; + amfree(quoted); } else if(access(tapefile, F_OK) != 0) { - fprintf(outf, "ERROR: can't access tape list %s\n", tapefile); + quoted = quote_string(tapefile); + fprintf(outf, "ERROR: can't access tape list %s\n", quoted); tapebad = 1; + amfree(quoted); } else if(access(tapefile, F_OK) == 0 && access(tapefile, W_OK) != 0) { - fprintf(outf, "ERROR: tape list %s: not writable\n", tapefile); + quoted = quote_string(tapefile); + fprintf(outf, "ERROR: tape list %s: not writable\n", quoted); tapebad = 1; + amfree(quoted); } else if(read_tapelist(tapefile)) { - fprintf(outf, "ERROR: tape list %s: parse error\n", tapefile); + quoted = quote_string(tapefile); + fprintf(outf, "ERROR: tape list %s: parse error\n", quoted); tapebad = 1; + amfree(quoted); } holdfile = vstralloc(config_dir, "/", "hold", NULL); if(access(holdfile, F_OK) != -1) { + quoted = quote_string(holdfile); fprintf(outf, "WARNING: hold file %s exists\n", holdfile); + amfree(quoted); } amfree(tapefile); amfree(tape_dir); @@ -703,48 +816,73 @@ int start_server_check(fd, do_localchk, do_tapechk) if(do_localchk) { for(hdp = holdingdisks; hdp != NULL; hdp = hdp->next) { - if(get_fs_stats(hdp->diskdir, &fs) == -1) { - fprintf(outf, "ERROR: holding dir %s: %s, you must create a directory.\n", - hdp->diskdir, strerror(errno)); + quoted = quote_string(holdingdisk_get_diskdir(hdp)); + if(get_fs_stats(holdingdisk_get_diskdir(hdp), &fs) == -1) { + fprintf(outf, "ERROR: holding dir %s (%s), " + "you must create a directory.\n", + quoted, strerror(errno)); disklow = 1; } - else if(access(hdp->diskdir, W_OK) == -1) { + else if(access(holdingdisk_get_diskdir(hdp), W_OK) == -1) { fprintf(outf, "ERROR: holding disk %s: not writable: %s.\n", - hdp->diskdir, strerror(errno)); + quoted, strerror(errno)); + disklow = 1; + } + else if(access(holdingdisk_get_diskdir(hdp), X_OK) == -1) { + fprintf(outf, "ERROR: holding disk %s: not searcheable: %s.\n", + quoted, strerror(errno)); disklow = 1; } - else if(fs.avail == -1) { + else if(fs.avail == (off_t)-1) { fprintf(outf, - "WARNING: holding disk %s: available space unknown (%ld KB requested)\n", - hdp->diskdir, (long)hdp->disksize); + "WARNING: holding disk %s: " + "available space unknown (" OFF_T_FMT" KB requested)\n", + quoted, (OFF_T_FMT_TYPE)holdingdisk_get_disksize(hdp)); disklow = 1; } - else if(hdp->disksize > 0) { - if(fs.avail < hdp->disksize) { + else if(holdingdisk_get_disksize(hdp) > (off_t)0) { + if(fs.avail < holdingdisk_get_disksize(hdp)) { fprintf(outf, - "WARNING: holding disk %s: only %ld %sB free (%ld %sB requested)\n", - hdp->diskdir, (long)fs.avail/unitdivisor, displayunit, - (long)hdp->disksize/unitdivisor, displayunit); + "WARNING: holding disk %s: " + "only " OFF_T_FMT " %sB free (" + OFF_T_FMT " %sB requested)\n", quoted, + (OFF_T_FMT_TYPE)(fs.avail / (off_t)unitdivisor), + displayunit, + (OFF_T_FMT_TYPE)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor), + displayunit); disklow = 1; } - else + else { fprintf(outf, - "Holding disk %s: %ld %sB disk space available, that's plenty\n", - hdp->diskdir, fs.avail/unitdivisor, displayunit); + "Holding disk %s: " OFF_T_FMT + " %sB disk space available, that's plenty\n", + quoted, (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor), + displayunit); + } } else { - if(fs.avail < -hdp->disksize) { + assert(holdingdisk_get_disksize(hdp) < (off_t)0); + if((fs.avail + holdingdisk_get_disksize(hdp)) <= (off_t)0) { fprintf(outf, - "WARNING: holding disk %s: only %ld %sB free, using nothing\n", - hdp->diskdir, fs.avail/unitdivisor, displayunit); + "WARNING: holding disk %s: " + "only " OFF_T_FMT " %sB free, using nothing\n", + quoted, (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor), + displayunit); disklow = 1; } - else + else { fprintf(outf, - "Holding disk %s: %ld %sB disk space available, using %ld %sB\n", - hdp->diskdir, fs.avail/unitdivisor, displayunit, - (fs.avail + hdp->disksize)/unitdivisor, displayunit); + "Holding disk %s: " + OFF_T_FMT " %sB disk space available, using " + OFF_T_FMT " %sB\n", + quoted, + (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor), + displayunit, + (OFF_T_FMT_TYPE)(fs.avail + holdingdisk_get_disksize(hdp) / (off_t)unitdivisor), + displayunit); + } } + amfree(quoted); } } @@ -765,36 +903,44 @@ int start_server_check(fd, do_localchk, do_tapechk) } logfile = vstralloc(conf_logdir, "/log", NULL); + quoted = quote_string(conf_logdir); if(stat(conf_logdir, &statbuf) == -1) { - fprintf(outf, "ERROR: logdir %s: %s, you must create a directory.\n", - conf_logdir, strerror(errno)); + fprintf(outf, "ERROR: logdir %s (%s), you must create directory.\n", + quoted, strerror(errno)); disklow = 1; } else if(access(conf_logdir, W_OK) == -1) { - fprintf(outf, "ERROR: log dir %s: not writable\n", conf_logdir); + fprintf(outf, "ERROR: log dir %s: not writable\n", quoted); logbad = 1; } + amfree(quoted); if(access(logfile, F_OK) == 0) { testtape = 0; logbad = 1; - if(access(logfile, W_OK) != 0) - fprintf(outf, "ERROR: log file %s: not writable\n", - logfile); + if(access(logfile, W_OK) != 0) { + quoted = quote_string(logfile); + fprintf(outf, "ERROR: log file %s: not writable\n", quoted); + amfree(quoted); + } } olddir = vstralloc(conf_logdir, "/oldlog", NULL); + quoted = quote_string(olddir); if (stat(olddir,&stat_old) == 0) { /* oldlog exist */ if(!(S_ISDIR(stat_old.st_mode))) { - fprintf(outf, "ERROR: oldlog directory \"%s\" is not a directory\n", olddir); + fprintf(outf, "ERROR: oldlog directory %s is not a directory\n", + quoted); } if(access(olddir, W_OK) == -1) { - fprintf(outf, "ERROR: oldlog dir %s: not writable\n", olddir); + fprintf(outf, "ERROR: oldlog dir %s: not writable\n", quoted); } } else if(lstat(olddir,&stat_old) == 0) { - fprintf(outf, "ERROR: oldlog directory \"%s\" is not a directory\n", olddir); + fprintf(outf, "ERROR: oldlog directory %s is not a directory\n", + quoted); } + amfree(quoted); if (testtape) { logfile = newvstralloc(logfile, conf_logdir, "/amdump", NULL); @@ -804,13 +950,13 @@ int start_server_check(fd, do_localchk, do_tapechk) } } + amfree(olddir); amfree(logfile); amfree(conf_logdir); } if (testtape) { /* check that the tape is a valid amanda tape */ - char *error_msg; int tape_status; tapedays = getconf_int(CNF_TAPECYCLE); @@ -822,20 +968,19 @@ int start_server_check(fd, do_localchk, do_tapechk) "WARNING: if a tape changer is not available, runtapes must be set to 1\n"); } - tape_status = taper_scan(NULL, &label, &datestamp, &error_msg, - &tapename); - fprintf(outf, "%s\n", error_msg); - amfree(error_msg); + tape_status = taper_scan(NULL, &label, &datestamp, &tapename, + FILE_taperscan_output_callback, outf); if (tape_status < 0) { tape_t *exptape = lookup_last_reusable_tape(0); fprintf(outf, " (expecting "); if(exptape != NULL) fprintf(outf, "tape %s or ", exptape->label); fprintf(outf, "a new tape)\n"); + tapebad = 1; } else { if (overwrite) { char *wrlabel_status; wrlabel_status = tape_wrlabel(tapename, "X", label, - tp->blocksize * 1024); + (unsigned)(tapetype_get_blocksize(tp) * 1024)); if (wrlabel_status != NULL) { if (tape_status == 3) { fprintf(outf, @@ -865,6 +1010,7 @@ int start_server_check(fd, do_localchk, do_tapechk) } } } + amfree(tapename); } else if (do_tapechk) { fprintf(outf, "WARNING: skipping tape test because amdump or amflush seem to be running\n"); fprintf(outf, "WARNING: if they are not, you must run amcleanup\n"); @@ -916,21 +1062,29 @@ int start_server_check(fd, do_localchk, do_tapechk) } #if TEXTDB + quoted = quote_string(conf_infofile); if(stat(conf_infofile, &statbuf) == -1) { - fprintf(outf, "NOTE: info dir %s: does not exist\n", conf_infofile); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + if (errno == ENOENT) { + fprintf(outf, "NOTE: conf info dir %s does not exist\n", + quoted); + fprintf(outf, "NOTE: it will be created on the next run.\n"); + } else { + fprintf(outf, "ERROR: conf info dir %s (%s)\n", + quoted, strerror(errno)); + } amfree(conf_infofile); } else if (!S_ISDIR(statbuf.st_mode)) { - fprintf(outf, "ERROR: info dir %s: not a directory\n", conf_infofile); + fprintf(outf, "ERROR: info dir %s: not a directory\n", quoted); amfree(conf_infofile); infobad = 1; } else if (access(conf_infofile, W_OK) == -1) { - fprintf(outf, "ERROR: info dir %s: not writable\n", conf_infofile); + fprintf(outf, "ERROR: info dir %s: not writable\n", quoted); amfree(conf_infofile); infobad = 1; } else { strappend(conf_infofile, "/"); } + amfree(quoted); #endif while(!empty(origq)) { @@ -939,135 +1093,191 @@ int start_server_check(fd, do_localchk, do_tapechk) #if TEXTDB if(conf_infofile) { hostinfodir = newstralloc2(hostinfodir, conf_infofile, host); + quoted = quote_string(hostinfodir); if(stat(hostinfodir, &statbuf) == -1) { - fprintf(outf, "NOTE: info dir %s: does not exist\n", - hostinfodir); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + if (errno == ENOENT) { + fprintf(outf, "NOTE: host info dir %s does not exist\n", + quoted); + fprintf(outf, + "NOTE: it will be created on the next run.\n"); + } else { + fprintf(outf, "ERROR: host info dir %s (%s)\n", + quoted, strerror(errno)); + } amfree(hostinfodir); } else if (!S_ISDIR(statbuf.st_mode)) { fprintf(outf, "ERROR: info dir %s: not a directory\n", - hostinfodir); + quoted); amfree(hostinfodir); infobad = 1; } else if (access(hostinfodir, W_OK) == -1) { - fprintf(outf, "ERROR: info dir %s: not writable\n", - hostinfodir); + fprintf(outf, "ERROR: info dir %s: not writable\n", quoted); amfree(hostinfodir); infobad = 1; } else { strappend(hostinfodir, "/"); } + amfree(quoted); } #endif for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { disk = sanitise_filename(dp->name); #if TEXTDB if(hostinfodir) { + char *quotedif; + diskdir = newstralloc2(diskdir, hostinfodir, disk); infofile = vstralloc(diskdir, "/", "info", NULL); + quoted = quote_string(diskdir); + quotedif = quote_string(infofile); if(stat(diskdir, &statbuf) == -1) { - fprintf(outf, "NOTE: info dir %s: does not exist\n", - diskdir); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + if (errno == ENOENT) { + fprintf(outf, "NOTE: info dir %s does not exist\n", + quoted); + fprintf(outf, + "NOTE: it will be created on the next run.\n"); + } else { + fprintf(outf, "ERROR: info dir %s (%s)\n", + quoted, strerror(errno)); + } } else if (!S_ISDIR(statbuf.st_mode)) { fprintf(outf, "ERROR: info dir %s: not a directory\n", - diskdir); + quoted); infobad = 1; } else if (access(diskdir, W_OK) == -1) { fprintf(outf, "ERROR: info dir %s: not writable\n", - diskdir); + quoted); infobad = 1; } else if(stat(infofile, &statbuf) == -1) { - fprintf(outf, "WARNING: info file %s: does not exist\n", - infofile); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + if (errno == ENOENT) { + fprintf(outf, "NOTE: info file %s does not exist\n", + quotedif); + fprintf(outf, "NOTE: it will be created on the next run.\n"); + } else { + fprintf(outf, "ERROR: info dir %s (%s)\n", + quoted, strerror(errno)); + } } else if (!S_ISREG(statbuf.st_mode)) { fprintf(outf, "ERROR: info file %s: not a file\n", - infofile); + quotedif); infobad = 1; } else if (access(infofile, R_OK) == -1) { fprintf(outf, "ERROR: info file %s: not readable\n", - infofile); + quotedif); infobad = 1; } + amfree(quotedif); + amfree(quoted); amfree(infofile); } #endif if(dp->index) { if(! indexdir_checked) { + quoted = quote_string(conf_indexdir); if(stat(conf_indexdir, &statbuf) == -1) { - fprintf(outf, "NOTE: index dir %s: does not exist\n", - conf_indexdir); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + if (errno == ENOENT) { + fprintf(outf, "NOTE: index dir %s does not exist\n", + quoted); + fprintf(outf, "NOTE: it will be created on the next run.\n"); + } else { + fprintf(outf, "ERROR: index dir %s (%s)\n", + quoted, strerror(errno)); + } amfree(conf_indexdir); } else if (!S_ISDIR(statbuf.st_mode)) { fprintf(outf, "ERROR: index dir %s: not a directory\n", - conf_indexdir); + quoted); amfree(conf_indexdir); indexbad = 1; } else if (access(conf_indexdir, W_OK) == -1) { fprintf(outf, "ERROR: index dir %s: not writable\n", - conf_indexdir); + quoted); amfree(conf_indexdir); indexbad = 1; } else { strappend(conf_indexdir, "/"); } indexdir_checked = 1; + amfree(quoted); } if(conf_indexdir) { if(! hostindexdir_checked) { hostindexdir = stralloc2(conf_indexdir, host); + quoted = quote_string(hostindexdir); if(stat(hostindexdir, &statbuf) == -1) { - fprintf(outf, "NOTE: index dir %s: does not exist\n", - hostindexdir); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + if (errno == ENOENT) { + fprintf(outf, "NOTE: index dir %s does not exist\n", + quoted); + fprintf(outf, "NOTE: it will be created on the next run.\n"); + } else { + fprintf(outf, "ERROR: index dir %s (%s)\n", + quoted, strerror(errno)); + } amfree(hostindexdir); } else if (!S_ISDIR(statbuf.st_mode)) { fprintf(outf, "ERROR: index dir %s: not a directory\n", - hostindexdir); + quoted); amfree(hostindexdir); indexbad = 1; } else if (access(hostindexdir, W_OK) == -1) { fprintf(outf, "ERROR: index dir %s: not writable\n", - hostindexdir); + quoted); amfree(hostindexdir); indexbad = 1; } else { strappend(hostindexdir, "/"); } hostindexdir_checked = 1; + amfree(quoted); } if(hostindexdir) { diskdir = newstralloc2(diskdir, hostindexdir, disk); + quoted = quote_string(diskdir); if(stat(diskdir, &statbuf) == -1) { - fprintf(outf, "NOTE: index dir %s: does not exist\n", - diskdir); - fprintf(outf, "NOTE: it will be created on the next run.\n"); + if (errno == ENOENT) { + fprintf(outf, "NOTE: index dir %s does not exist\n", + quoted); + fprintf(outf, "NOTE: it will be created on the next run.\n"); + } else { + fprintf(outf, "ERROR: index dir %s (%s)\n", + quoted, strerror(errno)); + } } else if (!S_ISDIR(statbuf.st_mode)) { fprintf(outf, "ERROR: index dir %s: not a directory\n", - diskdir); + quoted); indexbad = 1; } else if (access(diskdir, W_OK) == -1) { fprintf(outf, "ERROR: index dir %s: is not writable\n", - diskdir); + quoted); indexbad = 1; } + amfree(quoted); } } } - if ( dp->encrypt == ENCRYPT_SERV_CUST && dp->srv_encrypt ) { - if(access(dp->srv_encrypt, X_OK) == -1) { + if ( dp->encrypt == ENCRYPT_SERV_CUST ) { + if ( dp->srv_encrypt[0] == '\0' ) { + fprintf(outf, "ERROR: server encryption program not specified\n"); + pgmbad = 1; + } + else if(access(dp->srv_encrypt, X_OK) == -1) { fprintf(outf, "ERROR: %s is not executable, server encryption will not work\n", dp->srv_encrypt ); pgmbad = 1; } } - if ( dp->compress == COMP_SERV_CUST && dp->srvcompprog ) { - if(access(dp->srvcompprog, X_OK) == -1) { + if ( dp->compress == COMP_SERV_CUST ) { + if ( dp->srvcompprog[0] == '\0' ) { + fprintf(outf, "ERROR: server custom compression program not specified\n"); + pgmbad = 1; + } + else if(access(dp->srvcompprog, X_OK) == -1) { + quoted = quote_string(dp->srvcompprog); + fprintf(outf, "ERROR: %s is not executable, server custom compression will not work\n", - dp->srvcompprog ); + quoted); + amfree(quoted); pgmbad = 1; } } @@ -1108,7 +1318,7 @@ int start_server_check(fd, do_localchk, do_tapechk) || infobad \ || indexbad \ || pgmbad); - /* NOTREACHED */ + /*NOTREACHED*/ return 0; } @@ -1117,7 +1327,8 @@ int start_server_check(fd, do_localchk, do_tapechk) int remote_errors; FILE *outf; -static void handle_result P((void *, pkt_t *, security_handle_t *)); +static void handle_result(void *, pkt_t *, security_handle_t *); +void start_host(am_host_t *hostp); #define HOST_READY ((void *)0) /* must be 0 */ #define HOST_ACTIVE ((void *)1) @@ -1127,12 +1338,13 @@ static void handle_result P((void *, pkt_t *, security_handle_t *)); #define DISK_ACTIVE ((void *)1) #define DISK_DONE ((void *)2) -void start_host(hostp) - am_host_t *hostp; +void +start_host( + am_host_t *hostp) { disk_t *dp; char *req = NULL; - int req_len = 0; + size_t req_len = 0; int disk_count; const security_driver_t *secdrv; char number[NUM_STR_SIZE]; @@ -1162,6 +1374,8 @@ void start_host(hostp) fe_req_options_hostname); int has_maxdumps = am_has_feature(hostp->features, fe_req_options_maxdumps); + int has_config = am_has_feature(hostp->features, + fe_req_options_config); if(!am_has_feature(hostp->features, fe_selfcheck_req) && !am_has_feature(hostp->features, fe_selfcheck_req_device)) { @@ -1198,7 +1412,7 @@ void start_host(hostp) hostp->hostname); } - snprintf(number, sizeof(number), "%d", hostp->maxdumps); + snprintf(number, SIZEOF(number), "%d", hostp->maxdumps); req = vstralloc("SERVICE ", "selfcheck", "\n", "OPTIONS ", has_features ? "features=" : "", @@ -1210,6 +1424,9 @@ void start_host(hostp) has_hostname ? "hostname=" : "", has_hostname ? hostp->hostname : "", has_hostname ? ";" : "", + has_config ? "config=" : "", + has_config ? config_name : "", + has_config ? ";" : "", "\n", NULL); @@ -1218,30 +1435,46 @@ void start_host(hostp) req_len += 256; /* room for non-disk answers */ for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) { char *l; - int l_len; + size_t l_len; char *o; - char* calcsize; + char *calcsize; + char *qname; + char *qdevice; if(dp->up != DISK_READY || dp->todo != 1) { continue; } o = optionstr(dp, hostp->features, outf); + if (o == NULL) { + remote_errors++; + continue; + } + qname = quote_string(dp->name); + qdevice = quote_string(dp->device); + if ((dp->name && qname[0] == '"') || + (dp->device && qdevice[0] == '"')) { + if(!am_has_feature(hostp->features, fe_interface_quoted_text)) { + fprintf(outf, + "WARNING: %s:%s:%s host does not support quoted text\n", + hostp->hostname, qname, qdevice); + } + } if(dp->device) { if(!am_has_feature(hostp->features, fe_selfcheck_req_device)) { fprintf(outf, "ERROR: %s:%s (%s): selfcheck does not support device.\n", - hostp->hostname, dp->name, dp->device); + hostp->hostname, qname, dp->device); } if(!am_has_feature(hostp->features, fe_sendsize_req_device)) { fprintf(outf, "ERROR: %s:%s (%s): sendsize does not support device.\n", - hostp->hostname, dp->name, dp->device); + hostp->hostname, qname, dp->device); } if(!am_has_feature(hostp->features, fe_sendbackup_req_device)) { fprintf(outf, "ERROR: %s:%s (%s): sendbackup does not support device.\n", - hostp->hostname, dp->name, dp->device); + hostp->hostname, qname, dp->device); } } if(strncmp(dp->program,"DUMP",4) == 0 || @@ -1249,17 +1482,17 @@ void start_host(hostp) if(strcmp(dp->program, "DUMP") == 0 && !am_has_feature(hostp->features, fe_program_dump)) { fprintf(outf, "ERROR: %s:%s does not support DUMP.\n", - hostp->hostname, dp->name); + hostp->hostname, qname); } if(strcmp(dp->program, "GNUTAR") == 0 && !am_has_feature(hostp->features, fe_program_gnutar)) { fprintf(outf, "ERROR: %s:%s does not support GNUTAR.\n", - hostp->hostname, dp->name); + hostp->hostname, qname); } if(dp->estimate == ES_CALCSIZE && !am_has_feature(hostp->features, fe_calcsize_estimate)) { fprintf(outf, "ERROR: %s:%s does not support CALCSIZE for estimate, using CLIENT.\n", - hostp->hostname, dp->name); + hostp->hostname, qname); dp->estimate = ES_CLIENT; } if(dp->estimate == ES_CALCSIZE && @@ -1291,7 +1524,7 @@ void start_host(hostp) if(dp->device) { l = vstralloc(calcsize, dp->program, " ", - dp->name, " ", + qname, " ", dp->device, " 0 OPTIONS |", o, @@ -1301,7 +1534,7 @@ void start_host(hostp) else { l = vstralloc(calcsize, dp->program, " ", - dp->name, + qname, " 0 OPTIONS |", o, "\n", @@ -1310,12 +1543,12 @@ void start_host(hostp) } else { if(!am_has_feature(hostp->features, fe_program_dumper_api)) { fprintf(outf, "ERROR: %s:%s does not support DUMPER-API.\n", - hostp->hostname, dp->name); + hostp->hostname, qname); } l = vstralloc("DUMPER ", dp->program, " ", - dp->name, + qname, " ", dp->device, " 0 OPTIONS |", @@ -1323,15 +1556,11 @@ void start_host(hostp) "\n", NULL); } + amfree(qname); + amfree(qdevice); l_len = strlen(l); amfree(o); - /* - * Allow 2X for err response. - */ - if(req_len + l_len > MAX_PACKET / 2) { - amfree(l); - break; - } + strappend(req, l); req_len += l_len; amfree(l); @@ -1363,8 +1592,9 @@ void start_host(hostp) if (secdrv == NULL) { error("could not find security driver '%s' for host '%s'", hostp->disks->security_driver, hostp->hostname); + /*NOTREACHED*/ } - protocol_sendreq(hostp->hostname, secdrv, generic_get_security_conf, + protocol_sendreq(hostp->hostname, secdrv, amhost_get_security_conf, req, conf_ctimeout, handle_result, hostp); amfree(req); @@ -1372,17 +1602,24 @@ void start_host(hostp) hostp->up = HOST_ACTIVE; } -int start_client_checks(fd) -int fd; +pid_t +start_client_checks( + int fd) { am_host_t *hostp; disk_t *dp; - int hostcount, pid; + int hostcount; + pid_t pid; int userbad = 0; switch(pid = fork()) { - case -1: error("could not fork client check: %s", strerror(errno)); - case 0: break; + case -1: + error("could not fork client check: %s", strerror(errno)); + /*NOTREACHED*/ + + case 0: + break; + default: return pid; } @@ -1394,8 +1631,10 @@ int fd; startclock(); - if((outf = fdopen(fd, "w")) == NULL) + if((outf = fdopen(fd, "w")) == NULL) { error("fdopen %d: %s", fd, strerror(errno)); + /*NOTREACHED*/ + } errf = outf; fprintf(outf, "\nAmanda Backup Client Hosts Check\n"); @@ -1407,7 +1646,7 @@ int fd; for(dp = origq.head; dp != NULL; dp = dp->next) { hostp = dp->host; - if(hostp->up == HOST_READY) { + if(hostp->up == HOST_READY && dp->todo == 1) { start_host(hostp); hostcount++; protocol_check(); @@ -1433,14 +1672,15 @@ int fd; } exit(userbad || remote_errors > 0); - /* NOTREACHED */ + /*NOTREACHED*/ return 0; } -static void handle_result(datap, pkt, sech) -void *datap; -pkt_t *pkt; -security_handle_t *sech; +static void +handle_result( + void * datap, + pkt_t * pkt, + security_handle_t * sech) { am_host_t *hostp; disk_t *dp; @@ -1471,19 +1711,19 @@ security_handle_t *sech; ch = *s++; while(ch) { line = s - 1; - skip_line(s, ch); + skip_quoted_line(s, ch); if (s[-2] == '\n') { s[-2] = '\0'; } #define sc "OPTIONS " - if(strncmp(line, sc, sizeof(sc)-1) == 0) { + if(strncmp(line, sc, SIZEOF(sc)-1) == 0) { #undef sc #define sc "features=" t = strstr(line, sc); if(t != NULL && (isspace((int)t[-1]) || t[-1] == ';')) { - t += sizeof(sc)-1; + t += SIZEOF(sc)-1; #undef sc am_release_feature_set(hostp->features); if((hostp->features = am_string_to_feature(t)) == NULL) { @@ -1496,14 +1736,14 @@ security_handle_t *sech; } #define sc "OK " - if(strncmp(line, sc, sizeof(sc)-1) == 0) { + if(strncmp(line, sc, SIZEOF(sc)-1) == 0) { continue; #undef sc } #define sc "ERROR " - if(strncmp(line, sc, sizeof(sc)-1) == 0) { - t = line + sizeof(sc) - 1; + if(strncmp(line, sc, SIZEOF(sc)-1) == 0) { + t = line + SIZEOF(sc) - 1; tch = t[-1]; #undef sc @@ -1513,11 +1753,9 @@ security_handle_t *sech; * just means the client is "old" (does not support the service). * We can ignore this. */ - if(hostp->features == NULL - && pkt->type == P_NAK - && (strcmp(t - 1, "unknown service: noop") == 0 - || strcmp(t - 1, "noop: invalid service") == 0)) { - } else { + if(!((hostp->features == NULL) && (pkt->type == P_NAK) + && ((strcmp(t - 1, "unknown service: noop") == 0) + || (strcmp(t - 1, "noop: invalid service") == 0)))) { fprintf(outf, "ERROR: %s%s: %s\n", (pkt->type == P_NAK) ? "NAK " : "", hostp->hostname, @@ -1548,4 +1786,6 @@ security_handle_t *sech; } } start_host(hostp); + if(hostp->up == HOST_DONE) + security_close_connection(sech, hostp->hostname); }