1: /* $Header: respond.c,v 4.3.1.4 85/05/23 17:24:49 lwall Exp $ 2: * 3: * $Log: respond.c,v $ 4: * Revision 4.3.1.4 85/05/23 17:24:49 lwall 5: * Now allows 'r' and 'f' on null articles. 6: * 7: * Revision 4.3.1.3 85/05/15 14:42:32 lwall 8: * Removed duplicate include of intrp.h. 9: * 10: * Revision 4.3.1.2 85/05/14 08:55:15 lwall 11: * Default for normal/mailbox question was applied to wrong buffer. 12: * 13: * Revision 4.3.1.1 85/05/10 11:37:33 lwall 14: * Branch for patches. 15: * 16: * Revision 4.3 85/05/01 11:47:04 lwall 17: * Baseline for release with 4.3bsd. 18: * 19: */ 20: 21: #include "EXTERN.h" 22: #include "common.h" 23: #include "intrp.h" 24: #include "head.h" 25: #include "term.h" 26: #include "ng.h" 27: #include "util.h" 28: #include "rn.h" 29: #include "artio.h" 30: #include "final.h" 31: #include "INTERN.h" 32: #include "respond.h" 33: 34: static char nullart[] = "\nNull article\n"; 35: 36: void 37: respond_init() 38: { 39: ; 40: } 41: 42: int 43: save_article() 44: { 45: bool use_pref; 46: register char *s, *c; 47: char altbuf[CBUFLEN]; 48: int iter; 49: bool interactive = (buf[1] == FINISHCMD); 50: 51: if (!finish_command(interactive)) /* get rest of command */ 52: return SAVE_ABORT; 53: use_pref = isupper(*buf); 54: #ifdef ASYNC_PARSE 55: parse_maybe(art); 56: #endif 57: savefrom = (*buf=='w' || *buf=='W' ? htype[PAST_HEADER].ht_minpos : 0); 58: if (artopen(art) == Nullfp) { 59: #ifdef VERBOSE 60: IF(verbose) 61: fputs("\n\ 62: Saving null articles is not very productive! :-)\n\ 63: ",stdout) FLUSH; 64: ELSE 65: #endif 66: #ifdef TERSE 67: fputs(nullart,stdout) FLUSH; 68: #endif 69: return SAVE_DONE; 70: } 71: if (chdir(cwd)) { 72: printf(nocd,cwd) FLUSH; 73: sig_catcher(0); 74: } 75: if (savedest) 76: free(savedest); 77: if ((s = index(buf,'|')) != Nullch) { 78: /* is it a pipe command? */ 79: s++; /* skip the | */ 80: while (*s == ' ') s++; 81: safecpy(altbuf,filexp(s),sizeof altbuf); 82: savedest = altbuf; 83: interp(cmd_buf, (sizeof cmd_buf), getval("PIPESAVER",PIPESAVER)); 84: /* then set up for command */ 85: resetty(); /* restore tty state */ 86: if (use_pref) /* use preferred shell? */ 87: doshell(Nullch,cmd_buf); 88: /* do command with it */ 89: else 90: doshell(sh,cmd_buf); /* do command with sh */ 91: noecho(); /* and stop echoing */ 92: crmode(); /* and start cbreaking */ 93: savedest = savestr(savedest); 94: } 95: else { /* normal save */ 96: bool there, mailbox; 97: char *savename = getval("SAVENAME",SAVENAME); 98: 99: s = buf+1; /* skip s or S */ 100: if (*s == '-') { /* if they are confused, skip - also */ 101: #ifdef VERBOSE 102: IF(verbose) 103: fputs("Warning: '-' ignored. This isn't readnews.\n",stdout) 104: FLUSH; 105: ELSE 106: #endif 107: #ifdef TERSE 108: fputs("'-' ignored.\n",stdout) FLUSH; 109: #endif 110: s++; 111: } 112: for (; *s == ' '; s++); /* skip spaces */ 113: safecpy(altbuf,filexp(s),sizeof altbuf); 114: s = altbuf; 115: if (! index(s,'/')) { 116: interp(buf, (sizeof buf), getval("SAVEDIR",SAVEDIR)); 117: if (makedir(buf,MD_DIR)) /* ensure directory exists */ 118: strcpy(buf,cwd); 119: if (*s) { 120: for (c = buf; *c; c++) ; 121: *c++ = '/'; 122: strcpy(c,s); /* add filename */ 123: } 124: s = buf; 125: } 126: for (iter = 0; 127: (there = stat(s,&filestat) >= 0) && 128: (filestat.st_mode & S_IFDIR); 129: iter++) { /* is it a directory? */ 130: 131: c = (s+strlen(s)); 132: *c++ = '/'; /* put a slash before filename */ 133: interp(c, s==buf?(sizeof buf):(sizeof altbuf), 134: iter ? "News" : savename ); 135: /* generate a default name somehow or other */ 136: if (index(c,'/')) { /* yikes, a '/' in the filename */ 137: makedir(s,MD_FILE); 138: } 139: } 140: if (*s != '/') { /* relative path? */ 141: c = (s==buf ? altbuf : buf); 142: sprintf(c, "%s/%s", cwd, s); 143: s = c; /* absolutize it */ 144: } 145: s = savedest = savestr(s); /* doesn't move any more */ 146: /* make it handy for %b */ 147: if (!there) { 148: if (mbox_always) 149: mailbox = TRUE; 150: else if (norm_always) 151: mailbox = FALSE; 152: else { 153: char *dflt = (instr(savename,"%a") ? "nyq" : "ynq"); 154: 155: sprintf(cmd_buf, 156: "\nFile %s doesn't exist--\n use mailbox format? [%s] ", 157: s,dflt); 158: reask_save: 159: in_char(cmd_buf); 160: putchar('\n') FLUSH; 161: setdef(buf,dflt); 162: #ifdef VERIFY 163: printcmd(); 164: #endif 165: if (*buf == 'h') { 166: #ifdef VERBOSE 167: IF(verbose) 168: printf("\n\ 169: Type y to create %s as a mailbox.\n\ 170: Type n to create it as a normal file.\n\ 171: Type q to abort the save.\n\ 172: ",s) FLUSH; 173: ELSE 174: #endif 175: #ifdef TERSE 176: fputs("\n\ 177: y to create mailbox.\n\ 178: n to create normal file.\n\ 179: q to abort.\n\ 180: ",stdout) FLUSH; 181: #endif 182: goto reask_save; 183: } 184: else if (*buf == 'n') { 185: mailbox = FALSE; 186: } 187: else if (*buf == 'y') { 188: mailbox = TRUE; 189: } 190: else if (*buf == 'q') { 191: goto s_bomb; 192: } 193: else { 194: fputs(hforhelp,stdout) FLUSH; 195: settle_down(); 196: goto reask_save; 197: } 198: } 199: } 200: else if (filestat.st_mode & S_IFCHR) 201: mailbox = FALSE; 202: else { 203: int tmpfd; 204: 205: tmpfd = open(s,0); 206: if (tmpfd == -1) 207: mailbox = FALSE; 208: else { 209: read(tmpfd,buf,LBUFLEN); 210: c = buf; 211: if (!isspace(MBOXCHAR)) 212: while (isspace(*c)) 213: c++; 214: mailbox = (*c == MBOXCHAR); 215: close(tmpfd); 216: } 217: } 218: 219: safecpy(cmd_buf, filexp(mailbox ? 220: getval("MBOXSAVER",MBOXSAVER) : 221: getval("NORMSAVER",NORMSAVER) ), sizeof cmd_buf); 222: /* format the command */ 223: resetty(); /* make terminal behave */ 224: if (doshell(use_pref?Nullch:SH,cmd_buf)) 225: fputs("Not saved",stdout); 226: else 227: printf("%s to %s %s", 228: there?"Appended":"Saved", 229: mailbox?"mailbox":"file", 230: s); 231: if (interactive) 232: putchar('\n') FLUSH; 233: noecho(); /* make terminal do what we want */ 234: crmode(); 235: } 236: s_bomb: 237: #ifdef SERVER 238: if (chdir(spool)) { 239: #else 240: if (chdir(spool) || chdir(ngdir)) { 241: #endif 242: printf(nocd,ngdir) FLUSH; 243: sig_catcher(0); 244: } 245: return SAVE_DONE; 246: } 247: 248: int 249: cancel_article() 250: { 251: char *artid_buf; 252: char *ngs_buf; 253: char *from_buf; 254: char *reply_buf; 255: int myuid = getuid(); 256: int r = -1; 257: 258: if (artopen(art) == Nullfp) { 259: #ifdef VERBOSE 260: IF(verbose) 261: fputs("\n\ 262: Cancelling null articles is your idea of fun? :-)\n\ 263: ",stdout) FLUSH; 264: ELSE 265: #endif 266: #ifdef TERSE 267: fputs(nullart,stdout) FLUSH; 268: #endif 269: return r; 270: } 271: reply_buf = fetchlines(art,REPLY_LINE); 272: from_buf = fetchlines(art,FROM_LINE); 273: artid_buf = fetchlines(art,ARTID_LINE); 274: ngs_buf = fetchlines(art,NGS_LINE); 275: if (!instr(from_buf,sitename) || 276: (!instr(from_buf,logname) && 277: !instr(reply_buf,logname) && 278: #ifdef NEWSADMIN 279: myuid != newsuid && 280: #endif 281: myuid != ROOTID ) ) 282: #ifdef VERBOSE 283: IF(verbose) 284: fputs("You can't cancel someone else's article\n",stdout) 285: FLUSH; 286: ELSE 287: #endif 288: #ifdef TERSE 289: fputs("Not your article\n",stdout) FLUSH; 290: #endif 291: else { 292: tmpfp = fopen(headname,"w"); /* open header file */ 293: if (tmpfp == Nullfp) { 294: printf(cantcreate,headname) FLUSH; 295: goto no_cancel; 296: } 297: interp(buf, (sizeof buf), getval("CANCELHEADER",CANCELHEADER)); 298: fputs(buf,tmpfp); 299: fclose(tmpfp); 300: r = doshell(sh,filexp(getval("CANCEL",CANCEL))); 301: } 302: no_cancel: 303: free(artid_buf); 304: free(ngs_buf); 305: free(from_buf); 306: free(reply_buf); 307: return r; 308: } 309: 310: void 311: reply() 312: { 313: bool incl_body = (*buf == 'R'); 314: char *maildoer = savestr(filexp(getval("MAILPOSTER",MAILPOSTER))); 315: 316: artopen(art); 317: tmpfp = fopen(headname,"w"); /* open header file */ 318: if (tmpfp == Nullfp) { 319: printf(cantcreate,headname) FLUSH; 320: goto no_reply; 321: } 322: interp(buf, (sizeof buf), getval("MAILHEADER",MAILHEADER)); 323: fputs(buf,tmpfp); 324: if (!instr(maildoer,"%h")) 325: #ifdef VERBOSE 326: IF(verbose) 327: printf("\n%s\n(Above lines saved in file %s)\n",buf,headname) 328: FLUSH; 329: ELSE 330: #endif 331: #ifdef TERSE 332: printf("\n%s\n(Header in %s)\n",buf,headname) FLUSH; 333: #endif 334: if (incl_body && artfp != Nullfp) { 335: interp(buf, (sizeof buf), getval("YOUSAID",YOUSAID)); 336: fprintf(tmpfp,"%s\n",buf); 337: #ifdef ASYNC_PARSE 338: parse_maybe(art); 339: #endif 340: fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0); 341: while (fgets(buf,LBUFLEN,artfp) != Nullch) { 342: fprintf(tmpfp,"%s%s",indstr,buf); 343: } 344: fprintf(tmpfp,"\n"); 345: } 346: fclose(tmpfp); 347: interp(cmd_buf, (sizeof cmd_buf), maildoer); 348: invoke(cmd_buf,origdir); 349: UNLINK(headname); /* kill the header file */ 350: no_reply: 351: free(maildoer); 352: } 353: 354: void 355: followup() 356: { 357: bool incl_body = (*buf == 'F'); 358: 359: artopen(art); 360: tmpfp = fopen(headname,"w"); 361: if (tmpfp == Nullfp) { 362: printf(cantcreate,headname) FLUSH; 363: return; 364: } 365: interp(buf, (sizeof buf), getval("NEWSHEADER",NEWSHEADER)); 366: fprintf(tmpfp,"%s",buf); 367: if (incl_body && artfp != Nullfp) { 368: #ifdef VERBOSE 369: if (verbose) 370: fputs("\n\ 371: (Be sure to double-check the attribution against the signature, and\n\ 372: trim the quoted article down as much as possible.)\n\ 373: ",stdout) FLUSH; 374: #endif 375: interp(buf, (sizeof buf), getval("ATTRIBUTION",ATTRIBUTION)); 376: fprintf(tmpfp,"%s\n",buf); 377: #ifdef ASYNC_PARSE 378: parse_maybe(art); 379: #endif 380: fseek(artfp,(long)htype[PAST_HEADER].ht_minpos,0); 381: while (fgets(buf,LBUFLEN,artfp) != Nullch) { 382: fprintf(tmpfp,"%s%s",indstr,buf); 383: } 384: fprintf(tmpfp,"\n"); 385: } 386: fclose(tmpfp); 387: safecpy(cmd_buf,filexp(getval("NEWSPOSTER",NEWSPOSTER)),sizeof cmd_buf); 388: invoke(cmd_buf,origdir); 389: UNLINK(headname); 390: } 391: 392: void 393: invoke(cmd,dir) 394: char *cmd,*dir; 395: { 396: if (chdir(dir)) { 397: printf(nocd,dir) FLUSH; 398: return; 399: } 400: #ifdef VERBOSE 401: IF(verbose) 402: printf("\n(leaving cbreak mode; cwd=%s)\nInvoking command: %s\n\n", 403: dir,cmd) FLUSH; 404: ELSE 405: #endif 406: #ifdef TERSE 407: printf("\n(-cbreak; cwd=%s)\nInvoking: %s\n\n",dir,cmd) FLUSH; 408: #endif 409: resetty(); /* make terminal well-behaved */ 410: doshell(sh,cmd); /* do the command */ 411: noecho(); /* set no echo */ 412: crmode(); /* and cbreak mode */ 413: #ifdef VERBOSE 414: IF(verbose) 415: fputs("\n(re-entering cbreak mode)\n",stdout) FLUSH; 416: ELSE 417: #endif 418: #ifdef TERSE 419: fputs("\n(+cbreak)\n",stdout) FLUSH; 420: #endif 421: #ifdef SERVER 422: if (chdir(spool)) { 423: #else 424: if (chdir(spool) || chdir(ngdir)) { 425: #endif 426: printf(nocd,ngdir) FLUSH; 427: sig_catcher(0); 428: } 429: }