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