1 /* Copyright 2012-present Facebook, Inc.
2  * Licensed under the Apache License, Version 2.0 */
3 #include "ChildProcess.h"
4 #include "Logging.h"
5 #include "ThreadPool.h"
6 #include "watchman.h"
7 #ifndef _WIN32
8 #include <poll.h>
9 #endif
10 
11 using watchman::ChildProcess;
12 using watchman::FileDescriptor;
13 using Options = ChildProcess::Options;
14 
15 static int show_help = 0;
16 static int show_version = 0;
17 static enum w_pdu_type server_pdu = is_bser;
18 static enum w_pdu_type output_pdu = is_json_pretty;
19 static uint32_t server_capabilities = 0;
20 static uint32_t output_capabilities = 0;
21 static char *server_encoding = NULL;
22 static char *output_encoding = NULL;
23 static char *test_state_dir = NULL;
24 static char *sock_name = NULL;
25 char *log_name = NULL;
26 static char *pid_file = NULL;
27 char *watchman_state_file = NULL;
28 static char **daemon_argv = NULL;
29 const char *watchman_tmp_dir = NULL;
30 static int persistent = 0;
31 int dont_save_state = 0;
32 static int foreground = 0;
33 static int no_pretty = 0;
34 static int no_spawn = 0;
35 static int no_local = 0;
36 #ifndef _WIN32
37 static int inetd_style = 0;
38 static struct sockaddr_un un;
39 #endif
40 static int json_input_arg = 0;
41 
42 #ifdef __APPLE__
43 #include <mach-o/dyld.h>
44 #endif
45 
46 static const char *compute_user_name(void);
47 static void compute_file_name(char **strp, const char *user, const char *suffix,
48                               const char *what);
49 
lock_pidfile(void)50 static bool lock_pidfile(void) {
51 #if !defined(USE_GIMLI) && !defined(_WIN32)
52   struct flock lock;
53   pid_t mypid;
54 
55   // We defer computing this path until we're in the server context because
56   // eager evaluation can trigger integration test failures unless all clients
57   // are aware of both the pidfile and the sockpath being used in the tests.
58   compute_file_name(&pid_file, compute_user_name(), "pid", "pidfile");
59 
60   mypid = getpid();
61   memset(&lock, 0, sizeof(lock));
62   lock.l_type = F_WRLCK;
63   lock.l_start = 0;
64   lock.l_whence = SEEK_SET;
65   lock.l_len = 0;
66 
67   FileDescriptor fd(open(pid_file, O_RDWR | O_CREAT, 0644));
68 
69   if (!fd) {
70     w_log(W_LOG_ERR, "Failed to open pidfile %s for write: %s\n", pid_file,
71           strerror(errno));
72     return false;
73   }
74   // Ensure that no children inherit the locked pidfile descriptor
75   fd.setCloExec();
76 
77   if (fcntl(fd.fd(), F_SETLK, &lock) != 0) {
78     char pidstr[32];
79     int len;
80 
81     len = read(fd.fd(), pidstr, sizeof(pidstr) - 1);
82     pidstr[len] = '\0';
83 
84     w_log(W_LOG_ERR, "Failed to lock pidfile %s: process %s owns it: %s\n",
85           pid_file, pidstr, strerror(errno));
86     return false;
87   }
88 
89   // Replace contents of the pidfile with our pid string
90   if (ftruncate(fd.fd(), 0)) {
91     w_log(W_LOG_ERR, "Failed to truncate pidfile %s: %s\n",
92         pid_file, strerror(errno));
93     return false;
94   }
95 
96   dprintf(fd.fd(), "%d", mypid);
97   fsync(fd.fd());
98 
99   /* We are intentionally not closing the fd and intentionally not storing
100    * a reference to it anywhere: the intention is that it remain locked
101    * for the rest of the lifetime of our process.
102    * close(fd); // NOPE!
103    */
104   fd.release();
105   return true;
106 #else
107   // ze-googles, they do nothing!!
108   return true;
109 #endif
110 }
111 
run_service(void)112 static void run_service(void)
113 {
114   int fd;
115   bool res;
116 
117 #ifndef _WIN32
118   // Before we redirect stdin/stdout to the log files, move any inetd-provided
119   // socket to a different descriptor number.
120   if (inetd_style) {
121     w_listener_prep_inetd();
122   }
123 #endif
124 
125   // redirect std{in,out,err}
126   fd = open("/dev/null", O_RDONLY);
127   if (fd != -1) {
128     ignore_result(dup2(fd, STDIN_FILENO));
129     close(fd);
130   }
131   fd = open(log_name, O_WRONLY|O_APPEND|O_CREAT, 0600);
132   if (fd != -1) {
133     ignore_result(dup2(fd, STDOUT_FILENO));
134     ignore_result(dup2(fd, STDERR_FILENO));
135     close(fd);
136   }
137 
138   if (!lock_pidfile()) {
139     return;
140   }
141 
142 #ifndef _WIN32
143   /* we are the child, let's set things up */
144   ignore_result(chdir("/"));
145 #endif
146 
147   w_set_thread_name("listener");
148   {
149     char hostname[256];
150     gethostname(hostname, sizeof(hostname));
151     hostname[sizeof(hostname) - 1] = '\0';
152     w_log(W_LOG_ERR, "Watchman %s %s starting up on %s\n",
153         PACKAGE_VERSION,
154 #ifdef WATCHMAN_BUILD_INFO
155         WATCHMAN_BUILD_INFO,
156 #else
157         "<no build info set>",
158 #endif
159         hostname);
160   }
161 
162 #ifndef _WIN32
163   // Block SIGCHLD by default; we only want it to be delivered
164   // to the reaper thread and only when it is ready to reap.
165   // This MUST happen before we spawn any threads so that they
166   // can pick up our default blocked signal mask.
167   {
168     sigset_t sigset;
169 
170     sigemptyset(&sigset);
171     sigaddset(&sigset, SIGCHLD);
172     sigprocmask(SIG_BLOCK, &sigset, NULL);
173   }
174 #endif
175 
176   watchman::getThreadPool().start(
177       cfg_get_int("thread_pool_worker_threads", 16),
178       cfg_get_int("thread_pool_max_items", 1024 * 1024));
179 
180   ClockSpec::init();
181   w_state_load();
182   res = w_start_listener(sock_name);
183   w_root_free_watched_roots();
184   cfg_shutdown();
185 
186   watchman::log(watchman::ERR, "Exiting from service with res=", res, "\n");
187 
188   if (res) {
189     exit(0);
190   }
191   exit(1);
192 }
193 
194 #ifndef _WIN32
195 // close any random descriptors that we may have inherited,
196 // leaving only the main stdio descriptors open, if we execute a
197 // child process.
close_random_fds(void)198 static void close_random_fds(void) {
199   struct rlimit limit;
200   long open_max = 0;
201   int max_fd;
202 
203   // Deduce the upper bound for number of descriptors
204   limit.rlim_cur = 0;
205 #ifdef RLIMIT_NOFILE
206   if (getrlimit(RLIMIT_NOFILE, &limit) != 0) {
207     limit.rlim_cur = 0;
208   }
209 #elif defined(RLIM_OFILE)
210   if (getrlimit(RLIMIT_OFILE, &limit) != 0) {
211     limit.rlim_cur = 0;
212   }
213 #endif
214 #ifdef _SC_OPEN_MAX
215   open_max = sysconf(_SC_OPEN_MAX);
216 #endif
217   if (open_max <= 0) {
218     open_max = 36; /* POSIX_OPEN_MAX (20) + some padding */
219   }
220   if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > INT_MAX) {
221     // "no limit", which seems unlikely
222     limit.rlim_cur = INT_MAX;
223   }
224   // Take the larger of the two values we compute
225   if (limit.rlim_cur > (rlim_t)open_max) {
226     open_max = limit.rlim_cur;
227   }
228 
229   for (max_fd = open_max; max_fd > STDERR_FILENO; --max_fd) {
230     close(max_fd);
231   }
232 }
233 #endif
234 
235 #if !defined(USE_GIMLI) && !defined(_WIN32)
daemonize(void)236 static void daemonize(void)
237 {
238   close_random_fds();
239 
240   // the double-fork-and-setsid trick establishes a
241   // child process that runs in its own process group
242   // with its own session and that won't get killed
243   // off when your shell exits (for example).
244   if (fork()) {
245     // The parent of the first fork is the client
246     // process that is being run by the user, and
247     // we want to allow that to continue.
248     return;
249   }
250   setsid();
251   if (fork()) {
252     // The parent of the second fork has served its
253     // purpose, so we simply exit here, otherwise
254     // we'll duplicate the effort of either the
255     // client or the server depending on if we
256     // return or not.
257     _exit(0);
258   }
259 
260   // we are the child, let's set things up
261   run_service();
262 }
263 #endif
264 
265 #ifdef _WIN32
spawn_win32(void)266 static void spawn_win32(void) {
267   char module_name[WATCHMAN_NAME_MAX];
268   GetModuleFileName(NULL, module_name, sizeof(module_name));
269 
270   Options opts;
271   opts.setFlags(POSIX_SPAWN_SETPGROUP);
272   opts.open(STDIN_FILENO, "/dev/null", O_RDONLY, 0666);
273   opts.open(STDOUT_FILENO, log_name, O_WRONLY | O_CREAT | O_APPEND, 0600);
274   opts.dup2(STDOUT_FILENO, STDERR_FILENO);
275 
276   std::vector<w_string_piece> args{module_name, "--foreground"};
277   for (size_t i = 0; daemon_argv[i]; i++) {
278     args.push_back(daemon_argv[i]);
279   }
280 
281   ChildProcess proc(args, std::move(opts));
282   proc.disown();
283 }
284 #endif
285 
286 #ifdef USE_GIMLI
spawn_via_gimli(void)287 static void spawn_via_gimli(void)
288 {
289   std::vector<w_string_piece> args{
290       GIMLI_MONITOR_PATH,
291 #ifdef WATCHMAN_STATE_DIR
292       "--trace-dir=" WATCHMAN_STATE_DIR "/traces",
293 #endif
294       "--pidfile",
295       pid_file,
296       "watchman",
297       "--foreground",
298   };
299 
300   for (size_t i = 0; daemon_argv[i]; i++) {
301     args.push_back(daemon_argv[i]);
302   }
303 
304   close_random_fds();
305 
306   Options opts;
307   opts.open(STDIN_FILENO, "/dev/null", O_RDONLY, 0666);
308   opts.open(STDOUT_FILENO, log_name, O_WRONLY | O_CREAT | O_APPEND, 0600);
309   opts.dup2(STDOUT_FILENO, STDERR_FILENO);
310 
311   ChildProcess proc(args, std::move(opts));
312   proc.disown();
313 }
314 #endif
315 
316 #ifndef _WIN32
317 // Spawn watchman via a site-specific spawn helper program.
318 // We'll pass along any daemon-appropriate arguments that
319 // we noticed during argument parsing.
spawn_site_specific(const char * spawner)320 static void spawn_site_specific(const char *spawner)
321 {
322   std::vector<w_string_piece> args{
323       spawner,
324   };
325 
326   for (size_t i = 0; daemon_argv[i]; i++) {
327     args.push_back(daemon_argv[i]);
328   }
329 
330   close_random_fds();
331 
332   Options opts;
333   opts.open(STDIN_FILENO, "/dev/null", O_RDONLY, 0666);
334   opts.open(STDOUT_FILENO, log_name, O_WRONLY | O_CREAT | O_APPEND, 0600);
335   opts.dup2(STDOUT_FILENO, STDERR_FILENO);
336 
337   try {
338     ChildProcess proc(args, std::move(opts));
339 
340     auto res = proc.wait();
341 
342     if (WIFEXITED(res) && WEXITSTATUS(res) == 0) {
343       return;
344     }
345 
346     if (WIFEXITED(res)) {
347       watchman::log(
348           watchman::FATAL,
349           spawner,
350           ": exited with status ",
351           WEXITSTATUS(res),
352           "\n");
353     } else if (WIFSIGNALED(res)) {
354       watchman::log(
355           watchman::FATAL, spawner, ": signaled with ", WTERMSIG(res), "\n");
356     }
357     watchman::log(
358         watchman::ERR, spawner, ": failed to start, exit status ", res, "\n");
359 
360   } catch (const std::exception& exc) {
361     watchman::log(
362         watchman::FATAL,
363         "Failed to spawn watchman via `",
364         spawner,
365         "': ",
366         exc.what(),
367         "\n");
368   }
369 }
370 #endif
371 
372 #ifdef __APPLE__
spawn_via_launchd(void)373 static void spawn_via_launchd(void)
374 {
375   char watchman_path[WATCHMAN_NAME_MAX];
376   uint32_t size = sizeof(watchman_path);
377   char plist_path[WATCHMAN_NAME_MAX];
378   FILE *fp;
379   struct passwd *pw;
380   uid_t uid;
381 
382   close_random_fds();
383 
384   if (_NSGetExecutablePath(watchman_path, &size) == -1) {
385     w_log(W_LOG_ERR, "_NSGetExecutablePath: path too long; size %u\n", size);
386     abort();
387   }
388 
389   uid = getuid();
390   pw = getpwuid(uid);
391   if (!pw) {
392     w_log(W_LOG_ERR, "getpwuid(%d) failed: %s.  I don't know who you are\n",
393         uid, strerror(errno));
394     abort();
395   }
396 
397   snprintf(plist_path, sizeof(plist_path),
398       "%s/Library/LaunchAgents", pw->pw_dir);
399   // Best effort attempt to ensure that the agents dir exists.  We'll detect
400   // and report the failure in the fopen call below.
401   mkdir(plist_path, 0755);
402   snprintf(plist_path, sizeof(plist_path),
403       "%s/Library/LaunchAgents/com.github.facebook.watchman.plist", pw->pw_dir);
404 
405   if (access(plist_path, R_OK) == 0) {
406     // Unload any that may already exist, as it is likely wrong
407 
408     ChildProcess unload_proc(
409         {"/bin/launchctl", "unload", "-F", plist_path}, Options());
410     unload_proc.wait();
411 
412     // Forcibly remove the plist.  In some cases it may have some attributes
413     // set that prevent launchd from loading it.  This can happen where
414     // the system was re-imaged or restored from a backup
415     unlink(plist_path);
416   }
417 
418   fp = fopen(plist_path, "w");
419   if (!fp) {
420     w_log(W_LOG_ERR, "Failed to open %s for write: %s\n",
421         plist_path, strerror(errno));
422     abort();
423   }
424 
425   compute_file_name(&pid_file, compute_user_name(), "pid", "pidfile");
426 
427   auto plist_content = watchman::to<std::string>(
428       "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
429       "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
430       "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
431       "<plist version=\"1.0\">\n"
432       "<dict>\n"
433       "    <key>Label</key>\n"
434       "    <string>com.github.facebook.watchman</string>\n"
435       "    <key>Disabled</key>\n"
436       "    <false/>\n"
437       "    <key>ProgramArguments</key>\n"
438       "    <array>\n"
439       "        <string>",
440       watchman_path,
441       "</string>\n"
442       "        <string>--foreground</string>\n"
443       "        <string>--logfile=",
444       log_name,
445       "</string>\n"
446       "        <string>--log-level=",
447       log_level,
448       "</string>\n"
449       "        <string>--sockname=",
450       sock_name,
451       "</string>\n"
452       "        <string>--statefile=",
453       watchman_state_file,
454       "</string>\n"
455       "        <string>--pidfile=",
456       pid_file,
457       "</string>\n"
458       "    </array>\n"
459       "    <key>KeepAlive</key>\n"
460       "    <dict>\n"
461       "        <key>Crashed</key>\n"
462       "        <true/>\n"
463       "    </dict>\n"
464       "    <key>RunAtLoad</key>\n"
465       "    <true/>\n"
466       "    <key>EnvironmentVariables</key>\n"
467       "    <dict>\n"
468       "        <key>PATH</key>\n"
469       "        <string><![CDATA[",
470       getenv("PATH"),
471       "]]></string>\n"
472       "    </dict>\n"
473       "    <key>ProcessType</key>\n"
474       "    <string>Interactive</string>\n"
475       "    <key>Nice</key>\n"
476       "    <integer>-5</integer>\n"
477       "</dict>\n"
478       "</plist>\n");
479   fwrite(plist_content.data(), 1, plist_content.size(), fp);
480   fclose(fp);
481   // Don't rely on umask, ensure we have the correct perms
482   chmod(plist_path, 0644);
483 
484   ChildProcess load_proc(
485       {"/bin/launchctl", "load", "-F", plist_path}, Options());
486   auto res = load_proc.wait();
487 
488   if (WIFEXITED(res) && WEXITSTATUS(res) == 0) {
489     return;
490   }
491 
492   // Most likely cause is "headless" operation with no GUI context
493   if (WIFEXITED(res)) {
494     w_log(W_LOG_ERR, "launchctl: exited with status %d\n", WEXITSTATUS(res));
495   } else if (WIFSIGNALED(res)) {
496     w_log(W_LOG_ERR, "launchctl: signaled with %d\n", WTERMSIG(res));
497   }
498   w_log(W_LOG_ERR, "Falling back to daemonize\n");
499   daemonize();
500 }
501 #endif
502 
parse_encoding(const char * enc,enum w_pdu_type * pdu)503 static void parse_encoding(const char *enc, enum w_pdu_type *pdu)
504 {
505   if (!enc) {
506     return;
507   }
508   if (!strcmp(enc, "json")) {
509     *pdu = is_json_compact;
510     return;
511   }
512   if (!strcmp(enc, "bser")) {
513     *pdu = is_bser;
514     return;
515   }
516   if (!strcmp(enc, "bser-v2")) {
517     *pdu = is_bser_v2;
518     return;
519   }
520   w_log(W_LOG_ERR, "Invalid encoding '%s', use one of json, bser or bser-v2\n",
521       enc);
522   exit(EX_USAGE);
523 }
524 
get_env_with_fallback(const char * name1,const char * name2,const char * fallback)525 static const char *get_env_with_fallback(const char *name1,
526     const char *name2, const char *fallback)
527 {
528   const char *val;
529 
530   val = getenv(name1);
531   if (!val || *val == 0) {
532     val = getenv(name2);
533   }
534   if (!val || *val == 0) {
535     val = fallback;
536   }
537 
538   return val;
539 }
540 
compute_file_name(char ** strp,const char * user,const char * suffix,const char * what)541 static void compute_file_name(char **strp,
542     const char *user,
543     const char *suffix,
544     const char *what)
545 {
546   char *str = NULL;
547 
548   str = *strp;
549 
550   if (!str) {
551     /* We'll put our various artifacts in a user specific dir
552      * within the state dir location */
553     char *state_dir = NULL;
554     const char *state_parent = test_state_dir ? test_state_dir :
555 #ifdef WATCHMAN_STATE_DIR
556           WATCHMAN_STATE_DIR
557 #else
558           watchman_tmp_dir
559 #endif
560           ;
561 
562     ignore_result(asprintf(&state_dir, "%s/%s-state", state_parent, user));
563 
564     if (!state_dir) {
565       w_log(W_LOG_ERR, "out of memory computing %s\n", what);
566       exit(1);
567     }
568 
569     if (mkdir(state_dir, 0700) == 0 || errno == EEXIST) {
570 #ifndef _WIN32
571       // verify ownership
572       struct stat st;
573       int dir_fd;
574       int ret = 0;
575       uid_t euid = geteuid();
576       // TODO: also allow a gid to be specified here
577       const char* sock_group_name = cfg_get_string("sock_group", nullptr);
578       // S_ISGID is set so that files inside this directory inherit the group
579       // name
580       mode_t dir_perms =
581           cfg_get_perms(
582               "sock_access", false /* write bits */, true /* execute bits */) |
583           S_ISGID;
584 
585       auto dirp =
586           w_dir_open(state_dir, false /* don't need strict symlink rules */);
587 
588       dir_fd = dirp->getFd();
589       if (dir_fd == -1) {
590         w_log(W_LOG_ERR, "dirfd(%s): %s\n", state_dir, strerror(errno));
591         goto bail;
592       }
593 
594       if (fstat(dir_fd, &st) != 0) {
595         w_log(W_LOG_ERR, "fstat(%s): %s\n", state_dir, strerror(errno));
596         ret = 1;
597         goto bail;
598       }
599       if (euid != st.st_uid) {
600         w_log(W_LOG_ERR,
601             "the owner of %s is uid %d and doesn't match your euid %d\n",
602             state_dir, st.st_uid, euid);
603         ret = 1;
604         goto bail;
605       }
606       if (st.st_mode & 0022) {
607         w_log(W_LOG_ERR,
608             "the permissions on %s allow others to write to it. "
609             "Verify that you own the contents and then fix its "
610             "permissions by running `chmod 0700 %s`\n",
611             state_dir,
612             state_dir);
613         ret = 1;
614         goto bail;
615       }
616 
617       if (sock_group_name) {
618         const struct group *sock_group = w_get_group(sock_group_name);
619         if (!sock_group) {
620           ret = 1;
621           goto bail;
622         }
623 
624         if (fchown(dir_fd, -1, sock_group->gr_gid) == -1) {
625           w_log(W_LOG_ERR, "setting up group '%s' failed: %s\n",
626                 sock_group_name, strerror(errno));
627           ret = 1;
628           goto bail;
629         }
630       }
631 
632       // Depending on group and world accessibility, change permissions on the
633       // directory. We can't leave the directory open and set permissions on the
634       // socket because not all POSIX systems respect permissions on UNIX domain
635       // sockets, but all POSIX systems respect permissions on the containing
636       // directory.
637       w_log(W_LOG_DBG, "Setting permissions on state dir to 0%o\n", dir_perms);
638       if (fchmod(dir_fd, dir_perms) == -1) {
639         w_log(W_LOG_ERR, "fchmod(%s, %#o): %s\n", state_dir, dir_perms,
640               strerror(errno));
641         ret = 1;
642         goto bail;
643       }
644 
645     bail:
646       if (ret) {
647         exit(ret);
648       }
649 #endif
650     } else {
651       w_log(W_LOG_ERR, "while computing %s: failed to create %s: %s\n", what,
652             state_dir, strerror(errno));
653       exit(1);
654     }
655 
656     ignore_result(asprintf(&str, "%s/%s", state_dir, suffix));
657 
658     if (!str) {
659       w_log(W_LOG_ERR, "out of memory computing %s", what);
660       abort();
661     }
662 
663     free(state_dir);
664   }
665 
666 #ifndef _WIN32
667   if (str[0] != '/') {
668     w_log(W_LOG_ERR, "invalid %s: %s", what, str);
669     abort();
670   }
671 #endif
672 
673   *strp = str;
674 }
675 
676 #ifndef _WIN32
w_get_group(const char * group_name)677 const struct group *w_get_group(const char *group_name) {
678   // This explicit errno statement is necessary to distinguish between the
679   // group not existing and an error.
680   errno = 0;
681   struct group *group = getgrnam(group_name);
682   if (!group) {
683     if (errno == 0) {
684       w_log(W_LOG_ERR, "group '%s' does not exist\n", group_name);
685     } else {
686       w_log(W_LOG_ERR, "getting gid for '%s' failed: %s\n", group_name,
687             strerror(errno));
688     }
689     return nullptr;
690   }
691   return group;
692 }
693 #endif // ndef _WIN32
694 
compute_user_name(void)695 static const char *compute_user_name(void) {
696   const char *user = get_env_with_fallback("USER", "LOGNAME", NULL);
697 #ifdef _WIN32
698   static char user_buf[256];
699 #endif
700 
701   if (!user) {
702 #ifdef _WIN32
703     DWORD size = sizeof(user_buf);
704     if (GetUserName(user_buf, &size)) {
705       user_buf[size] = 0;
706       user = user_buf;
707     } else {
708       w_log(W_LOG_FATAL, "GetUserName failed: %s. I don't know who you are\n",
709           win32_strerror(GetLastError()));
710     }
711 #else
712     uid_t uid = getuid();
713     struct passwd *pw;
714 
715     pw = getpwuid(uid);
716     if (!pw) {
717       w_log(W_LOG_FATAL, "getpwuid(%d) failed: %s. I don't know who you are\n",
718           uid, strerror(errno));
719     }
720 
721     user = pw->pw_name;
722 #endif
723 
724     if (!user) {
725       w_log(W_LOG_ERR, "watchman requires that you set $USER in your env\n");
726       abort();
727     }
728   }
729 
730   return user;
731 }
732 
setup_sock_name(void)733 static void setup_sock_name(void)
734 {
735   const char *user = compute_user_name();
736 
737   watchman_tmp_dir = get_env_with_fallback("TMPDIR", "TMP", "/tmp");
738 
739 #ifdef _WIN32
740   if (!sock_name) {
741     asprintf(&sock_name, "\\\\.\\pipe\\watchman-%s", user);
742   }
743 #else
744   compute_file_name(&sock_name, user, "sock", "sockname");
745 #endif
746   compute_file_name(&watchman_state_file, user, "state", "statefile");
747   compute_file_name(&log_name, user, "log", "logname");
748 #ifdef USE_GIMLI
749   compute_file_name(&pid_file, user, "pid", "pidfile");
750 #endif
751 
752 #ifndef _WIN32
753   if (strlen(sock_name) >= sizeof(un.sun_path) - 1) {
754     w_log(W_LOG_ERR, "%s: path is too long\n",
755         sock_name);
756     abort();
757   }
758 
759   un.sun_family = PF_LOCAL;
760   memcpy(un.sun_path, sock_name, strlen(sock_name) + 1);
761 #endif
762 }
763 
should_start(int err)764 static bool should_start(int err)
765 {
766   if (err == ECONNREFUSED) {
767     return true;
768   }
769   if (err == ENOENT) {
770     return true;
771   }
772   return false;
773 }
774 
try_command(json_t * cmd,int timeout)775 static bool try_command(json_t *cmd, int timeout)
776 {
777   w_jbuffer_t buffer;
778   w_jbuffer_t output_pdu_buffer;
779   int err;
780 
781   auto client = w_stm_connect(sock_name, timeout * 1000);
782   if (!client) {
783     return false;
784   }
785 
786   if (!cmd) {
787     return true;
788   }
789 
790   // Send command
791   if (!buffer.pduEncodeToStream(
792           server_pdu, server_capabilities, cmd, client.get())) {
793     err = errno;
794     w_log(W_LOG_ERR, "error sending PDU to server\n");
795     errno = err;
796     return false;
797   }
798 
799   buffer.clear();
800 
801   do {
802     if (!buffer.passThru(
803             output_pdu,
804             output_capabilities,
805             &output_pdu_buffer,
806             client.get())) {
807       return false;
808     }
809   } while (persistent);
810 
811   return true;
812 }
813 
814 static struct watchman_getopt opts[] = {
815   { "help",     'h', "Show this help",
816     OPT_NONE,   &show_help, NULL, NOT_DAEMON },
817 #ifndef _WIN32
818   { "inetd",    0,   "Spawning from an inetd style supervisor",
819     OPT_NONE,   &inetd_style, NULL, IS_DAEMON },
820 #endif
821   { "version",  'v', "Show version number",
822     OPT_NONE,   &show_version, NULL, NOT_DAEMON },
823   { "sockname", 'U', "Specify alternate sockname",
824     REQ_STRING, &sock_name, "PATH", IS_DAEMON },
825   { "logfile", 'o', "Specify path to logfile",
826     REQ_STRING, &log_name, "PATH", IS_DAEMON },
827   { "log-level", 0, "set the log level (0 = off, default is 1, verbose = 2)",
828     REQ_INT, &log_level, NULL, IS_DAEMON },
829 #ifdef USE_GIMLI
830   { "pidfile", 0, "Specify path to gimli monitor pidfile",
831     REQ_STRING, &pid_file, "PATH", NOT_DAEMON },
832 #else
833   { "pidfile", 0, "Specify path to pidfile",
834     REQ_STRING, &pid_file, "PATH", IS_DAEMON },
835 #endif
836   { "persistent", 'p', "Persist and wait for further responses",
837     OPT_NONE, &persistent, NULL, NOT_DAEMON },
838   { "no-save-state", 'n', "Don't save state between invocations",
839     OPT_NONE, &dont_save_state, NULL, IS_DAEMON },
840   { "statefile", 0, "Specify path to file to hold watch and trigger state",
841     REQ_STRING, &watchman_state_file, "PATH", IS_DAEMON },
842   { "json-command", 'j', "Instead of parsing CLI arguments, take a single "
843     "json object from stdin",
844     OPT_NONE, &json_input_arg, NULL, NOT_DAEMON },
845   { "output-encoding", 0, "CLI output encoding. json (default) or bser",
846     REQ_STRING, &output_encoding, NULL, NOT_DAEMON },
847   { "server-encoding", 0, "CLI<->server encoding. bser (default) or json",
848     REQ_STRING, &server_encoding, NULL, NOT_DAEMON },
849   { "foreground", 'f', "Run the service in the foreground",
850     OPT_NONE, &foreground, NULL, NOT_DAEMON },
851   { "no-pretty", 0, "Don't pretty print JSON",
852     OPT_NONE, &no_pretty, NULL, NOT_DAEMON },
853   { "no-spawn", 0, "Don't try to start the service if it is not available",
854     OPT_NONE, &no_spawn, NULL, NOT_DAEMON },
855   { "no-local", 0, "When no-spawn is enabled, don't try to handle request"
856     " in client mode if service is unavailable",
857     OPT_NONE, &no_local, NULL, NOT_DAEMON },
858   // test-state-dir is for testing only and should not be used in production:
859   // instead, use the compile-time WATCHMAN_STATE_DIR option
860   { "test-state-dir", 0, NULL, REQ_STRING, &test_state_dir, "DIR", NOT_DAEMON },
861   { 0, 0, 0, OPT_NONE, 0, 0, 0 }
862 };
863 
parse_cmdline(int * argcp,char *** argvp)864 static void parse_cmdline(int *argcp, char ***argvp)
865 {
866   cfg_load_global_config_file();
867   w_getopt(opts, argcp, argvp, &daemon_argv);
868   if (show_help) {
869     usage(opts, stdout);
870   }
871   if (show_version) {
872     printf("%s\n", PACKAGE_VERSION);
873     exit(0);
874   }
875   watchman::getLog().setStdErrLoggingLevel(
876       static_cast<enum watchman::LogLevel>(log_level));
877   setup_sock_name();
878   parse_encoding(server_encoding, &server_pdu);
879   parse_encoding(output_encoding, &output_pdu);
880   if (!output_encoding) {
881     output_pdu = no_pretty ? is_json_compact : is_json_pretty;
882   }
883 }
884 
build_command(int argc,char ** argv)885 static json_ref build_command(int argc, char** argv) {
886   int i;
887 
888   // Read blob from stdin
889   if (json_input_arg) {
890     json_error_t err;
891     w_jbuffer_t buf;
892 
893     memset(&err, 0, sizeof(err));
894     auto cmd = buf.decodeNext(w_stm_stdin(), &err);
895 
896     if (buf.pdu_type == is_bser) {
897       // If they used bser for the input, select bser for output
898       // unless they explicitly requested something else
899       if (!server_encoding) {
900         server_pdu = is_bser;
901       }
902       if (!output_encoding) {
903         output_pdu = is_bser;
904       }
905     } else if (buf.pdu_type == is_bser_v2) {
906       // If they used bser v2 for the input, select bser v2 for output
907       // unless they explicitly requested something else
908       if (!server_encoding) {
909         server_pdu = is_bser_v2;
910       }
911       if (!output_encoding) {
912         output_pdu = is_bser_v2;
913       }
914     }
915 
916     if (!cmd) {
917       fprintf(
918           stderr,
919           "failed to parse command from stdin: "
920           "line %d, column %d, position %d: %s\n",
921           err.line,
922           err.column,
923           err.position,
924           err.text);
925       exit(1);
926     }
927     return cmd;
928   }
929 
930   // Special case: no arguments means that we just want
931   // to verify that the service is up, starting it if
932   // needed
933   if (argc == 0) {
934     return nullptr;
935   }
936 
937   auto cmd = json_array();
938   for (i = 0; i < argc; i++) {
939     json_array_append_new(cmd, typed_string_to_json(argv[i], W_STRING_UNICODE));
940   }
941 
942   return cmd;
943 }
944 
get_sock_name(void)945 const char *get_sock_name(void)
946 {
947   return sock_name;
948 }
949 
spawn_watchman(void)950 static void spawn_watchman(void) {
951 #ifndef _WIN32
952   // If we have a site-specific spawning requirement, then we'll
953   // invoke that spawner rather than using any of the built-in
954   // spawning functionality.
955   const char* site_spawn = cfg_get_string("spawn_watchman_service", nullptr);
956   if (site_spawn) {
957     spawn_site_specific(site_spawn);
958     return;
959   }
960 #endif
961 
962 #ifdef USE_GIMLI
963   spawn_via_gimli();
964 #elif defined(__APPLE__)
965   spawn_via_launchd();
966 #elif defined(_WIN32)
967   spawn_win32();
968 #else
969   daemonize();
970 #endif
971 }
972 
main(int argc,char ** argv)973 int main(int argc, char **argv)
974 {
975   bool ran;
976 
977   parse_cmdline(&argc, &argv);
978 
979   if (foreground) {
980     run_service();
981     return 0;
982   }
983 
984   w_set_thread_name("cli");
985   auto cmd = build_command(argc, argv);
986   preprocess_command(cmd, output_pdu, output_capabilities);
987 
988   ran = try_command(cmd, 0);
989   if (!ran && should_start(errno)) {
990     if (no_spawn) {
991       if (!no_local) {
992         ran = try_client_mode_command(cmd, !no_pretty);
993       }
994     } else {
995       spawn_watchman();
996       // Some site spawner scripts will asynchronously launch the service.
997       // When that happens we may encounter ECONNREFUSED.  We need to
998       // tolerate this, so we add some retries.
999       int attempts = 10;
1000       std::chrono::milliseconds interval(10);
1001       while (true) {
1002         ran = try_command(cmd, 10);
1003         if (!ran && should_start(errno) && attempts-- > 0) {
1004           /* sleep override */ std::this_thread::sleep_for(interval);
1005           interval *= 2;
1006           continue;
1007         }
1008         // Success or terminal failure
1009         break;
1010       }
1011     }
1012   }
1013 
1014   if (ran) {
1015     return 0;
1016   }
1017 
1018   if (!no_spawn) {
1019     w_log(W_LOG_ERR, "unable to talk to your watchman on %s! (%s)\n",
1020         sock_name, strerror(errno));
1021 #ifdef __APPLE__
1022     if (getenv("TMUX")) {
1023       w_log(W_LOG_ERR, "\n"
1024 "You may be hitting a tmux related session issue.\n"
1025 "An immediate workaround is to run:\n"
1026 "\n"
1027 "    watchman version\n"
1028 "\n"
1029 "just once, from *outside* your tmux session, to allow the launchd\n"
1030 "registration to be setup.  Once done, you can continue to access\n"
1031 "watchman from inside your tmux sessions as usual.\n"
1032 "\n"
1033 "Longer term, you may wish to install this tool:\n"
1034 "\n"
1035 "    https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard\n"
1036 "\n"
1037 "and configure tmux to use `reattach-to-user-namespace`\n"
1038 "when it launches your shell.\n");
1039     }
1040 #endif
1041   }
1042   return 1;
1043 }
1044 
1045 /* vim:ts=2:sw=2:et:
1046  */
1047