1*6c4efebfSray /* $OpenBSD: sendbug.c,v 1.36 2007/04/06 03:24:08 ray Exp $ */ 25ae6585fSray 35ae6585fSray /* 45ae6585fSray * Written by Ray Lai <ray@cyth.net>. 55ae6585fSray * Public domain. 65ae6585fSray */ 75ae6585fSray 85ae6585fSray #include <sys/types.h> 95ae6585fSray #include <sys/mman.h> 105ae6585fSray #include <sys/param.h> 115ae6585fSray #include <sys/stat.h> 125ae6585fSray #include <sys/sysctl.h> 135ae6585fSray #include <sys/wait.h> 145ae6585fSray 1549d07c37Sray #include <ctype.h> 165ae6585fSray #include <err.h> 175ae6585fSray #include <errno.h> 185ae6585fSray #include <fcntl.h> 195ae6585fSray #include <limits.h> 205ae6585fSray #include <paths.h> 215ae6585fSray #include <pwd.h> 224b9386a8Sderaadt #include <signal.h> 235ae6585fSray #include <stdio.h> 245ae6585fSray #include <stdlib.h> 255ae6585fSray #include <string.h> 265ae6585fSray #include <unistd.h> 275ae6585fSray 285ae6585fSray #include "atomicio.h" 295ae6585fSray 307d2774c0Sray #define _PATH_DMESG "/var/run/dmesg.boot" 317d2774c0Sray 32*6c4efebfSray void dmesg(FILE *); 334b9386a8Sderaadt int editit(char *); 34b2e65daaStedu void init(void); 355ae6585fSray int prompt(void); 360690c094Sray int send_file(const char *, int); 375ae6585fSray int sendmail(const char *); 385ae6585fSray void template(FILE *); 395ae6585fSray 405ae6585fSray const char *categories = "system user library documentation ports kernel " 415ae6585fSray "alpha amd64 arm i386 m68k m88k mips ppc sgi sparc sparc64 vax"; 42823e89efSderaadt char *version = "4.2"; 43823e89efSderaadt 44823e89efSderaadt struct passwd *pw; 45e051e8faSderaadt char os[BUFSIZ], rel[BUFSIZ], mach[BUFSIZ], details[BUFSIZ]; 466b1a1e2aSderaadt char *fullname, *tmppath; 47b2e65daaStedu int wantcleanup; 48823e89efSderaadt 49b2e65daaStedu __dead void 50903e61cbSderaadt usage(void) 51903e61cbSderaadt { 527d2774c0Sray fprintf(stderr, "usage: sendbug [-DLPV]\n"); 53b2e65daaStedu exit(1); 54903e61cbSderaadt } 55903e61cbSderaadt 56b2e65daaStedu void 57b2e65daaStedu cleanup() 58b2e65daaStedu { 59b2e65daaStedu if (wantcleanup && tmppath && unlink(tmppath) == -1) 60b2e65daaStedu warn("unlink"); 61b2e65daaStedu } 62b2e65daaStedu 63b2e65daaStedu 645ae6585fSray int 655ae6585fSray main(int argc, char *argv[]) 665ae6585fSray { 677d2774c0Sray int ch, c, Dflag = 0, fd, ret = 1; 68f4348cb9Sderaadt const char *tmpdir; 6970dfcc75Sderaadt struct stat sb; 70f4348cb9Sderaadt char *pr_form; 7170dfcc75Sderaadt time_t mtime; 7270dfcc75Sderaadt FILE *fp; 735ae6585fSray 747d2774c0Sray while ((ch = getopt(argc, argv, "DLPV")) != -1) 75903e61cbSderaadt switch (ch) { 767d2774c0Sray case 'D': 777d2774c0Sray Dflag = 1; 787d2774c0Sray break; 79903e61cbSderaadt case 'L': 80903e61cbSderaadt printf("Known categories:\n"); 81903e61cbSderaadt printf("%s\n\n", categories); 82903e61cbSderaadt exit(0); 83903e61cbSderaadt case 'P': 84b2e65daaStedu init(); 85903e61cbSderaadt template(stdout); 86903e61cbSderaadt exit(0); 875711e205Sderaadt case 'V': 885711e205Sderaadt printf("%s\n", version); 895711e205Sderaadt exit(0); 90903e61cbSderaadt default: 91903e61cbSderaadt usage(); 92903e61cbSderaadt } 937d2774c0Sray argc -= optind; 947d2774c0Sray argv += optind; 95903e61cbSderaadt 967d2774c0Sray if (argc > 1) 97903e61cbSderaadt usage(); 98903e61cbSderaadt 995ae6585fSray if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0') 1005ae6585fSray tmpdir = _PATH_TMP; 101795a8b97Sray if (asprintf(&tmppath, "%s%sp.XXXXXXXXXX", tmpdir, 102f4348cb9Sderaadt tmpdir[strlen(tmpdir) - 1] == '/' ? "" : "/") == -1) 103b2e65daaStedu err(1, "asprintf"); 1045ae6585fSray if ((fd = mkstemp(tmppath)) == -1) 1055ae6585fSray err(1, "mkstemp"); 106b2e65daaStedu wantcleanup = 1; 107b2e65daaStedu atexit(cleanup); 108f4348cb9Sderaadt if ((fp = fdopen(fd, "w+")) == NULL) 109b2e65daaStedu err(1, "fdopen"); 1105ae6585fSray 111b2e65daaStedu init(); 1125ae6585fSray 1134ff3398aSderaadt pr_form = getenv("PR_FORM"); 1144ff3398aSderaadt if (pr_form) { 1154ff3398aSderaadt char buf[BUFSIZ]; 1164ff3398aSderaadt size_t len; 1174ff3398aSderaadt FILE *frfp; 1184ff3398aSderaadt 1194ff3398aSderaadt frfp = fopen(pr_form, "r"); 1204ff3398aSderaadt if (frfp == NULL) { 1214ff3398aSderaadt fprintf(stderr, "sendbug: can't seem to read your" 1224ff3398aSderaadt " template file (`%s'), ignoring PR_FORM\n", 1234ff3398aSderaadt pr_form); 1244ff3398aSderaadt template(fp); 1254ff3398aSderaadt } else { 1264ff3398aSderaadt while (!feof(frfp)) { 1274ff3398aSderaadt len = fread(buf, 1, sizeof buf, frfp); 1284ff3398aSderaadt if (len == 0) 1294ff3398aSderaadt break; 1304ff3398aSderaadt if (fwrite(buf, 1, len, fp) != len) 1314ff3398aSderaadt break; 1324ff3398aSderaadt } 1334ff3398aSderaadt fclose(frfp); 1344ff3398aSderaadt } 1357d2774c0Sray } else { 1365ae6585fSray template(fp); 137*6c4efebfSray if (!Dflag) 138*6c4efebfSray dmesg(fp); 1397d2774c0Sray } 1405ae6585fSray 141f4348cb9Sderaadt if (fflush(fp) == EOF || fstat(fd, &sb) == -1 || fclose(fp) == EOF) 142b2e65daaStedu err(1, "error creating template"); 1435ae6585fSray mtime = sb.st_mtime; 1445ae6585fSray 1455ae6585fSray edit: 146648f0ffcSray if (editit(tmppath) == -1 && errno != ECHILD) 147648f0ffcSray err(1, "error running editor"); 1485ae6585fSray 149f4348cb9Sderaadt if (stat(tmppath, &sb) == -1) 150b2e65daaStedu err(1, "stat"); 151f4348cb9Sderaadt if (mtime == sb.st_mtime) 152b2e65daaStedu errx(1, "report unchanged, nothing sent"); 1535ae6585fSray 1545ae6585fSray prompt: 1555ae6585fSray c = prompt(); 1565ae6585fSray switch (c) { 1575711e205Sderaadt case 'a': 1585711e205Sderaadt case EOF: 159b2e65daaStedu wantcleanup = 0; 160b2e65daaStedu errx(1, "unsent report in %s", tmppath); 1615ae6585fSray case 'e': 1625ae6585fSray goto edit; 1635ae6585fSray case 's': 1645ae6585fSray if (sendmail(tmppath) == -1) 1655ae6585fSray goto quit; 1665ae6585fSray break; 1675ae6585fSray default: 1685ae6585fSray goto prompt; 1695ae6585fSray } 1705ae6585fSray 1715ae6585fSray ret = 0; 1725ae6585fSray quit: 1735ae6585fSray return (ret); 1745ae6585fSray } 1755ae6585fSray 176*6c4efebfSray void 177*6c4efebfSray dmesg(FILE *fp) 178*6c4efebfSray { 179*6c4efebfSray char buf[BUFSIZ]; 180*6c4efebfSray FILE *dfp; 181*6c4efebfSray off_t offset = -1; 182*6c4efebfSray 183*6c4efebfSray dfp = fopen(_PATH_DMESG, "r"); 184*6c4efebfSray if (dfp == NULL) { 185*6c4efebfSray warn("can't read dmesg"); 186*6c4efebfSray return; 187*6c4efebfSray } 188*6c4efebfSray 189*6c4efebfSray fputs("\n" 190*6c4efebfSray "<dmesg is attached.>\n" 191*6c4efebfSray "<Feel free to delete or use the -D flag if it contains " 192*6c4efebfSray "sensitive information.>\n", fp); 193*6c4efebfSray /* Find last line starting with "OpenBSD". */ 194*6c4efebfSray for (;;) { 195*6c4efebfSray off_t o; 196*6c4efebfSray 197*6c4efebfSray o = ftello(dfp); 198*6c4efebfSray if (fgets(buf, sizeof(buf), dfp) == NULL) 199*6c4efebfSray break; 200*6c4efebfSray if (!strncmp("OpenBSD ", buf, sizeof("OpenBSD ") - 1)) 201*6c4efebfSray offset = o; 202*6c4efebfSray } 203*6c4efebfSray if (offset != -1) { 204*6c4efebfSray size_t len; 205*6c4efebfSray 206*6c4efebfSray clearerr(dfp); 207*6c4efebfSray fseeko(dfp, offset, SEEK_SET); 208*6c4efebfSray while (offset != -1 && !feof(dfp)) { 209*6c4efebfSray len = fread(buf, 1, sizeof buf, dfp); 210*6c4efebfSray if (len == 0) 211*6c4efebfSray break; 212*6c4efebfSray if (fwrite(buf, 1, len, fp) != len) 213*6c4efebfSray break; 214*6c4efebfSray } 215*6c4efebfSray } 216*6c4efebfSray fclose(dfp); 217*6c4efebfSray } 218*6c4efebfSray 2194b9386a8Sderaadt int 2204b9386a8Sderaadt editit(char *tmpfile) 2214b9386a8Sderaadt { 222f4348cb9Sderaadt char *argp[] = {"sh", "-c", NULL, NULL}, *ed, *p; 2238ec2d82eSray sig_t sighup, sigint, sigquit; 2244b9386a8Sderaadt pid_t pid, xpid; 2256b1a1e2aSderaadt int st; 2264b9386a8Sderaadt 227c8a426adSray ed = getenv("VISUAL"); 228c8a426adSray if (ed == NULL || ed[0] == '\0') 229c8a426adSray ed = getenv("EDITOR"); 230c8a426adSray if (ed == NULL || ed[0] == '\0') 2314b9386a8Sderaadt ed = _PATH_VI; 2324b9386a8Sderaadt if (asprintf(&p, "%s %s", ed, tmpfile) == -1) 2338af53ff7Sray return (-1); 2344b9386a8Sderaadt argp[2] = p; 2354b9386a8Sderaadt 2364b9386a8Sderaadt top: 2378ec2d82eSray sighup = signal(SIGHUP, SIG_IGN); 2388ec2d82eSray sigint = signal(SIGINT, SIG_IGN); 2398ec2d82eSray sigquit = signal(SIGQUIT, SIG_IGN); 2407132776cSray if ((pid = fork()) == -1) { 2413c361d1bSray int saved_errno = errno; 2423c361d1bSray 2438ec2d82eSray (void)signal(SIGHUP, sighup); 2448ec2d82eSray (void)signal(SIGINT, sigint); 2458ec2d82eSray (void)signal(SIGQUIT, sigquit); 2463c361d1bSray if (saved_errno == EAGAIN) { 2474b9386a8Sderaadt sleep(1); 2484b9386a8Sderaadt goto top; 2494b9386a8Sderaadt } 2504b9386a8Sderaadt free(p); 2512bba59c0Sray errno = saved_errno; 2528af53ff7Sray return (-1); 2534b9386a8Sderaadt } 2544b9386a8Sderaadt if (pid == 0) { 2554b9386a8Sderaadt execv(_PATH_BSHELL, argp); 2564b9386a8Sderaadt _exit(127); 2574b9386a8Sderaadt } 2584b9386a8Sderaadt free(p); 2594b9386a8Sderaadt for (;;) { 260ecdc3c8bSray xpid = waitpid(pid, &st, WUNTRACED); 2616b1a1e2aSderaadt if (xpid == -1) { 2622bba59c0Sray if (errno != EINTR) 2636b1a1e2aSderaadt return (-1); 2646b1a1e2aSderaadt } else if (WIFSTOPPED(st)) 2656b1a1e2aSderaadt raise(WSTOPSIG(st)); 266f27d80daSray else 2674b9386a8Sderaadt break; 2684b9386a8Sderaadt } 2698ec2d82eSray (void)signal(SIGHUP, sighup); 2708ec2d82eSray (void)signal(SIGINT, sigint); 2718ec2d82eSray (void)signal(SIGQUIT, sigquit); 2722bba59c0Sray if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) { 2732bba59c0Sray errno = ECHILD; 2748af53ff7Sray return (-1); 2752bba59c0Sray } 2764b9386a8Sderaadt return (0); 2774b9386a8Sderaadt } 278b2e65daaStedu 2795ae6585fSray int 2805ae6585fSray prompt(void) 2815ae6585fSray { 2825ae6585fSray int c, ret; 2835ae6585fSray 2845ae6585fSray fpurge(stdin); 2855ae6585fSray fprintf(stderr, "a)bort, e)dit, or s)end: "); 2865ae6585fSray fflush(stderr); 2875ae6585fSray ret = getchar(); 2885ae6585fSray if (ret == EOF || ret == '\n') 2895ae6585fSray return (ret); 2905ae6585fSray do { 2915ae6585fSray c = getchar(); 2925ae6585fSray } while (c != EOF && c != '\n'); 2935ae6585fSray return (ret); 2945ae6585fSray } 2955ae6585fSray 2965ae6585fSray int 2975ae6585fSray sendmail(const char *tmppath) 2985ae6585fSray { 2995ae6585fSray int filedes[2]; 3005ae6585fSray 3015ae6585fSray if (pipe(filedes) == -1) { 3025ae6585fSray warn("pipe: unsent report in %s", tmppath); 3035ae6585fSray return (-1); 3045ae6585fSray } 3055ae6585fSray switch (fork()) { 3065ae6585fSray case -1: 3075ae6585fSray warn("fork error: unsent report in %s", 3085ae6585fSray tmppath); 3095ae6585fSray return (-1); 3105ae6585fSray case 0: 3115ae6585fSray close(filedes[1]); 3125ae6585fSray if (dup2(filedes[0], STDIN_FILENO) == -1) { 3135ae6585fSray warn("dup2 error: unsent report in %s", 3145ae6585fSray tmppath); 3155ae6585fSray return (-1); 3165ae6585fSray } 3175ae6585fSray close(filedes[0]); 3185ae6585fSray execl("/usr/sbin/sendmail", "sendmail", 31970dfcc75Sderaadt "-oi", "-t", (void *)NULL); 3205ae6585fSray warn("sendmail error: unsent report in %s", 3215ae6585fSray tmppath); 3225ae6585fSray return (-1); 3235ae6585fSray default: 3245ae6585fSray close(filedes[0]); 3255ae6585fSray /* Pipe into sendmail. */ 3265ae6585fSray if (send_file(tmppath, filedes[1]) == -1) { 3275ae6585fSray warn("send_file error: unsent report in %s", 3285ae6585fSray tmppath); 3295ae6585fSray return (-1); 3305ae6585fSray } 3315ae6585fSray close(filedes[1]); 3325ae6585fSray wait(NULL); 3335ae6585fSray break; 3345ae6585fSray } 3355ae6585fSray return (0); 3365ae6585fSray } 3375ae6585fSray 338b2e65daaStedu void 3395ae6585fSray init(void) 3405ae6585fSray { 341b088fbb0Sray size_t amp, len, gecoslen, namelen; 342f4348cb9Sderaadt int sysname[2]; 343b088fbb0Sray char ch, *cp; 3445ae6585fSray 345f4348cb9Sderaadt if ((pw = getpwuid(getuid())) == NULL) 346b2e65daaStedu err(1, "getpwuid"); 34749d07c37Sray namelen = strlen(pw->pw_name); 3485ae6585fSray 3499a66796cSmoritz /* Count number of '&'. */ 350b088fbb0Sray for (amp = 0, cp = pw->pw_gecos; *cp && *cp != ','; ++cp) 351b088fbb0Sray if (*cp == '&') 3529a66796cSmoritz ++amp; 353b088fbb0Sray 354b088fbb0Sray /* Truncate gecos to full name. */ 355b088fbb0Sray gecoslen = cp - pw->pw_gecos; 356b088fbb0Sray pw->pw_gecos[gecoslen] = '\0'; 357b088fbb0Sray 3589a66796cSmoritz /* Expanded str = orig str - '&' chars + concatenated logins. */ 359b088fbb0Sray len = gecoslen - amp + (amp * namelen) + 1; 360b088fbb0Sray if ((fullname = malloc(len)) == NULL) 361b2e65daaStedu err(1, "malloc"); 362f4348cb9Sderaadt 363b088fbb0Sray /* Upper case first char of login. */ 364b088fbb0Sray ch = pw->pw_name[0]; 365b088fbb0Sray pw->pw_name[0] = toupper((unsigned char)pw->pw_name[0]); 366b088fbb0Sray 367b088fbb0Sray cp = pw->pw_gecos; 368b088fbb0Sray fullname[0] = '\0'; 369b088fbb0Sray while (cp != NULL) { 370b088fbb0Sray char *token; 371b088fbb0Sray 372b088fbb0Sray token = strsep(&cp, "&"); 373b088fbb0Sray if (token != pw->pw_gecos && 374b088fbb0Sray strlcat(fullname, pw->pw_name, len) >= len) 375b088fbb0Sray errx(1, "truncated string"); 376b088fbb0Sray if (strlcat(fullname, token, len) >= len) 377b088fbb0Sray errx(1, "truncated string"); 37849d07c37Sray } 379b088fbb0Sray /* Restore case of first char of login. */ 380b088fbb0Sray pw->pw_name[0] = ch; 3815ae6585fSray 3825ae6585fSray sysname[0] = CTL_KERN; 3835ae6585fSray sysname[1] = KERN_OSTYPE; 3845ae6585fSray len = sizeof(os) - 1; 385f4348cb9Sderaadt if (sysctl(sysname, 2, &os, &len, NULL, 0) == -1) 386b2e65daaStedu err(1, "sysctl"); 3875ae6585fSray 3885ae6585fSray sysname[0] = CTL_KERN; 3895ae6585fSray sysname[1] = KERN_OSRELEASE; 3905ae6585fSray len = sizeof(rel) - 1; 391f4348cb9Sderaadt if (sysctl(sysname, 2, &rel, &len, NULL, 0) == -1) 392b2e65daaStedu err(1, "sysctl"); 3935ae6585fSray 394e051e8faSderaadt sysname[0] = CTL_KERN; 395e051e8faSderaadt sysname[1] = KERN_VERSION; 396e051e8faSderaadt len = sizeof(details) - 1; 397f4348cb9Sderaadt if (sysctl(sysname, 2, &details, &len, NULL, 0) == -1) 398e051e8faSderaadt err(1, "sysctl"); 399e051e8faSderaadt 400e051e8faSderaadt cp = strchr(details, '\n'); 401e051e8faSderaadt if (cp) { 402e051e8faSderaadt cp++; 403e051e8faSderaadt if (*cp) 404e051e8faSderaadt *cp++ = '\t'; 405e051e8faSderaadt if (*cp) 406e051e8faSderaadt *cp++ = '\t'; 407e051e8faSderaadt if (*cp) 408e051e8faSderaadt *cp++ = '\t'; 409e051e8faSderaadt } 410e051e8faSderaadt 4115ae6585fSray sysname[0] = CTL_HW; 4125ae6585fSray sysname[1] = HW_MACHINE; 4135ae6585fSray len = sizeof(mach) - 1; 414f4348cb9Sderaadt if (sysctl(sysname, 2, &mach, &len, NULL, 0) == -1) 415b2e65daaStedu err(1, "sysctl"); 4165ae6585fSray } 4175ae6585fSray 4185ae6585fSray int 4195ae6585fSray send_file(const char *file, int dst) 4205ae6585fSray { 4215ae6585fSray int blank = 0; 42270dfcc75Sderaadt size_t len; 42370dfcc75Sderaadt char *buf; 42470dfcc75Sderaadt FILE *fp; 4255ae6585fSray 4265ae6585fSray if ((fp = fopen(file, "r")) == NULL) 4275ae6585fSray return (-1); 4285ae6585fSray while ((buf = fgetln(fp, &len))) { 4295ae6585fSray /* Skip lines starting with "SENDBUG". */ 4305ae6585fSray if (len >= sizeof("SENDBUG") - 1 && 4315ae6585fSray memcmp(buf, "SENDBUG", sizeof("SENDBUG") - 1) == 0) 4325ae6585fSray continue; 4335ae6585fSray if (len == 1 && buf[0] == '\n') 4345ae6585fSray blank = 1; 4355ae6585fSray /* Skip comments, but only if we encountered a blank line. */ 4365ae6585fSray while (len) { 437e051e8faSderaadt char *sp = NULL, *ep = NULL; 4385ae6585fSray size_t copylen; 4395ae6585fSray 4405ae6585fSray if (blank && (sp = memchr(buf, '<', len)) != NULL) 4415ae6585fSray ep = memchr(sp, '>', len - (sp - buf + 1)); 4425ae6585fSray /* Length of string before comment. */ 4438cf86b71Sray if (ep) 4448cf86b71Sray copylen = sp - buf; 4458cf86b71Sray else 4468cf86b71Sray copylen = len; 4475ae6585fSray if (atomicio(vwrite, dst, buf, copylen) != copylen) { 4485ae6585fSray int saved_errno = errno; 4495ae6585fSray 4505ae6585fSray fclose(fp); 4515ae6585fSray errno = saved_errno; 4525ae6585fSray return (-1); 4535ae6585fSray } 4545ae6585fSray if (!ep) 4555ae6585fSray break; 4565ae6585fSray /* Skip comment. */ 4575ae6585fSray len -= ep - buf + 1; 4585ae6585fSray buf = ep + 1; 4595ae6585fSray } 4605ae6585fSray } 4615ae6585fSray fclose(fp); 4625ae6585fSray return (0); 4635ae6585fSray } 4645ae6585fSray 4655ae6585fSray void 4665ae6585fSray template(FILE *fp) 4675ae6585fSray { 4685ae6585fSray fprintf(fp, "SENDBUG: -*- sendbug -*-\n"); 469f4348cb9Sderaadt fprintf(fp, "SENDBUG: Lines starting with `SENDBUG' will" 470f4348cb9Sderaadt " be removed automatically, as\n"); 4715ae6585fSray fprintf(fp, "SENDBUG: will all comments (text enclosed in `<' and `>').\n"); 4725ae6585fSray fprintf(fp, "SENDBUG:\n"); 4735ae6585fSray fprintf(fp, "SENDBUG: Choose from the following categories:\n"); 4745ae6585fSray fprintf(fp, "SENDBUG:\n"); 4755ae6585fSray fprintf(fp, "SENDBUG: %s\n", categories); 4765ae6585fSray fprintf(fp, "SENDBUG:\n"); 4775ae6585fSray fprintf(fp, "SENDBUG:\n"); 4785ae6585fSray fprintf(fp, "To: %s\n", "gnats@openbsd.org"); 4795ae6585fSray fprintf(fp, "Subject: \n"); 4805ae6585fSray fprintf(fp, "From: %s\n", pw->pw_name); 481d23b3302Sray fprintf(fp, "Cc: %s\n", pw->pw_name); 4825ae6585fSray fprintf(fp, "Reply-To: %s\n", pw->pw_name); 4835711e205Sderaadt fprintf(fp, "X-sendbug-version: %s\n", version); 4845ae6585fSray fprintf(fp, "\n"); 4855ae6585fSray fprintf(fp, "\n"); 4865ae6585fSray fprintf(fp, ">Submitter-Id:\tnet\n"); 4875ae6585fSray fprintf(fp, ">Originator:\t%s\n", fullname); 4885ae6585fSray fprintf(fp, ">Organization:\n"); 4895ae6585fSray fprintf(fp, "net\n"); 4905ae6585fSray fprintf(fp, ">Synopsis:\t<synopsis of the problem (one line)>\n"); 491f4348cb9Sderaadt fprintf(fp, ">Severity:\t" 492f4348cb9Sderaadt "<[ non-critical | serious | critical ] (one line)>\n"); 4935ae6585fSray fprintf(fp, ">Priority:\t<[ low | medium | high ] (one line)>\n"); 4945ae6585fSray fprintf(fp, ">Category:\t<PR category (one line)>\n"); 495f4348cb9Sderaadt fprintf(fp, ">Class:\t\t" 496f4348cb9Sderaadt "<[ sw-bug | doc-bug | change-request | support ] (one line)>\n"); 4975ae6585fSray fprintf(fp, ">Release:\t<release number or tag (one line)>\n"); 4985ae6585fSray fprintf(fp, ">Environment:\n"); 4995ae6585fSray fprintf(fp, "\t<machine, os, target, libraries (multiple lines)>\n"); 5005ae6585fSray fprintf(fp, "\tSystem : %s %s\n", os, rel); 501e051e8faSderaadt fprintf(fp, "\tDetails : %s\n", details); 5025ae6585fSray fprintf(fp, "\tArchitecture: %s.%s\n", os, mach); 5035ae6585fSray fprintf(fp, "\tMachine : %s\n", mach); 5045ae6585fSray fprintf(fp, ">Description:\n"); 5055ae6585fSray fprintf(fp, "\t<precise description of the problem (multiple lines)>\n"); 5065ae6585fSray fprintf(fp, ">How-To-Repeat:\n"); 507f4348cb9Sderaadt fprintf(fp, "\t<code/input/activities to reproduce the problem" 508f4348cb9Sderaadt " (multiple lines)>\n"); 5095ae6585fSray fprintf(fp, ">Fix:\n"); 510f4348cb9Sderaadt fprintf(fp, "\t<how to correct or work around the problem," 511f4348cb9Sderaadt " if known (multiple lines)>\n"); 5125ae6585fSray } 513