// analyse.c: #define VERBOSE // This program reads the consolidated survey results file // and generates a summary of the multiple-choice questions. // It does not do anything with the descriptive text answers // which will need to be read by a human. #include #include #include #include #include #ifndef TRUE #define TRUE (0==0) #define FALSE (0!=0) #endif int choice[200 /* think there's 49 unique, 170-ish altogether */][10]; char *schema[] = { "Q00000000", "Submitter's IP", "Q000002E7", "Submitter's name", "Q00000341", "Submitter's job title", "Q0000039B", "Submitter's email", "Q00000568?", "Declaration of data ownership", "Q00000568/0", "I have NO access to or control over sensitive information", "Q00000568/1", "I do have access to or control over sensitive information", "Q00000568/2", "I don't know if I have access to sensitive data", "Q0000068D", "Final comments", "Q000009A3", "System name or description", "Q00000805", "Appropriate person", "Q00000780?", "Early form termination", "Q00000780/0", "My only access is via IA_SI_...", "Q00000780/1", "I defer to ...", "Q00000780/2", "I will complete the rest of the form", "Q00000CEC", "Name of responsible person", "Q00000D4B", "Job title of responsible person", "Q00000DA5", "Email address of responsible person", "Q00000A97", "Owning department", "Q00000E9A", "IP addresses", "Q00000F07", "System location", "Q0000107E", "Nature of sensitive data", "Q000010DD?", "Also on paper?", "Q000010DD/0", "Yes", "Q000010DD/1", "No", "Q00001159", "Disposition of paper?", "Q000011E8", "Comments on non-electronic issues", "Q00001255?", "Instructions from auditor", "Q00001255/0", "Yes", "Q00001255/1", "No", "Q00001255/2", "Don't know", "Q00001255/3", "Not applicable", "Q00001382", "Auditors instructions", "Q000012E7?", "Auditor happy?", "Q000012E7/0", "Yes", "Q000012E7/1", "No", "Q000012E7/2", "Don't know", "Q000012E7/3", "Not applicable", "Q00001485?", "Authentication needed?", "Q00001485/0", "Yes", "Q00001485/1", "No", "Q00001485/2", "Don't know", "Q00001485/3", "Not applicable", "Q00001427", "What is the authentication?", "Q00001548", "Source of passwords?", "Q000015C9?", "Type of people with access", "Q000015C9/0", "Selected staff only", "Q000015C9/1", "Full-time employees only", "Q000015C9/2", "Faculty only", "Q000015C9/3", "Part time employees or work studies", "Q000015C9/4", "Students", "Q000015C9/5", "Other (see next)", "Q000016C0", "Who has access:", "Q0000173F?", "Host behind firewall?", "Q0000173F/0", "Yes", "Q0000173F/1", "No", "Q0000173F/2", "Don't know", "Q0000173F/3", "Not applicable", "Q000017FE?", "Software firewall?", "Q000017FE/1", "Yes", "Q000017FE/2", "No", "Q000017FE/3", "Don't know", "Q000017FE/4", "Not applicable", "Q000018A2?", "So would a firewall help?", "Q000018A2/0", "Yes", "Q000018A2/1", "No", "Q000018A2/2", "Don't know", "Q000018A2/3", "Not applicable", "Q000019F7?", "Other intrusion measures?", "Q000019F7/1", "Yes", "Q000019F7/2", "No", "Q000019F7/3", "Don't know", "Q000019F7/4", "Not applicable", "Q00001A97", "What other intrusion measures?", "Q00001AFD?", "Keep logs?", "Q00001AFD/0", "Yes", "Q00001AFD/1", "No", "Q00001AFD/2", "Don't know", "Q00001AFD/3", "Not applicable", "Q00001C1F?", "Recently patched?", "Q00001C1F/1", "Yes", "Q00001C1F/2", "No", "Q00001C1F/3", "Don't know", "Q00001C1F/4", "Not applicable", "Q00001CBD?", "Auto updates?", "Q00001CBD/1", "Yes", "Q00001CBD/2", "No", "Q00001CBD/3", "Don't know", "Q00001CBD/4", "Not applicable", "Q00001D60?", "Last MBSA run?", "Q00001D60/0", "Not applicable", "Q00001D60/1", "Don't know when", "Q00001D60/2", "Don't know what MBSA is", "Q00001D60/3", "Last few days", "Q00001D60/4", "Last few weeks", "Q00001D60/5", "Last few months", "Q00001D60/6", "Long long time", "Q00001E54?", "Subscribe to bugfix mailing lists?", "Q00001E54/0", "Yes", "Q00001E54/1", "No", "Q00001E54/2", "Don't know", "Q00001E54/3", "Not applicable", "Q00001EEE", "Mailing list names", "Q00001F67?", "Someone sends bugfix info by mail?", "Q00001F67/0", "Yes, reliable!", "Q00001F67/1", "Yes, not dependable", "Q00001F67/2", "No", "Q00001F67/3", "Not applicable", "Q00001F67/4", "Don't know", "Q00002045?", "Last backup", "Q00002045/0", "Not applicable", "Q00002045/1", "Someone else does it for me", "Q00002045/2", "Today", "Q00002045/3", "Done in this last week", "Q00002045/4", "Done in this last month", "Q00002045/5", "Never backed up!", "Q0000212F?", "Where are backups stored?", "Q0000212F/0", "Not applicable", "Q0000212F/1", "CC does them", "Q0000212F/2", "ASB does them", "Q0000212F/3", "stored near computer", "Q0000212F/4", "on campus, not near computer", "Q0000212F/5", "off campus", "Q0000220E?", "A/V installed?", "Q0000220E/0", "Not applicable", "Q0000220E/1", "Don't know", "Q0000220E/2", "No", "Q0000220E/3", "McAffee", "Q0000220E/4", "Norton", "Q0000220E/5", "other", "Q00002336?", "Last A/V update?", "Q00002336/0", "Not applicable", "Q00002336/1", "Don't know", "Q00002336/2", "Done automatically", "Q00002336/3", "Today", "Q00002336/4", "Within the last week", "Q00002336/5", "Within the last month", "Q00002336/6", "Too long ago!", "Q00002480?", "Trojan scanner?", "Q00002480/0", "Yes", "Q00002480/1", "No", "Q00002480/2", "Don't know", "Q00002480/3", "Not applicable", "Q0000252E?", "Spyware checker?", "Q0000252E/0", "Yes", "Q0000252E/1", "No", "Q0000252E/2", "Don't know", "Q0000252E/3", "Not applicable", "Q00002664?", "training needed?", "Q00002664/0", "Yes", "Q00002664/1", "No", "Q00002664/2", "Don't know", "Q00002664/3", "Not applicable", "Q00002705?", "Warning banners displayed?", "Q00002705/0", "Yes", "Q00002705/1", "No", "Q00002705/2", "Don't know", "Q00002705/3", "Not applicable", "Q000027A8?", "Sensitive portable information systems?", "Q000027A8/0", "Yes", "Q000027A8/1", "No", "Q000027A8/2", "Don't know", "Q000027A8/3", "Not applicable", "Q00002851", "What is on portables?", "Q000028B8", "Other comments", }; int handle_line(char *line) // returns line index into schema { int lineno; lineno = 0; for (;;) { // fprintf(stderr, "Comparing 9 chars of '%s' and '%s'\n", schema[lineno*2], line); if (strncmp(schema[lineno*2], line, 9) == 0) break; assert(lineno != 199); lineno += 1; } if (schema[lineno*2][9] == '?') { // multiple choice question int ch, ans; char *response = strchr(line, '"'); assert(response != NULL); response += 1; ch = *response; if (ch == '"') { fprintf(stderr, "No answer given! %s\n", line); ans = 9; } else { if (!isdigit(ch)) { fprintf(stderr, "schema: q=\"%s\" a=\"%s\"\n", schema[lineno*2], schema[lineno*2+1]); fprintf(stderr, "digit expected: %s\n", line); exit(1); } ans = ch-'0'; } choice[lineno][ans] += 1; } // if (lineno == 3) fprintf(stdout, "%s: %s\n", schema[lineno*2+1], line); } int handled_one_form(FILE *f) { #define HUGELINE (1024*10) int schema_line; static char line[HUGELINE], *s; line[HUGELINE-1] = '\0'; s = fgets(line, HUGELINE-1, f); if (s == NULL) return (FALSE); s = strchr(line, '\n'); if (s != NULL) *s = '\0'; if (*line != '#') { fprintf(stderr, "Start of record not found! - %s\n", line); exit(1); } for (;;) { line[HUGELINE-1] = '\0'; s = fgets(line, HUGELINE-1, f); if (s == NULL) return (FALSE); s = strchr(line, '\n'); if (s != NULL) *s = '\0'; schema_line = handle_line(line); if (strncmp(line, "Q000028B8", 9) == 0) return (TRUE); // hard coded last item if (strncmp(line, "Q0000068D", 9) == 0) return (TRUE); // hard coded last item if (*line == '#') { fprintf(stderr, "Q000028B8 or Q0000068D not found! - %s\n", line); exit(1); } } // false on end of file. else true. } int main(int argc, char **argv) { int i, q, c; FILE *done = fopen("done.txt", "r"); if (done == NULL) { fprintf(stderr, "analyse: %s\n", strerror(errno)); exit(1); } // initialisation a little hacky but safe for this particular survey for (q = 0; q < 200; q++) { for (c = 0; c < 10; c++) { choice[q][c] = 0; } } // printf("Analyzing...\n"); for (;;) { if (!handled_one_form(done)) break; } // summarize multiple choice answers no. // remember that '9' means no answer given. // printf("Summarizing...\n"); for (q = 0; q < 200; q++) { i = 0; for (c = 0; c < 10; c++) { i += choice[q][c]; } if (i != 0) { // cheap test to determine if answers present #ifdef VERBOSE printf("%s:\n", schema[q*2+1]); #else printf("%s: ", schema[q*2+1]); #endif for (c = 0; c < 9; c++) { if (strncmp(schema[q*2], schema[(q+c+1)*2], 9) != 0) break; #ifdef VERBOSE printf(" %d answered %s\n", choice[q][c], schema[(q+c+1)*2+1]); #else if (strlen(schema[(q+c+1)*2+1]) > 20) printf("\n "); printf(" %s: %d ", schema[(q+c+1)*2+1], choice[q][c]); #endif } if ((i = choice[q][9]) != 0) printf(" %d did not select any answer\n", i); #ifndef VERBOSE printf("\n"); #endif } } }