|
|
1.1 ! root 1: # ! 2: ! 3: #include "rcv.h" ! 4: #include <sys/stat.h> ! 5: ! 6: /* ! 7: * Mail -- a mail program ! 8: * ! 9: * Still more user commands. ! 10: */ ! 11: ! 12: /* ! 13: * Process a shell escape by saving signals, ignoring signals, ! 14: * and forking a sh -c ! 15: */ ! 16: ! 17: shell(str) ! 18: char *str; ! 19: { ! 20: int (*sig[2])(), stat[1]; ! 21: register int t; ! 22: char *Shell; ! 23: ! 24: if ((Shell = value("SHELL")) == NOSTR) ! 25: Shell = SHELL; ! 26: for (t = 2; t < 4; t++) ! 27: sig[t-2] = signal(t, SIG_IGN); ! 28: t = vfork(); ! 29: if (t == 0) { ! 30: for (t = 2; t < 4; t++) ! 31: if (sig[t-2] != SIG_IGN) ! 32: signal(t, SIG_DFL); ! 33: execl(Shell, Shell, "-c", str, 0); ! 34: perror(Shell); ! 35: _exit(1); ! 36: } ! 37: while (wait(stat) != t) ! 38: ; ! 39: if (t == -1) ! 40: perror("fork"); ! 41: for (t = 2; t < 4; t++) ! 42: signal(t, sig[t-2]); ! 43: printf("!\n"); ! 44: return(0); ! 45: } ! 46: ! 47: /* ! 48: * Fork an interactive shell. ! 49: */ ! 50: ! 51: dosh(str) ! 52: char *str; ! 53: { ! 54: int (*sig[2])(), stat[1]; ! 55: register int t; ! 56: char *Shell; ! 57: ! 58: if ((Shell = value("SHELL")) == NOSTR) ! 59: Shell = SHELL; ! 60: for (t = 2; t < 4; t++) ! 61: sig[t-2] = signal(t, SIG_IGN); ! 62: t = vfork(); ! 63: if (t == 0) { ! 64: for (t = 2; t < 4; t++) ! 65: if (sig[t-2] != SIG_IGN) ! 66: signal(t, SIG_DFL); ! 67: execl(Shell, Shell, 0); ! 68: perror(Shell); ! 69: _exit(1); ! 70: } ! 71: while (wait(stat) != t) ! 72: ; ! 73: if (t == -1) ! 74: perror("fork"); ! 75: for (t = 2; t < 4; t++) ! 76: signal(t, sig[t-2]); ! 77: putchar('\n'); ! 78: return(0); ! 79: } ! 80: ! 81: /* ! 82: * Print out a nice help message from some file or another. ! 83: */ ! 84: ! 85: help() ! 86: { ! 87: register c; ! 88: register FILE *f; ! 89: ! 90: if ((f = fopen(HELPFILE, "r")) == NULL) { ! 91: printf("No help just now.\n"); ! 92: return(1); ! 93: } ! 94: while ((c = getc(f)) != EOF) ! 95: putchar(c); ! 96: fclose(f); ! 97: return(0); ! 98: } ! 99: ! 100: /* ! 101: * Change user's working directory. ! 102: */ ! 103: ! 104: schdir(str) ! 105: char *str; ! 106: { ! 107: register char *cp; ! 108: ! 109: for (cp = str; *cp == ' '; cp++) ! 110: ; ! 111: if (*cp == '\0') ! 112: cp = homedir; ! 113: else ! 114: if ((cp = expand(cp)) == NOSTR) ! 115: return(1); ! 116: if (chdir(cp) < 0) { ! 117: perror(cp); ! 118: return(1); ! 119: } ! 120: return(0); ! 121: } ! 122: ! 123: /* ! 124: * Reply to a list of messages. Extract each name from the ! 125: * message header and send them off to mail1() ! 126: */ ! 127: ! 128: respond(msgvec) ! 129: int *msgvec; ! 130: { ! 131: struct message *mp; ! 132: char *cp, buf[2 * LINESIZE], *rcv; ! 133: struct name *np; ! 134: struct header head; ! 135: char *netmap(); ! 136: ! 137: if (msgvec[1] != 0) { ! 138: printf("Sorry, can't reply to multiple messages at once\n"); ! 139: return(1); ! 140: } ! 141: mp = &message[msgvec[0] - 1]; ! 142: rcv = nameof(mp); ! 143: strcpy(buf, ""); ! 144: cp = hfield("to", mp); ! 145: if (cp != NOSTR) ! 146: strcpy(buf, cp); ! 147: np = elide(extract(buf)); ! 148: mapf(np, rcv); ! 149: np = delname(np, myname); ! 150: head.h_seq = 1; ! 151: cp = detract(np); ! 152: if (cp != NOSTR) { ! 153: strcpy(buf, cp); ! 154: strcat(buf, " "); ! 155: strcat(buf, rcv); ! 156: } ! 157: else ! 158: strcpy(buf, rcv); ! 159: head.h_to = buf; ! 160: head.h_subject = hfield("subject", mp); ! 161: if (head.h_subject == NOSTR) ! 162: head.h_subject = hfield("subj", mp); ! 163: head.h_cc = NOSTR; ! 164: cp = hfield("cc", mp); ! 165: if (cp != NOSTR) { ! 166: np = elide(extract(cp)); ! 167: mapf(np, rcv); ! 168: np = delname(np, myname); ! 169: head.h_cc = detract(np); ! 170: } ! 171: head.h_bcc = NOSTR; ! 172: mail1(&head); ! 173: return(0); ! 174: } ! 175: ! 176: /* ! 177: * Preserve the named messages, so that they will be sent ! 178: * back to the system mailbox. ! 179: */ ! 180: ! 181: preserve(msgvec) ! 182: int *msgvec; ! 183: { ! 184: register struct message *mp; ! 185: register int *ip, mesg; ! 186: ! 187: if (edit) { ! 188: printf("Cannot \"preserve\" in edit mode\n"); ! 189: return(1); ! 190: } ! 191: for (ip = msgvec; *ip != NULL; ip++) { ! 192: mesg = *ip; ! 193: mp = &message[mesg-1]; ! 194: mp->m_flag |= MPRESERVE; ! 195: dot = mp; ! 196: } ! 197: return(0); ! 198: } ! 199: ! 200: /* ! 201: * Print the size of each message. ! 202: */ ! 203: ! 204: messize(msgvec) ! 205: int *msgvec; ! 206: { ! 207: register struct message *mp; ! 208: register int *ip, mesg; ! 209: ! 210: for (ip = msgvec; *ip != NULL; ip++) { ! 211: mesg = *ip; ! 212: mp = &message[mesg-1]; ! 213: printf("%d: %d\n", mesg, msize(mp)); ! 214: } ! 215: return(0); ! 216: } ! 217: ! 218: /* ! 219: * Quit quickly. If we are sourcing, just pop the input level ! 220: * by returning an error. ! 221: */ ! 222: ! 223: rexit(e) ! 224: { ! 225: if (sourcing) ! 226: return(1); ! 227: exit(e); ! 228: } ! 229: ! 230: /* ! 231: * Set or display a variable value. Syntax is similar to that ! 232: * of csh. ! 233: */ ! 234: ! 235: set(arglist) ! 236: char **arglist; ! 237: { ! 238: register struct var *vp; ! 239: register char *cp, *cp2; ! 240: char varbuf[BUFSIZ], **ap, **p; ! 241: int errs, h, s; ! 242: ! 243: if (argcount(arglist) == 0) { ! 244: for (h = 0, s = 1; h < HSHSIZE; h++) ! 245: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) ! 246: s++; ! 247: ap = (char **) salloc(s * sizeof *ap); ! 248: for (h = 0, p = ap; h < HSHSIZE; h++) ! 249: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) ! 250: *p++ = vp->v_name; ! 251: *p = NOSTR; ! 252: sort(ap); ! 253: for (p = ap; *p != NOSTR; p++) ! 254: printf("%s\t%s\n", *p, value(*p)); ! 255: return(0); ! 256: } ! 257: errs = 0; ! 258: for (ap = arglist; *ap != NOSTR; ap++) { ! 259: cp = *ap; ! 260: cp2 = varbuf; ! 261: while (*cp != '=' && *cp != '\0') ! 262: *cp2++ = *cp++; ! 263: *cp2 = '\0'; ! 264: if (*cp == '\0') ! 265: cp = ""; ! 266: else ! 267: cp++; ! 268: if (equal(varbuf, "")) { ! 269: printf("Non-null variable name required\n"); ! 270: errs++; ! 271: continue; ! 272: } ! 273: assign(varbuf, cp); ! 274: } ! 275: return(errs); ! 276: } ! 277: ! 278: /* ! 279: * Unset a bunch of variable values. ! 280: */ ! 281: ! 282: unset(arglist) ! 283: char **arglist; ! 284: { ! 285: register struct var *vp, *vp2; ! 286: register char *cp; ! 287: int errs, h; ! 288: char **ap; ! 289: ! 290: errs = 0; ! 291: for (ap = arglist; *ap != NOSTR; ap++) { ! 292: if ((vp2 = lookup(*ap)) == NOVAR) { ! 293: if (!sourcing) { ! 294: printf("\"%s\": undefined variable\n", *ap); ! 295: errs++; ! 296: } ! 297: continue; ! 298: } ! 299: h = hash(*ap); ! 300: if (vp2 == variables[h]) { ! 301: variables[h] = variables[h]->v_link; ! 302: vfree(vp2->v_name); ! 303: vfree(vp2->v_value); ! 304: cfree(vp2); ! 305: continue; ! 306: } ! 307: for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) ! 308: ; ! 309: vp->v_link = vp2->v_link; ! 310: vfree(vp2->v_name); ! 311: vfree(vp2->v_value); ! 312: cfree(vp2); ! 313: } ! 314: return(errs); ! 315: } ! 316: ! 317: /* ! 318: * Put add users to a group. ! 319: */ ! 320: ! 321: group(argv) ! 322: char **argv; ! 323: { ! 324: register struct grouphead *gh; ! 325: register struct group *gp; ! 326: register int h; ! 327: int s; ! 328: char **ap, *gname, **p; ! 329: ! 330: if (argcount(argv) == 0) { ! 331: for (h = 0, s = 1; h < HSHSIZE; h++) ! 332: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) ! 333: s++; ! 334: ap = (char **) salloc(s * sizeof *ap); ! 335: for (h = 0, p = ap; h < HSHSIZE; h++) ! 336: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) ! 337: *p++ = gh->g_name; ! 338: *p = NOSTR; ! 339: sort(ap); ! 340: for (p = ap; *p != NOSTR; p++) ! 341: printgroup(*p); ! 342: return(0); ! 343: } ! 344: if (argcount(argv) == 1) { ! 345: printgroup(*argv); ! 346: return(0); ! 347: } ! 348: gname = *argv; ! 349: h = hash(gname); ! 350: if ((gh = findgroup(gname)) == NOGRP) { ! 351: gh = (struct grouphead *) calloc(sizeof *gh, 1); ! 352: gh->g_name = vcopy(gname); ! 353: gh->g_list = NOGE; ! 354: gh->g_link = groups[h]; ! 355: groups[h] = gh; ! 356: } ! 357: ! 358: /* ! 359: * Insert names from the command list into the group. ! 360: * Who cares if there are duplicates? They got tossed ! 361: * later anyway. ! 362: */ ! 363: ! 364: for (ap = argv+1; *ap != NOSTR; ap++) { ! 365: gp = (struct group *) calloc(sizeof *gp, 1); ! 366: gp->ge_name = vcopy(*ap); ! 367: gp->ge_link = gh->g_list; ! 368: gh->g_list = gp; ! 369: } ! 370: return(0); ! 371: } ! 372: ! 373: /* ! 374: * Sort the passed string vecotor into ascending dictionary ! 375: * order. ! 376: */ ! 377: ! 378: sort(list) ! 379: char **list; ! 380: { ! 381: register char **ap; ! 382: int diction(); ! 383: ! 384: for (ap = list; *ap != NOSTR; ap++) ! 385: ; ! 386: if (ap-list < 2) ! 387: return; ! 388: qsort(list, ap-list, sizeof *list, diction); ! 389: } ! 390: ! 391: /* ! 392: * Do a dictionary order comparison of the arguments from ! 393: * qsort. ! 394: */ ! 395: ! 396: diction(a, b) ! 397: register char **a, **b; ! 398: { ! 399: return(strcmp(*a, *b)); ! 400: } ! 401: ! 402: /* ! 403: * The do nothing command for comments. ! 404: */ ! 405: ! 406: null(e) ! 407: { ! 408: return(0); ! 409: } ! 410: ! 411: /* ! 412: * Print out the current edit file, if we are editting. ! 413: * Otherwise, print the name of the person who's mail ! 414: * we are reading. ! 415: */ ! 416: ! 417: file(e) ! 418: { ! 419: register char *cp; ! 420: ! 421: if (edit) ! 422: printf("Reading \"%s\"\n", editfile); ! 423: else ! 424: printf("Reading %s's mail\n", rindex(mailname, '/') + 1); ! 425: return(0); ! 426: } ! 427: ! 428: /* ! 429: * Expand file names like echo ! 430: */ ! 431: ! 432: echo(argv) ! 433: char **argv; ! 434: { ! 435: register char **ap; ! 436: register char *cp; ! 437: ! 438: for (ap = argv; *ap != NOSTR; ap++) { ! 439: cp = *ap; ! 440: if ((cp = expand(cp)) != NOSTR) ! 441: printf("%s\n", cp); ! 442: } ! 443: return(0); ! 444: } ! 445: ! 446: /* ! 447: * Reply to a series of messages by simply mailing to the senders ! 448: * and not messing around with the To: and Cc: lists as in normal ! 449: * reply. ! 450: */ ! 451: ! 452: Respond(msgvec) ! 453: int msgvec[]; ! 454: { ! 455: struct header head; ! 456: struct message *mp; ! 457: register int s, *ap; ! 458: register char *cp, *subject; ! 459: ! 460: for (s = 0, ap = msgvec; *ap != 0; ap++) { ! 461: mp = &message[*ap - 1]; ! 462: s += strlen(nameof(mp)) + 1; ! 463: } ! 464: if (s == 0) ! 465: return(0); ! 466: cp = salloc(s + 2); ! 467: head.h_to = cp; ! 468: for (ap = msgvec; *ap != 0; ap++) { ! 469: mp = &message[*ap - 1]; ! 470: cp = copy(nameof(mp), cp); ! 471: *cp++ = ' '; ! 472: } ! 473: *--cp = 0; ! 474: mp = &message[msgvec[0] - 1]; ! 475: subject = hfield("subject", mp); ! 476: if (subject == NOSTR) ! 477: subject = hfield("subj", mp); ! 478: head.h_subject = subject; ! 479: head.h_cc = NOSTR; ! 480: head.h_bcc = NOSTR; ! 481: head.h_seq = 0; ! 482: mail1(&head); ! 483: return(0); ! 484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.