xref: /aosp_15_r20/external/libcups/notifier/mailto.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * "mailto" notifier for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2007-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 1997-2005 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker  * information.
9*5e7646d2SAndroid Build Coastguard Worker  */
10*5e7646d2SAndroid Build Coastguard Worker 
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker  */
14*5e7646d2SAndroid Build Coastguard Worker 
15*5e7646d2SAndroid Build Coastguard Worker #include <cups/cups-private.h>
16*5e7646d2SAndroid Build Coastguard Worker #include <sys/wait.h>
17*5e7646d2SAndroid Build Coastguard Worker #include <signal.h>
18*5e7646d2SAndroid Build Coastguard Worker 
19*5e7646d2SAndroid Build Coastguard Worker 
20*5e7646d2SAndroid Build Coastguard Worker /*
21*5e7646d2SAndroid Build Coastguard Worker  * Globals...
22*5e7646d2SAndroid Build Coastguard Worker  */
23*5e7646d2SAndroid Build Coastguard Worker 
24*5e7646d2SAndroid Build Coastguard Worker char	mailtoCc[1024];			/* Cc email address */
25*5e7646d2SAndroid Build Coastguard Worker char	mailtoFrom[1024];		/* From email address */
26*5e7646d2SAndroid Build Coastguard Worker char	mailtoReplyTo[1024];		/* Reply-To email address */
27*5e7646d2SAndroid Build Coastguard Worker char	mailtoSubject[1024];		/* Subject prefix */
28*5e7646d2SAndroid Build Coastguard Worker char	mailtoSMTPServer[1024];		/* SMTP server to use */
29*5e7646d2SAndroid Build Coastguard Worker char	mailtoSendmail[1024];		/* Sendmail program to use */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker 
32*5e7646d2SAndroid Build Coastguard Worker /*
33*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
34*5e7646d2SAndroid Build Coastguard Worker  */
35*5e7646d2SAndroid Build Coastguard Worker 
36*5e7646d2SAndroid Build Coastguard Worker void		email_message(const char *to, const char *subject, const char *text);
37*5e7646d2SAndroid Build Coastguard Worker int		load_configuration(void);
38*5e7646d2SAndroid Build Coastguard Worker cups_file_t	*pipe_sendmail(const char *to);
39*5e7646d2SAndroid Build Coastguard Worker void		print_attributes(ipp_t *ipp, int indent);
40*5e7646d2SAndroid Build Coastguard Worker 
41*5e7646d2SAndroid Build Coastguard Worker 
42*5e7646d2SAndroid Build Coastguard Worker /*
43*5e7646d2SAndroid Build Coastguard Worker  * 'main()' - Main entry for the mailto notifier.
44*5e7646d2SAndroid Build Coastguard Worker  */
45*5e7646d2SAndroid Build Coastguard Worker 
46*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit status */
main(int argc,char * argv[])47*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line arguments */
48*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
49*5e7646d2SAndroid Build Coastguard Worker {
50*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
51*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*msg;			/* Event message from scheduler */
52*5e7646d2SAndroid Build Coastguard Worker   ipp_state_t	state;			/* IPP event state */
53*5e7646d2SAndroid Build Coastguard Worker   char		*subject,		/* Subject for notification message */
54*5e7646d2SAndroid Build Coastguard Worker 		*text;			/* Text for notification message */
55*5e7646d2SAndroid Build Coastguard Worker   cups_lang_t	*lang;			/* Language info */
56*5e7646d2SAndroid Build Coastguard Worker   char		temp[1024];		/* Temporary string */
57*5e7646d2SAndroid Build Coastguard Worker   int		templen;		/* Length of temporary string */
58*5e7646d2SAndroid Build Coastguard Worker #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
59*5e7646d2SAndroid Build Coastguard Worker   struct sigaction action;		/* POSIX sigaction data */
60*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
61*5e7646d2SAndroid Build Coastguard Worker 
62*5e7646d2SAndroid Build Coastguard Worker 
63*5e7646d2SAndroid Build Coastguard Worker  /*
64*5e7646d2SAndroid Build Coastguard Worker   * Don't buffer stderr...
65*5e7646d2SAndroid Build Coastguard Worker   */
66*5e7646d2SAndroid Build Coastguard Worker 
67*5e7646d2SAndroid Build Coastguard Worker   setbuf(stderr, NULL);
68*5e7646d2SAndroid Build Coastguard Worker 
69*5e7646d2SAndroid Build Coastguard Worker  /*
70*5e7646d2SAndroid Build Coastguard Worker   * Ignore SIGPIPE signals...
71*5e7646d2SAndroid Build Coastguard Worker   */
72*5e7646d2SAndroid Build Coastguard Worker 
73*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SIGSET
74*5e7646d2SAndroid Build Coastguard Worker   sigset(SIGPIPE, SIG_IGN);
75*5e7646d2SAndroid Build Coastguard Worker #elif defined(HAVE_SIGACTION)
76*5e7646d2SAndroid Build Coastguard Worker   memset(&action, 0, sizeof(action));
77*5e7646d2SAndroid Build Coastguard Worker   action.sa_handler = SIG_IGN;
78*5e7646d2SAndroid Build Coastguard Worker   sigaction(SIGPIPE, &action, NULL);
79*5e7646d2SAndroid Build Coastguard Worker #else
80*5e7646d2SAndroid Build Coastguard Worker   signal(SIGPIPE, SIG_IGN);
81*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SIGSET */
82*5e7646d2SAndroid Build Coastguard Worker 
83*5e7646d2SAndroid Build Coastguard Worker  /*
84*5e7646d2SAndroid Build Coastguard Worker   * Validate command-line options...
85*5e7646d2SAndroid Build Coastguard Worker   */
86*5e7646d2SAndroid Build Coastguard Worker 
87*5e7646d2SAndroid Build Coastguard Worker   if (argc != 3)
88*5e7646d2SAndroid Build Coastguard Worker   {
89*5e7646d2SAndroid Build Coastguard Worker     fputs("Usage: mailto mailto:[email protected] notify-user-data\n", stderr);
90*5e7646d2SAndroid Build Coastguard Worker     return (1);
91*5e7646d2SAndroid Build Coastguard Worker   }
92*5e7646d2SAndroid Build Coastguard Worker 
93*5e7646d2SAndroid Build Coastguard Worker   if (strncmp(argv[1], "mailto:", 7))
94*5e7646d2SAndroid Build Coastguard Worker   {
95*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "ERROR: Bad recipient \"%s\"!\n", argv[1]);
96*5e7646d2SAndroid Build Coastguard Worker     return (1);
97*5e7646d2SAndroid Build Coastguard Worker   }
98*5e7646d2SAndroid Build Coastguard Worker 
99*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: argc=%d\n", argc);
100*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < argc; i ++)
101*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);
102*5e7646d2SAndroid Build Coastguard Worker 
103*5e7646d2SAndroid Build Coastguard Worker  /*
104*5e7646d2SAndroid Build Coastguard Worker   * Load configuration data...
105*5e7646d2SAndroid Build Coastguard Worker   */
106*5e7646d2SAndroid Build Coastguard Worker 
107*5e7646d2SAndroid Build Coastguard Worker   if ((lang = cupsLangDefault()) == NULL)
108*5e7646d2SAndroid Build Coastguard Worker     return (1);
109*5e7646d2SAndroid Build Coastguard Worker 
110*5e7646d2SAndroid Build Coastguard Worker   if (!load_configuration())
111*5e7646d2SAndroid Build Coastguard Worker     return (1);
112*5e7646d2SAndroid Build Coastguard Worker 
113*5e7646d2SAndroid Build Coastguard Worker  /*
114*5e7646d2SAndroid Build Coastguard Worker   * Get the reply-to address...
115*5e7646d2SAndroid Build Coastguard Worker   */
116*5e7646d2SAndroid Build Coastguard Worker 
117*5e7646d2SAndroid Build Coastguard Worker   templen = sizeof(temp);
118*5e7646d2SAndroid Build Coastguard Worker   httpDecode64_2(temp, &templen, argv[2]);
119*5e7646d2SAndroid Build Coastguard Worker 
120*5e7646d2SAndroid Build Coastguard Worker   if (!strncmp(temp, "mailto:", 7))
121*5e7646d2SAndroid Build Coastguard Worker     strlcpy(mailtoReplyTo, temp + 7, sizeof(mailtoReplyTo));
122*5e7646d2SAndroid Build Coastguard Worker   else if (temp[0])
123*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "WARNING: Bad notify-user-data value (%d bytes) ignored!\n",
124*5e7646d2SAndroid Build Coastguard Worker             templen);
125*5e7646d2SAndroid Build Coastguard Worker 
126*5e7646d2SAndroid Build Coastguard Worker  /*
127*5e7646d2SAndroid Build Coastguard Worker   * Loop forever until we run out of events...
128*5e7646d2SAndroid Build Coastguard Worker   */
129*5e7646d2SAndroid Build Coastguard Worker 
130*5e7646d2SAndroid Build Coastguard Worker   for (;;)
131*5e7646d2SAndroid Build Coastguard Worker   {
132*5e7646d2SAndroid Build Coastguard Worker    /*
133*5e7646d2SAndroid Build Coastguard Worker     * Get the next event...
134*5e7646d2SAndroid Build Coastguard Worker     */
135*5e7646d2SAndroid Build Coastguard Worker 
136*5e7646d2SAndroid Build Coastguard Worker     msg = ippNew();
137*5e7646d2SAndroid Build Coastguard Worker     while ((state = ippReadFile(0, msg)) != IPP_DATA)
138*5e7646d2SAndroid Build Coastguard Worker     {
139*5e7646d2SAndroid Build Coastguard Worker       if (state <= IPP_IDLE)
140*5e7646d2SAndroid Build Coastguard Worker         break;
141*5e7646d2SAndroid Build Coastguard Worker     }
142*5e7646d2SAndroid Build Coastguard Worker 
143*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: state=%d\n", state);
144*5e7646d2SAndroid Build Coastguard Worker 
145*5e7646d2SAndroid Build Coastguard Worker     if (state == IPP_ERROR)
146*5e7646d2SAndroid Build Coastguard Worker       fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr);
147*5e7646d2SAndroid Build Coastguard Worker 
148*5e7646d2SAndroid Build Coastguard Worker     if (state <= IPP_IDLE)
149*5e7646d2SAndroid Build Coastguard Worker     {
150*5e7646d2SAndroid Build Coastguard Worker      /*
151*5e7646d2SAndroid Build Coastguard Worker       * Out of messages, free memory and then exit...
152*5e7646d2SAndroid Build Coastguard Worker       */
153*5e7646d2SAndroid Build Coastguard Worker 
154*5e7646d2SAndroid Build Coastguard Worker       ippDelete(msg);
155*5e7646d2SAndroid Build Coastguard Worker       return (0);
156*5e7646d2SAndroid Build Coastguard Worker     }
157*5e7646d2SAndroid Build Coastguard Worker 
158*5e7646d2SAndroid Build Coastguard Worker    /*
159*5e7646d2SAndroid Build Coastguard Worker     * Get the subject and text for the message, then email it...
160*5e7646d2SAndroid Build Coastguard Worker     */
161*5e7646d2SAndroid Build Coastguard Worker 
162*5e7646d2SAndroid Build Coastguard Worker     subject = cupsNotifySubject(lang, msg);
163*5e7646d2SAndroid Build Coastguard Worker     text    = cupsNotifyText(lang, msg);
164*5e7646d2SAndroid Build Coastguard Worker 
165*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: subject=\"%s\"\n", subject);
166*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: text=\"%s\"\n", text);
167*5e7646d2SAndroid Build Coastguard Worker 
168*5e7646d2SAndroid Build Coastguard Worker     if (subject && text)
169*5e7646d2SAndroid Build Coastguard Worker       email_message(argv[1] + 7, subject, text);
170*5e7646d2SAndroid Build Coastguard Worker     else
171*5e7646d2SAndroid Build Coastguard Worker     {
172*5e7646d2SAndroid Build Coastguard Worker       fputs("ERROR: Missing attributes in event notification!\n", stderr);
173*5e7646d2SAndroid Build Coastguard Worker       print_attributes(msg, 4);
174*5e7646d2SAndroid Build Coastguard Worker     }
175*5e7646d2SAndroid Build Coastguard Worker 
176*5e7646d2SAndroid Build Coastguard Worker    /*
177*5e7646d2SAndroid Build Coastguard Worker     * Free the memory used for this event...
178*5e7646d2SAndroid Build Coastguard Worker     */
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker     if (subject)
181*5e7646d2SAndroid Build Coastguard Worker       free(subject);
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker     if (text)
184*5e7646d2SAndroid Build Coastguard Worker       free(text);
185*5e7646d2SAndroid Build Coastguard Worker 
186*5e7646d2SAndroid Build Coastguard Worker     ippDelete(msg);
187*5e7646d2SAndroid Build Coastguard Worker   }
188*5e7646d2SAndroid Build Coastguard Worker }
189*5e7646d2SAndroid Build Coastguard Worker 
190*5e7646d2SAndroid Build Coastguard Worker 
191*5e7646d2SAndroid Build Coastguard Worker /*
192*5e7646d2SAndroid Build Coastguard Worker  * 'email_message()' - Email a notification message.
193*5e7646d2SAndroid Build Coastguard Worker  */
194*5e7646d2SAndroid Build Coastguard Worker 
195*5e7646d2SAndroid Build Coastguard Worker void
email_message(const char * to,const char * subject,const char * text)196*5e7646d2SAndroid Build Coastguard Worker email_message(const char *to,		/* I - Recipient of message */
197*5e7646d2SAndroid Build Coastguard Worker               const char *subject,	/* I - Subject of message */
198*5e7646d2SAndroid Build Coastguard Worker 	      const char *text)		/* I - Text of message */
199*5e7646d2SAndroid Build Coastguard Worker {
200*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* Pipe/socket to mail server */
201*5e7646d2SAndroid Build Coastguard Worker   const char	*nl;			/* Newline to use */
202*5e7646d2SAndroid Build Coastguard Worker   char		response[1024];		/* SMTP response buffer */
203*5e7646d2SAndroid Build Coastguard Worker 
204*5e7646d2SAndroid Build Coastguard Worker 
205*5e7646d2SAndroid Build Coastguard Worker  /*
206*5e7646d2SAndroid Build Coastguard Worker   * Connect to the mail server...
207*5e7646d2SAndroid Build Coastguard Worker   */
208*5e7646d2SAndroid Build Coastguard Worker 
209*5e7646d2SAndroid Build Coastguard Worker   if (mailtoSendmail[0])
210*5e7646d2SAndroid Build Coastguard Worker   {
211*5e7646d2SAndroid Build Coastguard Worker    /*
212*5e7646d2SAndroid Build Coastguard Worker     * Use the sendmail command...
213*5e7646d2SAndroid Build Coastguard Worker     */
214*5e7646d2SAndroid Build Coastguard Worker 
215*5e7646d2SAndroid Build Coastguard Worker     fp = pipe_sendmail(to);
216*5e7646d2SAndroid Build Coastguard Worker 
217*5e7646d2SAndroid Build Coastguard Worker     if (!fp)
218*5e7646d2SAndroid Build Coastguard Worker       return;
219*5e7646d2SAndroid Build Coastguard Worker 
220*5e7646d2SAndroid Build Coastguard Worker     nl = "\n";
221*5e7646d2SAndroid Build Coastguard Worker   }
222*5e7646d2SAndroid Build Coastguard Worker   else
223*5e7646d2SAndroid Build Coastguard Worker   {
224*5e7646d2SAndroid Build Coastguard Worker    /*
225*5e7646d2SAndroid Build Coastguard Worker     * Use an SMTP server...
226*5e7646d2SAndroid Build Coastguard Worker     */
227*5e7646d2SAndroid Build Coastguard Worker 
228*5e7646d2SAndroid Build Coastguard Worker     char	hostbuf[1024];		/* Local hostname */
229*5e7646d2SAndroid Build Coastguard Worker 
230*5e7646d2SAndroid Build Coastguard Worker 
231*5e7646d2SAndroid Build Coastguard Worker     if (strchr(mailtoSMTPServer, ':'))
232*5e7646d2SAndroid Build Coastguard Worker     {
233*5e7646d2SAndroid Build Coastguard Worker       fp = cupsFileOpen(mailtoSMTPServer, "s");
234*5e7646d2SAndroid Build Coastguard Worker     }
235*5e7646d2SAndroid Build Coastguard Worker     else
236*5e7646d2SAndroid Build Coastguard Worker     {
237*5e7646d2SAndroid Build Coastguard Worker       char	spec[1024];		/* Host:service spec */
238*5e7646d2SAndroid Build Coastguard Worker 
239*5e7646d2SAndroid Build Coastguard Worker 
240*5e7646d2SAndroid Build Coastguard Worker       snprintf(spec, sizeof(spec), "%s:smtp", mailtoSMTPServer);
241*5e7646d2SAndroid Build Coastguard Worker       fp = cupsFileOpen(spec, "s");
242*5e7646d2SAndroid Build Coastguard Worker     }
243*5e7646d2SAndroid Build Coastguard Worker 
244*5e7646d2SAndroid Build Coastguard Worker     if (!fp)
245*5e7646d2SAndroid Build Coastguard Worker     {
246*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "ERROR: Unable to connect to SMTP server \"%s\"!\n",
247*5e7646d2SAndroid Build Coastguard Worker               mailtoSMTPServer);
248*5e7646d2SAndroid Build Coastguard Worker       return;
249*5e7646d2SAndroid Build Coastguard Worker     }
250*5e7646d2SAndroid Build Coastguard Worker 
251*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: Connected to \"%s\"...\n", mailtoSMTPServer);
252*5e7646d2SAndroid Build Coastguard Worker 
253*5e7646d2SAndroid Build Coastguard Worker     if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
254*5e7646d2SAndroid Build Coastguard Worker       goto smtp_error;
255*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: <<< %s\n", response);
256*5e7646d2SAndroid Build Coastguard Worker 
257*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "HELO %s\r\n",
258*5e7646d2SAndroid Build Coastguard Worker                    httpGetHostname(NULL, hostbuf, sizeof(hostbuf)));
259*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: >>> HELO %s\n", hostbuf);
260*5e7646d2SAndroid Build Coastguard Worker 
261*5e7646d2SAndroid Build Coastguard Worker     if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
262*5e7646d2SAndroid Build Coastguard Worker       goto smtp_error;
263*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: <<< %s\n", response);
264*5e7646d2SAndroid Build Coastguard Worker 
265*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "MAIL FROM:%s\r\n", mailtoFrom);
266*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: >>> MAIL FROM:%s\n", mailtoFrom);
267*5e7646d2SAndroid Build Coastguard Worker 
268*5e7646d2SAndroid Build Coastguard Worker     if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
269*5e7646d2SAndroid Build Coastguard Worker       goto smtp_error;
270*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: <<< %s\n", response);
271*5e7646d2SAndroid Build Coastguard Worker 
272*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "RCPT TO:%s\r\n", to);
273*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: >>> RCPT TO:%s\n", to);
274*5e7646d2SAndroid Build Coastguard Worker 
275*5e7646d2SAndroid Build Coastguard Worker     if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
276*5e7646d2SAndroid Build Coastguard Worker       goto smtp_error;
277*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: <<< %s\n", response);
278*5e7646d2SAndroid Build Coastguard Worker 
279*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "DATA\r\n");
280*5e7646d2SAndroid Build Coastguard Worker     fputs("DEBUG: DATA\n", stderr);
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker     if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
283*5e7646d2SAndroid Build Coastguard Worker       goto smtp_error;
284*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: <<< %s\n", response);
285*5e7646d2SAndroid Build Coastguard Worker 
286*5e7646d2SAndroid Build Coastguard Worker     nl = "\r\n";
287*5e7646d2SAndroid Build Coastguard Worker   }
288*5e7646d2SAndroid Build Coastguard Worker 
289*5e7646d2SAndroid Build Coastguard Worker  /*
290*5e7646d2SAndroid Build Coastguard Worker   * Send the message...
291*5e7646d2SAndroid Build Coastguard Worker   */
292*5e7646d2SAndroid Build Coastguard Worker 
293*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "Date: %s%s", httpGetDateString(time(NULL)), nl);
294*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "From: %s%s", mailtoFrom, nl);
295*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "Subject: %s %s%s", mailtoSubject, subject, nl);
296*5e7646d2SAndroid Build Coastguard Worker   if (mailtoReplyTo[0])
297*5e7646d2SAndroid Build Coastguard Worker   {
298*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Sender: %s%s", mailtoReplyTo, nl);
299*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Reply-To: %s%s", mailtoReplyTo, nl);
300*5e7646d2SAndroid Build Coastguard Worker   }
301*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "To: %s%s", to, nl);
302*5e7646d2SAndroid Build Coastguard Worker   if (mailtoCc[0])
303*5e7646d2SAndroid Build Coastguard Worker     cupsFilePrintf(fp, "Cc: %s%s", mailtoCc, nl);
304*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "Content-Type: text/plain%s", nl);
305*5e7646d2SAndroid Build Coastguard Worker   cupsFilePuts(fp, nl);
306*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, "%s%s", text, nl);
307*5e7646d2SAndroid Build Coastguard Worker   cupsFilePrintf(fp, ".%s", nl);
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker  /*
310*5e7646d2SAndroid Build Coastguard Worker   * Close the connection to the mail server...
311*5e7646d2SAndroid Build Coastguard Worker   */
312*5e7646d2SAndroid Build Coastguard Worker 
313*5e7646d2SAndroid Build Coastguard Worker   if (mailtoSendmail[0])
314*5e7646d2SAndroid Build Coastguard Worker   {
315*5e7646d2SAndroid Build Coastguard Worker    /*
316*5e7646d2SAndroid Build Coastguard Worker     * Close the pipe and wait for the sendmail command to finish...
317*5e7646d2SAndroid Build Coastguard Worker     */
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker     int	status;				/* Exit status */
320*5e7646d2SAndroid Build Coastguard Worker 
321*5e7646d2SAndroid Build Coastguard Worker 
322*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
323*5e7646d2SAndroid Build Coastguard Worker 
324*5e7646d2SAndroid Build Coastguard Worker     while (wait(&status))
325*5e7646d2SAndroid Build Coastguard Worker     {
326*5e7646d2SAndroid Build Coastguard Worker       if (errno != EINTR)
327*5e7646d2SAndroid Build Coastguard Worker       {
328*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "DEBUG: Unable to get child status: %s\n",
329*5e7646d2SAndroid Build Coastguard Worker 	        strerror(errno));
330*5e7646d2SAndroid Build Coastguard Worker         status = 0;
331*5e7646d2SAndroid Build Coastguard Worker 	break;
332*5e7646d2SAndroid Build Coastguard Worker       }
333*5e7646d2SAndroid Build Coastguard Worker     }
334*5e7646d2SAndroid Build Coastguard Worker 
335*5e7646d2SAndroid Build Coastguard Worker    /*
336*5e7646d2SAndroid Build Coastguard Worker     * Report any non-zero status...
337*5e7646d2SAndroid Build Coastguard Worker     */
338*5e7646d2SAndroid Build Coastguard Worker 
339*5e7646d2SAndroid Build Coastguard Worker     if (status)
340*5e7646d2SAndroid Build Coastguard Worker     {
341*5e7646d2SAndroid Build Coastguard Worker       if (WIFEXITED(status))
342*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: Sendmail command returned status %d!\n",
343*5e7646d2SAndroid Build Coastguard Worker 	        WEXITSTATUS(status));
344*5e7646d2SAndroid Build Coastguard Worker       else
345*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "ERROR: Sendmail command crashed on signal %d!\n",
346*5e7646d2SAndroid Build Coastguard Worker 	        WTERMSIG(status));
347*5e7646d2SAndroid Build Coastguard Worker     }
348*5e7646d2SAndroid Build Coastguard Worker   }
349*5e7646d2SAndroid Build Coastguard Worker   else
350*5e7646d2SAndroid Build Coastguard Worker   {
351*5e7646d2SAndroid Build Coastguard Worker    /*
352*5e7646d2SAndroid Build Coastguard Worker     * Finish up the SMTP submission and close the connection...
353*5e7646d2SAndroid Build Coastguard Worker     */
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker     if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
356*5e7646d2SAndroid Build Coastguard Worker       goto smtp_error;
357*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: <<< %s\n", response);
358*5e7646d2SAndroid Build Coastguard Worker 
359*5e7646d2SAndroid Build Coastguard Worker    /*
360*5e7646d2SAndroid Build Coastguard Worker     * Process SMTP errors here...
361*5e7646d2SAndroid Build Coastguard Worker     */
362*5e7646d2SAndroid Build Coastguard Worker 
363*5e7646d2SAndroid Build Coastguard Worker     smtp_error:
364*5e7646d2SAndroid Build Coastguard Worker 
365*5e7646d2SAndroid Build Coastguard Worker     cupsFilePuts(fp, "QUIT\r\n");
366*5e7646d2SAndroid Build Coastguard Worker     fputs("DEBUG: QUIT\n", stderr);
367*5e7646d2SAndroid Build Coastguard Worker 
368*5e7646d2SAndroid Build Coastguard Worker     if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
369*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "ERROR: Got \"%s\" trying to QUIT connection.\n",
370*5e7646d2SAndroid Build Coastguard Worker               response);
371*5e7646d2SAndroid Build Coastguard Worker     else
372*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: <<< %s\n", response);
373*5e7646d2SAndroid Build Coastguard Worker 
374*5e7646d2SAndroid Build Coastguard Worker     cupsFileClose(fp);
375*5e7646d2SAndroid Build Coastguard Worker 
376*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: Closed connection to \"%s\"...\n",
377*5e7646d2SAndroid Build Coastguard Worker             mailtoSMTPServer);
378*5e7646d2SAndroid Build Coastguard Worker   }
379*5e7646d2SAndroid Build Coastguard Worker }
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker 
382*5e7646d2SAndroid Build Coastguard Worker /*
383*5e7646d2SAndroid Build Coastguard Worker  * 'load_configuration()' - Load the mailto.conf file.
384*5e7646d2SAndroid Build Coastguard Worker  */
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker int					/* I - 1 on success, 0 on failure */
load_configuration(void)387*5e7646d2SAndroid Build Coastguard Worker load_configuration(void)
388*5e7646d2SAndroid Build Coastguard Worker {
389*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* mailto.conf file */
390*5e7646d2SAndroid Build Coastguard Worker   const char	*server_root,		/* CUPS_SERVERROOT environment variable */
391*5e7646d2SAndroid Build Coastguard Worker 		*server_admin;		/* SERVER_ADMIN environment variable */
392*5e7646d2SAndroid Build Coastguard Worker   char		line[1024],		/* Line from file */
393*5e7646d2SAndroid Build Coastguard Worker 		*value;			/* Value for directive */
394*5e7646d2SAndroid Build Coastguard Worker   int		linenum;		/* Line number in file */
395*5e7646d2SAndroid Build Coastguard Worker 
396*5e7646d2SAndroid Build Coastguard Worker 
397*5e7646d2SAndroid Build Coastguard Worker  /*
398*5e7646d2SAndroid Build Coastguard Worker   * Initialize defaults...
399*5e7646d2SAndroid Build Coastguard Worker   */
400*5e7646d2SAndroid Build Coastguard Worker 
401*5e7646d2SAndroid Build Coastguard Worker   mailtoCc[0] = '\0';
402*5e7646d2SAndroid Build Coastguard Worker 
403*5e7646d2SAndroid Build Coastguard Worker   if ((server_admin = getenv("SERVER_ADMIN")) != NULL)
404*5e7646d2SAndroid Build Coastguard Worker     strlcpy(mailtoFrom, server_admin, sizeof(mailtoFrom));
405*5e7646d2SAndroid Build Coastguard Worker   else
406*5e7646d2SAndroid Build Coastguard Worker     snprintf(mailtoFrom, sizeof(mailtoFrom), "root@%s",
407*5e7646d2SAndroid Build Coastguard Worker              httpGetHostname(NULL, line, sizeof(line)));
408*5e7646d2SAndroid Build Coastguard Worker 
409*5e7646d2SAndroid Build Coastguard Worker   strlcpy(mailtoSendmail, "/usr/sbin/sendmail", sizeof(mailtoSendmail));
410*5e7646d2SAndroid Build Coastguard Worker 
411*5e7646d2SAndroid Build Coastguard Worker   mailtoSMTPServer[0] = '\0';
412*5e7646d2SAndroid Build Coastguard Worker 
413*5e7646d2SAndroid Build Coastguard Worker   mailtoSubject[0] = '\0';
414*5e7646d2SAndroid Build Coastguard Worker 
415*5e7646d2SAndroid Build Coastguard Worker  /*
416*5e7646d2SAndroid Build Coastguard Worker   * Try loading the config file...
417*5e7646d2SAndroid Build Coastguard Worker   */
418*5e7646d2SAndroid Build Coastguard Worker 
419*5e7646d2SAndroid Build Coastguard Worker   if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
420*5e7646d2SAndroid Build Coastguard Worker     server_root = CUPS_SERVERROOT;
421*5e7646d2SAndroid Build Coastguard Worker 
422*5e7646d2SAndroid Build Coastguard Worker   snprintf(line, sizeof(line), "%s/mailto.conf", server_root);
423*5e7646d2SAndroid Build Coastguard Worker 
424*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpen(line, "r")) == NULL)
425*5e7646d2SAndroid Build Coastguard Worker   {
426*5e7646d2SAndroid Build Coastguard Worker     if (errno != ENOENT)
427*5e7646d2SAndroid Build Coastguard Worker     {
428*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "ERROR: Unable to open \"%s\" - %s\n", line,
429*5e7646d2SAndroid Build Coastguard Worker 	      strerror(errno));
430*5e7646d2SAndroid Build Coastguard Worker       return (1);
431*5e7646d2SAndroid Build Coastguard Worker     }
432*5e7646d2SAndroid Build Coastguard Worker     else
433*5e7646d2SAndroid Build Coastguard Worker       return (0);
434*5e7646d2SAndroid Build Coastguard Worker   }
435*5e7646d2SAndroid Build Coastguard Worker 
436*5e7646d2SAndroid Build Coastguard Worker   linenum = 0;
437*5e7646d2SAndroid Build Coastguard Worker 
438*5e7646d2SAndroid Build Coastguard Worker   while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
439*5e7646d2SAndroid Build Coastguard Worker   {
440*5e7646d2SAndroid Build Coastguard Worker     if (!value)
441*5e7646d2SAndroid Build Coastguard Worker     {
442*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "ERROR: No value found for %s directive on line %d!\n",
443*5e7646d2SAndroid Build Coastguard Worker               line, linenum);
444*5e7646d2SAndroid Build Coastguard Worker       cupsFileClose(fp);
445*5e7646d2SAndroid Build Coastguard Worker       return (0);
446*5e7646d2SAndroid Build Coastguard Worker     }
447*5e7646d2SAndroid Build Coastguard Worker 
448*5e7646d2SAndroid Build Coastguard Worker     if (!_cups_strcasecmp(line, "Cc"))
449*5e7646d2SAndroid Build Coastguard Worker       strlcpy(mailtoCc, value, sizeof(mailtoCc));
450*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "From"))
451*5e7646d2SAndroid Build Coastguard Worker       strlcpy(mailtoFrom, value, sizeof(mailtoFrom));
452*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Sendmail"))
453*5e7646d2SAndroid Build Coastguard Worker     {
454*5e7646d2SAndroid Build Coastguard Worker       strlcpy(mailtoSendmail, value, sizeof(mailtoSendmail));
455*5e7646d2SAndroid Build Coastguard Worker       mailtoSMTPServer[0] = '\0';
456*5e7646d2SAndroid Build Coastguard Worker     }
457*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "SMTPServer"))
458*5e7646d2SAndroid Build Coastguard Worker     {
459*5e7646d2SAndroid Build Coastguard Worker       mailtoSendmail[0] = '\0';
460*5e7646d2SAndroid Build Coastguard Worker       strlcpy(mailtoSMTPServer, value, sizeof(mailtoSMTPServer));
461*5e7646d2SAndroid Build Coastguard Worker     }
462*5e7646d2SAndroid Build Coastguard Worker     else if (!_cups_strcasecmp(line, "Subject"))
463*5e7646d2SAndroid Build Coastguard Worker       strlcpy(mailtoSubject, value, sizeof(mailtoSubject));
464*5e7646d2SAndroid Build Coastguard Worker     else
465*5e7646d2SAndroid Build Coastguard Worker     {
466*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr,
467*5e7646d2SAndroid Build Coastguard Worker               "ERROR: Unknown configuration directive \"%s\" on line %d!\n",
468*5e7646d2SAndroid Build Coastguard Worker               line, linenum);
469*5e7646d2SAndroid Build Coastguard Worker     }
470*5e7646d2SAndroid Build Coastguard Worker   }
471*5e7646d2SAndroid Build Coastguard Worker 
472*5e7646d2SAndroid Build Coastguard Worker  /*
473*5e7646d2SAndroid Build Coastguard Worker   * Close file and return...
474*5e7646d2SAndroid Build Coastguard Worker   */
475*5e7646d2SAndroid Build Coastguard Worker 
476*5e7646d2SAndroid Build Coastguard Worker   cupsFileClose(fp);
477*5e7646d2SAndroid Build Coastguard Worker 
478*5e7646d2SAndroid Build Coastguard Worker   return (1);
479*5e7646d2SAndroid Build Coastguard Worker }
480*5e7646d2SAndroid Build Coastguard Worker 
481*5e7646d2SAndroid Build Coastguard Worker 
482*5e7646d2SAndroid Build Coastguard Worker /*
483*5e7646d2SAndroid Build Coastguard Worker  * 'pipe_sendmail()' - Open a pipe to sendmail...
484*5e7646d2SAndroid Build Coastguard Worker  */
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker cups_file_t *				/* O - CUPS file */
pipe_sendmail(const char * to)487*5e7646d2SAndroid Build Coastguard Worker pipe_sendmail(const char *to)		/* I - To: address */
488*5e7646d2SAndroid Build Coastguard Worker {
489*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* CUPS file */
490*5e7646d2SAndroid Build Coastguard Worker   int		pid;			/* Process ID */
491*5e7646d2SAndroid Build Coastguard Worker   int		pipefds[2];		/* Pipe file descriptors */
492*5e7646d2SAndroid Build Coastguard Worker   int		argc;			/* Number of arguments */
493*5e7646d2SAndroid Build Coastguard Worker   char		*argv[100],		/* Argument array */
494*5e7646d2SAndroid Build Coastguard Worker 		line[1024],		/* Sendmail command + args */
495*5e7646d2SAndroid Build Coastguard Worker 		*lineptr;		/* Pointer into line */
496*5e7646d2SAndroid Build Coastguard Worker 
497*5e7646d2SAndroid Build Coastguard Worker 
498*5e7646d2SAndroid Build Coastguard Worker  /*
499*5e7646d2SAndroid Build Coastguard Worker   * First break the mailtoSendmail string into arguments...
500*5e7646d2SAndroid Build Coastguard Worker   */
501*5e7646d2SAndroid Build Coastguard Worker 
502*5e7646d2SAndroid Build Coastguard Worker   strlcpy(line, mailtoSendmail, sizeof(line));
503*5e7646d2SAndroid Build Coastguard Worker   argv[0] = line;
504*5e7646d2SAndroid Build Coastguard Worker   argc    = 1;
505*5e7646d2SAndroid Build Coastguard Worker 
506*5e7646d2SAndroid Build Coastguard Worker   for (lineptr = strchr(line, ' '); lineptr; lineptr = strchr(lineptr, ' '))
507*5e7646d2SAndroid Build Coastguard Worker   {
508*5e7646d2SAndroid Build Coastguard Worker     while (*lineptr == ' ')
509*5e7646d2SAndroid Build Coastguard Worker       *lineptr++ = '\0';
510*5e7646d2SAndroid Build Coastguard Worker 
511*5e7646d2SAndroid Build Coastguard Worker     if (*lineptr)
512*5e7646d2SAndroid Build Coastguard Worker     {
513*5e7646d2SAndroid Build Coastguard Worker      /*
514*5e7646d2SAndroid Build Coastguard Worker       * Point to the next argument...
515*5e7646d2SAndroid Build Coastguard Worker       */
516*5e7646d2SAndroid Build Coastguard Worker 
517*5e7646d2SAndroid Build Coastguard Worker       argv[argc ++] = lineptr;
518*5e7646d2SAndroid Build Coastguard Worker 
519*5e7646d2SAndroid Build Coastguard Worker      /*
520*5e7646d2SAndroid Build Coastguard Worker       * Stop if we have too many...
521*5e7646d2SAndroid Build Coastguard Worker       */
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker       if (argc >= (int)(sizeof(argv) / sizeof(argv[0]) - 2))
524*5e7646d2SAndroid Build Coastguard Worker         break;
525*5e7646d2SAndroid Build Coastguard Worker     }
526*5e7646d2SAndroid Build Coastguard Worker   }
527*5e7646d2SAndroid Build Coastguard Worker 
528*5e7646d2SAndroid Build Coastguard Worker   argv[argc ++] = (char *)to;
529*5e7646d2SAndroid Build Coastguard Worker   argv[argc]    = NULL;
530*5e7646d2SAndroid Build Coastguard Worker 
531*5e7646d2SAndroid Build Coastguard Worker  /*
532*5e7646d2SAndroid Build Coastguard Worker   * Create the pipe...
533*5e7646d2SAndroid Build Coastguard Worker   */
534*5e7646d2SAndroid Build Coastguard Worker 
535*5e7646d2SAndroid Build Coastguard Worker   if (pipe(pipefds))
536*5e7646d2SAndroid Build Coastguard Worker   {
537*5e7646d2SAndroid Build Coastguard Worker     perror("ERROR: Unable to create pipe");
538*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
539*5e7646d2SAndroid Build Coastguard Worker   }
540*5e7646d2SAndroid Build Coastguard Worker 
541*5e7646d2SAndroid Build Coastguard Worker  /*
542*5e7646d2SAndroid Build Coastguard Worker   * Then run the command...
543*5e7646d2SAndroid Build Coastguard Worker   */
544*5e7646d2SAndroid Build Coastguard Worker 
545*5e7646d2SAndroid Build Coastguard Worker   if ((pid = fork()) == 0)
546*5e7646d2SAndroid Build Coastguard Worker   {
547*5e7646d2SAndroid Build Coastguard Worker    /*
548*5e7646d2SAndroid Build Coastguard Worker     * Child goes here - redirect stdin to the input side of the pipe,
549*5e7646d2SAndroid Build Coastguard Worker     * redirect stdout to stderr, and exec...
550*5e7646d2SAndroid Build Coastguard Worker     */
551*5e7646d2SAndroid Build Coastguard Worker 
552*5e7646d2SAndroid Build Coastguard Worker     close(0);
553*5e7646d2SAndroid Build Coastguard Worker     dup(pipefds[0]);
554*5e7646d2SAndroid Build Coastguard Worker 
555*5e7646d2SAndroid Build Coastguard Worker     close(1);
556*5e7646d2SAndroid Build Coastguard Worker     dup(2);
557*5e7646d2SAndroid Build Coastguard Worker 
558*5e7646d2SAndroid Build Coastguard Worker     close(pipefds[0]);
559*5e7646d2SAndroid Build Coastguard Worker     close(pipefds[1]);
560*5e7646d2SAndroid Build Coastguard Worker 
561*5e7646d2SAndroid Build Coastguard Worker     execvp(argv[0], argv);
562*5e7646d2SAndroid Build Coastguard Worker     exit(errno);
563*5e7646d2SAndroid Build Coastguard Worker   }
564*5e7646d2SAndroid Build Coastguard Worker   else if (pid < 0)
565*5e7646d2SAndroid Build Coastguard Worker   {
566*5e7646d2SAndroid Build Coastguard Worker    /*
567*5e7646d2SAndroid Build Coastguard Worker     * Unable to fork - error out...
568*5e7646d2SAndroid Build Coastguard Worker     */
569*5e7646d2SAndroid Build Coastguard Worker 
570*5e7646d2SAndroid Build Coastguard Worker     perror("ERROR: Unable to fork command");
571*5e7646d2SAndroid Build Coastguard Worker 
572*5e7646d2SAndroid Build Coastguard Worker     close(pipefds[0]);
573*5e7646d2SAndroid Build Coastguard Worker     close(pipefds[1]);
574*5e7646d2SAndroid Build Coastguard Worker 
575*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
576*5e7646d2SAndroid Build Coastguard Worker   }
577*5e7646d2SAndroid Build Coastguard Worker 
578*5e7646d2SAndroid Build Coastguard Worker  /*
579*5e7646d2SAndroid Build Coastguard Worker   * Create a CUPS file using the output side of the pipe and close the
580*5e7646d2SAndroid Build Coastguard Worker   * input side...
581*5e7646d2SAndroid Build Coastguard Worker   */
582*5e7646d2SAndroid Build Coastguard Worker 
583*5e7646d2SAndroid Build Coastguard Worker   close(pipefds[0]);
584*5e7646d2SAndroid Build Coastguard Worker 
585*5e7646d2SAndroid Build Coastguard Worker   if ((fp = cupsFileOpenFd(pipefds[1], "w")) == NULL)
586*5e7646d2SAndroid Build Coastguard Worker   {
587*5e7646d2SAndroid Build Coastguard Worker     int	status;				/* Status of command */
588*5e7646d2SAndroid Build Coastguard Worker 
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker     close(pipefds[1]);
591*5e7646d2SAndroid Build Coastguard Worker     wait(&status);
592*5e7646d2SAndroid Build Coastguard Worker   }
593*5e7646d2SAndroid Build Coastguard Worker 
594*5e7646d2SAndroid Build Coastguard Worker   return (fp);
595*5e7646d2SAndroid Build Coastguard Worker }
596*5e7646d2SAndroid Build Coastguard Worker 
597*5e7646d2SAndroid Build Coastguard Worker 
598*5e7646d2SAndroid Build Coastguard Worker /*
599*5e7646d2SAndroid Build Coastguard Worker  * 'print_attributes()' - Print the attributes in a request...
600*5e7646d2SAndroid Build Coastguard Worker  */
601*5e7646d2SAndroid Build Coastguard Worker 
602*5e7646d2SAndroid Build Coastguard Worker void
print_attributes(ipp_t * ipp,int indent)603*5e7646d2SAndroid Build Coastguard Worker print_attributes(ipp_t *ipp,		/* I - IPP request */
604*5e7646d2SAndroid Build Coastguard Worker                  int   indent)		/* I - Indentation */
605*5e7646d2SAndroid Build Coastguard Worker {
606*5e7646d2SAndroid Build Coastguard Worker   ipp_tag_t		group;		/* Current group */
607*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t	*attr;		/* Current attribute */
608*5e7646d2SAndroid Build Coastguard Worker   char			buffer[1024];	/* Value buffer */
609*5e7646d2SAndroid Build Coastguard Worker 
610*5e7646d2SAndroid Build Coastguard Worker 
611*5e7646d2SAndroid Build Coastguard Worker   for (group = IPP_TAG_ZERO, attr = ipp->attrs; attr; attr = attr->next)
612*5e7646d2SAndroid Build Coastguard Worker   {
613*5e7646d2SAndroid Build Coastguard Worker     if ((attr->group_tag == IPP_TAG_ZERO && indent <= 8) || !attr->name)
614*5e7646d2SAndroid Build Coastguard Worker     {
615*5e7646d2SAndroid Build Coastguard Worker       group = IPP_TAG_ZERO;
616*5e7646d2SAndroid Build Coastguard Worker       fputc('\n', stderr);
617*5e7646d2SAndroid Build Coastguard Worker       continue;
618*5e7646d2SAndroid Build Coastguard Worker     }
619*5e7646d2SAndroid Build Coastguard Worker 
620*5e7646d2SAndroid Build Coastguard Worker     if (group != attr->group_tag)
621*5e7646d2SAndroid Build Coastguard Worker     {
622*5e7646d2SAndroid Build Coastguard Worker       group = attr->group_tag;
623*5e7646d2SAndroid Build Coastguard Worker 
624*5e7646d2SAndroid Build Coastguard Worker       fprintf(stderr, "DEBUG: %*s%s:\n\n", indent - 4, "", ippTagString(group));
625*5e7646d2SAndroid Build Coastguard Worker     }
626*5e7646d2SAndroid Build Coastguard Worker 
627*5e7646d2SAndroid Build Coastguard Worker     ippAttributeString(attr, buffer, sizeof(buffer));
628*5e7646d2SAndroid Build Coastguard Worker 
629*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: %*s%s (%s%s) %s", indent, "", attr->name,
630*5e7646d2SAndroid Build Coastguard Worker             attr->num_values > 1 ? "1setOf " : "",
631*5e7646d2SAndroid Build Coastguard Worker 	    ippTagString(attr->value_tag), buffer);
632*5e7646d2SAndroid Build Coastguard Worker   }
633*5e7646d2SAndroid Build Coastguard Worker }
634