+ case CDCMDSW:
+ /* Change the working directory for attachments
+ *
+ * Run the directory through the user's shell so that
+ * we can take advantage of any syntax that the user
+ * is accustomed to. Read back the absolute path.
+ */
+
+ if (*++argp == (char *)0) {
+ (void)sprintf(buf, "$SHELL -c \"cd;pwd\"");
+ }
+ else if (strlen(*argp) >= BUFSIZ) {
+ adios((char *)0, "arguments too long");
+ }
+ else {
+ (void)sprintf(buf, "$SHELL -c \"cd %s;cd %s;pwd\"", cwd, *argp);
+ }
+ if ((f = popen(buf, "r")) != (FILE *)0) {
+ fgets(cwd, sizeof (cwd), f);
+
+ if (strchr(cwd, '\n') != (char *)0)
+ *strchr(cwd, '\n') = '\0';
+
+ pclose(f);
+ }
+ else {
+ advise("popen", "could not get directory");
+ }
+
+ break;
+
+ case PWDCMDSW:
+ /* Print the working directory for attachments */
+ printf("%s\n", cwd);
+ break;
+
+ case LSCMDSW:
+ /* List files in the current attachment working directory
+ *
+ * Use the user's shell so that we can take advantage of any
+ * syntax that the user is accustomed to.
+ */
+
+ cp = buf + sprintf(buf, "$SHELL -c \" cd %s;ls", cwd);
+
+ while (*++argp != (char *)0) {
+ if (cp + strlen(*argp) + 2 >= buf + BUFSIZ)
+ adios((char *)0, "arguments too long");
+
+ cp += sprintf(cp, " %s", *argp);
+ }
+
+ (void)strcat(cp, "\"");
+ (void)system(buf);
+ break;
+
+ case ALISTCMDSW:
+ /*
+ * List attachments on current draft. Options are:
+ *
+ * -l long listing (full path names)
+ * -n numbers listing
+ */
+
+ if (attach == (char *)0) {
+ advise((char *)0, "can't list because no header field name was given.");
+ break;
+ }
+
+ l = (char *)0;
+ n = 0;
+
+ while (*++argp != (char *)0) {
+ if (strcmp(*argp, "-l") == 0)
+ l = "/";
+
+ else if (strcmp(*argp, "-n") == 0)
+ n = 1;
+
+ else if (strcmp(*argp, "-ln") == 0 || strcmp(*argp, "-nl") == 0) {
+ l = "/";
+ n = 1;
+ }
+
+ else {
+ n = -1;
+ break;
+ }
+ }
+
+ if (n == -1)
+ advise((char *)0, "usage is alist [-ln].");
+
+ else
+ annolist(drft, attach, l, n);
+
+ break;
+
+ case ATTACHCMDSW:
+ /*
+ * Attach files to current draft.
+ */
+
+ if (attach == (char *)0) {
+ advise((char *)0, "can't attach because no header field name was given.");
+ break;
+ }
+
+ /*
+ * Build a command line that causes the user's shell to list the file name
+ * arguments. This handles and wildcard expansion, tilde expansion, etc.
+ */
+
+ cp = buf + sprintf(buf, "$SHELL -c \" cd %s;ls", cwd);
+
+ while (*++argp != (char *)0) {
+ if (cp + strlen(*argp) + 3 >= buf + BUFSIZ)
+ adios((char *)0, "arguments too long");
+
+ cp += sprintf(cp, " %s", *argp);
+ }
+
+ (void)strcat(cp, "\"");
+
+ /*
+ * Read back the response from the shell, which contains a number of lines
+ * with one file name per line. Remove off the newline. Determine whether
+ * we have an absolute or relative path name. Prepend the current working
+ * directory to relative path names. Add the attachment annotation to the
+ * draft.
+ */
+
+ if ((f = popen(buf, "r")) != (FILE *)0) {
+ while (fgets(shell, sizeof (shell), f) != (char *)0) {
+ *(strchr(shell, '\n')) = '\0';
+
+ if (*shell == '/')
+ (void)annotate(drft, attach, shell, 1, 0, -1, 1);
+ else {
+ (void)sprintf(file, "%s/%s", cwd, shell);
+ (void)annotate(drft, attach, file, 1, 0, -1, 1);
+ }
+ }
+
+ pclose(f);
+ }
+ else {
+ advise("popen", "could not get file from shell");
+ }
+
+ break;
+
+ case DETACHCMDSW:
+ /*
+ * Detach files from current draft.
+ */
+
+ if (attach == (char *)0) {
+ advise((char *)0, "can't detach because no header field name was given.");
+ break;
+ }
+
+ /*
+ * Scan the arguments for a -n. Mixed file names and numbers aren't allowed,
+ * so this catches a -n anywhere in the argument list.
+ */
+
+ for (n = 0, arguments = argp + 1; *arguments != (char *)0; arguments++) {
+ if (strcmp(*arguments, "-n") == 0) {
+ n = 1;
+ break;
+ }
+ }
+
+ /*
+ * A -n was found so interpret the arguments as attachment numbers.
+ * Decrement any remaining argument number that is greater than the one
+ * just processed after processing each one so that the numbering stays
+ * correct.
+ */
+
+ if (n == 1) {
+ for (arguments = argp + 1; *arguments != (char *)0; arguments++) {
+ if (strcmp(*arguments, "-n") == 0)
+ continue;
+
+ if (**arguments != '\0') {
+ n = atoi(*arguments);
+ (void)annotate(drft, attach, (char *)0, 1, 0, n, 1);
+
+ for (argp = arguments + 1; *argp != (char *)0; argp++) {
+ if (atoi(*argp) > n) {
+ if (atoi(*argp) == 1)
+ *argp = "";
+ else
+ (void)sprintf(*argp, "%d", atoi(*argp) - 1);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * The arguments are interpreted as file names. Run them through the
+ * user's shell for wildcard expansion and other goodies. Do this from
+ * the current working directory if the argument is not an absolute path
+ * name (does not begin with a /).
+ */
+
+ else {
+ for (arguments = argp + 1; *arguments != (char *)0; arguments++) {
+ if (**arguments == '/') {
+ if (strlen(*arguments) + sizeof ("$SHELL -c \"ls \"") >= sizeof (buf))
+ adios((char *)0, "arguments too long");
+
+ (void)sprintf(buf, "$SHELL -c \"ls %s\"", *arguments);
+ }
+ else {
+ if (strlen(cwd) + strlen(*arguments) + sizeof ("$SHELL -c \" cd ; ls \"") >= sizeof (buf))
+ adios((char *)0, "arguments too long");
+
+ (void)sprintf(buf, "$SHELL -c \" cd %s;ls %s\"", cwd, *arguments);
+ }
+
+ if ((f = popen(buf, "r")) != (FILE *)0) {
+ while (fgets(shell, sizeof (cwd), f) != (char *)0) {
+ *(strchr(shell, '\n')) = '\0';
+ (void)annotate(drft, attach, shell, 1, 0, 0, 1);
+ }
+
+ pclose(f);
+ }
+ else {
+ advise("popen", "could not get file from shell");
+ }
+ }
+ }
+
+ break;
+
+ default: