• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * BRF (Braille-Ready Format) virtual backend
3  *
4  * Copyright (c) 2017 by Samuel Thibault <samuel.thibault@ens-lyon.org>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 #include "backend-private.h"
28 #include <string.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 #include <pwd.h>
35 
main(int argc,char * argv[])36 int main(int argc, char *argv[]) {
37   char *user;
38   char *dir;
39   char *title;
40   char *outfile;
41   char *c;
42   char buffer[4096];
43   ssize_t sizein, sizeout, done;
44   struct passwd *pw;
45   int ret;
46   int fd;
47 
48   if (setuid(0)) {
49     /* We need to be root to be able to turn into another user.  */
50     fprintf(stderr,"ERROR: cups-brf must be called as root\n");
51     return CUPS_BACKEND_FAILED;
52   }
53 
54   if (argc == 1) {
55     /* This is just discovery.  */
56     printf("file cups-brf:/ \"Virtual Braille BRF Printer\" \"CUPS-BRF\" \"MFG:Generic;MDL:CUPS-BRF Printer;DES:Generic CUPS-BRF Printer;CLS:PRINTER;CMD:BRF;\"\n");
57     return CUPS_BACKEND_OK;
58   }
59 
60   if (argc < 6) {
61     /* Invalid number of parameters.  */
62     fprintf(stderr, "ERROR: cups-brf jobid user name nb options [filename]\n");
63     return CUPS_BACKEND_FAILED;
64   }
65 
66   if (argc == 7) {
67     /* Explicit file name, open it.  */
68     char *filename = argv[6];
69     fd = open(filename,  O_RDONLY);
70     if (dup2(fd, STDIN_FILENO) < 0) {
71       fprintf(stderr, "ERROR: opening file \"%s\"\n", filename);
72       return CUPS_BACKEND_FAILED;
73     }
74   }
75 
76   /* Now we have everything, turn into the user */
77   user = argv[2];
78   pw = getpwnam(user);
79   if (pw == NULL) {
80     fprintf(stderr, "ERROR: getting user \"%s\" information\n", user);
81     return CUPS_BACKEND_FAILED;
82   }
83   if (setgid(pw->pw_gid)) {
84     fprintf(stderr, "ERROR: turning gid into %u\n", pw->pw_gid);
85     return CUPS_BACKEND_FAILED;
86   }
87   if (setuid(pw->pw_uid)) {
88     fprintf(stderr, "ERROR: turning uid into %u\n", pw->pw_uid);
89     return CUPS_BACKEND_FAILED;
90   }
91 
92   /* Now we act as user */
93   umask(0077);
94 
95   /* Create BRF directory in $HOME */
96   if (asprintf(&dir, "%s/BRF", pw->pw_dir) < 0) {
97     fprintf(stderr, "ERROR: could not allocate memory\n");
98     return CUPS_BACKEND_FAILED;
99   }
100   fprintf(stderr, "DEBUG: creating directory \"%s\n", dir);
101   ret = mkdir(dir, 0700);
102   if (ret == -1 && errno != EEXIST) {
103     fprintf(stderr, "ERROR: could not create directory \"%s\": %s\n", dir, strerror(errno));
104     return CUPS_BACKEND_FAILED;
105   }
106 
107   /* Avoid escaping from the directory */
108   title = argv[3];
109   for (c = title; *c; c++) {
110     if (*c == '/')
111       *c = '_';
112   }
113   /* Avoid hiding the file */
114   while (*title == '.')
115     title++;
116 
117   /* Avoid empty title */
118   if (!*title)
119     title = "unknown";
120 
121   /* generate mask */
122   if (asprintf(&outfile, "%s/%s.XXXXXX.brf", dir, title) < 0) {
123     fprintf(stderr, "ERROR: could not allocate memory\n");
124     return CUPS_BACKEND_FAILED;
125   }
126 
127   /* Create file */
128   fprintf(stderr, "DEBUG: creating file \"%s\n", outfile);
129   fd = mkstemps(outfile, 4);
130   if (fd < 0) {
131     fprintf(stderr, "ERROR: could not create file \"%s\": %s\n", outfile, strerror(errno));
132     return CUPS_BACKEND_FAILED;
133   }
134 
135   /* We are all set, copy data.  */
136   while (1) {
137     /* Read some.  */
138     sizein = read(STDIN_FILENO, buffer, sizeof(buffer));
139     if (sizein < 0) {
140       fprintf(stderr, "ERROR: while reading input: %s\n", strerror(errno));
141       return CUPS_BACKEND_FAILED;
142     }
143     if (sizein == 0)
144       /* We are done! */
145       break;
146 
147     /* Write it.  */
148     for (done = 0; done < sizein; done += sizeout) {
149       sizeout = write(fd, buffer + done, sizein - done);
150       if (sizeout < 0) {
151 	fprintf(stderr, "ERROR: while writing to \"%s\": %s\n", outfile, strerror(errno));
152 	return CUPS_BACKEND_FAILED;
153       }
154     }
155   }
156   if (close(fd) < 0) {
157     fprintf(stderr, "ERROR: while closing \"%s\": %s\n", outfile, strerror(errno));
158     return CUPS_BACKEND_FAILED;
159   }
160 
161   return CUPS_BACKEND_OK;
162 }
163