bool lookfor(char *tag,FILE *fp) { char tagname[256]; for(;;) { if (!nexttag(tagname,fp)) return false; if (strcmp(tag,tagname)==0) return true; skipinfo(fp,0); } /* forever */ return false; } /* lookfor */
int lookfor2(char *tag,char *tag2,FILE *fp) { char tagname[256]; for(;;) { if (!nexttag(tagname,fp)) return 0; if (strcmp(tag,tagname)==0) return 1; if (strcmp(tag2,tagname)==0) return 2; skipinfo(fp,0); } /* forever */ return 0; } /* lookfor2 */
/* * Main command processor. * Accept and execute commands until a quit command. */ void commands(void) { int c = 0; int action; char *cbuf; int newaction; int save_search_type; char *extra; char tbuf[2]; PARG parg; IFILE old_ifile; IFILE new_ifile; char *tagfile; search_type = SRCH_FORW; wscroll = (sc_height + 1) / 2; newaction = A_NOACTION; for (;;) { mca = 0; cmd_accept(); number = 0; curropt = NULL; /* * See if any signals need processing. */ if (sigs) { psignals(); if (quitting) quit(QUIT_SAVED_STATUS); } /* * Display prompt and accept a character. */ cmd_reset(); prompt(); if (sigs) continue; if (newaction == A_NOACTION) c = getcc(); again: if (sigs) continue; if (newaction != A_NOACTION) { action = newaction; newaction = A_NOACTION; } else { /* * If we are in a multicharacter command, call mca_char. * Otherwise we call fcmd_decode to determine the * action to be performed. */ if (mca) switch (mca_char(c)) { case MCA_MORE: /* * Need another character. */ c = getcc(); goto again; case MCA_DONE: /* * Command has been handled by mca_char. * Start clean with a prompt. */ continue; case NO_MCA: /* * Not a multi-char command * (at least, not anymore). */ break; } /* * Decode the command character and decide what to do. */ if (mca) { /* * We're in a multichar command. * Add the character to the command buffer * and display it on the screen. * If the user backspaces past the start * of the line, abort the command. */ if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) continue; cbuf = get_cmdbuf(); } else { /* * Don't use cmd_char if we're starting fresh * at the beginning of a command, because we * don't want to echo the command until we know * it is a multichar command. We also don't * want erase_char/kill_char to be treated * as line editing characters. */ tbuf[0] = (char)c; tbuf[1] = '\0'; cbuf = tbuf; } extra = NULL; action = fcmd_decode(cbuf, &extra); /* * If an "extra" string was returned, * process it as a string of command characters. */ if (extra != NULL) ungetsc(extra); } /* * Clear the cmdbuf string. * (But not if we're in the prefix of a command, * because the partial command string is kept there.) */ if (action != A_PREFIX) cmd_reset(); switch (action) { case A_DIGIT: /* * First digit of a number. */ start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE); goto again; case A_F_WINDOW: /* * Forward one window (and set the window size). */ if (number > 0) swindow = (int)number; /* FALLTHRU */ case A_F_SCREEN: /* * Forward one screen. */ if (number <= 0) number = get_swindow(); cmd_exec(); if (show_attn) set_attnpos(bottompos); forward((int)number, 0, 1); break; case A_B_WINDOW: /* * Backward one window (and set the window size). */ if (number > 0) swindow = (int)number; /* FALLTHRU */ case A_B_SCREEN: /* * Backward one screen. */ if (number <= 0) number = get_swindow(); cmd_exec(); backward((int)number, 0, 1); break; case A_F_LINE: /* * Forward N (default 1) line. */ if (number <= 0) number = 1; cmd_exec(); if (show_attn == OPT_ONPLUS && number > 1) set_attnpos(bottompos); forward((int)number, 0, 0); break; case A_B_LINE: /* * Backward N (default 1) line. */ if (number <= 0) number = 1; cmd_exec(); backward((int)number, 0, 0); break; case A_F_SKIP: /* * Skip ahead one screen, and then number lines. */ if (number <= 0) { number = get_swindow(); } else { number += get_swindow(); } cmd_exec(); if (show_attn == OPT_ONPLUS) set_attnpos(bottompos); forward((int)number, 0, 1); break; case A_FF_LINE: /* * Force forward N (default 1) line. */ if (number <= 0) number = 1; cmd_exec(); if (show_attn == OPT_ONPLUS && number > 1) set_attnpos(bottompos); forward((int)number, 1, 0); break; case A_BF_LINE: /* * Force backward N (default 1) line. */ if (number <= 0) number = 1; cmd_exec(); backward((int)number, 1, 0); break; case A_FF_SCREEN: /* * Force forward one screen. */ if (number <= 0) number = get_swindow(); cmd_exec(); if (show_attn == OPT_ONPLUS) set_attnpos(bottompos); forward((int)number, 1, 0); break; case A_F_FOREVER: /* * Forward forever, ignoring EOF. */ newaction = forw_loop(0); break; case A_F_UNTIL_HILITE: newaction = forw_loop(1); break; case A_F_SCROLL: /* * Forward N lines * (default same as last 'd' or 'u' command). */ if (number > 0) wscroll = (int)number; cmd_exec(); if (show_attn == OPT_ONPLUS) set_attnpos(bottompos); forward(wscroll, 0, 0); break; case A_B_SCROLL: /* * Forward N lines * (default same as last 'd' or 'u' command). */ if (number > 0) wscroll = (int)number; cmd_exec(); backward(wscroll, 0, 0); break; case A_FREPAINT: /* * Flush buffers, then repaint screen. * Don't flush the buffers on a pipe! */ clear_buffers(); /* FALLTHRU */ case A_REPAINT: /* * Repaint screen. */ cmd_exec(); repaint(); break; case A_GOLINE: /* * Go to line N, default beginning of file. */ if (number <= 0) number = 1; cmd_exec(); jump_back(number); break; case A_PERCENT: /* * Go to a specified percentage into the file. */ if (number < 0) { number = 0; fraction = 0; } if (number > 100) { number = 100; fraction = 0; } cmd_exec(); jump_percent((int)number, fraction); break; case A_GOEND: /* * Go to line N, default end of file. */ cmd_exec(); if (number <= 0) jump_forw(); else jump_back(number); break; case A_GOPOS: /* * Go to a specified byte position in the file. */ cmd_exec(); if (number < 0) number = 0; jump_line_loc((off_t) number, jump_sline); break; case A_STAT: /* * Print file name, etc. */ if (ch_getflags() & CH_HELPFILE) break; cmd_exec(); parg.p_string = eq_message(); error("%s", &parg); break; case A_VERSION: /* * Print version number, without the "@(#)". */ cmd_exec(); dispversion(); break; case A_QUIT: /* * Exit. */ if (curr_ifile != NULL_IFILE && ch_getflags() & CH_HELPFILE) { /* * Quit while viewing the help file * just means return to viewing the * previous file. */ hshift = save_hshift; if (edit_prev(1) == 0) break; } if (extra != NULL) quit(*extra); quit(QUIT_OK); break; /* * Define abbreviation for a commonly used sequence below. */ #define DO_SEARCH() \ if (number <= 0) number = 1; \ mca_search(); \ cmd_exec(); \ multi_search(NULL, (int)number); case A_F_SEARCH: /* * Search forward for a pattern. * Get the first char of the pattern. */ search_type = SRCH_FORW; if (number <= 0) number = 1; mca_search(); c = getcc(); goto again; case A_B_SEARCH: /* * Search backward for a pattern. * Get the first char of the pattern. */ search_type = SRCH_BACK; if (number <= 0) number = 1; mca_search(); c = getcc(); goto again; case A_FILTER: search_type = SRCH_FORW | SRCH_FILTER; mca_search(); c = getcc(); goto again; case A_AGAIN_SEARCH: /* * Repeat previous search. */ DO_SEARCH(); break; case A_T_AGAIN_SEARCH: /* * Repeat previous search, multiple files. */ search_type |= SRCH_PAST_EOF; DO_SEARCH(); break; case A_REVERSE_SEARCH: /* * Repeat previous search, in reverse direction. */ save_search_type = search_type; search_type = SRCH_REVERSE(search_type); DO_SEARCH(); search_type = save_search_type; break; case A_T_REVERSE_SEARCH: /* * Repeat previous search, * multiple files in reverse direction. */ save_search_type = search_type; search_type = SRCH_REVERSE(search_type); search_type |= SRCH_PAST_EOF; DO_SEARCH(); search_type = save_search_type; break; case A_UNDO_SEARCH: undo_search(); break; case A_HELP: /* * Help. */ if (ch_getflags() & CH_HELPFILE) break; if (ungot != NULL || unget_end) { error(less_is_more ? "Invalid option -p h" : "Invalid option ++h", NULL_PARG); break; } cmd_exec(); save_hshift = hshift; hshift = 0; (void) edit(FAKE_HELPFILE); break; case A_EXAMINE: /* * Edit a new file. Get the filename. */ if (secure) { error("Command not available", NULL_PARG); break; } start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); c = getcc(); goto again; case A_VISUAL: /* * Invoke an editor on the input file. */ if (secure) { error("Command not available", NULL_PARG); break; } if (ch_getflags() & CH_HELPFILE) break; if (strcmp(get_filename(curr_ifile), "-") == 0) { error("Cannot edit standard input", NULL_PARG); break; } if (curr_altfilename != NULL) { error("WARNING: This file was viewed via " "LESSOPEN", NULL_PARG); } start_mca(A_SHELL, "!", ml_shell, 0); /* * Expand the editor prototype string * and pass it to the system to execute. * (Make sure the screen is displayed so the * expansion of "+%lm" works.) */ make_display(); cmd_exec(); lsystem(pr_expand(editproto, 0), NULL); break; case A_NEXT_FILE: /* * Examine next file. */ if (ntags()) { error("No next file", NULL_PARG); break; } if (number <= 0) number = 1; if (edit_next((int)number)) { if (get_quit_at_eof() && eof_displayed() && !(ch_getflags() & CH_HELPFILE)) quit(QUIT_OK); parg.p_string = (number > 1) ? "(N-th) " : ""; error("No %snext file", &parg); } break; case A_PREV_FILE: /* * Examine previous file. */ if (ntags()) { error("No previous file", NULL_PARG); break; } if (number <= 0) number = 1; if (edit_prev((int)number)) { parg.p_string = (number > 1) ? "(N-th) " : ""; error("No %sprevious file", &parg); } break; case A_NEXT_TAG: if (number <= 0) number = 1; tagfile = nexttag((int)number); if (tagfile == NULL) { error("No next tag", NULL_PARG); break; } if (edit(tagfile) == 0) { off_t pos = tagsearch(); if (pos != -1) jump_loc(pos, jump_sline); } break; case A_PREV_TAG: if (number <= 0) number = 1; tagfile = prevtag((int)number); if (tagfile == NULL) { error("No previous tag", NULL_PARG); break; } if (edit(tagfile) == 0) { off_t pos = tagsearch(); if (pos != -1) jump_loc(pos, jump_sline); } break; case A_INDEX_FILE: /* * Examine a particular file. */ if (number <= 0) number = 1; if (edit_index((int)number)) error("No such file", NULL_PARG); break; case A_REMOVE_FILE: if (ch_getflags() & CH_HELPFILE) break; old_ifile = curr_ifile; new_ifile = getoff_ifile(curr_ifile); if (new_ifile == NULL_IFILE) { ring_bell(); break; } if (edit_ifile(new_ifile) != 0) { reedit_ifile(old_ifile); break; } del_ifile(old_ifile); break; case A_OPT_TOGGLE: optflag = OPT_TOGGLE; optgetname = FALSE; mca_opt_toggle(); c = getcc(); goto again; case A_DISP_OPTION: /* * Report a flag setting. */ optflag = OPT_NO_TOGGLE; optgetname = FALSE; mca_opt_toggle(); c = getcc(); goto again; case A_FIRSTCMD: /* * Set an initial command for new files. */ start_mca(A_FIRSTCMD, "+", NULL, 0); c = getcc(); goto again; case A_SHELL: /* * Shell escape. */ if (secure) { error("Command not available", NULL_PARG); break; } start_mca(A_SHELL, "!", ml_shell, 0); c = getcc(); goto again; case A_SETMARK: /* * Set a mark. */ if (ch_getflags() & CH_HELPFILE) break; start_mca(A_SETMARK, "mark: ", (void*)NULL, 0); c = getcc(); if (c == erase_char || c == erase2_char || c == kill_char || c == '\n' || c == '\r') break; setmark(c); break; case A_GOMARK: /* * Go to a mark. */ start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); c = getcc(); if (c == erase_char || c == erase2_char || c == kill_char || c == '\n' || c == '\r') break; cmd_exec(); gomark(c); break; case A_PIPE: if (secure) { error("Command not available", NULL_PARG); break; } start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); c = getcc(); if (c == erase_char || c == erase2_char || c == kill_char) break; if (c == '\n' || c == '\r') c = '.'; if (badmark(c)) break; pipec = c; start_mca(A_PIPE, "!", ml_shell, 0); c = getcc(); goto again; case A_B_BRACKET: case A_F_BRACKET: start_mca(action, "Brackets: ", (void*)NULL, 0); c = getcc(); goto again; case A_LSHIFT: if (number > 0) shift_count = number; else number = (shift_count > 0) ? shift_count : sc_width / 2; if (number > hshift) number = hshift; hshift -= number; screen_trashed = 1; break; case A_RSHIFT: if (number > 0) shift_count = number; else number = (shift_count > 0) ? shift_count : sc_width / 2; hshift += number; screen_trashed = 1; break; case A_PREFIX: /* * The command is incomplete (more chars are needed). * Display the current char, so the user knows * what's going on, and get another character. */ if (mca != A_PREFIX) { cmd_reset(); start_mca(A_PREFIX, " ", (void*)NULL, CF_QUIT_ON_ERASE); (void) cmd_char(c); } c = getcc(); goto again; case A_NOACTION: break; default: ring_bell(); break; } } }
int main(int argc, char *argv[]) { char logfile[BUFFSIZE], filesdir[BUFFSIZE], collectcmd[BUFFSIZE], lscmd[BUFFSIZE], datfile[BUFFSIZE], imgfile[BUFFSIZE]; FILE *master, *page; FILE *sysout; char pageline[BUFFSIZE], buff[BUFFSIZE], scmd[BUFFSIZE], pagefile[BUFFSIZE]; char pageurl[BUFFSIZE], fullurl[BUFFSIZE], *url; char urldone; pid_t wgetchild; time_t waitstart; char *data; unsigned masterlength, masterloc; unsigned pageadds; long tester; int p; int firstentry; if (argc != 3 && argc != 4) { printf("Usage: web-collage <file> <program>\n"); exit(-2); } /* Fill out the commands with name */ sprintf(logfile, LOG_FILE, argv[1]); sprintf(filesdir, FILES_DIR, argv[1]); sprintf(collectcmd, COLLECT_CMD, argv[1], argv[1]); sprintf(lscmd, LS_CMD, argv[1]); sprintf(datfile, DAT_FILE, argv[1]); sprintf(imgfile, IMG_FILE, argv[1]); /* does the temp directory already exist? */ mkdir(filesdir, S_IRWXU); /* Open File */ if (!(master = fopen(datfile, "r"))) { printf("Creating File...\n"); master = fopen(datfile, "w+"); if (!master) { perror("creating master file"); exit(-1); } fprintf(master, "%s\n", argv[3]); /* First URL */ fclose(master); } else fclose(master); printf("Reading File...\n"); srand48(time(NULL)); master = waitreadmaster(datfile, 0, 0, 0); /* READ Lock! */ fseek(master, 0, SEEK_END); masterlength = ftell(master); freemaster(datfile, master, 0, 0); /* Unlock! */ int iter = 0; while (iter++ < 3) { /* Get random URL */ masterloc = lrand48() % masterlength; firstentry = 0; /* READ Lock! */ master = waitreadmaster(datfile, masterloc, masterloc, BUFFSIZE); fgets(pageurl, BUFFSIZE, master); /* skip to line after random char */ do if (!fgets(pageurl, BUFFSIZE - strlen(collectcmd) - 1, master)) { rewind(master); firstentry = 1; fgets(pageurl, BUFFSIZE - strlen(collectcmd) - 1, master); } while (pageurl[0] == '\t' || pageurl[0] == '\n'); if (!firstentry) { /* Invalidate URL */ /* READ->WRITE Lock! */ master = waitreadtowrite(datfile, master, masterloc, BUFFSIZE); fseek(master, -(strlen(pageurl) + 0), SEEK_CUR); voidline(master); } freemaster(datfile, master, masterloc, BUFFSIZE); /* Unlock! */ pageurl[strlen(pageurl) - 1] = '\0'; printf("\nGetting %s\n", pageurl); /* Get webpage, checking for any redirection */ sprintf(scmd, "%s \"%s\"", collectcmd, pageurl); waitstart = time(NULL); if (!(wgetchild = fork())) { system(scmd); exit(0); } while (validpid(wgetchild) && waitstart + 5 > time(NULL)); if (validpid(wgetchild)) kill(wgetchild, 9); wait(NULL); sysout = fopen(logfile, "r"); if (!sysout) continue; /* File does not exist */ while (fgets(buff, BUFFSIZE, sysout)) { printf("%s", buff); if (!strncmp(buff, "Location:", 9)) { if (strchr(buff + 10, ' ')) *strchr(buff + 10, ' ') = '\0'; strcpy(pageurl, buff + 10); } } fclose(sysout); unlink(logfile); /* Collect new links */ sysout = popen(lscmd, "r"); if (!sysout) { perror("searching files directory"); exit(-3); } strcpy(pagefile, filesdir); if (fgets(pagefile + strlen(pagefile), BUFFSIZE, sysout) != NULL) { pagefile[strlen(pagefile) - 1] = '\0'; /* remove newline */ page = fopen(pagefile, "r"); addfilename(pageurl, BUFFSIZE, pagefile); pageadds = 0; /* Write Additional URLs */ rewind(master); if (findlikes(page) || (rand() % KEEP_PROB)) { /* possibly just throw away */ while (nexttag(pageline, BUFFSIZE, page)) if (url = geturl(pageline)) { if (strncasecmp(url, "http://", 7)) { if (!getpath(fullurl, BUFFSIZE, url, pageurl)) continue; } else strcpy(fullurl, url); /* search for place in file to place */ urldone = 0; if (strlen(fullurl) > BUFFSIZE / 2) continue; /* too big, don't add */ if (rand() % (pageadds + 1) > KEEP_PROB) continue; /* add fewer urls as more on page */ if (strstr(fullurl, ".com") && rand() % DROP_PROB) continue; /* only chance to add a .com link */ if ((strstr(fullurl, "yahoo.com") || strstr(fullurl, "www.google.com")) && rand() % DROP_PROB) continue; /* almost no yahoo.com's, www.google.com's */ for (p = 0; p < DISLIKE_CNT; p++) if (strstr(fullurl, dislikes[p])) /* just skip */ continue; /* READ Lock! */ master = waitreadmaster(datfile, 0, 0, 0); while (fgets(buff, BUFFSIZE, master)) { if (!strncmp(buff, fullurl, strlen(fullurl)) || (!strncmp(buff, fullurl, strchr(buff + strlen("http://"), '/') - buff) && !(rand() % HOST_CROWD))) { urldone = 1; freemaster(datfile, master, 0, 0); /* Unlock! */ break; } if (buff[0] == '\t' || buff[0] == '\n') if (strlen(buff) >= strlen(fullurl) + 1) { masterloc = ftell(master); freemaster(datfile, master, 0, 0); /* Unlock! */ printf("Adding %s\n", fullurl); pageadds++; /* WRITE Lock! */ waitwritemaster(datfile, masterloc - strlen(buff), masterloc - strlen(buff), BUFFSIZE); fprintf(master, "%s\n", fullurl); if (strlen(buff) >= strlen(fullurl) + 2) fputc('\t', master); fseek(master, 0, SEEK_END); masterlength = ftell(master); freemaster(datfile, master, masterloc - strlen(buff), BUFFSIZE); /* Unlock! */ urldone = 1; break; } } if (!urldone) { if (ftell(master) > MAX_SIZE) { /* too big, just remove entries */ fseek(master, lrand48() % ftell(master), SEEK_SET); fgets(buff, BUFFSIZE, master); urldone = 1; /* flag that was greater than MAX_SIZE */ } masterloc = ftell(master); freemaster(datfile, master, 0, 0); /* Unlock! */ printf("Adding %s\n", fullurl); pageadds++; /* WRITE Lock! */ waitwritemaster(datfile, masterloc, masterloc - 2, BUFFSIZE); fprintf(master, "%s\n", fullurl); if (urldone) voidline(master); fseek(master, 0, SEEK_END); masterlength = ftell(master); freemaster(datfile, master, masterloc - 2, BUFFSIZE); /* Unlock! */ } } } fclose(page); /* Move file to final destination */ sprintf(scmd, "%s \"%s\" \"%s\"", argv[2], argv[1], pagefile); system(scmd); sleep(WAIT_TIME); sprintf(scmd, "touch %sREMOVE.tmp", filesdir); system(scmd); sprintf(scmd, "rm %s*", filesdir); system(scmd); } pclose(sysout); } }