/* Copyright (c) 1979 Regents of the University of California */ # #include "rcv.h" #include <sys/stat.h> /* * Mail -- a mail program * * Still more user commands. */ /* * Process a shell escape by saving signals, ignoring signals, * and forking a sh -c */ shell(str) char *str; { int (*sig[2])(), stat[1]; register int t; char *Shell; if ((Shell = value("SHELL")) == NOSTR) Shell = "/bin/sh"; for (t = 2; t < 4; t++) sig[t-2] = signal(t, SIG_IGN); t = fork(); if (t == 0) { for (t = 2; t < 4; t++) if (sig[t-2] != SIG_IGN) signal(t, SIG_DFL); execl(Shell, Shell, "-c", str, 0); perror(Shell); exit(1); } while (wait(stat) != t) ; if (t == -1) perror("fork"); for (t = 2; t < 4; t++) signal(t, sig[t-2]); printf("!\n"); return(0); } /* * Print out a nice help message from some file or another. */ help() { register c; register FILE *f; if ((f = fopen(HELPFILE, "r")) == NULL) { printf("No help just now.\n"); return(1); } while ((c = getc(f)) != EOF) putchar(c); fclose(f); return(0); } /* * Change user's working directory. */ schdir(str) char *str; { register char *cp; for (cp = str; *cp == ' '; cp++) ; if (*cp == '\0') cp = homedir; if (chdir(cp) < 0) { perror(cp); return(1); } return(0); } /* * Reply to a list of messages. Extract each name from the * message header and send them off to mail() */ respond(msgvec) int *msgvec; { register struct message *mp; register char **ap; register int *ip; int s; char *cp2, *buf; struct header head; for (ip = msgvec, s = 0; *ip; ip++) { mp = &message[*ip - 1]; s += strlen(nameof(mp))+1; } buf = salloc(s+1); cp2 = buf; for (ip = msgvec; *ip; ip++) { touch(*ip); mp = &message[*ip - 1]; dot = mp; cp2 = copy(nameof(mp), cp2); *cp2++ = ' '; } if (cp2 != buf) cp2--; *cp2 = '\0'; mp = &message[msgvec[0]-1]; head.h_seq = 1; head.h_to = buf; head.h_subj = hfield("subj", mp); head.h_cc = hfield("cc", mp); mail1(&head); return(0); } /* * Preserve the named messages, so that they will be sent * back to the system mailbox. */ preserve(msgvec) int *msgvec; { register struct message *mp; register int *ip, mesg; if (edit) { printf("Cannot \"preserve\" in edit mode\n"); return(1); } for (ip = msgvec; *ip != NULL; ip++) { mesg = *ip; mp = &message[mesg-1]; mp->m_flag |= MPRESERVE; dot = mp; } return(0); } /* * Print the size of each message. */ messize(msgvec) int *msgvec; { register struct message *mp; register int *ip, mesg; for (ip = msgvec; *ip != NULL; ip++) { mesg = *ip; mp = &message[mesg-1]; printf("%d: %d\n", mesg, msize(mp)); } return(0); } /* * Quit quickly. If we are sourcing, just pop the input level * by returning an error. */ rexit(e) { if (sourcing) return(1); exit(e); } /* * Set or display a variable value. Syntax is similar to that * of csh. */ set(arglist) char **arglist; { register struct var *vp; register char *cp, *cp2; char varbuf[BUFSIZ], **ap, **p; int errs, h, s; if (argcount(arglist) == 0) { for (h = 0, s = 1; h < HSHSIZE; h++) for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) s++; ap = (char **) salloc(s * sizeof *ap); for (h = 0, p = ap; h < HSHSIZE; h++) for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) *p++ = vp->v_name; *p = NOSTR; sort(ap); for (p = ap; *p != NOSTR; p++) printf("%s\t%s\n", *p, value(*p)); return(0); } errs = 0; for (ap = arglist; *ap != NOSTR; ap++) { cp = *ap; cp2 = varbuf; while (*cp != '=' && *cp != '\0') *cp2++ = *cp++; *cp2 = '\0'; if (*cp == '\0') cp = ""; else cp++; if (equal(varbuf, "")) { printf("Non-null variable name required\n"); errs++; continue; } assign(varbuf, cp); } return(errs); } /* * Unset a bunch of variable values. */ unset(arglist) char **arglist; { register struct var *vp, *vp2; register char *cp; int errs, h; char **ap; errs = 0; for (ap = arglist; *ap != NOSTR; ap++) { if ((vp2 = lookup(*ap)) == NOVAR) { printf("\"%s\": undefined variable\n", *ap); errs++; continue; } h = hash(*ap); if (vp2 == variables[h]) { variables[h] = variables[h]->v_link; vfree(vp2->v_name); vfree(vp2->v_value); cfree(vp2); continue; } for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) ; vp->v_link = vp2->v_link; vfree(vp2->v_name); vfree(vp2->v_value); cfree(vp2); } return(errs); } /* * Put add users to a group. */ group(argv) char **argv; { register struct grouphead *gh; register struct group *gp; register int h; int s; char **ap, *gname, **p; if (argcount(argv) == 0) { for (h = 0, s = 1; h < HSHSIZE; h++) for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) s++; ap = (char **) salloc(s * sizeof *ap); for (h = 0, p = ap; h < HSHSIZE; h++) for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) *p++ = gh->g_name; *p = NOSTR; sort(ap); for (p = ap; *p != NOSTR; p++) printgroup(*p); return(0); } if (argcount(argv) == 1) { printgroup(*argv); return(0); } gname = *argv; h = hash(gname); if ((gh = findgroup(gname)) == NOGRP) { gh = (struct grouphead *) calloc(sizeof *gh, 1); gh->g_name = vcopy(gname); gh->g_list = NOGE; gh->g_link = groups[h]; groups[h] = gh; } /* * Insert names from the command list into the group. * Who cares if there are duplicates? They got tossed * later anyway. */ for (ap = argv+1; *ap != NOSTR; ap++) { gp = (struct group *) calloc(sizeof *gp, 1); gp->ge_name = vcopy(*ap); gp->ge_link = gh->g_list; gh->g_list = gp; } return(0); } /* * Sort the passed string vecotor into ascending dictionary * order. */ sort(list) char **list; { register char **ap; int diction(); for (ap = list; *ap != NOSTR; ap++) ; if (ap-list < 2) return; qsort(list, ap-list, sizeof *list, diction); } /* * Do a dictionary order comparison of the arguments from * qsort. */ diction(a, b) register char **a, **b; { return(strcmp(*a, *b)); } /* * The do nothing command for comments. */ null(e) { return(0); }