1 # 2 3 #include "rcv.h" 4 #include <sys/stat.h> 5 6 /* 7 * Mail -- a mail program 8 * 9 * More user commands. 10 */ 11 12 static char *SccsId = "@(#)cmd2.c 1.1 10/08/80"; 13 14 /* 15 * If any arguments were given, go to the next applicable argument 16 * following dot, otherwise, go to the next applicable message. 17 * If given as first command with no arguments, print first message. 18 */ 19 20 next(msgvec) 21 int *msgvec; 22 { 23 register struct message *mp; 24 register int *ip, *ip2; 25 int list[2], mdot; 26 27 if (*msgvec != NULL) { 28 29 /* 30 * If some messages were supplied, find the 31 * first applicable one following dot using 32 * wrap around. 33 */ 34 35 mdot = dot - &message[0] + 1; 36 for (ip = msgvec; *ip != NULL; ip++) 37 if (*ip > mdot) 38 break; 39 if (*ip == NULL) 40 ip = msgvec; 41 ip2 = ip; 42 do { 43 if (*ip2 != NULL) 44 ip2++; 45 if (*ip2 == NULL) 46 ip2 = msgvec; 47 mp = &message[*ip2 - 1]; 48 if ((mp->m_flag & MDELETED) == 0) { 49 dot = mp; 50 goto hitit; 51 } 52 } while (ip2 != ip); 53 printf("No messages applicable\n"); 54 return(1); 55 } 56 57 /* 58 * If this is the first command, select message 1. 59 * Note that this must exist for us to get here at all. 60 */ 61 62 if (!sawcom) { 63 dot = &message[0]; 64 goto hitit; 65 } 66 67 /* 68 * Just find the next good message after dot, no 69 * wraparound. 70 */ 71 72 for (mp = dot+1; mp < &message[msgCount]; mp++) 73 if ((mp->m_flag & (MDELETED|MSAVED)) == 0) 74 break; 75 if (mp >= &message[msgCount]) { 76 printf("At EOF\n"); 77 return(0); 78 } 79 dot = mp; 80 hitit: 81 /* 82 * Print dot. 83 */ 84 85 list[0] = dot - &message[0] + 1; 86 list[1] = NULL; 87 return(type(list)); 88 } 89 90 /* 91 * Save the indicated messages at the end of the passed file name. 92 */ 93 94 save(str) 95 char str[]; 96 { 97 register int *ip, mesg; 98 register struct message *mp; 99 char *file, *disp; 100 int f, *msgvec, lc, cc, t; 101 FILE *obuf; 102 struct stat statb; 103 104 msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 105 if ((file = snarf(str, &f)) == NOSTR) 106 return(1); 107 if (!f) { 108 *msgvec = first(0, MMNORM); 109 if (*msgvec == NULL) { 110 printf("No messages to save.\n"); 111 return(1); 112 } 113 msgvec[1] = NULL; 114 } 115 if (f && getmsglist(str, msgvec, 0) < 0) 116 return(1); 117 if ((file = expand(file)) == NOSTR) 118 return(1); 119 printf("\"%s\" ", file); 120 flush(); 121 if (stat(file, &statb) >= 0) 122 disp = "[Appended]"; 123 else 124 disp = "[New file]"; 125 if ((obuf = fopen(file, "a")) == NULL) { 126 perror(NOSTR); 127 return(1); 128 } 129 cc = lc = 0; 130 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 131 mesg = *ip; 132 touch(mesg); 133 mp = &message[mesg-1]; 134 if ((t = send(mp, obuf)) < 0) { 135 perror(file); 136 fclose(obuf); 137 return(1); 138 } 139 lc += t; 140 cc += msize(mp); 141 mp->m_flag |= MSAVED; 142 } 143 fflush(obuf); 144 if (ferror(obuf)) 145 perror(file); 146 fclose(obuf); 147 printf("%s %d/%d\n", disp, lc, cc); 148 return(0); 149 } 150 151 /* 152 * Write the indicated messages at the end of the passed 153 * file name, minus header and trailing blank line. 154 */ 155 156 swrite(str) 157 char str[]; 158 { 159 register int *ip, mesg; 160 register struct message *mp; 161 register char *file, *disp; 162 char linebuf[BUFSIZ]; 163 int f, *msgvec, lc, cc, t; 164 FILE *obuf, *mesf; 165 struct stat statb; 166 167 msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 168 if ((file = snarf(str, &f)) == NOSTR) 169 return(1); 170 if ((file = expand(file)) == NOSTR) 171 return(1); 172 if (!f) { 173 *msgvec = first(0, MMNORM); 174 if (*msgvec == NULL) { 175 printf("No messages to write.\n"); 176 return(1); 177 } 178 msgvec[1] = NULL; 179 } 180 if (f && getmsglist(str, msgvec, 0) < 0) 181 return(1); 182 printf("\"%s\" ", file); 183 flush(); 184 if (stat(file, &statb) >= 0) 185 disp = "[Appended]"; 186 else 187 disp = "[New file]"; 188 if ((obuf = fopen(file, "a")) == NULL) { 189 perror(NOSTR); 190 return(1); 191 } 192 cc = lc = 0; 193 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 194 mesg = *ip; 195 touch(mesg); 196 mp = &message[mesg-1]; 197 mesf = setinput(mp); 198 t = mp->m_lines - 2; 199 readline(mesf, linebuf); 200 while (t-- > 0) { 201 fgets(linebuf, BUFSIZ, mesf); 202 fputs(linebuf, obuf); 203 cc += strlen(linebuf); 204 } 205 lc += mp->m_lines - 2; 206 mp->m_flag |= MSAVED; 207 } 208 fflush(obuf); 209 if (ferror(obuf)) 210 perror(file); 211 fclose(obuf); 212 printf("%s %d/%d\n", disp, lc, cc); 213 return(0); 214 } 215 216 /* 217 * Snarf the file from the end of the command line and 218 * return a pointer to it. If there is no file attached, 219 * just return NOSTR. Put a null in front of the file 220 * name so that the message list processing won't see it, 221 * unless the file name is the only thing on the line, in 222 * which case, return 0 in the reference flag variable. 223 */ 224 225 char * 226 snarf(linebuf, flag) 227 char linebuf[]; 228 int *flag; 229 { 230 register char *cp; 231 232 *flag = 1; 233 cp = strlen(linebuf) + linebuf - 1; 234 235 /* 236 * Strip away trailing blanks. 237 */ 238 239 while (*cp == ' ' && cp > linebuf) 240 cp--; 241 *++cp = 0; 242 243 /* 244 * Now search for the beginning of the file name. 245 */ 246 247 while (cp > linebuf && !any(*cp, "\t ")) 248 cp--; 249 if (*cp == '\0') { 250 printf("No file specified.\n"); 251 return(NOSTR); 252 } 253 if (any(*cp, " \t")) 254 *cp++ = 0; 255 else 256 *flag = 0; 257 return(cp); 258 } 259 260 /* 261 * Delete messages. 262 */ 263 264 delete(msgvec) 265 int msgvec[]; 266 { 267 return(delm(msgvec)); 268 } 269 270 /* 271 * Delete messages, then type the new dot. 272 */ 273 274 deltype(msgvec) 275 int msgvec[]; 276 { 277 int list[2]; 278 279 if (delm(msgvec) >= 0) { 280 list[0] = dot - &message[0]; 281 list[0]++; 282 touch(list[0]); 283 list[1] = NULL; 284 return(type(list)); 285 } 286 else { 287 printf("No more messages\n"); 288 return(0); 289 } 290 } 291 292 /* 293 * Delete the indicated messages. 294 * Set dot to some nice place afterwards. 295 * Internal interface. 296 */ 297 298 delm(msgvec) 299 int *msgvec; 300 { 301 register struct message *mp; 302 register *ip, mesg; 303 int last; 304 305 last = NULL; 306 for (ip = msgvec; *ip != NULL; ip++) { 307 mesg = *ip; 308 touch(mesg); 309 mp = &message[mesg-1]; 310 mp->m_flag |= MDELETED; 311 mp->m_flag &= ~(MPRESERVE|MSAVED); 312 last = mesg; 313 } 314 if (last != NULL) { 315 dot = &message[last-1]; 316 last = first(0, MDELETED); 317 if (last != NULL) { 318 dot = &message[last-1]; 319 return(0); 320 } 321 else { 322 dot = &message[0]; 323 return(-1); 324 } 325 } 326 327 /* 328 * Following can't happen -- it keeps lint happy 329 */ 330 331 return(-1); 332 } 333 334 /* 335 * Undelete the indicated messages. 336 */ 337 338 undelete(msgvec) 339 int *msgvec; 340 { 341 register struct message *mp; 342 register *ip, mesg; 343 344 for (ip = msgvec; ip-msgvec < msgCount; ip++) { 345 mesg = *ip; 346 if (mesg == 0) 347 return; 348 touch(mesg); 349 mp = &message[mesg-1]; 350 dot = mp; 351 mp->m_flag &= ~MDELETED; 352 } 353 } 354 355 /* 356 * Interactively dump core on "core" 357 */ 358 359 core() 360 { 361 register int pid; 362 int status; 363 364 if ((pid = vfork()) == -1) { 365 perror("fork"); 366 return(1); 367 } 368 if (pid == 0) { 369 abort(); 370 _exit(1); 371 } 372 printf("Okie dokie"); 373 fflush(stdout); 374 while (wait(&status) != pid) 375 ; 376 if (status & 0200) 377 printf(" -- Core dumped\n"); 378 else 379 printf("\n"); 380 } 381