1: /* prompter.c - prompting editor front-end */ 2: 3: #include "../h/mh.h" 4: #include <stdio.h> 5: #include <errno.h> 6: #ifndef SYS5 7: #include <sgtty.h> 8: #else SYS5 9: #include <sys/types.h> 10: #include <termio.h> 11: #include <sys/ioctl.h> 12: #endif SYS5 13: #ifdef BSD42 14: #include <setjmp.h> 15: #endif BSD42 16: #include <signal.h> 17: 18: 19: #define QUOTE '\\' 20: #ifndef CKILL 21: #define CKILL '@' 22: #endif not CKILL 23: #ifndef CERASE 24: #define CERASE '#' 25: #endif not CERASE 26: 27: /* */ 28: 29: static struct swit switches[] = { 30: #define ERASESW 0 31: "erase chr", 0, 32: #define KILLSW 1 33: "kill chr", 0, 34: 35: #define PREPSW 2 36: "prepend", 0, 37: #define NPREPSW 3 38: "noprepend", 0, 39: 40: #define RAPDSW 4 41: "rapid", 0, 42: #define NRAPDSW 5 43: "norapid", 0, 44: 45: #define BODYSW 6 46: "body", -4, 47: #define NBODYSW 7 48: "nobody", -6, 49: 50: #define HELPSW 8 51: "help", 4, 52: 53: NULL, NULL 54: }; 55: 56: /* */ 57: 58: extern int errno; 59: 60: 61: #ifndef SYS5 62: #define ERASE sg.sg_erase 63: #define KILL sg.sg_kill 64: static struct sgttyb sg; 65: 66: #define INTR tc.t_intrc 67: static struct tchars tc; 68: #else SYS5 69: #define ERASE sg.c_cc[VERASE] 70: #define KILL sg.c_cc[VKILL] 71: #define INTR sg.c_cc[VINTR] 72: static struct termio sg; 73: #endif SYS5 74: 75: 76: int intrser (); 77: 78: static int wtuser = 0; 79: static int sigint = 0; 80: 81: #ifdef BSD42 82: static jmp_buf sigenv; 83: #endif BSD42 84: 85: /* */ 86: 87: /* ARGSUSED */ 88: 89: main (argc, argv) 90: int argc; 91: char *argv[]; 92: { 93: int body = 1, 94: prepend = 1, 95: rapid = 0, 96: fdi, 97: fdo, 98: i, 99: state; 100: char *cp, 101: *drft = NULL, 102: *erasep = NULL, 103: *killp = NULL, 104: name[NAMESZ], 105: field[BUFSIZ], 106: buffer[BUFSIZ], 107: tmpfil[BUFSIZ], 108: **ap, 109: *arguments[MAXARGS], 110: **argp; 111: FILE *in, *out; 112: 113: invo_name = r1bindex (argv[0], '/'); 114: if ((cp = m_find (invo_name)) != NULL) { 115: ap = brkstring (cp = getcpy (cp), " ", "\n"); 116: ap = copyip (ap, arguments); 117: } 118: else 119: ap = arguments; 120: (void) copyip (argv + 1, ap); 121: argp = arguments; 122: 123: /* */ 124: 125: while (cp = *argp++) 126: if (*cp == '-') 127: switch (smatch (++cp, switches)) { 128: case AMBIGSW: 129: ambigsw (cp, switches); 130: done (1); 131: case UNKWNSW: 132: adios (NULLCP, "-%s unknown", cp); 133: case HELPSW: 134: (void) sprintf (buffer, "%s [switches] file", invo_name); 135: help (buffer, switches); 136: done (1); 137: 138: case ERASESW: 139: if (!(erasep = *argp++) || *erasep == '-') 140: adios (NULLCP, "missing argument to %s", argp[-2]); 141: continue; 142: case KILLSW: 143: if (!(killp = *argp++) || *killp == '-') 144: adios (NULLCP, "missing argument to %s", argp[-2]); 145: continue; 146: 147: case PREPSW: 148: prepend++; 149: continue; 150: case NPREPSW: 151: prepend = 0; 152: continue; 153: 154: case RAPDSW: 155: rapid++; 156: continue; 157: case NRAPDSW: 158: rapid = 0; 159: continue; 160: 161: case BODYSW: 162: body++; 163: continue; 164: case NBODYSW: 165: body = 0; 166: continue; 167: } 168: else 169: if (!drft) 170: drft = cp; 171: 172: /* */ 173: 174: if (!drft) 175: adios (NULLCP, "usage: %s [switches] file", invo_name); 176: if ((in = fopen (drft, "r")) == NULL) 177: adios (drft, "unable to open"); 178: 179: (void) strcpy (tmpfil, m_tmpfil (invo_name)); 180: if ((out = fopen (tmpfil, "w")) == NULL) 181: adios (tmpfil, "unable to create"); 182: (void) chmod (tmpfil, 0600); 183: 184: if (killp || erasep) { 185: #ifndef SYS5 186: int serase, 187: skill; 188: #else SYS5 189: char serase, 190: skill; 191: #endif SYS5 192: 193: #ifndef SYS5 194: (void) ioctl (0, TIOCGETP, (char *) &sg); 195: (void) ioctl (0, TIOCGETC, (char *) &tc); 196: #else SYS5 197: (void) ioctl(0, TCGETA, &sg); 198: #endif SYS5 199: skill = KILL; 200: serase = ERASE; 201: KILL = killp ? chrcnv (killp) : skill; 202: ERASE = erasep ? chrcnv (erasep) : serase; 203: #ifndef SYS5 204: (void) ioctl (0, TIOCSETN, (char *) &sg); 205: #else SYS5 206: (void) ioctl(0, TCSETAW, &sg); 207: #endif SYS5 208: 209: chrdsp ("erase", ERASE); 210: chrdsp (", kill", KILL); 211: chrdsp (", intr", INTR); 212: (void) putchar ('\n'); 213: (void) fflush (stdout); 214: 215: KILL = skill; 216: ERASE = serase; 217: } 218: 219: /* */ 220: 221: sigint = 0; 222: setsig (SIGINT, intrser); 223: 224: for (state = FLD;;) { 225: switch (state = m_getfld (state, name, field, sizeof field, in)) { 226: case FLD: 227: case FLDEOF: 228: case FLDPLUS: 229: for (cp = field; *cp; cp++) 230: if (*cp != ' ' && *cp != '\t') 231: break; 232: if (*cp++ != '\n' || *cp != NULL) { 233: printf ("%s:%s", name, field); 234: fprintf (out, "%s:%s", name, field); 235: while (state == FLDPLUS) { 236: state = 237: m_getfld (state, name, field, sizeof field, in); 238: printf ("%s", field); 239: fprintf (out, "%s", field); 240: } 241: } 242: else { 243: printf ("%s: ", name); 244: (void) fflush (stdout); 245: i = getln (field, sizeof field); 246: if (i == -1) { 247: abort: ; 248: if (killp || erasep) 249: #ifndef SYS5 250: (void) ioctl (0, TIOCSETN, (char *) &sg); 251: #else SYS5 252: (void) ioctl (0, TCSETA, &sg); 253: #endif SYS5 254: (void) unlink (tmpfil); 255: done (1); 256: } 257: if (i != 0 || (field[0] != '\n' && field[0] != NULL)) { 258: fprintf (out, "%s:", name); 259: do { 260: if (field[0] != ' ' && field[0] != '\t') 261: (void) putc (' ', out); 262: fprintf (out, "%s", field); 263: } while (i == 1 264: && (i = getln (field, sizeof field)) >= 0); 265: if (i == -1) 266: goto abort; 267: } 268: } 269: if (state == FLDEOF) {/* moby hack */ 270: fprintf (out, "--------\n"); 271: printf ("--------\n"); 272: if (!body) 273: break; 274: goto no_body; 275: } 276: continue; 277: 278: case BODY: 279: case BODYEOF: 280: case FILEEOF: 281: fprintf (out, "--------\n"); 282: if (field[0] == NULL || !prepend) 283: printf ("--------\n"); 284: if (field[0]) { 285: if (prepend && body) { 286: printf ("\n--------Enter initial text\n\n"); 287: (void) fflush (stdout); 288: for (;;) { 289: (void) getln (buffer, sizeof buffer); 290: if (buffer[0] == NULL) 291: break; 292: fprintf (out, "%s", buffer); 293: } 294: } 295: 296: do { 297: fprintf (out, "%s", field); 298: if (!rapid && !sigint) 299: printf ("%s", field); 300: } while (state == BODY && 301: (state = m_getfld (state, name, field, sizeof field, in))); 302: if (prepend || !body) 303: break; 304: else 305: printf ("\n--------Enter additional text\n\n"); 306: } 307: no_body: ; 308: (void) fflush (stdout); 309: for (;;) { 310: (void) getln (field, sizeof field); 311: if (field[0] == NULL) 312: break; 313: fprintf (out, "%s", field); 314: } 315: break; 316: 317: default: 318: adios (NULLCP, "skeleton is poorly formatted"); 319: } 320: break; 321: } 322: 323: if (body) 324: printf ("--------\n"); 325: (void) fflush (stdout); 326: 327: (void) fclose (in); 328: (void) fclose (out); 329: 330: (void) signal (SIGINT, SIG_IGN); 331: 332: /* */ 333: 334: if (killp || erasep) 335: #ifndef SYS5 336: (void) ioctl (0, TIOCSETN, (char *) &sg); 337: #else SYS5 338: (void) ioctl (0, TCSETAW, &sg); 339: #endif SYS5 340: 341: if ((fdi = open (tmpfil, 0)) == NOTOK) 342: adios (tmpfil, "unable to re-open"); 343: if ((fdo = creat (drft, m_gmprot ())) == NOTOK) 344: adios (drft, "unable to write"); 345: cpydata (fdi, fdo, tmpfil, drft); 346: (void) close (fdi); 347: (void) close (fdo); 348: (void) unlink (tmpfil); 349: 350: m_update (); 351: 352: done (0); 353: } 354: 355: /* */ 356: 357: getln (buffer, n) 358: register char *buffer; 359: register int n; 360: { 361: int c; 362: char *cp; 363: 364: cp = buffer; 365: *cp = NULL; 366: 367: #ifndef BSD42 368: wtuser = 1; 369: #else BSD42 370: switch (setjmp (sigenv)) { 371: case OK: 372: wtuser = 1; 373: break; 374: 375: case DONE: 376: wtuser = 0; 377: return 0; 378: 379: default: 380: wtuser = 0; 381: return NOTOK; 382: } 383: #endif BSD42 384: 385: for (;;) 386: switch (c = getchar ()) { 387: case EOF: 388: #ifndef BSD42 389: wtuser = 0; 390: return (errno != EINTR ? 0 : NOTOK); 391: #else BSD42 392: clearerr (stdin); 393: longjmp (sigenv, DONE); 394: #endif BSD42 395: 396: case '\n': 397: if (cp[-1] == QUOTE) { 398: cp[-1] = c; 399: wtuser = 0; 400: return 1; 401: } 402: *cp++ = c; 403: *cp = NULL; 404: wtuser = 0; 405: return 0; 406: 407: default: 408: if (cp < buffer + n) 409: *cp++ = c; 410: *cp = NULL; 411: } 412: } 413: 414: /* */ 415: 416: /* ARGSUSED */ 417: 418: static int intrser (i) 419: int i; 420: { 421: #ifndef BSD42 422: (void) signal (SIGINT, intrser); 423: if (!wtuser) 424: sigint++; 425: #else BSD42 426: if (wtuser) 427: longjmp (sigenv, NOTOK); 428: sigint++; 429: #endif BSD42 430: } 431: 432: 433: chrcnv (cp) 434: register char *cp; 435: { 436: return (*cp != QUOTE ? *cp : m_atoi (++cp)); 437: } 438: 439: 440: chrdsp (s, c) 441: char *s, 442: c; 443: { 444: printf ("%s ", s); 445: if (c < ' ' || c == 0177) 446: printf ("^%c", c ^ 0100); 447: else 448: printf ("%c", c); 449: }